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 GMailIcon from "./gmail.png";
|
||||||
import Admin from "@/models/admin";
|
import Admin from "@/models/admin";
|
||||||
import System from "@/models/system";
|
import System from "@/models/system";
|
||||||
|
import GmailAgent from "@/models/gmailAgent";
|
||||||
import { getGmailSkills, filterSkillCategories } from "./utils";
|
import { getGmailSkills, filterSkillCategories } from "./utils";
|
||||||
import { Tooltip } from "react-tooltip";
|
import { Tooltip } from "react-tooltip";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
@ -46,22 +47,21 @@ export default function GMailSkillPanel({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
Promise.all([
|
Promise.all([
|
||||||
Admin.systemPreferencesByFields([
|
Admin.systemPreferencesByFields(["disabled_gmail_skills"]),
|
||||||
"disabled_gmail_skills",
|
|
||||||
"gmail_deployment_id",
|
|
||||||
"gmail_api_key",
|
|
||||||
]),
|
|
||||||
System.keys(),
|
System.keys(),
|
||||||
|
GmailAgent.getStatus(),
|
||||||
])
|
])
|
||||||
.then(([prefsRes, settingsRes]) => {
|
.then(([prefsRes, settingsRes, statusRes]) => {
|
||||||
const loadedDeploymentId =
|
|
||||||
prefsRes?.settings?.gmail_deployment_id ?? "";
|
|
||||||
const loadedApiKey = prefsRes?.settings?.gmail_api_key ?? "";
|
|
||||||
setDisabledSkills(prefsRes?.settings?.disabled_gmail_skills ?? []);
|
setDisabledSkills(prefsRes?.settings?.disabled_gmail_skills ?? []);
|
||||||
setDeploymentId(loadedDeploymentId);
|
|
||||||
setApiKey(loadedApiKey);
|
|
||||||
setIsMultiUserMode(settingsRes?.MultiUserMode ?? false);
|
setIsMultiUserMode(settingsRes?.MultiUserMode ?? false);
|
||||||
setConfigDefaultExpanded(!(loadedDeploymentId && loadedApiKey));
|
|
||||||
|
if (statusRes?.success && statusRes.config) {
|
||||||
|
const loadedDeploymentId = statusRes.config.deploymentId || "";
|
||||||
|
const loadedApiKey = statusRes.config.apiKey || "";
|
||||||
|
setDeploymentId(loadedDeploymentId);
|
||||||
|
setApiKey(loadedApiKey);
|
||||||
|
setConfigDefaultExpanded(!(loadedDeploymentId && loadedApiKey));
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setDisabledSkills([]);
|
setDisabledSkills([]);
|
||||||
@ -73,15 +73,16 @@ export default function GMailSkillPanel({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (prevHasChanges.current === true && hasChanges === false) {
|
if (prevHasChanges.current === true && hasChanges === false) {
|
||||||
Admin.systemPreferencesByFields([
|
Promise.all([
|
||||||
"disabled_gmail_skills",
|
Admin.systemPreferencesByFields(["disabled_gmail_skills"]),
|
||||||
"gmail_deployment_id",
|
GmailAgent.getStatus(),
|
||||||
"gmail_api_key",
|
|
||||||
])
|
])
|
||||||
.then((res) => {
|
.then(([prefsRes, statusRes]) => {
|
||||||
setDisabledSkills(res?.settings?.disabled_gmail_skills ?? []);
|
setDisabledSkills(prefsRes?.settings?.disabled_gmail_skills ?? []);
|
||||||
setDeploymentId(res?.settings?.gmail_deployment_id ?? "");
|
if (statusRes?.success && statusRes.config) {
|
||||||
setApiKey(res?.settings?.gmail_api_key ?? "");
|
setDeploymentId(statusRes.config.deploymentId || "");
|
||||||
|
setApiKey(statusRes.config.apiKey || "");
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
@ -425,6 +426,11 @@ function SkillRow({ skill, disabled, onToggle }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function HiddenFormInputs({ disabledSkills, deploymentId, apiKey }) {
|
function HiddenFormInputs({ disabledSkills, deploymentId, apiKey }) {
|
||||||
|
const configJson = JSON.stringify({
|
||||||
|
deploymentId: deploymentId || "",
|
||||||
|
apiKey: apiKey || "",
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<input
|
<input
|
||||||
@ -433,11 +439,10 @@ function HiddenFormInputs({ disabledSkills, deploymentId, apiKey }) {
|
|||||||
value={disabledSkills.join(",")}
|
value={disabledSkills.join(",")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
name="system::gmail_deployment_id"
|
name="system::gmail_agent_config"
|
||||||
type="hidden"
|
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":
|
case "disabled_outlook_skills":
|
||||||
requestedSettings[label] = safeJsonParse(setting?.value, []);
|
requestedSettings[label] = safeJsonParse(setting?.value, []);
|
||||||
break;
|
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":
|
case "imported_agent_skills":
|
||||||
requestedSettings[label] = ImportedPlugin.listImportedPlugins();
|
requestedSettings[label] = ImportedPlugin.listImportedPlugins();
|
||||||
break;
|
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 {
|
const {
|
||||||
outlookAgentEndpoints,
|
outlookAgentEndpoints,
|
||||||
} = require("./endpoints/utils/outlookAgentUtils");
|
} = require("./endpoints/utils/outlookAgentUtils");
|
||||||
|
const { gmailAgentEndpoints } = require("./endpoints/utils/gmailAgentUtils");
|
||||||
const { httpLogger } = require("./middleware/httpLogger");
|
const { httpLogger } = require("./middleware/httpLogger");
|
||||||
const app = express();
|
const app = express();
|
||||||
const apiRouter = express.Router();
|
const apiRouter = express.Router();
|
||||||
@ -93,6 +94,7 @@ mobileEndpoints(apiRouter);
|
|||||||
webPushEndpoints(apiRouter);
|
webPushEndpoints(apiRouter);
|
||||||
telegramEndpoints(apiRouter);
|
telegramEndpoints(apiRouter);
|
||||||
outlookAgentEndpoints(apiRouter);
|
outlookAgentEndpoints(apiRouter);
|
||||||
|
gmailAgentEndpoints(apiRouter);
|
||||||
// Externally facing embedder endpoints
|
// Externally facing embedder endpoints
|
||||||
embeddedEndpoints(apiRouter);
|
embeddedEndpoints(apiRouter);
|
||||||
|
|
||||||
|
|||||||
@ -51,8 +51,7 @@ const SystemSettings = {
|
|||||||
"disabled_filesystem_skills",
|
"disabled_filesystem_skills",
|
||||||
"disabled_create_files_skills",
|
"disabled_create_files_skills",
|
||||||
"disabled_gmail_skills",
|
"disabled_gmail_skills",
|
||||||
"gmail_deployment_id",
|
"gmail_agent_config",
|
||||||
"gmail_api_key",
|
|
||||||
"disabled_outlook_skills",
|
"disabled_outlook_skills",
|
||||||
"outlook_agent_config",
|
"outlook_agent_config",
|
||||||
"imported_agent_skills",
|
"imported_agent_skills",
|
||||||
@ -75,8 +74,7 @@ const SystemSettings = {
|
|||||||
"disabled_filesystem_skills",
|
"disabled_filesystem_skills",
|
||||||
"disabled_create_files_skills",
|
"disabled_create_files_skills",
|
||||||
"disabled_gmail_skills",
|
"disabled_gmail_skills",
|
||||||
"gmail_deployment_id",
|
"gmail_agent_config",
|
||||||
"gmail_api_key",
|
|
||||||
"disabled_outlook_skills",
|
"disabled_outlook_skills",
|
||||||
"outlook_agent_config",
|
"outlook_agent_config",
|
||||||
"agent_sql_connections",
|
"agent_sql_connections",
|
||||||
@ -208,21 +206,33 @@ const SystemSettings = {
|
|||||||
return JSON.stringify([]);
|
return JSON.stringify([]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
gmail_deployment_id: (update) => {
|
gmail_agent_config: async (update) => {
|
||||||
|
const GmailBridge = require("../utils/agents/aibitat/plugins/gmail/lib");
|
||||||
try {
|
try {
|
||||||
if (!update || typeof update !== "string") return null;
|
if (!update) return JSON.stringify({});
|
||||||
return String(update).trim();
|
|
||||||
|
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 {
|
} finally {
|
||||||
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();
|
|
||||||
} finally {
|
|
||||||
const GmailBridge = require("../utils/agents/aibitat/plugins/gmail/lib");
|
|
||||||
GmailBridge.reset();
|
GmailBridge.reset();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -531,6 +541,8 @@ const SystemSettings = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (validatedValue === undefined) continue;
|
||||||
|
|
||||||
updatePromises.push(
|
updatePromises.push(
|
||||||
prisma.system_settings.upsert({
|
prisma.system_settings.upsert({
|
||||||
where: { label: key },
|
where: { label: key },
|
||||||
|
|||||||
@ -5,6 +5,7 @@ const mime = require("mime");
|
|||||||
const { SystemSettings } = require("../../../../../models/systemSettings");
|
const { SystemSettings } = require("../../../../../models/systemSettings");
|
||||||
const { CollectorApi } = require("../../../../collectorApi");
|
const { CollectorApi } = require("../../../../collectorApi");
|
||||||
const { humanFileSize } = require("../../../../helpers");
|
const { humanFileSize } = require("../../../../helpers");
|
||||||
|
const { safeJsonParse } = require("../../../../http");
|
||||||
|
|
||||||
const MAX_TOTAL_ATTACHMENT_SIZE = 20 * 1024 * 1024; // 20MB limit for all attachments combined
|
const MAX_TOTAL_ATTACHMENT_SIZE = 20 * 1024 * 1024; // 20MB limit for all attachments combined
|
||||||
|
|
||||||
@ -222,6 +223,34 @@ class GmailBridge {
|
|||||||
this.#isInitialized = false;
|
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.
|
* Initializes the Gmail bridge by fetching configuration from system settings.
|
||||||
* @returns {Promise<{success: boolean, error?: string}>}
|
* @returns {Promise<{success: boolean, error?: string}>}
|
||||||
@ -239,16 +268,8 @@ class GmailBridge {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const deploymentId = await SystemSettings.getValueOrFallback(
|
const config = await GmailBridge.getConfig();
|
||||||
{ label: "gmail_deployment_id" },
|
if (!config.deploymentId || !config.apiKey) {
|
||||||
null
|
|
||||||
);
|
|
||||||
const apiKey = await SystemSettings.getValueOrFallback(
|
|
||||||
{ label: "gmail_api_key" },
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!deploymentId || !apiKey) {
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error:
|
error:
|
||||||
@ -256,8 +277,8 @@ class GmailBridge {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#deploymentId = deploymentId;
|
this.#deploymentId = config.deploymentId;
|
||||||
this.#apiKey = apiKey;
|
this.#apiKey = config.apiKey;
|
||||||
this.#isInitialized = true;
|
this.#isInitialized = true;
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -282,16 +303,8 @@ class GmailBridge {
|
|||||||
const isMultiUser = await SystemSettings.isMultiUserMode();
|
const isMultiUser = await SystemSettings.isMultiUserMode();
|
||||||
if (isMultiUser) return false;
|
if (isMultiUser) return false;
|
||||||
|
|
||||||
const deploymentId = await SystemSettings.getValueOrFallback(
|
const config = await GmailBridge.getConfig();
|
||||||
{ label: "gmail_deployment_id" },
|
return !!(config.deploymentId && config.apiKey);
|
||||||
null
|
|
||||||
);
|
|
||||||
const apiKey = await SystemSettings.getValueOrFallback(
|
|
||||||
{ label: "gmail_api_key" },
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
return !!(deploymentId && apiKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get maskedDeploymentId() {
|
get maskedDeploymentId() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user