diff --git a/amd/build/vertexcachestatus.min.js b/amd/build/vertexcachestatus.min.js
new file mode 100644
index 0000000..e4d3f9b
--- /dev/null
+++ b/amd/build/vertexcachestatus.min.js
@@ -0,0 +1,11 @@
+define("local_ai_manager/vertexcachestatus",["exports","core/templates","core/ajax","core/notification","core/str"],(function(_exports,_templates,_ajax,_notification,_str){var obj;
+/**
+ * Module rendering the warning box to inform the users about misleading AI results.
+ *
+ * @module local_ai_manager/vertexcachestatus
+ * @copyright 2024 ISB Bayern
+ * @author Philipp Memmel
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_templates=(obj=_templates)&&obj.__esModule?obj:{default:obj};_exports.init=async selector=>{const statusElement=document.querySelector(selector),refreshButton=statusElement.querySelector('[data-action="refresh"]'),enableCachingButton=statusElement.querySelector('[data-action="enablecaching"]'),disableCachingButton=statusElement.querySelector('[data-action="disablecaching"]'),serviceaccountinfoTextArea=document.getElementById("id_serviceaccountjson");let serviceaccountinfo=serviceaccountinfoTextArea.value;serviceaccountinfoTextArea.addEventListener("input",(event=>{serviceaccountinfo=event.target.value})),refreshButton.addEventListener("click",(async event=>{event.preventDefault(),await updateCachingStatusDisplay(serviceaccountinfo,statusElement)})),enableCachingButton&&enableCachingButton.addEventListener("click",(async event=>{event.preventDefault(),enableCachingButton.disabled=!0,await updateCachingStatus(serviceaccountinfo,statusElement,!0)})),disableCachingButton&&disableCachingButton.addEventListener("click",(async event=>{event.preventDefault(),disableCachingButton.disabled=!0,await updateCachingStatus(serviceaccountinfo,statusElement,!1)}))};const updateCachingStatusDisplay=async(serviceaccountinfo,statusElement)=>{let queryResult=null;try{queryResult=await(serviceaccountinfo=>(0,_ajax.call)([{methodname:"local_ai_manager_vertex_cache_status",args:{serviceaccountinfo:serviceaccountinfo}}])[0])(serviceaccountinfo)}catch(error){return void await(0,_notification.exception)(error)}if(200!==queryResult.code){const errorTitleString=await(0,_str.getString)("vertex_error_cachestatus","local_ai_manager");await(0,_notification.alert)(errorTitleString,queryResult.error)}const templateContext={cachingEnabled:queryResult.cachingEnabled,noStatus:!1},{html:html,js:js}=await _templates.default.renderForPromise("local_ai_manager/vertexcachestatus",templateContext);_templates.default.replaceNode(statusElement,html,js)},updateCachingStatus=async(serviceaccountinfo,statusElement,newstatus)=>{let queryResult=null;try{queryResult=await((serviceaccountinfo,newstatus)=>(0,_ajax.call)([{methodname:"local_ai_manager_vertex_cache_status",args:{serviceaccountinfo:serviceaccountinfo,newstatus:newstatus}}])[0])(serviceaccountinfo,newstatus)}catch(error){return void await(0,_notification.exception)(error)}if(200===queryResult.code)await updateCachingStatusDisplay(serviceaccountinfo,statusElement);else{const errorTitleString=await(0,_str.getString)("vertex_error_cachestatus","local_ai_manager");await(0,_notification.alert)(errorTitleString,queryResult.error)}}}));
+
+//# sourceMappingURL=vertexcachestatus.min.js.map
\ No newline at end of file
diff --git a/amd/build/vertexcachestatus.min.js.map b/amd/build/vertexcachestatus.min.js.map
new file mode 100644
index 0000000..24cea6f
--- /dev/null
+++ b/amd/build/vertexcachestatus.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"vertexcachestatus.min.js","sources":["../src/vertexcachestatus.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module rendering the warning box to inform the users about misleading AI results.\n *\n * @module local_ai_manager/vertexcachestatus\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport {call as fetchMany} from 'core/ajax';\nimport {alert as alertModal, exception as displayException} from 'core/notification';\nimport {getString} from 'core/str';\n\n/**\n * Fetches the current cache status of the specified service account.\n *\n * @param {string} serviceaccountinfo the stringified JSON with the service account info\n */\nconst fetchCurrentCacheStatus = (serviceaccountinfo) => fetchMany([{\n methodname: 'local_ai_manager_vertex_cache_status',\n args: {\n serviceaccountinfo\n }\n}])[0];\n\n/**\n * Updates the current cache status.\n *\n * @param {string} serviceaccountinfo the stringified JSON with the service account info\n * @param {boolean} newstatus true if the cache should be enabled, false if it should be disabled\n */\nconst setCurrentCacheStatus = (serviceaccountinfo, newstatus) => fetchMany([{\n methodname: 'local_ai_manager_vertex_cache_status',\n args: {\n serviceaccountinfo,\n newstatus\n }\n}])[0];\n\n/**\n * Controls and renders the Google Vertex AI cache status elements.\n *\n * @param {string} selector the CSS selector of the status element to operate on\n */\nexport const init = async(selector) => {\n const statusElement = document.querySelector(selector);\n const refreshButton = statusElement.querySelector('[data-action=\"refresh\"]');\n const enableCachingButton = statusElement.querySelector('[data-action=\"enablecaching\"]');\n const disableCachingButton = statusElement.querySelector('[data-action=\"disablecaching\"]');\n const serviceaccountinfoTextArea = document.getElementById('id_serviceaccountjson');\n let serviceaccountinfo = serviceaccountinfoTextArea.value;\n // We want to keep track of the current serviceaccountinfo data, also if the user changes it.\n serviceaccountinfoTextArea.addEventListener('input', (event) => {\n serviceaccountinfo = event.target.value;\n });\n\n refreshButton.addEventListener('click', async(event) => {\n event.preventDefault();\n await updateCachingStatusDisplay(serviceaccountinfo, statusElement);\n });\n\n if (enableCachingButton) {\n enableCachingButton.addEventListener('click', async(event) => {\n event.preventDefault();\n enableCachingButton.disabled = true;\n await updateCachingStatus(serviceaccountinfo, statusElement, true);\n });\n }\n if (disableCachingButton) {\n disableCachingButton.addEventListener('click', async(event) => {\n event.preventDefault();\n disableCachingButton.disabled = true;\n await updateCachingStatus(serviceaccountinfo, statusElement, false);\n });\n }\n};\n\n/**\n * Updates the caching status display.\n *\n * @param {string} serviceaccountinfo the stringified JSON with the service account info\n * @param {string} statusElement the HTML element to operate on\n */\nconst updateCachingStatusDisplay = async(serviceaccountinfo, statusElement) => {\n let queryResult = null;\n try {\n queryResult = await fetchCurrentCacheStatus(serviceaccountinfo);\n } catch (error) {\n await displayException(error);\n return;\n }\n if (queryResult.code !== 200) {\n const errorTitleString = await getString('vertex_error_cachestatus', 'local_ai_manager');\n await alertModal(errorTitleString, queryResult.error);\n }\n const templateContext = {\n cachingEnabled: queryResult.cachingEnabled,\n noStatus: false\n };\n\n const {html, js} = await Templates.renderForPromise('local_ai_manager/vertexcachestatus', templateContext);\n Templates.replaceNode(statusElement, html, js);\n};\n\n/**\n * Updates the caching status and updates the DOM to reflect the current state.\n *\n * @param {string} serviceaccountinfo the stringified JSON with the service account info\n * @param {string} statusElement the HTML element to operate on\n * @param {boolean} newstatus the status to set the caching configuration to (true or false)\n */\nconst updateCachingStatus = async(serviceaccountinfo, statusElement, newstatus) => {\n let queryResult = null;\n try {\n queryResult = await setCurrentCacheStatus(serviceaccountinfo, newstatus);\n } catch (error) {\n await displayException(error);\n return;\n }\n if (queryResult.code !== 200) {\n const errorTitleString = await getString('vertex_error_cachestatus', 'local_ai_manager');\n await alertModal(errorTitleString, queryResult.error);\n return;\n }\n await updateCachingStatusDisplay(serviceaccountinfo, statusElement);\n};\n"],"names":["async","statusElement","document","querySelector","selector","refreshButton","enableCachingButton","disableCachingButton","serviceaccountinfoTextArea","getElementById","serviceaccountinfo","value","addEventListener","event","target","preventDefault","updateCachingStatusDisplay","disabled","updateCachingStatus","queryResult","methodname","args","fetchCurrentCacheStatus","error","code","errorTitleString","templateContext","cachingEnabled","noStatus","html","js","Templates","renderForPromise","replaceNode","newstatus","setCurrentCacheStatus"],"mappings":";;;;;;;;8JA4DoBA,MAAAA,iBACVC,cAAgBC,SAASC,cAAcC,UACvCC,cAAgBJ,cAAcE,cAAc,2BAC5CG,oBAAsBL,cAAcE,cAAc,iCAClDI,qBAAuBN,cAAcE,cAAc,kCACnDK,2BAA6BN,SAASO,eAAe,6BACvDC,mBAAqBF,2BAA2BG,MAEpDH,2BAA2BI,iBAAiB,SAAUC,QAClDH,mBAAqBG,MAAMC,OAAOH,SAGtCN,cAAcO,iBAAiB,SAASZ,MAAAA,QACpCa,MAAME,uBACAC,2BAA2BN,mBAAoBT,kBAGrDK,qBACAA,oBAAoBM,iBAAiB,SAASZ,MAAAA,QAC1Ca,MAAME,iBACNT,oBAAoBW,UAAW,QACzBC,oBAAoBR,mBAAoBT,eAAe,MAGjEM,sBACAA,qBAAqBK,iBAAiB,SAASZ,MAAAA,QAC3Ca,MAAME,iBACNR,qBAAqBU,UAAW,QAC1BC,oBAAoBR,mBAAoBT,eAAe,aAWnEe,2BAA6BhB,MAAMU,mBAAoBT,qBACrDkB,YAAc,SAEdA,iBApEyBT,CAAAA,qBAAuB,cAAU,CAAC,CAC/DU,WAAY,uCACZC,KAAM,CACFX,mBAAAA,uBAEJ,GA+DwBY,CAAwBZ,oBAC9C,MAAOa,yBACC,2BAAiBA,UAGF,MAArBJ,YAAYK,KAAc,OACpBC,uBAAyB,kBAAU,2BAA4B,0BAC/D,uBAAWA,iBAAkBN,YAAYI,aAE7CG,gBAAkB,CACpBC,eAAgBR,YAAYQ,eAC5BC,UAAU,IAGRC,KAACA,KAADC,GAAOA,UAAYC,mBAAUC,iBAAiB,qCAAsCN,oCAChFO,YAAYhC,cAAe4B,KAAMC,KAUzCZ,oBAAsBlB,MAAMU,mBAAoBT,cAAeiC,iBAC7Df,YAAc,SAEdA,iBAnFsB,EAACT,mBAAoBwB,aAAc,cAAU,CAAC,CACxEd,WAAY,uCACZC,KAAM,CACFX,mBAAAA,mBACAwB,UAAAA,cAEJ,GA6EwBC,CAAsBzB,mBAAoBwB,WAChE,MAAOX,yBACC,2BAAiBA,UAGF,MAArBJ,YAAYK,WAKVR,2BAA2BN,mBAAoBT,0BAJ3CwB,uBAAyB,kBAAU,2BAA4B,0BAC/D,uBAAWA,iBAAkBN,YAAYI"}
\ No newline at end of file
diff --git a/amd/src/vertexcachestatus.js b/amd/src/vertexcachestatus.js
new file mode 100644
index 0000000..c279271
--- /dev/null
+++ b/amd/src/vertexcachestatus.js
@@ -0,0 +1,142 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see .
+
+/**
+ * Module rendering the warning box to inform the users about misleading AI results.
+ *
+ * @module local_ai_manager/vertexcachestatus
+ * @copyright 2024 ISB Bayern
+ * @author Philipp Memmel
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+import Templates from 'core/templates';
+import {call as fetchMany} from 'core/ajax';
+import {alert as alertModal, exception as displayException} from 'core/notification';
+import {getString} from 'core/str';
+
+/**
+ * Fetches the current cache status of the specified service account.
+ *
+ * @param {string} serviceaccountinfo the stringified JSON with the service account info
+ */
+const fetchCurrentCacheStatus = (serviceaccountinfo) => fetchMany([{
+ methodname: 'local_ai_manager_vertex_cache_status',
+ args: {
+ serviceaccountinfo
+ }
+}])[0];
+
+/**
+ * Updates the current cache status.
+ *
+ * @param {string} serviceaccountinfo the stringified JSON with the service account info
+ * @param {boolean} newstatus true if the cache should be enabled, false if it should be disabled
+ */
+const setCurrentCacheStatus = (serviceaccountinfo, newstatus) => fetchMany([{
+ methodname: 'local_ai_manager_vertex_cache_status',
+ args: {
+ serviceaccountinfo,
+ newstatus
+ }
+}])[0];
+
+/**
+ * Controls and renders the Google Vertex AI cache status elements.
+ *
+ * @param {string} selector the CSS selector of the status element to operate on
+ */
+export const init = async(selector) => {
+ const statusElement = document.querySelector(selector);
+ const refreshButton = statusElement.querySelector('[data-action="refresh"]');
+ const enableCachingButton = statusElement.querySelector('[data-action="enablecaching"]');
+ const disableCachingButton = statusElement.querySelector('[data-action="disablecaching"]');
+ const serviceaccountinfoTextArea = document.getElementById('id_serviceaccountjson');
+ let serviceaccountinfo = serviceaccountinfoTextArea.value;
+ // We want to keep track of the current serviceaccountinfo data, also if the user changes it.
+ serviceaccountinfoTextArea.addEventListener('input', (event) => {
+ serviceaccountinfo = event.target.value;
+ });
+
+ refreshButton.addEventListener('click', async(event) => {
+ event.preventDefault();
+ await updateCachingStatusDisplay(serviceaccountinfo, statusElement);
+ });
+
+ if (enableCachingButton) {
+ enableCachingButton.addEventListener('click', async(event) => {
+ event.preventDefault();
+ enableCachingButton.disabled = true;
+ await updateCachingStatus(serviceaccountinfo, statusElement, true);
+ });
+ }
+ if (disableCachingButton) {
+ disableCachingButton.addEventListener('click', async(event) => {
+ event.preventDefault();
+ disableCachingButton.disabled = true;
+ await updateCachingStatus(serviceaccountinfo, statusElement, false);
+ });
+ }
+};
+
+/**
+ * Updates the caching status display.
+ *
+ * @param {string} serviceaccountinfo the stringified JSON with the service account info
+ * @param {string} statusElement the HTML element to operate on
+ */
+const updateCachingStatusDisplay = async(serviceaccountinfo, statusElement) => {
+ let queryResult = null;
+ try {
+ queryResult = await fetchCurrentCacheStatus(serviceaccountinfo);
+ } catch (error) {
+ await displayException(error);
+ return;
+ }
+ if (queryResult.code !== 200) {
+ const errorTitleString = await getString('vertex_error_cachestatus', 'local_ai_manager');
+ await alertModal(errorTitleString, queryResult.error);
+ }
+ const templateContext = {
+ cachingEnabled: queryResult.cachingEnabled,
+ noStatus: false
+ };
+
+ const {html, js} = await Templates.renderForPromise('local_ai_manager/vertexcachestatus', templateContext);
+ Templates.replaceNode(statusElement, html, js);
+};
+
+/**
+ * Updates the caching status and updates the DOM to reflect the current state.
+ *
+ * @param {string} serviceaccountinfo the stringified JSON with the service account info
+ * @param {string} statusElement the HTML element to operate on
+ * @param {boolean} newstatus the status to set the caching configuration to (true or false)
+ */
+const updateCachingStatus = async(serviceaccountinfo, statusElement, newstatus) => {
+ let queryResult = null;
+ try {
+ queryResult = await setCurrentCacheStatus(serviceaccountinfo, newstatus);
+ } catch (error) {
+ await displayException(error);
+ return;
+ }
+ if (queryResult.code !== 200) {
+ const errorTitleString = await getString('vertex_error_cachestatus', 'local_ai_manager');
+ await alertModal(errorTitleString, queryResult.error);
+ return;
+ }
+ await updateCachingStatusDisplay(serviceaccountinfo, statusElement);
+};
diff --git a/classes/external/vertex_cache_status.php b/classes/external/vertex_cache_status.php
new file mode 100644
index 0000000..0b6cf7a
--- /dev/null
+++ b/classes/external/vertex_cache_status.php
@@ -0,0 +1,109 @@
+.
+
+namespace local_ai_manager\external;
+
+use core_external\external_api;
+use core_external\external_function_parameters;
+use core_external\external_single_structure;
+use core_external\external_value;
+use local_ai_manager\local\aitool_option_vertexai_authhandler;
+
+/**
+ * Web service to check and update the Google Vertex AI cache status.
+ *
+ * @package local_ai_manager
+ * @copyright 2024 ISB Bayern
+ * @author Philipp Memmel
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class vertex_cache_status extends external_api {
+ /**
+ * Describes the parameters.
+ *
+ * @return external_function_parameters
+ */
+ public static function execute_parameters(): external_function_parameters {
+ return new external_function_parameters([
+ 'serviceaccountinfo' => new external_value(PARAM_RAW,
+ 'The JSON string containing the service account information of the used Google Account',
+ VALUE_REQUIRED),
+ 'newstatus' => new external_value(PARAM_BOOL,
+ 'The status to which the caching config should be set to',
+ VALUE_DEFAULT,
+ null),
+ ]);
+ }
+
+ /**
+ * Retrieve the purpose config.
+ *
+ * @param string $serviceaccountinfo The service account info stringified JSON
+ * @return array associative array containing the result of the request
+ */
+ public static function execute(string $serviceaccountinfo, ?bool $newstatus = null): array {
+ [
+ 'serviceaccountinfo' => $serviceaccountinfo,
+ 'newstatus' => $newstatus,
+ ] = self::validate_parameters(self::execute_parameters(),
+ [
+ 'serviceaccountinfo' => $serviceaccountinfo,
+ 'newstatus' => $newstatus,
+ ]);
+ $context = \context_system::instance();
+ self::validate_context($context);
+ require_capability('local/ai_manager:managevertexcache', $context);
+
+ $vertexaiauthhandler = new aitool_option_vertexai_authhandler(0, $serviceaccountinfo);
+ if (!is_null($newstatus)) {
+ try {
+ $cachingchangeresult = $vertexaiauthhandler->set_google_cache_status($newstatus);
+ } catch (\moodle_exception $exception) {
+ return ['code' => 500, 'error' => $exception->getMessage()];
+ }
+ return $cachingchangeresult ? ['code' => 200, 'cachingstatus' => $newstatus] :
+ ['code' => 500, 'error' => 'COULD NOT SET THE CACHING STATUS'];
+ } else {
+ // Variable $newstatus is null, so we just want to query and return the result.
+ try {
+ $currentcachingstatus = $vertexaiauthhandler->get_google_cache_status();
+ } catch (\moodle_exception $exception) {
+ return ['code' => 500, 'error' => $exception->getMessage()];
+ }
+ return ['code' => 200, 'cachingEnabled' => $currentcachingstatus];
+ }
+ }
+
+ /**
+ * Describes the return structure of the service.
+ *
+ * @return external_single_structure the return structure
+ */
+ public static function execute_returns(): external_single_structure {
+ $singlestructuredefinition = [];
+ $singlestructuredefinition['code'] = new external_value(PARAM_INT,
+ 'Status code of the request',
+ VALUE_REQUIRED);
+ $singlestructuredefinition['cachingEnabled'] = new external_value(PARAM_BOOL,
+ 'If the Google Vertex AI cache is enabled', VALUE_OPTIONAL);
+ $singlestructuredefinition['error'] = new external_value(PARAM_TEXT,
+ 'Error message if there is an error', VALUE_OPTIONAL);
+ return new external_single_structure(
+ $singlestructuredefinition,
+ 'Object containing the tools configured for each purpose'
+ );
+ }
+}
diff --git a/classes/local/aitool_option_vertexai.php b/classes/local/aitool_option_vertexai.php
index 3a4e9c4..2c9bb12 100644
--- a/classes/local/aitool_option_vertexai.php
+++ b/classes/local/aitool_option_vertexai.php
@@ -35,9 +35,14 @@ class aitool_option_vertexai {
* @param \MoodleQuickForm $mform the mform object
*/
public static function extend_form_definition(\MoodleQuickForm $mform): void {
+ global $OUTPUT;
$mform->freeze('endpoint');
$mform->addElement('textarea', 'serviceaccountjson',
get_string('serviceaccountjson', 'local_ai_manager'), ['rows' => '20']);
+ $vertexcachestatushtml = $OUTPUT->render_from_template('local_ai_manager/vertexcachestatus', ['noStatus' => true]);
+ $mform->addElement('static', 'vertexcachestatus',
+ get_string('vertexcachestatus', 'local_ai_manager'),
+ $vertexcachestatushtml, ['class' => 'mw-100']);
}
/**
diff --git a/classes/local/aitool_option_vertexai_authhandler.php b/classes/local/aitool_option_vertexai_authhandler.php
index 7b84826..dfc2104 100644
--- a/classes/local/aitool_option_vertexai_authhandler.php
+++ b/classes/local/aitool_option_vertexai_authhandler.php
@@ -34,7 +34,7 @@ class aitool_option_vertexai_authhandler {
* Constructor for the auth handler.
*/
public function __construct(
- /** @var int The ID of the instance being used. Will be used as key for the cache handling. */
+ /** @var int The ID of the instance being used. Will be used as key for the cache handling. */
private readonly int $instanceid,
/** @var string The serviceaccountinfo stringified JSON */
private readonly string $serviceaccountinfo
@@ -165,4 +165,65 @@ public function is_expired_accesstoken_reason_for_failing(request_response $requ
return !empty(array_filter($content['error']['details'], fn($details) => $details['reason'] === 'ACCESS_TOKEN_EXPIRED'));
}
+ /**
+ * Retrieves and checks the cache status from Google's AI Platform.
+ *
+ * Makes an HTTP GET request to the AI Platform cache configuration endpoint
+ * using the project ID from the service account information. The method
+ * verifies if the cache is enabled by checking the 'disableCache' key in the
+ * response.
+ *
+ * @return bool true if the cache is enabled, false if the cache is disabled
+ * @throws \moodle_exception if the HTTP request to retrieve the cache status fails.
+ */
+ public function get_google_cache_status(): bool {
+ $client = new http_client([
+ 'timeout' => get_config('local_ai_manager', 'requesttimeout'),
+ ]);
+
+ $options['headers'] = [
+ 'Authorization' => 'Bearer ' . $this->get_access_token(),
+ ];
+
+ $serviceaccountinfo = json_decode($this->serviceaccountinfo);
+ $projectid = trim($serviceaccountinfo->project_id);
+
+ $response = $client->get('https://europe-west3-aiplatform.googleapis.com/v1beta1/projects/' . $projectid . '/cacheConfig',
+ $options);
+ if ($response->getStatusCode() !== 200) {
+ throw new \moodle_exception('Error retrieving cache status', '', '', '', $response->getBody()->getContents());
+ } else {
+ $result = json_decode($response->getBody()->getContents(), true);
+ return !array_key_exists('disableCache', $result);
+ }
+ }
+
+ /**
+ * Sets the Google cache status for the specified project.
+ *
+ * @param bool $status Determines whether the cache should be enabled or disabled.
+ * @return bool Returns true if the cache status was successfully set, false otherwise.
+ */
+ public function set_google_cache_status(bool $status): bool {
+ $client = new http_client([
+ 'timeout' => get_config('local_ai_manager', 'requesttimeout'),
+ ]);
+ $options['headers'] = [
+ 'Authorization' => 'Bearer ' . $this->get_access_token(),
+ ];
+
+ $serviceaccountinfo = json_decode($this->serviceaccountinfo);
+ $projectid = trim($serviceaccountinfo->project_id);
+
+ $data = [
+ 'name' => 'projects/' . $projectid . '/cacheConfig',
+ 'disableCache' => !$status,
+ ];
+
+ $options['body'] = json_encode($data);
+
+ $response = $client->patch('https://europe-west3-aiplatform.googleapis.com/v1beta1/projects/' . $projectid . '/cacheConfig',
+ $options);
+ return $response->getStatusCode() === 200;
+ }
}
diff --git a/db/access.php b/db/access.php
index 4477985..fa3ae33 100755
--- a/db/access.php
+++ b/db/access.php
@@ -110,5 +110,16 @@
'manager' => CAP_ALLOW,
],
],
-
+ 'local/ai_manager:managevertexcache' => [
+ 'captype' => 'write',
+ 'contextlevel' => CONTEXT_SYSTEM,
+ 'archetypes' => [
+ 'user' => CAP_PREVENT,
+ 'guest' => CAP_PREVENT,
+ 'student' => CAP_PREVENT,
+ 'teacher' => CAP_PREVENT,
+ 'editingteacher' => CAP_PREVENT,
+ 'manager' => CAP_ALLOW,
+ ],
+ ],
];
diff --git a/db/services.php b/db/services.php
index 99783fc..841c6ca 100755
--- a/db/services.php
+++ b/db/services.php
@@ -54,4 +54,12 @@
'ajax' => true,
'capabilities' => 'local/ai_manager:use',
],
+ 'local_ai_manager_vertex_cache_status' => [
+ 'classname' => 'local_ai_manager\external\vertex_cache_status',
+ 'description' => 'Fetch and update the Google Vertex AI caching status',
+ 'type' => 'write',
+ 'ajax' => true,
+ 'capabilities' => '',
+ ],
+
];
diff --git a/lang/de/local_ai_manager.php b/lang/de/local_ai_manager.php
index 9a27b4f..367a14b 100644
--- a/lang/de/local_ai_manager.php
+++ b/lang/de/local_ai_manager.php
@@ -211,4 +211,11 @@
$string['userwithusageonlyshown'] = 'Die Tabelle zeigt nur Benutzer, die diesen Einsatzzweck bereits genutzt haben.';
$string['verifyssl'] = 'SSL-Zertifikate verifizieren';
$string['verifyssldesc'] = 'Wenn aktiviert, werden Verbindungen zu externen KI-Tools nur dann hergestellt, wenn die Zertifikate verifiziert werden können. Diese Option sollte in Produktionsumgebungen nicht deaktiviert werden!';
+$string['vertex_cachingdisabled'] = 'Caching deaktiviert';
+$string['vertex_cachingenabled'] = 'Caching aktiviert';
+$string['vertex_disablecaching'] = 'Caching deaktivieren';
+$string['vertex_enablecaching'] = 'Caching aktivieren';
+$string['vertex_error_cachestatus'] = 'Fehler beim Abfragen/Ändern der Vertex-AI-Cache-Konfiguration';
+$string['vertex_nocachestatus'] = 'Klicken Sie auf den Neu-Laden-Button, um den aktuellen Caching-Status von Vertex AI abzufragen.';
+$string['vertexcachestatus'] = 'Cache-Status von Vertex AI abfragen und ändern';
$string['within'] = 'innerhalb von';
diff --git a/lang/en/local_ai_manager.php b/lang/en/local_ai_manager.php
index ed904a6..6523df3 100644
--- a/lang/en/local_ai_manager.php
+++ b/lang/en/local_ai_manager.php
@@ -211,4 +211,11 @@
$string['userwithusageonlyshown'] = 'Only users who already have used this purpose are being shown in this table.';
$string['verifyssl'] = 'Verify SSL certificates';
$string['verifyssldesc'] = 'If enabled, connections to the AI tools will only be established if the certificates can properly be verified. Only recommended to disable for development use!';
+$string['vertex_cachingdisabled'] = 'Caching disabled';
+$string['vertex_cachingenabled'] = 'Caching enabled';
+$string['vertex_disablecaching'] = 'Disable Caching';
+$string['vertex_enablecaching'] = 'Enable Caching';
+$string['vertex_error_cachestatus'] = 'Error while querying/updating the Vertex AI caching configuration';
+$string['vertex_nocachestatus'] = 'Click the refresh button to query the current Vertex AI cache status.';
+$string['vertexcachestatus'] = 'Query and change Vertex AI cache status';
$string['within'] = 'in';
diff --git a/styles.css b/styles.css
index d72c427..4ffb0b1 100644
--- a/styles.css
+++ b/styles.css
@@ -142,3 +142,15 @@ body.limitcontentwidth #page-content {
.dark .local_ai_manager-info-warning .local_ai_manager-info-warning-link {
color: #60616d;
}
+
+.local_ai_manager-caching_enabled {
+ color: #f00;
+}
+
+.local_ai_manager-caching_disabled {
+ color: #00bf00;
+}
+
+#page-local-ai_manager-edit_instance [data-name="vertexcachestatus"] {
+ width: 100%;
+}
\ No newline at end of file
diff --git a/templates/vertexcachestatus.mustache b/templates/vertexcachestatus.mustache
new file mode 100644
index 0000000..f5bb2f5
--- /dev/null
+++ b/templates/vertexcachestatus.mustache
@@ -0,0 +1,50 @@
+{{!
+ This file is part of Moodle - http://moodle.org/
+
+ Moodle is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Moodle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Moodle. If not, see .
+}}
+{{!
+ @template local_ai_manager/vertexcachestatus
+
+ Template for showing and editing the Google Vertex AI cache status.
+
+ Example context (json):
+ {
+ "noStatus": false,
+ "cachingEnabled": true
+ }
+}}
+