Refactor Gmail Agent (#5439)
This commit is contained in:
parent
f17337fb97
commit
5aae72a5e5
22
frontend/src/models/gmailAgent.js
Normal file
22
frontend/src/models/gmailAgent.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { API_BASE } from "@/utils/constants";
|
||||
import { baseHeaders } from "@/utils/request";
|
||||
|
||||
const GmailAgent = {
|
||||
/**
|
||||
* Get the current configuration status for Gmail.
|
||||
* @returns {Promise<{success: boolean, isConfigured?: boolean, config?: {deploymentId: string, apiKey: string}, error?: string}>}
|
||||
*/
|
||||
getStatus: async () => {
|
||||
return await fetch(`${API_BASE}/admin/agent-skills/gmail/status`, {
|
||||
method: "GET",
|
||||
headers: baseHeaders(),
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
return { success: false, error: e.message };
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default GmailAgent;
|
||||
@ -19,6 +19,7 @@ import {
|
||||
import GMailIcon from "./gmail.png";
|
||||
import Admin from "@/models/admin";
|
||||
import System from "@/models/system";
|
||||
import GmailAgent from "@/models/gmailAgent";
|
||||
import { getGmailSkills, filterSkillCategories } from "./utils";
|
||||
import { Tooltip } from "react-tooltip";
|
||||
import { Link } from "react-router-dom";
|
||||
@ -46,22 +47,21 @@ export default function GMailSkillPanel({
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
Promise.all([
|
||||
Admin.systemPreferencesByFields([
|
||||
"disabled_gmail_skills",
|
||||
"gmail_deployment_id",
|
||||
"gmail_api_key",
|
||||
]),
|
||||
Admin.systemPreferencesByFields(["disabled_gmail_skills"]),
|
||||
System.keys(),
|
||||
GmailAgent.getStatus(),
|
||||
])
|
||||
.then(([prefsRes, settingsRes]) => {
|
||||
const loadedDeploymentId =
|
||||
prefsRes?.settings?.gmail_deployment_id ?? "";
|
||||
const loadedApiKey = prefsRes?.settings?.gmail_api_key ?? "";
|
||||
.then(([prefsRes, settingsRes, statusRes]) => {
|
||||
setDisabledSkills(prefsRes?.settings?.disabled_gmail_skills ?? []);
|
||||
setIsMultiUserMode(settingsRes?.MultiUserMode ?? false);
|
||||
|
||||
if (statusRes?.success && statusRes.config) {
|
||||
const loadedDeploymentId = statusRes.config.deploymentId || "";
|
||||
const loadedApiKey = statusRes.config.apiKey || "";
|
||||
setDeploymentId(loadedDeploymentId);
|
||||
setApiKey(loadedApiKey);
|
||||
setIsMultiUserMode(settingsRes?.MultiUserMode ?? false);
|
||||
setConfigDefaultExpanded(!(loadedDeploymentId && loadedApiKey));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setDisabledSkills([]);
|
||||
@ -73,15 +73,16 @@ export default function GMailSkillPanel({
|
||||
|
||||
useEffect(() => {
|
||||
if (prevHasChanges.current === true && hasChanges === false) {
|
||||
Admin.systemPreferencesByFields([
|
||||
"disabled_gmail_skills",
|
||||
"gmail_deployment_id",
|
||||
"gmail_api_key",
|
||||
Promise.all([
|
||||
Admin.systemPreferencesByFields(["disabled_gmail_skills"]),
|
||||
GmailAgent.getStatus(),
|
||||
])
|
||||
.then((res) => {
|
||||
setDisabledSkills(res?.settings?.disabled_gmail_skills ?? []);
|
||||
setDeploymentId(res?.settings?.gmail_deployment_id ?? "");
|
||||
setApiKey(res?.settings?.gmail_api_key ?? "");
|
||||
.then(([prefsRes, statusRes]) => {
|
||||
setDisabledSkills(prefsRes?.settings?.disabled_gmail_skills ?? []);
|
||||
if (statusRes?.success && statusRes.config) {
|
||||
setDeploymentId(statusRes.config.deploymentId || "");
|
||||
setApiKey(statusRes.config.apiKey || "");
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
@ -425,6 +426,11 @@ function SkillRow({ skill, disabled, onToggle }) {
|
||||
}
|
||||
|
||||
function HiddenFormInputs({ disabledSkills, deploymentId, apiKey }) {
|
||||
const configJson = JSON.stringify({
|
||||
deploymentId: deploymentId || "",
|
||||
apiKey: apiKey || "",
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
@ -433,11 +439,10 @@ function HiddenFormInputs({ disabledSkills, deploymentId, apiKey }) {
|
||||
value={disabledSkills.join(",")}
|
||||
/>
|
||||
<input
|
||||
name="system::gmail_deployment_id"
|
||||
name="system::gmail_agent_config"
|
||||
type="hidden"
|
||||
value={deploymentId}
|
||||
value={configJson}
|
||||
/>
|
||||
<input name="system::gmail_api_key" type="hidden" value={apiKey} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -415,12 +415,6 @@ function adminEndpoints(app) {
|
||||
case "disabled_outlook_skills":
|
||||
requestedSettings[label] = safeJsonParse(setting?.value, []);
|
||||
break;
|
||||
case "gmail_deployment_id":
|
||||
requestedSettings[label] = setting?.value || null;
|
||||
break;
|
||||
case "gmail_api_key":
|
||||
requestedSettings[label] = setting?.value || null;
|
||||
break;
|
||||
case "imported_agent_skills":
|
||||
requestedSettings[label] = ImportedPlugin.listImportedPlugins();
|
||||
break;
|
||||
|
||||
39
server/endpoints/utils/gmailAgentUtils.js
Normal file
39
server/endpoints/utils/gmailAgentUtils.js
Normal file
@ -0,0 +1,39 @@
|
||||
const {
|
||||
isSingleUserMode,
|
||||
} = require("../../utils/middleware/multiUserProtected");
|
||||
const { validatedRequest } = require("../../utils/middleware/validatedRequest");
|
||||
const { GmailBridge } = require("../../utils/agents/aibitat/plugins/gmail/lib");
|
||||
|
||||
function gmailAgentEndpoints(app) {
|
||||
if (!app) return;
|
||||
|
||||
app.get(
|
||||
"/admin/agent-skills/gmail/status",
|
||||
[validatedRequest, isSingleUserMode],
|
||||
async (_request, response) => {
|
||||
try {
|
||||
const config = await GmailBridge.getConfig();
|
||||
|
||||
const hasDeploymentId = !!config.deploymentId;
|
||||
const hasApiKey = !!config.apiKey;
|
||||
const isConfigured = hasDeploymentId && hasApiKey;
|
||||
|
||||
const safeConfig = {
|
||||
deploymentId: config.deploymentId || "",
|
||||
apiKey: hasApiKey ? "********" : "",
|
||||
};
|
||||
|
||||
return response.status(200).json({
|
||||
success: true,
|
||||
isConfigured,
|
||||
config: safeConfig,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Gmail status error:", e);
|
||||
response.status(500).json({ success: false, error: e.message });
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = { gmailAgentEndpoints };
|
||||
@ -38,6 +38,7 @@ const { telegramEndpoints } = require("./endpoints/telegram");
|
||||
const {
|
||||
outlookAgentEndpoints,
|
||||
} = require("./endpoints/utils/outlookAgentUtils");
|
||||
const { gmailAgentEndpoints } = require("./endpoints/utils/gmailAgentUtils");
|
||||
const { httpLogger } = require("./middleware/httpLogger");
|
||||
const app = express();
|
||||
const apiRouter = express.Router();
|
||||
@ -93,6 +94,7 @@ mobileEndpoints(apiRouter);
|
||||
webPushEndpoints(apiRouter);
|
||||
telegramEndpoints(apiRouter);
|
||||
outlookAgentEndpoints(apiRouter);
|
||||
gmailAgentEndpoints(apiRouter);
|
||||
// Externally facing embedder endpoints
|
||||
embeddedEndpoints(apiRouter);
|
||||
|
||||
|
||||
@ -51,8 +51,7 @@ const SystemSettings = {
|
||||
"disabled_filesystem_skills",
|
||||
"disabled_create_files_skills",
|
||||
"disabled_gmail_skills",
|
||||
"gmail_deployment_id",
|
||||
"gmail_api_key",
|
||||
"gmail_agent_config",
|
||||
"disabled_outlook_skills",
|
||||
"outlook_agent_config",
|
||||
"imported_agent_skills",
|
||||
@ -75,8 +74,7 @@ const SystemSettings = {
|
||||
"disabled_filesystem_skills",
|
||||
"disabled_create_files_skills",
|
||||
"disabled_gmail_skills",
|
||||
"gmail_deployment_id",
|
||||
"gmail_api_key",
|
||||
"gmail_agent_config",
|
||||
"disabled_outlook_skills",
|
||||
"outlook_agent_config",
|
||||
"agent_sql_connections",
|
||||
@ -208,21 +206,33 @@ const SystemSettings = {
|
||||
return JSON.stringify([]);
|
||||
}
|
||||
},
|
||||
gmail_deployment_id: (update) => {
|
||||
try {
|
||||
if (!update || typeof update !== "string") return null;
|
||||
return String(update).trim();
|
||||
} finally {
|
||||
gmail_agent_config: async (update) => {
|
||||
const GmailBridge = require("../utils/agents/aibitat/plugins/gmail/lib");
|
||||
GmailBridge.reset();
|
||||
}
|
||||
},
|
||||
gmail_api_key: (update) => {
|
||||
try {
|
||||
if (!update || typeof update !== "string") return null;
|
||||
return String(update).trim();
|
||||
if (!update) return JSON.stringify({});
|
||||
|
||||
const newConfig =
|
||||
typeof update === "string" ? safeJsonParse(update, {}) : update;
|
||||
const existingConfig = safeJsonParse(
|
||||
(await SystemSettings.get({ label: "gmail_agent_config" }))?.value,
|
||||
{}
|
||||
);
|
||||
|
||||
const mergedConfig = { ...existingConfig };
|
||||
|
||||
mergeStringField(mergedConfig, newConfig, "deploymentId");
|
||||
mergeStringField(
|
||||
mergedConfig,
|
||||
newConfig,
|
||||
"apiKey",
|
||||
(v) => !v.match(/^\*+$/)
|
||||
);
|
||||
|
||||
return JSON.stringify(mergedConfig);
|
||||
} catch (e) {
|
||||
console.error(`Could not validate gmail agent config:`, e.message);
|
||||
return JSON.stringify({});
|
||||
} finally {
|
||||
const GmailBridge = require("../utils/agents/aibitat/plugins/gmail/lib");
|
||||
GmailBridge.reset();
|
||||
}
|
||||
},
|
||||
@ -531,6 +541,8 @@ const SystemSettings = {
|
||||
}
|
||||
}
|
||||
|
||||
if (validatedValue === undefined) continue;
|
||||
|
||||
updatePromises.push(
|
||||
prisma.system_settings.upsert({
|
||||
where: { label: key },
|
||||
|
||||
@ -5,6 +5,7 @@ const mime = require("mime");
|
||||
const { SystemSettings } = require("../../../../../models/systemSettings");
|
||||
const { CollectorApi } = require("../../../../collectorApi");
|
||||
const { humanFileSize } = require("../../../../helpers");
|
||||
const { safeJsonParse } = require("../../../../http");
|
||||
|
||||
const MAX_TOTAL_ATTACHMENT_SIZE = 20 * 1024 * 1024; // 20MB limit for all attachments combined
|
||||
|
||||
@ -222,6 +223,34 @@ class GmailBridge {
|
||||
this.#isInitialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current Gmail agent configuration from system settings.
|
||||
* @returns {Promise<{deploymentId?: string, apiKey?: string}>}
|
||||
*/
|
||||
static async getConfig() {
|
||||
const configJson = await SystemSettings.getValueOrFallback(
|
||||
{ label: "gmail_agent_config" },
|
||||
"{}"
|
||||
);
|
||||
return safeJsonParse(configJson, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Gmail agent configuration in system settings.
|
||||
* @param {Object} updates - Fields to update
|
||||
* @returns {Promise<{success: boolean, error?: string}>}
|
||||
*/
|
||||
static async updateConfig(updates) {
|
||||
try {
|
||||
await SystemSettings.updateSettings({
|
||||
gmail_agent_config: JSON.stringify(updates),
|
||||
});
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Gmail bridge by fetching configuration from system settings.
|
||||
* @returns {Promise<{success: boolean, error?: string}>}
|
||||
@ -239,16 +268,8 @@ class GmailBridge {
|
||||
};
|
||||
}
|
||||
|
||||
const deploymentId = await SystemSettings.getValueOrFallback(
|
||||
{ label: "gmail_deployment_id" },
|
||||
null
|
||||
);
|
||||
const apiKey = await SystemSettings.getValueOrFallback(
|
||||
{ label: "gmail_api_key" },
|
||||
null
|
||||
);
|
||||
|
||||
if (!deploymentId || !apiKey) {
|
||||
const config = await GmailBridge.getConfig();
|
||||
if (!config.deploymentId || !config.apiKey) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
@ -256,8 +277,8 @@ class GmailBridge {
|
||||
};
|
||||
}
|
||||
|
||||
this.#deploymentId = deploymentId;
|
||||
this.#apiKey = apiKey;
|
||||
this.#deploymentId = config.deploymentId;
|
||||
this.#apiKey = config.apiKey;
|
||||
this.#isInitialized = true;
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
@ -282,16 +303,8 @@ class GmailBridge {
|
||||
const isMultiUser = await SystemSettings.isMultiUserMode();
|
||||
if (isMultiUser) return false;
|
||||
|
||||
const deploymentId = await SystemSettings.getValueOrFallback(
|
||||
{ label: "gmail_deployment_id" },
|
||||
null
|
||||
);
|
||||
const apiKey = await SystemSettings.getValueOrFallback(
|
||||
{ label: "gmail_api_key" },
|
||||
null
|
||||
);
|
||||
|
||||
return !!(deploymentId && apiKey);
|
||||
const config = await GmailBridge.getConfig();
|
||||
return !!(config.deploymentId && config.apiKey);
|
||||
}
|
||||
|
||||
get maskedDeploymentId() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user