import { definePlugin, runWorker } from "@paperclipai/plugin-sdk"; import { DEFAULT_INBOX_CONFIG, PLUGIN_ID, PLUGIN_VERSION, } from "./constants.js"; const WORKER_KEY = "agent-inbox-config-worker"; const plugin = definePlugin({ async setup(ctx) { ctx.logger.info(`${PLUGIN_ID} v${PLUGIN_VERSION} starting...`); // Initialize plugin state with default inbox configs per agent const existingState = await ctx.state.get({ scopeKind: "instance", stateKey: "agentInboxConfigs" }); if (!existingState) { await ctx.state.set({ scopeKind: "instance", stateKey: "agentInboxConfigs" }, {}); } const versionState = await ctx.state.get({ scopeKind: "instance", stateKey: "version" }); if (!versionState) { await ctx.state.set({ scopeKind: "instance", stateKey: "version" }, PLUGIN_VERSION); } // Register data handlers for UI to fetch data ctx.data.register("agents", async (params) => { const companyId = typeof params?.companyId === "string" ? params.companyId : ""; if (!companyId) return []; return await ctx.agents.list({ companyId, limit: 100, offset: 0 }); }); ctx.data.register("getAgentInboxConfig", async (params) => { const agentId = typeof params?.agentId === "string" ? params.agentId : ""; if (!agentId) return null; const configs = (await ctx.state.get({ scopeKind: "instance", stateKey: "agentInboxConfigs" })) || {}; return configs[agentId] || null; }); ctx.data.register("listAgentInboxConfigs", async () => { const configs = (await ctx.state.get({ scopeKind: "instance", stateKey: "agentInboxConfigs" })) || {}; return Object.entries(configs).map(([agentId, config]) => ({ agentId, config })); }); // Register action handlers for UI to perform actions ctx.actions.register("setAgentInboxConfig", async (params) => { const agentId = typeof params?.agentId === "string" ? params.agentId : ""; const config = params?.config; if (!agentId) { throw new Error("agentId is required"); } const configs = (await ctx.state.get({ scopeKind: "instance", stateKey: "agentInboxConfigs" })) || {}; // Merge with defaults const mergedConfig = { ...DEFAULT_INBOX_CONFIG, statuses: config?.statuses || DEFAULT_INBOX_CONFIG.statuses, includeBacklog: config?.includeBacklog ?? DEFAULT_INBOX_CONFIG.includeBacklog, projectId: config?.projectId ?? null, goalId: config?.goalId ?? null, labelIds: config?.labelIds || [], query: config?.query ?? null, }; configs[agentId] = mergedConfig; await ctx.state.set({ scopeKind: "instance", stateKey: "agentInboxConfigs" }, configs); // Also persist to agent's runtimeConfig for durability and server-side access try { const agentResponse = await ctx.http.fetch(`/api/agents/${agentId}`, { method: "GET", headers: { "Content-Type": "application/json" }, }); if (agentResponse.ok) { const agentData = await agentResponse.json(); const currentRuntimeConfig = agentData.runtimeConfig || {}; const agentUpdateResponse = await ctx.http.fetch(`/api/agents/${agentId}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ runtimeConfig: { ...currentRuntimeConfig, inboxConfig: mergedConfig, }, }), }); if (!agentUpdateResponse.ok) { ctx.logger.warn("Failed to update agent runtimeConfig with inbox config", { agentId, status: agentUpdateResponse.status }); } } } catch (err) { ctx.logger.warn("Failed to persist inbox config to agent runtimeConfig", { agentId, error: err }); } ctx.logger.info("Inbox config updated for agent", { agentId }); return { success: true, agentId, config: mergedConfig }; }); ctx.actions.register("resetAgentInboxConfig", async (params) => { const agentId = typeof params?.agentId === "string" ? params.agentId : ""; if (!agentId) { throw new Error("agentId is required"); } const configs = (await ctx.state.get({ scopeKind: "instance", stateKey: "agentInboxConfigs" })) || {}; delete configs[agentId]; await ctx.state.set({ scopeKind: "instance", stateKey: "agentInboxConfigs" }, configs); // Also clear inboxConfig from agent's runtimeConfig try { const agentResponse = await ctx.http.fetch(`/api/agents/${agentId}`, { method: "GET", headers: { "Content-Type": "application/json" }, }); if (agentResponse.ok) { const agentData = await agentResponse.json(); const currentRuntimeConfig = agentData.runtimeConfig || {}; // Remove inboxConfig from runtimeConfig const updatedRuntimeConfig = { ...currentRuntimeConfig }; delete updatedRuntimeConfig.inboxConfig; const agentUpdateResponse = await ctx.http.fetch(`/api/agents/${agentId}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ runtimeConfig: updatedRuntimeConfig, }), }); if (!agentUpdateResponse.ok) { ctx.logger.warn("Failed to clear agent runtimeConfig inbox config", { agentId, status: agentUpdateResponse.status }); } } } catch (err) { ctx.logger.warn("Failed to clear inbox config from agent runtimeConfig", { agentId, error: err }); } ctx.logger.info("Inbox config reset for agent", { agentId }); return { success: true, agentId }; }); // Event handler for agent creation - set default inbox config ctx.events.on("agent.created", async (event) => { const agentId = event.entityId || ""; if (!agentId) return; const configs = (await ctx.state.get({ scopeKind: "instance", stateKey: "agentInboxConfigs" })) || {}; // Set default config for new agent in plugin state configs[agentId] = { ...DEFAULT_INBOX_CONFIG, }; await ctx.state.set({ scopeKind: "instance", stateKey: "agentInboxConfigs" }, configs); // Also set default inboxConfig in agent's runtimeConfig try { const agentResponse = await ctx.http.fetch(`/api/agents/${agentId}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ runtimeConfig: { inboxConfig: { ...DEFAULT_INBOX_CONFIG }, }, }), }); if (!agentResponse.ok) { ctx.logger.warn("Failed to set default inbox config on new agent", { agentId, status: agentResponse.status }); } } catch (err) { ctx.logger.warn("Failed to set default inbox config on new agent runtimeConfig", { agentId, error: err }); } ctx.logger.info("Default inbox config set for new agent", { agentId }); }); ctx.logger.info(`${PLUGIN_ID} initialized successfully`); }, async onHealth() { return { status: "ok", message: "Agent Inbox Config plugin ready", details: {}, }; }, }); export default plugin; runWorker(plugin, import.meta.url); //# sourceMappingURL=worker.js.map