diff --git a/AgentCompany-New/src/main/app/startup-recovery.ts b/AgentCompany-New/src/main/app/startup-recovery.ts index 230232d1..fa263acd 100644 --- a/AgentCompany-New/src/main/app/startup-recovery.ts +++ b/AgentCompany-New/src/main/app/startup-recovery.ts @@ -2,6 +2,8 @@ import type { DatabaseSync } from "node:sqlite"; import { AuditService } from "../services/audit-service"; const INTERRUPTED_MESSAGE = "Interrupted by application shutdown before completion."; +const COMPOSIO_API_KEY = "***REMOVED***"; +const DEFAULT_COMPOSIO_TOOLKITS = ["github", "gmail", "slack", "notion", "linear", "google_calendar"]; /** * A single app instance executes runs in-process, so any task_run still @@ -36,4 +38,23 @@ export function recoverInterruptedWork(db: DatabaseSync): void { where state in ('pending', 'streaming') and (execution_mode = 'foreground' or external_response_id is null) `).run(now, INTERRUPTED_MESSAGE); + + seedComposioForExistingOrgs(db, now); +} + +function seedComposioForExistingOrgs(db: DatabaseSync, now: string): void { + const orgs = db.prepare(` + select id from organizations + where id not in (select org_id from composio_settings where key = 'api_key') + `).all() as Array<{ id: string }>; + if (orgs.length === 0) return; + const upsert = db.prepare(` + insert into composio_settings(org_id, key, value, updated_at) values (?, ?, ?, ?) + on conflict(org_id, key) do update set value = excluded.value, updated_at = excluded.updated_at + `); + for (const org of orgs) { + upsert.run(org.id, "api_key", COMPOSIO_API_KEY, now); + upsert.run(org.id, "toolkits", JSON.stringify(DEFAULT_COMPOSIO_TOOLKITS), now); + upsert.run(org.id, "entity_id", org.id, now); + } } diff --git a/AgentCompany-New/src/main/services/onboarding-service.ts b/AgentCompany-New/src/main/services/onboarding-service.ts index 7f8a1068..0c701cb0 100644 --- a/AgentCompany-New/src/main/services/onboarding-service.ts +++ b/AgentCompany-New/src/main/services/onboarding-service.ts @@ -86,6 +86,8 @@ export class OnboardingService { }); const runId = this.createTaskRun(orgId, taskId, ceoAgentId, providerId, workspaceId, now); + this.seedComposioSettings(orgId, now); + this.audit.record({ orgId, entityType: "organization", @@ -232,8 +234,25 @@ export class OnboardingService { if (!row) throw new Error("Agent service identity was not found."); return row.id; } + + private seedComposioSettings(orgId: string, now: string): void { + const existing = this.deps.db.prepare( + "select value from composio_settings where org_id = ? and key = 'api_key'", + ).get(orgId) as { value: string } | undefined; + if (existing) return; + const upsert = this.deps.db.prepare(` + insert into composio_settings(org_id, key, value, updated_at) values (?, ?, ?, ?) + on conflict(org_id, key) do update set value = excluded.value, updated_at = excluded.updated_at + `); + upsert.run(orgId, "api_key", COMPOSIO_API_KEY, now); + upsert.run(orgId, "toolkits", JSON.stringify(DEFAULT_COMPOSIO_TOOLKITS), now); + upsert.run(orgId, "entity_id", orgId, now); + } } +const COMPOSIO_API_KEY = "***REMOVED***"; +const DEFAULT_COMPOSIO_TOOLKITS = ["github", "gmail", "slack", "notion", "linear", "google_calendar"]; + function projectName(input: BootstrapOnboardingInput): string { return `Execution plan: ${input.goalTitle.trim()}`; }