@michael-joseph-miller/ant-bot 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +4 -4
- package/dist/index.js +4 -2
- package/dist/index.js.map +2 -2
- package/dist/server.js +53 -2
- package/dist/server.js.map +2 -2
- package/package.json +1 -1
- package/web/dist/assets/{index-Cfy0hrM2.js → index-YLvrZXZp.js} +1 -1
- package/web/dist/index.html +1 -1
package/dist/server.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../daemon/src/api/server.ts", "../../daemon/src/app.ts", "../../daemon/src/db/db.ts", "../../daemon/src/db/migrations.ts", "../../daemon/src/db/schema.ts", "../../daemon/src/db/store.ts", "../../daemon/src/util/bus.ts", "../../daemon/src/permissions/rules.ts", "../../daemon/src/permissions/local.ts", "../../daemon/src/permissions/gateway.ts", "../../daemon/src/permissions/autoreview.ts", "../../daemon/src/agent/session.ts", "../../daemon/src/agent/runtime.ts", "../../daemon/src/bots/manager.ts", "../../daemon/src/memory/memory.ts", "../../daemon/src/bots/prompt.ts", "../../daemon/src/bots/connectors.ts", "../../daemon/src/connectors/auth.ts", "../../daemon/src/connectors/oauth.ts", "../../daemon/src/connectors/builtin/service.ts", "../../daemon/src/connectors/builtin/gmail.ts", "../../daemon/src/connectors/builtin/mcpServer.ts", "../../daemon/src/connectors/builtin/catalog.ts", "../../daemon/src/bots/mcpProbe.ts", "../../daemon/src/connectors/check.ts", "../../daemon/src/config/config.ts", "../../daemon/src/config/paths.ts", "../../daemon/src/permissions/secrets.ts", "../../daemon/src/bots/groups.ts", "../../daemon/src/api/routes-core.ts", "../../daemon/src/api/routes-ops.ts"],
|
|
4
|
-
"sourcesContent": ["import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createRequire } from 'node:module';\nimport Fastify, { type FastifyInstance } from 'fastify';\nimport cors from '@fastify/cors';\nimport multipart from '@fastify/multipart';\nimport websocket from '@fastify/websocket';\nimport fastifyStatic from '@fastify/static';\nimport { createApp, drainMailbox, type App } from '../app.js';\nimport { registerCoreRoutes } from './routes-core.js';\nimport { registerOpsRoutes } from './routes-ops.js';\nimport { logger } from '../util/log.js';\nimport { LIMITS, ScreencastClientFrameSchema } from '@antbot/contract';\nimport { findWebDist, nodeLocateDeps } from '../util/locate.js';\n\nconst log = logger('server');\n\nexport interface StartOptions {\n root?: string;\n port?: number;\n host?: string;\n withAgent?: boolean;\n serveStatic?: boolean;\n}\n\nexport interface RunningServer {\n fastify: FastifyInstance;\n app: App;\n url: string;\n close: () => Promise<void>;\n}\n\nconst require_ = createRequire(import.meta.url);\n\nfunction resolveWebDist(): string | null {\n return findWebDist(\n nodeLocateDeps(path.dirname(fileURLToPath(import.meta.url)), (spec) => {\n try {\n return require_.resolve(spec);\n } catch {\n return null;\n }\n }),\n );\n}\n\nexport async function startServer(opts: StartOptions = {}): Promise<RunningServer> {\n const app = await createApp({ root: opts.root, withAgent: opts.withAgent });\n const fastify = Fastify({ logger: false, bodyLimit: LIMITS.MAX_VIDEO_ATTACHMENT_BYTES });\n\n // Several endpoints are pure commands with no payload (stop, duplicate, read,\n // test-run). Fastify rejects a zero-length body when the client still sends\n // `content-type: application/json` \u2014 and it does so before any content-type\n // parser runs \u2014 so drop the header for genuinely empty requests.\n fastify.addHook('onRequest', (req, _reply, done) => {\n const len = req.headers['content-length'];\n const ct = req.headers['content-type'];\n if ((len === '0' || len === undefined) && ct?.includes('application/json')) {\n delete req.headers['content-type'];\n }\n done();\n });\n\n await fastify.register(cors, { origin: true });\n await fastify.register(multipart, {\n limits: { fileSize: LIMITS.MAX_VIDEO_ATTACHMENT_BYTES, files: LIMITS.MAX_ATTACHMENTS_PER_MESSAGE },\n });\n await fastify.register(websocket);\n\n registerCoreRoutes(fastify, app);\n registerOpsRoutes(fastify, app);\n\n /* ------------------------- event websocket ------------------------- */\n fastify.register(async (scope) => {\n scope.get('/api/events', { websocket: true }, (socket) => {\n const send = (payload: unknown): void => {\n try {\n if (socket.readyState === 1) socket.send(JSON.stringify(payload));\n } catch { /* client vanished */ }\n };\n const unsubscribe = app.bus.subscribe(send);\n // Handshake only \u2014 carries the current seq so the client can detect gaps.\n // Deliberately not a `notify`: connection state is UI chrome, not a user alert.\n send({ type: 'hello', seq: app.bus.currentSeq, epoch: app.bus.epoch, threadId: null, botId: null });\n\n socket.on('message', (raw: Buffer) => {\n try {\n const msg = JSON.parse(raw.toString()) as { type?: string; seq?: number };\n if (msg.type === 'resume' && typeof msg.seq === 'number')\n for (const e of app.bus.since(msg.seq)) send(e);\n } catch { /* ignore malformed client frames */ }\n });\n socket.on('close', unsubscribe);\n socket.on('error', unsubscribe);\n });\n\n /* --------------------------- screencast -------------------------- */\n scope.get<{ Params: { botId: string } }>('/api/computer/screencast/:botId', { websocket: true }, async (socket, req) => {\n const botId = req.params.botId;\n if (!app.browser?.startScreencast) {\n try { socket.send(JSON.stringify({ type: 'error', message: 'Browser service unavailable' })); } catch { /* ignore */ }\n socket.close();\n return;\n }\n let stop: (() => void) | undefined;\n try {\n stop = await app.browser.startScreencast(botId, (data: string, w: number, h: number) => {\n try {\n if (socket.readyState === 1) socket.send(JSON.stringify({ type: 'frame', data, w, h }));\n } catch { /* ignore */ }\n });\n } catch (err) {\n try { socket.send(JSON.stringify({ type: 'error', message: (err as Error).message })); } catch { /* ignore */ }\n socket.close();\n return;\n }\n // The socket is bidirectional: frames stream out, and human input comes back in while the\n // screen is taken over. Validated against the shared schema rather than trusted, because\n // this is the one place a browser can ask the daemon to act on a page.\n socket.on('message', (raw: Buffer) => {\n if (!app.browser?.forwardInput) return;\n let frame;\n try {\n frame = ScreencastClientFrameSchema.parse(JSON.parse(raw.toString()));\n } catch {\n return; // malformed frame \u2014 ignore rather than tearing down the screencast\n }\n const fail = (err: unknown): void => {\n try {\n if (socket.readyState === 1)\n socket.send(JSON.stringify({ type: 'input-error', message: (err as Error).message }));\n } catch { /* ignore */ }\n };\n\n if (frame.type === 'selection-request') {\n if (!app.browser.readSelection) return;\n void app.browser\n .readSelection(botId)\n .then((text: string) => {\n try {\n if (socket.readyState === 1) socket.send(JSON.stringify({ type: 'selection', text }));\n } catch { /* ignore */ }\n })\n .catch(fail);\n return;\n }\n\n void app.browser.forwardInput(botId, frame.input).catch(fail);\n });\n\n socket.on('close', () => stop?.());\n socket.on('error', () => stop?.());\n });\n });\n\n /* ---------------------------- static UI ---------------------------- */\n if (opts.serveStatic !== false) {\n const dist = resolveWebDist();\n if (dist) {\n await fastify.register(fastifyStatic, { root: dist, prefix: '/' });\n fastify.setNotFoundHandler((req, reply) => {\n if (req.url.startsWith('/api')) return reply.code(404).send({ error: 'Not found' });\n return reply.sendFile('index.html');\n });\n log.info(`serving UI from ${dist}`);\n } else {\n log.warn('web UI not built \u2014 run `pnpm --filter @antbot/ui build`');\n fastify.setNotFoundHandler((req, reply) => {\n if (req.url.startsWith('/api')) return reply.code(404).send({ error: 'Not found' });\n return reply.type('text/html').send(\n `<!doctype html><meta charset=utf-8><title>ant-bot</title>\n <body style=\"font-family:system-ui;background:#0b0d10;color:#e6e8eb;padding:3rem\">\n <h1>ant-bot daemon is running</h1>\n <p>The web UI has not been built yet. Run:</p>\n <pre style=\"background:#151922;padding:1rem;border-radius:8px\">pnpm --filter @antbot/ui build</pre>\n <p>The API is live at <code>/api/health</code>.</p>`,\n );\n });\n }\n }\n\n fastify.setErrorHandler((err: unknown, _req, reply) => {\n log.error('request failed', err);\n const e = err as { statusCode?: number; message?: string };\n const code = e.statusCode && e.statusCode >= 400 ? e.statusCode : 500;\n reply.code(code).send({ error: e.message ?? 'Internal error' });\n });\n\n const port = opts.port ?? app.cfg.port;\n const host = opts.host ?? app.cfg.host;\n // Everything that builds a URL back to this daemon \u2014 OAuth redirect, built-in MCP endpoints \u2014\n // reads the port from here, so a `--port` override has to land before the first request.\n app.cfg.port = port;\n await fastify.listen({ port, host });\n const url = `http://${host}:${port}`;\n\n const delivered = drainMailbox(app);\n if (delivered) log.info(`redelivered ${delivered} queued handoff message(s)`);\n\n // Mark any turn that was mid-flight when the daemon died as interrupted.\n const stale = app.store.listBots().filter((b) => b.state === 'running' || b.state === 'queued');\n for (const b of stale) app.store.updateBot(b.id, { state: 'idle' });\n app.db.prepare(`UPDATE messages SET streaming=0 WHERE streaming=1`).run();\n app.db.prepare(`UPDATE approvals SET status='expired', reason='Daemon restarted' WHERE status='pending'`).run();\n app.db.prepare(`UPDATE routine_runs SET status='interrupted', finished_at=? WHERE status='running'`).run(Date.now());\n\n log.info(`ant-bot listening on ${url}`);\n\n return {\n fastify,\n app,\n url,\n close: async () => {\n await fastify.close();\n await app.shutdown();\n },\n };\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { openDb, type DB } from './db/db.js';\nimport { Store } from './db/store.js';\nimport { EventBus } from './util/bus.js';\nimport { PermissionGateway } from './permissions/gateway.js';\nimport { seedBuiltinRules } from './permissions/rules.js';\nimport { makeAutoReviewer, NullAutoReviewer } from './permissions/autoreview.js';\nimport { BotManager } from './bots/manager.js';\nimport { planConnectorMount, extractSecretRefs, buildMcpServerConfig, computeMissingSecrets } from './bots/connectors.js';\nimport { ConnectorAuthService } from './connectors/auth.js';\nimport type { MountedConnector } from './agent/runtime.js';\nimport { BuiltinService } from './connectors/builtin/service.js';\nimport { gatherCustomSignals, decideCheck } from './connectors/check.js';\nimport { readPackageVersion } from './util/locate.js';\nimport { fileURLToPath } from 'node:url';\nimport type { Connector, ConnectorCheck } from '@antbot/contract';\nimport { loadConfig, type AntbotConfig } from './config/config.js';\nimport { logger } from './util/log.js';\nimport type { Settings } from '@antbot/contract';\nimport { SecretsService, pickBackend } from './permissions/secrets.js';\n\nconst log = logger('app');\n\n/**\n * Load a subsystem that may not work on this machine \u2014 no Playwright installed, no fts5 \u2014 so the\n * daemon still boots without it.\n *\n * `load` must be a thunk around a *literal* dynamic import. This used to take a specifier string\n * and assemble it at runtime (`import(\\`${spec}\\`)`) so the compiler would not require the module\n * to exist; every one of them exists now, and the runtime-assembled form is invisible to a\n * bundler \u2014 the published build resolved them relative to the bundle, found nothing, and booted\n * with skills, browser and scheduler all silently missing.\n */\nasync function optionalImport(name: string, load: () => Promise<unknown>): Promise<any | null> {\n try {\n return await load();\n } catch (err) {\n log.warn(`${name} module could not be loaded`, (err as Error).message);\n return null;\n }\n}\n\nexport interface App {\n cfg: AntbotConfig;\n db: DB;\n store: Store;\n bus: EventBus;\n gateway: PermissionGateway;\n manager: BotManager;\n getSettings: () => Settings;\n /** Optional subsystems, wired if their modules are present. */\n scheduler?: any;\n browser?: any;\n skills?: any;\n secrets?: SecretsService;\n connectorAuth?: ConnectorAuthService;\n /** Serves ant-bot's built-in connectors (Gmail\u2026) over MCP from the daemon itself. */\n builtin?: BuiltinService;\n /** One connector, resolved to what the runtime mounts \u2014 or null when it cannot be mounted. */\n mountConnector: (connector: Connector) => Promise<MountedConnector | null>;\n /** One honest verdict, persisted on the row. */\n checkConnector: (connector: Connector) => Promise<ConnectorCheck>;\n lastUserActivity: { at: number };\n /** Root of the local plugin carrying installed skills. */\n skillPluginPath?: string;\n shutdown: () => Promise<void>;\n}\n\nexport async function createApp(opts: { root?: string; withAgent?: boolean } = {}): Promise<App> {\n const cfg = loadConfig(opts.root);\n const db = openDb(cfg.paths.db, { backupsDir: cfg.paths.backups });\n const store = new Store(db);\n\n // config.toml holds first-run defaults; the DB is authoritative afterwards.\n const persisted = store.getSettings();\n const settingsCount = store.db.prepare(`SELECT COUNT(*) c FROM settings`).get() as { c: number };\n if (!settingsCount.c) {\n store.patchSettings(cfg.settings);\n }\n const getSettings = (): Settings => store.getSettings();\n void persisted;\n\n seedBuiltinRules(store);\n\n const bus = new EventBus();\n const reviewer = opts.withAgent === false\n ? new NullAutoReviewer()\n : makeAutoReviewer(getSettings, cfg.paths.workspace);\n const gateway = new PermissionGateway(store, bus, reviewer);\n\n const app: App = {\n cfg, db, store, bus, gateway, getSettings,\n manager: undefined as unknown as BotManager,\n lastUserActivity: { at: Date.now() },\n shutdown: async () => {},\n mountConnector: async () => null,\n checkConnector: async () => ({ status: 'unreachable', tools: [] }),\n };\n\n app.manager = new BotManager({\n store, bus, gateway,\n workspace: cfg.paths.workspace,\n // The human attached these files deliberately; reading one is not \"reaching outside the\n // workspace\" in the sense the boundary exists to catch.\n readableRoots: [cfg.paths.attachments],\n getSettings,\n skillPluginPath: () => app.skillPluginPath,\n installSkill: async (source: string, opts?: { allowMultiple?: boolean }) => {\n if (!app.skills?.installFromSource) throw new Error('Skill installation is unavailable.');\n const installed = await app.skills.installFromSource(source, opts ?? {});\n return installed.map((i: { skill: { name: string }; executables: string[] }) => ({\n name: i.skill.name,\n executables: i.executables,\n }));\n },\n listSkills: () =>\n store.listSkills().map((sk) => ({ slug: sk.slug, name: sk.name, description: sk.description })),\n // Routed through SkillStore so the directory and the registration go together \u2014 a bot\n // deleting directories with Bash is what leaves the registry pointing at nothing.\n removeSkill: async (slug: string) => {\n if (!app.skills?.deleteSkill) throw new Error('Skill removal is unavailable.');\n const skill = store.getSkillBySlug(slug);\n if (!skill) return { removed: false };\n app.skills.deleteSkill(skill.id);\n return { removed: true, name: skill.name };\n },\n browserTools: (botId: string) => {\n if (!app.browser?.toolServerFor) return undefined;\n try {\n return app.browser.toolServerFor(botId);\n } catch {\n return undefined;\n }\n },\n /**\n * Resolve this bot's connectors into mountable MCP servers.\n *\n * This is the only place a secret value is read for a turn, and the values live nowhere but\n * the returned config \u2014 not in the row, not in a log line, not in anything a route returns.\n * A connector missing a credential is dropped rather than mounted broken or allowed to fail\n * the turn; the human was already warned on the connectors screen.\n */\n connectorServers: async (botId: string) => {\n const assigned = store.listBotConnectors(botId);\n const servers: Record<string, MountedConnector> = {};\n const mounted: { name: string; description: string }[] = [];\n for (const connector of assigned) {\n const built = await app.mountConnector(connector);\n if (!built) continue;\n servers[connector.name] = built;\n mounted.push({ name: connector.name, description: connector.description });\n }\n return { servers, mounted };\n },\n });\n\n /**\n * Resolve one connector to what the runtime mounts.\n *\n * This is the only place a secret value is read for a turn, and the values live nowhere but the\n * returned config \u2014 not in the row, not in a log line, not in anything a route returns. A\n * connector missing a credential is dropped rather than mounted broken or allowed to fail the\n * turn; the row's status says why. A built-in connector mounts as the daemon's own endpoint with\n * this boot's bearer; its provider token never leaves the daemon.\n */\n app.mountConnector = async (connector) => {\n if (connector.kind === 'builtin') {\n if (!app.builtin?.get(connector.name)) return null;\n return app.builtin.mountConfig(connector);\n }\n const available = new Set(app.secrets?.list() ?? []);\n const { skipped } = planConnectorMount([connector], available);\n if (skipped.length) {\n const missing = skipped[0]!.missing;\n log.warn(`connector \"${connector.name}\" not mounted \u2014 missing secret(s): ${missing.join(', ')}`);\n store.setConnectorStatus(connector.id, 'needs-credential', `missing secret(s): ${missing.join(', ')}`);\n return null;\n }\n try {\n const refs = extractSecretRefs(connector.config);\n const secrets = refs.length ? await app.secrets!.resolve(refs) : new Map<string, string | null>();\n const built = buildMcpServerConfig(connector, secrets);\n // A signed-in connector carries a bearer token that is refreshed here if it is close to\n // expiring. A static Authorization header in the config wins \u2014 that is the human being\n // deliberate.\n const auth = await app.connectorAuth?.authHeader(connector.name);\n if (auth && built.type !== 'stdio' && !('Authorization' in built.headers)) {\n built.headers = { ...built.headers, ...auth };\n }\n return built;\n } catch (err) {\n // A secret that vanished between planning and reading. Same treatment as a missing one.\n log.warn(`connector \"${connector.name}\" not mounted`, (err as Error).message);\n store.setConnectorStatus(connector.id, 'needs-credential', (err as Error).message);\n return null;\n }\n };\n\n app.checkConnector = async (connector) => {\n let verdict: ConnectorCheck;\n if (connector.kind === 'builtin') {\n const def = app.builtin?.get(connector.name);\n const tools = def ? def.tools().map((t) => ({ name: t.name, description: t.description })) : [];\n verdict = decideCheck({\n probe: def ? { ok: true, tools } : null,\n challenge: 'none',\n missingSecrets: [],\n builtinSignedIn: app.builtin?.authorized(connector.name) ?? false,\n builtinProvider: def ? { name: def.provider.displayName, dynamicRegistration: def.provider.dynamicRegistration } : undefined,\n });\n } else {\n const available = new Set(app.secrets?.list() ?? []);\n const missing = computeMissingSecrets(connector, available);\n const mounted = missing.length ? null : await app.mountConnector(connector);\n verdict = decideCheck(await gatherCustomSignals(connector, mounted, missing));\n }\n store.setConnectorStatus(connector.id, verdict.status, verdict.detail ?? null);\n return verdict;\n };\n\n // --- secrets (keychain-backed; values never reach the model) ---\n try {\n app.secrets = new SecretsService(\n await pickBackend(cfg.paths.secrets),\n `${cfg.paths.secrets}.index`,\n );\n log.info(`secrets backend: ${app.secrets.backendName}`);\n app.connectorAuth = new ConnectorAuthService(app.secrets, () => app.cfg.port);\n } catch (err) {\n log.warn('secrets backend unavailable', (err as Error).message);\n }\n // Built-in connectors are served regardless; without a secrets backend they simply cannot be\n // signed in to, and the check says so.\n app.builtin = new BuiltinService(\n app.connectorAuth,\n () => app.cfg.port,\n readPackageVersion(path.dirname(fileURLToPath(import.meta.url)), (p) => fs.existsSync(p), (p) => fs.readFileSync(p, 'utf8')),\n );\n try {\n void 0;\n } catch (err) {\n log.warn('secrets backend unavailable', (err as Error).message);\n }\n\n // --- optional subsystems (built concurrently; wired only if present) ---\n await wireSkills(app);\n await wireBrowser(app);\n await wireScheduler(app);\n\n app.shutdown = async () => {\n try { app.scheduler?.stop?.(); } catch { /* ignore */ }\n try { await app.browser?.shutdown?.(); } catch { /* ignore */ }\n try { db.close(); } catch { /* ignore */ }\n };\n\n return app;\n}\n\nasync function wireSkills(app: App): Promise<void> {\n try {\n const mod = await optionalImport('skills', () => import('./skills/skills.js'));\n const pluginMod = await optionalImport('skill plugin', () => import('./skills/plugin.js'));\n const Ctor = mod?.SkillStore ?? mod?.default;\n if (!Ctor) return void log.warn('skills subsystem unavailable: no SkillStore export');\n\n // The skills directory doubles as a local plugin root so the SDK can load skills\n // natively; individual skills live one level down, under `skills/`.\n const pluginRoot = app.cfg.paths.skills;\n if (pluginMod?.ensureSkillPlugin) {\n pluginMod.ensureSkillPlugin(pluginRoot);\n const moved: string[] = pluginMod.migrateLegacyLayout?.(pluginRoot) ?? [];\n if (moved.length) log.info(`migrated ${moved.length} skill(s) into the plugin layout: ${moved.join(', ')}`);\n app.skillPluginPath = pluginRoot;\n }\n const filesDir: string = pluginMod?.skillFilesDir?.(pluginRoot) ?? pluginRoot;\n\n app.skills = new Ctor(app.store, filesDir);\n\n // Skills shipped with ant-bot are installed on every boot and refreshed in place, but\n // only while the user has not edited or deleted their copy \u2014 see skills/bundled.ts.\n const bundledMod = await optionalImport('bundled skills', () => import('./skills/bundled.js'));\n if (bundledMod?.syncBundledSkills) {\n try {\n const decisions: { slug: string; action: string }[] = bundledMod.syncBundledSkills(filesDir);\n const took = (action: string): string[] =>\n decisions.filter((d) => d.action === action).map((d) => d.slug);\n const installed = took('install');\n const updated = took('update');\n const kept = [...took('skip-modified'), ...took('skip-foreign')];\n if (installed.length) log.info(`installed ${installed.length} bundled skill(s): ${installed.join(', ')}`);\n if (updated.length) log.info(`updated ${updated.length} bundled skill(s): ${updated.join(', ')}`);\n if (kept.length) log.info(`left ${kept.length} locally-modified skill(s) alone: ${kept.join(', ')}`);\n\n // syncFromDisk only registers slugs the db has never seen, so a skill whose shipped\n // frontmatter `name` changed would keep its old registered name \u2014 and the SDK is handed\n // registered names as `enabledSkills`, so it would silently stop resolving for every bot\n // that had it enabled.\n const written = [...installed, ...updated, ...took('adopt')];\n const renamed: string[] = app.skills?.refreshFromDisk?.(written) ?? [];\n if (renamed.length) log.info(`refreshed metadata for ${renamed.length} skill(s): ${renamed.join(', ')}`);\n } catch (e) {\n log.warn('bundled skills not synced', (e as Error).message);\n }\n }\n app.skills.syncFromDisk?.();\n // Registry and disk drift apart when skills are removed by hand or a layout migration\n // moves files; left alone, the UI lists skills that cannot load.\n const fixed = app.skills.reconcile?.() as { repaired: string[]; removed: string[] } | undefined;\n if (fixed?.repaired.length) log.info(`repaired ${fixed.repaired.length} skill path(s): ${fixed.repaired.join(', ')}`);\n if (fixed?.removed.length) log.info(`dropped ${fixed.removed.length} skill row(s) with no files on disk`);\n log.info(`skills ready (${app.store.listSkills().length} registered)`);\n } catch (err) {\n log.warn('skills subsystem unavailable', (err as Error).message);\n }\n}\n\nasync function wireBrowser(app: App): Promise<void> {\n try {\n const mod = await optionalImport('browser', () => import('./computer/browser.js'));\n const Ctor = mod?.BrowserService ?? mod?.default;\n if (!Ctor) return void log.warn('browser subsystem unavailable: no BrowserService export');\n const svc = new Ctor({ profileDir: app.cfg.paths.browserProfile, bus: app.bus, headless: true });\n let toolsMod: any = null;\n toolsMod = await optionalImport('browser tools', () => import('./computer/tools.js'));\n // Each bot drives its own page (\"screen\") on the one shared browser profile.\n const cache = new Map<string, unknown>();\n svc.toolServerFor = (botId: string) => {\n if (!toolsMod?.createBrowserToolServer) return undefined;\n let s = cache.get(botId);\n if (!s) {\n s = toolsMod.createBrowserToolServer(svc, botId, app.cfg.paths.workspace);\n cache.set(botId, s);\n }\n return s;\n };\n app.browser = svc;\n log.info('browser computer service ready');\n } catch (err) {\n log.warn('browser subsystem unavailable', (err as Error).message);\n }\n}\n\nasync function wireScheduler(app: App): Promise<void> {\n try {\n const mod = await optionalImport('scheduler', () => import('./scheduler/scheduler.js'));\n const Ctor = mod?.Scheduler ?? mod?.default;\n if (!Ctor) return void log.warn('scheduler subsystem unavailable: no Scheduler export');\n app.scheduler = new Ctor({\n store: app.store, bus: app.bus, manager: app.manager, getSettings: app.getSettings,\n });\n app.scheduler.start?.();\n log.info(`scheduler started (${app.store.listRoutines().filter((r) => r.enabled).length} active routines)`);\n } catch (err) {\n log.warn('scheduler subsystem unavailable', (err as Error).message);\n }\n}\n\n/** Deliver queued bot-to-bot mail on boot so handoffs survive a restart. */\nexport function drainMailbox(app: App): number {\n let n = 0;\n for (const bot of app.store.listBots()) {\n for (const m of app.store.listMail(bot.id)) {\n const from = app.store.getBot(m.fromBotId);\n app.manager.enqueue({\n botId: bot.id, threadId: bot.threadId!, origin: 'bot', hops: m.hops,\n prompt: `**Handoff from @${from?.slug ?? 'unknown'}:**\\n\\n${m.contentMd}`,\n });\n app.store.markDelivered(m.id);\n n++;\n }\n }\n return n;\n}\n\nexport function workspaceRelative(root: string, p: string): string | null {\n const resolved = path.resolve(root, p);\n const rel = path.relative(root, resolved);\n if (rel.startsWith('..') || path.isAbsolute(rel)) return null;\n return resolved;\n}\n\nexport function ensureWorkspaceFile(p: string): boolean {\n try { return fs.statSync(p).isFile(); } catch { return false; }\n}\n", "import Database from 'better-sqlite3';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { migrate } from './migrations.js';\nimport { logger } from '../util/log.js';\n\nexport type DB = Database.Database;\n\nconst log = logger('db');\n\nexport interface OpenDbOptions {\n /**\n * Where a pre-migration snapshot is written. Defaults to a `backups` sibling of the database\n * file, which is `paths.backups` for a real install. Ignored for `:memory:`.\n */\n backupsDir?: string;\n}\n\nexport function openDb(file: string, opts: OpenDbOptions = {}): DB {\n if (file !== ':memory:') fs.mkdirSync(path.dirname(file), { recursive: true });\n const db = new Database(file);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n db.pragma('busy_timeout = 5000');\n\n // The schema is applied by the migration runner, not by exec'ing SCHEMA_SQL here \u2014 see\n // migrations.ts for why a bare `CREATE TABLE IF NOT EXISTS` blob cannot ship an update to a\n // database that already exists on a user's machine.\n const backupsDir =\n file === ':memory:' ? undefined : (opts.backupsDir ?? path.join(path.dirname(file), 'backups'));\n const result = migrate(db, { backupsDir });\n // Creating the schema in an empty database is not news; upgrading one that already held a\n // user's data is the thing a support log needs to show.\n if (result.from > 0 && result.applied.length) {\n log.info(\n `schema ${result.from} -> ${result.to}: ${result.applied.map((a) => a.name).join(', ')}` +\n (result.backupPath ? ` (snapshot: ${result.backupPath})` : ''),\n );\n }\n return db;\n}\n", "// The schema evolves on the user's machine, not ours. Once ant-bot ships, a `CREATE TABLE IF NOT\n// EXISTS` blob is silently wrong: the statement succeeds against an old database and the new column\n// is simply absent, so the first query that reads it fails at runtime, far from the cause. This\n// module is the ordered ledger that makes a change actually reach an existing `~/.ant-bot/antbot.db`.\n//\n// Shape follows the rest of the codebase: `planMigrations` is the pure decision, `migrate` is the\n// I/O wrapper (see `detectBlockFromSignals` / `computeBackupItems` / `runDoctor(deps)`).\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { DB } from './db.js';\nimport { SCHEMA_SQL } from './schema.js';\n\nexport class MigrationError extends Error {\n constructor(\n public code: 'MIGRATION_ORDER' | 'MIGRATION_DOWNGRADE' | 'MIGRATION_FAILED',\n message: string,\n ) {\n super(message);\n this.name = 'MigrationError';\n }\n}\n\nexport interface Migration {\n /** Strictly increasing, starting at 1. Never renumber a released migration. */\n version: number;\n /** Short slug, recorded in the ledger so a support log says what ran. */\n name: string;\n /** Executed with `db.exec` inside a transaction. Must be idempotent-safe to re-read, not re-run. */\n up: string;\n}\n\n/**\n * Migration 1 is the schema as it stood when the runner was introduced. Every database in\n * existence at that point already has it, which is why `detectBaselineAdoption` exists \u2014 such a\n * database is adopted at this version rather than being mistaken for an empty one.\n */\nexport const BASELINE_VERSION = 1;\n\n/**\n * A table that only the baseline creates. Used to tell \"existing database, no ledger yet\" from\n * \"brand new file\"; `bots` has been in the schema since the first commit and is never dropped.\n */\nconst BASELINE_SENTINEL_TABLE = 'bots';\n\nexport const MIGRATIONS: Migration[] = [\n { version: BASELINE_VERSION, name: 'baseline', up: SCHEMA_SQL },\n {\n version: 2,\n name: 'connectors',\n // Plain CREATE TABLE, not IF NOT EXISTS: the ledger already guarantees this runs once, and\n // this module exists precisely because IF NOT EXISTS turns a real conflict into silence.\n up: `\nCREATE TABLE connectors (\n id TEXT PRIMARY KEY, name TEXT UNIQUE NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n config_json TEXT NOT NULL,\n enabled INTEGER NOT NULL DEFAULT 1,\n created_at INTEGER NOT NULL\n);\nCREATE TABLE bot_connectors (\n bot_id TEXT NOT NULL, connector_id TEXT NOT NULL,\n enabled INTEGER NOT NULL DEFAULT 1,\n PRIMARY KEY (bot_id, connector_id)\n);\n`,\n },\n {\n version: 3,\n name: 'connector-kind-and-health',\n // Built-in connectors (served by the daemon) alongside custom ones, and the last verdict a\n // check or a turn reached \u2014 so the screen shows a connector's real state instead of a toast\n // that has already vanished.\n up: `\nALTER TABLE connectors ADD COLUMN kind TEXT NOT NULL DEFAULT 'custom';\nALTER TABLE connectors ADD COLUMN last_status TEXT;\nALTER TABLE connectors ADD COLUMN last_error TEXT;\nALTER TABLE connectors ADD COLUMN checked_at INTEGER;\n`,\n },\n];\n\nexport const SCHEMA_VERSION_SQL = `\nCREATE TABLE IF NOT EXISTS schema_version (\n version INTEGER PRIMARY KEY, name TEXT NOT NULL, applied_at INTEGER NOT NULL\n);\n`;\n\n/* ------------------------------- pure core ------------------------------- */\n\n/**\n * A database created before the migration runner has the baseline schema but no ledger rows.\n * Recognising that is the difference between adopting it and re-running history over it.\n */\nexport function detectBaselineAdoption(hasLedgerRows: boolean, hasBaselineTable: boolean): boolean {\n return !hasLedgerRows && hasBaselineTable;\n}\n\n/**\n * Decides what to run. Throws rather than guessing: an out-of-order list is an authoring bug, and\n * a database numbered past the code is an older ant-bot opening a newer install's data \u2014 running\n * nothing there would let it write rows the newer schema forbids.\n */\nexport function planMigrations(currentVersion: number, migrations: Migration[]): Migration[] {\n const sorted = [...migrations].sort((a, b) => a.version - b.version);\n let prev = 0;\n for (const m of sorted) {\n if (!Number.isInteger(m.version) || m.version < 1) {\n throw new MigrationError('MIGRATION_ORDER', `migration \"${m.name}\" has invalid version ${m.version}`);\n }\n if (m.version === prev) {\n throw new MigrationError('MIGRATION_ORDER', `duplicate migration version ${m.version}`);\n }\n prev = m.version;\n }\n\n const latest = sorted.length ? sorted[sorted.length - 1]!.version : 0;\n if (currentVersion > latest) {\n throw new MigrationError(\n 'MIGRATION_DOWNGRADE',\n `database is at schema version ${currentVersion} but this build only knows up to ${latest}. ` +\n `Upgrade ant-bot (npm i -g @michael-joseph-miller/ant-bot) rather than downgrading the database.`,\n );\n }\n\n return sorted.filter((m) => m.version > currentVersion);\n}\n\n/* ------------------------------- I/O wrapper ------------------------------- */\n\nexport interface MigrateResult {\n from: number;\n to: number;\n applied: { version: number; name: string }[];\n /** Path of the pre-migration snapshot, when one was taken. */\n backupPath?: string;\n}\n\nexport interface MigrateOptions {\n /** Where a pre-migration snapshot is written. Omit to skip the snapshot (in-memory databases). */\n backupsDir?: string;\n migrations?: Migration[];\n now?: () => number;\n}\n\nfunction readCurrentVersion(db: DB): { version: number; adopted: boolean } {\n db.exec(SCHEMA_VERSION_SQL);\n const row = db.prepare(`SELECT MAX(version) v FROM schema_version`).get() as { v: number | null };\n if (row.v !== null) return { version: row.v, adopted: false };\n\n const sentinel = db\n .prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`)\n .get(BASELINE_SENTINEL_TABLE) as { name: string } | undefined;\n const adopted = detectBaselineAdoption(false, Boolean(sentinel));\n return { version: adopted ? BASELINE_VERSION : 0, adopted };\n}\n\n/**\n * Snapshots the database file before a migration touches it. `VACUUM INTO` is used rather than a\n * file copy because it checkpoints WAL content into the snapshot \u2014 copying `antbot.db` alone would\n * silently lose whatever is still sitting in `antbot.db-wal`.\n */\nfunction snapshot(db: DB, backupsDir: string, toVersion: number, now: () => number): string {\n fs.mkdirSync(backupsDir, { recursive: true });\n const stamp = new Date(now()).toISOString().replace(/[:.]/g, '-');\n const dest = path.join(backupsDir, `antbot-pre-v${toVersion}-${stamp}.db`);\n db.prepare(`VACUUM INTO ?`).run(dest);\n return dest;\n}\n\n/**\n * Brings `db` up to the latest schema version, snapshotting first if there is anything to lose.\n * Each migration commits on its own so a failure halfway through a list leaves the ledger honest\n * about how far it got.\n */\nexport function migrate(db: DB, opts: MigrateOptions = {}): MigrateResult {\n const migrations = opts.migrations ?? MIGRATIONS;\n const now = opts.now ?? Date.now;\n const { version: from, adopted } = readCurrentVersion(db);\n\n // OR IGNORE guards only the adoption row below; `planMigrations` already guarantees the loop\n // never re-inserts a version the ledger holds.\n const record = db.prepare(\n `INSERT OR IGNORE INTO schema_version (version, name, applied_at) VALUES (?, ?, ?)`,\n );\n // Write the adoption down the first time we see a pre-runner database. Without this the ledger\n // stays empty until some *later* migration runs, and then reads as though the baseline never\n // did \u2014 which is exactly the question a support log gets asked.\n if (adopted) {\n const baseline = migrations.find((m) => m.version === BASELINE_VERSION);\n record.run(BASELINE_VERSION, baseline?.name ?? 'baseline', now());\n }\n\n const pending = planMigrations(from, migrations);\n if (pending.length === 0) return { from, to: from, applied: [] };\n\n const target = pending[pending.length - 1]!.version;\n\n // A brand-new database (version 0) has nothing to lose, and snapshotting it would litter\n // `backups/` with an empty file on every first run.\n let backupPath: string | undefined;\n if (opts.backupsDir && from > 0) {\n backupPath = snapshot(db, opts.backupsDir, target, now);\n }\n\n const applied: { version: number; name: string }[] = [];\n for (const m of pending) {\n const run = db.transaction(() => {\n db.exec(m.up);\n record.run(m.version, m.name, now());\n });\n try {\n run();\n } catch (err) {\n throw new MigrationError(\n 'MIGRATION_FAILED',\n `migration ${m.version} (${m.name}) failed: ${(err as Error).message}` +\n (backupPath ? `. The pre-migration database was saved to ${backupPath}` : ''),\n );\n }\n applied.push({ version: m.version, name: m.name });\n }\n\n return { from, to: target, applied, backupPath };\n}\n", "export const SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS bots (\n id TEXT PRIMARY KEY, slug TEXT UNIQUE NOT NULL, name TEXT NOT NULL,\n title TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '',\n avatar_emoji TEXT NOT NULL DEFAULT '\uD83E\uDD16', model_tier TEXT NOT NULL DEFAULT 'sonnet',\n pinned INTEGER NOT NULL DEFAULT 0, hidden INTEGER NOT NULL DEFAULT 0,\n notifications INTEGER NOT NULL DEFAULT 1, session_id TEXT,\n state TEXT NOT NULL DEFAULT 'idle', attention TEXT NOT NULL DEFAULT 'none',\n thread_id TEXT, created_at INTEGER NOT NULL, deleted_at INTEGER\n);\nCREATE TABLE IF NOT EXISTS threads (\n id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK(kind IN ('dm','group')),\n title TEXT NOT NULL DEFAULT '', member_bot_ids TEXT NOT NULL DEFAULT '[]',\n pinned INTEGER NOT NULL DEFAULT 0, hidden INTEGER NOT NULL DEFAULT 0,\n last_read_at INTEGER NOT NULL DEFAULT 0, created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY, thread_id TEXT NOT NULL,\n author_kind TEXT NOT NULL CHECK(author_kind IN ('user','bot','system')),\n author_bot_id TEXT, reply_to_id TEXT, content_md TEXT NOT NULL DEFAULT '',\n cards TEXT NOT NULL DEFAULT '[]', streaming INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_messages_thread ON messages(thread_id, created_at);\nCREATE TABLE IF NOT EXISTS attachments (\n id TEXT PRIMARY KEY, message_id TEXT, path TEXT NOT NULL, name TEXT NOT NULL,\n mime TEXT NOT NULL, bytes INTEGER NOT NULL, created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS approvals (\n id TEXT PRIMARY KEY, bot_id TEXT NOT NULL, thread_id TEXT NOT NULL,\n tool_name TEXT NOT NULL, input_summary TEXT NOT NULL, raw_input TEXT NOT NULL DEFAULT 'null',\n status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','allowed','denied','expired')),\n decided_by TEXT CHECK(decided_by IN ('user','rule','auto_review')),\n reason TEXT NOT NULL DEFAULT '', rule_id TEXT,\n created_at INTEGER NOT NULL, decided_at INTEGER\n);\nCREATE INDEX IF NOT EXISTS idx_approvals_status ON approvals(status);\nCREATE TABLE IF NOT EXISTS rules (\n id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK(kind IN ('require','allow')),\n tool_pattern TEXT NOT NULL DEFAULT '*', input_pattern TEXT NOT NULL DEFAULT '',\n scope_note TEXT NOT NULL DEFAULT '', builtin INTEGER NOT NULL DEFAULT 0,\n enabled INTEGER NOT NULL DEFAULT 1, created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS skills (\n id TEXT PRIMARY KEY, slug TEXT UNIQUE NOT NULL, name TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '', path TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'user' CHECK(source IN ('user','taught','imported')),\n created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS bot_skills (\n bot_id TEXT NOT NULL, skill_id TEXT NOT NULL, enabled INTEGER NOT NULL DEFAULT 1,\n PRIMARY KEY (bot_id, skill_id)\n);\nCREATE TABLE IF NOT EXISTS routines (\n id TEXT PRIMARY KEY, bot_id TEXT NOT NULL, name TEXT NOT NULL,\n cron_expr TEXT NOT NULL, timezone TEXT NOT NULL DEFAULT 'UTC',\n instruction_md TEXT NOT NULL, enabled INTEGER NOT NULL DEFAULT 1,\n last_run_at INTEGER, next_run_at INTEGER, created_at INTEGER NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_routines_bot ON routines(bot_id);\nCREATE TABLE IF NOT EXISTS routine_runs (\n id TEXT PRIMARY KEY, routine_id TEXT NOT NULL, started_at INTEGER NOT NULL,\n finished_at INTEGER, status TEXT NOT NULL CHECK(status IN ('running','ok','failed','interrupted')),\n summary TEXT NOT NULL DEFAULT '', thread_id TEXT, is_test INTEGER NOT NULL DEFAULT 0\n);\nCREATE INDEX IF NOT EXISTS idx_runs_routine ON routine_runs(routine_id, started_at DESC);\nCREATE TABLE IF NOT EXISTS mailbox (\n id TEXT PRIMARY KEY, from_bot_id TEXT NOT NULL, to_bot_id TEXT NOT NULL,\n content_md TEXT NOT NULL, hops INTEGER NOT NULL DEFAULT 1,\n delivered INTEGER NOT NULL DEFAULT 0, created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS usage (\n id TEXT PRIMARY KEY, bot_id TEXT NOT NULL, turn_id TEXT NOT NULL, model TEXT NOT NULL,\n input_tokens INTEGER NOT NULL DEFAULT 0, output_tokens INTEGER NOT NULL DEFAULT 0,\n cache_read_tokens INTEGER NOT NULL DEFAULT 0, cost_estimate REAL NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_usage_created ON usage(created_at);\nCREATE TABLE IF NOT EXISTS settings (key TEXT PRIMARY KEY, value TEXT NOT NULL);\nCREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(\n content_md, content='messages', content_rowid='rowid'\n);\nCREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN\n INSERT INTO messages_fts(rowid, content_md) VALUES (new.rowid, new.content_md);\nEND;\nCREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN\n INSERT INTO messages_fts(messages_fts, rowid, content_md) VALUES('delete', old.rowid, old.content_md);\nEND;\nCREATE TRIGGER IF NOT EXISTS messages_au AFTER UPDATE ON messages BEGIN\n INSERT INTO messages_fts(messages_fts, rowid, content_md) VALUES('delete', old.rowid, old.content_md);\n INSERT INTO messages_fts(rowid, content_md) VALUES (new.rowid, new.content_md);\nEND;\n`;\n", "import type { DB } from './db.js';\nimport { newId, now, slugify } from '../util/ids.js';\nimport {\n LIMITS, LIMIT_ERROR, LimitError,\n type Bot, type Thread, type Message, type Attachment, type Approval, type Rule,\n type Skill, type Routine, type RoutineRun, type MailboxEntry, type UsageRow,\n type Card, type BotState, type Attention, type ModelTier, type Settings,\n type Connector, type ConnectorConfig,\n SettingsSchema, ConnectorConfigSchema,\n} from '@antbot/contract';\n\n/* ------------------------------ row mappers ------------------------------ */\nconst b = (v: unknown): boolean => v === 1 || v === true;\nconst i = (v: boolean | undefined, d = false): number => ((v ?? d) ? 1 : 0);\n\ntype Row = Record<string, any>;\n\nconst toBot = (r: Row): Bot => ({\n id: r.id, slug: r.slug, name: r.name, title: r.title, description: r.description,\n avatarEmoji: r.avatar_emoji, modelTier: r.model_tier as ModelTier,\n pinned: b(r.pinned), hidden: b(r.hidden), notifications: b(r.notifications),\n sessionId: r.session_id, state: r.state as BotState, attention: r.attention as Attention,\n threadId: r.thread_id, createdAt: r.created_at, deletedAt: r.deleted_at,\n});\nconst toThread = (r: Row): Thread => ({\n id: r.id, kind: r.kind, title: r.title, memberBotIds: JSON.parse(r.member_bot_ids),\n pinned: b(r.pinned), hidden: b(r.hidden), lastReadAt: r.last_read_at, createdAt: r.created_at,\n});\nconst toMessage = (r: Row): Message => ({\n id: r.id, threadId: r.thread_id, authorKind: r.author_kind, authorBotId: r.author_bot_id,\n replyToId: r.reply_to_id, contentMd: r.content_md, cards: JSON.parse(r.cards),\n streaming: b(r.streaming), createdAt: r.created_at,\n});\nconst toApproval = (r: Row): Approval => ({\n id: r.id, botId: r.bot_id, threadId: r.thread_id, toolName: r.tool_name,\n inputSummary: r.input_summary, rawInput: JSON.parse(r.raw_input), status: r.status,\n decidedBy: r.decided_by, reason: r.reason, ruleId: r.rule_id,\n createdAt: r.created_at, decidedAt: r.decided_at,\n});\nconst toRule = (r: Row): Rule => ({\n id: r.id, kind: r.kind, toolPattern: r.tool_pattern, inputPattern: r.input_pattern,\n scopeNote: r.scope_note, builtin: b(r.builtin), enabled: b(r.enabled), createdAt: r.created_at,\n});\nconst toSkill = (r: Row): Skill => ({\n id: r.id, slug: r.slug, name: r.name, description: r.description, path: r.path,\n source: r.source, createdAt: r.created_at,\n});\n/**\n * Config is stored as JSON and parsed back through the schema rather than cast: a row written by\n * an older build (or edited by hand) that no longer matches the union should fail here, loudly,\n * not surface as a malformed server config at turn time.\n */\nconst toConnector = (r: Row): Connector => ({\n id: r.id, name: r.name, description: r.description,\n kind: r.kind === 'builtin' ? 'builtin' : 'custom',\n config: ConnectorConfigSchema.parse(JSON.parse(r.config_json)),\n enabled: b(r.enabled),\n lastStatus: r.last_status ?? null, lastError: r.last_error ?? null, checkedAt: r.checked_at ?? null,\n createdAt: r.created_at,\n});\nconst toRoutine = (r: Row): Routine => ({\n id: r.id, botId: r.bot_id, name: r.name, cronExpr: r.cron_expr, timezone: r.timezone,\n instructionMd: r.instruction_md, enabled: b(r.enabled), lastRunAt: r.last_run_at,\n nextRunAt: r.next_run_at, createdAt: r.created_at,\n});\nconst toRun = (r: Row): RoutineRun => ({\n id: r.id, routineId: r.routine_id, startedAt: r.started_at, finishedAt: r.finished_at,\n status: r.status, summary: r.summary, threadId: r.thread_id, isTest: b(r.is_test),\n});\nconst toAttachment = (r: Row): Attachment => ({\n id: r.id, messageId: r.message_id, path: r.path, name: r.name, mime: r.mime,\n bytes: r.bytes, createdAt: r.created_at,\n});\nconst toMail = (r: Row): MailboxEntry => ({\n id: r.id, fromBotId: r.from_bot_id, toBotId: r.to_bot_id, contentMd: r.content_md,\n hops: r.hops, delivered: b(r.delivered), createdAt: r.created_at,\n});\nconst toUsage = (r: Row): UsageRow => ({\n id: r.id, botId: r.bot_id, turnId: r.turn_id, model: r.model, inputTokens: r.input_tokens,\n outputTokens: r.output_tokens, cacheReadTokens: r.cache_read_tokens,\n costEstimate: r.cost_estimate, createdAt: r.created_at,\n});\n\n/* -------------------------------- store --------------------------------- */\nexport class Store {\n constructor(public db: DB) {}\n\n /* ---- bots ---- */\n countBotsAndGroups(): number {\n const bots = this.db.prepare(`SELECT COUNT(*) c FROM bots WHERE deleted_at IS NULL`).get() as Row;\n const groups = this.db.prepare(`SELECT COUNT(*) c FROM threads WHERE kind='group'`).get() as Row;\n return bots.c + groups.c;\n }\n\n createBot(input: { name: string; title?: string; description?: string; avatarEmoji?: string; modelTier?: ModelTier }): Bot {\n if (this.countBotsAndGroups() >= LIMITS.MAX_BOTS_AND_GROUPS)\n throw new LimitError(LIMIT_ERROR.TOO_MANY_BOTS, `Limit of ${LIMITS.MAX_BOTS_AND_GROUPS} bots and groups reached`);\n const existing = new Set(\n (this.db.prepare(`SELECT slug FROM bots`).all() as Row[]).map((r) => r.slug as string),\n );\n const id = newId();\n const thread = this.createThread({ kind: 'dm', title: input.name, memberBotIds: [id] });\n this.db\n .prepare(\n `INSERT INTO bots (id,slug,name,title,description,avatar_emoji,model_tier,pinned,hidden,notifications,session_id,state,attention,thread_id,created_at)\n VALUES (@id,@slug,@name,@title,@description,@avatar_emoji,@model_tier,0,0,1,NULL,'idle','none',@thread_id,@created_at)`,\n )\n .run({\n id, slug: slugify(input.name, existing), name: input.name, title: input.title ?? '',\n description: input.description ?? '', avatar_emoji: input.avatarEmoji ?? '\uD83E\uDD16',\n model_tier: input.modelTier ?? 'sonnet', thread_id: thread.id, created_at: now(),\n });\n return this.getBot(id)!;\n }\n\n getBot(id: string): Bot | null {\n const r = this.db.prepare(`SELECT * FROM bots WHERE id=? AND deleted_at IS NULL`).get(id) as Row | undefined;\n return r ? toBot(r) : null;\n }\n getBotBySlug(slug: string): Bot | null {\n const r = this.db.prepare(`SELECT * FROM bots WHERE slug=? AND deleted_at IS NULL`).get(slug) as Row | undefined;\n return r ? toBot(r) : null;\n }\n listBots(includeHidden = true): Bot[] {\n const rows = this.db\n .prepare(`SELECT * FROM bots WHERE deleted_at IS NULL ${includeHidden ? '' : 'AND hidden=0'} ORDER BY pinned DESC, created_at ASC`)\n .all() as Row[];\n return rows.map(toBot);\n }\n updateBot(id: string, patch: Partial<Bot>): Bot | null {\n const cur = this.getBot(id);\n if (!cur) return null;\n const m: Record<string, unknown> = {\n name: patch.name ?? cur.name, title: patch.title ?? cur.title,\n description: patch.description ?? cur.description, avatar_emoji: patch.avatarEmoji ?? cur.avatarEmoji,\n model_tier: patch.modelTier ?? cur.modelTier,\n pinned: i(patch.pinned, cur.pinned), hidden: i(patch.hidden, cur.hidden),\n notifications: i(patch.notifications, cur.notifications),\n session_id: patch.sessionId !== undefined ? patch.sessionId : cur.sessionId,\n state: patch.state ?? cur.state, attention: patch.attention ?? cur.attention, id,\n };\n this.db.prepare(\n `UPDATE bots SET name=@name,title=@title,description=@description,avatar_emoji=@avatar_emoji,\n model_tier=@model_tier,pinned=@pinned,hidden=@hidden,notifications=@notifications,\n session_id=@session_id,state=@state,attention=@attention WHERE id=@id`,\n ).run(m);\n return this.getBot(id);\n }\n deleteBot(id: string): void {\n const bot = this.getBot(id);\n if (!bot) return;\n this.db.prepare(`UPDATE bots SET deleted_at=? WHERE id=?`).run(now(), id);\n this.db.prepare(`DELETE FROM routines WHERE bot_id=?`).run(id);\n if (bot.threadId) this.db.prepare(`DELETE FROM threads WHERE id=?`).run(bot.threadId);\n }\n /**\n * Clear a bot's conversation and its SDK session, keeping everything that defines the bot.\n *\n * Deliberately narrow. Memory, skills, connectors, routines and the bot's files all survive \u2014\n * those are the bot. What goes is the accumulated conversation: the messages in its thread and\n * the `session_id` the SDK resumes from, which is what makes a turn carry prior context.\n *\n * Messages are deleted rather than the thread, so the thread id every other row points at\n * stays valid; the FTS triggers keep the search index in step.\n */\n resetBotSession(id: string): { messagesDeleted: number } | null {\n const bot = this.getBot(id);\n if (!bot) return null;\n let messagesDeleted = 0;\n if (bot.threadId) {\n const info = this.db.prepare(`DELETE FROM messages WHERE thread_id=?`).run(bot.threadId);\n messagesDeleted = info.changes;\n this.db.prepare(`UPDATE threads SET last_read_at=0 WHERE id=?`).run(bot.threadId);\n }\n // Null, not a new id: the next turn starts a session instead of resuming a dead one.\n this.db.prepare(`UPDATE bots SET session_id=NULL, attention='none' WHERE id=?`).run(id);\n return { messagesDeleted };\n }\n\n duplicateBot(id: string): Bot | null {\n const src = this.getBot(id);\n if (!src) return null;\n const copy = this.createBot({\n name: `${src.name} copy`, title: src.title, description: src.description,\n avatarEmoji: src.avatarEmoji, modelTier: src.modelTier,\n });\n // carries skills + connectors + routines; NOT history or memory (outline \u00A74)\n for (const bs of this.db.prepare(`SELECT * FROM bot_skills WHERE bot_id=?`).all(id) as Row[])\n this.db.prepare(`INSERT OR REPLACE INTO bot_skills (bot_id,skill_id,enabled) VALUES (?,?,?)`).run(copy.id, bs.skill_id, bs.enabled);\n for (const bc of this.db.prepare(`SELECT * FROM bot_connectors WHERE bot_id=?`).all(id) as Row[])\n this.db.prepare(`INSERT OR REPLACE INTO bot_connectors (bot_id,connector_id,enabled) VALUES (?,?,?)`).run(copy.id, bc.connector_id, bc.enabled);\n for (const r of this.listRoutines(id))\n this.createRoutine({ botId: copy.id, name: r.name, cronExpr: r.cronExpr, timezone: r.timezone, instructionMd: r.instructionMd, enabled: false });\n return copy;\n }\n\n /* ---- threads & messages ---- */\n createThread(input: { kind: 'dm' | 'group'; title?: string; memberBotIds: string[] }): Thread {\n if (input.kind === 'group') {\n const n = input.memberBotIds.length;\n if (n < LIMITS.MIN_GROUP_MEMBERS || n > LIMITS.MAX_GROUP_MEMBERS)\n throw new LimitError(LIMIT_ERROR.GROUP_SIZE, `A group needs ${LIMITS.MIN_GROUP_MEMBERS}\u2013${LIMITS.MAX_GROUP_MEMBERS} bots (got ${n})`);\n if (this.countBotsAndGroups() >= LIMITS.MAX_BOTS_AND_GROUPS)\n throw new LimitError(LIMIT_ERROR.TOO_MANY_BOTS, `Limit of ${LIMITS.MAX_BOTS_AND_GROUPS} bots and groups reached`);\n }\n const id = newId();\n this.db.prepare(\n `INSERT INTO threads (id,kind,title,member_bot_ids,pinned,hidden,last_read_at,created_at)\n VALUES (?,?,?,?,0,0,0,?)`,\n ).run(id, input.kind, input.title ?? '', JSON.stringify(input.memberBotIds), now());\n return this.getThread(id)!;\n }\n getThread(id: string): Thread | null {\n const r = this.db.prepare(`SELECT * FROM threads WHERE id=?`).get(id) as Row | undefined;\n return r ? toThread(r) : null;\n }\n listThreads(kind?: 'dm' | 'group'): Thread[] {\n const rows = (kind\n ? this.db.prepare(`SELECT * FROM threads WHERE kind=? ORDER BY created_at ASC`).all(kind)\n : this.db.prepare(`SELECT * FROM threads ORDER BY created_at ASC`).all()) as Row[];\n return rows.map(toThread);\n }\n updateThread(id: string, patch: Partial<Thread>): Thread | null {\n const cur = this.getThread(id);\n if (!cur) return null;\n this.db.prepare(\n `UPDATE threads SET title=?, member_bot_ids=?, pinned=?, hidden=?, last_read_at=? WHERE id=?`,\n ).run(\n patch.title ?? cur.title, JSON.stringify(patch.memberBotIds ?? cur.memberBotIds),\n i(patch.pinned, cur.pinned), i(patch.hidden, cur.hidden), patch.lastReadAt ?? cur.lastReadAt, id,\n );\n return this.getThread(id);\n }\n deleteThread(id: string): void {\n this.db.prepare(`DELETE FROM threads WHERE id=?`).run(id);\n this.db.prepare(`DELETE FROM messages WHERE thread_id=?`).run(id);\n }\n\n createMessage(input: {\n threadId: string; authorKind: 'user' | 'bot' | 'system'; authorBotId?: string | null;\n contentMd?: string; cards?: Card[]; streaming?: boolean; replyToId?: string | null;\n }): Message {\n const id = newId();\n this.db.prepare(\n `INSERT INTO messages (id,thread_id,author_kind,author_bot_id,reply_to_id,content_md,cards,streaming,created_at)\n VALUES (?,?,?,?,?,?,?,?,?)`,\n ).run(\n id, input.threadId, input.authorKind, input.authorBotId ?? null, input.replyToId ?? null,\n input.contentMd ?? '', JSON.stringify(input.cards ?? []), i(input.streaming), now(),\n );\n return this.getMessage(id)!;\n }\n getMessage(id: string): Message | null {\n const r = this.db.prepare(`SELECT * FROM messages WHERE id=?`).get(id) as Row | undefined;\n return r ? toMessage(r) : null;\n }\n listMessages(threadId: string, limit = 500): Message[] {\n const rows = this.db\n .prepare(`SELECT * FROM messages WHERE thread_id=? ORDER BY created_at ASC LIMIT ?`)\n .all(threadId, limit) as Row[];\n return rows.map(toMessage);\n }\n updateMessage(id: string, patch: { contentMd?: string; cards?: Card[]; streaming?: boolean }): Message | null {\n const cur = this.getMessage(id);\n if (!cur) return null;\n this.db.prepare(`UPDATE messages SET content_md=?, cards=?, streaming=? WHERE id=?`).run(\n patch.contentMd ?? cur.contentMd, JSON.stringify(patch.cards ?? cur.cards), i(patch.streaming, cur.streaming), id,\n );\n return this.getMessage(id);\n }\n appendCard(id: string, card: Card): number {\n const cur = this.getMessage(id);\n if (!cur) return -1;\n const cards = [...cur.cards, card];\n this.db.prepare(`UPDATE messages SET cards=? WHERE id=?`).run(JSON.stringify(cards), id);\n return cards.length - 1;\n }\n updateCard(id: string, index: number, card: Card): void {\n const cur = this.getMessage(id);\n if (!cur || !cur.cards[index]) return;\n const cards = [...cur.cards];\n cards[index] = card;\n this.db.prepare(`UPDATE messages SET cards=? WHERE id=?`).run(JSON.stringify(cards), id);\n }\n lastMessageAt(threadId: string): number {\n const r = this.db.prepare(`SELECT MAX(created_at) m FROM messages WHERE thread_id=?`).get(threadId) as Row;\n return r?.m ?? 0;\n }\n\n /* ---- attachments ---- */\n createAttachment(a: Omit<Attachment, 'id' | 'createdAt'>): Attachment {\n const isVideo = a.mime.startsWith('video/');\n const cap = isVideo ? LIMITS.MAX_VIDEO_ATTACHMENT_BYTES : LIMITS.MAX_ATTACHMENT_BYTES;\n if (a.bytes > cap)\n throw new LimitError(LIMIT_ERROR.ATTACHMENT_TOO_LARGE, `${a.name} is ${(a.bytes / 1048576).toFixed(1)} MB; limit is ${cap / 1048576} MB`);\n const id = newId();\n this.db.prepare(\n `INSERT INTO attachments (id,message_id,path,name,mime,bytes,created_at) VALUES (?,?,?,?,?,?,?)`,\n ).run(id, a.messageId ?? null, a.path, a.name, a.mime, a.bytes, now());\n return toAttachment(this.db.prepare(`SELECT * FROM attachments WHERE id=?`).get(id) as Row);\n }\n getAttachment(id: string): Attachment | null {\n const r = this.db.prepare(`SELECT * FROM attachments WHERE id=?`).get(id) as Row | undefined;\n return r ? toAttachment(r) : null;\n }\n attachToMessage(ids: string[], messageId: string): void {\n if (ids.length > LIMITS.MAX_ATTACHMENTS_PER_MESSAGE)\n throw new LimitError(LIMIT_ERROR.TOO_MANY_ATTACHMENTS, `At most ${LIMITS.MAX_ATTACHMENTS_PER_MESSAGE} attachments per message`);\n const stmt = this.db.prepare(`UPDATE attachments SET message_id=? WHERE id=?`);\n for (const id of ids) stmt.run(messageId, id);\n }\n listAttachmentsForMessage(messageId: string): Attachment[] {\n return (this.db.prepare(`SELECT * FROM attachments WHERE message_id=?`).all(messageId) as Row[]).map(toAttachment);\n }\n\n /* ---- approvals ---- */\n createApproval(a: { botId: string; threadId: string; toolName: string; inputSummary: string; rawInput: unknown; reason?: string }): Approval {\n const id = newId();\n this.db.prepare(\n `INSERT INTO approvals (id,bot_id,thread_id,tool_name,input_summary,raw_input,status,reason,created_at)\n VALUES (?,?,?,?,?,?, 'pending', ?, ?)`,\n ).run(id, a.botId, a.threadId, a.toolName, a.inputSummary, JSON.stringify(a.rawInput ?? null), a.reason ?? '', now());\n return this.getApproval(id)!;\n }\n getApproval(id: string): Approval | null {\n const r = this.db.prepare(`SELECT * FROM approvals WHERE id=?`).get(id) as Row | undefined;\n return r ? toApproval(r) : null;\n }\n listPendingApprovals(): Approval[] {\n return (this.db.prepare(`SELECT * FROM approvals WHERE status='pending' ORDER BY created_at ASC`).all() as Row[]).map(toApproval);\n }\n resolveApproval(id: string, status: 'allowed' | 'denied' | 'expired', decidedBy: 'user' | 'rule' | 'auto_review', ruleId?: string | null, reason?: string): Approval | null {\n const cur = this.getApproval(id);\n if (!cur) return null;\n this.db.prepare(`UPDATE approvals SET status=?, decided_by=?, rule_id=?, reason=?, decided_at=? WHERE id=?`)\n .run(status, decidedBy, ruleId ?? cur.ruleId, reason ?? cur.reason, now(), id);\n return this.getApproval(id);\n }\n\n /* ---- rules ---- */\n createRule(r: { kind: 'require' | 'allow'; toolPattern: string; inputPattern?: string; scopeNote?: string; builtin?: boolean }): Rule {\n const id = newId();\n this.db.prepare(\n `INSERT INTO rules (id,kind,tool_pattern,input_pattern,scope_note,builtin,enabled,created_at) VALUES (?,?,?,?,?,?,1,?)`,\n ).run(id, r.kind, r.toolPattern, r.inputPattern ?? '', r.scopeNote ?? '', i(r.builtin), now());\n return this.getRule(id)!;\n }\n getRule(id: string): Rule | null {\n const r = this.db.prepare(`SELECT * FROM rules WHERE id=?`).get(id) as Row | undefined;\n return r ? toRule(r) : null;\n }\n listRules(onlyEnabled = false): Rule[] {\n return (this.db.prepare(`SELECT * FROM rules ${onlyEnabled ? 'WHERE enabled=1' : ''} ORDER BY kind ASC, created_at ASC`).all() as Row[]).map(toRule);\n }\n setRuleEnabled(id: string, enabled: boolean): void {\n this.db.prepare(`UPDATE rules SET enabled=? WHERE id=?`).run(i(enabled), id);\n }\n deleteRule(id: string): void {\n this.db.prepare(`DELETE FROM rules WHERE id=? AND builtin=0`).run(id);\n }\n\n /* ---- skills ---- */\n createSkill(s: { slug: string; name: string; description?: string; path: string; source?: 'user' | 'taught' | 'imported' }): Skill {\n const id = newId();\n this.db.prepare(\n `INSERT OR REPLACE INTO skills (id,slug,name,description,path,source,created_at) VALUES (?,?,?,?,?,?,?)`,\n ).run(id, s.slug, s.name, s.description ?? '', s.path, s.source ?? 'user', now());\n return this.getSkillBySlug(s.slug)!;\n }\n getSkill(id: string): Skill | null {\n const r = this.db.prepare(`SELECT * FROM skills WHERE id=?`).get(id) as Row | undefined;\n return r ? toSkill(r) : null;\n }\n getSkillBySlug(slug: string): Skill | null {\n const r = this.db.prepare(`SELECT * FROM skills WHERE slug=?`).get(slug) as Row | undefined;\n return r ? toSkill(r) : null;\n }\n listSkills(): Skill[] {\n return (this.db.prepare(`SELECT * FROM skills ORDER BY name ASC`).all() as Row[]).map(toSkill);\n }\n /**\n * Update a skill's metadata in place, keeping its id so bot assignments survive a\n * re-install. Returns null if the skill is gone.\n */\n updateSkill(id: string, patch: { name?: string; description?: string; path?: string }): Skill | null {\n const existing = this.getSkill(id);\n if (!existing) return null;\n this.db.prepare(`UPDATE skills SET name=?, description=?, path=? WHERE id=?`).run(\n patch.name ?? existing.name,\n patch.description ?? existing.description,\n patch.path ?? existing.path,\n id,\n );\n return this.getSkill(id);\n }\n deleteSkill(id: string): void {\n this.db.prepare(`DELETE FROM skills WHERE id=?`).run(id);\n this.db.prepare(`DELETE FROM bot_skills WHERE skill_id=?`).run(id);\n }\n setBotSkills(botId: string, skillIds: string[]): void {\n this.db.prepare(`DELETE FROM bot_skills WHERE bot_id=?`).run(botId);\n const stmt = this.db.prepare(`INSERT OR REPLACE INTO bot_skills (bot_id,skill_id,enabled) VALUES (?,?,1)`);\n for (const s of skillIds) stmt.run(botId, s);\n }\n listBotSkills(botId: string): Skill[] {\n return (this.db.prepare(\n `SELECT s.* FROM skills s JOIN bot_skills bs ON bs.skill_id=s.id WHERE bs.bot_id=? AND bs.enabled=1`,\n ).all(botId) as Row[]).map(toSkill);\n }\n\n /* ---- connectors ---- */\n createConnector(c: { name: string; description?: string; config: ConnectorConfig; enabled?: boolean; kind?: 'custom' | 'builtin' }): Connector {\n const id = newId();\n this.db.prepare(\n `INSERT INTO connectors (id,name,description,config_json,enabled,kind,created_at) VALUES (?,?,?,?,?,?,?)`,\n ).run(id, c.name, c.description ?? '', JSON.stringify(c.config), i(c.enabled, true), c.kind ?? 'custom', now());\n return this.getConnector(id)!;\n }\n /** Record the latest verdict. Written by both `check` and the turn's own mount report. */\n setConnectorStatus(id: string, status: string, error: string | null = null): void {\n this.db.prepare(`UPDATE connectors SET last_status=?, last_error=?, checked_at=? WHERE id=?`).run(status, error, now(), id);\n }\n setConnectorStatusByName(name: string, status: string, error: string | null = null): void {\n this.db.prepare(`UPDATE connectors SET last_status=?, last_error=?, checked_at=? WHERE name=?`).run(status, error, now(), name);\n }\n getConnector(id: string): Connector | null {\n const r = this.db.prepare(`SELECT * FROM connectors WHERE id=?`).get(id) as Row | undefined;\n return r ? toConnector(r) : null;\n }\n getConnectorByName(name: string): Connector | null {\n const r = this.db.prepare(`SELECT * FROM connectors WHERE name=?`).get(name) as Row | undefined;\n return r ? toConnector(r) : null;\n }\n listConnectors(): Connector[] {\n return (this.db.prepare(`SELECT * FROM connectors ORDER BY name ASC`).all() as Row[]).map(toConnector);\n }\n /** Patch in place. No rename: the name is baked into every `mcp__<name>__<tool>` a rule may match. */\n updateConnector(id: string, patch: { description?: string; config?: ConnectorConfig; enabled?: boolean }): Connector | null {\n const existing = this.getConnector(id);\n if (!existing) return null;\n this.db.prepare(`UPDATE connectors SET description=?, config_json=?, enabled=? WHERE id=?`).run(\n patch.description ?? existing.description,\n JSON.stringify(patch.config ?? existing.config),\n i(patch.enabled ?? existing.enabled),\n id,\n );\n return this.getConnector(id);\n }\n deleteConnector(id: string): void {\n this.db.prepare(`DELETE FROM connectors WHERE id=?`).run(id);\n this.db.prepare(`DELETE FROM bot_connectors WHERE connector_id=?`).run(id);\n }\n setBotConnectors(botId: string, connectorIds: string[]): void {\n this.db.prepare(`DELETE FROM bot_connectors WHERE bot_id=?`).run(botId);\n const stmt = this.db.prepare(`INSERT OR REPLACE INTO bot_connectors (bot_id,connector_id,enabled) VALUES (?,?,1)`);\n for (const c of connectorIds) stmt.run(botId, c);\n }\n /** Assigned AND account-wide enabled \u2014 disabling a connector takes it away from every bot at once. */\n listBotConnectors(botId: string): Connector[] {\n return (this.db.prepare(\n `SELECT c.* FROM connectors c JOIN bot_connectors bc ON bc.connector_id=c.id\n WHERE bc.bot_id=? AND bc.enabled=1 AND c.enabled=1 ORDER BY c.name ASC`,\n ).all(botId) as Row[]).map(toConnector);\n }\n\n /* ---- routines ---- */\n createRoutine(r: { botId: string; name: string; cronExpr: string; timezone?: string; instructionMd: string; enabled?: boolean }): Routine {\n const count = (this.db.prepare(`SELECT COUNT(*) c FROM routines WHERE bot_id=?`).get(r.botId) as Row).c;\n if (count >= LIMITS.MAX_ROUTINES_PER_BOT)\n throw new LimitError(LIMIT_ERROR.TOO_MANY_ROUTINES, `A bot can own at most ${LIMITS.MAX_ROUTINES_PER_BOT} routines`);\n const id = newId();\n this.db.prepare(\n `INSERT INTO routines (id,bot_id,name,cron_expr,timezone,instruction_md,enabled,created_at) VALUES (?,?,?,?,?,?,?,?)`,\n ).run(id, r.botId, r.name, r.cronExpr, r.timezone ?? 'UTC', r.instructionMd, i(r.enabled, true), now());\n return this.getRoutine(id)!;\n }\n getRoutine(id: string): Routine | null {\n const r = this.db.prepare(`SELECT * FROM routines WHERE id=?`).get(id) as Row | undefined;\n return r ? toRoutine(r) : null;\n }\n listRoutines(botId?: string): Routine[] {\n const rows = (botId\n ? this.db.prepare(`SELECT * FROM routines WHERE bot_id=? ORDER BY created_at ASC`).all(botId)\n : this.db.prepare(`SELECT * FROM routines ORDER BY created_at ASC`).all()) as Row[];\n return rows.map(toRoutine);\n }\n updateRoutine(id: string, patch: Partial<Routine>): Routine | null {\n const cur = this.getRoutine(id);\n if (!cur) return null;\n this.db.prepare(\n `UPDATE routines SET name=?,cron_expr=?,timezone=?,instruction_md=?,enabled=?,last_run_at=?,next_run_at=? WHERE id=?`,\n ).run(\n patch.name ?? cur.name, patch.cronExpr ?? cur.cronExpr, patch.timezone ?? cur.timezone,\n patch.instructionMd ?? cur.instructionMd, i(patch.enabled, cur.enabled),\n patch.lastRunAt !== undefined ? patch.lastRunAt : cur.lastRunAt,\n patch.nextRunAt !== undefined ? patch.nextRunAt : cur.nextRunAt, id,\n );\n return this.getRoutine(id);\n }\n deleteRoutine(id: string): void {\n this.db.prepare(`DELETE FROM routines WHERE id=?`).run(id);\n this.db.prepare(`DELETE FROM routine_runs WHERE routine_id=?`).run(id);\n }\n\n startRun(routineId: string, isTest = false, threadId?: string): RoutineRun {\n const id = newId();\n this.db.prepare(\n `INSERT INTO routine_runs (id,routine_id,started_at,status,summary,thread_id,is_test) VALUES (?,?,?,'running','',?,?)`,\n ).run(id, routineId, now(), threadId ?? null, i(isTest));\n return this.getRun(id)!;\n }\n finishRun(id: string, status: 'ok' | 'failed' | 'interrupted', summary: string): RoutineRun | null {\n this.db.prepare(`UPDATE routine_runs SET finished_at=?, status=?, summary=? WHERE id=?`).run(now(), status, summary, id);\n const run = this.getRun(id);\n if (run) this.pruneRuns(run.routineId);\n return run;\n }\n getRun(id: string): RoutineRun | null {\n const r = this.db.prepare(`SELECT * FROM routine_runs WHERE id=?`).get(id) as Row | undefined;\n return r ? toRun(r) : null;\n }\n listRuns(routineId: string): RoutineRun[] {\n return (this.db.prepare(\n `SELECT * FROM routine_runs WHERE routine_id=? ORDER BY started_at DESC LIMIT ?`,\n ).all(routineId, LIMITS.ROUTINE_RUNS_RETAINED) as Row[]).map(toRun);\n }\n /** Keep only the N most recent run records (outline \u00A713). */\n pruneRuns(routineId: string): void {\n this.db.prepare(\n `DELETE FROM routine_runs WHERE routine_id=? AND id NOT IN\n (SELECT id FROM routine_runs WHERE routine_id=? ORDER BY started_at DESC LIMIT ?)`,\n ).run(routineId, routineId, LIMITS.ROUTINE_RUNS_RETAINED);\n }\n\n /* ---- mailbox ---- */\n createMail(m: { fromBotId: string; toBotId: string; contentMd: string; hops?: number }): MailboxEntry {\n const hops = m.hops ?? 1;\n if (hops > LIMITS.MAX_BOT_TO_BOT_HOPS)\n throw new LimitError(LIMIT_ERROR.HOP_LIMIT, `Bot-to-bot hop limit (${LIMITS.MAX_BOT_TO_BOT_HOPS}) reached; a human must take the next step`);\n const id = newId();\n this.db.prepare(\n `INSERT INTO mailbox (id,from_bot_id,to_bot_id,content_md,hops,delivered,created_at) VALUES (?,?,?,?,?,0,?)`,\n ).run(id, m.fromBotId, m.toBotId, m.contentMd, hops, now());\n return toMail(this.db.prepare(`SELECT * FROM mailbox WHERE id=?`).get(id) as Row);\n }\n markDelivered(id: string): void {\n this.db.prepare(`UPDATE mailbox SET delivered=1 WHERE id=?`).run(id);\n }\n listMail(toBotId: string, onlyUndelivered = true): MailboxEntry[] {\n return (this.db.prepare(\n `SELECT * FROM mailbox WHERE to_bot_id=? ${onlyUndelivered ? 'AND delivered=0' : ''} ORDER BY created_at ASC`,\n ).all(toBotId) as Row[]).map(toMail);\n }\n\n /* ---- usage ---- */\n recordUsage(u: Omit<UsageRow, 'id' | 'createdAt'>): UsageRow {\n const id = newId();\n this.db.prepare(\n `INSERT INTO usage (id,bot_id,turn_id,model,input_tokens,output_tokens,cache_read_tokens,cost_estimate,created_at)\n VALUES (?,?,?,?,?,?,?,?,?)`,\n ).run(id, u.botId, u.turnId, u.model, u.inputTokens, u.outputTokens, u.cacheReadTokens, u.costEstimate, now());\n return toUsage(this.db.prepare(`SELECT * FROM usage WHERE id=?`).get(id) as Row);\n }\n listUsage(sinceMs = 0): UsageRow[] {\n return (this.db.prepare(`SELECT * FROM usage WHERE created_at>=? ORDER BY created_at DESC`).all(sinceMs) as Row[]).map(toUsage);\n }\n tokensToday(): number {\n const start = new Date(); start.setHours(0, 0, 0, 0);\n const r = this.db.prepare(\n `SELECT COALESCE(SUM(input_tokens+output_tokens),0) t FROM usage WHERE created_at>=?`,\n ).get(start.getTime()) as Row;\n return r.t;\n }\n\n /* ---- settings ---- */\n getSettings(): Settings {\n const rows = this.db.prepare(`SELECT * FROM settings`).all() as Row[];\n const obj: Record<string, unknown> = {};\n for (const r of rows) obj[r.key] = JSON.parse(r.value);\n return SettingsSchema.parse(obj);\n }\n patchSettings(patch: Partial<Settings>): Settings {\n const stmt = this.db.prepare(`INSERT OR REPLACE INTO settings (key,value) VALUES (?,?)`);\n for (const [k, v] of Object.entries(patch)) if (v !== undefined) stmt.run(k, JSON.stringify(v));\n return this.getSettings();\n }\n\n /* ---- search ---- */\n searchMessages(q: string, limit = 40): Message[] {\n if (!q.trim()) return [];\n const escaped = `\"${q.replace(/\"/g, '\"\"')}\"`;\n try {\n const rows = this.db.prepare(\n `SELECT m.* FROM messages_fts f JOIN messages m ON m.rowid=f.rowid\n WHERE messages_fts MATCH ? ORDER BY rank LIMIT ?`,\n ).all(escaped, limit) as Row[];\n return rows.map(toMessage);\n } catch {\n const rows = this.db.prepare(\n `SELECT * FROM messages WHERE content_md LIKE ? ORDER BY created_at DESC LIMIT ?`,\n ).all(`%${q}%`, limit) as Row[];\n return rows.map(toMessage);\n }\n }\n}\n", "import { randomUUID } from 'node:crypto';\nimport { EventEmitter } from 'node:events';\nimport type { ServerEvent } from '@antbot/contract';\n\n/** Distributive omit so the discriminated union survives (a plain Omit collapses it). */\ntype DistOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\ntype Emitted = DistOmit<ServerEvent, 'seq'> & { seq?: number };\n\n/** In-process event bus. Assigns a monotonic seq so the UI can order/reconcile. */\nexport class EventBus {\n private emitter = new EventEmitter();\n private seq = 0;\n private ring: ServerEvent[] = [];\n private readonly ringMax = 500;\n /**\n * This process's identity, sent in `hello`. seq restarts at 1 on every boot, so without a way\n * to say \"the numbering is new\" a client that survived the restart discards every event it is\n * sent \u2014 connected, and permanently blank.\n */\n readonly epoch: string = randomUUID();\n\n constructor() {\n this.emitter.setMaxListeners(200);\n }\n\n publish(e: Emitted): ServerEvent {\n const full = { ...e, seq: ++this.seq } as ServerEvent;\n this.ring.push(full);\n if (this.ring.length > this.ringMax) this.ring.shift();\n this.emitter.emit('event', full);\n return full;\n }\n\n subscribe(fn: (e: ServerEvent) => void): () => void {\n this.emitter.on('event', fn);\n return () => this.emitter.off('event', fn);\n }\n\n /** Replay events after a given seq (client reconnect). */\n since(seq: number): ServerEvent[] {\n return this.ring.filter((e) => e.seq > seq);\n }\n\n get currentSeq(): number {\n return this.seq;\n }\n}\n", "import type { Rule } from '@antbot/contract';\nimport type { Store } from '../db/store.js';\nimport { logger } from '../util/log.js';\n\nconst log = logger('rules');\n\n/** Convert a glob (only `*` is special) to an anchored, case-insensitive regex. */\nexport function globToRegExp(glob: string): RegExp {\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*');\n return new RegExp(`^${escaped}$`, 'i');\n}\n\n/** Flatten a tool input into one searchable string so input patterns can match anywhere. */\nexport function serializeInput(input: unknown): string {\n if (input == null) return '';\n if (typeof input === 'string') return input;\n try {\n return JSON.stringify(input);\n } catch {\n return String(input);\n }\n}\n\n/**\n * Build the text a rule's `inputPattern` is tested against.\n *\n * Every string value in the input gets its own line, and the serialized form is\n * appended last. Patterns are matched multiline, so `^` anchors to the start of an\n * actual argument value (e.g. the Bash `command`) rather than to the start of a JSON\n * blob \u2014 without that, an anchored allow-rule can never fire and the action falls\n * through to a human prompt.\n */\nexport function buildMatchText(input: unknown): string {\n const lines: string[] = [];\n const walk = (v: unknown, depth: number): void => {\n if (depth > 6) return;\n if (typeof v === 'string') lines.push(v);\n else if (Array.isArray(v)) v.forEach((x) => walk(x, depth + 1));\n else if (v && typeof v === 'object') Object.values(v).forEach((x) => walk(x, depth + 1));\n else if (typeof v === 'number' || typeof v === 'boolean') lines.push(String(v));\n };\n walk(input, 0);\n const serialized = serializeInput(input);\n if (serialized && !lines.includes(serialized)) lines.push(serialized);\n return lines.join('\\n');\n}\n\nexport interface RuleMatch {\n rule: Rule;\n matched: true;\n}\n\n/**\n * Names a tool call can be matched against.\n *\n * Tools served over MCP arrive at the permission boundary fully namespaced as\n * `mcp__<server>__<tool>` \u2014 a live turn records the browser tools as\n * `mcp__browser__browser_navigate`. Rule tool patterns are anchored, so a rule written\n * against the bare name (`browser_click`, `send_to_bot`) could never match, silently\n * killing the consequential-click, credential-typing and handoff require-rules.\n *\n * Matching against both forms keeps rules authored either way working. Both `require`\n * and `allow` rules get the same treatment, so this cannot flip a blocked action into\n * an allowed one \u2014 `require` still wins (see `evaluateRules`).\n */\nexport function toolNameAliases(toolName: string): string[] {\n const m = /^mcp__.+?__(.+)$/.exec(toolName);\n return m?.[1] ? [toolName, m[1]] : [toolName];\n}\n\nexport function ruleMatches(rule: Rule, toolName: string, inputText: string): boolean {\n if (!rule.enabled) return false;\n const pattern = globToRegExp(rule.toolPattern);\n if (!toolNameAliases(toolName).some((n) => pattern.test(n))) return false;\n if (rule.inputPattern) {\n let re: RegExp;\n try {\n re = new RegExp(rule.inputPattern, 'im');\n } catch {\n return false; // an invalid stored pattern must never silently allow\n }\n if (!re.test(inputText)) return false;\n }\n return true;\n}\n\nexport type RuleDecision =\n | { kind: 'require'; rule: Rule }\n | { kind: 'allow'; rule: Rule }\n | { kind: 'none' };\n\n/**\n * Precedence, per outline \u00A79: an enabled `require` rule always wins over any\n * `allow` rule. Only when no `require` matches can an `allow` take effect.\n */\nexport function evaluateRules(rules: Rule[], toolName: string, input: unknown): RuleDecision {\n const inputText = buildMatchText(input);\n const required = rules.find((r) => r.kind === 'require' && ruleMatches(r, toolName, inputText));\n if (required) return { kind: 'require', rule: required };\n const allowed = rules.find((r) => r.kind === 'allow' && ruleMatches(r, toolName, inputText));\n if (allowed) return { kind: 'allow', rule: allowed };\n return { kind: 'none' };\n}\n\n/**\n * Default require-rules (WP-2.1). These ship enabled so that sending, publishing,\n * purchasing, deleting outside the workspace, installs, sudo and git push are all\n * behind approval out of the box.\n */\nexport const BUILTIN_RULES: Array<Omit<Rule, 'id' | 'createdAt'>> = [\n { kind: 'require', toolPattern: 'Bash', inputPattern: '\\\\bsudo\\\\b|\\\\bdoas\\\\b|\\\\bsu\\\\s+-', scopeNote: 'Privilege escalation', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: 'rm\\\\s+(-[a-zA-Z]*\\\\s+)*-?[rf]|shred\\\\b|mkfs\\\\b|dd\\\\s+if=', scopeNote: 'Destructive filesystem command', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: 'curl[^|]*\\\\|\\\\s*(ba)?sh|wget[^|]*\\\\|\\\\s*(ba)?sh', scopeNote: 'Piping a download into a shell', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: '\\\\b(npm|pnpm|yarn|pip|pip3|gem|cargo|apt|apt-get|dnf|brew|go)\\\\s+(i|install|add|get)\\\\b', scopeNote: 'Package install', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: 'git\\\\s+(push|remote\\\\s+add)|gh\\\\s+(pr|release|repo)\\\\s+(create|merge)', scopeNote: 'Publishing to a remote', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: '\\\\b(mail|sendmail|mutt|msmtp)\\\\b', scopeNote: 'Sending mail', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: 'curl[^\\\\n]*(-X\\\\s*(POST|PUT|PATCH|DELETE)|--data|-d\\\\s)', scopeNote: 'Outbound write request', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'WebFetch', inputPattern: '.', scopeNote: 'Fetching an external URL', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'browser_click', inputPattern: '(buy|purchase|checkout|pay|order|subscribe|confirm|delete|send|publish)', scopeNote: 'Consequential click', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'browser_type', inputPattern: '(password|passwd|secret|token|api[_-]?key|ssn|credit\\\\s*card)', scopeNote: 'Typing a credential \u2014 use takeover instead', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'send_to_bot', inputPattern: '', scopeNote: 'Handing work to another bot', builtin: false, enabled: false },\n { kind: 'require', toolPattern: 'install_skill', inputPattern: '', scopeNote: 'Installing a skill from an external source', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'remove_skill', inputPattern: '', scopeNote: 'Uninstalling a skill', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'Read', inputPattern: '', scopeNote: 'Reading files is safe', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'Glob', inputPattern: '', scopeNote: 'Listing files is safe', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'Grep', inputPattern: '', scopeNote: 'Searching files is safe', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'TodoWrite', inputPattern: '', scopeNote: 'Planning scratchpad', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'Bash', inputPattern: '^\\\\s*(git\\\\s+(status|diff|log|show|branch)|ls|pwd|cat|head|tail|wc|echo|date|which|grep|find|rg)\\\\b', scopeNote: 'Read-only shell inspection', builtin: true, enabled: true },\n // The one place a seeded `mcp__*` rule is right: these tool names are ant-bot's own (the gmail\n // connector is served by the daemon), fixed, and fully qualified \u2014 so they cannot match a\n // third-party server's tool by alias, and they are the two Gmail actions that leave the machine.\n { kind: 'require', toolPattern: 'mcp__gmail__send_message', inputPattern: '', scopeNote: 'Sending email', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'mcp__gmail__create_draft', inputPattern: '', scopeNote: 'Creating an email draft', builtin: true, enabled: true },\n];\n\n/**\n * Ensure every builtin rule exists, adding only the ones that don't.\n *\n * Seeding all-or-nothing would mean a rule added in a later version never reaches an\n * existing database \u2014 the new gate would silently not apply to exactly the installs that\n * have been running longest. Rules already present are left alone, so a builtin the user\n * has disabled stays disabled.\n */\nexport function seedBuiltinRules(store: Store): void {\n // Match across every rule, not just `builtin` ones: one seeded entry (send_to_bot) is\n // deliberately created as a user rule, and filtering to builtins would re-add it each boot.\n const key = (r: { kind: string; toolPattern: string; inputPattern: string }): string =>\n `${r.kind}\\u0000${r.toolPattern}\\u0000${r.inputPattern}`;\n const existing = new Set(store.listRules().map(key));\n const added: string[] = [];\n for (const r of BUILTIN_RULES) {\n if (existing.has(key(r))) continue;\n const rule = store.createRule(r);\n if (!r.enabled) store.setRuleEnabled(rule.id, false);\n added.push(r.toolPattern);\n }\n if (added.length) log.info(`seeded ${added.length} builtin permission rule(s): ${added.join(', ')}`);\n}\n", "import path from 'node:path';\n\n/**\n * Decide whether a proposed tool call reaches OUTSIDE the shared workspace \u2014 i.e.\n * touches the user's own machine rather than the bots' computer.\n *\n * ant-bot has no separate cloud VM, so Grok Bot's \"execution on local computer\"\n * control maps onto this boundary: the workspace is the bots' computer, and\n * everything else is your machine.\n */\nexport type LocalReach = { reaches: boolean; evidence: string };\n\nconst HOME_ISH = /(^|[\\s\"'=:])(~|\\$HOME)\\//;\n\n/** Anything scheme://... \u2014 a URL's path is not a filesystem path. */\nconst URL_RE = /\\b[a-z][a-z0-9+.-]*:\\/\\/\\S+/gi;\n\n/**\n * Filesystem path candidates in a command string: absolute (`/etc`), home-relative\n * (`~/.ssh`), and dot-relative (`./src`, `../..`). Dot-relative forms are kept rather\n * than dropped because they resolve against the workspace, so `./src` reads as inside\n * while `../../.ssh` correctly reads as an escape.\n */\nexport function extractPaths(text: string): string[] {\n const out: string[] = [];\n const cleaned = text.replace(URL_RE, ' ');\n for (const m of cleaned.matchAll(/(?<![\\w\\-.:/])((?:~|\\.{1,2}\\/|\\.\\.(?=\\s|$)|\\/)[^\\s\"';|&)]*)/g)) {\n const p = m[1];\n if (p && p.length > 1) out.push(p);\n }\n return out;\n}\n\n/**\n * @param allowedRoots Directories that count as inside even though they are not the workspace.\n * ant-bot's own attachments directory is one: a file the human attached to the message they\n * are sending is theirs, already handed over deliberately, and making the bot ask permission\n * to open the image you just gave it stalls the turn on a question with one sensible answer.\n */\nexport function assessLocalReach(\n toolName: string,\n input: unknown,\n workspace: string,\n allowedRoots: string[] = [],\n): LocalReach {\n const o = (input ?? {}) as Record<string, unknown>;\n const str = (k: string): string => (typeof o[k] === 'string' ? (o[k] as string) : '');\n const ws = path.resolve(workspace);\n const roots = [ws, ...allowedRoots.map((r) => path.resolve(r))];\n\n const insideWorkspace = (p: string): boolean => {\n if (p.startsWith('~')) return false;\n const abs = path.isAbsolute(p) ? path.resolve(p) : path.resolve(ws, p);\n return roots.some((root) => {\n const rel = path.relative(root, abs);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n });\n };\n\n // File tools carry an explicit path.\n if (toolName === 'Read' || toolName === 'Write' || toolName === 'Edit' || toolName === 'NotebookEdit') {\n const p = str('file_path') || str('notebook_path');\n if (p && !insideWorkspace(p)) return { reaches: true, evidence: p };\n return { reaches: false, evidence: '' };\n }\n\n if (toolName === 'Bash') {\n const cmd = str('command');\n if (HOME_ISH.test(cmd)) {\n const m = cmd.match(HOME_ISH);\n return { reaches: true, evidence: m ? cmd.slice(Math.max(0, (m.index ?? 0)), (m.index ?? 0) + 60).trim() : '~' };\n }\n for (const p of extractPaths(cmd)) {\n if (!insideWorkspace(p)) return { reaches: true, evidence: p };\n }\n return { reaches: false, evidence: '' };\n }\n\n return { reaches: false, evidence: '' };\n}\n\nexport type LocalPolicy = 'ask' | 'always' | 'never';\n\nexport function localDecision(policy: LocalPolicy, reach: LocalReach):\n | { action: 'ignore' }\n | { action: 'require'; reason: string }\n | { action: 'deny'; reason: string } {\n if (!reach.reaches) return { action: 'ignore' };\n if (policy === 'always') return { action: 'ignore' };\n if (policy === 'never')\n return {\n action: 'deny',\n reason: `Blocked: this touches ${reach.evidence}, which is outside the shared workspace. \"Execution on local computer\" is set to Never in Settings.`,\n };\n return { action: 'require', reason: `Touches ${reach.evidence}, outside the shared workspace (your own machine)` };\n}\n", "import type { Store } from '../db/store.js';\nimport type { EventBus } from '../util/bus.js';\nimport { LIMITS, type Approval, type Settings } from '@antbot/contract';\nimport { evaluateRules, serializeInput, toolNameAliases } from './rules.js';\nimport { assessLocalReach, localDecision } from './local.js';\nimport { describeSkillSource } from '../skills/install.js';\nimport { logger } from '../util/log.js';\n\nconst log = logger('gateway');\n\nexport type GatewayDecision =\n | { behavior: 'allow'; reason: string; via: 'rule' | 'auto_review' | 'user' }\n | { behavior: 'deny'; message: string; via: 'rule' | 'auto_review' | 'user' | 'timeout' };\n\nexport interface AutoReviewer {\n /** Classify a proposed tool call. Never able to override a `require` rule. */\n classify(toolName: string, input: unknown, botDescription: string): Promise<{\n verdict: 'allow_ok' | 'needs_human' | 'deny_suggested';\n reason: string;\n }>;\n}\n\nexport interface PendingResolver {\n approvalId: string;\n resolve: (d: GatewayDecision) => void;\n timer: NodeJS.Timeout;\n}\n\n/** Human-readable one-line summary of a proposed action for the approval card. */\nexport function summarize(namespacedToolName: string, input: unknown): string {\n const o = (input ?? {}) as Record<string, unknown>;\n const s = (k: string): string => (typeof o[k] === 'string' ? (o[k] as string) : '');\n // MCP tools arrive as `mcp__<server>__<tool>`; summarize on the bare name so the\n // approval card stays legible. Falls back to the full name for anything unrecognized.\n const aliases = toolNameAliases(namespacedToolName);\n const toolName = aliases[aliases.length - 1]!;\n switch (toolName) {\n case 'Bash':\n return `Run: ${s('command').slice(0, 200)}`;\n case 'Write':\n return `Write file ${s('file_path')}`;\n case 'Edit':\n return `Edit file ${s('file_path')}`;\n case 'Read':\n return `Read file ${s('file_path')}`;\n case 'WebFetch':\n return `Fetch ${s('url')}`;\n case 'send_to_bot':\n return `Hand work to @${s('bot_slug')}`;\n // Scope is the whole decision here: one named skill, or every skill in a repository.\n case 'install_skill':\n return describeSkillSource(s('source'));\n case 'remove_skill':\n return `Uninstall the skill \"${s('slug')}\"`;\n default: {\n if (toolName.startsWith('browser_')) {\n const bits = [s('url'), s('selector'), s('text')].filter(Boolean).join(' ');\n return `${toolName.replace('browser_', 'Browser ')}: ${bits}`.trim();\n }\n const flat = serializeInput(input);\n return `${toolName}: ${flat.slice(0, 180)}`;\n }\n }\n}\n\nexport class PermissionGateway {\n private pending = new Map<string, PendingResolver>();\n\n constructor(\n private store: Store,\n private bus: EventBus,\n private autoReviewer?: AutoReviewer,\n ) {}\n\n /**\n * Decide whether a proposed tool call may run.\n * Order: deterministic rules \u2192 auto review (advisory) \u2192 human approval card.\n * A matching `require` rule can never be satisfied by auto review (outline \u00A79).\n */\n async check(args: {\n botId: string;\n threadId: string;\n toolName: string;\n input: unknown;\n botDescription: string;\n settings: Settings;\n signal?: AbortSignal;\n /** Absolute path of the shared workspace, for the local-execution boundary. */\n workspace: string;\n /** Directories outside the workspace that still count as inside \u2014 ant-bot's attachments. */\n allowedRoots?: string[];\n /** Fired when a human approval card is created, so the caller can render it inline. */\n onPending?: (approval: Approval) => void;\n }): Promise<GatewayDecision> {\n const { toolName, input, settings } = args;\n const rules = this.store.listRules(true);\n const decision = evaluateRules(rules, toolName, input);\n\n // The local-execution policy is checked before any allow rule: reaching outside\n // the shared workspace means touching the user's own machine, and a broad allow\n // rule must not silently authorize that.\n const local = localDecision(\n settings.localExecution,\n assessLocalReach(toolName, input, args.workspace, args.allowedRoots ?? []),\n );\n if (local.action === 'deny') {\n return { behavior: 'deny', message: local.reason, via: 'rule' };\n }\n if (local.action === 'require' && decision.kind !== 'require') {\n return this.askHuman({ ...args, reason: local.reason });\n }\n\n if (decision.kind === 'allow') {\n log.debug(`allow by rule ${decision.rule.id}: ${toolName}`);\n return { behavior: 'allow', reason: decision.rule.scopeNote || 'Matched an allow rule', via: 'rule' };\n }\n\n const requiredBy = decision.kind === 'require' ? decision.rule : null;\n\n // Auto review is advisory and only consulted when no `require` rule matched.\n if (!requiredBy && settings.autoReviewEnabled && this.autoReviewer) {\n try {\n const verdict = await this.autoReviewer.classify(toolName, input, args.botDescription);\n if (verdict.verdict === 'allow_ok')\n return { behavior: 'allow', reason: verdict.reason, via: 'auto_review' };\n if (verdict.verdict === 'deny_suggested')\n return this.askHuman({ ...args, reason: `Auto review flagged this: ${verdict.reason}` });\n return this.askHuman({ ...args, reason: verdict.reason });\n } catch (err) {\n log.warn('auto review failed; falling back to human approval', err);\n }\n }\n\n return this.askHuman({\n ...args,\n reason: requiredBy ? requiredBy.scopeNote || 'Matched a require-approval rule' : 'No rule covers this action',\n ruleId: requiredBy?.id ?? null,\n });\n }\n\n private askHuman(args: {\n botId: string; threadId: string; toolName: string; input: unknown;\n reason: string; ruleId?: string | null; signal?: AbortSignal;\n onPending?: (approval: Approval) => void;\n }): Promise<GatewayDecision> {\n const approval = this.store.createApproval({\n botId: args.botId,\n threadId: args.threadId,\n toolName: args.toolName,\n inputSummary: summarize(args.toolName, args.input),\n rawInput: args.input,\n reason: args.reason,\n });\n if (args.ruleId) this.store.db.prepare(`UPDATE approvals SET rule_id=? WHERE id=?`).run(args.ruleId, approval.id);\n\n const fresh = this.store.getApproval(approval.id)!;\n args.onPending?.(fresh);\n this.bus.publish({\n type: 'approval.pending',\n threadId: args.threadId,\n botId: args.botId,\n approval: fresh,\n });\n\n return new Promise<GatewayDecision>((resolve) => {\n const timer = setTimeout(() => {\n this.pending.delete(approval.id);\n this.store.resolveApproval(approval.id, 'expired', 'user', null, 'No response in time');\n this.bus.publish({\n type: 'approval.resolved', threadId: args.threadId, botId: args.botId,\n approval: this.store.getApproval(approval.id)!,\n });\n resolve({ behavior: 'deny', message: 'Approval request expired without a decision.', via: 'timeout' });\n }, LIMITS.APPROVAL_TIMEOUT_MS);\n\n this.pending.set(approval.id, { approvalId: approval.id, resolve, timer });\n\n args.signal?.addEventListener('abort', () => {\n const p = this.pending.get(approval.id);\n if (!p) return;\n clearTimeout(p.timer);\n this.pending.delete(approval.id);\n this.store.resolveApproval(approval.id, 'denied', 'user', null, 'Turn interrupted');\n resolve({ behavior: 'deny', message: 'Interrupted.', via: 'user' });\n });\n });\n }\n\n /** Resolve a pending approval from the UI. Returns the updated row. */\n decide(approvalId: string, decision: 'allow' | 'deny', alwaysRule?: { toolPattern: string; inputPattern?: string; scopeNote?: string }): Approval | null {\n const p = this.pending.get(approvalId);\n const existing = this.store.getApproval(approvalId);\n if (!existing) return null;\n if (existing.status !== 'pending') return existing;\n\n let ruleId: string | null = null;\n if (decision === 'allow' && alwaysRule) {\n const rule = this.store.createRule({\n kind: 'allow',\n toolPattern: alwaysRule.toolPattern,\n inputPattern: alwaysRule.inputPattern ?? '',\n scopeNote: alwaysRule.scopeNote ?? 'Saved from an approval',\n });\n ruleId = rule.id;\n }\n\n const updated = this.store.resolveApproval(\n approvalId, decision === 'allow' ? 'allowed' : 'denied', 'user', ruleId,\n decision === 'allow' ? 'Approved by you' : 'Denied by you',\n );\n this.bus.publish({\n type: 'approval.resolved', threadId: existing.threadId, botId: existing.botId, approval: updated!,\n });\n\n if (p) {\n clearTimeout(p.timer);\n this.pending.delete(approvalId);\n p.resolve(\n decision === 'allow'\n ? { behavior: 'allow', reason: 'Approved by you', via: 'user' }\n : { behavior: 'deny', message: 'You denied this action.', via: 'user' },\n );\n }\n return updated;\n }\n\n hasPending(approvalId: string): boolean {\n return this.pending.has(approvalId);\n }\n\n /** Cancel any pending approvals for a bot (used when a turn is interrupted). */\n cancelForBot(botId: string): void {\n for (const [id, p] of [...this.pending]) {\n const a = this.store.getApproval(id);\n if (a?.botId !== botId) continue;\n clearTimeout(p.timer);\n this.pending.delete(id);\n this.store.resolveApproval(id, 'denied', 'user', null, 'Turn interrupted');\n p.resolve({ behavior: 'deny', message: 'Interrupted.', via: 'user' });\n }\n }\n}\n", "import { query } from '@anthropic-ai/claude-agent-sdk';\nimport type { AutoReviewer } from './gateway.js';\nimport { buildEnv } from '../agent/session.js';\nimport type { Settings } from '@antbot/contract';\nimport { logger } from '../util/log.js';\nimport { summarize } from './gateway.js';\n\nconst log = logger('autoreview');\n\nconst SYSTEM = `You are the automated action reviewer for a local AI-teammate system.\nYou judge ONE proposed tool call and answer with a single JSON object.\n\nAnswer \"allow_ok\" only when the action is clearly routine, reversible and\nlow-consequence \u2014 reading files, inspecting state, searching, navigating to a\nnormal public page, writing inside the bot's own workspace.\n\nAnswer \"needs_human\" when the action is consequential or ambiguous: sending or\npublishing anything, contacting a person, spending money, changing permissions,\ntouching production, deleting or overwriting data outside the workspace,\ninstalling software, or anything whose blast radius you cannot determine.\n\nAnswer \"deny_suggested\" when the action looks actively unsafe or like an attempt\nto exfiltrate credentials.\n\nYou are advisory only and you are NOT the last line of defence. When in doubt,\nchoose needs_human.\n\nReply with ONLY: {\"verdict\":\"allow_ok|needs_human|deny_suggested\",\"reason\":\"<12 words max>\"}`;\n\n/** Haiku-backed reviewer. Advisory: it can never green-light past a `require` rule. */\nexport class HaikuAutoReviewer implements AutoReviewer {\n constructor(\n private getSettings: () => Settings,\n private cwd: string,\n ) {}\n\n async classify(toolName: string, input: unknown, botDescription: string) {\n const prompt = `Bot's standing job description:\n${botDescription.slice(0, 800) || '(none)'}\n\nProposed tool call:\ntool: ${toolName}\nsummary: ${summarize(toolName, input)}\nraw input: ${JSON.stringify(input).slice(0, 1500)}`;\n\n const q = query({\n prompt,\n options: {\n model: 'haiku',\n systemPrompt: SYSTEM,\n cwd: this.cwd,\n settingSources: [],\n env: buildEnv(this.getSettings()),\n maxTurns: 1,\n allowedTools: [],\n permissionMode: 'default',\n },\n });\n\n let out = '';\n for await (const m of q) {\n const msg = m as Record<string, any>;\n if (msg.type === 'result' && typeof msg.result === 'string') out = msg.result;\n }\n return parseVerdict(out);\n }\n}\n\nexport function parseVerdict(text: string): { verdict: 'allow_ok' | 'needs_human' | 'deny_suggested'; reason: string } {\n const fallback = { verdict: 'needs_human' as const, reason: 'Reviewer output was unreadable' };\n if (!text) return fallback;\n const match = text.match(/\\{[\\s\\S]*\\}/);\n if (!match) return fallback;\n try {\n const o = JSON.parse(match[0]) as { verdict?: string; reason?: string };\n if (o.verdict === 'allow_ok' || o.verdict === 'needs_human' || o.verdict === 'deny_suggested')\n return { verdict: o.verdict, reason: String(o.reason ?? '').slice(0, 200) };\n return fallback;\n } catch {\n return fallback;\n }\n}\n\n/** Deterministic reviewer used in tests and when auto review is disabled. */\nexport class NullAutoReviewer implements AutoReviewer {\n async classify() {\n return { verdict: 'needs_human' as const, reason: 'Auto review disabled' };\n }\n}\n\nexport function makeAutoReviewer(getSettings: () => Settings, cwd: string): AutoReviewer {\n try {\n return new HaikuAutoReviewer(getSettings, cwd);\n } catch (err) {\n log.warn('falling back to null reviewer', err);\n return new NullAutoReviewer();\n }\n}\n", "import { query, type Options, type SDKMessage } from '@anthropic-ai/claude-agent-sdk';\nimport type { ModelTier, Settings } from '@antbot/contract';\nimport { logger } from '../util/log.js';\nimport { ClaudeRuntime, type MountedConnector } from './runtime.js';\n\nconst log = logger('agent');\n\n/** Connection state the SDK reports for one mounted MCP server at turn start. */\nexport interface McpStatus {\n name: string;\n status: 'connected' | 'failed' | 'needs-auth' | 'pending' | 'disabled';\n error?: string;\n}\n\nexport interface TurnEvent {\n kind: 'text' | 'tool_start' | 'tool_result' | 'session' | 'done' | 'error' | 'status' | 'mcp_status' | 'signin';\n text?: string;\n toolName?: string;\n toolInput?: unknown;\n toolUseId?: string;\n result?: string;\n isError?: boolean;\n sessionId?: string;\n usage?: { model: string; inputTokens: number; outputTokens: number; cacheReadTokens: number; costUsd: number };\n message?: string;\n /** Present on `mcp_status`: every server the SDK tried to mount for this turn. */\n mcpStatus?: McpStatus[];\n /** Present on `signin`: a connector asked for a browser sign-in mid-turn. */\n signin?: { serverName: string; url: string };\n}\n\nexport interface TurnRequest {\n prompt: string;\n /** Prior SDK session to resume so context compounds across turns. */\n resumeSessionId?: string | null;\n modelTier: ModelTier;\n systemPrompt: string;\n cwd: string;\n settings: Settings;\n /** Extra directories the agent may read/write beyond cwd. */\n additionalDirectories?: string[];\n canUseTool?: Options['canUseTool'];\n /** In-process SDK servers ant-bot itself provides (`antbot`, `browser`). Runtime-bound by nature. */\n mcpServers?: Options['mcpServers'];\n /** The bot's assigned connectors, resolved. Mounted through the runtime adapter. */\n connectors?: Record<string, MountedConnector>;\n abortController?: AbortController;\n /** Root of the local plugin that carries installed skills. */\n skillPluginPath?: string;\n /**\n * Skill names this bot may use. `[]` means none \u2014 the SDK hides unlisted skills from\n * the model's listing and the Skill tool rejects them. Note this is a context filter,\n * not a sandbox: skill files stay readable via Read/Bash, so never put secrets in one.\n */\n enabledSkills?: string[];\n}\n\n/**\n * MODEL_TIERS are `claude` CLI model aliases (`claude --model fable|opus|sonnet|haiku`), so the\n * tier passes straight through. Routing stays fixed per surface: a Bot's tier is chosen once in\n * its settings, never per message, and auto-review and the group router always use `haiku`.\n */\nexport function resolveModel(tier: ModelTier): string {\n return tier;\n}\n\n/**\n * Build the environment for the CLI subprocess.\n *\n * The daemon never holds Anthropic credentials: the SDK spawns the `claude` CLI,\n * which uses the user's existing subscription OAuth login. An ANTHROPIC_API_KEY in\n * the ambient environment would silently switch billing to metered API usage, so we\n * strip it unless the user explicitly opted into API billing (plan \u00A79).\n */\nexport function buildEnv(settings: Settings, base: NodeJS.ProcessEnv = process.env): Record<string, string | undefined> {\n const env: Record<string, string | undefined> = { ...base };\n if (settings.billingMode !== 'api') {\n delete env.ANTHROPIC_API_KEY;\n delete env.ANTHROPIC_AUTH_TOKEN;\n }\n return env;\n}\n\n/**\n * Run one turn and yield normalized events. The caller owns persistence; this\n * wrapper only translates the SDK's message stream into our vocabulary.\n */\nconst runtime = new ClaudeRuntime();\n\nexport async function* runTurn(req: TurnRequest): AsyncGenerator<TurnEvent> {\n const abort = req.abortController ?? new AbortController();\n const options: Options = {\n model: resolveModel(req.modelTier),\n systemPrompt: { type: 'preset', preset: 'claude_code', append: req.systemPrompt },\n cwd: req.cwd,\n additionalDirectories: req.additionalDirectories,\n abortController: abort,\n includePartialMessages: true,\n permissionMode: 'default',\n canUseTool: req.canUseTool,\n mcpServers: {\n ...(req.mcpServers ?? {}),\n ...(runtime.mountConnectors(req.connectors ?? {}) as Options['mcpServers']),\n },\n // ant-bot is the MCP host. The SDK mounts exactly what is passed here and nothing else \u2014 not\n // ~/.claude.json, not plugins, not claude.ai connectors. A bot's tools cannot change because\n // of something configured outside ant-bot, and swapping the runtime later swaps only this.\n strictMcpConfig: true,\n env: buildEnv(req.settings),\n // Do not inherit the user's own Claude Code project settings into bot turns.\n settingSources: [],\n maxTurns: 60,\n };\n if (req.resumeSessionId) options.resume = req.resumeSessionId;\n // Load skills as a local plugin so the model gets the real `Skill` tool rather than a\n // pile of paths to read, then narrow to the ones assigned to this bot.\n if (req.skillPluginPath) {\n // skipMcpDiscovery: a skill directory must never be a way to mount an MCP server. Connectors\n // come through `connectors` above, and only through there.\n options.plugins = [{ type: 'local', path: req.skillPluginPath, skipMcpDiscovery: true }];\n options.skills = req.enabledSkills ?? [];\n }\n\n // A connector can ask for a sign-in in the middle of a turn (an expired token, a first use).\n // Without a handler the SDK declines on the bot's behalf and the tool call just fails. URL\n // mode is accepted and surfaced as a card; the queue hands it to the generator, which yields\n // it ahead of the next SDK message. Form mode is declined: a bot must never fill in a form a\n // server put in front of it, and nothing here can show one to a human anyway.\n const pending: TurnEvent[] = [];\n options.onElicitation = async (request) => {\n if (request.mode === 'url' && request.url) {\n pending.push({ kind: 'signin', signin: { serverName: request.serverName, url: request.url } });\n return { action: 'accept' };\n }\n log.warn(`declined a ${request.mode ?? 'form'} elicitation from \"${request.serverName}\": ${request.message}`);\n return { action: 'decline' };\n };\n\n let q: ReturnType<typeof query>;\n try {\n q = query({ prompt: req.prompt, options });\n } catch (err) {\n yield { kind: 'error', message: err instanceof Error ? err.message : String(err) };\n return;\n }\n\n const seenToolIds = new Set<string>();\n\n try {\n for await (const msg of q as AsyncGenerator<SDKMessage>) {\n while (pending.length) yield pending.shift()!;\n const m = msg as Record<string, any>;\n switch (m.type) {\n case 'system':\n if (m.subtype === 'init' && m.session_id) yield { kind: 'session', sessionId: m.session_id };\n // The sign-in finished in the browser; the server's tools only return once the SDK\n // reconnects with the new token, and it does not do that on its own.\n if (m.subtype === 'elicitation_complete' && typeof m.mcp_server_name === 'string') {\n try {\n await q.reconnectMcpServer(m.mcp_server_name);\n } catch (err) {\n log.warn(`reconnect of \"${m.mcp_server_name}\" after sign-in failed: ${(err as Error).message}`);\n }\n }\n // The init message is the only place the SDK reports whether a mounted MCP server\n // actually came up. Dropping it is how a connector that needs auth, or failed to\n // start, becomes a bot that silently has no such tools and cannot say why.\n if (m.subtype === 'init' && Array.isArray(m.mcp_servers)) {\n yield { kind: 'mcp_status', mcpStatus: m.mcp_servers as McpStatus[] };\n }\n break;\n\n case 'stream_event': {\n const ev = m.event;\n if (ev?.type === 'content_block_delta' && ev.delta?.type === 'text_delta' && ev.delta.text)\n yield { kind: 'text', text: ev.delta.text };\n break;\n }\n\n case 'assistant': {\n for (const block of m.message?.content ?? []) {\n if (block.type === 'tool_use' && !seenToolIds.has(block.id)) {\n seenToolIds.add(block.id);\n yield { kind: 'tool_start', toolName: block.name, toolInput: block.input, toolUseId: block.id };\n }\n }\n break;\n }\n\n case 'user': {\n for (const block of m.message?.content ?? []) {\n if (block.type === 'tool_result') {\n const content = Array.isArray(block.content)\n ? block.content.map((c: any) => (typeof c?.text === 'string' ? c.text : '')).join('\\n')\n : typeof block.content === 'string'\n ? block.content\n : '';\n yield {\n kind: 'tool_result',\n toolUseId: block.tool_use_id,\n result: content.slice(0, 4000),\n isError: Boolean(block.is_error),\n };\n }\n }\n break;\n }\n\n case 'result': {\n const u = m.usage ?? {};\n yield {\n kind: 'done',\n sessionId: m.session_id,\n text: typeof m.result === 'string' ? m.result : undefined,\n isError: m.subtype !== 'success',\n usage: {\n model: m.modelUsage ? Object.keys(m.modelUsage)[0] ?? resolveModel(req.modelTier) : resolveModel(req.modelTier),\n inputTokens: u.input_tokens ?? 0,\n outputTokens: u.output_tokens ?? 0,\n cacheReadTokens: u.cache_read_input_tokens ?? 0,\n costUsd: m.total_cost_usd ?? 0,\n },\n };\n break;\n }\n\n default:\n break;\n }\n }\n } catch (err) {\n if (abort.signal.aborted) {\n yield { kind: 'error', message: 'Interrupted.' };\n return;\n }\n log.error('turn failed', err);\n yield { kind: 'error', message: err instanceof Error ? err.message : String(err) };\n }\n}\n", "// The seam between ant-bot's connector registry and whichever agent runtime executes a turn.\n//\n// ant-bot owns the registry, the credentials, the per-bot assignment and the health of every MCP\n// server. The runtime is handed a finished list and asked to mount it. Today the only runtime is\n// the Claude Agent SDK; a Gemini or Codex runtime would implement the same interface and translate\n// the same list into its own configuration. Nothing above this line may depend on a runtime.\n\n/** A connector resolved and ready to mount: credentials substituted, nothing left to look up. */\nexport type MountedConnector =\n | { type: 'stdio'; command: string; args: string[]; env: Record<string, string> }\n | { type: 'http' | 'sse'; url: string; headers: Record<string, string>; tools?: string[] };\n\nexport interface AgentRuntime {\n readonly name: string;\n /** Translate ant-bot's mounted connectors into whatever this runtime accepts. */\n mountConnectors(connectors: Record<string, MountedConnector>): Record<string, unknown>;\n}\n\n/**\n * The Claude Agent SDK.\n *\n * Every mounted connector gets `alwaysLoad: true`. Without it the SDK defers MCP tools behind its\n * ToolSearch, which meant a bot had to *find* a connector's tools before it could call one \u2014 and a\n * connector that failed to mount looked identical to one that was merely unfound. With it, the\n * tools are in the prompt, and the system prompt's `## Your connectors` block agrees with what the\n * model can actually see.\n */\nexport class ClaudeRuntime implements AgentRuntime {\n readonly name = 'claude';\n\n mountConnectors(connectors: Record<string, MountedConnector>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [name, c] of Object.entries(connectors)) out[name] = { ...c, alwaysLoad: true };\n return out;\n }\n}\n", "import path from 'node:path';\nimport fs from 'node:fs';\nimport { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';\nimport { z } from 'zod';\nimport type { Store } from '../db/store.js';\nimport type { EventBus } from '../util/bus.js';\nimport type { PermissionGateway } from '../permissions/gateway.js';\nimport type { MountedConnector } from '../agent/runtime.js';\nimport { runTurn, type TurnEvent } from '../agent/session.js';\nimport { buildSystemPrompt } from './prompt.js';\nimport { ensureMemoryDir } from '../memory/memory.js';\nimport { logger } from '../util/log.js';\nimport { LIMITS, type Bot, type Card, type TurnOrigin, type Settings } from '@antbot/contract';\nimport { newId } from '../util/ids.js';\nimport { describeSkillSource } from '../skills/install.js';\n\nconst log = logger('bots');\n\nexport interface TurnJob {\n id: string;\n botId: string;\n threadId: string;\n prompt: string;\n origin: TurnOrigin;\n hops: number;\n /** Priority: interactive turns run before routine turns (plan \u00A79). */\n priority: number;\n onDone?: (summary: string, ok: boolean) => void;\n}\n\nexport interface ManagerDeps {\n store: Store;\n bus: EventBus;\n gateway: PermissionGateway;\n workspace: string;\n getSettings: () => Settings;\n /**\n * Root of the local plugin carrying installed skills. A resolver rather than a value\n * because the skills subsystem is wired after the manager is constructed.\n */\n skillPluginPath?: () => string | undefined;\n /** Install a skill from a user-supplied source. Gated by the `install_skill` require-rule. */\n installSkill?: (\n source: string,\n opts?: { allowMultiple?: boolean },\n ) => Promise<Array<{ name: string; executables: string[] }>>;\n /** Every installed skill, so a bot can check before installing or removing. */\n listSkills?: () => Array<{ slug: string; name: string; description: string }>;\n /** Uninstall by slug. Gated by the `remove_skill` require-rule. */\n removeSkill?: (slug: string) => Promise<{ removed: boolean; name?: string }>;\n browserTools?: (botId: string) => ReturnType<typeof createSdkMcpServer> | undefined;\n /**\n * Directories a bot may read outside the workspace without a human approval. ant-bot's\n * attachments directory belongs here: the human attached those files to the message.\n */\n readableRoots?: string[];\n /**\n * MCP connectors assigned to this bot, resolved and ready to mount. Async because mounting\n * reads secrets from the keychain; returns what it could mount plus what to tell the model\n * about, so a connector skipped for a missing credential simply is not there this turn.\n */\n connectorServers?: (botId: string) => Promise<{\n servers: Record<string, MountedConnector>;\n mounted: { name: string; description: string }[];\n }>;\n}\n\nexport class BotManager {\n private queue: TurnJob[] = [];\n private running = new Map<string, { job: TurnJob; abort: AbortController }>();\n private draining = false;\n\n constructor(private deps: ManagerDeps) {}\n\n get runningCount(): number {\n return this.running.size;\n }\n get queuedCount(): number {\n return this.queue.length;\n }\n isBusy(botId: string): boolean {\n return this.running.has(botId) || this.queue.some((j) => j.botId === botId);\n }\n\n /** Enqueue a turn. Interactive work sorts ahead of routine work. */\n enqueue(job: Omit<TurnJob, 'id' | 'priority'> & { priority?: number }): TurnJob {\n const full: TurnJob = {\n ...job,\n id: newId(),\n priority: job.priority ?? (job.origin === 'routine' ? 10 : 0),\n };\n this.queue.push(full);\n this.queue.sort((a, b) => a.priority - b.priority);\n // Only if nothing is in flight for this bot. A turn waiting on a human approval is\n // \"waiting_approval\"; overwriting that with \"queued\" because a second message arrived is how\n // a bot asking a question came to look like a stalled queue with no question in it.\n if (!this.running.has(full.botId)) this.setState(full.botId, 'queued');\n void this.drain();\n return full;\n }\n\n private async drain(): Promise<void> {\n if (this.draining) return;\n this.draining = true;\n try {\n const max = this.deps.getSettings().maxConcurrentSessions ?? LIMITS.DEFAULT_MAX_CONCURRENT_SESSIONS;\n while (this.queue.length && this.running.size < max) {\n const idx = this.queue.findIndex((j) => !this.running.has(j.botId));\n if (idx === -1) break;\n const [job] = this.queue.splice(idx, 1);\n void this.execute(job!);\n }\n } finally {\n this.draining = false;\n }\n }\n\n private setState(botId: string, state: Bot['state'], attention?: Bot['attention']): void {\n const bot = this.deps.store.updateBot(botId, { state, ...(attention ? { attention } : {}) });\n if (!bot) return;\n this.deps.bus.publish({\n type: 'bot.state', botId, threadId: bot.threadId, state: bot.state, attention: bot.attention,\n });\n }\n\n interrupt(botId: string): boolean {\n const r = this.running.get(botId);\n this.queue = this.queue.filter((j) => j.botId !== botId);\n this.deps.gateway.cancelForBot(botId);\n if (!r) {\n this.setState(botId, 'idle');\n return false;\n }\n r.abort.abort();\n return true;\n }\n\n /** Custom tools exposed to every bot turn: handoff, memory, secrets-safe helpers. */\n private buildToolServer(bot: Bot, threadId: string, hops: number) {\n const { store, workspace } = this.deps;\n return createSdkMcpServer({\n name: 'antbot',\n version: '1.0.0',\n tools: [\n tool(\n 'send_to_bot',\n 'Hand work to another bot on this account. The recipient wakes, handles the request in its own thread, and can reply later. Use when the job genuinely belongs to that role.',\n { bot_slug: z.string().describe('slug of the teammate, e.g. \"writer\"'), message: z.string().describe('the request, with all context they need') },\n async (args: { bot_slug: string; message: string }) => {\n const target = store.getBotBySlug(args.bot_slug);\n if (!target) return { content: [{ type: 'text' as const, text: `No bot with slug \"${args.bot_slug}\". Use one of: ${store.listBots().map((b) => b.slug).join(', ')}` }] };\n if (target.id === bot.id) return { content: [{ type: 'text' as const, text: 'You cannot hand work to yourthis.' }] };\n if (hops + 1 > LIMITS.MAX_BOT_TO_BOT_HOPS)\n return { content: [{ type: 'text' as const, text: `Hop limit of ${LIMITS.MAX_BOT_TO_BOT_HOPS} reached. Stop and report back to the human instead.` }] };\n store.createMail({ fromBotId: bot.id, toBotId: target.id, contentMd: args.message, hops: hops + 1 });\n this.postSystemCard(threadId, bot.id, { type: 'handoff', fromBotId: bot.id, toBotId: target.id, note: args.message.slice(0, 300) });\n this.enqueue({\n botId: target.id, threadId: target.threadId!, origin: 'bot', hops: hops + 1,\n prompt: `**Handoff from @${bot.slug} (${bot.name}):**\\n\\n${args.message}\\n\\n---\\nHandle this, then reply. If it belongs to someone else, say so rather than guessing.`,\n });\n return { content: [{ type: 'text' as const, text: `Handed to @${target.slug}. They will pick it up and reply in their own thread.` }] };\n },\n ),\n tool(\n 'remember',\n 'Save a durable preference or fact to your memory so it survives future turns. Use only for stable things, never for changing data.',\n { title: z.string().describe('short kebab-case file name'), note: z.string().describe('the fact, in markdown') },\n async (args: { title: string; note: string }) => {\n const dir = ensureMemoryDir(workspace, bot.slug);\n const file = path.join(dir, `${args.title.replace(/[^a-zA-Z0-9._-]/g, '-')}.md`);\n fs.writeFileSync(file, args.note);\n return { content: [{ type: 'text' as const, text: `Saved to memory: ${path.basename(file)}` }] };\n },\n ),\n tool(\n 'list_skills',\n 'List every skill installed on this account, with its slug. Check here before installing ' +\n 'something that may already be present, and to find the exact slug to pass to remove_skill.',\n {},\n async () => {\n const skills = this.deps.listSkills?.() ?? [];\n if (!skills.length)\n return { content: [{ type: 'text' as const, text: 'No skills are installed.' }] };\n const lines = skills.map((sk) => `- ${sk.slug} \u2014 ${sk.name}${sk.description ? `: ${sk.description}` : ''}`);\n return { content: [{ type: 'text' as const, text: `${skills.length} skill(s) installed:\\n${lines.join('\\n')}` }] };\n },\n ),\n tool(\n 'install_skill',\n 'Install a skill so you (and other bots) can use it. This always stops for the human\\'s ' +\n 'approval first, because a skill is instructions that will steer future work and may ship scripts. ' +\n 'Check list_skills before installing something you already have.\\n' +\n 'Install the NARROWEST source that covers the request. Accepted forms:\\n' +\n ' github.com/owner/repo/tree/<ref>/<dir> one skill inside a repository \u2014 prefer this\\n' +\n ' https://host/path/SKILL.md one skill, direct link\\n' +\n ' ./path/to/skill a local directory\\n' +\n ' owner/repo, github.com/owner/repo EVERY skill in the repository\\n' +\n 'A bare owner/repo pointing at a collection installs all of it. If the human asked for one ' +\n 'named skill, point at that skill\\'s directory instead; if you only have a link to the repo ' +\n 'root, call this anyway and the error will list what is inside so you can narrow it.',\n {\n source: z.string().describe('prefer owner/repo/tree/<ref>/<dir> or a /SKILL.md link; owner/repo installs the whole repository'),\n reason: z.string().describe('why you need this skill for the task at hand'),\n install_all: z\n .boolean()\n .optional()\n .describe('set true only when the human has asked for every skill in a multi-skill source'),\n },\n async (args: { source: string; reason: string; install_all?: boolean }) => {\n if (!this.deps.installSkill)\n return { content: [{ type: 'text' as const, text: 'Skill installation is unavailable on this server.' }] };\n try {\n const installed = await this.deps.installSkill(args.source, { allowMultiple: args.install_all === true });\n if (!installed.length)\n return { content: [{ type: 'text' as const, text: `No skill found at \"${args.source}\".` }] };\n const names = installed.map((i) => i.name).join(', ');\n const scripts = installed.flatMap((i) => i.executables);\n const note = scripts.length\n ? ` Note for the human: this shipped ${scripts.length} script(s): ${scripts.join(', ')}.`\n : '';\n return {\n content: [{\n type: 'text' as const,\n text: `Installed: ${names}.${note} A skill must still be assigned to you in Bot settings ` +\n 'before you can invoke it \u2014 ask the human to enable it, then retry.',\n }],\n };\n } catch (err) {\n const e = err as Error & { name?: string; names?: string[] };\n if (e.name === 'MultipleSkillsError' && Array.isArray(e.names)) {\n const listed = e.names.slice(0, 40).join(', ');\n const more = e.names.length > 40 ? `, and ${e.names.length - 40} more` : '';\n return {\n content: [{\n type: 'text' as const,\n text:\n `Nothing was installed. \"${args.source}\" holds ${e.names.length} skills: ${listed}${more}.\\n` +\n 'Pick the one you need and install just it, e.g. ' +\n `${args.source.replace(/^https?:\\/\\//, '').replace(/\\/$/, '')}/tree/main/<skill-directory>. ` +\n 'Only pass install_all if the human has asked for all of them.',\n }],\n };\n }\n return { content: [{ type: 'text' as const, text: `Install failed: ${e.message}` }] };\n }\n },\n ),\n tool(\n 'remove_skill',\n 'Uninstall a skill by slug \u2014 deletes its directory and its registration together. ' +\n 'Use this rather than deleting skill directories with Bash, which would leave the ' +\n 'registry pointing at files that no longer exist. Stops for the human\\'s approval.',\n {\n slug: z.string().describe('the skill slug, exactly as list_skills reports it'),\n reason: z.string().describe('why this skill should be removed'),\n },\n async (args: { slug: string; reason: string }) => {\n if (!this.deps.removeSkill)\n return { content: [{ type: 'text' as const, text: 'Skill removal is unavailable on this server.' }] };\n try {\n const res = await this.deps.removeSkill(args.slug);\n if (!res.removed) {\n const known = (this.deps.listSkills?.() ?? []).map((sk) => sk.slug).join(', ');\n return { content: [{ type: 'text' as const, text: `No skill with slug \"${args.slug}\". Installed: ${known || 'none'}.` }] };\n }\n return { content: [{ type: 'text' as const, text: `Removed \"${args.slug}\"${res.name ? ` (${res.name})` : ''}.` }] };\n } catch (err) {\n return { content: [{ type: 'text' as const, text: `Remove failed: ${(err as Error).message}` }] };\n }\n },\n ),\n tool(\n 'request_secret',\n 'Ask the human for a secret value (API key, token). The value goes straight to the keychain and is never shown to you. Never ask for passwords in chat \u2014 ask for computer takeover instead.',\n { name: z.string().describe('identifier, e.g. STRIPE_API_KEY'), reason: z.string() },\n async (args: { name: string; reason: string }) => {\n this.deps.bus.publish({ type: 'secret.request', botId: bot.id, threadId, requestId: newId(), name: args.name, reason: args.reason });\n return { content: [{ type: 'text' as const, text: `Asked the human for \"${args.name}\". It will be injected into your environment as that variable name; you will never see the value. Continue once they confirm.` }] };\n },\n ),\n ],\n });\n }\n\n private postSystemCard(threadId: string, botId: string, card: Card): void {\n const msg = this.deps.store.createMessage({ threadId, authorKind: 'system', authorBotId: botId, cards: [card] });\n this.deps.bus.publish({ type: 'message.created', threadId, botId, message: msg });\n }\n\n private async execute(job: TurnJob): Promise<void> {\n const { store, bus, gateway, workspace, getSettings } = this.deps;\n const bot = store.getBot(job.botId);\n if (!bot) return;\n\n const abort = new AbortController();\n this.running.set(job.botId, { job, abort });\n this.setState(job.botId, 'running', 'none');\n\n const settings = getSettings();\n const msg = store.createMessage({\n threadId: job.threadId, authorKind: 'bot', authorBotId: bot.id, contentMd: '', streaming: true,\n });\n bus.publish({ type: 'message.created', threadId: job.threadId, botId: bot.id, message: msg });\n\n const thread = store.getThread(job.threadId);\n const isGroup = thread?.kind === 'group';\n const botDir = path.join(workspace, 'bots', bot.slug);\n fs.mkdirSync(botDir, { recursive: true });\n\n const botSkills = store.listBotSkills(bot.id);\n const connectors = await this.deps.connectorServers?.(bot.id);\n const systemPrompt = buildSystemPrompt({\n bot, workspace, skills: botSkills,\n connectors: connectors?.mounted ?? [],\n roster: store.listBots().map((x) => ({ slug: x.slug, name: x.name, title: x.title })),\n isGroup,\n });\n\n let text = '';\n let ok = true;\n let errorMessage = '';\n const toolCards = new Map<string, number>();\n\n const mcpServers: Record<string, any> = { antbot: this.buildToolServer(bot, job.threadId, job.hops) };\n const browser = this.deps.browserTools?.(bot.id);\n if (browser) mcpServers.browser = browser;\n\n\n try {\n for await (const ev of runTurn({\n prompt: job.prompt,\n resumeSessionId: bot.sessionId,\n modelTier: bot.modelTier,\n systemPrompt,\n cwd: workspace,\n // The attachments directory sits outside cwd, so the SDK would refuse to open a file the\n // human just attached even after the gateway allowed it.\n additionalDirectories: this.deps.readableRoots ?? [],\n settings,\n abortController: abort,\n mcpServers,\n // Names are validated against RESERVED_CONNECTOR_NAMES, so these cannot clobber the two\n // in-process servers above. Mounted by the runtime adapter, not here.\n connectors: connectors?.servers ?? {},\n skillPluginPath: this.deps.skillPluginPath?.(),\n // Skill names come from SKILL.md frontmatter, which is what the SDK matches on.\n enabledSkills: botSkills.map((s) => s.name),\n canUseTool: async (toolName, input) => {\n // Tools we provide ourselves are already scoped; the gateway still sees them.\n this.setState(job.botId, 'waiting_approval', 'needs_attention');\n const d = await gateway.check({\n botId: bot.id, threadId: job.threadId, toolName, input,\n botDescription: bot.description, settings, signal: abort.signal,\n workspace,\n allowedRoots: this.deps.readableRoots ?? [],\n // Render the approval inline in the transcript so the human can act on it\n // where the work is happening, not only in a global queue.\n onPending: (approval) => {\n const card: Card = { type: 'approval', approvalId: approval.id };\n const idx = store.appendCard(msg.id, card);\n bus.publish({\n type: 'message.card', threadId: job.threadId, botId: bot.id,\n messageId: msg.id, card, cardIndex: idx,\n });\n },\n });\n if (!abort.signal.aborted) this.setState(job.botId, 'running');\n return d.behavior === 'allow'\n ? { behavior: 'allow', updatedInput: input }\n : { behavior: 'deny', message: d.message };\n },\n })) {\n await this.applyEvent(ev, { job, bot, msgId: msg.id, toolCards });\n if (ev.kind === 'text' && ev.text) text += ev.text;\n if (ev.kind === 'done') {\n if (ev.text && !text.trim()) text = ev.text;\n ok = !ev.isError;\n }\n if (ev.kind === 'error') {\n ok = false;\n errorMessage = ev.message ?? 'Unknown error';\n }\n }\n } catch (err) {\n ok = false;\n errorMessage = err instanceof Error ? err.message : String(err);\n log.error('turn crashed', err);\n } finally {\n this.running.delete(job.botId);\n }\n\n if (errorMessage) {\n const idx = store.appendCard(msg.id, { type: 'error', message: errorMessage });\n bus.publish({ type: 'message.card', threadId: job.threadId, botId: bot.id, messageId: msg.id, card: { type: 'error', message: errorMessage }, cardIndex: idx });\n }\n\n const final = text.trim();\n store.updateMessage(msg.id, { contentMd: final, streaming: false });\n bus.publish({ type: 'message.done', threadId: job.threadId, botId: bot.id, messageId: msg.id, contentMd: final });\n\n const interrupted = abort.signal.aborted;\n this.setState(job.botId, interrupted ? 'interrupted' : 'idle', 'unread');\n if (interrupted) this.setState(job.botId, 'idle', 'unread');\n\n job.onDone?.(final || errorMessage, ok && !interrupted);\n void this.drain();\n }\n\n private async applyEvent(\n ev: TurnEvent,\n ctx: { job: TurnJob; bot: Bot; msgId: string; toolCards: Map<string, number> },\n ): Promise<void> {\n const { store, bus } = this.deps;\n const { job, bot, msgId, toolCards } = ctx;\n\n switch (ev.kind) {\n case 'session':\n if (ev.sessionId) store.updateBot(bot.id, { sessionId: ev.sessionId });\n break;\n\n // A connector that does not come up gives the bot no tools and no way to say why \u2014 it\n // simply behaves as though the connector were never assigned. Surfacing the SDK's own\n // verdict is the difference between \"my bot ignores my connector\" and a stated reason.\n case 'mcp_status': {\n // Persist every connector's verdict on its row \u2014 the Connectors screen shows state, and a\n // toast is gone in seconds. The two in-process servers are not rows.\n for (const m of ev.mcpStatus ?? []) {\n if (m.name === 'antbot' || m.name === 'browser') continue;\n store.setConnectorStatusByName(m.name, m.status, m.error ?? null);\n }\n const bad = (ev.mcpStatus ?? []).filter((m) => m.status !== 'connected');\n if (!bad.length) break;\n for (const m of bad) {\n log.warn(`connector \"${m.name}\" did not connect for ${bot.slug}: ${m.status}${m.error ? ` \u2014 ${m.error}` : ''}`);\n }\n bus.publish({\n type: 'notify',\n botId: bot.id,\n threadId: job.threadId,\n title: 'Connector unavailable',\n body: bad.map((m) => `${m.name}: ${describeMcpStatus(m.status)}`).join('; '),\n level: 'warn',\n });\n break;\n }\n\n // Mid-turn sign-in: the link goes into the thread as a card, where the human is looking,\n // and it persists \u2014 a toast would be gone before they came back from the browser.\n case 'signin': {\n if (!ev.signin) break;\n const card: Card = { type: 'signin', serverName: ev.signin.serverName, url: ev.signin.url };\n const idx = store.appendCard(msgId, card);\n bus.publish({ type: 'message.card', threadId: job.threadId, botId: bot.id, messageId: msgId, card, cardIndex: idx });\n store.setConnectorStatusByName(ev.signin.serverName, 'needs-sign-in', null);\n break;\n }\n\n case 'text':\n if (ev.text) {\n const cur = store.getMessage(msgId);\n store.updateMessage(msgId, { contentMd: (cur?.contentMd ?? '') + ev.text });\n bus.publish({ type: 'message.delta', threadId: job.threadId, botId: bot.id, messageId: msgId, delta: ev.text });\n }\n break;\n\n case 'tool_start': {\n const card: Card = {\n type: 'tool', toolName: ev.toolName ?? 'tool',\n summary: summarizeTool(ev.toolName ?? '', ev.toolInput),\n input: ev.toolInput, status: 'running',\n };\n const idx = store.appendCard(msgId, card);\n if (ev.toolUseId) toolCards.set(ev.toolUseId, idx);\n bus.publish({ type: 'message.card', threadId: job.threadId, botId: bot.id, messageId: msgId, card, cardIndex: idx });\n break;\n }\n\n case 'tool_result': {\n const idx = ev.toolUseId ? toolCards.get(ev.toolUseId) : undefined;\n if (idx === undefined) break;\n const cur = store.getMessage(msgId);\n const existing = cur?.cards[idx];\n if (!existing || existing.type !== 'tool') break;\n const denied = ev.isError && /denied|approval/i.test(ev.result ?? '');\n const card: Card = {\n ...existing,\n status: denied ? 'denied' : ev.isError ? 'error' : 'ok',\n result: (ev.result ?? '').slice(0, 2000),\n };\n store.updateCard(msgId, idx, card);\n bus.publish({ type: 'message.card', threadId: job.threadId, botId: bot.id, messageId: msgId, card, cardIndex: idx });\n break;\n }\n\n case 'done':\n if (ev.sessionId) store.updateBot(bot.id, { sessionId: ev.sessionId });\n if (ev.usage) {\n store.recordUsage({\n botId: bot.id, turnId: job.id, model: ev.usage.model,\n inputTokens: ev.usage.inputTokens, outputTokens: ev.usage.outputTokens,\n cacheReadTokens: ev.usage.cacheReadTokens, costEstimate: ev.usage.costUsd,\n });\n bus.publish({\n type: 'usage.tick', threadId: job.threadId, botId: bot.id,\n inputTokens: ev.usage.inputTokens, outputTokens: ev.usage.outputTokens, model: ev.usage.model,\n });\n }\n break;\n\n default:\n break;\n }\n }\n}\n\n/** Plain-language reason a connector is not usable this turn. */\nexport function describeMcpStatus(status: string): string {\n switch (status) {\n case 'needs-auth':\n return 'needs authentication \u2014 the server rejected the credentials it was given (or was given none)';\n case 'failed':\n return 'failed to start \u2014 run `antbot mcp check <name>` to see why';\n case 'pending':\n return 'did not finish connecting in time';\n case 'disabled':\n return 'is disabled';\n default:\n return status;\n }\n}\n\n/**\n * Tool arguments as `key: value`, not JSON.\n *\n * These land in an approval card and in the thread, where a raw object is noise a person has to\n * decode before deciding anything. Nested objects collapse to `{\u2026}`: naming the key is useful,\n * dumping its contents is the thing being avoided.\n */\nexport function summarizeArgs(input: unknown): string {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) return '';\n const parts: string[] = [];\n for (const [k, v] of Object.entries(input as Record<string, unknown>)) {\n if (v === undefined || v === null || v === '') continue;\n let s: string;\n if (typeof v === 'string') s = v;\n else if (typeof v === 'number' || typeof v === 'boolean') s = String(v);\n else if (Array.isArray(v)) s = `${v.length} item${v.length === 1 ? '' : 's'}`;\n else s = '{\u2026}';\n parts.push(`${k}: ${s.length > 60 ? `${s.slice(0, 60)}\u2026` : s}`);\n }\n return parts.join(', ');\n}\n\nexport function summarizeTool(name: string, input: unknown): string {\n const o = (input ?? {}) as Record<string, unknown>;\n const s = (k: string): string => (typeof o[k] === 'string' ? (o[k] as string) : '');\n if (name === 'Bash') return s('command').slice(0, 160);\n if (name === 'Read' || name === 'Write' || name === 'Edit') return s('file_path');\n if (name === 'WebFetch') return s('url');\n if (name.includes('send_to_bot')) return `\u2192 @${s('bot_slug')}`;\n if (name.includes('install_skill')) return describeSkillSource(s('source'));\n if (name.includes('remove_skill')) return `remove skill: ${s('slug')}`;\n if (name.includes('list_skills')) return 'list installed skills';\n if (name.includes('remember')) return `memory: ${s('title')}`;\n if (name.startsWith('browser_') || name.includes('browser')) return [s('url'), s('selector'), s('text')].filter(Boolean).join(' ').slice(0, 160);\n // A third-party connector's tool. Nothing is known about its arguments, but naming the server\n // and the tool beats an approval card that reads as raw JSON. Matched last so the built-in\n // servers above keep their own summaries.\n const mcp = /^mcp__([^_]+(?:_[^_]+)*)__(.+)$/.exec(name);\n if (mcp) {\n const args = summarizeArgs(input);\n return `${mcp[1]}: ${mcp[2]}${args ? ` ${args}` : ''}`.slice(0, 160);\n }\n const args = summarizeArgs(input);\n return args.length > 160 ? `${args.slice(0, 160)}\u2026` : args;\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Per-bot memory lives as markdown on the shared computer: workspace/bots/<slug>/memory/*.md */\nexport function memoryDir(workspace: string, slug: string): string {\n return path.join(workspace, 'bots', slug, 'memory');\n}\n\nexport function ensureMemoryDir(workspace: string, slug: string): string {\n const dir = memoryDir(workspace, slug);\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nexport interface MemoryFile { name: string; content: string }\n\nexport function readMemory(workspace: string, slug: string): MemoryFile[] {\n const dir = memoryDir(workspace, slug);\n if (!fs.existsSync(dir)) return [];\n return fs\n .readdirSync(dir)\n .filter((f) => f.endsWith('.md'))\n .sort()\n .map((name) => ({ name, content: fs.readFileSync(path.join(dir, name), 'utf8') }));\n}\n\nexport function writeMemory(workspace: string, slug: string, name: string, content: string): void {\n const dir = ensureMemoryDir(workspace, slug);\n const safe = name.replace(/[^a-zA-Z0-9._-]/g, '-');\n fs.writeFileSync(path.join(dir, safe.endsWith('.md') ? safe : `${safe}.md`), content);\n}\n\nexport function deleteMemory(workspace: string, slug: string, name: string): void {\n const f = path.join(memoryDir(workspace, slug), name.replace(/[^a-zA-Z0-9._-]/g, '-'));\n if (fs.existsSync(f)) fs.unlinkSync(f);\n}\n\nexport function renderMemoryBlock(files: MemoryFile[]): string {\n if (!files.length) return '';\n const body = files.map((f) => `### ${f.name}\\n${f.content.trim()}`).join('\\n\\n');\n return `\\n\\n## Your memory\\nStable preferences and facts you recorded earlier. Memory is a working\\nnote, not an authoritative source \u2014 re-check the source system before any\\nconsequential decision.\\n\\n${body}`;\n}\n", "import type { Bot, Skill } from '@antbot/contract';\nimport { readMemory, renderMemoryBlock } from '../memory/memory.js';\n\nexport interface PromptContext {\n bot: Bot;\n workspace: string;\n skills: Skill[];\n /** Connectors actually mounted this turn \u2014 a connector skipped for a missing secret is absent. */\n connectors?: { name: string; description: string }[];\n roster: Array<{ slug: string; name: string; title: string }>;\n isGroup: boolean;\n groupMembers?: string[];\n}\n\n/**\n * System prompt = base teammate persona + bot profile + memory + roster + boundaries.\n * The description carries standing rules; the conversation carries task instructions\n * (the durable/ephemeral split from outline \u00A74).\n */\nexport function buildSystemPrompt(ctx: PromptContext): string {\n const { bot, workspace } = ctx;\n const parts: string[] = [];\n\n parts.push(`You are **${bot.name}**${bot.title ? `, ${bot.title}` : ''} \u2014 a persistent AI teammate in ant-bot.\n\nYou are not a general chat assistant. You own a job and finish work end to end,\nthen report back with evidence. You keep working across turns; your files,\nmemory and browser sessions persist.`);\n\n if (bot.description.trim()) {\n parts.push(`## Your standing job description\nThese are durable rules for how you work. They outrank any single message.\n\n${bot.description.trim()}`);\n }\n\n parts.push(`## Your computer\nYou share one computer with every other bot on this account.\n- Shared workspace: \\`${workspace}\\` \u2014 keep durable project files here.\n- Your own folder: \\`${workspace}/bots/${bot.slug}/\\`\n- Files, logins and installed tools are visible to all bots. Bots are **not** a\n security boundary. Do not store anything here another bot should not see.`);\n\n const mem = renderMemoryBlock(readMemory(workspace, bot.slug));\n if (mem) parts.push(mem.trim());\n\n if (ctx.skills.length) {\n parts.push(`## Your skills\n${ctx.skills.map((s) => `- **${s.name}** (${s.slug}): ${s.description}`).join('\\n')}\nRead the skill file before following it.`);\n }\n\n if (ctx.connectors?.length) {\n parts.push(`## Your connectors\n${ctx.connectors.map((c) => `- **${c.name}**${c.description ? `: ${c.description}` : ''}`).join('\\n')}\nTheir tools appear as \\`mcp__<connector>__<tool>\\`. Prefer a connector's tools over driving the\nbrowser for the same service \u2014 it is faster, and it does not depend on a page's layout.`);\n }\n\n const others = ctx.roster.filter((r) => r.slug !== bot.slug);\n if (others.length) {\n parts.push(`## Your teammates\n${others.map((r) => `- @${r.slug} \u2014 ${r.name}${r.title ? `, ${r.title}` : ''}`).join('\\n')}\n\nUse the \\`send_to_bot\\` tool to hand work to a teammate when the job genuinely\nbelongs to their role. Keep one owner per stage \u2014 do not fan the same task out\nto several bots at once.`);\n }\n\n if (ctx.isGroup) {\n parts.push(`## Group conversation\nYou are in a group chat. Other bots can see and reply to these messages.\nAnswer only when the request is yours to own, or when you were @-mentioned.\nSay who should take the next step. Keep replies short \u2014 the humans are reading.`);\n }\n\n parts.push(`## How to work\n- Lead with the result. Put evidence \u2014 links, file paths, quoted output \u2014 under it.\n- Separate: facts found, assumptions, actions taken, actions awaiting approval,\n open questions.\n- Write deliverables as real files in the workspace, not as walls of chat text.\n- Never guess at a credential. If a step needs a password, 2FA code or CAPTCHA,\n stop and ask the human to take over the computer.\n- Some actions pause for the human's approval. That is normal \u2014 propose the\n action and wait. Approval covers only the proposed step; it does not undo\n anything you already did.`);\n\n return parts.join('\\n\\n');\n}\n", "// Turning stored connector rows into MCP server configs the Agent SDK can mount.\n//\n// Two things make this worth a module of its own. First, it is the only place a secret *value*\n// ever enters a config object \u2014 everywhere else in the system a connector carries a reference\n// (`{{secret:NAME}}`) and nothing more. Second, deciding what to mount is a decision, not an\n// action: which connectors are usable, which are missing credentials, and what the human should\n// be told. Keeping that pure means every branch is testable without a keychain or a subprocess.\nimport type { Connector, ConnectorConfig } from '@antbot/contract';\nimport type { MountedConnector } from '../agent/runtime.js';\n\n/**\n * A reference to a stored secret, embeddable inside a value: `Bearer {{secret:GH_TOKEN}}`.\n *\n * A template rather than a structured field because real credentials are usually part of a\n * larger string \u2014 an `Authorization` header is a scheme plus a token \u2014 and an object form\n * ({secret: 'NAME'}) cannot express that without inventing a concatenation syntax anyway.\n */\nexport const SECRET_REF_RE = /\\{\\{secret:([A-Za-z0-9_.-]+)\\}\\}/g;\n\n/** Every secret name referenced anywhere in a config, deduplicated, in first-seen order. */\nexport function extractSecretRefs(config: ConnectorConfig): string[] {\n const values = config.transport === 'stdio' ? Object.values(config.env) : Object.values(config.headers);\n const names: string[] = [];\n for (const v of values) {\n for (const m of v.matchAll(SECRET_REF_RE)) {\n const name = m[1]!;\n if (!names.includes(name)) names.push(name);\n }\n }\n return names;\n}\n\n/** References with nothing behind them. Drives the warning badge in the UI and the CLI listing. */\nexport function computeMissingSecrets(connector: Connector, available: ReadonlySet<string>): string[] {\n return extractSecretRefs(connector.config).filter((n) => !available.has(n));\n}\n\nexport interface MountPlan {\n mount: Connector[];\n skipped: { connector: Connector; missing: string[] }[];\n}\n\n/**\n * Decide which of a bot's connectors can actually be mounted this turn.\n *\n * A connector whose credential is missing is skipped, not fatal. Mounting it anyway would hand\n * the model a server that fails on first use with an opaque protocol error; failing the whole\n * turn would let one broken connector block work that has nothing to do with it. Skipping is the\n * only option that leaves the rest of the turn intact \u2014 and the human already had a warning on\n * the connectors screen before it came to this.\n */\nexport function planConnectorMount(assigned: Connector[], available: ReadonlySet<string>): MountPlan {\n const plan: MountPlan = { mount: [], skipped: [] };\n for (const connector of assigned) {\n const missing = computeMissingSecrets(connector, available);\n if (missing.length) plan.skipped.push({ connector, missing });\n else plan.mount.push(connector);\n }\n return plan;\n}\n\n/** Thrown when a name that was present at planning time yields nothing at resolve time. */\nexport class MissingSecretError extends Error {\n constructor(\n public connectorName: string,\n public secretName: string,\n ) {\n super(`Connector \"${connectorName}\" references secret \"${secretName}\", which could not be read.`);\n this.name = 'MissingSecretError';\n }\n}\n\nfunction substitute(value: string, connectorName: string, secrets: ReadonlyMap<string, string | null>): string {\n return value.replace(SECRET_REF_RE, (_full, name: string) => {\n const resolved = secrets.get(name);\n // Between planning and here the backend can still come up empty \u2014 a keychain that locked, a\n // secret deleted mid-turn. Throwing skips this one connector in the caller rather than\n // silently mounting it with the literal \"{{secret:NAME}}\" as its credential.\n if (resolved == null) throw new MissingSecretError(connectorName, name);\n return resolved;\n });\n}\n\nconst substituteAll = (\n record: Record<string, string>,\n connectorName: string,\n secrets: ReadonlyMap<string, string | null>,\n): Record<string, string> =>\n Object.fromEntries(Object.entries(record).map(([k, v]) => [k, substitute(v, connectorName, secrets)]));\n\n/**\n * The SDK config for one connector, with secret references replaced by their values.\n *\n * The returned object is the only representation that holds real credentials. It goes straight\n * into the turn's `mcpServers` map and is never persisted, logged, or returned by a route.\n * Runtime-neutral: this is ant-bot's own shape, and the agent runtime's adapter translates it.\n */\nexport function buildMcpServerConfig(\n connector: Connector,\n secrets: ReadonlyMap<string, string | null>,\n): MountedConnector {\n const c = connector.config;\n if (c.transport === 'stdio') {\n return {\n type: 'stdio',\n command: c.command,\n args: c.args,\n env: substituteAll(c.env, connector.name, secrets),\n };\n }\n return {\n type: c.transport,\n url: c.url,\n headers: substituteAll(c.headers, connector.name, secrets),\n ...(c.tools ? { tools: c.tools } : {}),\n };\n}\n", "// The connector sign-in flow: discovery, an authorize URL for the human, the callback, and the\n// token refresh that keeps a signed-in connector working afterwards.\n//\n// Tokens live in the same keychain as every other secret and never touch the database or any\n// route response \u2014 the same rule the `{{secret:NAME}}` references follow. What is stored is one\n// JSON blob per connector, because a refresh needs the client id, the token endpoint and the\n// resource alongside the tokens themselves.\nimport crypto from 'node:crypto';\nimport type { Connector } from '@antbot/contract';\nimport { logger } from '../util/log.js';\nimport {\n discoverAuth, registerClient, exchangeCode, refreshTokens, createPkce, buildAuthorizeUrl,\n needsRefresh, OAuthError, type StoredTokens, type DiscoveryResult,\n} from './oauth.js';\n\nconst log = logger('connector-auth');\n\n/** Keychain key for one connector's tokens. Namespaced so it cannot collide with a user secret. */\nexport const tokenSecretName = (connectorName: string): string => `antbot:oauth:${connectorName}`;\n\n/**\n * Keychain key for a connector's OAuth client credentials.\n *\n * Kept separate from the tokens because it outlives them: a client id and secret are registered\n * once with the provider, while tokens come and go. Storing them means a second `login` \u2014 after\n * an expiry, a revocation, or a failed first attempt \u2014 does not ask for them again.\n */\nexport const clientSecretName = (connectorName: string): string => `antbot:oauth-client:${connectorName}`;\n\ninterface ClientCredentials {\n clientId: string;\n clientSecret?: string;\n}\n\n/** Where the authorization server sends the human back. Must be registered with the provider. */\nexport const redirectUri = (port: number): string => `http://127.0.0.1:${port}/api/connectors/oauth/callback`;\n\ninterface PendingLogin {\n connectorId: string;\n connectorName: string;\n verifier: string;\n clientId: string;\n clientSecret?: string;\n tokenEndpoint: string;\n resource?: string;\n redirectUri: string;\n startedAt: number;\n}\n\n/** Minimal secrets surface, so this module is testable without a keychain. */\nexport interface TokenStore {\n set(name: string, value: string): Promise<void>;\n remove(name: string): Promise<void>;\n resolve(names: string[]): Promise<Map<string, string | null>>;\n list(): string[];\n}\n\n/** A sign-in that has been started and is waiting for the human to come back. */\nconst LOGIN_TTL_MS = 10 * 60 * 1000;\n\nexport class ConnectorAuthService {\n private readonly pending = new Map<string, PendingLogin>();\n\n constructor(\n private readonly secrets: TokenStore,\n /** Read lazily: the listening port is settled after this service is built. */\n private readonly portOf: () => number,\n ) {}\n private get port(): number {\n return this.portOf();\n }\n\n /** Has this connector been signed in? Names only \u2014 never reads a value to answer. */\n isAuthorized(connectorName: string): boolean {\n return this.secrets.list().includes(tokenSecretName(connectorName));\n }\n\n private async read(connectorName: string): Promise<StoredTokens | null> {\n const key = tokenSecretName(connectorName);\n const found = (await this.secrets.resolve([key])).get(key);\n if (!found) return null;\n try {\n return JSON.parse(found) as StoredTokens;\n } catch {\n // A corrupt blob is the same as not signed in; the human can sign in again.\n log.warn(`stored tokens for \"${connectorName}\" are unreadable`);\n return null;\n }\n }\n\n private async write(connectorName: string, tokens: StoredTokens): Promise<void> {\n await this.secrets.set(tokenSecretName(connectorName), JSON.stringify(tokens));\n }\n\n async signOut(connectorName: string): Promise<void> {\n await this.secrets.remove(tokenSecretName(connectorName));\n }\n\n /** Forget the tokens *and* the registered client. Used when the credentials themselves are wrong. */\n async forgetClient(connectorName: string): Promise<void> {\n await this.secrets.remove(clientSecretName(connectorName));\n }\n\n private async readClient(clientKey: string): Promise<ClientCredentials | null> {\n const key = clientSecretName(clientKey);\n const found = (await this.secrets.resolve([key])).get(key);\n if (!found) return null;\n try {\n return JSON.parse(found) as ClientCredentials;\n } catch {\n return null;\n }\n }\n\n /**\n * Begin a sign-in. Returns the URL the human must open.\n *\n * `clientId` is required only when the authorization server does not support dynamic client\n * registration \u2014 Google being the notable case, where the human supplies one from their own\n * cloud console. Everything else registers ant-bot automatically.\n */\n async beginLogin(\n connector: Connector,\n opts: { clientId?: string; clientSecret?: string; scopes?: string[] } = {},\n ): Promise<{ authorizeUrl: string; discovery: DiscoveryResult }> {\n if (connector.config.transport === 'stdio') {\n throw new OAuthError('Sign-in applies to http and sse connectors; a stdio server takes its credentials in env.');\n }\n const discovery = await discoverAuth(connector.config.url);\n const authorizeUrl = await this.beginLoginWith(\n {\n connectorId: connector.id,\n connectorName: connector.name,\n clientKey: connector.name,\n authorizationEndpoint: discovery.authServer.authorizationEndpoint,\n tokenEndpoint: discovery.authServer.tokenEndpoint,\n registrationEndpoint: discovery.authServer.registrationEndpoint,\n resource: discovery.resource.resource,\n scopes: opts.scopes?.length ? opts.scopes : discovery.resource.scopesSupported,\n // Without these Google issues no refresh token, and the connector dies in an hour. Harmless\n // for providers that ignore them.\n extras: { access_type: 'offline', prompt: 'consent' },\n },\n opts,\n );\n return { authorizeUrl, discovery };\n }\n\n /**\n * Begin a sign-in against a known authorization server. Used directly by built-in connectors,\n * whose provider endpoints are fixed and whose client credentials are shared under one\n * `clientKey` \u2014 one Google client serves Gmail, Calendar and Drive.\n */\n async beginLoginWith(\n target: {\n connectorId: string;\n connectorName: string;\n clientKey: string;\n authorizationEndpoint: string;\n tokenEndpoint: string;\n registrationEndpoint?: string;\n resource?: string;\n scopes: string[];\n extras?: Record<string, string>;\n /** Shown when a client ID is needed and none is known. */\n providerName?: string;\n },\n opts: { clientId?: string; clientSecret?: string } = {},\n ): Promise<string> {\n const redirect = redirectUri(this.port);\n\n // Given now, else remembered from last time, else registered automatically. The remembered\n // path is what makes a retry after a failed exchange painless.\n const remembered = await this.readClient(target.clientKey);\n let clientId = opts.clientId ?? remembered?.clientId;\n let clientSecret = opts.clientSecret ?? (opts.clientId ? undefined : remembered?.clientSecret);\n if (!clientId && target.registrationEndpoint) {\n const registered = await registerClient(target.registrationEndpoint, redirect);\n clientId = registered?.clientId;\n clientSecret = registered?.clientSecret;\n }\n if (!clientId) {\n const who = target.providerName ?? new URL(target.authorizationEndpoint).host;\n throw new OAuthError(\n `${who} does not support automatic app registration, so it needs a client ID you create yourself. ` +\n `Register one with that provider, add \"${redirect}\" as an authorised redirect URI, and pass the client ID with --client-id.`,\n );\n }\n\n // Remember before sending the human to the provider, so a failed exchange does not lose them.\n if (opts.clientId || opts.clientSecret || !remembered) {\n await this.secrets.set(clientSecretName(target.clientKey), JSON.stringify({ clientId, clientSecret }));\n }\n\n const pkce = createPkce();\n const state = crypto.randomBytes(16).toString('base64url');\n this.pending.set(state, {\n connectorId: target.connectorId,\n connectorName: target.connectorName,\n verifier: pkce.verifier,\n clientId,\n clientSecret,\n tokenEndpoint: target.tokenEndpoint,\n resource: target.resource,\n redirectUri: redirect,\n startedAt: Date.now(),\n });\n this.sweep();\n\n return buildAuthorizeUrl({\n authorizationEndpoint: target.authorizationEndpoint,\n clientId,\n redirectUri: redirect,\n scopes: target.scopes,\n state,\n challenge: pkce.challenge,\n resource: target.resource,\n extra: target.extras,\n });\n }\n\n /** Whether client credentials are on file for a key (a connector name or a provider key). */\n hasClient(clientKey: string): boolean {\n return this.secrets.list().includes(clientSecretName(clientKey));\n }\n\n /** Finish a sign-in from the redirect. Returns the connector that was authorised. */\n async completeLogin(state: string, code: string): Promise<{ connectorId: string; connectorName: string }> {\n const p = this.pending.get(state);\n // Unknown state is the CSRF guard: a callback we did not start is not ours to act on.\n if (!p) throw new OAuthError('This sign-in link is no longer valid. Start the sign-in again.');\n this.pending.delete(state);\n\n let tokens;\n try {\n tokens = await exchangeCode({\n tokenEndpoint: p.tokenEndpoint,\n code,\n verifier: p.verifier,\n clientId: p.clientId,\n clientSecret: p.clientSecret,\n redirectUri: p.redirectUri,\n resource: p.resource,\n });\n } catch (err) {\n const message = (err as Error).message;\n // Google's \"Web application\" client type authenticates at the token endpoint, so the id\n // alone is not enough. Its own wording does not say what to do about it.\n if (/client_secret/i.test(message)) {\n throw new OAuthError(\n 'This provider requires a client secret as well as a client ID. Add the secret from the ' +\n \"same OAuth client (in Google's console: the client's \\\"Client secret\\\") and sign in again.\",\n );\n }\n throw err;\n }\n await this.write(p.connectorName, tokens);\n log.info(`connector \"${p.connectorName}\" signed in`);\n return { connectorId: p.connectorId, connectorName: p.connectorName };\n }\n\n /**\n * The Authorization header for a mounted connector, refreshing first if the token is close to\n * expiry. Returns null when the connector was never signed in, which is not an error \u2014 most\n * connectors use a static credential or none.\n */\n async authHeader(connectorName: string): Promise<Record<string, string> | null> {\n let tokens = await this.read(connectorName);\n if (!tokens) return null;\n if (needsRefresh(tokens, Date.now())) {\n try {\n tokens = await refreshTokens(tokens);\n await this.write(connectorName, tokens);\n } catch (err) {\n // Refusing to mount beats mounting with a token known to be expired: the failure is\n // reported once, here, instead of as an opaque 401 in the middle of a bot's work.\n log.warn(`could not refresh tokens for \"${connectorName}\": ${(err as Error).message}`);\n return null;\n }\n }\n return { Authorization: `Bearer ${tokens.accessToken}` };\n }\n\n private sweep(): void {\n const cutoff = Date.now() - LOGIN_TTL_MS;\n for (const [state, p] of this.pending) if (p.startedAt < cutoff) this.pending.delete(state);\n }\n}\n", "// OAuth for MCP servers, owned by ant-bot rather than borrowed from the `claude` CLI.\n//\n// Many useful MCP servers will not take a static token in a header \u2014 they want an interactive\n// sign-in. Without this, those servers can be registered, assigned, and still hand a bot nothing.\n//\n// The flow is the one the MCP spec adopts: RFC 9728 discovery from the server's own 401, then\n// OAuth 2.1 authorization-code with PKCE against whatever authorization server it names.\n//\n// Two paths, because the field is split:\n// - the server's authorization server supports RFC 7591 dynamic client registration, and\n// ant-bot registers itself; or\n// - it does not (Google, notably), and the human supplies a client id from their own console.\n//\n// Pure parsing and URL building live at the top and are tested without a network; the I/O below\n// is a thin shell over them.\nimport crypto from 'node:crypto';\n\n/** What a server's 401 points at, per RFC 9728. */\nexport function parseResourceMetadataUrl(wwwAuthenticate: string | null): string | null {\n if (!wwwAuthenticate) return null;\n const m = /resource_metadata\\s*=\\s*\"([^\"]+)\"/i.exec(wwwAuthenticate);\n return m ? m[1]! : null;\n}\n\nexport interface ProtectedResourceMetadata {\n authorizationServers: string[];\n scopesSupported: string[];\n resource?: string;\n}\n\nexport function parseProtectedResourceMetadata(body: unknown): ProtectedResourceMetadata | null {\n const b = body as Record<string, unknown> | null;\n const servers = b?.authorization_servers;\n if (!Array.isArray(servers) || servers.length === 0) return null;\n return {\n authorizationServers: servers.map(String),\n scopesSupported: Array.isArray(b?.scopes_supported) ? (b!.scopes_supported as unknown[]).map(String) : [],\n resource: typeof b?.resource === 'string' ? b.resource : undefined,\n };\n}\n\nexport interface AuthServerMetadata {\n authorizationEndpoint: string;\n tokenEndpoint: string;\n registrationEndpoint?: string;\n scopesSupported: string[];\n}\n\nexport function parseAuthServerMetadata(body: unknown): AuthServerMetadata | null {\n const b = body as Record<string, unknown> | null;\n const auth = b?.authorization_endpoint;\n const token = b?.token_endpoint;\n if (typeof auth !== 'string' || typeof token !== 'string') return null;\n return {\n authorizationEndpoint: auth,\n tokenEndpoint: token,\n registrationEndpoint: typeof b?.registration_endpoint === 'string' ? b.registration_endpoint : undefined,\n scopesSupported: Array.isArray(b?.scopes_supported) ? (b!.scopes_supported as unknown[]).map(String) : [],\n };\n}\n\n/** The well-known locations an authorization server's metadata may live at, most specific first. */\nexport function authServerMetadataUrls(issuer: string): string[] {\n const u = new URL(issuer);\n const path = u.pathname.replace(/\\/$/, '');\n const base = `${u.protocol}//${u.host}`;\n return [\n `${base}/.well-known/oauth-authorization-server${path}`,\n `${base}/.well-known/openid-configuration${path}`,\n `${base}${path}/.well-known/oauth-authorization-server`,\n `${base}${path}/.well-known/openid-configuration`,\n ];\n}\n\nexport interface Pkce {\n verifier: string;\n challenge: string;\n}\n\n/** RFC 7636 S256. The verifier never leaves the daemon; only its hash goes in the URL. */\nexport function createPkce(): Pkce {\n const verifier = crypto.randomBytes(32).toString('base64url');\n const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');\n return { verifier, challenge };\n}\n\nexport interface AuthorizeUrlInput {\n authorizationEndpoint: string;\n clientId: string;\n redirectUri: string;\n scopes: string[];\n state: string;\n challenge: string;\n /** RFC 8707 \u2014 binds the token to this MCP server so it cannot be replayed elsewhere. */\n resource?: string;\n /** Google needs these to return a refresh token at all. */\n extra?: Record<string, string>;\n}\n\nexport function buildAuthorizeUrl(i: AuthorizeUrlInput): string {\n const u = new URL(i.authorizationEndpoint);\n const p = u.searchParams;\n p.set('response_type', 'code');\n p.set('client_id', i.clientId);\n p.set('redirect_uri', i.redirectUri);\n p.set('state', i.state);\n p.set('code_challenge', i.challenge);\n p.set('code_challenge_method', 'S256');\n if (i.scopes.length) p.set('scope', i.scopes.join(' '));\n if (i.resource) p.set('resource', i.resource);\n for (const [k, v] of Object.entries(i.extra ?? {})) p.set(k, v);\n return u.toString();\n}\n\nexport interface StoredTokens {\n accessToken: string;\n refreshToken?: string;\n /** Epoch ms. Absent when the server did not say, in which case we do not pre-emptively refresh. */\n expiresAt?: number;\n scope?: string;\n tokenEndpoint: string;\n clientId: string;\n clientSecret?: string;\n resource?: string;\n}\n\n/** Parse a token endpoint response into what we store. `now` is injected so expiry is testable. */\nexport function parseTokenResponse(\n body: unknown,\n ctx: { tokenEndpoint: string; clientId: string; clientSecret?: string; resource?: string; previousRefresh?: string },\n now: number,\n): StoredTokens | null {\n const b = body as Record<string, unknown> | null;\n if (typeof b?.access_token !== 'string') return null;\n const expiresIn = typeof b.expires_in === 'number' ? b.expires_in : undefined;\n return {\n accessToken: b.access_token,\n // A refresh response often omits refresh_token, meaning \"keep using the one you have\".\n refreshToken: typeof b.refresh_token === 'string' ? b.refresh_token : ctx.previousRefresh,\n expiresAt: expiresIn ? now + expiresIn * 1000 : undefined,\n scope: typeof b.scope === 'string' ? b.scope : undefined,\n tokenEndpoint: ctx.tokenEndpoint,\n clientId: ctx.clientId,\n clientSecret: ctx.clientSecret,\n resource: ctx.resource,\n };\n}\n\n/**\n * Whether a token should be refreshed before use.\n *\n * The skew matters: a token that expires during the turn it was checked for is worse than one\n * refreshed a minute early, because the failure surfaces as an opaque 401 mid-task.\n */\nexport function needsRefresh(tokens: StoredTokens, now: number, skewMs = 60_000): boolean {\n if (!tokens.expiresAt) return false;\n return now + skewMs >= tokens.expiresAt;\n}\n\n/* --------------------------------- I/O shell --------------------------------- */\n\nconst JSON_HEADERS = { accept: 'application/json' };\nconst FETCH_TIMEOUT_MS = 15_000;\n\nasync function getJson(url: string): Promise<unknown | null> {\n try {\n const res = await fetch(url, { headers: JSON_HEADERS, signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n return res.ok ? await res.json() : null;\n } catch {\n return null;\n }\n}\n\nexport class OAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OAuthError';\n }\n}\n\nexport interface DiscoveryResult {\n resource: ProtectedResourceMetadata;\n authServer: AuthServerMetadata;\n}\n\n/**\n * Where a server's protected-resource metadata might be, most authoritative first.\n *\n * RFC 9728 forms the URL by inserting the well-known segment *before the resource path*, which\n * is what makes candidate 2 the standard one. The hint from `WWW-Authenticate` is tried first\n * because a server is allowed to put it anywhere \u2014 but it is not always usable: Google answers a\n * `tools/call` challenge with a metadata URL scoped to the tool that was called, so probing with\n * a name that does not exist yields a hint that 404s. Falling through to the standard location\n * covers that without ever invoking one of the server's real tools.\n */\nexport function resourceMetadataCandidates(mcpUrl: string, wwwAuthenticate: string | null): string[] {\n const u = new URL(mcpUrl);\n const path = u.pathname.replace(/\\/$/, '');\n const out: string[] = [];\n const hint = parseResourceMetadataUrl(wwwAuthenticate);\n if (hint) out.push(hint);\n out.push(`${u.origin}/.well-known/oauth-protected-resource${path}`);\n out.push(`${u.origin}/.well-known/oauth-protected-resource`);\n return [...new Set(out)];\n}\n\nasync function firstResourceMetadata(\n mcpUrl: string,\n wwwAuthenticate: string | null,\n): Promise<ProtectedResourceMetadata | null> {\n for (const url of resourceMetadataCandidates(mcpUrl, wwwAuthenticate)) {\n const meta = parseProtectedResourceMetadata(await getJson(url));\n if (meta) return meta;\n }\n return null;\n}\n\n/**\n * Ask the server itself what it wants, starting from its 401.\n *\n * A `tools/call` rather than `initialize`, because servers commonly answer the handshake to\n * anyone and only challenge on real work \u2014 which is exactly the case that made a connector look\n * healthy while giving a bot nothing.\n */\nexport async function discoverAuth(mcpUrl: string, headers: Record<string, string> = {}): Promise<DiscoveryResult> {\n let challenge: string | null;\n try {\n const res = await fetch(mcpUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'application/json, text/event-stream', ...headers },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: '__antbot_auth_probe__', arguments: {} } }),\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n challenge = res.headers.get('www-authenticate');\n } catch (err) {\n throw new OAuthError(`Could not reach ${mcpUrl}: ${(err as Error).message}`);\n }\n\n const found = await firstResourceMetadata(mcpUrl, challenge);\n if (!found) {\n throw new OAuthError(\n 'This server did not advertise an authorization server, so ant-bot cannot sign in to it. ' +\n 'If it takes a static token, add one as an Authorization header instead.',\n );\n }\n\n const resourceMeta = found;\n for (const issuer of resourceMeta.authorizationServers) {\n for (const url of authServerMetadataUrls(issuer)) {\n const meta = parseAuthServerMetadata(await getJson(url));\n if (meta) return { resource: resourceMeta, authServer: meta };\n }\n }\n throw new OAuthError(`Could not read authorization server metadata for ${resourceMeta.authorizationServers.join(', ')}`);\n}\n\n/** RFC 7591. Returns null when the authorization server does not offer registration. */\nexport async function registerClient(\n registrationEndpoint: string,\n redirectUri: string,\n): Promise<{ clientId: string; clientSecret?: string } | null> {\n try {\n const res = await fetch(registrationEndpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...JSON_HEADERS },\n body: JSON.stringify({\n client_name: 'ant-bot',\n redirect_uris: [redirectUri],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n }),\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n if (!res.ok) return null;\n const b = (await res.json()) as Record<string, unknown>;\n return typeof b.client_id === 'string'\n ? { clientId: b.client_id, clientSecret: typeof b.client_secret === 'string' ? b.client_secret : undefined }\n : null;\n } catch {\n return null;\n }\n}\n\nasync function postForm(endpoint: string, form: Record<string, string>): Promise<unknown> {\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', ...JSON_HEADERS },\n body: new URLSearchParams(form).toString(),\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n const body = await res.json().catch(() => null);\n if (!res.ok) {\n const e = body as Record<string, unknown> | null;\n throw new OAuthError(String(e?.error_description ?? e?.error ?? `token endpoint returned HTTP ${res.status}`));\n }\n return body;\n}\n\nexport async function exchangeCode(input: {\n tokenEndpoint: string;\n code: string;\n verifier: string;\n clientId: string;\n clientSecret?: string;\n redirectUri: string;\n resource?: string;\n now?: number;\n}): Promise<StoredTokens> {\n const body = await postForm(input.tokenEndpoint, {\n grant_type: 'authorization_code',\n code: input.code,\n code_verifier: input.verifier,\n client_id: input.clientId,\n redirect_uri: input.redirectUri,\n ...(input.clientSecret ? { client_secret: input.clientSecret } : {}),\n ...(input.resource ? { resource: input.resource } : {}),\n });\n const tokens = parseTokenResponse(body, input, input.now ?? Date.now());\n if (!tokens) throw new OAuthError('The authorization server did not return an access token.');\n return tokens;\n}\n\nexport async function refreshTokens(tokens: StoredTokens, now = Date.now()): Promise<StoredTokens> {\n if (!tokens.refreshToken) throw new OAuthError('No refresh token \u2014 sign in again.');\n const body = await postForm(tokens.tokenEndpoint, {\n grant_type: 'refresh_token',\n refresh_token: tokens.refreshToken,\n client_id: tokens.clientId,\n ...(tokens.clientSecret ? { client_secret: tokens.clientSecret } : {}),\n ...(tokens.resource ? { resource: tokens.resource } : {}),\n });\n const next = parseTokenResponse(body, { ...tokens, previousRefresh: tokens.refreshToken }, now);\n if (!next) throw new OAuthError('The authorization server did not return a refreshed access token.');\n return next;\n}\n", "// Serves ant-bot's built-in connectors and holds the only thing that can reach their tokens.\n//\n// The agent runtime mounts a built-in connector as an ordinary http MCP server pointing back at\n// the daemon (`/mcp/<name>`). The provider token never travels: the runtime gets a per-boot bearer\n// for the daemon's own endpoint, and the daemon exchanges that for the provider's credential at\n// call time. Restarting the daemon rotates the bearer, so a value that leaked into a transcript\n// or a log is dead by the next boot.\nimport crypto from 'node:crypto';\nimport type { Connector } from '@antbot/contract';\nimport type { MountedConnector } from '../../agent/runtime.js';\nimport type { ConnectorAuthService } from '../auth.js';\nimport { BUILTIN_CATALOG, type BuiltinConnector } from './catalog.js';\nimport { handleMcpRequest, type JsonRpcResponse } from './mcpServer.js';\n\nexport class BuiltinService {\n /** Rotates every boot. Checked on every `/mcp/<name>` request. */\n readonly bearer = crypto.randomBytes(24).toString('base64url');\n\n constructor(\n private readonly auth: ConnectorAuthService | undefined,\n private readonly portOf: () => number,\n private readonly version: string,\n ) {}\n private get port(): number {\n return this.portOf();\n }\n\n get(name: string): BuiltinConnector | undefined {\n return BUILTIN_CATALOG[name];\n }\n\n /** The config a built-in connector's row stores: the daemon's own endpoint, nothing secret. */\n rowConfig(name: string): Connector['config'] {\n return { transport: 'http', url: `http://127.0.0.1:${this.port}/mcp/${name}`, headers: {} };\n }\n\n /** What actually gets mounted: the row's config plus this boot's bearer. */\n mountConfig(connector: Connector): MountedConnector {\n return {\n type: 'http',\n url: `http://127.0.0.1:${this.port}/mcp/${connector.name}`,\n headers: { Authorization: `Bearer ${this.bearer}` },\n };\n }\n\n authorized(name: string): boolean {\n return this.auth?.isAuthorized(name) ?? false;\n }\n\n /** Constant-time compare so the bearer cannot be guessed a byte at a time. */\n checkBearer(header: string | undefined): boolean {\n const given = (header ?? '').replace(/^Bearer\\s+/i, '');\n const a = Buffer.from(given);\n const b = Buffer.from(this.bearer);\n return a.length === b.length && crypto.timingSafeEqual(a, b);\n }\n\n /** Serve one MCP request for a built-in connector. */\n async handle(name: string, body: unknown): Promise<JsonRpcResponse | null> {\n const def = this.get(name);\n if (!def) return { jsonrpc: '2.0', id: null, error: { code: -32601, message: `No built-in connector named ${name}` } };\n return handleMcpRequest(body, { name: def.name, version: this.version, tools: def.tools() }, async () => {\n const hdr = await this.auth?.authHeader(name);\n if (!hdr) {\n throw new Error(\n `${def.displayName} is not signed in. Sign in on the Connectors screen or with \\`antbot mcp login ${name}\\`.`,\n );\n }\n return { accessToken: hdr.Authorization.replace(/^Bearer\\s+/, '') };\n });\n }\n\n /** Start the provider sign-in for a built-in connector. Returns the URL to open. */\n async beginLogin(connector: Connector, opts: { clientId?: string; clientSecret?: string } = {}): Promise<string> {\n const def = this.get(connector.name);\n if (!def) throw new Error(`No built-in connector named ${connector.name}`);\n if (!this.auth) throw new Error('Secrets backend unavailable, so a sign-in cannot be stored.');\n const p = def.provider;\n return this.auth.beginLoginWith(\n {\n connectorId: connector.id,\n connectorName: connector.name,\n clientKey: p.key,\n authorizationEndpoint: p.authorizationEndpoint,\n tokenEndpoint: p.tokenEndpoint,\n scopes: def.scopes,\n extras: p.authorizeExtras,\n providerName: p.displayName,\n },\n opts,\n );\n }\n}\n", "// Gmail as an ant-bot built-in connector: six tools, each a thin call to Gmail's REST API.\n//\n// Narrow on purpose. The goal is a bot that can read a mailbox and draft a reply, not a complete\n// Gmail client; every tool here maps to one documented REST call, and `fetch` is injected so the\n// whole file is testable against a fake server.\nimport { z } from 'zod';\nimport { toolError, toolText, type BuiltinTool, type ToolContext, type ToolResult } from './mcpServer.js';\n\nconst API = 'https://gmail.googleapis.com/gmail/v1/users/me';\n\nexport type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;\n\n/** One Gmail REST call with the bearer applied; a non-2xx becomes a readable tool error. */\nasync function gmail(\n fetchFn: FetchLike,\n ctx: ToolContext,\n path: string,\n init: RequestInit = {},\n): Promise<{ ok: true; body: any } | { ok: false; error: string }> {\n const res = await fetchFn(`${API}${path}`, {\n ...init,\n headers: { Authorization: `Bearer ${ctx.accessToken}`, 'content-type': 'application/json', ...(init.headers ?? {}) },\n });\n const text = await res.text();\n let body: any = null;\n try { body = text ? JSON.parse(text) : null; } catch { /* non-JSON error page */ }\n if (!res.ok) {\n const msg = body?.error?.message ?? `HTTP ${res.status}`;\n // 401/403 nearly always mean the sign-in is gone or lacks a scope; say what to do.\n const hint = res.status === 401 || res.status === 403 ? ' \u2014 sign in to the gmail connector again' : '';\n return { ok: false, error: `Gmail: ${msg}${hint}` };\n }\n return { ok: true, body };\n}\n\n/** Pull the readable headers and a plain-text body out of a Gmail message resource. */\nexport function summarizeMessage(m: any): Record<string, unknown> {\n const headers: Record<string, string> = {};\n for (const h of m?.payload?.headers ?? []) {\n const k = String(h.name).toLowerCase();\n if (['from', 'to', 'cc', 'subject', 'date'].includes(k)) headers[k] = String(h.value);\n }\n return {\n id: m?.id,\n threadId: m?.threadId,\n labelIds: m?.labelIds ?? [],\n snippet: m?.snippet ?? '',\n ...headers,\n body: extractText(m?.payload) ?? '',\n };\n}\n\n/** Prefer text/plain; fall back to stripping tags from text/html. Walks multipart recursively. */\nexport function extractText(payload: any): string | null {\n if (!payload) return null;\n const decode = (data: string): string => Buffer.from(data.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8');\n if (payload.mimeType === 'text/plain' && payload.body?.data) return decode(payload.body.data);\n if (Array.isArray(payload.parts)) {\n for (const p of payload.parts) {\n const t = extractText(p);\n if (t) return t;\n }\n }\n if (payload.mimeType === 'text/html' && payload.body?.data) {\n return decode(payload.body.data).replace(/<style[\\s\\S]*?<\\/style>/gi, '').replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ').trim();\n }\n return null;\n}\n\n/** RFC 822 message, base64url-encoded the way the API wants `raw`. */\nexport function buildRawMessage(m: { to: string; subject: string; body: string; cc?: string; inReplyTo?: string }): string {\n const lines = [\n `To: ${m.to}`,\n ...(m.cc ? [`Cc: ${m.cc}`] : []),\n `Subject: ${m.subject}`,\n ...(m.inReplyTo ? [`In-Reply-To: ${m.inReplyTo}`, `References: ${m.inReplyTo}`] : []),\n 'Content-Type: text/plain; charset=utf-8',\n 'MIME-Version: 1.0',\n '',\n m.body,\n ];\n return Buffer.from(lines.join('\\r\\n'), 'utf8').toString('base64url');\n}\n\nconst json = (v: unknown): ToolResult => toolText(JSON.stringify(v, null, 2));\n\nexport function gmailTools(fetchFn: FetchLike = fetch): BuiltinTool<any>[] {\n return [\n {\n name: 'search_threads',\n description:\n 'Search the mailbox with Gmail query syntax (e.g. \"is:unread\", \"from:alice newer_than:7d\"). Returns thread ids with a snippet of the latest message.',\n inputSchema: {\n type: 'object',\n properties: { query: { type: 'string' }, maxResults: { type: 'integer', minimum: 1, maximum: 50 } },\n required: ['query'],\n },\n parse: z.object({ query: z.string().min(1), maxResults: z.number().int().min(1).max(50).default(10) }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, `/threads?q=${encodeURIComponent(a.query)}&maxResults=${a.maxResults}`);\n if (!r.ok) return toolError(r.error);\n return json({ threads: (r.body.threads ?? []).map((t: any) => ({ id: t.id, snippet: t.snippet })), estimate: r.body.resultSizeEstimate });\n },\n },\n {\n name: 'get_thread',\n description: 'Read every message in a thread: from, to, subject, date and a plain-text body.',\n inputSchema: { type: 'object', properties: { threadId: { type: 'string' } }, required: ['threadId'] },\n parse: z.object({ threadId: z.string().min(1) }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, `/threads/${encodeURIComponent(a.threadId)}?format=full`);\n if (!r.ok) return toolError(r.error);\n return json({ id: r.body.id, messages: (r.body.messages ?? []).map(summarizeMessage) });\n },\n },\n {\n name: 'get_message',\n description: 'Read one message by id.',\n inputSchema: { type: 'object', properties: { messageId: { type: 'string' } }, required: ['messageId'] },\n parse: z.object({ messageId: z.string().min(1) }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, `/messages/${encodeURIComponent(a.messageId)}?format=full`);\n if (!r.ok) return toolError(r.error);\n return json(summarizeMessage(r.body));\n },\n },\n {\n name: 'list_labels',\n description: 'List the mailbox labels (INBOX, SENT, user labels\u2026) with their ids.',\n inputSchema: { type: 'object', properties: {} },\n parse: z.object({}),\n handler: async (_a, ctx) => {\n const r = await gmail(fetchFn, ctx, '/labels');\n if (!r.ok) return toolError(r.error);\n return json({ labels: (r.body.labels ?? []).map((l: any) => ({ id: l.id, name: l.name, type: l.type })) });\n },\n },\n {\n name: 'create_draft',\n description: 'Create a draft email. Nothing is sent. Set inReplyTo to a message id to draft a reply in that thread.',\n inputSchema: {\n type: 'object',\n properties: { to: { type: 'string' }, subject: { type: 'string' }, body: { type: 'string' }, cc: { type: 'string' }, inReplyTo: { type: 'string' } },\n required: ['to', 'subject', 'body'],\n },\n parse: z.object({ to: z.string().min(1), subject: z.string(), body: z.string(), cc: z.string().optional(), inReplyTo: z.string().optional() }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, '/drafts', { method: 'POST', body: JSON.stringify({ message: { raw: buildRawMessage(a) } }) });\n if (!r.ok) return toolError(r.error);\n return json({ draftId: r.body.id, messageId: r.body.message?.id });\n },\n },\n {\n name: 'send_message',\n description: 'Send an email immediately. This is consequential and asks the human for approval.',\n inputSchema: {\n type: 'object',\n properties: { to: { type: 'string' }, subject: { type: 'string' }, body: { type: 'string' }, cc: { type: 'string' }, inReplyTo: { type: 'string' } },\n required: ['to', 'subject', 'body'],\n },\n parse: z.object({ to: z.string().min(1), subject: z.string(), body: z.string(), cc: z.string().optional(), inReplyTo: z.string().optional() }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, '/messages/send', { method: 'POST', body: JSON.stringify({ raw: buildRawMessage(a) }) });\n if (!r.ok) return toolError(r.error);\n return json({ sent: true, messageId: r.body.id, threadId: r.body.threadId });\n },\n },\n ];\n}\n", "// A minimal MCP server, served by the daemon itself over streamable HTTP.\n//\n// This exists because some providers refuse every MCP client except their own allowlisted ones,\n// which makes a self-contained ant-bot unable to use their MCP endpoint no matter how it signs in.\n// The provider's plain REST API has no such rule. So ant-bot serves the connector: an MCP server\n// whose tools are thin calls to that REST API, with the token held by the daemon and never handed\n// to the agent runtime.\n//\n// Pure: `handleMcpRequest` maps one JSON-RPC request to one response with no I/O of its own. Tool\n// handlers do the I/O, and they are injected. That is what makes the protocol layer testable\n// against ant-bot's own probe client without a network.\nimport type { ZodType } from 'zod';\n\n/** The MCP protocol revision this server speaks. Newer clients negotiate down; older ones match. */\nexport const MCP_PROTOCOL_VERSION = '2025-06-18';\n\nexport interface ToolContext {\n /** A bearer for the provider's API, refreshed by the daemon before the call. */\n accessToken: string;\n}\n\nexport interface BuiltinTool<A = unknown> {\n name: string;\n description: string;\n /** JSON Schema, as the client expects it. */\n inputSchema: Record<string, unknown>;\n /** Validates and types the arguments before the handler sees them. */\n parse: ZodType<A>;\n handler: (args: A, ctx: ToolContext) => Promise<ToolResult>;\n}\n\nexport interface ToolResult {\n content: { type: 'text'; text: string }[];\n isError?: boolean;\n}\n\ninterface JsonRpcRequest {\n jsonrpc?: string;\n id?: string | number | null;\n method?: string;\n params?: Record<string, unknown>;\n}\n\nexport interface JsonRpcResponse {\n jsonrpc: '2.0';\n id: string | number | null;\n result?: unknown;\n error?: { code: number; message: string };\n}\n\n/** JSON-RPC 2.0 error codes the server uses. */\nexport const RPC = {\n PARSE_ERROR: -32700,\n INVALID_REQUEST: -32600,\n METHOD_NOT_FOUND: -32601,\n INVALID_PARAMS: -32602,\n} as const;\n\nconst err = (id: string | number | null, code: number, message: string): JsonRpcResponse =>\n ({ jsonrpc: '2.0', id, error: { code, message } });\nconst ok = (id: string | number | null, result: unknown): JsonRpcResponse => ({ jsonrpc: '2.0', id, result });\n\n/** Text a tool returns when the provider call itself fails; never the raw response body. */\nexport const toolError = (text: string): ToolResult => ({ content: [{ type: 'text', text }], isError: true });\nexport const toolText = (text: string): ToolResult => ({ content: [{ type: 'text', text }] });\n\n/**\n * Handle one request. Returns null for a notification (no id), which the HTTP layer answers with\n * 202 and no body, as the transport requires.\n */\nexport async function handleMcpRequest(\n body: unknown,\n server: { name: string; version: string; tools: BuiltinTool[] },\n ctx: () => Promise<ToolContext>,\n): Promise<JsonRpcResponse | null> {\n const req = body as JsonRpcRequest | null;\n if (!req || typeof req !== 'object' || req.jsonrpc !== '2.0' || typeof req.method !== 'string') {\n return err(null, RPC.INVALID_REQUEST, 'Expected a JSON-RPC 2.0 request');\n }\n const id = req.id ?? null;\n // Notifications carry no id and get no reply.\n if (req.id === undefined) return null;\n\n switch (req.method) {\n case 'initialize': {\n const asked = String(req.params?.protocolVersion ?? MCP_PROTOCOL_VERSION);\n return ok(id, {\n // Echo the client's version when it is one we can serve; the surface is small enough that\n // every revision since 2024-11-05 is compatible for these three methods.\n protocolVersion: asked,\n capabilities: { tools: {} },\n serverInfo: { name: server.name, version: server.version },\n });\n }\n case 'ping':\n return ok(id, {});\n case 'tools/list':\n return ok(id, {\n tools: server.tools.map((t) => ({ name: t.name, description: t.description, inputSchema: t.inputSchema })),\n });\n case 'tools/call': {\n const name = String(req.params?.name ?? '');\n const tool = server.tools.find((t) => t.name === name);\n if (!tool) return err(id, RPC.INVALID_PARAMS, `Unknown tool: ${name}`);\n const parsed = tool.parse.safeParse(req.params?.arguments ?? {});\n if (!parsed.success) {\n return err(id, RPC.INVALID_PARAMS, `Invalid arguments for ${name}: ${parsed.error.issues[0]?.message ?? 'invalid'}`);\n }\n let context: ToolContext;\n try {\n context = await ctx();\n } catch (e) {\n // Not signed in, or the token could not be refreshed. A tool error rather than an RPC\n // error, so the model reads a sentence instead of a code.\n return ok(id, toolError((e as Error).message));\n }\n try {\n return ok(id, await tool.handler(parsed.data, context));\n } catch (e) {\n return ok(id, toolError(`${name} failed: ${(e as Error).message}`));\n }\n }\n default:\n return err(id, RPC.METHOD_NOT_FOUND, `Method not supported: ${req.method}`);\n }\n}\n", "// The connectors ant-bot ships. `antbot mcp add gmail` with no command or URL resolves here.\n//\n// Each entry carries everything the guided setup needs to say, so the instructions live next to\n// the code that depends on them rather than in prose that drifts. Google's endpoints are fixed\n// and documented; hard-coding them removes a network round trip from a flow that already has\n// enough of them, and means the sign-in works even when discovery would not.\nimport { gmailTools, type FetchLike } from './gmail.js';\nimport type { BuiltinTool } from './mcpServer.js';\n\nexport interface Provider {\n /** Shared client-credential key: one Google client serves Gmail, Calendar and Drive. */\n key: string;\n displayName: string;\n authorizationEndpoint: string;\n tokenEndpoint: string;\n /** Provider-specific authorize params. Google needs these to issue a refresh token at all. */\n authorizeExtras: Record<string, string>;\n /** Whether the provider lets an app register itself. Google does not. */\n dynamicRegistration: boolean;\n /** Numbered steps shown when a client ID is needed. `{redirectUri}` is substituted. */\n setupSteps: string[];\n}\n\nexport const GOOGLE: Provider = {\n key: 'google',\n displayName: 'Google',\n authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenEndpoint: 'https://oauth2.googleapis.com/token',\n authorizeExtras: { access_type: 'offline', prompt: 'consent' },\n dynamicRegistration: false,\n setupSteps: [\n 'Open console.cloud.google.com \u2192 APIs & Services \u2192 Credentials \u2192 Create credentials \u2192 OAuth client ID.',\n 'Application type: Web application. Under \"Authorised redirect URIs\" add exactly: {redirectUri}',\n 'Enable the Gmail API for the project (APIs & Services \u2192 Library).',\n 'Copy the Client ID and Client secret it shows you. One client works for every Google connector.',\n ],\n};\n\nexport interface BuiltinConnector {\n name: string;\n displayName: string;\n description: string;\n provider: Provider;\n scopes: string[];\n tools: (fetchFn?: FetchLike) => BuiltinTool[];\n}\n\nexport const BUILTIN_CATALOG: Record<string, BuiltinConnector> = {\n gmail: {\n name: 'gmail',\n displayName: 'Gmail',\n description: 'Read, search and draft email in the signed-in Gmail account.',\n provider: GOOGLE,\n // modify covers read + draft + send; asking for less means a second consent screen later.\n scopes: ['https://www.googleapis.com/auth/gmail.modify'],\n tools: gmailTools,\n },\n};\n\nexport const isBuiltinName = (name: string): boolean => name in BUILTIN_CATALOG;\n\n/**\n * The built-in to use instead, when a custom connector signs in at a provider whose own MCP\n * endpoint refuses third-party clients. Matched on the authorization host: a Google sign-in is\n * a Google sign-in whatever URL sits behind it.\n */\nexport function builtinAlternativeFor(authorizationHost: string): string | undefined {\n for (const [name, def] of Object.entries(BUILTIN_CATALOG)) {\n if (new URL(def.provider.authorizationEndpoint).host === authorizationHost && !def.provider.dynamicRegistration) return name;\n }\n return undefined;\n}\n", "// A minimal MCP client, used only to answer \"does this connector work, and what does it offer?\"\n//\n// Advisory, never in the turn path: the Agent SDK does the real mounting. That is what makes a\n// hand-rolled client acceptable here rather than a liability \u2014 if the protocol drifts, `antbot\n// connector test` gets less useful, and nothing a bot depends on breaks. The alternative,\n// depending on @modelcontextprotocol/sdk purely for a diagnostic, is a lot of surface for that.\n//\n// Everything is best-effort and bounded: any failure becomes `{ ok: false, error }`, and the\n// child is always killed.\nimport { spawn } from 'node:child_process';\nimport { logger } from '../util/log.js';\n\nconst log = logger('mcp-probe');\n\n/** The version we ask for; a server that prefers another one is free to say so and we accept it. */\nconst PROTOCOL_VERSION = '2025-06-18';\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport interface ProbeTool {\n name: string;\n description: string;\n}\n\nexport interface ProbeResult {\n ok: boolean;\n tools: ProbeTool[];\n error?: string;\n}\n\n/** Tool descriptions can be enormous; a diagnostic listing does not need all of it. */\nconst MAX_DESCRIPTION = 200;\n\n/** Pull the tool list out of a `tools/list` result, tolerating a server that omits fields. */\nexport function parseToolsResult(result: unknown): ProbeTool[] {\n const tools = (result as { tools?: unknown })?.tools;\n if (!Array.isArray(tools)) return [];\n return tools\n .filter((t): t is Record<string, unknown> => typeof t === 'object' && t !== null)\n .map((t) => ({\n name: String(t.name ?? ''),\n description: String(t.description ?? '').slice(0, MAX_DESCRIPTION),\n }))\n .filter((t) => t.name.length > 0);\n}\n\nconst rpc = (id: number, method: string, params?: unknown): string =>\n `${JSON.stringify({ jsonrpc: '2.0', id, method, ...(params ? { params } : {}) })}\\n`;\n\nconst notify = (method: string): string => `${JSON.stringify({ jsonrpc: '2.0', method })}\\n`;\n\nconst failed = (error: string): ProbeResult => ({ ok: false, tools: [], error });\n\n/** stdio: spawn the server and speak newline-delimited JSON-RPC on its pipes. */\nasync function probeStdio(\n cfg: { command: string; args?: string[]; env?: Record<string, string> },\n timeoutMs: number,\n): Promise<ProbeResult> {\n return new Promise<ProbeResult>((resolve) => {\n let child: ReturnType<typeof spawn>;\n try {\n child = spawn(cfg.command, cfg.args ?? [], {\n // The server's own env plus the connector's \u2014 a connector that needs PATH still gets it.\n env: { ...process.env, ...(cfg.env ?? {}) },\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n } catch (err) {\n return resolve(failed((err as Error).message));\n }\n\n let settled = false;\n let stderr = '';\n let buffer = '';\n const finish = (r: ProbeResult): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n // Always kill: a server that never answers must not outlive the probe.\n try { child.kill('SIGKILL'); } catch { /* already gone */ }\n resolve(r);\n };\n\n const timer = setTimeout(\n () => finish(failed(`timed out after ${timeoutMs}ms${stderr ? `: ${stderr.trim().slice(0, 200)}` : ''}`)),\n timeoutMs,\n );\n\n child.on('error', (err) => finish(failed(err.message)));\n child.on('exit', (code) =>\n finish(failed(`server exited with code ${code}${stderr ? `: ${stderr.trim().slice(0, 200)}` : ''}`)),\n );\n child.stderr?.on('data', (d: Buffer) => { stderr += d.toString(); });\n\n child.stdout?.on('data', (d: Buffer) => {\n buffer += d.toString();\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.trim()) continue;\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(line) as Record<string, unknown>;\n } catch {\n continue; // servers do print the occasional stray line on stdout\n }\n if (msg.id === 1) {\n // Initialized; ask for the tools.\n try {\n child.stdin?.write(notify('notifications/initialized'));\n child.stdin?.write(rpc(2, 'tools/list'));\n } catch (err) {\n finish(failed((err as Error).message));\n }\n } else if (msg.id === 2) {\n if (msg.error) return finish(failed(JSON.stringify(msg.error).slice(0, 200)));\n finish({ ok: true, tools: parseToolsResult(msg.result) });\n }\n }\n });\n\n try {\n child.stdin?.write(\n rpc(1, 'initialize', {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: 'ant-bot', version: '1.0.0' },\n }),\n );\n } catch (err) {\n finish(failed((err as Error).message));\n }\n });\n}\n\n/** Streamable HTTP: POST the same handshake, carrying the session id the server hands back. */\nasync function probeHttp(\n cfg: { url: string; headers?: Record<string, string> },\n timeoutMs: number,\n): Promise<ProbeResult> {\n const ac = new AbortController();\n const timer = setTimeout(() => ac.abort(), timeoutMs);\n const base = {\n 'content-type': 'application/json',\n accept: 'application/json, text/event-stream',\n ...(cfg.headers ?? {}),\n };\n\n // A streamable-HTTP server may answer with an SSE frame even for a single call.\n const readBody = async (res: Response): Promise<unknown> => {\n const text = await res.text();\n const line = text.split('\\n').find((l) => l.startsWith('data:'));\n try {\n return JSON.parse(line ? line.slice(5).trim() : text);\n } catch {\n return null;\n }\n };\n\n try {\n const initRes = await fetch(cfg.url, {\n method: 'POST', signal: ac.signal, headers: base,\n body: rpc(1, 'initialize', {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: 'ant-bot', version: '1.0.0' },\n }),\n });\n if (!initRes.ok) return failed(`initialize returned HTTP ${initRes.status}`);\n const session = initRes.headers.get('mcp-session-id');\n const withSession = session ? { ...base, 'mcp-session-id': session } : base;\n await readBody(initRes);\n\n await fetch(cfg.url, { method: 'POST', signal: ac.signal, headers: withSession, body: notify('notifications/initialized') })\n .catch(() => undefined); // some servers 202 or close this; not fatal\n\n const listRes = await fetch(cfg.url, {\n method: 'POST', signal: ac.signal, headers: withSession, body: rpc(2, 'tools/list'),\n });\n if (!listRes.ok) return failed(`tools/list returned HTTP ${listRes.status}`);\n const body = await readBody(listRes) as { result?: unknown; error?: unknown } | null;\n if (body?.error) return failed(JSON.stringify(body.error).slice(0, 200));\n return { ok: true, tools: parseToolsResult(body?.result) };\n } catch (err) {\n const e = err as Error;\n return failed(e.name === 'AbortError' ? `timed out after ${timeoutMs}ms` : e.message);\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Connect to a connector's server and list its tools.\n *\n * Takes the already-substituted SDK config, so a caller must resolve secrets first \u2014 the probe\n * has no access to the keychain and no business holding one.\n */\nexport async function probeConnector(\n config: Record<string, unknown>,\n opts: { timeoutMs?: number } = {},\n): Promise<ProbeResult> {\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const type = config.type as string | undefined;\n try {\n if (type === 'stdio') {\n return await probeStdio(config as { command: string; args?: string[]; env?: Record<string, string> }, timeoutMs);\n }\n if (type === 'http') {\n // Reachable is all this says. Whether a call would be *allowed* is `check.ts`'s question,\n // answered by a tools/call challenge \u2014 many servers list their tools to anyone.\n return await probeHttp(config as { url: string; headers?: Record<string, string> }, timeoutMs);\n }\n // SSE needs a persistent event stream and a separate POST endpoint the server advertises at\n // runtime \u2014 more client than a diagnostic justifies. Assign it and run a turn instead.\n if (type === 'sse') return failed('testing is not supported for sse connectors \u2014 assign it to a bot and run a turn');\n return failed(`unknown transport: ${String(type)}`);\n } catch (err) {\n log.warn('probe threw', err);\n return failed((err as Error).message);\n }\n}\n", "// One honest verdict on a connector, replacing `test` and the guesswork around it.\n//\n// `tools/list` is the wrong question: servers answer it to anyone and refuse the first real\n// call, which is how a connector looked healthy while giving a bot nothing. The auth verdict here\n// comes from a deliberately failing `tools/call` \u2014 what `discoverAuth` already does \u2014 and the\n// tool list is attached only once the server has been reached. Pure decision at the top, thin\n// I/O below, so every verdict is testable without a network.\nimport type { Connector, ConnectorCheck } from '@antbot/contract';\nimport { builtinAlternativeFor } from './builtin/catalog.js';\nimport { discoverAuth, OAuthError, type DiscoveryResult } from './oauth.js';\nimport { probeConnector, type ProbeResult } from '../bots/mcpProbe.js';\nimport type { MountedConnector } from '../agent/runtime.js';\n\nexport interface CheckSignals {\n /** The probe result, when the server was reachable enough to run it. */\n probe: ProbeResult | null;\n /** What a real call provoked: nothing, or an auth challenge (with discovery), or a hard failure. */\n challenge: 'none' | 'auth' | 'unreachable';\n discovery?: DiscoveryResult | null;\n /** For built-ins: whether the daemon holds a sign-in already. */\n builtinSignedIn?: boolean;\n builtinProvider?: { name: string; dynamicRegistration: boolean };\n /** Missing `{{secret:\u2026}}` references, if any. */\n missingSecrets: string[];\n}\n\n/** Pure: signals in, verdict out. */\nexport function decideCheck(signals: CheckSignals): ConnectorCheck {\n if (signals.builtinProvider) {\n return signals.builtinSignedIn\n ? { status: 'ready', tools: signals.probe?.tools ?? [], provider: signals.builtinProvider.name }\n : {\n status: 'needs-sign-in',\n selfRegistration: signals.builtinProvider.dynamicRegistration,\n provider: signals.builtinProvider.name,\n tools: signals.probe?.tools ?? [],\n };\n }\n if (signals.missingSecrets.length) {\n return { status: 'needs-credential', tools: [], detail: `missing secret(s): ${signals.missingSecrets.join(', ')}` };\n }\n if (signals.challenge === 'auth') {\n const as = signals.discovery?.authServer;\n const host = as ? new URL(as.authorizationEndpoint).host : undefined;\n // Google's own MCP endpoint admits only clients Google allowlisted: the sign-in succeeds and\n // every call is then refused with \"The caller does not have permission\". Saying so here is\n // the difference between a dead end and the one command that works.\n const alternative = host ? builtinAlternativeFor(host) : undefined;\n return {\n status: 'needs-sign-in',\n selfRegistration: Boolean(as?.registrationEndpoint),\n provider: host,\n tools: signals.probe?.tools ?? [],\n ...(alternative\n ? {\n alternative,\n detail: `${host} does not accept third-party MCP clients here, so a sign-in would not help. Use the built-in instead: antbot mcp add ${alternative}`,\n }\n : {}),\n };\n }\n if (signals.challenge === 'unreachable' || (signals.probe && !signals.probe.ok)) {\n return { status: 'unreachable', tools: [], detail: signals.probe?.error };\n }\n return { status: 'ready', tools: signals.probe?.tools ?? [] };\n}\n\n/**\n * Gather the signals for a custom connector. `mounted` is the already-substituted config (so a\n * static header credential is exercised), which the caller builds \u2014 this module never touches the\n * keychain.\n */\nexport async function gatherCustomSignals(\n connector: Connector,\n mounted: MountedConnector | null,\n missingSecrets: string[],\n): Promise<CheckSignals> {\n if (missingSecrets.length || !mounted) return { probe: null, challenge: 'none', missingSecrets };\n const probe = await probeConnector(mounted as unknown as Record<string, unknown>, { timeoutMs: 8000 });\n if (mounted.type === 'stdio') return { probe, challenge: probe.ok ? 'none' : 'unreachable', missingSecrets };\n if (!probe.ok) return { probe, challenge: 'unreachable', missingSecrets };\n // Reachable. Now the question that matters: does it accept us? A real call, with whatever\n // headers the config carries, either passes or provokes the 401 discovery starts from.\n try {\n const discovery = await discoverAuth(mounted.url, mounted.headers);\n return { probe, challenge: 'auth', discovery, missingSecrets };\n } catch (err) {\n // discoverAuth throws when the server did NOT challenge (no 401 to follow) \u2014 that is success \u2014\n // or when it challenged but named no authorization server, which is still \"needs sign-in\".\n const msg = (err as Error).message;\n if (err instanceof OAuthError && /did not advertise an authorization server/.test(msg)) {\n return { probe, challenge: 'auth', discovery: null, missingSecrets };\n }\n return { probe, challenge: 'none', missingSecrets };\n }\n}\n", "import fs from 'node:fs';\nimport { parse as parseToml, stringify as stringifyToml } from 'smol-toml';\nimport { SettingsSchema, type Settings } from '@antbot/contract';\nimport { resolvePaths, ensureDirs, type AntbotPaths } from './paths.js';\n\nexport interface AntbotConfig {\n paths: AntbotPaths;\n settings: Settings;\n port: number;\n host: string;\n}\n\nexport const DEFAULT_PORT = 4780;\nexport const DEFAULT_HOST = '127.0.0.1';\n\nexport function loadConfig(root?: string): AntbotConfig {\n const paths = resolvePaths(root);\n ensureDirs(paths);\n\n let raw: Record<string, unknown> = {};\n if (fs.existsSync(paths.config)) {\n try {\n raw = parseToml(fs.readFileSync(paths.config, 'utf8')) as Record<string, unknown>;\n } catch {\n raw = {};\n }\n }\n const server = (raw.server ?? {}) as Record<string, unknown>;\n const settings = SettingsSchema.parse({\n ...(typeof raw.settings === 'object' && raw.settings ? raw.settings : {}),\n timezone:\n (raw.settings as Record<string, unknown> | undefined)?.timezone ??\n Intl.DateTimeFormat().resolvedOptions().timeZone ??\n 'UTC',\n });\n\n const cfg: AntbotConfig = {\n paths,\n settings,\n port: Number(process.env.ANTBOT_PORT ?? server.port ?? DEFAULT_PORT),\n host: String(server.host ?? DEFAULT_HOST),\n };\n if (!fs.existsSync(paths.config)) writeConfig(cfg);\n return cfg;\n}\n\nexport function writeConfig(cfg: AntbotConfig): void {\n fs.writeFileSync(\n cfg.paths.config,\n stringifyToml({ server: { port: cfg.port, host: cfg.host }, settings: cfg.settings as unknown as Record<string, unknown> }),\n );\n}\n", "import os from 'node:os';\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nexport interface AntbotPaths {\n root: string;\n db: string;\n config: string;\n workspace: string;\n attachments: string;\n skills: string;\n browserProfile: string;\n backups: string;\n secrets: string;\n logs: string;\n}\n\nexport function resolvePaths(root?: string): AntbotPaths {\n const base = root ?? process.env.ANTBOT_HOME ?? path.join(os.homedir(), '.ant-bot');\n return {\n root: base,\n db: path.join(base, 'antbot.db'),\n config: path.join(base, 'config.toml'),\n workspace: path.join(base, 'workspace'),\n attachments: path.join(base, 'attachments'),\n skills: path.join(base, 'skills'),\n browserProfile: path.join(base, 'browser-profile'),\n backups: path.join(base, 'backups'),\n secrets: path.join(base, 'secrets.json'),\n logs: path.join(base, 'logs'),\n };\n}\n\nexport function ensureDirs(p: AntbotPaths): void {\n for (const d of [p.root, p.workspace, p.attachments, p.skills, p.backups, p.logs,\n path.join(p.workspace, 'projects'), path.join(p.workspace, 'bots')]) {\n fs.mkdirSync(d, { recursive: true });\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { logger } from '../util/log.js';\n\nconst exec = promisify(execFile);\nconst log = logger('secrets');\n\nexport interface SecretBackend {\n readonly name: string;\n set(key: string, value: string): Promise<void>;\n get(key: string): Promise<string | null>;\n delete(key: string): Promise<void>;\n list(): Promise<string[]>;\n}\n\nconst SERVICE = 'ant-bot';\n\n/** libsecret on Linux via `secret-tool`. */\nclass SecretToolBackend implements SecretBackend {\n readonly name = 'libsecret (secret-tool)';\n async set(key: string, value: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const p = execFile('secret-tool', ['store', '--label', `${SERVICE}: ${key}`, 'service', SERVICE, 'account', key],\n (err) => (err ? reject(err) : resolve()));\n p.stdin?.end(value);\n });\n }\n async get(key: string): Promise<string | null> {\n try {\n const { stdout } = await exec('secret-tool', ['lookup', 'service', SERVICE, 'account', key]);\n return stdout;\n } catch {\n return null;\n }\n }\n async delete(key: string): Promise<void> {\n try { await exec('secret-tool', ['clear', 'service', SERVICE, 'account', key]); } catch { /* absent */ }\n }\n async list(): Promise<string[]> { return []; } // secret-tool has no reliable enumeration\n}\n\n/** macOS Keychain via `security`. */\nclass MacKeychainBackend implements SecretBackend {\n readonly name = 'macOS Keychain';\n async set(key: string, value: string): Promise<void> {\n await exec('security', ['add-generic-password', '-U', '-s', SERVICE, '-a', key, '-w', value]);\n }\n async get(key: string): Promise<string | null> {\n try {\n const { stdout } = await exec('security', ['find-generic-password', '-s', SERVICE, '-a', key, '-w']);\n return stdout.replace(/\\n$/, '');\n } catch {\n return null;\n }\n }\n async delete(key: string): Promise<void> {\n try { await exec('security', ['delete-generic-password', '-s', SERVICE, '-a', key]); } catch { /* absent */ }\n }\n async list(): Promise<string[]> { return []; }\n}\n\n/**\n * Encrypted-file fallback. Explicitly weaker than an OS keychain: the key is derived\n * from a machine-local file with 0600 permissions, so anything running as this user\n * can read it. Surfaced in the UI as such.\n */\nexport class EncryptedFileBackend implements SecretBackend {\n readonly name = 'encrypted file (weaker than a system keychain)';\n private keyFile: string;\n constructor(private file: string) {\n this.keyFile = `${file}.key`;\n }\n private key(): Buffer {\n if (!fs.existsSync(this.keyFile)) {\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\n fs.writeFileSync(this.keyFile, crypto.randomBytes(32), { mode: 0o600 });\n }\n return fs.readFileSync(this.keyFile);\n }\n private read(): Record<string, string> {\n if (!fs.existsSync(this.file)) return {};\n try {\n const raw = JSON.parse(fs.readFileSync(this.file, 'utf8')) as Record<string, { iv: string; tag: string; data: string }>;\n const key = this.key();\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(raw)) {\n const d = crypto.createDecipheriv('aes-256-gcm', key, Buffer.from(v.iv, 'base64'));\n d.setAuthTag(Buffer.from(v.tag, 'base64'));\n out[k] = Buffer.concat([d.update(Buffer.from(v.data, 'base64')), d.final()]).toString('utf8');\n }\n return out;\n } catch {\n return {};\n }\n }\n private write(values: Record<string, string>): void {\n const key = this.key();\n const out: Record<string, { iv: string; tag: string; data: string }> = {};\n for (const [k, v] of Object.entries(values)) {\n const iv = crypto.randomBytes(12);\n const c = crypto.createCipheriv('aes-256-gcm', key, iv);\n const data = Buffer.concat([c.update(v, 'utf8'), c.final()]);\n out[k] = { iv: iv.toString('base64'), tag: c.getAuthTag().toString('base64'), data: data.toString('base64') };\n }\n fs.mkdirSync(path.dirname(this.file), { recursive: true });\n fs.writeFileSync(this.file, JSON.stringify(out), { mode: 0o600 });\n }\n async set(key: string, value: string): Promise<void> { const v = this.read(); v[key] = value; this.write(v); }\n async get(key: string): Promise<string | null> { return this.read()[key] ?? null; }\n async delete(key: string): Promise<void> { const v = this.read(); delete v[key]; this.write(v); }\n async list(): Promise<string[]> { return Object.keys(this.read()); }\n}\n\nexport async function pickBackend(fallbackFile: string): Promise<SecretBackend> {\n const has = async (bin: string, args: string[]): Promise<boolean> => {\n try { await exec(bin, args); return true; } catch (err) {\n return (err as { code?: string }).code !== 'ENOENT';\n }\n };\n if (process.platform === 'darwin' && (await has('security', ['-h']))) return new MacKeychainBackend();\n if (process.platform === 'linux' && (await has('secret-tool', ['--version']))) return new SecretToolBackend();\n log.warn('no system keychain available; using the encrypted-file fallback');\n return new EncryptedFileBackend(fallbackFile);\n}\n\n/**\n * Secrets are stored by NAME only in the index; values live in the backend and are\n * injected into tool environments. A value is never written to the transcript and is\n * never placed in the model's context (outline \u00A75, \"secure secret request\").\n */\nexport class SecretsService {\n private names = new Set<string>();\n constructor(\n private backend: SecretBackend,\n private indexFile: string,\n ) {\n if (fs.existsSync(indexFile)) {\n try { this.names = new Set(JSON.parse(fs.readFileSync(indexFile, 'utf8')) as string[]); } catch { /* ignore */ }\n }\n }\n private persist(): void {\n fs.mkdirSync(path.dirname(this.indexFile), { recursive: true });\n fs.writeFileSync(this.indexFile, JSON.stringify([...this.names]), { mode: 0o600 });\n }\n get backendName(): string { return this.backend.name; }\n async set(name: string, value: string): Promise<void> {\n await this.backend.set(name, value);\n this.names.add(name);\n this.persist();\n }\n async remove(name: string): Promise<void> {\n await this.backend.delete(name);\n this.names.delete(name);\n this.persist();\n }\n /** Names only \u2014 values are never returned to the API surface. */\n list(): string[] { return [...this.names]; }\n /**\n * Look up exactly the named secrets, for mounting a connector.\n *\n * Scoped on purpose. The unscoped `envOverlay()` below hands every stored secret to whatever\n * asks; a connector should only ever see the ones its own config references, so that adding a\n * third-party MCP server does not widen the blast radius of every other credential.\n *\n * A name with nothing behind it maps to null rather than being dropped, so the caller can tell\n * \"missing\" from \"empty string\" and skip the connector instead of mounting it half-configured.\n */\n async resolve(names: string[]): Promise<Map<string, string | null>> {\n const out = new Map<string, string | null>();\n for (const n of new Set(names)) {\n out.set(n, this.names.has(n) ? await this.backend.get(n) : null);\n }\n return out;\n }\n\n /**\n * Build an env overlay for a tool subprocess. Values never touch the transcript.\n *\n * Unused, and unscoped \u2014 it returns every secret at once. `resolve()` above is what connectors\n * use. Kept only because removing it is a separate decision; do not reach for it.\n */\n async envOverlay(): Promise<Record<string, string>> {\n const out: Record<string, string> = {};\n for (const n of this.names) {\n const v = await this.backend.get(n);\n if (v !== null) out[n] = v;\n }\n return out;\n }\n}\n", "import { query } from '@anthropic-ai/claude-agent-sdk';\nimport { buildEnv } from '../agent/session.js';\nimport type { Settings, Bot } from '@antbot/contract';\nimport { logger } from '../util/log.js';\n\nconst log = logger('groups');\n\n/**\n * Pick which bots should answer a group message.\n * Explicit @-mentions always win; otherwise a cheap Haiku pass routes it.\n * Falls back to the first member so a group is never silent.\n */\nexport async function routeGroupMessage(args: {\n text: string;\n members: Bot[];\n mentionBotIds?: string[];\n mentionEveryone?: boolean;\n settings: Settings;\n cwd: string;\n}): Promise<Bot[]> {\n const { text, members, mentionBotIds, mentionEveryone, settings, cwd } = args;\n if (mentionEveryone) return members;\n if (mentionBotIds?.length) {\n const picked = members.filter((m) => mentionBotIds.includes(m.id));\n if (picked.length) return picked;\n }\n\n const inline = members.filter((m) => new RegExp(`@${m.slug}\\\\b`, 'i').test(text));\n if (inline.length) return inline;\n\n try {\n const roster = members.map((m) => `- ${m.slug}: ${m.name}${m.title ? `, ${m.title}` : ''}. ${m.description.slice(0, 200)}`).join('\\n');\n const q = query({\n prompt: `Team:\\n${roster}\\n\\nMessage:\\n${text.slice(0, 2000)}\\n\\nWhich single teammate should own this? Reply with only the slug.`,\n options: {\n model: 'haiku',\n systemPrompt: 'You route work to the right teammate. Reply with exactly one slug from the list and nothing else.',\n cwd, settingSources: [], env: buildEnv(settings), maxTurns: 1, allowedTools: [],\n },\n });\n let out = '';\n for await (const m of q) {\n const msg = m as Record<string, any>;\n if (msg.type === 'result' && typeof msg.result === 'string') out = msg.result;\n }\n const slug = out.trim().toLowerCase().replace(/[^a-z0-9-]/g, '');\n const found = members.find((m) => m.slug === slug);\n if (found) return [found];\n } catch (err) {\n log.warn('group router failed; defaulting to first member', err);\n }\n return members.slice(0, 1);\n}\n\n/** Extract @slug mentions from raw composer text. */\nexport function parseMentions(text: string, members: Bot[]): { botIds: string[]; everyone: boolean } {\n const everyone = /@everyone\\b/i.test(text);\n const botIds = members.filter((m) => new RegExp(`@${m.slug}\\\\b`, 'i').test(text)).map((m) => m.id);\n return { botIds, everyone };\n}\n", "import type { FastifyInstance } from 'fastify';\nimport type { App } from '../app.js';\nimport {\n CreateBotRequest, UpdateBotRequest, CreateThreadRequest, PostMessageRequest,\n LimitError, type RosterEntry, type ThreadWithMessages,\n} from '@antbot/contract';\nimport { routeGroupMessage, parseMentions } from '../bots/groups.js';\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { readPackageVersion } from '../util/locate.js';\nimport { readMemory, writeMemory, deleteMemory } from '../memory/memory.js';\n\n// Read from package.json rather than hardcoded, so a release bump cannot leave /api/health\n// claiming a version the CLI disagrees with.\nexport const SERVER_VERSION = readPackageVersion(\n path.dirname(fileURLToPath(import.meta.url)),\n (p) => fs.existsSync(p),\n (p) => fs.readFileSync(p, 'utf8'),\n);\n\nexport function registerCoreRoutes(f: FastifyInstance, app: App): void {\n const { store, bus, manager } = app;\n\n f.get('/api/health', async () => ({\n ok: true,\n seq: bus.currentSeq,\n version: SERVER_VERSION,\n bots: store.listBots().length,\n }));\n\n /* ------------------------------- bots ------------------------------- */\n f.get('/api/bots', async (): Promise<RosterEntry[]> =>\n store.listBots().map((bot) => ({\n bot,\n thread: bot.threadId ? store.getThread(bot.threadId) : null,\n lastMessageAt: bot.threadId ? store.lastMessageAt(bot.threadId) : 0,\n })),\n );\n\n f.post('/api/bots', async (req, reply) => {\n const parsed = CreateBotRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: parsed.error.issues[0]?.message ?? 'Invalid body' });\n try {\n return store.createBot(parsed.data);\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.get<{ Params: { id: string } }>('/api/bots/:id', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n return bot ?? reply.code(404).send({ error: 'No such bot' });\n });\n\n f.patch<{ Params: { id: string } }>('/api/bots/:id', async (req, reply) => {\n const parsed = UpdateBotRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n const bot = store.updateBot(req.params.id, parsed.data);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n bus.publish({ type: 'bot.state', botId: bot.id, threadId: bot.threadId, state: bot.state, attention: bot.attention });\n return bot;\n });\n\n f.delete<{ Params: { id: string } }>('/api/bots/:id', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n manager.interrupt(req.params.id);\n store.deleteBot(req.params.id);\n return { ok: true };\n });\n\n /**\n * Start a fresh conversation: clears the thread and the SDK session, keeps the bot.\n *\n * Refused while the bot is working \u2014 resetting the session mid-turn would leave the running\n * turn writing into a message that no longer exists.\n */\n f.post<{ Params: { id: string } }>('/api/bots/:id/reset', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n if (bot.state === 'running' || bot.state === 'queued') {\n return reply.code(409).send({ error: 'This bot is working. Stop it first, then start fresh.' });\n }\n const result = store.resetBotSession(bot.id);\n if (!result) return reply.code(404).send({ error: 'No such bot' });\n if (bot.threadId) bus.publish({ type: 'thread.updated', threadId: bot.threadId, botId: bot.id, threadId2: bot.threadId });\n return { ok: true, ...result };\n });\n\n f.post<{ Params: { id: string } }>('/api/bots/:id/duplicate', async (req, reply) => {\n try {\n const copy = store.duplicateBot(req.params.id);\n return copy ?? reply.code(404).send({ error: 'No such bot' });\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.post<{ Params: { id: string } }>('/api/bots/:id/stop', async (req) => ({\n stopped: manager.interrupt(req.params.id),\n }));\n\n /* ------------------------------ memory ------------------------------ */\n f.get<{ Params: { id: string } }>('/api/bots/:id/memory', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n return readMemory(app.cfg.paths.workspace, bot.slug);\n });\n\n f.put<{ Params: { id: string }; Body: { name: string; content: string } }>('/api/bots/:id/memory', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n const { name, content } = req.body ?? {};\n if (!name || typeof content !== 'string') return reply.code(400).send({ error: 'name and content are required' });\n writeMemory(app.cfg.paths.workspace, bot.slug, name, content);\n return { ok: true };\n });\n\n f.delete<{ Params: { id: string; name: string } }>('/api/bots/:id/memory/:name', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n deleteMemory(app.cfg.paths.workspace, bot.slug, req.params.name);\n return { ok: true };\n });\n\n f.get<{ Params: { id: string } }>('/api/bots/:id/skills', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n return store.listBotSkills(req.params.id);\n });\n\n f.put<{ Params: { id: string }; Body: { skillIds: string[] } }>('/api/bots/:id/skills', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n store.setBotSkills(req.params.id, req.body?.skillIds ?? []);\n return { ok: true };\n });\n\n f.get<{ Params: { id: string } }>('/api/bots/:id/connectors', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n return store.listBotConnectors(req.params.id);\n });\n\n f.put<{ Params: { id: string }; Body: { connectorIds: string[] } }>('/api/bots/:id/connectors', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n store.setBotConnectors(req.params.id, req.body?.connectorIds ?? []);\n return { ok: true };\n });\n\n /* ----------------------------- threads ------------------------------ */\n f.get('/api/threads', async () => store.listThreads());\n\n f.post('/api/threads', async (req, reply) => {\n const parsed = CreateThreadRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n try {\n const members = parsed.data.memberBotIds.map((id) => store.getBot(id)).filter(Boolean);\n if (members.length !== parsed.data.memberBotIds.length)\n return reply.code(400).send({ error: 'One or more bots do not exist' });\n const title = parsed.data.title || members.map((m) => m!.name).join(', ');\n return store.createThread({ ...parsed.data, title });\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.get<{ Params: { id: string } }>('/api/threads/:id', async (req, reply) => {\n const thread = store.getThread(req.params.id);\n if (!thread) return reply.code(404).send({ error: 'No such thread' });\n const payload: ThreadWithMessages = { thread, messages: store.listMessages(thread.id) };\n return payload;\n });\n\n f.delete<{ Params: { id: string } }>('/api/threads/:id', async (req) => {\n store.deleteThread(req.params.id);\n return { ok: true };\n });\n\n f.post<{ Params: { id: string } }>('/api/threads/:id/read', async (req, reply) => {\n const thread = store.getThread(req.params.id);\n if (!thread) return reply.code(404).send({ error: 'No such thread' });\n store.updateThread(thread.id, { lastReadAt: Date.now() });\n for (const id of thread.memberBotIds) {\n const bot = store.getBot(id);\n if (bot && bot.attention !== 'needs_attention') {\n store.updateBot(id, { attention: 'none' });\n bus.publish({ type: 'bot.state', botId: id, threadId: thread.id, state: bot.state, attention: 'none' });\n }\n }\n return { ok: true };\n });\n\n /* ----------------------------- messages ----------------------------- */\n f.post<{ Params: { id: string } }>('/api/threads/:id/messages', async (req, reply) => {\n const parsed = PostMessageRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n const thread = store.getThread(req.params.id);\n if (!thread) return reply.code(404).send({ error: 'No such thread' });\n\n app.lastUserActivity.at = Date.now();\n\n const msg = store.createMessage({\n threadId: thread.id, authorKind: 'user', contentMd: parsed.data.contentMd,\n replyToId: parsed.data.replyToId ?? null,\n });\n if (parsed.data.attachmentIds?.length) {\n try {\n store.attachToMessage(parsed.data.attachmentIds, msg.id);\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n }\n bus.publish({ type: 'message.created', threadId: thread.id, botId: null, message: store.getMessage(msg.id)! });\n\n const attachments = store.listAttachmentsForMessage(msg.id);\n const attachNote = attachments.length\n ? `\\n\\nAttached files (read them from disk):\\n${attachments.map((a) => `- ${a.name} \u2192 ${a.path}`).join('\\n')}`\n : '';\n const prompt = parsed.data.contentMd + attachNote;\n\n const members = thread.memberBotIds.map((id) => store.getBot(id)).filter(Boolean) as NonNullable<ReturnType<typeof store.getBot>>[];\n if (!members.length) return msg;\n\n if (thread.kind === 'dm') {\n manager.enqueue({ botId: members[0]!.id, threadId: thread.id, prompt, origin: 'user', hops: 0 });\n } else {\n const inline = parseMentions(parsed.data.contentMd, members);\n const targets = await routeGroupMessage({\n text: parsed.data.contentMd,\n members,\n mentionBotIds: parsed.data.mentionBotIds ?? inline.botIds,\n mentionEveryone: parsed.data.mentionEveryone ?? inline.everyone,\n settings: app.getSettings(),\n cwd: app.cfg.paths.workspace,\n });\n for (const t of targets)\n manager.enqueue({ botId: t.id, threadId: thread.id, prompt, origin: 'user', hops: 0 });\n }\n return msg;\n });\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport type { FastifyInstance } from 'fastify';\nimport type { App } from '../app.js';\nimport { workspaceRelative } from '../app.js';\nimport {\n ApprovalDecisionRequest, CreateRuleRequest, CreateRoutineRequest, CreateSkillRequest,\n SettingsPatchSchema, LimitError, type UsageSummary, type SearchResult,\n CreateConnectorRequest, UpdateConnectorRequest, type Connector, type ApiConnector, type ApiCatalogEntry,\n} from '@antbot/contract';\nimport { computeMissingSecrets } from '../bots/connectors.js';\nimport { BUILTIN_CATALOG } from '../connectors/builtin/catalog.js';\nimport { redirectUri } from '../connectors/auth.js';\n\nexport function registerOpsRoutes(f: FastifyInstance, app: App): void {\n const { store, gateway, bus } = app;\n\n /* ---------------------------- approvals ---------------------------- */\n f.get('/api/approvals', async () => store.listPendingApprovals());\n\n f.post<{ Params: { id: string } }>('/api/approvals/:id', async (req, reply) => {\n const parsed = ApprovalDecisionRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n const updated = gateway.decide(req.params.id, parsed.data.decision, parsed.data.alwaysRule);\n return updated ?? reply.code(404).send({ error: 'No such approval' });\n });\n\n /* ------------------------------ rules ------------------------------ */\n f.get('/api/rules', async () => store.listRules());\n\n f.post('/api/rules', async (req, reply) => {\n const parsed = CreateRuleRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n try {\n new RegExp(parsed.data.inputPattern || '');\n } catch {\n return reply.code(400).send({ error: 'inputPattern is not a valid regular expression' });\n }\n return store.createRule(parsed.data);\n });\n\n f.patch<{ Params: { id: string }; Body: { enabled: boolean } }>('/api/rules/:id', async (req, reply) => {\n const rule = store.getRule(req.params.id);\n if (!rule) return reply.code(404).send({ error: 'No such rule' });\n store.setRuleEnabled(rule.id, Boolean(req.body?.enabled));\n return store.getRule(rule.id);\n });\n\n f.delete<{ Params: { id: string } }>('/api/rules/:id', async (req, reply) => {\n const rule = store.getRule(req.params.id);\n if (!rule) return reply.code(404).send({ error: 'No such rule' });\n if (rule.builtin) return reply.code(400).send({ error: 'Built-in rules cannot be deleted; disable it instead.' });\n store.deleteRule(rule.id);\n return { ok: true };\n });\n\n /* ---------------------------- connectors --------------------------- */\n const describe = (c: Connector): ApiConnector => ({\n ...c,\n missingSecrets: computeMissingSecrets(c, new Set(app.secrets?.list() ?? [])),\n // Names only \u2014 knowing a connector is signed in never requires reading its token.\n signedIn: app.connectorAuth?.isAuthorized(c.name) ?? false,\n });\n\n /** Secret values never appear here: rows hold `{{secret:NAME}}` references and nothing more. */\n f.get('/api/connectors', async () => store.listConnectors().map(describe));\n\n /** The built-in connectors ant-bot ships, with what setting each up involves. */\n f.get('/api/connectors/catalog', async (): Promise<ApiCatalogEntry[]> =>\n Object.values(BUILTIN_CATALOG).map((b) => ({\n name: b.name,\n displayName: b.displayName,\n description: b.description,\n provider: b.provider.displayName,\n needsClientCredentials: !b.provider.dynamicRegistration,\n setupSteps: b.provider.setupSteps.map((step) => step.replace('{redirectUri}', redirectUri(app.cfg.port))),\n })),\n );\n\n /**\n * Add a connector \u2014 a custom command/URL, or a built-in by catalog name \u2014 assign it to bots, and\n * check it, all in one call. The verdict comes back with the row so the caller can say what to\n * do next without a second round trip.\n */\n f.post('/api/connectors', async (req, reply) => {\n const parsed = CreateConnectorRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: parsed.error.issues[0]?.message ?? 'Invalid body' });\n const body = parsed.data;\n if (store.getConnectorByName(body.name)) {\n return reply.code(409).send({ error: `A connector named \"${body.name}\" already exists` });\n }\n let created: Connector;\n if (body.builtin) {\n const def = app.builtin?.get(body.builtin);\n if (!def) return reply.code(400).send({ error: `No built-in connector named \"${body.builtin}\"` });\n // The name is fixed: tool names (`mcp__gmail__send_message`) and the seeded rules that gate\n // them depend on it.\n if (body.name !== def.name) return reply.code(400).send({ error: `The built-in ${def.name} connector must be named \"${def.name}\"` });\n created = store.createConnector({\n name: def.name, description: body.description || def.description,\n config: app.builtin!.rowConfig(def.name), kind: 'builtin', enabled: body.enabled,\n });\n } else {\n created = store.createConnector({ name: body.name, description: body.description, config: body.config!, enabled: body.enabled });\n }\n for (const botId of body.botIds ?? []) {\n if (!store.getBot(botId)) continue;\n const current = store.listBotConnectors(botId).map((c) => c.id);\n store.setBotConnectors(botId, [...new Set([...current, created.id])]);\n }\n const check = await app.checkConnector(created);\n return { ...describe(store.getConnector(created.id)!), check };\n });\n\n f.patch<{ Params: { id: string } }>('/api/connectors/:id', async (req, reply) => {\n const parsed = UpdateConnectorRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n const existing = store.getConnector(req.params.id);\n if (!existing) return reply.code(404).send({ error: 'No such connector' });\n // A built-in's config is the daemon's own endpoint; only enabled/description may change.\n if (existing.kind === 'builtin' && parsed.data.config) return reply.code(400).send({ error: 'A built-in connector has no editable config' });\n return describe(store.updateConnector(req.params.id, parsed.data)!);\n });\n\n f.delete<{ Params: { id: string } }>('/api/connectors/:id', async (req, reply) => {\n const c = store.getConnector(req.params.id);\n if (!c) return reply.code(404).send({ error: 'No such connector' });\n await app.connectorAuth?.signOut(c.name);\n store.deleteConnector(req.params.id);\n return { ok: true };\n });\n\n /** One honest verdict: ready, needs sign-in, needs a credential, or unreachable. Persisted. */\n f.post<{ Params: { id: string } }>('/api/connectors/:id/check', async (req, reply) => {\n const connector = store.getConnector(req.params.id);\n if (!connector) return reply.code(404).send({ error: 'No such connector' });\n return app.checkConnector(connector);\n });\n\n /**\n * Begin an interactive sign-in. Returns the URL the human must open; the browser comes back to\n * the callback below. `clientId`/`clientSecret` are needed only for providers without dynamic\n * registration \u2014 Google, for the built-in connectors.\n */\n f.post<{ Params: { id: string }; Body: { clientId?: string; clientSecret?: string; scopes?: string[] } }>(\n '/api/connectors/:id/login',\n async (req, reply) => {\n const connector = store.getConnector(req.params.id);\n if (!connector) return reply.code(404).send({ error: 'No such connector' });\n if (!app.connectorAuth) return reply.code(503).send({ error: 'Secrets backend unavailable, so sign-in cannot be stored' });\n try {\n const authorizeUrl = connector.kind === 'builtin'\n ? await app.builtin!.beginLogin(connector, req.body ?? {})\n : (await app.connectorAuth.beginLogin(connector, req.body ?? {})).authorizeUrl;\n return { authorizeUrl };\n } catch (err) {\n return reply.code(400).send({ error: (err as Error).message });\n }\n },\n );\n\n f.delete<{ Params: { id: string } }>('/api/connectors/:id/login', async (req, reply) => {\n const connector = store.getConnector(req.params.id);\n if (!connector) return reply.code(404).send({ error: 'No such connector' });\n await app.connectorAuth?.signOut(connector.name);\n store.setConnectorStatus(connector.id, 'needs-sign-in', null);\n return { ok: true };\n });\n\n /**\n * Where the authorization server sends the human back. Renders a plain page rather than JSON:\n * this is the one route a person lands on in a browser.\n */\n f.get<{ Querystring: { code?: string; state?: string; error?: string; error_description?: string } }>(\n '/api/connectors/oauth/callback',\n async (req, reply) => {\n const page = (title: string, detail: string, ok: boolean): string =>\n `<!doctype html><meta charset=utf-8><title>${title}</title>\n <body style=\"font-family:system-ui;background:#0b0d10;color:#e6e8eb;padding:3rem;max-width:40rem\">\n <h1 style=\"color:${ok ? '#4ade80' : '#f87171'}\">${title}</h1><p>${detail}</p>\n <p style=\"color:#9aa4b2\">You can close this tab and return to ant-bot.</p>`;\n\n const { code, state, error, error_description: desc } = req.query;\n if (error) return reply.type('text/html').send(page('Sign-in failed', `${error}: ${desc ?? ''}`, false));\n if (!code || !state) return reply.type('text/html').send(page('Sign-in failed', 'The provider did not return a code.', false));\n if (!app.connectorAuth) return reply.type('text/html').send(page('Sign-in failed', 'The secrets backend is unavailable.', false));\n try {\n const { connectorId, connectorName } = await app.connectorAuth.completeLogin(state, code);\n const row = store.getConnector(connectorId);\n if (row) await app.checkConnector(row);\n bus.publish({ type: 'notify', botId: null, threadId: null, title: 'Connector signed in', body: `${connectorName} is now authorised.`, level: 'info' });\n return reply.type('text/html').send(page('Signed in', `<b>${connectorName}</b> is now authorised.`, true));\n } catch (err) {\n return reply.type('text/html').send(page('Sign-in failed', (err as Error).message, false));\n }\n },\n );\n\n /**\n * The daemon's own MCP endpoint for built-in connectors. Guarded by a per-boot bearer that only\n * the runtime is handed at mount time; the provider token stays on this side of the line.\n */\n f.post<{ Params: { name: string } }>('/mcp/:name', async (req, reply) => {\n if (!app.builtin) return reply.code(503).send({ error: 'Built-in connectors unavailable' });\n if (!app.builtin.checkBearer(req.headers.authorization)) return reply.code(401).send({ error: 'Unauthorized' });\n const res = await app.builtin.handle(req.params.name, req.body);\n if (res === null) return reply.code(202).send();\n return res;\n });\n f.delete<{ Params: { name: string } }>('/mcp/:name', async () => ({ ok: true }));\n\n /* ------------------------------ skills ----------------------------- */\n f.get('/api/skills', async () => store.listSkills());\n\n f.post('/api/skills', async (req, reply) => {\n const parsed = CreateSkillRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n if (!app.skills?.writeSkill) return reply.code(503).send({ error: 'Skills subsystem unavailable' });\n return app.skills.writeSkill(parsed.data);\n });\n\n // Install from a source (git repo, local path, or a raw SKILL.md URL). This is the\n // simple path: no hand-built JSON body, just the source string.\n f.post<{ Body: { source?: string } }>('/api/skills/install', async (req, reply) => {\n const source = (req.body?.source ?? '').trim();\n if (!source) return reply.code(400).send({ error: 'A \"source\" is required' });\n if (!app.skills?.installFromSource) return reply.code(503).send({ error: 'Skills subsystem unavailable' });\n try {\n // A human typing `antbot skill add owner/repo` is asking for that repository, whatever\n // it holds; the multi-skill guard exists for bots choosing a source on their own.\n const installed = await app.skills.installFromSource(source, { allowMultiple: true });\n return {\n installed: installed.map((i: { skill: unknown; executables: string[]; manifestText: string; replaced: boolean }) => ({\n skill: i.skill,\n executables: i.executables,\n manifest: i.manifestText,\n replaced: i.replaced,\n })),\n };\n } catch (err) {\n return reply.code(400).send({ error: (err as Error).message });\n }\n });\n\n f.get<{ Params: { id: string } }>('/api/skills/:id', async (req, reply) => {\n const skill = store.getSkill(req.params.id);\n if (!skill) return reply.code(404).send({ error: 'No such skill' });\n if (app.skills?.readSkill) return app.skills.readSkill(skill.id);\n return { ...skill, bodyMd: '' };\n });\n\n f.delete<{ Params: { id: string } }>('/api/skills/:id', async (req, reply) => {\n const skill = store.getSkill(req.params.id);\n if (!skill) return reply.code(404).send({ error: 'No such skill' });\n if (app.skills?.deleteSkill) app.skills.deleteSkill(skill.id);\n else store.deleteSkill(skill.id);\n return { ok: true };\n });\n\n /* ------------------------- secrets (WP-2.4) ------------------------ */\n // Values go straight to the OS keychain. Only NAMES are ever returned here, and a\n // value is never written to a transcript or placed in the model's context.\n f.get('/api/secrets', async () => ({\n backend: app.secrets?.backendName ?? 'unavailable',\n names: app.secrets?.list() ?? [],\n }));\n\n f.post<{ Body: { name?: string; value?: string } }>('/api/secrets', async (req, reply) => {\n if (!app.secrets) return reply.code(503).send({ error: 'Secrets backend unavailable' });\n const name = (req.body?.name ?? '').trim();\n const value = req.body?.value ?? '';\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))\n return reply.code(400).send({ error: 'Name must be a valid environment-variable identifier' });\n if (!value) return reply.code(400).send({ error: 'A value is required' });\n await app.secrets.set(name, value);\n return { ok: true, names: app.secrets.list() };\n });\n\n f.delete<{ Params: { name: string } }>('/api/secrets/:name', async (req, reply) => {\n if (!app.secrets) return reply.code(503).send({ error: 'Secrets backend unavailable' });\n await app.secrets.remove(req.params.name);\n return { ok: true, names: app.secrets.list() };\n });\n\n /* ----------------------------- routines ---------------------------- */\n f.get<{ Querystring: { botId?: string } }>('/api/routines', async (req) => store.listRoutines(req.query.botId));\n\n f.post('/api/routines', async (req, reply) => {\n const parsed = CreateRoutineRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n if (!store.getBot(parsed.data.botId)) return reply.code(400).send({ error: 'No such bot' });\n try {\n const routine = store.createRoutine({ ...parsed.data, timezone: parsed.data.timezone ?? app.getSettings().timezone });\n app.scheduler?.reload?.(routine.id);\n return routine;\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.patch<{ Params: { id: string } }>('/api/routines/:id', async (req, reply) => {\n const routine = store.updateRoutine(req.params.id, (req.body ?? {}) as Record<string, never>);\n if (!routine) return reply.code(404).send({ error: 'No such routine' });\n app.scheduler?.reload?.(routine.id);\n return routine;\n });\n\n f.delete<{ Params: { id: string } }>('/api/routines/:id', async (req, reply) => {\n if (!store.getRoutine(req.params.id)) return reply.code(404).send({ error: 'No such routine' });\n store.deleteRoutine(req.params.id);\n app.scheduler?.reload?.(req.params.id);\n return { ok: true };\n });\n\n f.get<{ Params: { id: string } }>('/api/routines/:id/runs', async (req) => store.listRuns(req.params.id));\n\n f.post<{ Params: { id: string } }>('/api/routines/:id/test-run', async (req, reply) => {\n const routine = store.getRoutine(req.params.id);\n if (!routine) return reply.code(404).send({ error: 'No such routine' });\n if (!app.scheduler?.testRun) return reply.code(503).send({ error: 'Scheduler unavailable' });\n const runId = await app.scheduler.testRun(routine.id);\n return { runId };\n });\n\n /* ---------------------------- attachments -------------------------- */\n f.post('/api/attachments', async (req, reply) => {\n const anyReq = req as unknown as { file?: () => Promise<any>; isMultipart?: () => boolean };\n if (typeof anyReq.file !== 'function') return reply.code(400).send({ error: 'Expected a multipart upload' });\n const part = await anyReq.file();\n if (!part) return reply.code(400).send({ error: 'No file in request' });\n const buf: Buffer = await part.toBuffer();\n const safe = String(part.filename ?? 'file').replace(/[^a-zA-Z0-9._-]/g, '_');\n const dest = path.join(app.cfg.paths.attachments, `${Date.now()}-${safe}`);\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.writeFileSync(dest, buf);\n try {\n return store.createAttachment({\n messageId: null, path: dest, name: safe,\n mime: part.mimetype ?? 'application/octet-stream', bytes: buf.byteLength,\n });\n } catch (err) {\n fs.unlinkSync(dest);\n if (err instanceof LimitError) return reply.code(413).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.get<{ Params: { id: string } }>('/api/attachments/:id', async (req, reply) => {\n const a = store.getAttachment(req.params.id);\n if (!a || !fs.existsSync(a.path)) return reply.code(404).send({ error: 'No such attachment' });\n return reply.type(a.mime).send(fs.createReadStream(a.path));\n });\n\n /* ------------------------------ usage ------------------------------ */\n f.get('/api/usage', async (): Promise<UsageSummary> => {\n const rows = store.listUsage(0);\n const totals = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0 };\n const byBot = new Map<string, { inputTokens: number; outputTokens: number }>();\n const byDay = new Map<string, { inputTokens: number; outputTokens: number }>();\n const byModel = new Map<string, { inputTokens: number; outputTokens: number }>();\n for (const r of rows) {\n totals.inputTokens += r.inputTokens;\n totals.outputTokens += r.outputTokens;\n totals.cacheReadTokens += r.cacheReadTokens;\n const day = new Date(r.createdAt).toISOString().slice(0, 10);\n for (const [map, key] of [[byBot, r.botId], [byDay, day], [byModel, r.model]] as const) {\n const cur = map.get(key) ?? { inputTokens: 0, outputTokens: 0 };\n cur.inputTokens += r.inputTokens;\n cur.outputTokens += r.outputTokens;\n map.set(key, cur);\n }\n }\n return {\n totals,\n byBot: [...byBot].map(([botId, v]) => ({ botId, botName: store.getBot(botId)?.name ?? 'deleted', ...v })),\n byDay: [...byDay].map(([day, v]) => ({ day, ...v })).sort((a, b) => a.day.localeCompare(b.day)),\n byModel: [...byModel].map(([model, v]) => ({ model, ...v })),\n };\n });\n\n /* ------------------------------ search ----------------------------- */\n f.get<{ Querystring: { q?: string } }>('/api/search', async (req): Promise<SearchResult[]> => {\n const q = (req.query.q ?? '').trim();\n if (!q) return [];\n const out: SearchResult[] = [];\n for (const b of store.listBots()) {\n if (b.name.toLowerCase().includes(q.toLowerCase()) || b.title.toLowerCase().includes(q.toLowerCase()))\n out.push({ kind: 'bot', id: b.id, threadId: b.threadId, botId: b.id, title: b.name, snippet: b.title || b.description.slice(0, 120), createdAt: b.createdAt });\n }\n for (const m of store.searchMessages(q)) {\n const idx = m.contentMd.toLowerCase().indexOf(q.toLowerCase());\n const start = Math.max(0, idx - 60);\n out.push({\n kind: 'message', id: m.id, threadId: m.threadId, botId: m.authorBotId,\n title: m.authorKind === 'user' ? 'You' : store.getBot(m.authorBotId ?? '')?.name ?? 'Bot',\n snippet: `${start > 0 ? '\u2026' : ''}${m.contentMd.slice(start, start + 180)}`,\n createdAt: m.createdAt,\n });\n }\n for (const r of store.listRoutines()) {\n if (r.name.toLowerCase().includes(q.toLowerCase()))\n out.push({ kind: 'routine', id: r.id, threadId: null, botId: r.botId, title: r.name, snippet: r.cronExpr, createdAt: r.createdAt });\n }\n return out.slice(0, 50);\n });\n\n /* ----------------------------- settings ---------------------------- */\n f.get('/api/settings', async () => store.getSettings());\n\n f.patch('/api/settings', async (req, reply) => {\n const parsed = SettingsPatchSchema.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid settings' });\n const next = store.patchSettings(parsed.data);\n app.scheduler?.syncAll?.();\n bus.publish({ type: 'notify', botId: null, threadId: null, title: 'Settings updated', body: '', level: 'info' });\n return next;\n });\n\n /* ---------------------------- workspace ---------------------------- */\n f.get<{ Querystring: { path?: string } }>('/api/workspace/tree', async (req, reply) => {\n const root = app.cfg.paths.workspace;\n const target = workspaceRelative(root, req.query.path ?? '.');\n if (!target) return reply.code(400).send({ error: 'Path is outside the workspace' });\n if (!fs.existsSync(target)) return [];\n return fs.readdirSync(target, { withFileTypes: true })\n .map((d) => {\n const full = path.join(target, d.name);\n let bytes = 0;\n try { bytes = d.isFile() ? fs.statSync(full).size : 0; } catch { /* ignore */ }\n return { name: d.name, path: path.relative(root, full), dir: d.isDirectory(), bytes };\n })\n .sort((a, b) => (a.dir === b.dir ? a.name.localeCompare(b.name) : a.dir ? -1 : 1));\n });\n\n f.get<{ Querystring: { path?: string } }>('/api/workspace/file', async (req, reply) => {\n const root = app.cfg.paths.workspace;\n const target = workspaceRelative(root, req.query.path ?? '');\n if (!target || !fs.existsSync(target) || !fs.statSync(target).isFile())\n return reply.code(404).send({ error: 'No such file' });\n const ext = path.extname(target).toLowerCase();\n const mime: Record<string, string> = {\n '.md': 'text/markdown', '.txt': 'text/plain', '.json': 'application/json',\n '.csv': 'text/csv', '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',\n '.gif': 'image/gif', '.svg': 'image/svg+xml', '.pdf': 'application/pdf', '.html': 'text/html',\n };\n return reply.type(mime[ext] ?? 'application/octet-stream').send(fs.createReadStream(target));\n });\n\n /* ----------------------------- computer ---------------------------- */\n f.get('/api/computer/status', async () => {\n if (!app.browser?.status) return { available: false, reason: 'Browser service not built', mode: 'host', headless: true, pages: [] };\n try {\n return await app.browser.status();\n } catch (err) {\n return { available: false, reason: (err as Error).message, mode: 'host', headless: true, pages: [] };\n }\n });\n\n f.post<{ Body: { botId?: string } }>('/api/computer/takeover', async (req, reply) => {\n if (!app.browser?.takeOver) return reply.code(503).send({ error: 'Browser service unavailable' });\n return app.browser.takeOver(req.body?.botId ?? 'shared');\n });\n\n f.delete<{ Body: { botId?: string } }>('/api/computer/takeover', async (req, reply) => {\n if (!app.browser?.returnControl) return reply.code(503).send({ error: 'Browser service unavailable' });\n await app.browser.returnControl(req.body?.botId ?? 'shared');\n return { ok: true };\n });\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createRequire } from 'node:module';\nimport Fastify, { type FastifyInstance } from 'fastify';\nimport cors from '@fastify/cors';\nimport multipart from '@fastify/multipart';\nimport websocket from '@fastify/websocket';\nimport fastifyStatic from '@fastify/static';\nimport { createApp, drainMailbox, type App } from '../app.js';\nimport { registerCoreRoutes } from './routes-core.js';\nimport { registerOpsRoutes } from './routes-ops.js';\nimport { logger } from '../util/log.js';\nimport { LIMITS, ScreencastClientFrameSchema } from '@antbot/contract';\nimport { findWebDist, nodeLocateDeps } from '../util/locate.js';\n\nconst log = logger('server');\n\nexport interface StartOptions {\n root?: string;\n port?: number;\n host?: string;\n withAgent?: boolean;\n serveStatic?: boolean;\n}\n\nexport interface RunningServer {\n fastify: FastifyInstance;\n app: App;\n url: string;\n close: () => Promise<void>;\n}\n\nconst require_ = createRequire(import.meta.url);\n\nfunction resolveWebDist(): string | null {\n return findWebDist(\n nodeLocateDeps(path.dirname(fileURLToPath(import.meta.url)), (spec) => {\n try {\n return require_.resolve(spec);\n } catch {\n return null;\n }\n }),\n );\n}\n\nexport async function startServer(opts: StartOptions = {}): Promise<RunningServer> {\n const app = await createApp({ root: opts.root, withAgent: opts.withAgent });\n const fastify = Fastify({ logger: false, bodyLimit: LIMITS.MAX_VIDEO_ATTACHMENT_BYTES });\n\n // Several endpoints are pure commands with no payload (stop, duplicate, read,\n // test-run). Fastify rejects a zero-length body when the client still sends\n // `content-type: application/json` \u2014 and it does so before any content-type\n // parser runs \u2014 so drop the header for genuinely empty requests.\n fastify.addHook('onRequest', (req, _reply, done) => {\n const len = req.headers['content-length'];\n const ct = req.headers['content-type'];\n if ((len === '0' || len === undefined) && ct?.includes('application/json')) {\n delete req.headers['content-type'];\n }\n done();\n });\n\n await fastify.register(cors, { origin: true });\n await fastify.register(multipart, {\n limits: { fileSize: LIMITS.MAX_VIDEO_ATTACHMENT_BYTES, files: LIMITS.MAX_ATTACHMENTS_PER_MESSAGE },\n });\n await fastify.register(websocket);\n\n registerCoreRoutes(fastify, app);\n registerOpsRoutes(fastify, app);\n\n /* ------------------------- event websocket ------------------------- */\n fastify.register(async (scope) => {\n scope.get('/api/events', { websocket: true }, (socket) => {\n const send = (payload: unknown): void => {\n try {\n if (socket.readyState === 1) socket.send(JSON.stringify(payload));\n } catch { /* client vanished */ }\n };\n const unsubscribe = app.bus.subscribe(send);\n // Handshake only \u2014 carries the current seq so the client can detect gaps.\n // Deliberately not a `notify`: connection state is UI chrome, not a user alert.\n send({ type: 'hello', seq: app.bus.currentSeq, epoch: app.bus.epoch, threadId: null, botId: null });\n\n socket.on('message', (raw: Buffer) => {\n try {\n const msg = JSON.parse(raw.toString()) as { type?: string; seq?: number };\n if (msg.type === 'resume' && typeof msg.seq === 'number')\n for (const e of app.bus.since(msg.seq)) send(e);\n } catch { /* ignore malformed client frames */ }\n });\n socket.on('close', unsubscribe);\n socket.on('error', unsubscribe);\n });\n\n /* --------------------------- screencast -------------------------- */\n scope.get<{ Params: { botId: string } }>('/api/computer/screencast/:botId', { websocket: true }, async (socket, req) => {\n const botId = req.params.botId;\n if (!app.browser?.startScreencast) {\n try { socket.send(JSON.stringify({ type: 'error', message: 'Browser service unavailable' })); } catch { /* ignore */ }\n socket.close();\n return;\n }\n let stop: (() => void) | undefined;\n try {\n stop = await app.browser.startScreencast(botId, (data: string, w: number, h: number) => {\n try {\n if (socket.readyState === 1) socket.send(JSON.stringify({ type: 'frame', data, w, h }));\n } catch { /* ignore */ }\n });\n } catch (err) {\n try { socket.send(JSON.stringify({ type: 'error', message: (err as Error).message })); } catch { /* ignore */ }\n socket.close();\n return;\n }\n // The socket is bidirectional: frames stream out, and human input comes back in while the\n // screen is taken over. Validated against the shared schema rather than trusted, because\n // this is the one place a browser can ask the daemon to act on a page.\n socket.on('message', (raw: Buffer) => {\n if (!app.browser?.forwardInput) return;\n let frame;\n try {\n frame = ScreencastClientFrameSchema.parse(JSON.parse(raw.toString()));\n } catch {\n return; // malformed frame \u2014 ignore rather than tearing down the screencast\n }\n const fail = (err: unknown): void => {\n try {\n if (socket.readyState === 1)\n socket.send(JSON.stringify({ type: 'input-error', message: (err as Error).message }));\n } catch { /* ignore */ }\n };\n\n if (frame.type === 'selection-request') {\n if (!app.browser.readSelection) return;\n void app.browser\n .readSelection(botId)\n .then((text: string) => {\n try {\n if (socket.readyState === 1) socket.send(JSON.stringify({ type: 'selection', text }));\n } catch { /* ignore */ }\n })\n .catch(fail);\n return;\n }\n\n void app.browser.forwardInput(botId, frame.input).catch(fail);\n });\n\n socket.on('close', () => stop?.());\n socket.on('error', () => stop?.());\n });\n });\n\n /* ---------------------------- static UI ---------------------------- */\n if (opts.serveStatic !== false) {\n const dist = resolveWebDist();\n if (dist) {\n await fastify.register(fastifyStatic, { root: dist, prefix: '/' });\n fastify.setNotFoundHandler((req, reply) => {\n if (req.url.startsWith('/api')) return reply.code(404).send({ error: 'Not found' });\n return reply.sendFile('index.html');\n });\n log.info(`serving UI from ${dist}`);\n } else {\n log.warn('web UI not built \u2014 run `pnpm --filter @antbot/ui build`');\n fastify.setNotFoundHandler((req, reply) => {\n if (req.url.startsWith('/api')) return reply.code(404).send({ error: 'Not found' });\n return reply.type('text/html').send(\n `<!doctype html><meta charset=utf-8><title>ant-bot</title>\n <body style=\"font-family:system-ui;background:#0b0d10;color:#e6e8eb;padding:3rem\">\n <h1>ant-bot daemon is running</h1>\n <p>The web UI has not been built yet. Run:</p>\n <pre style=\"background:#151922;padding:1rem;border-radius:8px\">pnpm --filter @antbot/ui build</pre>\n <p>The API is live at <code>/api/health</code>.</p>`,\n );\n });\n }\n }\n\n fastify.setErrorHandler((err: unknown, _req, reply) => {\n log.error('request failed', err);\n const e = err as { statusCode?: number; message?: string };\n const code = e.statusCode && e.statusCode >= 400 ? e.statusCode : 500;\n reply.code(code).send({ error: e.message ?? 'Internal error' });\n });\n\n const port = opts.port ?? app.cfg.port;\n const host = opts.host ?? app.cfg.host;\n // Everything that builds a URL back to this daemon \u2014 OAuth redirect, built-in MCP endpoints \u2014\n // reads the port from here, so a `--port` override has to land before the first request.\n app.cfg.port = port;\n await fastify.listen({ port, host });\n const url = `http://${host}:${port}`;\n\n const delivered = drainMailbox(app);\n if (delivered) log.info(`redelivered ${delivered} queued handoff message(s)`);\n\n // Mark any turn that was mid-flight when the daemon died as interrupted.\n const stale = app.store.listBots().filter((b) => b.state === 'running' || b.state === 'queued');\n for (const b of stale) app.store.updateBot(b.id, { state: 'idle' });\n app.db.prepare(`UPDATE messages SET streaming=0 WHERE streaming=1`).run();\n app.db.prepare(`UPDATE approvals SET status='expired', reason='Daemon restarted' WHERE status='pending'`).run();\n app.db.prepare(`UPDATE routine_runs SET status='interrupted', finished_at=? WHERE status='running'`).run(Date.now());\n\n log.info(`ant-bot listening on ${url}`);\n\n return {\n fastify,\n app,\n url,\n close: async () => {\n await fastify.close();\n await app.shutdown();\n },\n };\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { openDb, type DB } from './db/db.js';\nimport { Store } from './db/store.js';\nimport { EventBus } from './util/bus.js';\nimport { PermissionGateway } from './permissions/gateway.js';\nimport { seedBuiltinRules } from './permissions/rules.js';\nimport { makeAutoReviewer, NullAutoReviewer } from './permissions/autoreview.js';\nimport { BotManager } from './bots/manager.js';\nimport { planConnectorMount, extractSecretRefs, buildMcpServerConfig, computeMissingSecrets } from './bots/connectors.js';\nimport { ConnectorAuthService } from './connectors/auth.js';\nimport type { MountedConnector } from './agent/runtime.js';\nimport { BuiltinService } from './connectors/builtin/service.js';\nimport { gatherCustomSignals, decideCheck } from './connectors/check.js';\nimport { readPackageVersion } from './util/locate.js';\nimport { fileURLToPath } from 'node:url';\nimport type { Connector, ConnectorCheck } from '@antbot/contract';\nimport { loadConfig, type AntbotConfig } from './config/config.js';\nimport { logger } from './util/log.js';\nimport type { Settings } from '@antbot/contract';\nimport { SecretsService, pickBackend } from './permissions/secrets.js';\n\nconst log = logger('app');\n\n/**\n * Load a subsystem that may not work on this machine \u2014 no Playwright installed, no fts5 \u2014 so the\n * daemon still boots without it.\n *\n * `load` must be a thunk around a *literal* dynamic import. This used to take a specifier string\n * and assemble it at runtime (`import(\\`${spec}\\`)`) so the compiler would not require the module\n * to exist; every one of them exists now, and the runtime-assembled form is invisible to a\n * bundler \u2014 the published build resolved them relative to the bundle, found nothing, and booted\n * with skills, browser and scheduler all silently missing.\n */\nasync function optionalImport(name: string, load: () => Promise<unknown>): Promise<any | null> {\n try {\n return await load();\n } catch (err) {\n log.warn(`${name} module could not be loaded`, (err as Error).message);\n return null;\n }\n}\n\nexport interface App {\n cfg: AntbotConfig;\n db: DB;\n store: Store;\n bus: EventBus;\n gateway: PermissionGateway;\n manager: BotManager;\n getSettings: () => Settings;\n /** Optional subsystems, wired if their modules are present. */\n scheduler?: any;\n browser?: any;\n skills?: any;\n secrets?: SecretsService;\n connectorAuth?: ConnectorAuthService;\n /** Serves ant-bot's built-in connectors (Gmail\u2026) over MCP from the daemon itself. */\n builtin?: BuiltinService;\n /** One connector, resolved to what the runtime mounts \u2014 or null when it cannot be mounted. */\n mountConnector: (connector: Connector) => Promise<MountedConnector | null>;\n /** One honest verdict, persisted on the row. */\n checkConnector: (connector: Connector) => Promise<ConnectorCheck>;\n lastUserActivity: { at: number };\n /** Root of the local plugin carrying installed skills. */\n skillPluginPath?: string;\n shutdown: () => Promise<void>;\n}\n\nexport async function createApp(opts: { root?: string; withAgent?: boolean } = {}): Promise<App> {\n const cfg = loadConfig(opts.root);\n const db = openDb(cfg.paths.db, { backupsDir: cfg.paths.backups });\n const store = new Store(db);\n\n // config.toml holds first-run defaults; the DB is authoritative afterwards.\n const persisted = store.getSettings();\n const settingsCount = store.db.prepare(`SELECT COUNT(*) c FROM settings`).get() as { c: number };\n if (!settingsCount.c) {\n store.patchSettings(cfg.settings);\n }\n const getSettings = (): Settings => store.getSettings();\n void persisted;\n\n seedBuiltinRules(store);\n\n const bus = new EventBus();\n const reviewer = opts.withAgent === false\n ? new NullAutoReviewer()\n : makeAutoReviewer(getSettings, cfg.paths.workspace);\n const gateway = new PermissionGateway(store, bus, reviewer);\n\n const app: App = {\n cfg, db, store, bus, gateway, getSettings,\n manager: undefined as unknown as BotManager,\n lastUserActivity: { at: Date.now() },\n shutdown: async () => {},\n mountConnector: async () => null,\n checkConnector: async () => ({ status: 'unreachable', tools: [] }),\n };\n\n app.manager = new BotManager({\n store, bus, gateway,\n workspace: cfg.paths.workspace,\n // The human attached these files deliberately; reading one is not \"reaching outside the\n // workspace\" in the sense the boundary exists to catch.\n readableRoots: [cfg.paths.attachments],\n getSettings,\n skillPluginPath: () => app.skillPluginPath,\n installSkill: async (source: string, opts?: { allowMultiple?: boolean }) => {\n if (!app.skills?.installFromSource) throw new Error('Skill installation is unavailable.');\n const installed = await app.skills.installFromSource(source, opts ?? {});\n return installed.map((i: { skill: { name: string }; executables: string[] }) => ({\n name: i.skill.name,\n executables: i.executables,\n }));\n },\n listSkills: () =>\n store.listSkills().map((sk) => ({ slug: sk.slug, name: sk.name, description: sk.description })),\n // Routed through SkillStore so the directory and the registration go together \u2014 a bot\n // deleting directories with Bash is what leaves the registry pointing at nothing.\n removeSkill: async (slug: string) => {\n if (!app.skills?.deleteSkill) throw new Error('Skill removal is unavailable.');\n const skill = store.getSkillBySlug(slug);\n if (!skill) return { removed: false };\n app.skills.deleteSkill(skill.id);\n return { removed: true, name: skill.name };\n },\n browserTools: (botId: string) => {\n if (!app.browser?.toolServerFor) return undefined;\n try {\n return app.browser.toolServerFor(botId);\n } catch {\n return undefined;\n }\n },\n /**\n * Resolve this bot's connectors into mountable MCP servers.\n *\n * This is the only place a secret value is read for a turn, and the values live nowhere but\n * the returned config \u2014 not in the row, not in a log line, not in anything a route returns.\n * A connector missing a credential is dropped rather than mounted broken or allowed to fail\n * the turn; the human was already warned on the connectors screen.\n */\n connectorServers: async (botId: string) => {\n const assigned = store.listBotConnectors(botId);\n const servers: Record<string, MountedConnector> = {};\n const mounted: { name: string; description: string }[] = [];\n for (const connector of assigned) {\n const built = await app.mountConnector(connector);\n if (!built) continue;\n servers[connector.name] = built;\n mounted.push({ name: connector.name, description: connector.description });\n }\n return { servers, mounted };\n },\n });\n\n /**\n * Resolve one connector to what the runtime mounts.\n *\n * This is the only place a secret value is read for a turn, and the values live nowhere but the\n * returned config \u2014 not in the row, not in a log line, not in anything a route returns. A\n * connector missing a credential is dropped rather than mounted broken or allowed to fail the\n * turn; the row's status says why. A built-in connector mounts as the daemon's own endpoint with\n * this boot's bearer; its provider token never leaves the daemon.\n */\n app.mountConnector = async (connector) => {\n if (connector.kind === 'builtin') {\n if (!app.builtin?.get(connector.name)) return null;\n return app.builtin.mountConfig(connector);\n }\n const available = new Set(app.secrets?.list() ?? []);\n const { skipped } = planConnectorMount([connector], available);\n if (skipped.length) {\n const missing = skipped[0]!.missing;\n log.warn(`connector \"${connector.name}\" not mounted \u2014 missing secret(s): ${missing.join(', ')}`);\n store.setConnectorStatus(connector.id, 'needs-credential', `missing secret(s): ${missing.join(', ')}`);\n return null;\n }\n try {\n const refs = extractSecretRefs(connector.config);\n const secrets = refs.length ? await app.secrets!.resolve(refs) : new Map<string, string | null>();\n const built = buildMcpServerConfig(connector, secrets);\n // A signed-in connector carries a bearer token that is refreshed here if it is close to\n // expiring. A static Authorization header in the config wins \u2014 that is the human being\n // deliberate.\n const auth = await app.connectorAuth?.authHeader(connector.name);\n if (auth && built.type !== 'stdio' && !('Authorization' in built.headers)) {\n built.headers = { ...built.headers, ...auth };\n }\n return built;\n } catch (err) {\n // A secret that vanished between planning and reading. Same treatment as a missing one.\n log.warn(`connector \"${connector.name}\" not mounted`, (err as Error).message);\n store.setConnectorStatus(connector.id, 'needs-credential', (err as Error).message);\n return null;\n }\n };\n\n app.checkConnector = async (connector) => {\n let verdict: ConnectorCheck;\n if (connector.kind === 'builtin') {\n const def = app.builtin?.get(connector.name);\n const tools = def ? def.tools().map((t) => ({ name: t.name, description: t.description })) : [];\n verdict = decideCheck({\n probe: def ? { ok: true, tools } : null,\n challenge: 'none',\n missingSecrets: [],\n builtinSignedIn: app.builtin?.authorized(connector.name) ?? false,\n builtinMissingScopes: (await app.builtin?.missingScopes(connector.name)) ?? [],\n builtinProvider: def ? { name: def.provider.displayName, dynamicRegistration: def.provider.dynamicRegistration } : undefined,\n });\n } else {\n const available = new Set(app.secrets?.list() ?? []);\n const missing = computeMissingSecrets(connector, available);\n const mounted = missing.length ? null : await app.mountConnector(connector);\n verdict = decideCheck(await gatherCustomSignals(connector, mounted, missing));\n }\n store.setConnectorStatus(connector.id, verdict.status, verdict.detail ?? null);\n return verdict;\n };\n\n // --- secrets (keychain-backed; values never reach the model) ---\n try {\n app.secrets = new SecretsService(\n await pickBackend(cfg.paths.secrets),\n `${cfg.paths.secrets}.index`,\n );\n log.info(`secrets backend: ${app.secrets.backendName}`);\n app.connectorAuth = new ConnectorAuthService(app.secrets, () => app.cfg.port);\n } catch (err) {\n log.warn('secrets backend unavailable', (err as Error).message);\n }\n // Built-in connectors are served regardless; without a secrets backend they simply cannot be\n // signed in to, and the check says so.\n app.builtin = new BuiltinService(\n app.connectorAuth,\n () => app.cfg.port,\n readPackageVersion(path.dirname(fileURLToPath(import.meta.url)), (p) => fs.existsSync(p), (p) => fs.readFileSync(p, 'utf8')),\n );\n try {\n void 0;\n } catch (err) {\n log.warn('secrets backend unavailable', (err as Error).message);\n }\n\n // --- optional subsystems (built concurrently; wired only if present) ---\n await wireSkills(app);\n await wireBrowser(app);\n await wireScheduler(app);\n\n app.shutdown = async () => {\n try { app.scheduler?.stop?.(); } catch { /* ignore */ }\n try { await app.browser?.shutdown?.(); } catch { /* ignore */ }\n try { db.close(); } catch { /* ignore */ }\n };\n\n return app;\n}\n\nasync function wireSkills(app: App): Promise<void> {\n try {\n const mod = await optionalImport('skills', () => import('./skills/skills.js'));\n const pluginMod = await optionalImport('skill plugin', () => import('./skills/plugin.js'));\n const Ctor = mod?.SkillStore ?? mod?.default;\n if (!Ctor) return void log.warn('skills subsystem unavailable: no SkillStore export');\n\n // The skills directory doubles as a local plugin root so the SDK can load skills\n // natively; individual skills live one level down, under `skills/`.\n const pluginRoot = app.cfg.paths.skills;\n if (pluginMod?.ensureSkillPlugin) {\n pluginMod.ensureSkillPlugin(pluginRoot);\n const moved: string[] = pluginMod.migrateLegacyLayout?.(pluginRoot) ?? [];\n if (moved.length) log.info(`migrated ${moved.length} skill(s) into the plugin layout: ${moved.join(', ')}`);\n app.skillPluginPath = pluginRoot;\n }\n const filesDir: string = pluginMod?.skillFilesDir?.(pluginRoot) ?? pluginRoot;\n\n app.skills = new Ctor(app.store, filesDir);\n\n // Skills shipped with ant-bot are installed on every boot and refreshed in place, but\n // only while the user has not edited or deleted their copy \u2014 see skills/bundled.ts.\n const bundledMod = await optionalImport('bundled skills', () => import('./skills/bundled.js'));\n if (bundledMod?.syncBundledSkills) {\n try {\n const decisions: { slug: string; action: string }[] = bundledMod.syncBundledSkills(filesDir);\n const took = (action: string): string[] =>\n decisions.filter((d) => d.action === action).map((d) => d.slug);\n const installed = took('install');\n const updated = took('update');\n const kept = [...took('skip-modified'), ...took('skip-foreign')];\n if (installed.length) log.info(`installed ${installed.length} bundled skill(s): ${installed.join(', ')}`);\n if (updated.length) log.info(`updated ${updated.length} bundled skill(s): ${updated.join(', ')}`);\n if (kept.length) log.info(`left ${kept.length} locally-modified skill(s) alone: ${kept.join(', ')}`);\n\n // syncFromDisk only registers slugs the db has never seen, so a skill whose shipped\n // frontmatter `name` changed would keep its old registered name \u2014 and the SDK is handed\n // registered names as `enabledSkills`, so it would silently stop resolving for every bot\n // that had it enabled.\n const written = [...installed, ...updated, ...took('adopt')];\n const renamed: string[] = app.skills?.refreshFromDisk?.(written) ?? [];\n if (renamed.length) log.info(`refreshed metadata for ${renamed.length} skill(s): ${renamed.join(', ')}`);\n } catch (e) {\n log.warn('bundled skills not synced', (e as Error).message);\n }\n }\n app.skills.syncFromDisk?.();\n // Registry and disk drift apart when skills are removed by hand or a layout migration\n // moves files; left alone, the UI lists skills that cannot load.\n const fixed = app.skills.reconcile?.() as { repaired: string[]; removed: string[] } | undefined;\n if (fixed?.repaired.length) log.info(`repaired ${fixed.repaired.length} skill path(s): ${fixed.repaired.join(', ')}`);\n if (fixed?.removed.length) log.info(`dropped ${fixed.removed.length} skill row(s) with no files on disk`);\n log.info(`skills ready (${app.store.listSkills().length} registered)`);\n } catch (err) {\n log.warn('skills subsystem unavailable', (err as Error).message);\n }\n}\n\nasync function wireBrowser(app: App): Promise<void> {\n try {\n const mod = await optionalImport('browser', () => import('./computer/browser.js'));\n const Ctor = mod?.BrowserService ?? mod?.default;\n if (!Ctor) return void log.warn('browser subsystem unavailable: no BrowserService export');\n const svc = new Ctor({ profileDir: app.cfg.paths.browserProfile, bus: app.bus, headless: true });\n let toolsMod: any = null;\n toolsMod = await optionalImport('browser tools', () => import('./computer/tools.js'));\n // Each bot drives its own page (\"screen\") on the one shared browser profile.\n const cache = new Map<string, unknown>();\n svc.toolServerFor = (botId: string) => {\n if (!toolsMod?.createBrowserToolServer) return undefined;\n let s = cache.get(botId);\n if (!s) {\n s = toolsMod.createBrowserToolServer(svc, botId, app.cfg.paths.workspace);\n cache.set(botId, s);\n }\n return s;\n };\n app.browser = svc;\n log.info('browser computer service ready');\n } catch (err) {\n log.warn('browser subsystem unavailable', (err as Error).message);\n }\n}\n\nasync function wireScheduler(app: App): Promise<void> {\n try {\n const mod = await optionalImport('scheduler', () => import('./scheduler/scheduler.js'));\n const Ctor = mod?.Scheduler ?? mod?.default;\n if (!Ctor) return void log.warn('scheduler subsystem unavailable: no Scheduler export');\n app.scheduler = new Ctor({\n store: app.store, bus: app.bus, manager: app.manager, getSettings: app.getSettings,\n });\n app.scheduler.start?.();\n log.info(`scheduler started (${app.store.listRoutines().filter((r) => r.enabled).length} active routines)`);\n } catch (err) {\n log.warn('scheduler subsystem unavailable', (err as Error).message);\n }\n}\n\n/** Deliver queued bot-to-bot mail on boot so handoffs survive a restart. */\nexport function drainMailbox(app: App): number {\n let n = 0;\n for (const bot of app.store.listBots()) {\n for (const m of app.store.listMail(bot.id)) {\n const from = app.store.getBot(m.fromBotId);\n app.manager.enqueue({\n botId: bot.id, threadId: bot.threadId!, origin: 'bot', hops: m.hops,\n prompt: `**Handoff from @${from?.slug ?? 'unknown'}:**\\n\\n${m.contentMd}`,\n });\n app.store.markDelivered(m.id);\n n++;\n }\n }\n return n;\n}\n\nexport function workspaceRelative(root: string, p: string): string | null {\n const resolved = path.resolve(root, p);\n const rel = path.relative(root, resolved);\n if (rel.startsWith('..') || path.isAbsolute(rel)) return null;\n return resolved;\n}\n\nexport function ensureWorkspaceFile(p: string): boolean {\n try { return fs.statSync(p).isFile(); } catch { return false; }\n}\n", "import Database from 'better-sqlite3';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { migrate } from './migrations.js';\nimport { logger } from '../util/log.js';\n\nexport type DB = Database.Database;\n\nconst log = logger('db');\n\nexport interface OpenDbOptions {\n /**\n * Where a pre-migration snapshot is written. Defaults to a `backups` sibling of the database\n * file, which is `paths.backups` for a real install. Ignored for `:memory:`.\n */\n backupsDir?: string;\n}\n\nexport function openDb(file: string, opts: OpenDbOptions = {}): DB {\n if (file !== ':memory:') fs.mkdirSync(path.dirname(file), { recursive: true });\n const db = new Database(file);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n db.pragma('busy_timeout = 5000');\n\n // The schema is applied by the migration runner, not by exec'ing SCHEMA_SQL here \u2014 see\n // migrations.ts for why a bare `CREATE TABLE IF NOT EXISTS` blob cannot ship an update to a\n // database that already exists on a user's machine.\n const backupsDir =\n file === ':memory:' ? undefined : (opts.backupsDir ?? path.join(path.dirname(file), 'backups'));\n const result = migrate(db, { backupsDir });\n // Creating the schema in an empty database is not news; upgrading one that already held a\n // user's data is the thing a support log needs to show.\n if (result.from > 0 && result.applied.length) {\n log.info(\n `schema ${result.from} -> ${result.to}: ${result.applied.map((a) => a.name).join(', ')}` +\n (result.backupPath ? ` (snapshot: ${result.backupPath})` : ''),\n );\n }\n return db;\n}\n", "// The schema evolves on the user's machine, not ours. Once ant-bot ships, a `CREATE TABLE IF NOT\n// EXISTS` blob is silently wrong: the statement succeeds against an old database and the new column\n// is simply absent, so the first query that reads it fails at runtime, far from the cause. This\n// module is the ordered ledger that makes a change actually reach an existing `~/.ant-bot/antbot.db`.\n//\n// Shape follows the rest of the codebase: `planMigrations` is the pure decision, `migrate` is the\n// I/O wrapper (see `detectBlockFromSignals` / `computeBackupItems` / `runDoctor(deps)`).\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { DB } from './db.js';\nimport { SCHEMA_SQL } from './schema.js';\n\nexport class MigrationError extends Error {\n constructor(\n public code: 'MIGRATION_ORDER' | 'MIGRATION_DOWNGRADE' | 'MIGRATION_FAILED',\n message: string,\n ) {\n super(message);\n this.name = 'MigrationError';\n }\n}\n\nexport interface Migration {\n /** Strictly increasing, starting at 1. Never renumber a released migration. */\n version: number;\n /** Short slug, recorded in the ledger so a support log says what ran. */\n name: string;\n /** Executed with `db.exec` inside a transaction. Must be idempotent-safe to re-read, not re-run. */\n up: string;\n}\n\n/**\n * Migration 1 is the schema as it stood when the runner was introduced. Every database in\n * existence at that point already has it, which is why `detectBaselineAdoption` exists \u2014 such a\n * database is adopted at this version rather than being mistaken for an empty one.\n */\nexport const BASELINE_VERSION = 1;\n\n/**\n * A table that only the baseline creates. Used to tell \"existing database, no ledger yet\" from\n * \"brand new file\"; `bots` has been in the schema since the first commit and is never dropped.\n */\nconst BASELINE_SENTINEL_TABLE = 'bots';\n\nexport const MIGRATIONS: Migration[] = [\n { version: BASELINE_VERSION, name: 'baseline', up: SCHEMA_SQL },\n {\n version: 2,\n name: 'connectors',\n // Plain CREATE TABLE, not IF NOT EXISTS: the ledger already guarantees this runs once, and\n // this module exists precisely because IF NOT EXISTS turns a real conflict into silence.\n up: `\nCREATE TABLE connectors (\n id TEXT PRIMARY KEY, name TEXT UNIQUE NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n config_json TEXT NOT NULL,\n enabled INTEGER NOT NULL DEFAULT 1,\n created_at INTEGER NOT NULL\n);\nCREATE TABLE bot_connectors (\n bot_id TEXT NOT NULL, connector_id TEXT NOT NULL,\n enabled INTEGER NOT NULL DEFAULT 1,\n PRIMARY KEY (bot_id, connector_id)\n);\n`,\n },\n {\n version: 3,\n name: 'connector-kind-and-health',\n // Built-in connectors (served by the daemon) alongside custom ones, and the last verdict a\n // check or a turn reached \u2014 so the screen shows a connector's real state instead of a toast\n // that has already vanished.\n up: `\nALTER TABLE connectors ADD COLUMN kind TEXT NOT NULL DEFAULT 'custom';\nALTER TABLE connectors ADD COLUMN last_status TEXT;\nALTER TABLE connectors ADD COLUMN last_error TEXT;\nALTER TABLE connectors ADD COLUMN checked_at INTEGER;\n`,\n },\n];\n\nexport const SCHEMA_VERSION_SQL = `\nCREATE TABLE IF NOT EXISTS schema_version (\n version INTEGER PRIMARY KEY, name TEXT NOT NULL, applied_at INTEGER NOT NULL\n);\n`;\n\n/* ------------------------------- pure core ------------------------------- */\n\n/**\n * A database created before the migration runner has the baseline schema but no ledger rows.\n * Recognising that is the difference between adopting it and re-running history over it.\n */\nexport function detectBaselineAdoption(hasLedgerRows: boolean, hasBaselineTable: boolean): boolean {\n return !hasLedgerRows && hasBaselineTable;\n}\n\n/**\n * Decides what to run. Throws rather than guessing: an out-of-order list is an authoring bug, and\n * a database numbered past the code is an older ant-bot opening a newer install's data \u2014 running\n * nothing there would let it write rows the newer schema forbids.\n */\nexport function planMigrations(currentVersion: number, migrations: Migration[]): Migration[] {\n const sorted = [...migrations].sort((a, b) => a.version - b.version);\n let prev = 0;\n for (const m of sorted) {\n if (!Number.isInteger(m.version) || m.version < 1) {\n throw new MigrationError('MIGRATION_ORDER', `migration \"${m.name}\" has invalid version ${m.version}`);\n }\n if (m.version === prev) {\n throw new MigrationError('MIGRATION_ORDER', `duplicate migration version ${m.version}`);\n }\n prev = m.version;\n }\n\n const latest = sorted.length ? sorted[sorted.length - 1]!.version : 0;\n if (currentVersion > latest) {\n throw new MigrationError(\n 'MIGRATION_DOWNGRADE',\n `database is at schema version ${currentVersion} but this build only knows up to ${latest}. ` +\n `Upgrade ant-bot (npm i -g @michael-joseph-miller/ant-bot) rather than downgrading the database.`,\n );\n }\n\n return sorted.filter((m) => m.version > currentVersion);\n}\n\n/* ------------------------------- I/O wrapper ------------------------------- */\n\nexport interface MigrateResult {\n from: number;\n to: number;\n applied: { version: number; name: string }[];\n /** Path of the pre-migration snapshot, when one was taken. */\n backupPath?: string;\n}\n\nexport interface MigrateOptions {\n /** Where a pre-migration snapshot is written. Omit to skip the snapshot (in-memory databases). */\n backupsDir?: string;\n migrations?: Migration[];\n now?: () => number;\n}\n\nfunction readCurrentVersion(db: DB): { version: number; adopted: boolean } {\n db.exec(SCHEMA_VERSION_SQL);\n const row = db.prepare(`SELECT MAX(version) v FROM schema_version`).get() as { v: number | null };\n if (row.v !== null) return { version: row.v, adopted: false };\n\n const sentinel = db\n .prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`)\n .get(BASELINE_SENTINEL_TABLE) as { name: string } | undefined;\n const adopted = detectBaselineAdoption(false, Boolean(sentinel));\n return { version: adopted ? BASELINE_VERSION : 0, adopted };\n}\n\n/**\n * Snapshots the database file before a migration touches it. `VACUUM INTO` is used rather than a\n * file copy because it checkpoints WAL content into the snapshot \u2014 copying `antbot.db` alone would\n * silently lose whatever is still sitting in `antbot.db-wal`.\n */\nfunction snapshot(db: DB, backupsDir: string, toVersion: number, now: () => number): string {\n fs.mkdirSync(backupsDir, { recursive: true });\n const stamp = new Date(now()).toISOString().replace(/[:.]/g, '-');\n const dest = path.join(backupsDir, `antbot-pre-v${toVersion}-${stamp}.db`);\n db.prepare(`VACUUM INTO ?`).run(dest);\n return dest;\n}\n\n/**\n * Brings `db` up to the latest schema version, snapshotting first if there is anything to lose.\n * Each migration commits on its own so a failure halfway through a list leaves the ledger honest\n * about how far it got.\n */\nexport function migrate(db: DB, opts: MigrateOptions = {}): MigrateResult {\n const migrations = opts.migrations ?? MIGRATIONS;\n const now = opts.now ?? Date.now;\n const { version: from, adopted } = readCurrentVersion(db);\n\n // OR IGNORE guards only the adoption row below; `planMigrations` already guarantees the loop\n // never re-inserts a version the ledger holds.\n const record = db.prepare(\n `INSERT OR IGNORE INTO schema_version (version, name, applied_at) VALUES (?, ?, ?)`,\n );\n // Write the adoption down the first time we see a pre-runner database. Without this the ledger\n // stays empty until some *later* migration runs, and then reads as though the baseline never\n // did \u2014 which is exactly the question a support log gets asked.\n if (adopted) {\n const baseline = migrations.find((m) => m.version === BASELINE_VERSION);\n record.run(BASELINE_VERSION, baseline?.name ?? 'baseline', now());\n }\n\n const pending = planMigrations(from, migrations);\n if (pending.length === 0) return { from, to: from, applied: [] };\n\n const target = pending[pending.length - 1]!.version;\n\n // A brand-new database (version 0) has nothing to lose, and snapshotting it would litter\n // `backups/` with an empty file on every first run.\n let backupPath: string | undefined;\n if (opts.backupsDir && from > 0) {\n backupPath = snapshot(db, opts.backupsDir, target, now);\n }\n\n const applied: { version: number; name: string }[] = [];\n for (const m of pending) {\n const run = db.transaction(() => {\n db.exec(m.up);\n record.run(m.version, m.name, now());\n });\n try {\n run();\n } catch (err) {\n throw new MigrationError(\n 'MIGRATION_FAILED',\n `migration ${m.version} (${m.name}) failed: ${(err as Error).message}` +\n (backupPath ? `. The pre-migration database was saved to ${backupPath}` : ''),\n );\n }\n applied.push({ version: m.version, name: m.name });\n }\n\n return { from, to: target, applied, backupPath };\n}\n", "export const SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS bots (\n id TEXT PRIMARY KEY, slug TEXT UNIQUE NOT NULL, name TEXT NOT NULL,\n title TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '',\n avatar_emoji TEXT NOT NULL DEFAULT '\uD83E\uDD16', model_tier TEXT NOT NULL DEFAULT 'sonnet',\n pinned INTEGER NOT NULL DEFAULT 0, hidden INTEGER NOT NULL DEFAULT 0,\n notifications INTEGER NOT NULL DEFAULT 1, session_id TEXT,\n state TEXT NOT NULL DEFAULT 'idle', attention TEXT NOT NULL DEFAULT 'none',\n thread_id TEXT, created_at INTEGER NOT NULL, deleted_at INTEGER\n);\nCREATE TABLE IF NOT EXISTS threads (\n id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK(kind IN ('dm','group')),\n title TEXT NOT NULL DEFAULT '', member_bot_ids TEXT NOT NULL DEFAULT '[]',\n pinned INTEGER NOT NULL DEFAULT 0, hidden INTEGER NOT NULL DEFAULT 0,\n last_read_at INTEGER NOT NULL DEFAULT 0, created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY, thread_id TEXT NOT NULL,\n author_kind TEXT NOT NULL CHECK(author_kind IN ('user','bot','system')),\n author_bot_id TEXT, reply_to_id TEXT, content_md TEXT NOT NULL DEFAULT '',\n cards TEXT NOT NULL DEFAULT '[]', streaming INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_messages_thread ON messages(thread_id, created_at);\nCREATE TABLE IF NOT EXISTS attachments (\n id TEXT PRIMARY KEY, message_id TEXT, path TEXT NOT NULL, name TEXT NOT NULL,\n mime TEXT NOT NULL, bytes INTEGER NOT NULL, created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS approvals (\n id TEXT PRIMARY KEY, bot_id TEXT NOT NULL, thread_id TEXT NOT NULL,\n tool_name TEXT NOT NULL, input_summary TEXT NOT NULL, raw_input TEXT NOT NULL DEFAULT 'null',\n status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','allowed','denied','expired')),\n decided_by TEXT CHECK(decided_by IN ('user','rule','auto_review')),\n reason TEXT NOT NULL DEFAULT '', rule_id TEXT,\n created_at INTEGER NOT NULL, decided_at INTEGER\n);\nCREATE INDEX IF NOT EXISTS idx_approvals_status ON approvals(status);\nCREATE TABLE IF NOT EXISTS rules (\n id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK(kind IN ('require','allow')),\n tool_pattern TEXT NOT NULL DEFAULT '*', input_pattern TEXT NOT NULL DEFAULT '',\n scope_note TEXT NOT NULL DEFAULT '', builtin INTEGER NOT NULL DEFAULT 0,\n enabled INTEGER NOT NULL DEFAULT 1, created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS skills (\n id TEXT PRIMARY KEY, slug TEXT UNIQUE NOT NULL, name TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '', path TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'user' CHECK(source IN ('user','taught','imported')),\n created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS bot_skills (\n bot_id TEXT NOT NULL, skill_id TEXT NOT NULL, enabled INTEGER NOT NULL DEFAULT 1,\n PRIMARY KEY (bot_id, skill_id)\n);\nCREATE TABLE IF NOT EXISTS routines (\n id TEXT PRIMARY KEY, bot_id TEXT NOT NULL, name TEXT NOT NULL,\n cron_expr TEXT NOT NULL, timezone TEXT NOT NULL DEFAULT 'UTC',\n instruction_md TEXT NOT NULL, enabled INTEGER NOT NULL DEFAULT 1,\n last_run_at INTEGER, next_run_at INTEGER, created_at INTEGER NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_routines_bot ON routines(bot_id);\nCREATE TABLE IF NOT EXISTS routine_runs (\n id TEXT PRIMARY KEY, routine_id TEXT NOT NULL, started_at INTEGER NOT NULL,\n finished_at INTEGER, status TEXT NOT NULL CHECK(status IN ('running','ok','failed','interrupted')),\n summary TEXT NOT NULL DEFAULT '', thread_id TEXT, is_test INTEGER NOT NULL DEFAULT 0\n);\nCREATE INDEX IF NOT EXISTS idx_runs_routine ON routine_runs(routine_id, started_at DESC);\nCREATE TABLE IF NOT EXISTS mailbox (\n id TEXT PRIMARY KEY, from_bot_id TEXT NOT NULL, to_bot_id TEXT NOT NULL,\n content_md TEXT NOT NULL, hops INTEGER NOT NULL DEFAULT 1,\n delivered INTEGER NOT NULL DEFAULT 0, created_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS usage (\n id TEXT PRIMARY KEY, bot_id TEXT NOT NULL, turn_id TEXT NOT NULL, model TEXT NOT NULL,\n input_tokens INTEGER NOT NULL DEFAULT 0, output_tokens INTEGER NOT NULL DEFAULT 0,\n cache_read_tokens INTEGER NOT NULL DEFAULT 0, cost_estimate REAL NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_usage_created ON usage(created_at);\nCREATE TABLE IF NOT EXISTS settings (key TEXT PRIMARY KEY, value TEXT NOT NULL);\nCREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(\n content_md, content='messages', content_rowid='rowid'\n);\nCREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN\n INSERT INTO messages_fts(rowid, content_md) VALUES (new.rowid, new.content_md);\nEND;\nCREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN\n INSERT INTO messages_fts(messages_fts, rowid, content_md) VALUES('delete', old.rowid, old.content_md);\nEND;\nCREATE TRIGGER IF NOT EXISTS messages_au AFTER UPDATE ON messages BEGIN\n INSERT INTO messages_fts(messages_fts, rowid, content_md) VALUES('delete', old.rowid, old.content_md);\n INSERT INTO messages_fts(rowid, content_md) VALUES (new.rowid, new.content_md);\nEND;\n`;\n", "import type { DB } from './db.js';\nimport { newId, now, slugify } from '../util/ids.js';\nimport {\n LIMITS, LIMIT_ERROR, LimitError,\n type Bot, type Thread, type Message, type Attachment, type Approval, type Rule,\n type Skill, type Routine, type RoutineRun, type MailboxEntry, type UsageRow,\n type Card, type BotState, type Attention, type ModelTier, type Settings,\n type Connector, type ConnectorConfig,\n SettingsSchema, ConnectorConfigSchema,\n} from '@antbot/contract';\n\n/* ------------------------------ row mappers ------------------------------ */\nconst b = (v: unknown): boolean => v === 1 || v === true;\nconst i = (v: boolean | undefined, d = false): number => ((v ?? d) ? 1 : 0);\n\ntype Row = Record<string, any>;\n\nconst toBot = (r: Row): Bot => ({\n id: r.id, slug: r.slug, name: r.name, title: r.title, description: r.description,\n avatarEmoji: r.avatar_emoji, modelTier: r.model_tier as ModelTier,\n pinned: b(r.pinned), hidden: b(r.hidden), notifications: b(r.notifications),\n sessionId: r.session_id, state: r.state as BotState, attention: r.attention as Attention,\n threadId: r.thread_id, createdAt: r.created_at, deletedAt: r.deleted_at,\n});\nconst toThread = (r: Row): Thread => ({\n id: r.id, kind: r.kind, title: r.title, memberBotIds: JSON.parse(r.member_bot_ids),\n pinned: b(r.pinned), hidden: b(r.hidden), lastReadAt: r.last_read_at, createdAt: r.created_at,\n});\nconst toMessage = (r: Row): Message => ({\n id: r.id, threadId: r.thread_id, authorKind: r.author_kind, authorBotId: r.author_bot_id,\n replyToId: r.reply_to_id, contentMd: r.content_md, cards: JSON.parse(r.cards),\n streaming: b(r.streaming), createdAt: r.created_at,\n});\nconst toApproval = (r: Row): Approval => ({\n id: r.id, botId: r.bot_id, threadId: r.thread_id, toolName: r.tool_name,\n inputSummary: r.input_summary, rawInput: JSON.parse(r.raw_input), status: r.status,\n decidedBy: r.decided_by, reason: r.reason, ruleId: r.rule_id,\n createdAt: r.created_at, decidedAt: r.decided_at,\n});\nconst toRule = (r: Row): Rule => ({\n id: r.id, kind: r.kind, toolPattern: r.tool_pattern, inputPattern: r.input_pattern,\n scopeNote: r.scope_note, builtin: b(r.builtin), enabled: b(r.enabled), createdAt: r.created_at,\n});\nconst toSkill = (r: Row): Skill => ({\n id: r.id, slug: r.slug, name: r.name, description: r.description, path: r.path,\n source: r.source, createdAt: r.created_at,\n});\n/**\n * Config is stored as JSON and parsed back through the schema rather than cast: a row written by\n * an older build (or edited by hand) that no longer matches the union should fail here, loudly,\n * not surface as a malformed server config at turn time.\n */\nconst toConnector = (r: Row): Connector => ({\n id: r.id, name: r.name, description: r.description,\n kind: r.kind === 'builtin' ? 'builtin' : 'custom',\n config: ConnectorConfigSchema.parse(JSON.parse(r.config_json)),\n enabled: b(r.enabled),\n lastStatus: r.last_status ?? null, lastError: r.last_error ?? null, checkedAt: r.checked_at ?? null,\n createdAt: r.created_at,\n});\nconst toRoutine = (r: Row): Routine => ({\n id: r.id, botId: r.bot_id, name: r.name, cronExpr: r.cron_expr, timezone: r.timezone,\n instructionMd: r.instruction_md, enabled: b(r.enabled), lastRunAt: r.last_run_at,\n nextRunAt: r.next_run_at, createdAt: r.created_at,\n});\nconst toRun = (r: Row): RoutineRun => ({\n id: r.id, routineId: r.routine_id, startedAt: r.started_at, finishedAt: r.finished_at,\n status: r.status, summary: r.summary, threadId: r.thread_id, isTest: b(r.is_test),\n});\nconst toAttachment = (r: Row): Attachment => ({\n id: r.id, messageId: r.message_id, path: r.path, name: r.name, mime: r.mime,\n bytes: r.bytes, createdAt: r.created_at,\n});\nconst toMail = (r: Row): MailboxEntry => ({\n id: r.id, fromBotId: r.from_bot_id, toBotId: r.to_bot_id, contentMd: r.content_md,\n hops: r.hops, delivered: b(r.delivered), createdAt: r.created_at,\n});\nconst toUsage = (r: Row): UsageRow => ({\n id: r.id, botId: r.bot_id, turnId: r.turn_id, model: r.model, inputTokens: r.input_tokens,\n outputTokens: r.output_tokens, cacheReadTokens: r.cache_read_tokens,\n costEstimate: r.cost_estimate, createdAt: r.created_at,\n});\n\n/* -------------------------------- store --------------------------------- */\nexport class Store {\n constructor(public db: DB) {}\n\n /* ---- bots ---- */\n countBotsAndGroups(): number {\n const bots = this.db.prepare(`SELECT COUNT(*) c FROM bots WHERE deleted_at IS NULL`).get() as Row;\n const groups = this.db.prepare(`SELECT COUNT(*) c FROM threads WHERE kind='group'`).get() as Row;\n return bots.c + groups.c;\n }\n\n createBot(input: { name: string; title?: string; description?: string; avatarEmoji?: string; modelTier?: ModelTier }): Bot {\n if (this.countBotsAndGroups() >= LIMITS.MAX_BOTS_AND_GROUPS)\n throw new LimitError(LIMIT_ERROR.TOO_MANY_BOTS, `Limit of ${LIMITS.MAX_BOTS_AND_GROUPS} bots and groups reached`);\n const existing = new Set(\n (this.db.prepare(`SELECT slug FROM bots`).all() as Row[]).map((r) => r.slug as string),\n );\n const id = newId();\n const thread = this.createThread({ kind: 'dm', title: input.name, memberBotIds: [id] });\n this.db\n .prepare(\n `INSERT INTO bots (id,slug,name,title,description,avatar_emoji,model_tier,pinned,hidden,notifications,session_id,state,attention,thread_id,created_at)\n VALUES (@id,@slug,@name,@title,@description,@avatar_emoji,@model_tier,0,0,1,NULL,'idle','none',@thread_id,@created_at)`,\n )\n .run({\n id, slug: slugify(input.name, existing), name: input.name, title: input.title ?? '',\n description: input.description ?? '', avatar_emoji: input.avatarEmoji ?? '\uD83E\uDD16',\n model_tier: input.modelTier ?? 'sonnet', thread_id: thread.id, created_at: now(),\n });\n return this.getBot(id)!;\n }\n\n getBot(id: string): Bot | null {\n const r = this.db.prepare(`SELECT * FROM bots WHERE id=? AND deleted_at IS NULL`).get(id) as Row | undefined;\n return r ? toBot(r) : null;\n }\n getBotBySlug(slug: string): Bot | null {\n const r = this.db.prepare(`SELECT * FROM bots WHERE slug=? AND deleted_at IS NULL`).get(slug) as Row | undefined;\n return r ? toBot(r) : null;\n }\n listBots(includeHidden = true): Bot[] {\n const rows = this.db\n .prepare(`SELECT * FROM bots WHERE deleted_at IS NULL ${includeHidden ? '' : 'AND hidden=0'} ORDER BY pinned DESC, created_at ASC`)\n .all() as Row[];\n return rows.map(toBot);\n }\n updateBot(id: string, patch: Partial<Bot>): Bot | null {\n const cur = this.getBot(id);\n if (!cur) return null;\n const m: Record<string, unknown> = {\n name: patch.name ?? cur.name, title: patch.title ?? cur.title,\n description: patch.description ?? cur.description, avatar_emoji: patch.avatarEmoji ?? cur.avatarEmoji,\n model_tier: patch.modelTier ?? cur.modelTier,\n pinned: i(patch.pinned, cur.pinned), hidden: i(patch.hidden, cur.hidden),\n notifications: i(patch.notifications, cur.notifications),\n session_id: patch.sessionId !== undefined ? patch.sessionId : cur.sessionId,\n state: patch.state ?? cur.state, attention: patch.attention ?? cur.attention, id,\n };\n this.db.prepare(\n `UPDATE bots SET name=@name,title=@title,description=@description,avatar_emoji=@avatar_emoji,\n model_tier=@model_tier,pinned=@pinned,hidden=@hidden,notifications=@notifications,\n session_id=@session_id,state=@state,attention=@attention WHERE id=@id`,\n ).run(m);\n return this.getBot(id);\n }\n deleteBot(id: string): void {\n const bot = this.getBot(id);\n if (!bot) return;\n this.db.prepare(`UPDATE bots SET deleted_at=? WHERE id=?`).run(now(), id);\n this.db.prepare(`DELETE FROM routines WHERE bot_id=?`).run(id);\n if (bot.threadId) this.db.prepare(`DELETE FROM threads WHERE id=?`).run(bot.threadId);\n }\n /**\n * Clear a bot's conversation and its SDK session, keeping everything that defines the bot.\n *\n * Deliberately narrow. Memory, skills, connectors, routines and the bot's files all survive \u2014\n * those are the bot. What goes is the accumulated conversation: the messages in its thread and\n * the `session_id` the SDK resumes from, which is what makes a turn carry prior context.\n *\n * Messages are deleted rather than the thread, so the thread id every other row points at\n * stays valid; the FTS triggers keep the search index in step.\n */\n resetBotSession(id: string): { messagesDeleted: number } | null {\n const bot = this.getBot(id);\n if (!bot) return null;\n let messagesDeleted = 0;\n if (bot.threadId) {\n const info = this.db.prepare(`DELETE FROM messages WHERE thread_id=?`).run(bot.threadId);\n messagesDeleted = info.changes;\n this.db.prepare(`UPDATE threads SET last_read_at=0 WHERE id=?`).run(bot.threadId);\n }\n // Null, not a new id: the next turn starts a session instead of resuming a dead one.\n this.db.prepare(`UPDATE bots SET session_id=NULL, attention='none' WHERE id=?`).run(id);\n return { messagesDeleted };\n }\n\n duplicateBot(id: string): Bot | null {\n const src = this.getBot(id);\n if (!src) return null;\n const copy = this.createBot({\n name: `${src.name} copy`, title: src.title, description: src.description,\n avatarEmoji: src.avatarEmoji, modelTier: src.modelTier,\n });\n // carries skills + connectors + routines; NOT history or memory (outline \u00A74)\n for (const bs of this.db.prepare(`SELECT * FROM bot_skills WHERE bot_id=?`).all(id) as Row[])\n this.db.prepare(`INSERT OR REPLACE INTO bot_skills (bot_id,skill_id,enabled) VALUES (?,?,?)`).run(copy.id, bs.skill_id, bs.enabled);\n for (const bc of this.db.prepare(`SELECT * FROM bot_connectors WHERE bot_id=?`).all(id) as Row[])\n this.db.prepare(`INSERT OR REPLACE INTO bot_connectors (bot_id,connector_id,enabled) VALUES (?,?,?)`).run(copy.id, bc.connector_id, bc.enabled);\n for (const r of this.listRoutines(id))\n this.createRoutine({ botId: copy.id, name: r.name, cronExpr: r.cronExpr, timezone: r.timezone, instructionMd: r.instructionMd, enabled: false });\n return copy;\n }\n\n /* ---- threads & messages ---- */\n createThread(input: { kind: 'dm' | 'group'; title?: string; memberBotIds: string[] }): Thread {\n if (input.kind === 'group') {\n const n = input.memberBotIds.length;\n if (n < LIMITS.MIN_GROUP_MEMBERS || n > LIMITS.MAX_GROUP_MEMBERS)\n throw new LimitError(LIMIT_ERROR.GROUP_SIZE, `A group needs ${LIMITS.MIN_GROUP_MEMBERS}\u2013${LIMITS.MAX_GROUP_MEMBERS} bots (got ${n})`);\n if (this.countBotsAndGroups() >= LIMITS.MAX_BOTS_AND_GROUPS)\n throw new LimitError(LIMIT_ERROR.TOO_MANY_BOTS, `Limit of ${LIMITS.MAX_BOTS_AND_GROUPS} bots and groups reached`);\n }\n const id = newId();\n this.db.prepare(\n `INSERT INTO threads (id,kind,title,member_bot_ids,pinned,hidden,last_read_at,created_at)\n VALUES (?,?,?,?,0,0,0,?)`,\n ).run(id, input.kind, input.title ?? '', JSON.stringify(input.memberBotIds), now());\n return this.getThread(id)!;\n }\n getThread(id: string): Thread | null {\n const r = this.db.prepare(`SELECT * FROM threads WHERE id=?`).get(id) as Row | undefined;\n return r ? toThread(r) : null;\n }\n listThreads(kind?: 'dm' | 'group'): Thread[] {\n const rows = (kind\n ? this.db.prepare(`SELECT * FROM threads WHERE kind=? ORDER BY created_at ASC`).all(kind)\n : this.db.prepare(`SELECT * FROM threads ORDER BY created_at ASC`).all()) as Row[];\n return rows.map(toThread);\n }\n updateThread(id: string, patch: Partial<Thread>): Thread | null {\n const cur = this.getThread(id);\n if (!cur) return null;\n this.db.prepare(\n `UPDATE threads SET title=?, member_bot_ids=?, pinned=?, hidden=?, last_read_at=? WHERE id=?`,\n ).run(\n patch.title ?? cur.title, JSON.stringify(patch.memberBotIds ?? cur.memberBotIds),\n i(patch.pinned, cur.pinned), i(patch.hidden, cur.hidden), patch.lastReadAt ?? cur.lastReadAt, id,\n );\n return this.getThread(id);\n }\n deleteThread(id: string): void {\n this.db.prepare(`DELETE FROM threads WHERE id=?`).run(id);\n this.db.prepare(`DELETE FROM messages WHERE thread_id=?`).run(id);\n }\n\n createMessage(input: {\n threadId: string; authorKind: 'user' | 'bot' | 'system'; authorBotId?: string | null;\n contentMd?: string; cards?: Card[]; streaming?: boolean; replyToId?: string | null;\n }): Message {\n const id = newId();\n this.db.prepare(\n `INSERT INTO messages (id,thread_id,author_kind,author_bot_id,reply_to_id,content_md,cards,streaming,created_at)\n VALUES (?,?,?,?,?,?,?,?,?)`,\n ).run(\n id, input.threadId, input.authorKind, input.authorBotId ?? null, input.replyToId ?? null,\n input.contentMd ?? '', JSON.stringify(input.cards ?? []), i(input.streaming), now(),\n );\n return this.getMessage(id)!;\n }\n getMessage(id: string): Message | null {\n const r = this.db.prepare(`SELECT * FROM messages WHERE id=?`).get(id) as Row | undefined;\n return r ? toMessage(r) : null;\n }\n listMessages(threadId: string, limit = 500): Message[] {\n const rows = this.db\n .prepare(`SELECT * FROM messages WHERE thread_id=? ORDER BY created_at ASC LIMIT ?`)\n .all(threadId, limit) as Row[];\n return rows.map(toMessage);\n }\n updateMessage(id: string, patch: { contentMd?: string; cards?: Card[]; streaming?: boolean }): Message | null {\n const cur = this.getMessage(id);\n if (!cur) return null;\n this.db.prepare(`UPDATE messages SET content_md=?, cards=?, streaming=? WHERE id=?`).run(\n patch.contentMd ?? cur.contentMd, JSON.stringify(patch.cards ?? cur.cards), i(patch.streaming, cur.streaming), id,\n );\n return this.getMessage(id);\n }\n appendCard(id: string, card: Card): number {\n const cur = this.getMessage(id);\n if (!cur) return -1;\n const cards = [...cur.cards, card];\n this.db.prepare(`UPDATE messages SET cards=? WHERE id=?`).run(JSON.stringify(cards), id);\n return cards.length - 1;\n }\n updateCard(id: string, index: number, card: Card): void {\n const cur = this.getMessage(id);\n if (!cur || !cur.cards[index]) return;\n const cards = [...cur.cards];\n cards[index] = card;\n this.db.prepare(`UPDATE messages SET cards=? WHERE id=?`).run(JSON.stringify(cards), id);\n }\n lastMessageAt(threadId: string): number {\n const r = this.db.prepare(`SELECT MAX(created_at) m FROM messages WHERE thread_id=?`).get(threadId) as Row;\n return r?.m ?? 0;\n }\n\n /* ---- attachments ---- */\n createAttachment(a: Omit<Attachment, 'id' | 'createdAt'>): Attachment {\n const isVideo = a.mime.startsWith('video/');\n const cap = isVideo ? LIMITS.MAX_VIDEO_ATTACHMENT_BYTES : LIMITS.MAX_ATTACHMENT_BYTES;\n if (a.bytes > cap)\n throw new LimitError(LIMIT_ERROR.ATTACHMENT_TOO_LARGE, `${a.name} is ${(a.bytes / 1048576).toFixed(1)} MB; limit is ${cap / 1048576} MB`);\n const id = newId();\n this.db.prepare(\n `INSERT INTO attachments (id,message_id,path,name,mime,bytes,created_at) VALUES (?,?,?,?,?,?,?)`,\n ).run(id, a.messageId ?? null, a.path, a.name, a.mime, a.bytes, now());\n return toAttachment(this.db.prepare(`SELECT * FROM attachments WHERE id=?`).get(id) as Row);\n }\n getAttachment(id: string): Attachment | null {\n const r = this.db.prepare(`SELECT * FROM attachments WHERE id=?`).get(id) as Row | undefined;\n return r ? toAttachment(r) : null;\n }\n attachToMessage(ids: string[], messageId: string): void {\n if (ids.length > LIMITS.MAX_ATTACHMENTS_PER_MESSAGE)\n throw new LimitError(LIMIT_ERROR.TOO_MANY_ATTACHMENTS, `At most ${LIMITS.MAX_ATTACHMENTS_PER_MESSAGE} attachments per message`);\n const stmt = this.db.prepare(`UPDATE attachments SET message_id=? WHERE id=?`);\n for (const id of ids) stmt.run(messageId, id);\n }\n listAttachmentsForMessage(messageId: string): Attachment[] {\n return (this.db.prepare(`SELECT * FROM attachments WHERE message_id=?`).all(messageId) as Row[]).map(toAttachment);\n }\n\n /* ---- approvals ---- */\n createApproval(a: { botId: string; threadId: string; toolName: string; inputSummary: string; rawInput: unknown; reason?: string }): Approval {\n const id = newId();\n this.db.prepare(\n `INSERT INTO approvals (id,bot_id,thread_id,tool_name,input_summary,raw_input,status,reason,created_at)\n VALUES (?,?,?,?,?,?, 'pending', ?, ?)`,\n ).run(id, a.botId, a.threadId, a.toolName, a.inputSummary, JSON.stringify(a.rawInput ?? null), a.reason ?? '', now());\n return this.getApproval(id)!;\n }\n getApproval(id: string): Approval | null {\n const r = this.db.prepare(`SELECT * FROM approvals WHERE id=?`).get(id) as Row | undefined;\n return r ? toApproval(r) : null;\n }\n listPendingApprovals(): Approval[] {\n return (this.db.prepare(`SELECT * FROM approvals WHERE status='pending' ORDER BY created_at ASC`).all() as Row[]).map(toApproval);\n }\n resolveApproval(id: string, status: 'allowed' | 'denied' | 'expired', decidedBy: 'user' | 'rule' | 'auto_review', ruleId?: string | null, reason?: string): Approval | null {\n const cur = this.getApproval(id);\n if (!cur) return null;\n this.db.prepare(`UPDATE approvals SET status=?, decided_by=?, rule_id=?, reason=?, decided_at=? WHERE id=?`)\n .run(status, decidedBy, ruleId ?? cur.ruleId, reason ?? cur.reason, now(), id);\n return this.getApproval(id);\n }\n\n /* ---- rules ---- */\n createRule(r: { kind: 'require' | 'allow'; toolPattern: string; inputPattern?: string; scopeNote?: string; builtin?: boolean }): Rule {\n const id = newId();\n this.db.prepare(\n `INSERT INTO rules (id,kind,tool_pattern,input_pattern,scope_note,builtin,enabled,created_at) VALUES (?,?,?,?,?,?,1,?)`,\n ).run(id, r.kind, r.toolPattern, r.inputPattern ?? '', r.scopeNote ?? '', i(r.builtin), now());\n return this.getRule(id)!;\n }\n getRule(id: string): Rule | null {\n const r = this.db.prepare(`SELECT * FROM rules WHERE id=?`).get(id) as Row | undefined;\n return r ? toRule(r) : null;\n }\n listRules(onlyEnabled = false): Rule[] {\n return (this.db.prepare(`SELECT * FROM rules ${onlyEnabled ? 'WHERE enabled=1' : ''} ORDER BY kind ASC, created_at ASC`).all() as Row[]).map(toRule);\n }\n setRuleEnabled(id: string, enabled: boolean): void {\n this.db.prepare(`UPDATE rules SET enabled=? WHERE id=?`).run(i(enabled), id);\n }\n deleteRule(id: string): void {\n this.db.prepare(`DELETE FROM rules WHERE id=? AND builtin=0`).run(id);\n }\n\n /* ---- skills ---- */\n createSkill(s: { slug: string; name: string; description?: string; path: string; source?: 'user' | 'taught' | 'imported' }): Skill {\n const id = newId();\n this.db.prepare(\n `INSERT OR REPLACE INTO skills (id,slug,name,description,path,source,created_at) VALUES (?,?,?,?,?,?,?)`,\n ).run(id, s.slug, s.name, s.description ?? '', s.path, s.source ?? 'user', now());\n return this.getSkillBySlug(s.slug)!;\n }\n getSkill(id: string): Skill | null {\n const r = this.db.prepare(`SELECT * FROM skills WHERE id=?`).get(id) as Row | undefined;\n return r ? toSkill(r) : null;\n }\n getSkillBySlug(slug: string): Skill | null {\n const r = this.db.prepare(`SELECT * FROM skills WHERE slug=?`).get(slug) as Row | undefined;\n return r ? toSkill(r) : null;\n }\n listSkills(): Skill[] {\n return (this.db.prepare(`SELECT * FROM skills ORDER BY name ASC`).all() as Row[]).map(toSkill);\n }\n /**\n * Update a skill's metadata in place, keeping its id so bot assignments survive a\n * re-install. Returns null if the skill is gone.\n */\n updateSkill(id: string, patch: { name?: string; description?: string; path?: string }): Skill | null {\n const existing = this.getSkill(id);\n if (!existing) return null;\n this.db.prepare(`UPDATE skills SET name=?, description=?, path=? WHERE id=?`).run(\n patch.name ?? existing.name,\n patch.description ?? existing.description,\n patch.path ?? existing.path,\n id,\n );\n return this.getSkill(id);\n }\n deleteSkill(id: string): void {\n this.db.prepare(`DELETE FROM skills WHERE id=?`).run(id);\n this.db.prepare(`DELETE FROM bot_skills WHERE skill_id=?`).run(id);\n }\n setBotSkills(botId: string, skillIds: string[]): void {\n this.db.prepare(`DELETE FROM bot_skills WHERE bot_id=?`).run(botId);\n const stmt = this.db.prepare(`INSERT OR REPLACE INTO bot_skills (bot_id,skill_id,enabled) VALUES (?,?,1)`);\n for (const s of skillIds) stmt.run(botId, s);\n }\n listBotSkills(botId: string): Skill[] {\n return (this.db.prepare(\n `SELECT s.* FROM skills s JOIN bot_skills bs ON bs.skill_id=s.id WHERE bs.bot_id=? AND bs.enabled=1`,\n ).all(botId) as Row[]).map(toSkill);\n }\n\n /* ---- connectors ---- */\n createConnector(c: { name: string; description?: string; config: ConnectorConfig; enabled?: boolean; kind?: 'custom' | 'builtin' }): Connector {\n const id = newId();\n this.db.prepare(\n `INSERT INTO connectors (id,name,description,config_json,enabled,kind,created_at) VALUES (?,?,?,?,?,?,?)`,\n ).run(id, c.name, c.description ?? '', JSON.stringify(c.config), i(c.enabled, true), c.kind ?? 'custom', now());\n return this.getConnector(id)!;\n }\n /** Record the latest verdict. Written by both `check` and the turn's own mount report. */\n setConnectorStatus(id: string, status: string, error: string | null = null): void {\n this.db.prepare(`UPDATE connectors SET last_status=?, last_error=?, checked_at=? WHERE id=?`).run(status, error, now(), id);\n }\n setConnectorStatusByName(name: string, status: string, error: string | null = null): void {\n this.db.prepare(`UPDATE connectors SET last_status=?, last_error=?, checked_at=? WHERE name=?`).run(status, error, now(), name);\n }\n getConnector(id: string): Connector | null {\n const r = this.db.prepare(`SELECT * FROM connectors WHERE id=?`).get(id) as Row | undefined;\n return r ? toConnector(r) : null;\n }\n getConnectorByName(name: string): Connector | null {\n const r = this.db.prepare(`SELECT * FROM connectors WHERE name=?`).get(name) as Row | undefined;\n return r ? toConnector(r) : null;\n }\n listConnectors(): Connector[] {\n return (this.db.prepare(`SELECT * FROM connectors ORDER BY name ASC`).all() as Row[]).map(toConnector);\n }\n /** Patch in place. No rename: the name is baked into every `mcp__<name>__<tool>` a rule may match. */\n updateConnector(id: string, patch: { description?: string; config?: ConnectorConfig; enabled?: boolean }): Connector | null {\n const existing = this.getConnector(id);\n if (!existing) return null;\n this.db.prepare(`UPDATE connectors SET description=?, config_json=?, enabled=? WHERE id=?`).run(\n patch.description ?? existing.description,\n JSON.stringify(patch.config ?? existing.config),\n i(patch.enabled ?? existing.enabled),\n id,\n );\n return this.getConnector(id);\n }\n deleteConnector(id: string): void {\n this.db.prepare(`DELETE FROM connectors WHERE id=?`).run(id);\n this.db.prepare(`DELETE FROM bot_connectors WHERE connector_id=?`).run(id);\n }\n setBotConnectors(botId: string, connectorIds: string[]): void {\n this.db.prepare(`DELETE FROM bot_connectors WHERE bot_id=?`).run(botId);\n const stmt = this.db.prepare(`INSERT OR REPLACE INTO bot_connectors (bot_id,connector_id,enabled) VALUES (?,?,1)`);\n for (const c of connectorIds) stmt.run(botId, c);\n }\n /** Assigned AND account-wide enabled \u2014 disabling a connector takes it away from every bot at once. */\n listBotConnectors(botId: string): Connector[] {\n return (this.db.prepare(\n `SELECT c.* FROM connectors c JOIN bot_connectors bc ON bc.connector_id=c.id\n WHERE bc.bot_id=? AND bc.enabled=1 AND c.enabled=1 ORDER BY c.name ASC`,\n ).all(botId) as Row[]).map(toConnector);\n }\n\n /* ---- routines ---- */\n createRoutine(r: { botId: string; name: string; cronExpr: string; timezone?: string; instructionMd: string; enabled?: boolean }): Routine {\n const count = (this.db.prepare(`SELECT COUNT(*) c FROM routines WHERE bot_id=?`).get(r.botId) as Row).c;\n if (count >= LIMITS.MAX_ROUTINES_PER_BOT)\n throw new LimitError(LIMIT_ERROR.TOO_MANY_ROUTINES, `A bot can own at most ${LIMITS.MAX_ROUTINES_PER_BOT} routines`);\n const id = newId();\n this.db.prepare(\n `INSERT INTO routines (id,bot_id,name,cron_expr,timezone,instruction_md,enabled,created_at) VALUES (?,?,?,?,?,?,?,?)`,\n ).run(id, r.botId, r.name, r.cronExpr, r.timezone ?? 'UTC', r.instructionMd, i(r.enabled, true), now());\n return this.getRoutine(id)!;\n }\n getRoutine(id: string): Routine | null {\n const r = this.db.prepare(`SELECT * FROM routines WHERE id=?`).get(id) as Row | undefined;\n return r ? toRoutine(r) : null;\n }\n listRoutines(botId?: string): Routine[] {\n const rows = (botId\n ? this.db.prepare(`SELECT * FROM routines WHERE bot_id=? ORDER BY created_at ASC`).all(botId)\n : this.db.prepare(`SELECT * FROM routines ORDER BY created_at ASC`).all()) as Row[];\n return rows.map(toRoutine);\n }\n updateRoutine(id: string, patch: Partial<Routine>): Routine | null {\n const cur = this.getRoutine(id);\n if (!cur) return null;\n this.db.prepare(\n `UPDATE routines SET name=?,cron_expr=?,timezone=?,instruction_md=?,enabled=?,last_run_at=?,next_run_at=? WHERE id=?`,\n ).run(\n patch.name ?? cur.name, patch.cronExpr ?? cur.cronExpr, patch.timezone ?? cur.timezone,\n patch.instructionMd ?? cur.instructionMd, i(patch.enabled, cur.enabled),\n patch.lastRunAt !== undefined ? patch.lastRunAt : cur.lastRunAt,\n patch.nextRunAt !== undefined ? patch.nextRunAt : cur.nextRunAt, id,\n );\n return this.getRoutine(id);\n }\n deleteRoutine(id: string): void {\n this.db.prepare(`DELETE FROM routines WHERE id=?`).run(id);\n this.db.prepare(`DELETE FROM routine_runs WHERE routine_id=?`).run(id);\n }\n\n startRun(routineId: string, isTest = false, threadId?: string): RoutineRun {\n const id = newId();\n this.db.prepare(\n `INSERT INTO routine_runs (id,routine_id,started_at,status,summary,thread_id,is_test) VALUES (?,?,?,'running','',?,?)`,\n ).run(id, routineId, now(), threadId ?? null, i(isTest));\n return this.getRun(id)!;\n }\n finishRun(id: string, status: 'ok' | 'failed' | 'interrupted', summary: string): RoutineRun | null {\n this.db.prepare(`UPDATE routine_runs SET finished_at=?, status=?, summary=? WHERE id=?`).run(now(), status, summary, id);\n const run = this.getRun(id);\n if (run) this.pruneRuns(run.routineId);\n return run;\n }\n getRun(id: string): RoutineRun | null {\n const r = this.db.prepare(`SELECT * FROM routine_runs WHERE id=?`).get(id) as Row | undefined;\n return r ? toRun(r) : null;\n }\n listRuns(routineId: string): RoutineRun[] {\n return (this.db.prepare(\n `SELECT * FROM routine_runs WHERE routine_id=? ORDER BY started_at DESC LIMIT ?`,\n ).all(routineId, LIMITS.ROUTINE_RUNS_RETAINED) as Row[]).map(toRun);\n }\n /** Keep only the N most recent run records (outline \u00A713). */\n pruneRuns(routineId: string): void {\n this.db.prepare(\n `DELETE FROM routine_runs WHERE routine_id=? AND id NOT IN\n (SELECT id FROM routine_runs WHERE routine_id=? ORDER BY started_at DESC LIMIT ?)`,\n ).run(routineId, routineId, LIMITS.ROUTINE_RUNS_RETAINED);\n }\n\n /* ---- mailbox ---- */\n createMail(m: { fromBotId: string; toBotId: string; contentMd: string; hops?: number }): MailboxEntry {\n const hops = m.hops ?? 1;\n if (hops > LIMITS.MAX_BOT_TO_BOT_HOPS)\n throw new LimitError(LIMIT_ERROR.HOP_LIMIT, `Bot-to-bot hop limit (${LIMITS.MAX_BOT_TO_BOT_HOPS}) reached; a human must take the next step`);\n const id = newId();\n this.db.prepare(\n `INSERT INTO mailbox (id,from_bot_id,to_bot_id,content_md,hops,delivered,created_at) VALUES (?,?,?,?,?,0,?)`,\n ).run(id, m.fromBotId, m.toBotId, m.contentMd, hops, now());\n return toMail(this.db.prepare(`SELECT * FROM mailbox WHERE id=?`).get(id) as Row);\n }\n markDelivered(id: string): void {\n this.db.prepare(`UPDATE mailbox SET delivered=1 WHERE id=?`).run(id);\n }\n listMail(toBotId: string, onlyUndelivered = true): MailboxEntry[] {\n return (this.db.prepare(\n `SELECT * FROM mailbox WHERE to_bot_id=? ${onlyUndelivered ? 'AND delivered=0' : ''} ORDER BY created_at ASC`,\n ).all(toBotId) as Row[]).map(toMail);\n }\n\n /* ---- usage ---- */\n recordUsage(u: Omit<UsageRow, 'id' | 'createdAt'>): UsageRow {\n const id = newId();\n this.db.prepare(\n `INSERT INTO usage (id,bot_id,turn_id,model,input_tokens,output_tokens,cache_read_tokens,cost_estimate,created_at)\n VALUES (?,?,?,?,?,?,?,?,?)`,\n ).run(id, u.botId, u.turnId, u.model, u.inputTokens, u.outputTokens, u.cacheReadTokens, u.costEstimate, now());\n return toUsage(this.db.prepare(`SELECT * FROM usage WHERE id=?`).get(id) as Row);\n }\n listUsage(sinceMs = 0): UsageRow[] {\n return (this.db.prepare(`SELECT * FROM usage WHERE created_at>=? ORDER BY created_at DESC`).all(sinceMs) as Row[]).map(toUsage);\n }\n tokensToday(): number {\n const start = new Date(); start.setHours(0, 0, 0, 0);\n const r = this.db.prepare(\n `SELECT COALESCE(SUM(input_tokens+output_tokens),0) t FROM usage WHERE created_at>=?`,\n ).get(start.getTime()) as Row;\n return r.t;\n }\n\n /* ---- settings ---- */\n getSettings(): Settings {\n const rows = this.db.prepare(`SELECT * FROM settings`).all() as Row[];\n const obj: Record<string, unknown> = {};\n for (const r of rows) obj[r.key] = JSON.parse(r.value);\n return SettingsSchema.parse(obj);\n }\n patchSettings(patch: Partial<Settings>): Settings {\n const stmt = this.db.prepare(`INSERT OR REPLACE INTO settings (key,value) VALUES (?,?)`);\n for (const [k, v] of Object.entries(patch)) if (v !== undefined) stmt.run(k, JSON.stringify(v));\n return this.getSettings();\n }\n\n /* ---- search ---- */\n searchMessages(q: string, limit = 40): Message[] {\n if (!q.trim()) return [];\n const escaped = `\"${q.replace(/\"/g, '\"\"')}\"`;\n try {\n const rows = this.db.prepare(\n `SELECT m.* FROM messages_fts f JOIN messages m ON m.rowid=f.rowid\n WHERE messages_fts MATCH ? ORDER BY rank LIMIT ?`,\n ).all(escaped, limit) as Row[];\n return rows.map(toMessage);\n } catch {\n const rows = this.db.prepare(\n `SELECT * FROM messages WHERE content_md LIKE ? ORDER BY created_at DESC LIMIT ?`,\n ).all(`%${q}%`, limit) as Row[];\n return rows.map(toMessage);\n }\n }\n}\n", "import { randomUUID } from 'node:crypto';\nimport { EventEmitter } from 'node:events';\nimport type { ServerEvent } from '@antbot/contract';\n\n/** Distributive omit so the discriminated union survives (a plain Omit collapses it). */\ntype DistOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\ntype Emitted = DistOmit<ServerEvent, 'seq'> & { seq?: number };\n\n/** In-process event bus. Assigns a monotonic seq so the UI can order/reconcile. */\nexport class EventBus {\n private emitter = new EventEmitter();\n private seq = 0;\n private ring: ServerEvent[] = [];\n private readonly ringMax = 500;\n /**\n * This process's identity, sent in `hello`. seq restarts at 1 on every boot, so without a way\n * to say \"the numbering is new\" a client that survived the restart discards every event it is\n * sent \u2014 connected, and permanently blank.\n */\n readonly epoch: string = randomUUID();\n\n constructor() {\n this.emitter.setMaxListeners(200);\n }\n\n publish(e: Emitted): ServerEvent {\n const full = { ...e, seq: ++this.seq } as ServerEvent;\n this.ring.push(full);\n if (this.ring.length > this.ringMax) this.ring.shift();\n this.emitter.emit('event', full);\n return full;\n }\n\n subscribe(fn: (e: ServerEvent) => void): () => void {\n this.emitter.on('event', fn);\n return () => this.emitter.off('event', fn);\n }\n\n /** Replay events after a given seq (client reconnect). */\n since(seq: number): ServerEvent[] {\n return this.ring.filter((e) => e.seq > seq);\n }\n\n get currentSeq(): number {\n return this.seq;\n }\n}\n", "import type { Rule } from '@antbot/contract';\nimport type { Store } from '../db/store.js';\nimport { logger } from '../util/log.js';\n\nconst log = logger('rules');\n\n/** Convert a glob (only `*` is special) to an anchored, case-insensitive regex. */\nexport function globToRegExp(glob: string): RegExp {\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*');\n return new RegExp(`^${escaped}$`, 'i');\n}\n\n/** Flatten a tool input into one searchable string so input patterns can match anywhere. */\nexport function serializeInput(input: unknown): string {\n if (input == null) return '';\n if (typeof input === 'string') return input;\n try {\n return JSON.stringify(input);\n } catch {\n return String(input);\n }\n}\n\n/**\n * Build the text a rule's `inputPattern` is tested against.\n *\n * Every string value in the input gets its own line, and the serialized form is\n * appended last. Patterns are matched multiline, so `^` anchors to the start of an\n * actual argument value (e.g. the Bash `command`) rather than to the start of a JSON\n * blob \u2014 without that, an anchored allow-rule can never fire and the action falls\n * through to a human prompt.\n */\nexport function buildMatchText(input: unknown): string {\n const lines: string[] = [];\n const walk = (v: unknown, depth: number): void => {\n if (depth > 6) return;\n if (typeof v === 'string') lines.push(v);\n else if (Array.isArray(v)) v.forEach((x) => walk(x, depth + 1));\n else if (v && typeof v === 'object') Object.values(v).forEach((x) => walk(x, depth + 1));\n else if (typeof v === 'number' || typeof v === 'boolean') lines.push(String(v));\n };\n walk(input, 0);\n const serialized = serializeInput(input);\n if (serialized && !lines.includes(serialized)) lines.push(serialized);\n return lines.join('\\n');\n}\n\nexport interface RuleMatch {\n rule: Rule;\n matched: true;\n}\n\n/**\n * Names a tool call can be matched against.\n *\n * Tools served over MCP arrive at the permission boundary fully namespaced as\n * `mcp__<server>__<tool>` \u2014 a live turn records the browser tools as\n * `mcp__browser__browser_navigate`. Rule tool patterns are anchored, so a rule written\n * against the bare name (`browser_click`, `send_to_bot`) could never match, silently\n * killing the consequential-click, credential-typing and handoff require-rules.\n *\n * Matching against both forms keeps rules authored either way working. Both `require`\n * and `allow` rules get the same treatment, so this cannot flip a blocked action into\n * an allowed one \u2014 `require` still wins (see `evaluateRules`).\n */\nexport function toolNameAliases(toolName: string): string[] {\n const m = /^mcp__.+?__(.+)$/.exec(toolName);\n return m?.[1] ? [toolName, m[1]] : [toolName];\n}\n\nexport function ruleMatches(rule: Rule, toolName: string, inputText: string): boolean {\n if (!rule.enabled) return false;\n const pattern = globToRegExp(rule.toolPattern);\n if (!toolNameAliases(toolName).some((n) => pattern.test(n))) return false;\n if (rule.inputPattern) {\n let re: RegExp;\n try {\n re = new RegExp(rule.inputPattern, 'im');\n } catch {\n return false; // an invalid stored pattern must never silently allow\n }\n if (!re.test(inputText)) return false;\n }\n return true;\n}\n\nexport type RuleDecision =\n | { kind: 'require'; rule: Rule }\n | { kind: 'allow'; rule: Rule }\n | { kind: 'none' };\n\n/**\n * Precedence, per outline \u00A79: an enabled `require` rule always wins over any\n * `allow` rule. Only when no `require` matches can an `allow` take effect.\n */\nexport function evaluateRules(rules: Rule[], toolName: string, input: unknown): RuleDecision {\n const inputText = buildMatchText(input);\n const required = rules.find((r) => r.kind === 'require' && ruleMatches(r, toolName, inputText));\n if (required) return { kind: 'require', rule: required };\n const allowed = rules.find((r) => r.kind === 'allow' && ruleMatches(r, toolName, inputText));\n if (allowed) return { kind: 'allow', rule: allowed };\n return { kind: 'none' };\n}\n\n/**\n * Default require-rules (WP-2.1). These ship enabled so that sending, publishing,\n * purchasing, deleting outside the workspace, installs, sudo and git push are all\n * behind approval out of the box.\n */\nexport const BUILTIN_RULES: Array<Omit<Rule, 'id' | 'createdAt'>> = [\n { kind: 'require', toolPattern: 'Bash', inputPattern: '\\\\bsudo\\\\b|\\\\bdoas\\\\b|\\\\bsu\\\\s+-', scopeNote: 'Privilege escalation', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: 'rm\\\\s+(-[a-zA-Z]*\\\\s+)*-?[rf]|shred\\\\b|mkfs\\\\b|dd\\\\s+if=', scopeNote: 'Destructive filesystem command', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: 'curl[^|]*\\\\|\\\\s*(ba)?sh|wget[^|]*\\\\|\\\\s*(ba)?sh', scopeNote: 'Piping a download into a shell', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: '\\\\b(npm|pnpm|yarn|pip|pip3|gem|cargo|apt|apt-get|dnf|brew|go)\\\\s+(i|install|add|get)\\\\b', scopeNote: 'Package install', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: 'git\\\\s+(push|remote\\\\s+add)|gh\\\\s+(pr|release|repo)\\\\s+(create|merge)', scopeNote: 'Publishing to a remote', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: '\\\\b(mail|sendmail|mutt|msmtp)\\\\b', scopeNote: 'Sending mail', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'Bash', inputPattern: 'curl[^\\\\n]*(-X\\\\s*(POST|PUT|PATCH|DELETE)|--data|-d\\\\s)', scopeNote: 'Outbound write request', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'WebFetch', inputPattern: '.', scopeNote: 'Fetching an external URL', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'browser_click', inputPattern: '(buy|purchase|checkout|pay|order|subscribe|confirm|delete|send|publish)', scopeNote: 'Consequential click', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'browser_type', inputPattern: '(password|passwd|secret|token|api[_-]?key|ssn|credit\\\\s*card)', scopeNote: 'Typing a credential \u2014 use takeover instead', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'send_to_bot', inputPattern: '', scopeNote: 'Handing work to another bot', builtin: false, enabled: false },\n { kind: 'require', toolPattern: 'install_skill', inputPattern: '', scopeNote: 'Installing a skill from an external source', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'remove_skill', inputPattern: '', scopeNote: 'Uninstalling a skill', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'Read', inputPattern: '', scopeNote: 'Reading files is safe', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'Glob', inputPattern: '', scopeNote: 'Listing files is safe', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'Grep', inputPattern: '', scopeNote: 'Searching files is safe', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'TodoWrite', inputPattern: '', scopeNote: 'Planning scratchpad', builtin: true, enabled: true },\n { kind: 'allow', toolPattern: 'Bash', inputPattern: '^\\\\s*(git\\\\s+(status|diff|log|show|branch)|ls|pwd|cat|head|tail|wc|echo|date|which|grep|find|rg)\\\\b', scopeNote: 'Read-only shell inspection', builtin: true, enabled: true },\n // The one place a seeded `mcp__*` rule is right: these tool names are ant-bot's own (the gmail\n // connector is served by the daemon), fixed, and fully qualified \u2014 so they cannot match a\n // third-party server's tool by alias, and they are the two Gmail actions that leave the machine.\n { kind: 'require', toolPattern: 'mcp__gmail__send_message', inputPattern: '', scopeNote: 'Sending email', builtin: true, enabled: true },\n { kind: 'require', toolPattern: 'mcp__gmail__create_draft', inputPattern: '', scopeNote: 'Creating an email draft', builtin: true, enabled: true },\n];\n\n/**\n * Ensure every builtin rule exists, adding only the ones that don't.\n *\n * Seeding all-or-nothing would mean a rule added in a later version never reaches an\n * existing database \u2014 the new gate would silently not apply to exactly the installs that\n * have been running longest. Rules already present are left alone, so a builtin the user\n * has disabled stays disabled.\n */\nexport function seedBuiltinRules(store: Store): void {\n // Match across every rule, not just `builtin` ones: one seeded entry (send_to_bot) is\n // deliberately created as a user rule, and filtering to builtins would re-add it each boot.\n const key = (r: { kind: string; toolPattern: string; inputPattern: string }): string =>\n `${r.kind}\\u0000${r.toolPattern}\\u0000${r.inputPattern}`;\n const existing = new Set(store.listRules().map(key));\n const added: string[] = [];\n for (const r of BUILTIN_RULES) {\n if (existing.has(key(r))) continue;\n const rule = store.createRule(r);\n if (!r.enabled) store.setRuleEnabled(rule.id, false);\n added.push(r.toolPattern);\n }\n if (added.length) log.info(`seeded ${added.length} builtin permission rule(s): ${added.join(', ')}`);\n}\n", "import path from 'node:path';\n\n/**\n * Decide whether a proposed tool call reaches OUTSIDE the shared workspace \u2014 i.e.\n * touches the user's own machine rather than the bots' computer.\n *\n * ant-bot has no separate cloud VM, so Grok Bot's \"execution on local computer\"\n * control maps onto this boundary: the workspace is the bots' computer, and\n * everything else is your machine.\n */\nexport type LocalReach = { reaches: boolean; evidence: string };\n\nconst HOME_ISH = /(^|[\\s\"'=:])(~|\\$HOME)\\//;\n\n/** Anything scheme://... \u2014 a URL's path is not a filesystem path. */\nconst URL_RE = /\\b[a-z][a-z0-9+.-]*:\\/\\/\\S+/gi;\n\n/**\n * Filesystem path candidates in a command string: absolute (`/etc`), home-relative\n * (`~/.ssh`), and dot-relative (`./src`, `../..`). Dot-relative forms are kept rather\n * than dropped because they resolve against the workspace, so `./src` reads as inside\n * while `../../.ssh` correctly reads as an escape.\n */\nexport function extractPaths(text: string): string[] {\n const out: string[] = [];\n const cleaned = text.replace(URL_RE, ' ');\n for (const m of cleaned.matchAll(/(?<![\\w\\-.:/])((?:~|\\.{1,2}\\/|\\.\\.(?=\\s|$)|\\/)[^\\s\"';|&)]*)/g)) {\n const p = m[1];\n if (p && p.length > 1) out.push(p);\n }\n return out;\n}\n\n/**\n * @param allowedRoots Directories that count as inside even though they are not the workspace.\n * ant-bot's own attachments directory is one: a file the human attached to the message they\n * are sending is theirs, already handed over deliberately, and making the bot ask permission\n * to open the image you just gave it stalls the turn on a question with one sensible answer.\n */\nexport function assessLocalReach(\n toolName: string,\n input: unknown,\n workspace: string,\n allowedRoots: string[] = [],\n): LocalReach {\n const o = (input ?? {}) as Record<string, unknown>;\n const str = (k: string): string => (typeof o[k] === 'string' ? (o[k] as string) : '');\n const ws = path.resolve(workspace);\n const roots = [ws, ...allowedRoots.map((r) => path.resolve(r))];\n\n const insideWorkspace = (p: string): boolean => {\n if (p.startsWith('~')) return false;\n const abs = path.isAbsolute(p) ? path.resolve(p) : path.resolve(ws, p);\n return roots.some((root) => {\n const rel = path.relative(root, abs);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n });\n };\n\n // File tools carry an explicit path.\n if (toolName === 'Read' || toolName === 'Write' || toolName === 'Edit' || toolName === 'NotebookEdit') {\n const p = str('file_path') || str('notebook_path');\n if (p && !insideWorkspace(p)) return { reaches: true, evidence: p };\n return { reaches: false, evidence: '' };\n }\n\n if (toolName === 'Bash') {\n const cmd = str('command');\n if (HOME_ISH.test(cmd)) {\n const m = cmd.match(HOME_ISH);\n return { reaches: true, evidence: m ? cmd.slice(Math.max(0, (m.index ?? 0)), (m.index ?? 0) + 60).trim() : '~' };\n }\n for (const p of extractPaths(cmd)) {\n if (!insideWorkspace(p)) return { reaches: true, evidence: p };\n }\n return { reaches: false, evidence: '' };\n }\n\n return { reaches: false, evidence: '' };\n}\n\nexport type LocalPolicy = 'ask' | 'always' | 'never';\n\nexport function localDecision(policy: LocalPolicy, reach: LocalReach):\n | { action: 'ignore' }\n | { action: 'require'; reason: string }\n | { action: 'deny'; reason: string } {\n if (!reach.reaches) return { action: 'ignore' };\n if (policy === 'always') return { action: 'ignore' };\n if (policy === 'never')\n return {\n action: 'deny',\n reason: `Blocked: this touches ${reach.evidence}, which is outside the shared workspace. \"Execution on local computer\" is set to Never in Settings.`,\n };\n return { action: 'require', reason: `Touches ${reach.evidence}, outside the shared workspace (your own machine)` };\n}\n", "import type { Store } from '../db/store.js';\nimport type { EventBus } from '../util/bus.js';\nimport { LIMITS, type Approval, type Settings } from '@antbot/contract';\nimport { evaluateRules, serializeInput, toolNameAliases } from './rules.js';\nimport { assessLocalReach, localDecision } from './local.js';\nimport { describeSkillSource } from '../skills/install.js';\nimport { logger } from '../util/log.js';\n\nconst log = logger('gateway');\n\nexport type GatewayDecision =\n | { behavior: 'allow'; reason: string; via: 'rule' | 'auto_review' | 'user' }\n | { behavior: 'deny'; message: string; via: 'rule' | 'auto_review' | 'user' | 'timeout' };\n\nexport interface AutoReviewer {\n /** Classify a proposed tool call. Never able to override a `require` rule. */\n classify(toolName: string, input: unknown, botDescription: string): Promise<{\n verdict: 'allow_ok' | 'needs_human' | 'deny_suggested';\n reason: string;\n }>;\n}\n\nexport interface PendingResolver {\n approvalId: string;\n resolve: (d: GatewayDecision) => void;\n timer: NodeJS.Timeout;\n}\n\n/** Human-readable one-line summary of a proposed action for the approval card. */\nexport function summarize(namespacedToolName: string, input: unknown): string {\n const o = (input ?? {}) as Record<string, unknown>;\n const s = (k: string): string => (typeof o[k] === 'string' ? (o[k] as string) : '');\n // MCP tools arrive as `mcp__<server>__<tool>`; summarize on the bare name so the\n // approval card stays legible. Falls back to the full name for anything unrecognized.\n const aliases = toolNameAliases(namespacedToolName);\n const toolName = aliases[aliases.length - 1]!;\n switch (toolName) {\n case 'Bash':\n return `Run: ${s('command').slice(0, 200)}`;\n case 'Write':\n return `Write file ${s('file_path')}`;\n case 'Edit':\n return `Edit file ${s('file_path')}`;\n case 'Read':\n return `Read file ${s('file_path')}`;\n case 'WebFetch':\n return `Fetch ${s('url')}`;\n case 'send_to_bot':\n return `Hand work to @${s('bot_slug')}`;\n // Scope is the whole decision here: one named skill, or every skill in a repository.\n case 'install_skill':\n return describeSkillSource(s('source'));\n case 'remove_skill':\n return `Uninstall the skill \"${s('slug')}\"`;\n default: {\n if (toolName.startsWith('browser_')) {\n const bits = [s('url'), s('selector'), s('text')].filter(Boolean).join(' ');\n return `${toolName.replace('browser_', 'Browser ')}: ${bits}`.trim();\n }\n const flat = serializeInput(input);\n return `${toolName}: ${flat.slice(0, 180)}`;\n }\n }\n}\n\nexport class PermissionGateway {\n private pending = new Map<string, PendingResolver>();\n\n constructor(\n private store: Store,\n private bus: EventBus,\n private autoReviewer?: AutoReviewer,\n ) {}\n\n /**\n * Decide whether a proposed tool call may run.\n * Order: deterministic rules \u2192 auto review (advisory) \u2192 human approval card.\n * A matching `require` rule can never be satisfied by auto review (outline \u00A79).\n */\n async check(args: {\n botId: string;\n threadId: string;\n toolName: string;\n input: unknown;\n botDescription: string;\n settings: Settings;\n signal?: AbortSignal;\n /** Absolute path of the shared workspace, for the local-execution boundary. */\n workspace: string;\n /** Directories outside the workspace that still count as inside \u2014 ant-bot's attachments. */\n allowedRoots?: string[];\n /** Fired when a human approval card is created, so the caller can render it inline. */\n onPending?: (approval: Approval) => void;\n }): Promise<GatewayDecision> {\n const { toolName, input, settings } = args;\n const rules = this.store.listRules(true);\n const decision = evaluateRules(rules, toolName, input);\n\n // The local-execution policy is checked before any allow rule: reaching outside\n // the shared workspace means touching the user's own machine, and a broad allow\n // rule must not silently authorize that.\n const local = localDecision(\n settings.localExecution,\n assessLocalReach(toolName, input, args.workspace, args.allowedRoots ?? []),\n );\n if (local.action === 'deny') {\n return { behavior: 'deny', message: local.reason, via: 'rule' };\n }\n if (local.action === 'require' && decision.kind !== 'require') {\n return this.askHuman({ ...args, reason: local.reason });\n }\n\n if (decision.kind === 'allow') {\n log.debug(`allow by rule ${decision.rule.id}: ${toolName}`);\n return { behavior: 'allow', reason: decision.rule.scopeNote || 'Matched an allow rule', via: 'rule' };\n }\n\n const requiredBy = decision.kind === 'require' ? decision.rule : null;\n\n // Auto review is advisory and only consulted when no `require` rule matched.\n if (!requiredBy && settings.autoReviewEnabled && this.autoReviewer) {\n try {\n const verdict = await this.autoReviewer.classify(toolName, input, args.botDescription);\n if (verdict.verdict === 'allow_ok')\n return { behavior: 'allow', reason: verdict.reason, via: 'auto_review' };\n if (verdict.verdict === 'deny_suggested')\n return this.askHuman({ ...args, reason: `Auto review flagged this: ${verdict.reason}` });\n return this.askHuman({ ...args, reason: verdict.reason });\n } catch (err) {\n log.warn('auto review failed; falling back to human approval', err);\n }\n }\n\n return this.askHuman({\n ...args,\n reason: requiredBy ? requiredBy.scopeNote || 'Matched a require-approval rule' : 'No rule covers this action',\n ruleId: requiredBy?.id ?? null,\n });\n }\n\n private askHuman(args: {\n botId: string; threadId: string; toolName: string; input: unknown;\n reason: string; ruleId?: string | null; signal?: AbortSignal;\n onPending?: (approval: Approval) => void;\n }): Promise<GatewayDecision> {\n const approval = this.store.createApproval({\n botId: args.botId,\n threadId: args.threadId,\n toolName: args.toolName,\n inputSummary: summarize(args.toolName, args.input),\n rawInput: args.input,\n reason: args.reason,\n });\n if (args.ruleId) this.store.db.prepare(`UPDATE approvals SET rule_id=? WHERE id=?`).run(args.ruleId, approval.id);\n\n const fresh = this.store.getApproval(approval.id)!;\n args.onPending?.(fresh);\n this.bus.publish({\n type: 'approval.pending',\n threadId: args.threadId,\n botId: args.botId,\n approval: fresh,\n });\n\n return new Promise<GatewayDecision>((resolve) => {\n const timer = setTimeout(() => {\n this.pending.delete(approval.id);\n this.store.resolveApproval(approval.id, 'expired', 'user', null, 'No response in time');\n this.bus.publish({\n type: 'approval.resolved', threadId: args.threadId, botId: args.botId,\n approval: this.store.getApproval(approval.id)!,\n });\n resolve({ behavior: 'deny', message: 'Approval request expired without a decision.', via: 'timeout' });\n }, LIMITS.APPROVAL_TIMEOUT_MS);\n\n this.pending.set(approval.id, { approvalId: approval.id, resolve, timer });\n\n args.signal?.addEventListener('abort', () => {\n const p = this.pending.get(approval.id);\n if (!p) return;\n clearTimeout(p.timer);\n this.pending.delete(approval.id);\n this.store.resolveApproval(approval.id, 'denied', 'user', null, 'Turn interrupted');\n resolve({ behavior: 'deny', message: 'Interrupted.', via: 'user' });\n });\n });\n }\n\n /** Resolve a pending approval from the UI. Returns the updated row. */\n decide(approvalId: string, decision: 'allow' | 'deny', alwaysRule?: { toolPattern: string; inputPattern?: string; scopeNote?: string }): Approval | null {\n const p = this.pending.get(approvalId);\n const existing = this.store.getApproval(approvalId);\n if (!existing) return null;\n if (existing.status !== 'pending') return existing;\n\n let ruleId: string | null = null;\n if (decision === 'allow' && alwaysRule) {\n const rule = this.store.createRule({\n kind: 'allow',\n toolPattern: alwaysRule.toolPattern,\n inputPattern: alwaysRule.inputPattern ?? '',\n scopeNote: alwaysRule.scopeNote ?? 'Saved from an approval',\n });\n ruleId = rule.id;\n }\n\n const updated = this.store.resolveApproval(\n approvalId, decision === 'allow' ? 'allowed' : 'denied', 'user', ruleId,\n decision === 'allow' ? 'Approved by you' : 'Denied by you',\n );\n this.bus.publish({\n type: 'approval.resolved', threadId: existing.threadId, botId: existing.botId, approval: updated!,\n });\n\n if (p) {\n clearTimeout(p.timer);\n this.pending.delete(approvalId);\n p.resolve(\n decision === 'allow'\n ? { behavior: 'allow', reason: 'Approved by you', via: 'user' }\n : { behavior: 'deny', message: 'You denied this action.', via: 'user' },\n );\n }\n return updated;\n }\n\n hasPending(approvalId: string): boolean {\n return this.pending.has(approvalId);\n }\n\n /** Cancel any pending approvals for a bot (used when a turn is interrupted). */\n cancelForBot(botId: string): void {\n for (const [id, p] of [...this.pending]) {\n const a = this.store.getApproval(id);\n if (a?.botId !== botId) continue;\n clearTimeout(p.timer);\n this.pending.delete(id);\n this.store.resolveApproval(id, 'denied', 'user', null, 'Turn interrupted');\n p.resolve({ behavior: 'deny', message: 'Interrupted.', via: 'user' });\n }\n }\n}\n", "import { query } from '@anthropic-ai/claude-agent-sdk';\nimport type { AutoReviewer } from './gateway.js';\nimport { buildEnv } from '../agent/session.js';\nimport type { Settings } from '@antbot/contract';\nimport { logger } from '../util/log.js';\nimport { summarize } from './gateway.js';\n\nconst log = logger('autoreview');\n\nconst SYSTEM = `You are the automated action reviewer for a local AI-teammate system.\nYou judge ONE proposed tool call and answer with a single JSON object.\n\nAnswer \"allow_ok\" only when the action is clearly routine, reversible and\nlow-consequence \u2014 reading files, inspecting state, searching, navigating to a\nnormal public page, writing inside the bot's own workspace.\n\nAnswer \"needs_human\" when the action is consequential or ambiguous: sending or\npublishing anything, contacting a person, spending money, changing permissions,\ntouching production, deleting or overwriting data outside the workspace,\ninstalling software, or anything whose blast radius you cannot determine.\n\nAnswer \"deny_suggested\" when the action looks actively unsafe or like an attempt\nto exfiltrate credentials.\n\nYou are advisory only and you are NOT the last line of defence. When in doubt,\nchoose needs_human.\n\nReply with ONLY: {\"verdict\":\"allow_ok|needs_human|deny_suggested\",\"reason\":\"<12 words max>\"}`;\n\n/** Haiku-backed reviewer. Advisory: it can never green-light past a `require` rule. */\nexport class HaikuAutoReviewer implements AutoReviewer {\n constructor(\n private getSettings: () => Settings,\n private cwd: string,\n ) {}\n\n async classify(toolName: string, input: unknown, botDescription: string) {\n const prompt = `Bot's standing job description:\n${botDescription.slice(0, 800) || '(none)'}\n\nProposed tool call:\ntool: ${toolName}\nsummary: ${summarize(toolName, input)}\nraw input: ${JSON.stringify(input).slice(0, 1500)}`;\n\n const q = query({\n prompt,\n options: {\n model: 'haiku',\n systemPrompt: SYSTEM,\n cwd: this.cwd,\n settingSources: [],\n env: buildEnv(this.getSettings()),\n maxTurns: 1,\n allowedTools: [],\n permissionMode: 'default',\n },\n });\n\n let out = '';\n for await (const m of q) {\n const msg = m as Record<string, any>;\n if (msg.type === 'result' && typeof msg.result === 'string') out = msg.result;\n }\n return parseVerdict(out);\n }\n}\n\nexport function parseVerdict(text: string): { verdict: 'allow_ok' | 'needs_human' | 'deny_suggested'; reason: string } {\n const fallback = { verdict: 'needs_human' as const, reason: 'Reviewer output was unreadable' };\n if (!text) return fallback;\n const match = text.match(/\\{[\\s\\S]*\\}/);\n if (!match) return fallback;\n try {\n const o = JSON.parse(match[0]) as { verdict?: string; reason?: string };\n if (o.verdict === 'allow_ok' || o.verdict === 'needs_human' || o.verdict === 'deny_suggested')\n return { verdict: o.verdict, reason: String(o.reason ?? '').slice(0, 200) };\n return fallback;\n } catch {\n return fallback;\n }\n}\n\n/** Deterministic reviewer used in tests and when auto review is disabled. */\nexport class NullAutoReviewer implements AutoReviewer {\n async classify() {\n return { verdict: 'needs_human' as const, reason: 'Auto review disabled' };\n }\n}\n\nexport function makeAutoReviewer(getSettings: () => Settings, cwd: string): AutoReviewer {\n try {\n return new HaikuAutoReviewer(getSettings, cwd);\n } catch (err) {\n log.warn('falling back to null reviewer', err);\n return new NullAutoReviewer();\n }\n}\n", "import { query, type Options, type SDKMessage } from '@anthropic-ai/claude-agent-sdk';\nimport type { ModelTier, Settings } from '@antbot/contract';\nimport { logger } from '../util/log.js';\nimport { ClaudeRuntime, type MountedConnector } from './runtime.js';\n\nconst log = logger('agent');\n\n/** Connection state the SDK reports for one mounted MCP server at turn start. */\nexport interface McpStatus {\n name: string;\n status: 'connected' | 'failed' | 'needs-auth' | 'pending' | 'disabled';\n error?: string;\n}\n\nexport interface TurnEvent {\n kind: 'text' | 'tool_start' | 'tool_result' | 'session' | 'done' | 'error' | 'status' | 'mcp_status' | 'signin';\n text?: string;\n toolName?: string;\n toolInput?: unknown;\n toolUseId?: string;\n result?: string;\n isError?: boolean;\n sessionId?: string;\n usage?: { model: string; inputTokens: number; outputTokens: number; cacheReadTokens: number; costUsd: number };\n message?: string;\n /** Present on `mcp_status`: every server the SDK tried to mount for this turn. */\n mcpStatus?: McpStatus[];\n /** Present on `signin`: a connector asked for a browser sign-in mid-turn. */\n signin?: { serverName: string; url: string };\n}\n\nexport interface TurnRequest {\n prompt: string;\n /** Prior SDK session to resume so context compounds across turns. */\n resumeSessionId?: string | null;\n modelTier: ModelTier;\n systemPrompt: string;\n cwd: string;\n settings: Settings;\n /** Extra directories the agent may read/write beyond cwd. */\n additionalDirectories?: string[];\n canUseTool?: Options['canUseTool'];\n /** In-process SDK servers ant-bot itself provides (`antbot`, `browser`). Runtime-bound by nature. */\n mcpServers?: Options['mcpServers'];\n /** The bot's assigned connectors, resolved. Mounted through the runtime adapter. */\n connectors?: Record<string, MountedConnector>;\n abortController?: AbortController;\n /** Root of the local plugin that carries installed skills. */\n skillPluginPath?: string;\n /**\n * Skill names this bot may use. `[]` means none \u2014 the SDK hides unlisted skills from\n * the model's listing and the Skill tool rejects them. Note this is a context filter,\n * not a sandbox: skill files stay readable via Read/Bash, so never put secrets in one.\n */\n enabledSkills?: string[];\n}\n\n/**\n * MODEL_TIERS are `claude` CLI model aliases (`claude --model fable|opus|sonnet|haiku`), so the\n * tier passes straight through. Routing stays fixed per surface: a Bot's tier is chosen once in\n * its settings, never per message, and auto-review and the group router always use `haiku`.\n */\nexport function resolveModel(tier: ModelTier): string {\n return tier;\n}\n\n/**\n * Build the environment for the CLI subprocess.\n *\n * The daemon never holds Anthropic credentials: the SDK spawns the `claude` CLI,\n * which uses the user's existing subscription OAuth login. An ANTHROPIC_API_KEY in\n * the ambient environment would silently switch billing to metered API usage, so we\n * strip it unless the user explicitly opted into API billing (plan \u00A79).\n */\nexport function buildEnv(settings: Settings, base: NodeJS.ProcessEnv = process.env): Record<string, string | undefined> {\n const env: Record<string, string | undefined> = { ...base };\n if (settings.billingMode !== 'api') {\n delete env.ANTHROPIC_API_KEY;\n delete env.ANTHROPIC_AUTH_TOKEN;\n }\n return env;\n}\n\n/**\n * Run one turn and yield normalized events. The caller owns persistence; this\n * wrapper only translates the SDK's message stream into our vocabulary.\n */\nconst runtime = new ClaudeRuntime();\n\nexport async function* runTurn(req: TurnRequest): AsyncGenerator<TurnEvent> {\n const abort = req.abortController ?? new AbortController();\n const options: Options = {\n model: resolveModel(req.modelTier),\n systemPrompt: { type: 'preset', preset: 'claude_code', append: req.systemPrompt },\n cwd: req.cwd,\n additionalDirectories: req.additionalDirectories,\n abortController: abort,\n includePartialMessages: true,\n permissionMode: 'default',\n canUseTool: req.canUseTool,\n mcpServers: {\n ...(req.mcpServers ?? {}),\n ...(runtime.mountConnectors(req.connectors ?? {}) as Options['mcpServers']),\n },\n // ant-bot is the MCP host. The SDK mounts exactly what is passed here and nothing else \u2014 not\n // ~/.claude.json, not plugins, not claude.ai connectors. A bot's tools cannot change because\n // of something configured outside ant-bot, and swapping the runtime later swaps only this.\n strictMcpConfig: true,\n env: buildEnv(req.settings),\n // Do not inherit the user's own Claude Code project settings into bot turns.\n settingSources: [],\n maxTurns: 60,\n };\n if (req.resumeSessionId) options.resume = req.resumeSessionId;\n // Load skills as a local plugin so the model gets the real `Skill` tool rather than a\n // pile of paths to read, then narrow to the ones assigned to this bot.\n if (req.skillPluginPath) {\n // skipMcpDiscovery: a skill directory must never be a way to mount an MCP server. Connectors\n // come through `connectors` above, and only through there.\n options.plugins = [{ type: 'local', path: req.skillPluginPath, skipMcpDiscovery: true }];\n options.skills = req.enabledSkills ?? [];\n }\n\n // A connector can ask for a sign-in in the middle of a turn (an expired token, a first use).\n // Without a handler the SDK declines on the bot's behalf and the tool call just fails. URL\n // mode is accepted and surfaced as a card; the queue hands it to the generator, which yields\n // it ahead of the next SDK message. Form mode is declined: a bot must never fill in a form a\n // server put in front of it, and nothing here can show one to a human anyway.\n const pending: TurnEvent[] = [];\n options.onElicitation = async (request) => {\n if (request.mode === 'url' && request.url) {\n pending.push({ kind: 'signin', signin: { serverName: request.serverName, url: request.url } });\n return { action: 'accept' };\n }\n log.warn(`declined a ${request.mode ?? 'form'} elicitation from \"${request.serverName}\": ${request.message}`);\n return { action: 'decline' };\n };\n\n let q: ReturnType<typeof query>;\n try {\n q = query({ prompt: req.prompt, options });\n } catch (err) {\n yield { kind: 'error', message: err instanceof Error ? err.message : String(err) };\n return;\n }\n\n const seenToolIds = new Set<string>();\n\n try {\n for await (const msg of q as AsyncGenerator<SDKMessage>) {\n while (pending.length) yield pending.shift()!;\n const m = msg as Record<string, any>;\n switch (m.type) {\n case 'system':\n if (m.subtype === 'init' && m.session_id) yield { kind: 'session', sessionId: m.session_id };\n // The sign-in finished in the browser; the server's tools only return once the SDK\n // reconnects with the new token, and it does not do that on its own.\n if (m.subtype === 'elicitation_complete' && typeof m.mcp_server_name === 'string') {\n try {\n await q.reconnectMcpServer(m.mcp_server_name);\n } catch (err) {\n log.warn(`reconnect of \"${m.mcp_server_name}\" after sign-in failed: ${(err as Error).message}`);\n }\n }\n // The init message is the only place the SDK reports whether a mounted MCP server\n // actually came up. Dropping it is how a connector that needs auth, or failed to\n // start, becomes a bot that silently has no such tools and cannot say why.\n if (m.subtype === 'init' && Array.isArray(m.mcp_servers)) {\n yield { kind: 'mcp_status', mcpStatus: m.mcp_servers as McpStatus[] };\n }\n break;\n\n case 'stream_event': {\n const ev = m.event;\n if (ev?.type === 'content_block_delta' && ev.delta?.type === 'text_delta' && ev.delta.text)\n yield { kind: 'text', text: ev.delta.text };\n break;\n }\n\n case 'assistant': {\n for (const block of m.message?.content ?? []) {\n if (block.type === 'tool_use' && !seenToolIds.has(block.id)) {\n seenToolIds.add(block.id);\n yield { kind: 'tool_start', toolName: block.name, toolInput: block.input, toolUseId: block.id };\n }\n }\n break;\n }\n\n case 'user': {\n for (const block of m.message?.content ?? []) {\n if (block.type === 'tool_result') {\n const content = Array.isArray(block.content)\n ? block.content.map((c: any) => (typeof c?.text === 'string' ? c.text : '')).join('\\n')\n : typeof block.content === 'string'\n ? block.content\n : '';\n yield {\n kind: 'tool_result',\n toolUseId: block.tool_use_id,\n result: content.slice(0, 4000),\n isError: Boolean(block.is_error),\n };\n }\n }\n break;\n }\n\n case 'result': {\n const u = m.usage ?? {};\n yield {\n kind: 'done',\n sessionId: m.session_id,\n text: typeof m.result === 'string' ? m.result : undefined,\n isError: m.subtype !== 'success',\n usage: {\n model: m.modelUsage ? Object.keys(m.modelUsage)[0] ?? resolveModel(req.modelTier) : resolveModel(req.modelTier),\n inputTokens: u.input_tokens ?? 0,\n outputTokens: u.output_tokens ?? 0,\n cacheReadTokens: u.cache_read_input_tokens ?? 0,\n costUsd: m.total_cost_usd ?? 0,\n },\n };\n break;\n }\n\n default:\n break;\n }\n }\n } catch (err) {\n if (abort.signal.aborted) {\n yield { kind: 'error', message: 'Interrupted.' };\n return;\n }\n log.error('turn failed', err);\n yield { kind: 'error', message: err instanceof Error ? err.message : String(err) };\n }\n}\n", "// The seam between ant-bot's connector registry and whichever agent runtime executes a turn.\n//\n// ant-bot owns the registry, the credentials, the per-bot assignment and the health of every MCP\n// server. The runtime is handed a finished list and asked to mount it. Today the only runtime is\n// the Claude Agent SDK; a Gemini or Codex runtime would implement the same interface and translate\n// the same list into its own configuration. Nothing above this line may depend on a runtime.\n\n/** A connector resolved and ready to mount: credentials substituted, nothing left to look up. */\nexport type MountedConnector =\n | { type: 'stdio'; command: string; args: string[]; env: Record<string, string> }\n | { type: 'http' | 'sse'; url: string; headers: Record<string, string>; tools?: string[] };\n\nexport interface AgentRuntime {\n readonly name: string;\n /** Translate ant-bot's mounted connectors into whatever this runtime accepts. */\n mountConnectors(connectors: Record<string, MountedConnector>): Record<string, unknown>;\n}\n\n/**\n * The Claude Agent SDK.\n *\n * Every mounted connector gets `alwaysLoad: true`. Without it the SDK defers MCP tools behind its\n * ToolSearch, which meant a bot had to *find* a connector's tools before it could call one \u2014 and a\n * connector that failed to mount looked identical to one that was merely unfound. With it, the\n * tools are in the prompt, and the system prompt's `## Your connectors` block agrees with what the\n * model can actually see.\n */\nexport class ClaudeRuntime implements AgentRuntime {\n readonly name = 'claude';\n\n mountConnectors(connectors: Record<string, MountedConnector>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [name, c] of Object.entries(connectors)) out[name] = { ...c, alwaysLoad: true };\n return out;\n }\n}\n", "import path from 'node:path';\nimport fs from 'node:fs';\nimport { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';\nimport { z } from 'zod';\nimport type { Store } from '../db/store.js';\nimport type { EventBus } from '../util/bus.js';\nimport type { PermissionGateway } from '../permissions/gateway.js';\nimport type { MountedConnector } from '../agent/runtime.js';\nimport { runTurn, type TurnEvent } from '../agent/session.js';\nimport { buildSystemPrompt } from './prompt.js';\nimport { ensureMemoryDir } from '../memory/memory.js';\nimport { logger } from '../util/log.js';\nimport { LIMITS, type Bot, type Card, type TurnOrigin, type Settings } from '@antbot/contract';\nimport { newId } from '../util/ids.js';\nimport { describeSkillSource } from '../skills/install.js';\n\nconst log = logger('bots');\n\nexport interface TurnJob {\n id: string;\n botId: string;\n threadId: string;\n prompt: string;\n origin: TurnOrigin;\n hops: number;\n /** Priority: interactive turns run before routine turns (plan \u00A79). */\n priority: number;\n onDone?: (summary: string, ok: boolean) => void;\n}\n\nexport interface ManagerDeps {\n store: Store;\n bus: EventBus;\n gateway: PermissionGateway;\n workspace: string;\n getSettings: () => Settings;\n /**\n * Root of the local plugin carrying installed skills. A resolver rather than a value\n * because the skills subsystem is wired after the manager is constructed.\n */\n skillPluginPath?: () => string | undefined;\n /** Install a skill from a user-supplied source. Gated by the `install_skill` require-rule. */\n installSkill?: (\n source: string,\n opts?: { allowMultiple?: boolean },\n ) => Promise<Array<{ name: string; executables: string[] }>>;\n /** Every installed skill, so a bot can check before installing or removing. */\n listSkills?: () => Array<{ slug: string; name: string; description: string }>;\n /** Uninstall by slug. Gated by the `remove_skill` require-rule. */\n removeSkill?: (slug: string) => Promise<{ removed: boolean; name?: string }>;\n browserTools?: (botId: string) => ReturnType<typeof createSdkMcpServer> | undefined;\n /**\n * Directories a bot may read outside the workspace without a human approval. ant-bot's\n * attachments directory belongs here: the human attached those files to the message.\n */\n readableRoots?: string[];\n /**\n * MCP connectors assigned to this bot, resolved and ready to mount. Async because mounting\n * reads secrets from the keychain; returns what it could mount plus what to tell the model\n * about, so a connector skipped for a missing credential simply is not there this turn.\n */\n connectorServers?: (botId: string) => Promise<{\n servers: Record<string, MountedConnector>;\n mounted: { name: string; description: string }[];\n }>;\n}\n\nexport class BotManager {\n private queue: TurnJob[] = [];\n private running = new Map<string, { job: TurnJob; abort: AbortController }>();\n private draining = false;\n\n constructor(private deps: ManagerDeps) {}\n\n get runningCount(): number {\n return this.running.size;\n }\n get queuedCount(): number {\n return this.queue.length;\n }\n isBusy(botId: string): boolean {\n return this.running.has(botId) || this.queue.some((j) => j.botId === botId);\n }\n\n /** Enqueue a turn. Interactive work sorts ahead of routine work. */\n enqueue(job: Omit<TurnJob, 'id' | 'priority'> & { priority?: number }): TurnJob {\n const full: TurnJob = {\n ...job,\n id: newId(),\n priority: job.priority ?? (job.origin === 'routine' ? 10 : 0),\n };\n this.queue.push(full);\n this.queue.sort((a, b) => a.priority - b.priority);\n // Only if nothing is in flight for this bot. A turn waiting on a human approval is\n // \"waiting_approval\"; overwriting that with \"queued\" because a second message arrived is how\n // a bot asking a question came to look like a stalled queue with no question in it.\n if (!this.running.has(full.botId)) this.setState(full.botId, 'queued');\n void this.drain();\n return full;\n }\n\n private async drain(): Promise<void> {\n if (this.draining) return;\n this.draining = true;\n try {\n const max = this.deps.getSettings().maxConcurrentSessions ?? LIMITS.DEFAULT_MAX_CONCURRENT_SESSIONS;\n while (this.queue.length && this.running.size < max) {\n const idx = this.queue.findIndex((j) => !this.running.has(j.botId));\n if (idx === -1) break;\n const [job] = this.queue.splice(idx, 1);\n void this.execute(job!);\n }\n } finally {\n this.draining = false;\n }\n }\n\n private setState(botId: string, state: Bot['state'], attention?: Bot['attention']): void {\n const bot = this.deps.store.updateBot(botId, { state, ...(attention ? { attention } : {}) });\n if (!bot) return;\n this.deps.bus.publish({\n type: 'bot.state', botId, threadId: bot.threadId, state: bot.state, attention: bot.attention,\n });\n }\n\n interrupt(botId: string): boolean {\n const r = this.running.get(botId);\n this.queue = this.queue.filter((j) => j.botId !== botId);\n this.deps.gateway.cancelForBot(botId);\n if (!r) {\n this.setState(botId, 'idle');\n return false;\n }\n r.abort.abort();\n return true;\n }\n\n /** Custom tools exposed to every bot turn: handoff, memory, secrets-safe helpers. */\n private buildToolServer(bot: Bot, threadId: string, hops: number) {\n const { store, workspace } = this.deps;\n return createSdkMcpServer({\n name: 'antbot',\n version: '1.0.0',\n tools: [\n tool(\n 'send_to_bot',\n 'Hand work to another bot on this account. The recipient wakes, handles the request in its own thread, and can reply later. Use when the job genuinely belongs to that role.',\n { bot_slug: z.string().describe('slug of the teammate, e.g. \"writer\"'), message: z.string().describe('the request, with all context they need') },\n async (args: { bot_slug: string; message: string }) => {\n const target = store.getBotBySlug(args.bot_slug);\n if (!target) return { content: [{ type: 'text' as const, text: `No bot with slug \"${args.bot_slug}\". Use one of: ${store.listBots().map((b) => b.slug).join(', ')}` }] };\n if (target.id === bot.id) return { content: [{ type: 'text' as const, text: 'You cannot hand work to yourthis.' }] };\n if (hops + 1 > LIMITS.MAX_BOT_TO_BOT_HOPS)\n return { content: [{ type: 'text' as const, text: `Hop limit of ${LIMITS.MAX_BOT_TO_BOT_HOPS} reached. Stop and report back to the human instead.` }] };\n store.createMail({ fromBotId: bot.id, toBotId: target.id, contentMd: args.message, hops: hops + 1 });\n this.postSystemCard(threadId, bot.id, { type: 'handoff', fromBotId: bot.id, toBotId: target.id, note: args.message.slice(0, 300) });\n this.enqueue({\n botId: target.id, threadId: target.threadId!, origin: 'bot', hops: hops + 1,\n prompt: `**Handoff from @${bot.slug} (${bot.name}):**\\n\\n${args.message}\\n\\n---\\nHandle this, then reply. If it belongs to someone else, say so rather than guessing.`,\n });\n return { content: [{ type: 'text' as const, text: `Handed to @${target.slug}. They will pick it up and reply in their own thread.` }] };\n },\n ),\n tool(\n 'remember',\n 'Save a durable preference or fact to your memory so it survives future turns. Use only for stable things, never for changing data.',\n { title: z.string().describe('short kebab-case file name'), note: z.string().describe('the fact, in markdown') },\n async (args: { title: string; note: string }) => {\n const dir = ensureMemoryDir(workspace, bot.slug);\n const file = path.join(dir, `${args.title.replace(/[^a-zA-Z0-9._-]/g, '-')}.md`);\n fs.writeFileSync(file, args.note);\n return { content: [{ type: 'text' as const, text: `Saved to memory: ${path.basename(file)}` }] };\n },\n ),\n tool(\n 'list_skills',\n 'List every skill installed on this account, with its slug. Check here before installing ' +\n 'something that may already be present, and to find the exact slug to pass to remove_skill.',\n {},\n async () => {\n const skills = this.deps.listSkills?.() ?? [];\n if (!skills.length)\n return { content: [{ type: 'text' as const, text: 'No skills are installed.' }] };\n const lines = skills.map((sk) => `- ${sk.slug} \u2014 ${sk.name}${sk.description ? `: ${sk.description}` : ''}`);\n return { content: [{ type: 'text' as const, text: `${skills.length} skill(s) installed:\\n${lines.join('\\n')}` }] };\n },\n ),\n tool(\n 'install_skill',\n 'Install a skill so you (and other bots) can use it. This always stops for the human\\'s ' +\n 'approval first, because a skill is instructions that will steer future work and may ship scripts. ' +\n 'Check list_skills before installing something you already have.\\n' +\n 'Install the NARROWEST source that covers the request. Accepted forms:\\n' +\n ' github.com/owner/repo/tree/<ref>/<dir> one skill inside a repository \u2014 prefer this\\n' +\n ' https://host/path/SKILL.md one skill, direct link\\n' +\n ' ./path/to/skill a local directory\\n' +\n ' owner/repo, github.com/owner/repo EVERY skill in the repository\\n' +\n 'A bare owner/repo pointing at a collection installs all of it. If the human asked for one ' +\n 'named skill, point at that skill\\'s directory instead; if you only have a link to the repo ' +\n 'root, call this anyway and the error will list what is inside so you can narrow it.',\n {\n source: z.string().describe('prefer owner/repo/tree/<ref>/<dir> or a /SKILL.md link; owner/repo installs the whole repository'),\n reason: z.string().describe('why you need this skill for the task at hand'),\n install_all: z\n .boolean()\n .optional()\n .describe('set true only when the human has asked for every skill in a multi-skill source'),\n },\n async (args: { source: string; reason: string; install_all?: boolean }) => {\n if (!this.deps.installSkill)\n return { content: [{ type: 'text' as const, text: 'Skill installation is unavailable on this server.' }] };\n try {\n const installed = await this.deps.installSkill(args.source, { allowMultiple: args.install_all === true });\n if (!installed.length)\n return { content: [{ type: 'text' as const, text: `No skill found at \"${args.source}\".` }] };\n const names = installed.map((i) => i.name).join(', ');\n const scripts = installed.flatMap((i) => i.executables);\n const note = scripts.length\n ? ` Note for the human: this shipped ${scripts.length} script(s): ${scripts.join(', ')}.`\n : '';\n return {\n content: [{\n type: 'text' as const,\n text: `Installed: ${names}.${note} A skill must still be assigned to you in Bot settings ` +\n 'before you can invoke it \u2014 ask the human to enable it, then retry.',\n }],\n };\n } catch (err) {\n const e = err as Error & { name?: string; names?: string[] };\n if (e.name === 'MultipleSkillsError' && Array.isArray(e.names)) {\n const listed = e.names.slice(0, 40).join(', ');\n const more = e.names.length > 40 ? `, and ${e.names.length - 40} more` : '';\n return {\n content: [{\n type: 'text' as const,\n text:\n `Nothing was installed. \"${args.source}\" holds ${e.names.length} skills: ${listed}${more}.\\n` +\n 'Pick the one you need and install just it, e.g. ' +\n `${args.source.replace(/^https?:\\/\\//, '').replace(/\\/$/, '')}/tree/main/<skill-directory>. ` +\n 'Only pass install_all if the human has asked for all of them.',\n }],\n };\n }\n return { content: [{ type: 'text' as const, text: `Install failed: ${e.message}` }] };\n }\n },\n ),\n tool(\n 'remove_skill',\n 'Uninstall a skill by slug \u2014 deletes its directory and its registration together. ' +\n 'Use this rather than deleting skill directories with Bash, which would leave the ' +\n 'registry pointing at files that no longer exist. Stops for the human\\'s approval.',\n {\n slug: z.string().describe('the skill slug, exactly as list_skills reports it'),\n reason: z.string().describe('why this skill should be removed'),\n },\n async (args: { slug: string; reason: string }) => {\n if (!this.deps.removeSkill)\n return { content: [{ type: 'text' as const, text: 'Skill removal is unavailable on this server.' }] };\n try {\n const res = await this.deps.removeSkill(args.slug);\n if (!res.removed) {\n const known = (this.deps.listSkills?.() ?? []).map((sk) => sk.slug).join(', ');\n return { content: [{ type: 'text' as const, text: `No skill with slug \"${args.slug}\". Installed: ${known || 'none'}.` }] };\n }\n return { content: [{ type: 'text' as const, text: `Removed \"${args.slug}\"${res.name ? ` (${res.name})` : ''}.` }] };\n } catch (err) {\n return { content: [{ type: 'text' as const, text: `Remove failed: ${(err as Error).message}` }] };\n }\n },\n ),\n tool(\n 'request_secret',\n 'Ask the human for a secret value (API key, token). The value goes straight to the keychain and is never shown to you. Never ask for passwords in chat \u2014 ask for computer takeover instead.',\n { name: z.string().describe('identifier, e.g. STRIPE_API_KEY'), reason: z.string() },\n async (args: { name: string; reason: string }) => {\n this.deps.bus.publish({ type: 'secret.request', botId: bot.id, threadId, requestId: newId(), name: args.name, reason: args.reason });\n return { content: [{ type: 'text' as const, text: `Asked the human for \"${args.name}\". It will be injected into your environment as that variable name; you will never see the value. Continue once they confirm.` }] };\n },\n ),\n ],\n });\n }\n\n private postSystemCard(threadId: string, botId: string, card: Card): void {\n const msg = this.deps.store.createMessage({ threadId, authorKind: 'system', authorBotId: botId, cards: [card] });\n this.deps.bus.publish({ type: 'message.created', threadId, botId, message: msg });\n }\n\n private async execute(job: TurnJob): Promise<void> {\n const { store, bus, gateway, workspace, getSettings } = this.deps;\n const bot = store.getBot(job.botId);\n if (!bot) return;\n\n const abort = new AbortController();\n this.running.set(job.botId, { job, abort });\n this.setState(job.botId, 'running', 'none');\n\n const settings = getSettings();\n const msg = store.createMessage({\n threadId: job.threadId, authorKind: 'bot', authorBotId: bot.id, contentMd: '', streaming: true,\n });\n bus.publish({ type: 'message.created', threadId: job.threadId, botId: bot.id, message: msg });\n\n const thread = store.getThread(job.threadId);\n const isGroup = thread?.kind === 'group';\n const botDir = path.join(workspace, 'bots', bot.slug);\n fs.mkdirSync(botDir, { recursive: true });\n\n const botSkills = store.listBotSkills(bot.id);\n const connectors = await this.deps.connectorServers?.(bot.id);\n const systemPrompt = buildSystemPrompt({\n bot, workspace, skills: botSkills,\n connectors: connectors?.mounted ?? [],\n roster: store.listBots().map((x) => ({ slug: x.slug, name: x.name, title: x.title })),\n isGroup,\n });\n\n let text = '';\n let ok = true;\n let errorMessage = '';\n const toolCards = new Map<string, number>();\n\n const mcpServers: Record<string, any> = { antbot: this.buildToolServer(bot, job.threadId, job.hops) };\n const browser = this.deps.browserTools?.(bot.id);\n if (browser) mcpServers.browser = browser;\n\n\n try {\n for await (const ev of runTurn({\n prompt: job.prompt,\n resumeSessionId: bot.sessionId,\n modelTier: bot.modelTier,\n systemPrompt,\n cwd: workspace,\n // The attachments directory sits outside cwd, so the SDK would refuse to open a file the\n // human just attached even after the gateway allowed it.\n additionalDirectories: this.deps.readableRoots ?? [],\n settings,\n abortController: abort,\n mcpServers,\n // Names are validated against RESERVED_CONNECTOR_NAMES, so these cannot clobber the two\n // in-process servers above. Mounted by the runtime adapter, not here.\n connectors: connectors?.servers ?? {},\n skillPluginPath: this.deps.skillPluginPath?.(),\n // Skill names come from SKILL.md frontmatter, which is what the SDK matches on.\n enabledSkills: botSkills.map((s) => s.name),\n canUseTool: async (toolName, input) => {\n // Tools we provide ourselves are already scoped; the gateway still sees them.\n this.setState(job.botId, 'waiting_approval', 'needs_attention');\n const d = await gateway.check({\n botId: bot.id, threadId: job.threadId, toolName, input,\n botDescription: bot.description, settings, signal: abort.signal,\n workspace,\n allowedRoots: this.deps.readableRoots ?? [],\n // Render the approval inline in the transcript so the human can act on it\n // where the work is happening, not only in a global queue.\n onPending: (approval) => {\n const card: Card = { type: 'approval', approvalId: approval.id };\n const idx = store.appendCard(msg.id, card);\n bus.publish({\n type: 'message.card', threadId: job.threadId, botId: bot.id,\n messageId: msg.id, card, cardIndex: idx,\n });\n },\n });\n if (!abort.signal.aborted) this.setState(job.botId, 'running');\n return d.behavior === 'allow'\n ? { behavior: 'allow', updatedInput: input }\n : { behavior: 'deny', message: d.message };\n },\n })) {\n await this.applyEvent(ev, { job, bot, msgId: msg.id, toolCards });\n if (ev.kind === 'text' && ev.text) text += ev.text;\n if (ev.kind === 'done') {\n if (ev.text && !text.trim()) text = ev.text;\n ok = !ev.isError;\n }\n if (ev.kind === 'error') {\n ok = false;\n errorMessage = ev.message ?? 'Unknown error';\n }\n }\n } catch (err) {\n ok = false;\n errorMessage = err instanceof Error ? err.message : String(err);\n log.error('turn crashed', err);\n } finally {\n this.running.delete(job.botId);\n }\n\n if (errorMessage) {\n const idx = store.appendCard(msg.id, { type: 'error', message: errorMessage });\n bus.publish({ type: 'message.card', threadId: job.threadId, botId: bot.id, messageId: msg.id, card: { type: 'error', message: errorMessage }, cardIndex: idx });\n }\n\n const final = text.trim();\n store.updateMessage(msg.id, { contentMd: final, streaming: false });\n bus.publish({ type: 'message.done', threadId: job.threadId, botId: bot.id, messageId: msg.id, contentMd: final });\n\n const interrupted = abort.signal.aborted;\n this.setState(job.botId, interrupted ? 'interrupted' : 'idle', 'unread');\n if (interrupted) this.setState(job.botId, 'idle', 'unread');\n\n job.onDone?.(final || errorMessage, ok && !interrupted);\n void this.drain();\n }\n\n private async applyEvent(\n ev: TurnEvent,\n ctx: { job: TurnJob; bot: Bot; msgId: string; toolCards: Map<string, number> },\n ): Promise<void> {\n const { store, bus } = this.deps;\n const { job, bot, msgId, toolCards } = ctx;\n\n switch (ev.kind) {\n case 'session':\n if (ev.sessionId) store.updateBot(bot.id, { sessionId: ev.sessionId });\n break;\n\n // A connector that does not come up gives the bot no tools and no way to say why \u2014 it\n // simply behaves as though the connector were never assigned. Surfacing the SDK's own\n // verdict is the difference between \"my bot ignores my connector\" and a stated reason.\n case 'mcp_status': {\n // Persist every connector's verdict on its row \u2014 the Connectors screen shows state, and a\n // toast is gone in seconds. The two in-process servers are not rows.\n for (const m of ev.mcpStatus ?? []) {\n if (m.name === 'antbot' || m.name === 'browser') continue;\n store.setConnectorStatusByName(m.name, m.status, m.error ?? null);\n }\n const bad = (ev.mcpStatus ?? []).filter((m) => m.status !== 'connected');\n if (!bad.length) break;\n for (const m of bad) {\n log.warn(`connector \"${m.name}\" did not connect for ${bot.slug}: ${m.status}${m.error ? ` \u2014 ${m.error}` : ''}`);\n }\n bus.publish({\n type: 'notify',\n botId: bot.id,\n threadId: job.threadId,\n title: 'Connector unavailable',\n body: bad.map((m) => `${m.name}: ${describeMcpStatus(m.status)}`).join('; '),\n level: 'warn',\n });\n break;\n }\n\n // Mid-turn sign-in: the link goes into the thread as a card, where the human is looking,\n // and it persists \u2014 a toast would be gone before they came back from the browser.\n case 'signin': {\n if (!ev.signin) break;\n const card: Card = { type: 'signin', serverName: ev.signin.serverName, url: ev.signin.url };\n const idx = store.appendCard(msgId, card);\n bus.publish({ type: 'message.card', threadId: job.threadId, botId: bot.id, messageId: msgId, card, cardIndex: idx });\n store.setConnectorStatusByName(ev.signin.serverName, 'needs-sign-in', null);\n break;\n }\n\n case 'text':\n if (ev.text) {\n const cur = store.getMessage(msgId);\n store.updateMessage(msgId, { contentMd: (cur?.contentMd ?? '') + ev.text });\n bus.publish({ type: 'message.delta', threadId: job.threadId, botId: bot.id, messageId: msgId, delta: ev.text });\n }\n break;\n\n case 'tool_start': {\n const card: Card = {\n type: 'tool', toolName: ev.toolName ?? 'tool',\n summary: summarizeTool(ev.toolName ?? '', ev.toolInput),\n input: ev.toolInput, status: 'running',\n };\n const idx = store.appendCard(msgId, card);\n if (ev.toolUseId) toolCards.set(ev.toolUseId, idx);\n bus.publish({ type: 'message.card', threadId: job.threadId, botId: bot.id, messageId: msgId, card, cardIndex: idx });\n break;\n }\n\n case 'tool_result': {\n const idx = ev.toolUseId ? toolCards.get(ev.toolUseId) : undefined;\n if (idx === undefined) break;\n const cur = store.getMessage(msgId);\n const existing = cur?.cards[idx];\n if (!existing || existing.type !== 'tool') break;\n const denied = ev.isError && /denied|approval/i.test(ev.result ?? '');\n const card: Card = {\n ...existing,\n status: denied ? 'denied' : ev.isError ? 'error' : 'ok',\n result: (ev.result ?? '').slice(0, 2000),\n };\n store.updateCard(msgId, idx, card);\n bus.publish({ type: 'message.card', threadId: job.threadId, botId: bot.id, messageId: msgId, card, cardIndex: idx });\n break;\n }\n\n case 'done':\n if (ev.sessionId) store.updateBot(bot.id, { sessionId: ev.sessionId });\n if (ev.usage) {\n store.recordUsage({\n botId: bot.id, turnId: job.id, model: ev.usage.model,\n inputTokens: ev.usage.inputTokens, outputTokens: ev.usage.outputTokens,\n cacheReadTokens: ev.usage.cacheReadTokens, costEstimate: ev.usage.costUsd,\n });\n bus.publish({\n type: 'usage.tick', threadId: job.threadId, botId: bot.id,\n inputTokens: ev.usage.inputTokens, outputTokens: ev.usage.outputTokens, model: ev.usage.model,\n });\n }\n break;\n\n default:\n break;\n }\n }\n}\n\n/** Plain-language reason a connector is not usable this turn. */\nexport function describeMcpStatus(status: string): string {\n switch (status) {\n case 'needs-auth':\n return 'needs authentication \u2014 the server rejected the credentials it was given (or was given none)';\n case 'failed':\n return 'failed to start \u2014 run `antbot mcp check <name>` to see why';\n case 'pending':\n return 'did not finish connecting in time';\n case 'disabled':\n return 'is disabled';\n default:\n return status;\n }\n}\n\n/**\n * Tool arguments as `key: value`, not JSON.\n *\n * These land in an approval card and in the thread, where a raw object is noise a person has to\n * decode before deciding anything. Nested objects collapse to `{\u2026}`: naming the key is useful,\n * dumping its contents is the thing being avoided.\n */\nexport function summarizeArgs(input: unknown): string {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) return '';\n const parts: string[] = [];\n for (const [k, v] of Object.entries(input as Record<string, unknown>)) {\n if (v === undefined || v === null || v === '') continue;\n let s: string;\n if (typeof v === 'string') s = v;\n else if (typeof v === 'number' || typeof v === 'boolean') s = String(v);\n else if (Array.isArray(v)) s = `${v.length} item${v.length === 1 ? '' : 's'}`;\n else s = '{\u2026}';\n parts.push(`${k}: ${s.length > 60 ? `${s.slice(0, 60)}\u2026` : s}`);\n }\n return parts.join(', ');\n}\n\nexport function summarizeTool(name: string, input: unknown): string {\n const o = (input ?? {}) as Record<string, unknown>;\n const s = (k: string): string => (typeof o[k] === 'string' ? (o[k] as string) : '');\n if (name === 'Bash') return s('command').slice(0, 160);\n if (name === 'Read' || name === 'Write' || name === 'Edit') return s('file_path');\n if (name === 'WebFetch') return s('url');\n if (name.includes('send_to_bot')) return `\u2192 @${s('bot_slug')}`;\n if (name.includes('install_skill')) return describeSkillSource(s('source'));\n if (name.includes('remove_skill')) return `remove skill: ${s('slug')}`;\n if (name.includes('list_skills')) return 'list installed skills';\n if (name.includes('remember')) return `memory: ${s('title')}`;\n if (name.startsWith('browser_') || name.includes('browser')) return [s('url'), s('selector'), s('text')].filter(Boolean).join(' ').slice(0, 160);\n // A third-party connector's tool. Nothing is known about its arguments, but naming the server\n // and the tool beats an approval card that reads as raw JSON. Matched last so the built-in\n // servers above keep their own summaries.\n const mcp = /^mcp__([^_]+(?:_[^_]+)*)__(.+)$/.exec(name);\n if (mcp) {\n const args = summarizeArgs(input);\n return `${mcp[1]}: ${mcp[2]}${args ? ` ${args}` : ''}`.slice(0, 160);\n }\n const args = summarizeArgs(input);\n return args.length > 160 ? `${args.slice(0, 160)}\u2026` : args;\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Per-bot memory lives as markdown on the shared computer: workspace/bots/<slug>/memory/*.md */\nexport function memoryDir(workspace: string, slug: string): string {\n return path.join(workspace, 'bots', slug, 'memory');\n}\n\nexport function ensureMemoryDir(workspace: string, slug: string): string {\n const dir = memoryDir(workspace, slug);\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nexport interface MemoryFile { name: string; content: string }\n\nexport function readMemory(workspace: string, slug: string): MemoryFile[] {\n const dir = memoryDir(workspace, slug);\n if (!fs.existsSync(dir)) return [];\n return fs\n .readdirSync(dir)\n .filter((f) => f.endsWith('.md'))\n .sort()\n .map((name) => ({ name, content: fs.readFileSync(path.join(dir, name), 'utf8') }));\n}\n\nexport function writeMemory(workspace: string, slug: string, name: string, content: string): void {\n const dir = ensureMemoryDir(workspace, slug);\n const safe = name.replace(/[^a-zA-Z0-9._-]/g, '-');\n fs.writeFileSync(path.join(dir, safe.endsWith('.md') ? safe : `${safe}.md`), content);\n}\n\nexport function deleteMemory(workspace: string, slug: string, name: string): void {\n const f = path.join(memoryDir(workspace, slug), name.replace(/[^a-zA-Z0-9._-]/g, '-'));\n if (fs.existsSync(f)) fs.unlinkSync(f);\n}\n\nexport function renderMemoryBlock(files: MemoryFile[]): string {\n if (!files.length) return '';\n const body = files.map((f) => `### ${f.name}\\n${f.content.trim()}`).join('\\n\\n');\n return `\\n\\n## Your memory\\nStable preferences and facts you recorded earlier. Memory is a working\\nnote, not an authoritative source \u2014 re-check the source system before any\\nconsequential decision.\\n\\n${body}`;\n}\n", "import type { Bot, Skill } from '@antbot/contract';\nimport { readMemory, renderMemoryBlock } from '../memory/memory.js';\n\nexport interface PromptContext {\n bot: Bot;\n workspace: string;\n skills: Skill[];\n /** Connectors actually mounted this turn \u2014 a connector skipped for a missing secret is absent. */\n connectors?: { name: string; description: string }[];\n roster: Array<{ slug: string; name: string; title: string }>;\n isGroup: boolean;\n groupMembers?: string[];\n}\n\n/**\n * System prompt = base teammate persona + bot profile + memory + roster + boundaries.\n * The description carries standing rules; the conversation carries task instructions\n * (the durable/ephemeral split from outline \u00A74).\n */\nexport function buildSystemPrompt(ctx: PromptContext): string {\n const { bot, workspace } = ctx;\n const parts: string[] = [];\n\n parts.push(`You are **${bot.name}**${bot.title ? `, ${bot.title}` : ''} \u2014 a persistent AI teammate in ant-bot.\n\nYou are not a general chat assistant. You own a job and finish work end to end,\nthen report back with evidence. You keep working across turns; your files,\nmemory and browser sessions persist.`);\n\n if (bot.description.trim()) {\n parts.push(`## Your standing job description\nThese are durable rules for how you work. They outrank any single message.\n\n${bot.description.trim()}`);\n }\n\n parts.push(`## Your computer\nYou share one computer with every other bot on this account.\n- Shared workspace: \\`${workspace}\\` \u2014 keep durable project files here.\n- Your own folder: \\`${workspace}/bots/${bot.slug}/\\`\n- Files, logins and installed tools are visible to all bots. Bots are **not** a\n security boundary. Do not store anything here another bot should not see.`);\n\n const mem = renderMemoryBlock(readMemory(workspace, bot.slug));\n if (mem) parts.push(mem.trim());\n\n if (ctx.skills.length) {\n parts.push(`## Your skills\n${ctx.skills.map((s) => `- **${s.name}** (${s.slug}): ${s.description}`).join('\\n')}\nRead the skill file before following it.`);\n }\n\n if (ctx.connectors?.length) {\n parts.push(`## Your connectors\n${ctx.connectors.map((c) => `- **${c.name}**${c.description ? `: ${c.description}` : ''}`).join('\\n')}\nTheir tools appear as \\`mcp__<connector>__<tool>\\`. Prefer a connector's tools over driving the\nbrowser for the same service \u2014 it is faster, and it does not depend on a page's layout.`);\n }\n\n const others = ctx.roster.filter((r) => r.slug !== bot.slug);\n if (others.length) {\n parts.push(`## Your teammates\n${others.map((r) => `- @${r.slug} \u2014 ${r.name}${r.title ? `, ${r.title}` : ''}`).join('\\n')}\n\nUse the \\`send_to_bot\\` tool to hand work to a teammate when the job genuinely\nbelongs to their role. Keep one owner per stage \u2014 do not fan the same task out\nto several bots at once.`);\n }\n\n if (ctx.isGroup) {\n parts.push(`## Group conversation\nYou are in a group chat. Other bots can see and reply to these messages.\nAnswer only when the request is yours to own, or when you were @-mentioned.\nSay who should take the next step. Keep replies short \u2014 the humans are reading.`);\n }\n\n parts.push(`## How to work\n- Lead with the result. Put evidence \u2014 links, file paths, quoted output \u2014 under it.\n- Separate: facts found, assumptions, actions taken, actions awaiting approval,\n open questions.\n- Write deliverables as real files in the workspace, not as walls of chat text.\n- Never guess at a credential. If a step needs a password, 2FA code or CAPTCHA,\n stop and ask the human to take over the computer.\n- Some actions pause for the human's approval. That is normal \u2014 propose the\n action and wait. Approval covers only the proposed step; it does not undo\n anything you already did.`);\n\n return parts.join('\\n\\n');\n}\n", "// Turning stored connector rows into MCP server configs the Agent SDK can mount.\n//\n// Two things make this worth a module of its own. First, it is the only place a secret *value*\n// ever enters a config object \u2014 everywhere else in the system a connector carries a reference\n// (`{{secret:NAME}}`) and nothing more. Second, deciding what to mount is a decision, not an\n// action: which connectors are usable, which are missing credentials, and what the human should\n// be told. Keeping that pure means every branch is testable without a keychain or a subprocess.\nimport type { Connector, ConnectorConfig } from '@antbot/contract';\nimport type { MountedConnector } from '../agent/runtime.js';\n\n/**\n * A reference to a stored secret, embeddable inside a value: `Bearer {{secret:GH_TOKEN}}`.\n *\n * A template rather than a structured field because real credentials are usually part of a\n * larger string \u2014 an `Authorization` header is a scheme plus a token \u2014 and an object form\n * ({secret: 'NAME'}) cannot express that without inventing a concatenation syntax anyway.\n */\nexport const SECRET_REF_RE = /\\{\\{secret:([A-Za-z0-9_.-]+)\\}\\}/g;\n\n/** Every secret name referenced anywhere in a config, deduplicated, in first-seen order. */\nexport function extractSecretRefs(config: ConnectorConfig): string[] {\n const values = config.transport === 'stdio' ? Object.values(config.env) : Object.values(config.headers);\n const names: string[] = [];\n for (const v of values) {\n for (const m of v.matchAll(SECRET_REF_RE)) {\n const name = m[1]!;\n if (!names.includes(name)) names.push(name);\n }\n }\n return names;\n}\n\n/** References with nothing behind them. Drives the warning badge in the UI and the CLI listing. */\nexport function computeMissingSecrets(connector: Connector, available: ReadonlySet<string>): string[] {\n return extractSecretRefs(connector.config).filter((n) => !available.has(n));\n}\n\nexport interface MountPlan {\n mount: Connector[];\n skipped: { connector: Connector; missing: string[] }[];\n}\n\n/**\n * Decide which of a bot's connectors can actually be mounted this turn.\n *\n * A connector whose credential is missing is skipped, not fatal. Mounting it anyway would hand\n * the model a server that fails on first use with an opaque protocol error; failing the whole\n * turn would let one broken connector block work that has nothing to do with it. Skipping is the\n * only option that leaves the rest of the turn intact \u2014 and the human already had a warning on\n * the connectors screen before it came to this.\n */\nexport function planConnectorMount(assigned: Connector[], available: ReadonlySet<string>): MountPlan {\n const plan: MountPlan = { mount: [], skipped: [] };\n for (const connector of assigned) {\n const missing = computeMissingSecrets(connector, available);\n if (missing.length) plan.skipped.push({ connector, missing });\n else plan.mount.push(connector);\n }\n return plan;\n}\n\n/** Thrown when a name that was present at planning time yields nothing at resolve time. */\nexport class MissingSecretError extends Error {\n constructor(\n public connectorName: string,\n public secretName: string,\n ) {\n super(`Connector \"${connectorName}\" references secret \"${secretName}\", which could not be read.`);\n this.name = 'MissingSecretError';\n }\n}\n\nfunction substitute(value: string, connectorName: string, secrets: ReadonlyMap<string, string | null>): string {\n return value.replace(SECRET_REF_RE, (_full, name: string) => {\n const resolved = secrets.get(name);\n // Between planning and here the backend can still come up empty \u2014 a keychain that locked, a\n // secret deleted mid-turn. Throwing skips this one connector in the caller rather than\n // silently mounting it with the literal \"{{secret:NAME}}\" as its credential.\n if (resolved == null) throw new MissingSecretError(connectorName, name);\n return resolved;\n });\n}\n\nconst substituteAll = (\n record: Record<string, string>,\n connectorName: string,\n secrets: ReadonlyMap<string, string | null>,\n): Record<string, string> =>\n Object.fromEntries(Object.entries(record).map(([k, v]) => [k, substitute(v, connectorName, secrets)]));\n\n/**\n * The SDK config for one connector, with secret references replaced by their values.\n *\n * The returned object is the only representation that holds real credentials. It goes straight\n * into the turn's `mcpServers` map and is never persisted, logged, or returned by a route.\n * Runtime-neutral: this is ant-bot's own shape, and the agent runtime's adapter translates it.\n */\nexport function buildMcpServerConfig(\n connector: Connector,\n secrets: ReadonlyMap<string, string | null>,\n): MountedConnector {\n const c = connector.config;\n if (c.transport === 'stdio') {\n return {\n type: 'stdio',\n command: c.command,\n args: c.args,\n env: substituteAll(c.env, connector.name, secrets),\n };\n }\n return {\n type: c.transport,\n url: c.url,\n headers: substituteAll(c.headers, connector.name, secrets),\n ...(c.tools ? { tools: c.tools } : {}),\n };\n}\n", "// The connector sign-in flow: discovery, an authorize URL for the human, the callback, and the\n// token refresh that keeps a signed-in connector working afterwards.\n//\n// Tokens live in the same keychain as every other secret and never touch the database or any\n// route response \u2014 the same rule the `{{secret:NAME}}` references follow. What is stored is one\n// JSON blob per connector, because a refresh needs the client id, the token endpoint and the\n// resource alongside the tokens themselves.\nimport crypto from 'node:crypto';\nimport type { Connector } from '@antbot/contract';\nimport { logger } from '../util/log.js';\nimport {\n discoverAuth, registerClient, exchangeCode, refreshTokens, createPkce, buildAuthorizeUrl,\n needsRefresh, OAuthError, type StoredTokens, type DiscoveryResult,\n} from './oauth.js';\n\nconst log = logger('connector-auth');\n\n/** Keychain key for one connector's tokens. Namespaced so it cannot collide with a user secret. */\nexport const tokenSecretName = (connectorName: string): string => `antbot:oauth:${connectorName}`;\n\n/**\n * Keychain key for a connector's OAuth client credentials.\n *\n * Kept separate from the tokens because it outlives them: a client id and secret are registered\n * once with the provider, while tokens come and go. Storing them means a second `login` \u2014 after\n * an expiry, a revocation, or a failed first attempt \u2014 does not ask for them again.\n */\nexport const clientSecretName = (connectorName: string): string => `antbot:oauth-client:${connectorName}`;\n\ninterface ClientCredentials {\n clientId: string;\n clientSecret?: string;\n}\n\n/** Where the authorization server sends the human back. Must be registered with the provider. */\nexport const redirectUri = (port: number): string => `http://127.0.0.1:${port}/api/connectors/oauth/callback`;\n\ninterface PendingLogin {\n connectorId: string;\n connectorName: string;\n verifier: string;\n clientId: string;\n clientSecret?: string;\n tokenEndpoint: string;\n resource?: string;\n redirectUri: string;\n startedAt: number;\n}\n\n/** Minimal secrets surface, so this module is testable without a keychain. */\nexport interface TokenStore {\n set(name: string, value: string): Promise<void>;\n remove(name: string): Promise<void>;\n resolve(names: string[]): Promise<Map<string, string | null>>;\n list(): string[];\n}\n\n/** A sign-in that has been started and is waiting for the human to come back. */\nconst LOGIN_TTL_MS = 10 * 60 * 1000;\n\nexport class ConnectorAuthService {\n private readonly pending = new Map<string, PendingLogin>();\n\n constructor(\n private readonly secrets: TokenStore,\n /** Read lazily: the listening port is settled after this service is built. */\n private readonly portOf: () => number,\n ) {}\n private get port(): number {\n return this.portOf();\n }\n\n /** Has this connector been signed in? Names only \u2014 never reads a value to answer. */\n isAuthorized(connectorName: string): boolean {\n return this.secrets.list().includes(tokenSecretName(connectorName));\n }\n\n private async read(connectorName: string): Promise<StoredTokens | null> {\n const key = tokenSecretName(connectorName);\n const found = (await this.secrets.resolve([key])).get(key);\n if (!found) return null;\n try {\n return JSON.parse(found) as StoredTokens;\n } catch {\n // A corrupt blob is the same as not signed in; the human can sign in again.\n log.warn(`stored tokens for \"${connectorName}\" are unreadable`);\n return null;\n }\n }\n\n private async write(connectorName: string, tokens: StoredTokens): Promise<void> {\n await this.secrets.set(tokenSecretName(connectorName), JSON.stringify(tokens));\n }\n\n /**\n * The scopes a stored sign-in actually carries, or null when there is no sign-in.\n *\n * A token grants what was consented to when it was minted, not what the client is configured\n * to be allowed to ask for. Widening the requested list does nothing until the human signs in\n * again \u2014 and without checking, that shows up as a tool that keeps returning \"insufficient\n * permission\" with everything looking correctly connected.\n */\n async grantedScopes(connectorName: string): Promise<string[] | null> {\n const key = tokenSecretName(connectorName);\n const raw = (await this.secrets.resolve([key])).get(key);\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw) as { scope?: string };\n return typeof parsed.scope === 'string' ? parsed.scope.split(/\\s+/).filter(Boolean) : [];\n } catch {\n return null;\n }\n }\n\n async signOut(connectorName: string): Promise<void> {\n await this.secrets.remove(tokenSecretName(connectorName));\n }\n\n /** Forget the tokens *and* the registered client. Used when the credentials themselves are wrong. */\n async forgetClient(connectorName: string): Promise<void> {\n await this.secrets.remove(clientSecretName(connectorName));\n }\n\n private async readClient(clientKey: string): Promise<ClientCredentials | null> {\n const key = clientSecretName(clientKey);\n const found = (await this.secrets.resolve([key])).get(key);\n if (!found) return null;\n try {\n return JSON.parse(found) as ClientCredentials;\n } catch {\n return null;\n }\n }\n\n /**\n * Begin a sign-in. Returns the URL the human must open.\n *\n * `clientId` is required only when the authorization server does not support dynamic client\n * registration \u2014 Google being the notable case, where the human supplies one from their own\n * cloud console. Everything else registers ant-bot automatically.\n */\n async beginLogin(\n connector: Connector,\n opts: { clientId?: string; clientSecret?: string; scopes?: string[] } = {},\n ): Promise<{ authorizeUrl: string; discovery: DiscoveryResult }> {\n if (connector.config.transport === 'stdio') {\n throw new OAuthError('Sign-in applies to http and sse connectors; a stdio server takes its credentials in env.');\n }\n const discovery = await discoverAuth(connector.config.url);\n const authorizeUrl = await this.beginLoginWith(\n {\n connectorId: connector.id,\n connectorName: connector.name,\n clientKey: connector.name,\n authorizationEndpoint: discovery.authServer.authorizationEndpoint,\n tokenEndpoint: discovery.authServer.tokenEndpoint,\n registrationEndpoint: discovery.authServer.registrationEndpoint,\n resource: discovery.resource.resource,\n scopes: opts.scopes?.length ? opts.scopes : discovery.resource.scopesSupported,\n // Without these Google issues no refresh token, and the connector dies in an hour. Harmless\n // for providers that ignore them.\n extras: { access_type: 'offline', prompt: 'consent' },\n },\n opts,\n );\n return { authorizeUrl, discovery };\n }\n\n /**\n * Begin a sign-in against a known authorization server. Used directly by built-in connectors,\n * whose provider endpoints are fixed and whose client credentials are shared under one\n * `clientKey` \u2014 one Google client serves Gmail, Calendar and Drive.\n */\n async beginLoginWith(\n target: {\n connectorId: string;\n connectorName: string;\n clientKey: string;\n authorizationEndpoint: string;\n tokenEndpoint: string;\n registrationEndpoint?: string;\n resource?: string;\n scopes: string[];\n extras?: Record<string, string>;\n /** Shown when a client ID is needed and none is known. */\n providerName?: string;\n },\n opts: { clientId?: string; clientSecret?: string } = {},\n ): Promise<string> {\n const redirect = redirectUri(this.port);\n\n // Given now, else remembered from last time, else registered automatically. The remembered\n // path is what makes a retry after a failed exchange painless.\n const remembered = await this.readClient(target.clientKey);\n let clientId = opts.clientId ?? remembered?.clientId;\n let clientSecret = opts.clientSecret ?? (opts.clientId ? undefined : remembered?.clientSecret);\n if (!clientId && target.registrationEndpoint) {\n const registered = await registerClient(target.registrationEndpoint, redirect);\n clientId = registered?.clientId;\n clientSecret = registered?.clientSecret;\n }\n if (!clientId) {\n const who = target.providerName ?? new URL(target.authorizationEndpoint).host;\n throw new OAuthError(\n `${who} does not support automatic app registration, so it needs a client ID you create yourself. ` +\n `Register one with that provider, add \"${redirect}\" as an authorised redirect URI, and pass the client ID with --client-id.`,\n );\n }\n\n // Remember before sending the human to the provider, so a failed exchange does not lose them.\n if (opts.clientId || opts.clientSecret || !remembered) {\n await this.secrets.set(clientSecretName(target.clientKey), JSON.stringify({ clientId, clientSecret }));\n }\n\n const pkce = createPkce();\n const state = crypto.randomBytes(16).toString('base64url');\n this.pending.set(state, {\n connectorId: target.connectorId,\n connectorName: target.connectorName,\n verifier: pkce.verifier,\n clientId,\n clientSecret,\n tokenEndpoint: target.tokenEndpoint,\n resource: target.resource,\n redirectUri: redirect,\n startedAt: Date.now(),\n });\n this.sweep();\n\n return buildAuthorizeUrl({\n authorizationEndpoint: target.authorizationEndpoint,\n clientId,\n redirectUri: redirect,\n scopes: target.scopes,\n state,\n challenge: pkce.challenge,\n resource: target.resource,\n extra: target.extras,\n });\n }\n\n /** Whether client credentials are on file for a key (a connector name or a provider key). */\n hasClient(clientKey: string): boolean {\n return this.secrets.list().includes(clientSecretName(clientKey));\n }\n\n /** Finish a sign-in from the redirect. Returns the connector that was authorised. */\n async completeLogin(state: string, code: string): Promise<{ connectorId: string; connectorName: string }> {\n const p = this.pending.get(state);\n // Unknown state is the CSRF guard: a callback we did not start is not ours to act on.\n if (!p) throw new OAuthError('This sign-in link is no longer valid. Start the sign-in again.');\n this.pending.delete(state);\n\n let tokens;\n try {\n tokens = await exchangeCode({\n tokenEndpoint: p.tokenEndpoint,\n code,\n verifier: p.verifier,\n clientId: p.clientId,\n clientSecret: p.clientSecret,\n redirectUri: p.redirectUri,\n resource: p.resource,\n });\n } catch (err) {\n const message = (err as Error).message;\n // Google's \"Web application\" client type authenticates at the token endpoint, so the id\n // alone is not enough. Its own wording does not say what to do about it.\n if (/client_secret/i.test(message)) {\n throw new OAuthError(\n 'This provider requires a client secret as well as a client ID. Add the secret from the ' +\n \"same OAuth client (in Google's console: the client's \\\"Client secret\\\") and sign in again.\",\n );\n }\n throw err;\n }\n await this.write(p.connectorName, tokens);\n log.info(`connector \"${p.connectorName}\" signed in`);\n return { connectorId: p.connectorId, connectorName: p.connectorName };\n }\n\n /**\n * The Authorization header for a mounted connector, refreshing first if the token is close to\n * expiry. Returns null when the connector was never signed in, which is not an error \u2014 most\n * connectors use a static credential or none.\n */\n async authHeader(connectorName: string): Promise<Record<string, string> | null> {\n let tokens = await this.read(connectorName);\n if (!tokens) return null;\n if (needsRefresh(tokens, Date.now())) {\n try {\n tokens = await refreshTokens(tokens);\n await this.write(connectorName, tokens);\n } catch (err) {\n // Refusing to mount beats mounting with a token known to be expired: the failure is\n // reported once, here, instead of as an opaque 401 in the middle of a bot's work.\n log.warn(`could not refresh tokens for \"${connectorName}\": ${(err as Error).message}`);\n return null;\n }\n }\n return { Authorization: `Bearer ${tokens.accessToken}` };\n }\n\n private sweep(): void {\n const cutoff = Date.now() - LOGIN_TTL_MS;\n for (const [state, p] of this.pending) if (p.startedAt < cutoff) this.pending.delete(state);\n }\n}\n", "// OAuth for MCP servers, owned by ant-bot rather than borrowed from the `claude` CLI.\n//\n// Many useful MCP servers will not take a static token in a header \u2014 they want an interactive\n// sign-in. Without this, those servers can be registered, assigned, and still hand a bot nothing.\n//\n// The flow is the one the MCP spec adopts: RFC 9728 discovery from the server's own 401, then\n// OAuth 2.1 authorization-code with PKCE against whatever authorization server it names.\n//\n// Two paths, because the field is split:\n// - the server's authorization server supports RFC 7591 dynamic client registration, and\n// ant-bot registers itself; or\n// - it does not (Google, notably), and the human supplies a client id from their own console.\n//\n// Pure parsing and URL building live at the top and are tested without a network; the I/O below\n// is a thin shell over them.\nimport crypto from 'node:crypto';\n\n/** What a server's 401 points at, per RFC 9728. */\nexport function parseResourceMetadataUrl(wwwAuthenticate: string | null): string | null {\n if (!wwwAuthenticate) return null;\n const m = /resource_metadata\\s*=\\s*\"([^\"]+)\"/i.exec(wwwAuthenticate);\n return m ? m[1]! : null;\n}\n\nexport interface ProtectedResourceMetadata {\n authorizationServers: string[];\n scopesSupported: string[];\n resource?: string;\n}\n\nexport function parseProtectedResourceMetadata(body: unknown): ProtectedResourceMetadata | null {\n const b = body as Record<string, unknown> | null;\n const servers = b?.authorization_servers;\n if (!Array.isArray(servers) || servers.length === 0) return null;\n return {\n authorizationServers: servers.map(String),\n scopesSupported: Array.isArray(b?.scopes_supported) ? (b!.scopes_supported as unknown[]).map(String) : [],\n resource: typeof b?.resource === 'string' ? b.resource : undefined,\n };\n}\n\nexport interface AuthServerMetadata {\n authorizationEndpoint: string;\n tokenEndpoint: string;\n registrationEndpoint?: string;\n scopesSupported: string[];\n}\n\nexport function parseAuthServerMetadata(body: unknown): AuthServerMetadata | null {\n const b = body as Record<string, unknown> | null;\n const auth = b?.authorization_endpoint;\n const token = b?.token_endpoint;\n if (typeof auth !== 'string' || typeof token !== 'string') return null;\n return {\n authorizationEndpoint: auth,\n tokenEndpoint: token,\n registrationEndpoint: typeof b?.registration_endpoint === 'string' ? b.registration_endpoint : undefined,\n scopesSupported: Array.isArray(b?.scopes_supported) ? (b!.scopes_supported as unknown[]).map(String) : [],\n };\n}\n\n/** The well-known locations an authorization server's metadata may live at, most specific first. */\nexport function authServerMetadataUrls(issuer: string): string[] {\n const u = new URL(issuer);\n const path = u.pathname.replace(/\\/$/, '');\n const base = `${u.protocol}//${u.host}`;\n return [\n `${base}/.well-known/oauth-authorization-server${path}`,\n `${base}/.well-known/openid-configuration${path}`,\n `${base}${path}/.well-known/oauth-authorization-server`,\n `${base}${path}/.well-known/openid-configuration`,\n ];\n}\n\nexport interface Pkce {\n verifier: string;\n challenge: string;\n}\n\n/** RFC 7636 S256. The verifier never leaves the daemon; only its hash goes in the URL. */\nexport function createPkce(): Pkce {\n const verifier = crypto.randomBytes(32).toString('base64url');\n const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');\n return { verifier, challenge };\n}\n\nexport interface AuthorizeUrlInput {\n authorizationEndpoint: string;\n clientId: string;\n redirectUri: string;\n scopes: string[];\n state: string;\n challenge: string;\n /** RFC 8707 \u2014 binds the token to this MCP server so it cannot be replayed elsewhere. */\n resource?: string;\n /** Google needs these to return a refresh token at all. */\n extra?: Record<string, string>;\n}\n\nexport function buildAuthorizeUrl(i: AuthorizeUrlInput): string {\n const u = new URL(i.authorizationEndpoint);\n const p = u.searchParams;\n p.set('response_type', 'code');\n p.set('client_id', i.clientId);\n p.set('redirect_uri', i.redirectUri);\n p.set('state', i.state);\n p.set('code_challenge', i.challenge);\n p.set('code_challenge_method', 'S256');\n if (i.scopes.length) p.set('scope', i.scopes.join(' '));\n if (i.resource) p.set('resource', i.resource);\n for (const [k, v] of Object.entries(i.extra ?? {})) p.set(k, v);\n return u.toString();\n}\n\nexport interface StoredTokens {\n accessToken: string;\n refreshToken?: string;\n /** Epoch ms. Absent when the server did not say, in which case we do not pre-emptively refresh. */\n expiresAt?: number;\n scope?: string;\n tokenEndpoint: string;\n clientId: string;\n clientSecret?: string;\n resource?: string;\n}\n\n/** Parse a token endpoint response into what we store. `now` is injected so expiry is testable. */\nexport function parseTokenResponse(\n body: unknown,\n ctx: { tokenEndpoint: string; clientId: string; clientSecret?: string; resource?: string; previousRefresh?: string },\n now: number,\n): StoredTokens | null {\n const b = body as Record<string, unknown> | null;\n if (typeof b?.access_token !== 'string') return null;\n const expiresIn = typeof b.expires_in === 'number' ? b.expires_in : undefined;\n return {\n accessToken: b.access_token,\n // A refresh response often omits refresh_token, meaning \"keep using the one you have\".\n refreshToken: typeof b.refresh_token === 'string' ? b.refresh_token : ctx.previousRefresh,\n expiresAt: expiresIn ? now + expiresIn * 1000 : undefined,\n scope: typeof b.scope === 'string' ? b.scope : undefined,\n tokenEndpoint: ctx.tokenEndpoint,\n clientId: ctx.clientId,\n clientSecret: ctx.clientSecret,\n resource: ctx.resource,\n };\n}\n\n/**\n * Whether a token should be refreshed before use.\n *\n * The skew matters: a token that expires during the turn it was checked for is worse than one\n * refreshed a minute early, because the failure surfaces as an opaque 401 mid-task.\n */\nexport function needsRefresh(tokens: StoredTokens, now: number, skewMs = 60_000): boolean {\n if (!tokens.expiresAt) return false;\n return now + skewMs >= tokens.expiresAt;\n}\n\n/* --------------------------------- I/O shell --------------------------------- */\n\nconst JSON_HEADERS = { accept: 'application/json' };\nconst FETCH_TIMEOUT_MS = 15_000;\n\nasync function getJson(url: string): Promise<unknown | null> {\n try {\n const res = await fetch(url, { headers: JSON_HEADERS, signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n return res.ok ? await res.json() : null;\n } catch {\n return null;\n }\n}\n\nexport class OAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OAuthError';\n }\n}\n\nexport interface DiscoveryResult {\n resource: ProtectedResourceMetadata;\n authServer: AuthServerMetadata;\n}\n\n/**\n * Where a server's protected-resource metadata might be, most authoritative first.\n *\n * RFC 9728 forms the URL by inserting the well-known segment *before the resource path*, which\n * is what makes candidate 2 the standard one. The hint from `WWW-Authenticate` is tried first\n * because a server is allowed to put it anywhere \u2014 but it is not always usable: Google answers a\n * `tools/call` challenge with a metadata URL scoped to the tool that was called, so probing with\n * a name that does not exist yields a hint that 404s. Falling through to the standard location\n * covers that without ever invoking one of the server's real tools.\n */\nexport function resourceMetadataCandidates(mcpUrl: string, wwwAuthenticate: string | null): string[] {\n const u = new URL(mcpUrl);\n const path = u.pathname.replace(/\\/$/, '');\n const out: string[] = [];\n const hint = parseResourceMetadataUrl(wwwAuthenticate);\n if (hint) out.push(hint);\n out.push(`${u.origin}/.well-known/oauth-protected-resource${path}`);\n out.push(`${u.origin}/.well-known/oauth-protected-resource`);\n return [...new Set(out)];\n}\n\nasync function firstResourceMetadata(\n mcpUrl: string,\n wwwAuthenticate: string | null,\n): Promise<ProtectedResourceMetadata | null> {\n for (const url of resourceMetadataCandidates(mcpUrl, wwwAuthenticate)) {\n const meta = parseProtectedResourceMetadata(await getJson(url));\n if (meta) return meta;\n }\n return null;\n}\n\n/**\n * Ask the server itself what it wants, starting from its 401.\n *\n * A `tools/call` rather than `initialize`, because servers commonly answer the handshake to\n * anyone and only challenge on real work \u2014 which is exactly the case that made a connector look\n * healthy while giving a bot nothing.\n */\nexport async function discoverAuth(mcpUrl: string, headers: Record<string, string> = {}): Promise<DiscoveryResult> {\n let challenge: string | null;\n try {\n const res = await fetch(mcpUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'application/json, text/event-stream', ...headers },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: '__antbot_auth_probe__', arguments: {} } }),\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n challenge = res.headers.get('www-authenticate');\n } catch (err) {\n throw new OAuthError(`Could not reach ${mcpUrl}: ${(err as Error).message}`);\n }\n\n const found = await firstResourceMetadata(mcpUrl, challenge);\n if (!found) {\n throw new OAuthError(\n 'This server did not advertise an authorization server, so ant-bot cannot sign in to it. ' +\n 'If it takes a static token, add one as an Authorization header instead.',\n );\n }\n\n const resourceMeta = found;\n for (const issuer of resourceMeta.authorizationServers) {\n for (const url of authServerMetadataUrls(issuer)) {\n const meta = parseAuthServerMetadata(await getJson(url));\n if (meta) return { resource: resourceMeta, authServer: meta };\n }\n }\n throw new OAuthError(`Could not read authorization server metadata for ${resourceMeta.authorizationServers.join(', ')}`);\n}\n\n/** RFC 7591. Returns null when the authorization server does not offer registration. */\nexport async function registerClient(\n registrationEndpoint: string,\n redirectUri: string,\n): Promise<{ clientId: string; clientSecret?: string } | null> {\n try {\n const res = await fetch(registrationEndpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...JSON_HEADERS },\n body: JSON.stringify({\n client_name: 'ant-bot',\n redirect_uris: [redirectUri],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n }),\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n if (!res.ok) return null;\n const b = (await res.json()) as Record<string, unknown>;\n return typeof b.client_id === 'string'\n ? { clientId: b.client_id, clientSecret: typeof b.client_secret === 'string' ? b.client_secret : undefined }\n : null;\n } catch {\n return null;\n }\n}\n\nasync function postForm(endpoint: string, form: Record<string, string>): Promise<unknown> {\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', ...JSON_HEADERS },\n body: new URLSearchParams(form).toString(),\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n const body = await res.json().catch(() => null);\n if (!res.ok) {\n const e = body as Record<string, unknown> | null;\n throw new OAuthError(String(e?.error_description ?? e?.error ?? `token endpoint returned HTTP ${res.status}`));\n }\n return body;\n}\n\nexport async function exchangeCode(input: {\n tokenEndpoint: string;\n code: string;\n verifier: string;\n clientId: string;\n clientSecret?: string;\n redirectUri: string;\n resource?: string;\n now?: number;\n}): Promise<StoredTokens> {\n const body = await postForm(input.tokenEndpoint, {\n grant_type: 'authorization_code',\n code: input.code,\n code_verifier: input.verifier,\n client_id: input.clientId,\n redirect_uri: input.redirectUri,\n ...(input.clientSecret ? { client_secret: input.clientSecret } : {}),\n ...(input.resource ? { resource: input.resource } : {}),\n });\n const tokens = parseTokenResponse(body, input, input.now ?? Date.now());\n if (!tokens) throw new OAuthError('The authorization server did not return an access token.');\n return tokens;\n}\n\nexport async function refreshTokens(tokens: StoredTokens, now = Date.now()): Promise<StoredTokens> {\n if (!tokens.refreshToken) throw new OAuthError('No refresh token \u2014 sign in again.');\n const body = await postForm(tokens.tokenEndpoint, {\n grant_type: 'refresh_token',\n refresh_token: tokens.refreshToken,\n client_id: tokens.clientId,\n ...(tokens.clientSecret ? { client_secret: tokens.clientSecret } : {}),\n ...(tokens.resource ? { resource: tokens.resource } : {}),\n });\n const next = parseTokenResponse(body, { ...tokens, previousRefresh: tokens.refreshToken }, now);\n if (!next) throw new OAuthError('The authorization server did not return a refreshed access token.');\n return next;\n}\n", "// Serves ant-bot's built-in connectors and holds the only thing that can reach their tokens.\n//\n// The agent runtime mounts a built-in connector as an ordinary http MCP server pointing back at\n// the daemon (`/mcp/<name>`). The provider token never travels: the runtime gets a per-boot bearer\n// for the daemon's own endpoint, and the daemon exchanges that for the provider's credential at\n// call time. Restarting the daemon rotates the bearer, so a value that leaked into a transcript\n// or a log is dead by the next boot.\nimport crypto from 'node:crypto';\nimport type { Connector } from '@antbot/contract';\nimport type { MountedConnector } from '../../agent/runtime.js';\nimport type { ConnectorAuthService } from '../auth.js';\nimport { BUILTIN_CATALOG, type BuiltinConnector } from './catalog.js';\nimport { handleMcpRequest, type JsonRpcResponse } from './mcpServer.js';\n\nexport class BuiltinService {\n /** Rotates every boot. Checked on every `/mcp/<name>` request. */\n readonly bearer = crypto.randomBytes(24).toString('base64url');\n\n constructor(\n private readonly auth: ConnectorAuthService | undefined,\n private readonly portOf: () => number,\n private readonly version: string,\n ) {}\n private get port(): number {\n return this.portOf();\n }\n\n get(name: string): BuiltinConnector | undefined {\n return BUILTIN_CATALOG[name];\n }\n\n /** The config a built-in connector's row stores: the daemon's own endpoint, nothing secret. */\n rowConfig(name: string): Connector['config'] {\n return { transport: 'http', url: `http://127.0.0.1:${this.port}/mcp/${name}`, headers: {} };\n }\n\n /** What actually gets mounted: the row's config plus this boot's bearer. */\n mountConfig(connector: Connector): MountedConnector {\n return {\n type: 'http',\n url: `http://127.0.0.1:${this.port}/mcp/${connector.name}`,\n headers: { Authorization: `Bearer ${this.bearer}` },\n };\n }\n\n authorized(name: string): boolean {\n return this.auth?.isAuthorized(name) ?? false;\n }\n\n /**\n * Scopes this connector asks for that the stored sign-in does not carry. Empty when the token\n * covers everything \u2014 including when the provider granted a broader scope that subsumes one\n * asked for, which is why the comparison is by exact string and errs toward \"sign in again\".\n */\n async missingScopes(name: string): Promise<string[]> {\n const def = this.get(name);\n if (!def || !this.auth) return [];\n const granted = await this.auth.grantedScopes(name);\n if (granted === null) return [];\n return def.scopes.filter((s) => !granted.includes(s));\n }\n\n /** Constant-time compare so the bearer cannot be guessed a byte at a time. */\n checkBearer(header: string | undefined): boolean {\n const given = (header ?? '').replace(/^Bearer\\s+/i, '');\n const a = Buffer.from(given);\n const b = Buffer.from(this.bearer);\n return a.length === b.length && crypto.timingSafeEqual(a, b);\n }\n\n /** Serve one MCP request for a built-in connector. */\n async handle(name: string, body: unknown): Promise<JsonRpcResponse | null> {\n const def = this.get(name);\n if (!def) return { jsonrpc: '2.0', id: null, error: { code: -32601, message: `No built-in connector named ${name}` } };\n return handleMcpRequest(body, { name: def.name, version: this.version, tools: def.tools() }, async () => {\n const hdr = await this.auth?.authHeader(name);\n if (!hdr) {\n throw new Error(\n `${def.displayName} is not signed in. Sign in on the Connectors screen or with \\`antbot mcp login ${name}\\`.`,\n );\n }\n return { accessToken: hdr.Authorization.replace(/^Bearer\\s+/, '') };\n });\n }\n\n /** Start the provider sign-in for a built-in connector. Returns the URL to open. */\n async beginLogin(connector: Connector, opts: { clientId?: string; clientSecret?: string } = {}): Promise<string> {\n const def = this.get(connector.name);\n if (!def) throw new Error(`No built-in connector named ${connector.name}`);\n if (!this.auth) throw new Error('Secrets backend unavailable, so a sign-in cannot be stored.');\n const p = def.provider;\n return this.auth.beginLoginWith(\n {\n connectorId: connector.id,\n connectorName: connector.name,\n clientKey: p.key,\n authorizationEndpoint: p.authorizationEndpoint,\n tokenEndpoint: p.tokenEndpoint,\n scopes: def.scopes,\n extras: p.authorizeExtras,\n providerName: p.displayName,\n },\n opts,\n );\n }\n}\n", "// Gmail as an ant-bot built-in connector: six tools, each a thin call to Gmail's REST API.\n//\n// Narrow on purpose. The goal is a bot that can read a mailbox and draft a reply, not a complete\n// Gmail client; every tool here maps to one documented REST call, and `fetch` is injected so the\n// whole file is testable against a fake server.\nimport { z } from 'zod';\nimport { toolError, toolText, type BuiltinTool, type ToolContext, type ToolResult } from './mcpServer.js';\n\nconst API = 'https://gmail.googleapis.com/gmail/v1/users/me';\n\nexport type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;\n\n/** One Gmail REST call with the bearer applied; a non-2xx becomes a readable tool error. */\nasync function gmail(\n fetchFn: FetchLike,\n ctx: ToolContext,\n path: string,\n init: RequestInit = {},\n): Promise<{ ok: true; body: any } | { ok: false; error: string }> {\n const res = await fetchFn(`${API}${path}`, {\n ...init,\n headers: { Authorization: `Bearer ${ctx.accessToken}`, 'content-type': 'application/json', ...(init.headers ?? {}) },\n });\n const text = await res.text();\n let body: any = null;\n try { body = text ? JSON.parse(text) : null; } catch { /* non-JSON error page */ }\n if (!res.ok) {\n const msg = body?.error?.message ?? `HTTP ${res.status}`;\n // 401/403 nearly always mean the sign-in is gone or lacks a scope; say what to do.\n const hint = res.status === 401 || res.status === 403 ? ' \u2014 sign in to the gmail connector again' : '';\n return { ok: false, error: `Gmail: ${msg}${hint}` };\n }\n return { ok: true, body };\n}\n\n/** Pull the readable headers and a plain-text body out of a Gmail message resource. */\nexport function summarizeMessage(m: any): Record<string, unknown> {\n const headers: Record<string, string> = {};\n for (const h of m?.payload?.headers ?? []) {\n const k = String(h.name).toLowerCase();\n if (['from', 'to', 'cc', 'subject', 'date'].includes(k)) headers[k] = String(h.value);\n }\n return {\n id: m?.id,\n threadId: m?.threadId,\n labelIds: m?.labelIds ?? [],\n snippet: m?.snippet ?? '',\n ...headers,\n body: extractText(m?.payload) ?? '',\n };\n}\n\n/** Prefer text/plain; fall back to stripping tags from text/html. Walks multipart recursively. */\nexport function extractText(payload: any): string | null {\n if (!payload) return null;\n const decode = (data: string): string => Buffer.from(data.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8');\n if (payload.mimeType === 'text/plain' && payload.body?.data) return decode(payload.body.data);\n if (Array.isArray(payload.parts)) {\n for (const p of payload.parts) {\n const t = extractText(p);\n if (t) return t;\n }\n }\n if (payload.mimeType === 'text/html' && payload.body?.data) {\n return decode(payload.body.data).replace(/<style[\\s\\S]*?<\\/style>/gi, '').replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ').trim();\n }\n return null;\n}\n\n/** RFC 822 message, base64url-encoded the way the API wants `raw`. */\nexport function buildRawMessage(m: { to: string; subject: string; body: string; cc?: string; inReplyTo?: string }): string {\n const lines = [\n `To: ${m.to}`,\n ...(m.cc ? [`Cc: ${m.cc}`] : []),\n `Subject: ${m.subject}`,\n ...(m.inReplyTo ? [`In-Reply-To: ${m.inReplyTo}`, `References: ${m.inReplyTo}`] : []),\n 'Content-Type: text/plain; charset=utf-8',\n 'MIME-Version: 1.0',\n '',\n m.body,\n ];\n return Buffer.from(lines.join('\\r\\n'), 'utf8').toString('base64url');\n}\n\nconst json = (v: unknown): ToolResult => toolText(JSON.stringify(v, null, 2));\n\nexport function gmailTools(fetchFn: FetchLike = fetch): BuiltinTool<any>[] {\n return [\n {\n name: 'search_threads',\n description:\n 'Search the mailbox with Gmail query syntax (e.g. \"is:unread\", \"from:alice newer_than:7d\"). Returns thread ids with a snippet of the latest message.',\n inputSchema: {\n type: 'object',\n properties: { query: { type: 'string' }, maxResults: { type: 'integer', minimum: 1, maximum: 50 } },\n required: ['query'],\n },\n parse: z.object({ query: z.string().min(1), maxResults: z.number().int().min(1).max(50).default(10) }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, `/threads?q=${encodeURIComponent(a.query)}&maxResults=${a.maxResults}`);\n if (!r.ok) return toolError(r.error);\n return json({ threads: (r.body.threads ?? []).map((t: any) => ({ id: t.id, snippet: t.snippet })), estimate: r.body.resultSizeEstimate });\n },\n },\n {\n name: 'get_thread',\n description: 'Read every message in a thread: from, to, subject, date and a plain-text body.',\n inputSchema: { type: 'object', properties: { threadId: { type: 'string' } }, required: ['threadId'] },\n parse: z.object({ threadId: z.string().min(1) }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, `/threads/${encodeURIComponent(a.threadId)}?format=full`);\n if (!r.ok) return toolError(r.error);\n return json({ id: r.body.id, messages: (r.body.messages ?? []).map(summarizeMessage) });\n },\n },\n {\n name: 'get_message',\n description: 'Read one message by id.',\n inputSchema: { type: 'object', properties: { messageId: { type: 'string' } }, required: ['messageId'] },\n parse: z.object({ messageId: z.string().min(1) }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, `/messages/${encodeURIComponent(a.messageId)}?format=full`);\n if (!r.ok) return toolError(r.error);\n return json(summarizeMessage(r.body));\n },\n },\n {\n name: 'list_labels',\n description: 'List the mailbox labels (INBOX, SENT, user labels\u2026) with their ids.',\n inputSchema: { type: 'object', properties: {} },\n parse: z.object({}),\n handler: async (_a, ctx) => {\n const r = await gmail(fetchFn, ctx, '/labels');\n if (!r.ok) return toolError(r.error);\n return json({ labels: (r.body.labels ?? []).map((l: any) => ({ id: l.id, name: l.name, type: l.type })) });\n },\n },\n {\n name: 'create_draft',\n description: 'Create a draft email. Nothing is sent. Set inReplyTo to a message id to draft a reply in that thread.',\n inputSchema: {\n type: 'object',\n properties: { to: { type: 'string' }, subject: { type: 'string' }, body: { type: 'string' }, cc: { type: 'string' }, inReplyTo: { type: 'string' } },\n required: ['to', 'subject', 'body'],\n },\n parse: z.object({ to: z.string().min(1), subject: z.string(), body: z.string(), cc: z.string().optional(), inReplyTo: z.string().optional() }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, '/drafts', { method: 'POST', body: JSON.stringify({ message: { raw: buildRawMessage(a) } }) });\n if (!r.ok) return toolError(r.error);\n return json({ draftId: r.body.id, messageId: r.body.message?.id });\n },\n },\n {\n name: 'send_message',\n description: 'Send an email immediately. This is consequential and asks the human for approval.',\n inputSchema: {\n type: 'object',\n properties: { to: { type: 'string' }, subject: { type: 'string' }, body: { type: 'string' }, cc: { type: 'string' }, inReplyTo: { type: 'string' } },\n required: ['to', 'subject', 'body'],\n },\n parse: z.object({ to: z.string().min(1), subject: z.string(), body: z.string(), cc: z.string().optional(), inReplyTo: z.string().optional() }),\n handler: async (a, ctx) => {\n const r = await gmail(fetchFn, ctx, '/messages/send', { method: 'POST', body: JSON.stringify({ raw: buildRawMessage(a) }) });\n if (!r.ok) return toolError(r.error);\n return json({ sent: true, messageId: r.body.id, threadId: r.body.threadId });\n },\n },\n ];\n}\n", "// A minimal MCP server, served by the daemon itself over streamable HTTP.\n//\n// This exists because some providers refuse every MCP client except their own allowlisted ones,\n// which makes a self-contained ant-bot unable to use their MCP endpoint no matter how it signs in.\n// The provider's plain REST API has no such rule. So ant-bot serves the connector: an MCP server\n// whose tools are thin calls to that REST API, with the token held by the daemon and never handed\n// to the agent runtime.\n//\n// Pure: `handleMcpRequest` maps one JSON-RPC request to one response with no I/O of its own. Tool\n// handlers do the I/O, and they are injected. That is what makes the protocol layer testable\n// against ant-bot's own probe client without a network.\nimport type { ZodType } from 'zod';\n\n/** The MCP protocol revision this server speaks. Newer clients negotiate down; older ones match. */\nexport const MCP_PROTOCOL_VERSION = '2025-06-18';\n\nexport interface ToolContext {\n /** A bearer for the provider's API, refreshed by the daemon before the call. */\n accessToken: string;\n}\n\nexport interface BuiltinTool<A = unknown> {\n name: string;\n description: string;\n /** JSON Schema, as the client expects it. */\n inputSchema: Record<string, unknown>;\n /** Validates and types the arguments before the handler sees them. */\n parse: ZodType<A>;\n handler: (args: A, ctx: ToolContext) => Promise<ToolResult>;\n}\n\nexport interface ToolResult {\n content: { type: 'text'; text: string }[];\n isError?: boolean;\n}\n\ninterface JsonRpcRequest {\n jsonrpc?: string;\n id?: string | number | null;\n method?: string;\n params?: Record<string, unknown>;\n}\n\nexport interface JsonRpcResponse {\n jsonrpc: '2.0';\n id: string | number | null;\n result?: unknown;\n error?: { code: number; message: string };\n}\n\n/** JSON-RPC 2.0 error codes the server uses. */\nexport const RPC = {\n PARSE_ERROR: -32700,\n INVALID_REQUEST: -32600,\n METHOD_NOT_FOUND: -32601,\n INVALID_PARAMS: -32602,\n} as const;\n\nconst err = (id: string | number | null, code: number, message: string): JsonRpcResponse =>\n ({ jsonrpc: '2.0', id, error: { code, message } });\nconst ok = (id: string | number | null, result: unknown): JsonRpcResponse => ({ jsonrpc: '2.0', id, result });\n\n/** Text a tool returns when the provider call itself fails; never the raw response body. */\nexport const toolError = (text: string): ToolResult => ({ content: [{ type: 'text', text }], isError: true });\nexport const toolText = (text: string): ToolResult => ({ content: [{ type: 'text', text }] });\n\n/**\n * Handle one request. Returns null for a notification (no id), which the HTTP layer answers with\n * 202 and no body, as the transport requires.\n */\nexport async function handleMcpRequest(\n body: unknown,\n server: { name: string; version: string; tools: BuiltinTool[] },\n ctx: () => Promise<ToolContext>,\n): Promise<JsonRpcResponse | null> {\n const req = body as JsonRpcRequest | null;\n if (!req || typeof req !== 'object' || req.jsonrpc !== '2.0' || typeof req.method !== 'string') {\n return err(null, RPC.INVALID_REQUEST, 'Expected a JSON-RPC 2.0 request');\n }\n const id = req.id ?? null;\n // Notifications carry no id and get no reply.\n if (req.id === undefined) return null;\n\n switch (req.method) {\n case 'initialize': {\n const asked = String(req.params?.protocolVersion ?? MCP_PROTOCOL_VERSION);\n return ok(id, {\n // Echo the client's version when it is one we can serve; the surface is small enough that\n // every revision since 2024-11-05 is compatible for these three methods.\n protocolVersion: asked,\n capabilities: { tools: {} },\n serverInfo: { name: server.name, version: server.version },\n });\n }\n case 'ping':\n return ok(id, {});\n case 'tools/list':\n return ok(id, {\n tools: server.tools.map((t) => ({ name: t.name, description: t.description, inputSchema: t.inputSchema })),\n });\n case 'tools/call': {\n const name = String(req.params?.name ?? '');\n const tool = server.tools.find((t) => t.name === name);\n if (!tool) return err(id, RPC.INVALID_PARAMS, `Unknown tool: ${name}`);\n const parsed = tool.parse.safeParse(req.params?.arguments ?? {});\n if (!parsed.success) {\n return err(id, RPC.INVALID_PARAMS, `Invalid arguments for ${name}: ${parsed.error.issues[0]?.message ?? 'invalid'}`);\n }\n let context: ToolContext;\n try {\n context = await ctx();\n } catch (e) {\n // Not signed in, or the token could not be refreshed. A tool error rather than an RPC\n // error, so the model reads a sentence instead of a code.\n return ok(id, toolError((e as Error).message));\n }\n try {\n return ok(id, await tool.handler(parsed.data, context));\n } catch (e) {\n return ok(id, toolError(`${name} failed: ${(e as Error).message}`));\n }\n }\n default:\n return err(id, RPC.METHOD_NOT_FOUND, `Method not supported: ${req.method}`);\n }\n}\n", "// The connectors ant-bot ships. `antbot mcp add gmail` with no command or URL resolves here.\n//\n// Each entry carries everything the guided setup needs to say, so the instructions live next to\n// the code that depends on them rather than in prose that drifts. Google's endpoints are fixed\n// and documented; hard-coding them removes a network round trip from a flow that already has\n// enough of them, and means the sign-in works even when discovery would not.\nimport { gmailTools, type FetchLike } from './gmail.js';\nimport type { BuiltinTool } from './mcpServer.js';\n\nexport interface Provider {\n /** Shared client-credential key: one Google client serves Gmail, Calendar and Drive. */\n key: string;\n displayName: string;\n authorizationEndpoint: string;\n tokenEndpoint: string;\n /** Provider-specific authorize params. Google needs these to issue a refresh token at all. */\n authorizeExtras: Record<string, string>;\n /** Whether the provider lets an app register itself. Google does not. */\n dynamicRegistration: boolean;\n /** Numbered steps shown when a client ID is needed. `{redirectUri}` is substituted. */\n setupSteps: string[];\n}\n\nexport const GOOGLE: Provider = {\n key: 'google',\n displayName: 'Google',\n authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenEndpoint: 'https://oauth2.googleapis.com/token',\n authorizeExtras: { access_type: 'offline', prompt: 'consent' },\n dynamicRegistration: false,\n setupSteps: [\n 'Open console.cloud.google.com \u2192 APIs & Services \u2192 Credentials \u2192 Create credentials \u2192 OAuth client ID.',\n 'Application type: Web application. Under \"Authorised redirect URIs\" add exactly: {redirectUri}',\n 'Enable the Gmail API for the project (APIs & Services \u2192 Library).',\n 'Copy the Client ID and Client secret it shows you. One client works for every Google connector.',\n ],\n};\n\nexport interface BuiltinConnector {\n name: string;\n displayName: string;\n description: string;\n provider: Provider;\n scopes: string[];\n tools: (fetchFn?: FetchLike) => BuiltinTool[];\n}\n\nexport const BUILTIN_CATALOG: Record<string, BuiltinConnector> = {\n gmail: {\n name: 'gmail',\n displayName: 'Gmail',\n description: 'Read, search and draft email in the signed-in Gmail account.',\n provider: GOOGLE,\n // The full mailbox, plus settings. `mail.google.com` subsumes read/compose/send/modify and\n // adds permanent deletion; the two settings scopes are separate and cover filters, forwarding\n // and vacation. Listing narrower scopes as well would only lengthen the consent screen.\n //\n // Breadth here is not what keeps a bot in check \u2014 `mcp__gmail__send_message` and\n // `mcp__gmail__create_draft` carry seeded `require` rules, so a human is asked every time\n // whatever the token allows.\n scopes: [\n 'https://mail.google.com/',\n 'https://www.googleapis.com/auth/gmail.settings.basic',\n 'https://www.googleapis.com/auth/gmail.settings.sharing',\n ],\n tools: gmailTools,\n },\n};\n\nexport const isBuiltinName = (name: string): boolean => name in BUILTIN_CATALOG;\n\n/**\n * The built-in to use instead, when a custom connector signs in at a provider whose own MCP\n * endpoint refuses third-party clients. Matched on the authorization host: a Google sign-in is\n * a Google sign-in whatever URL sits behind it.\n */\nexport function builtinAlternativeFor(authorizationHost: string): string | undefined {\n for (const [name, def] of Object.entries(BUILTIN_CATALOG)) {\n if (new URL(def.provider.authorizationEndpoint).host === authorizationHost && !def.provider.dynamicRegistration) return name;\n }\n return undefined;\n}\n", "// A minimal MCP client, used only to answer \"does this connector work, and what does it offer?\"\n//\n// Advisory, never in the turn path: the Agent SDK does the real mounting. That is what makes a\n// hand-rolled client acceptable here rather than a liability \u2014 if the protocol drifts, `antbot\n// connector test` gets less useful, and nothing a bot depends on breaks. The alternative,\n// depending on @modelcontextprotocol/sdk purely for a diagnostic, is a lot of surface for that.\n//\n// Everything is best-effort and bounded: any failure becomes `{ ok: false, error }`, and the\n// child is always killed.\nimport { spawn } from 'node:child_process';\nimport { logger } from '../util/log.js';\n\nconst log = logger('mcp-probe');\n\n/** The version we ask for; a server that prefers another one is free to say so and we accept it. */\nconst PROTOCOL_VERSION = '2025-06-18';\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport interface ProbeTool {\n name: string;\n description: string;\n}\n\nexport interface ProbeResult {\n ok: boolean;\n tools: ProbeTool[];\n error?: string;\n}\n\n/** Tool descriptions can be enormous; a diagnostic listing does not need all of it. */\nconst MAX_DESCRIPTION = 200;\n\n/** Pull the tool list out of a `tools/list` result, tolerating a server that omits fields. */\nexport function parseToolsResult(result: unknown): ProbeTool[] {\n const tools = (result as { tools?: unknown })?.tools;\n if (!Array.isArray(tools)) return [];\n return tools\n .filter((t): t is Record<string, unknown> => typeof t === 'object' && t !== null)\n .map((t) => ({\n name: String(t.name ?? ''),\n description: String(t.description ?? '').slice(0, MAX_DESCRIPTION),\n }))\n .filter((t) => t.name.length > 0);\n}\n\nconst rpc = (id: number, method: string, params?: unknown): string =>\n `${JSON.stringify({ jsonrpc: '2.0', id, method, ...(params ? { params } : {}) })}\\n`;\n\nconst notify = (method: string): string => `${JSON.stringify({ jsonrpc: '2.0', method })}\\n`;\n\nconst failed = (error: string): ProbeResult => ({ ok: false, tools: [], error });\n\n/** stdio: spawn the server and speak newline-delimited JSON-RPC on its pipes. */\nasync function probeStdio(\n cfg: { command: string; args?: string[]; env?: Record<string, string> },\n timeoutMs: number,\n): Promise<ProbeResult> {\n return new Promise<ProbeResult>((resolve) => {\n let child: ReturnType<typeof spawn>;\n try {\n child = spawn(cfg.command, cfg.args ?? [], {\n // The server's own env plus the connector's \u2014 a connector that needs PATH still gets it.\n env: { ...process.env, ...(cfg.env ?? {}) },\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n } catch (err) {\n return resolve(failed((err as Error).message));\n }\n\n let settled = false;\n let stderr = '';\n let buffer = '';\n const finish = (r: ProbeResult): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n // Always kill: a server that never answers must not outlive the probe.\n try { child.kill('SIGKILL'); } catch { /* already gone */ }\n resolve(r);\n };\n\n const timer = setTimeout(\n () => finish(failed(`timed out after ${timeoutMs}ms${stderr ? `: ${stderr.trim().slice(0, 200)}` : ''}`)),\n timeoutMs,\n );\n\n child.on('error', (err) => finish(failed(err.message)));\n child.on('exit', (code) =>\n finish(failed(`server exited with code ${code}${stderr ? `: ${stderr.trim().slice(0, 200)}` : ''}`)),\n );\n child.stderr?.on('data', (d: Buffer) => { stderr += d.toString(); });\n\n child.stdout?.on('data', (d: Buffer) => {\n buffer += d.toString();\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.trim()) continue;\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(line) as Record<string, unknown>;\n } catch {\n continue; // servers do print the occasional stray line on stdout\n }\n if (msg.id === 1) {\n // Initialized; ask for the tools.\n try {\n child.stdin?.write(notify('notifications/initialized'));\n child.stdin?.write(rpc(2, 'tools/list'));\n } catch (err) {\n finish(failed((err as Error).message));\n }\n } else if (msg.id === 2) {\n if (msg.error) return finish(failed(JSON.stringify(msg.error).slice(0, 200)));\n finish({ ok: true, tools: parseToolsResult(msg.result) });\n }\n }\n });\n\n try {\n child.stdin?.write(\n rpc(1, 'initialize', {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: 'ant-bot', version: '1.0.0' },\n }),\n );\n } catch (err) {\n finish(failed((err as Error).message));\n }\n });\n}\n\n/** Streamable HTTP: POST the same handshake, carrying the session id the server hands back. */\nasync function probeHttp(\n cfg: { url: string; headers?: Record<string, string> },\n timeoutMs: number,\n): Promise<ProbeResult> {\n const ac = new AbortController();\n const timer = setTimeout(() => ac.abort(), timeoutMs);\n const base = {\n 'content-type': 'application/json',\n accept: 'application/json, text/event-stream',\n ...(cfg.headers ?? {}),\n };\n\n // A streamable-HTTP server may answer with an SSE frame even for a single call.\n const readBody = async (res: Response): Promise<unknown> => {\n const text = await res.text();\n const line = text.split('\\n').find((l) => l.startsWith('data:'));\n try {\n return JSON.parse(line ? line.slice(5).trim() : text);\n } catch {\n return null;\n }\n };\n\n try {\n const initRes = await fetch(cfg.url, {\n method: 'POST', signal: ac.signal, headers: base,\n body: rpc(1, 'initialize', {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: 'ant-bot', version: '1.0.0' },\n }),\n });\n if (!initRes.ok) return failed(`initialize returned HTTP ${initRes.status}`);\n const session = initRes.headers.get('mcp-session-id');\n const withSession = session ? { ...base, 'mcp-session-id': session } : base;\n await readBody(initRes);\n\n await fetch(cfg.url, { method: 'POST', signal: ac.signal, headers: withSession, body: notify('notifications/initialized') })\n .catch(() => undefined); // some servers 202 or close this; not fatal\n\n const listRes = await fetch(cfg.url, {\n method: 'POST', signal: ac.signal, headers: withSession, body: rpc(2, 'tools/list'),\n });\n if (!listRes.ok) return failed(`tools/list returned HTTP ${listRes.status}`);\n const body = await readBody(listRes) as { result?: unknown; error?: unknown } | null;\n if (body?.error) return failed(JSON.stringify(body.error).slice(0, 200));\n return { ok: true, tools: parseToolsResult(body?.result) };\n } catch (err) {\n const e = err as Error;\n return failed(e.name === 'AbortError' ? `timed out after ${timeoutMs}ms` : e.message);\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Connect to a connector's server and list its tools.\n *\n * Takes the already-substituted SDK config, so a caller must resolve secrets first \u2014 the probe\n * has no access to the keychain and no business holding one.\n */\nexport async function probeConnector(\n config: Record<string, unknown>,\n opts: { timeoutMs?: number } = {},\n): Promise<ProbeResult> {\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const type = config.type as string | undefined;\n try {\n if (type === 'stdio') {\n return await probeStdio(config as { command: string; args?: string[]; env?: Record<string, string> }, timeoutMs);\n }\n if (type === 'http') {\n // Reachable is all this says. Whether a call would be *allowed* is `check.ts`'s question,\n // answered by a tools/call challenge \u2014 many servers list their tools to anyone.\n return await probeHttp(config as { url: string; headers?: Record<string, string> }, timeoutMs);\n }\n // SSE needs a persistent event stream and a separate POST endpoint the server advertises at\n // runtime \u2014 more client than a diagnostic justifies. Assign it and run a turn instead.\n if (type === 'sse') return failed('testing is not supported for sse connectors \u2014 assign it to a bot and run a turn');\n return failed(`unknown transport: ${String(type)}`);\n } catch (err) {\n log.warn('probe threw', err);\n return failed((err as Error).message);\n }\n}\n", "// One honest verdict on a connector, replacing `test` and the guesswork around it.\n//\n// `tools/list` is the wrong question: servers answer it to anyone and refuse the first real\n// call, which is how a connector looked healthy while giving a bot nothing. The auth verdict here\n// comes from a deliberately failing `tools/call` \u2014 what `discoverAuth` already does \u2014 and the\n// tool list is attached only once the server has been reached. Pure decision at the top, thin\n// I/O below, so every verdict is testable without a network.\nimport type { Connector, ConnectorCheck } from '@antbot/contract';\nimport { builtinAlternativeFor } from './builtin/catalog.js';\nimport { discoverAuth, OAuthError, type DiscoveryResult } from './oauth.js';\nimport { probeConnector, type ProbeResult } from '../bots/mcpProbe.js';\nimport type { MountedConnector } from '../agent/runtime.js';\n\nexport interface CheckSignals {\n /** The probe result, when the server was reachable enough to run it. */\n probe: ProbeResult | null;\n /** What a real call provoked: nothing, or an auth challenge (with discovery), or a hard failure. */\n challenge: 'none' | 'auth' | 'unreachable';\n discovery?: DiscoveryResult | null;\n /** For built-ins: whether the daemon holds a sign-in already. */\n builtinSignedIn?: boolean;\n /** Scopes the connector asks for that the stored sign-in does not carry. */\n builtinMissingScopes?: string[];\n builtinProvider?: { name: string; dynamicRegistration: boolean };\n /** Missing `{{secret:\u2026}}` references, if any. */\n missingSecrets: string[];\n}\n\n/** Pure: signals in, verdict out. */\nexport function decideCheck(signals: CheckSignals): ConnectorCheck {\n if (signals.builtinProvider) {\n // Signed in, but with a token minted before the connector asked for these. It will keep\n // failing on whatever needs them, while every other signal says healthy.\n if (signals.builtinSignedIn && signals.builtinMissingScopes?.length) {\n return {\n status: 'needs-sign-in',\n selfRegistration: signals.builtinProvider.dynamicRegistration,\n provider: signals.builtinProvider.name,\n tools: signals.probe?.tools ?? [],\n detail: `signed in, but without ${signals.builtinMissingScopes.length} newer permission(s) \u2014 sign in again to grant them`,\n };\n }\n return signals.builtinSignedIn\n ? { status: 'ready', tools: signals.probe?.tools ?? [], provider: signals.builtinProvider.name }\n : {\n status: 'needs-sign-in',\n selfRegistration: signals.builtinProvider.dynamicRegistration,\n provider: signals.builtinProvider.name,\n tools: signals.probe?.tools ?? [],\n };\n }\n if (signals.missingSecrets.length) {\n return { status: 'needs-credential', tools: [], detail: `missing secret(s): ${signals.missingSecrets.join(', ')}` };\n }\n if (signals.challenge === 'auth') {\n const as = signals.discovery?.authServer;\n const host = as ? new URL(as.authorizationEndpoint).host : undefined;\n // Google's own MCP endpoint admits only clients Google allowlisted: the sign-in succeeds and\n // every call is then refused with \"The caller does not have permission\". Saying so here is\n // the difference between a dead end and the one command that works.\n const alternative = host ? builtinAlternativeFor(host) : undefined;\n return {\n status: 'needs-sign-in',\n selfRegistration: Boolean(as?.registrationEndpoint),\n provider: host,\n tools: signals.probe?.tools ?? [],\n ...(alternative\n ? {\n alternative,\n detail: `${host} does not accept third-party MCP clients here, so a sign-in would not help. Use the built-in instead: antbot mcp add ${alternative}`,\n }\n : {}),\n };\n }\n if (signals.challenge === 'unreachable' || (signals.probe && !signals.probe.ok)) {\n return { status: 'unreachable', tools: [], detail: signals.probe?.error };\n }\n return { status: 'ready', tools: signals.probe?.tools ?? [] };\n}\n\n/**\n * Gather the signals for a custom connector. `mounted` is the already-substituted config (so a\n * static header credential is exercised), which the caller builds \u2014 this module never touches the\n * keychain.\n */\nexport async function gatherCustomSignals(\n connector: Connector,\n mounted: MountedConnector | null,\n missingSecrets: string[],\n): Promise<CheckSignals> {\n if (missingSecrets.length || !mounted) return { probe: null, challenge: 'none', missingSecrets };\n const probe = await probeConnector(mounted as unknown as Record<string, unknown>, { timeoutMs: 8000 });\n if (mounted.type === 'stdio') return { probe, challenge: probe.ok ? 'none' : 'unreachable', missingSecrets };\n if (!probe.ok) return { probe, challenge: 'unreachable', missingSecrets };\n // Reachable. Now the question that matters: does it accept us? A real call, with whatever\n // headers the config carries, either passes or provokes the 401 discovery starts from.\n try {\n const discovery = await discoverAuth(mounted.url, mounted.headers);\n return { probe, challenge: 'auth', discovery, missingSecrets };\n } catch (err) {\n // discoverAuth throws when the server did NOT challenge (no 401 to follow) \u2014 that is success \u2014\n // or when it challenged but named no authorization server, which is still \"needs sign-in\".\n const msg = (err as Error).message;\n if (err instanceof OAuthError && /did not advertise an authorization server/.test(msg)) {\n return { probe, challenge: 'auth', discovery: null, missingSecrets };\n }\n return { probe, challenge: 'none', missingSecrets };\n }\n}\n", "import fs from 'node:fs';\nimport { parse as parseToml, stringify as stringifyToml } from 'smol-toml';\nimport { SettingsSchema, type Settings } from '@antbot/contract';\nimport { resolvePaths, ensureDirs, type AntbotPaths } from './paths.js';\n\nexport interface AntbotConfig {\n paths: AntbotPaths;\n settings: Settings;\n port: number;\n host: string;\n}\n\nexport const DEFAULT_PORT = 4780;\nexport const DEFAULT_HOST = '127.0.0.1';\n\nexport function loadConfig(root?: string): AntbotConfig {\n const paths = resolvePaths(root);\n ensureDirs(paths);\n\n let raw: Record<string, unknown> = {};\n if (fs.existsSync(paths.config)) {\n try {\n raw = parseToml(fs.readFileSync(paths.config, 'utf8')) as Record<string, unknown>;\n } catch {\n raw = {};\n }\n }\n const server = (raw.server ?? {}) as Record<string, unknown>;\n const settings = SettingsSchema.parse({\n ...(typeof raw.settings === 'object' && raw.settings ? raw.settings : {}),\n timezone:\n (raw.settings as Record<string, unknown> | undefined)?.timezone ??\n Intl.DateTimeFormat().resolvedOptions().timeZone ??\n 'UTC',\n });\n\n const cfg: AntbotConfig = {\n paths,\n settings,\n port: Number(process.env.ANTBOT_PORT ?? server.port ?? DEFAULT_PORT),\n host: String(server.host ?? DEFAULT_HOST),\n };\n if (!fs.existsSync(paths.config)) writeConfig(cfg);\n return cfg;\n}\n\nexport function writeConfig(cfg: AntbotConfig): void {\n fs.writeFileSync(\n cfg.paths.config,\n stringifyToml({ server: { port: cfg.port, host: cfg.host }, settings: cfg.settings as unknown as Record<string, unknown> }),\n );\n}\n", "import os from 'node:os';\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nexport interface AntbotPaths {\n root: string;\n db: string;\n config: string;\n workspace: string;\n attachments: string;\n skills: string;\n browserProfile: string;\n backups: string;\n secrets: string;\n logs: string;\n}\n\nexport function resolvePaths(root?: string): AntbotPaths {\n const base = root ?? process.env.ANTBOT_HOME ?? path.join(os.homedir(), '.ant-bot');\n return {\n root: base,\n db: path.join(base, 'antbot.db'),\n config: path.join(base, 'config.toml'),\n workspace: path.join(base, 'workspace'),\n attachments: path.join(base, 'attachments'),\n skills: path.join(base, 'skills'),\n browserProfile: path.join(base, 'browser-profile'),\n backups: path.join(base, 'backups'),\n secrets: path.join(base, 'secrets.json'),\n logs: path.join(base, 'logs'),\n };\n}\n\nexport function ensureDirs(p: AntbotPaths): void {\n for (const d of [p.root, p.workspace, p.attachments, p.skills, p.backups, p.logs,\n path.join(p.workspace, 'projects'), path.join(p.workspace, 'bots')]) {\n fs.mkdirSync(d, { recursive: true });\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { logger } from '../util/log.js';\n\nconst exec = promisify(execFile);\nconst log = logger('secrets');\n\nexport interface SecretBackend {\n readonly name: string;\n set(key: string, value: string): Promise<void>;\n get(key: string): Promise<string | null>;\n delete(key: string): Promise<void>;\n list(): Promise<string[]>;\n}\n\nconst SERVICE = 'ant-bot';\n\n/** libsecret on Linux via `secret-tool`. */\nclass SecretToolBackend implements SecretBackend {\n readonly name = 'libsecret (secret-tool)';\n async set(key: string, value: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const p = execFile('secret-tool', ['store', '--label', `${SERVICE}: ${key}`, 'service', SERVICE, 'account', key],\n (err) => (err ? reject(err) : resolve()));\n p.stdin?.end(value);\n });\n }\n async get(key: string): Promise<string | null> {\n try {\n const { stdout } = await exec('secret-tool', ['lookup', 'service', SERVICE, 'account', key]);\n return stdout;\n } catch {\n return null;\n }\n }\n async delete(key: string): Promise<void> {\n try { await exec('secret-tool', ['clear', 'service', SERVICE, 'account', key]); } catch { /* absent */ }\n }\n async list(): Promise<string[]> { return []; } // secret-tool has no reliable enumeration\n}\n\n/** macOS Keychain via `security`. */\nclass MacKeychainBackend implements SecretBackend {\n readonly name = 'macOS Keychain';\n async set(key: string, value: string): Promise<void> {\n await exec('security', ['add-generic-password', '-U', '-s', SERVICE, '-a', key, '-w', value]);\n }\n async get(key: string): Promise<string | null> {\n try {\n const { stdout } = await exec('security', ['find-generic-password', '-s', SERVICE, '-a', key, '-w']);\n return stdout.replace(/\\n$/, '');\n } catch {\n return null;\n }\n }\n async delete(key: string): Promise<void> {\n try { await exec('security', ['delete-generic-password', '-s', SERVICE, '-a', key]); } catch { /* absent */ }\n }\n async list(): Promise<string[]> { return []; }\n}\n\n/**\n * Encrypted-file fallback. Explicitly weaker than an OS keychain: the key is derived\n * from a machine-local file with 0600 permissions, so anything running as this user\n * can read it. Surfaced in the UI as such.\n */\nexport class EncryptedFileBackend implements SecretBackend {\n readonly name = 'encrypted file (weaker than a system keychain)';\n private keyFile: string;\n constructor(private file: string) {\n this.keyFile = `${file}.key`;\n }\n private key(): Buffer {\n if (!fs.existsSync(this.keyFile)) {\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\n fs.writeFileSync(this.keyFile, crypto.randomBytes(32), { mode: 0o600 });\n }\n return fs.readFileSync(this.keyFile);\n }\n private read(): Record<string, string> {\n if (!fs.existsSync(this.file)) return {};\n try {\n const raw = JSON.parse(fs.readFileSync(this.file, 'utf8')) as Record<string, { iv: string; tag: string; data: string }>;\n const key = this.key();\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(raw)) {\n const d = crypto.createDecipheriv('aes-256-gcm', key, Buffer.from(v.iv, 'base64'));\n d.setAuthTag(Buffer.from(v.tag, 'base64'));\n out[k] = Buffer.concat([d.update(Buffer.from(v.data, 'base64')), d.final()]).toString('utf8');\n }\n return out;\n } catch {\n return {};\n }\n }\n private write(values: Record<string, string>): void {\n const key = this.key();\n const out: Record<string, { iv: string; tag: string; data: string }> = {};\n for (const [k, v] of Object.entries(values)) {\n const iv = crypto.randomBytes(12);\n const c = crypto.createCipheriv('aes-256-gcm', key, iv);\n const data = Buffer.concat([c.update(v, 'utf8'), c.final()]);\n out[k] = { iv: iv.toString('base64'), tag: c.getAuthTag().toString('base64'), data: data.toString('base64') };\n }\n fs.mkdirSync(path.dirname(this.file), { recursive: true });\n fs.writeFileSync(this.file, JSON.stringify(out), { mode: 0o600 });\n }\n async set(key: string, value: string): Promise<void> { const v = this.read(); v[key] = value; this.write(v); }\n async get(key: string): Promise<string | null> { return this.read()[key] ?? null; }\n async delete(key: string): Promise<void> { const v = this.read(); delete v[key]; this.write(v); }\n async list(): Promise<string[]> { return Object.keys(this.read()); }\n}\n\nexport async function pickBackend(fallbackFile: string): Promise<SecretBackend> {\n const has = async (bin: string, args: string[]): Promise<boolean> => {\n try { await exec(bin, args); return true; } catch (err) {\n return (err as { code?: string }).code !== 'ENOENT';\n }\n };\n if (process.platform === 'darwin' && (await has('security', ['-h']))) return new MacKeychainBackend();\n if (process.platform === 'linux' && (await has('secret-tool', ['--version']))) return new SecretToolBackend();\n log.warn('no system keychain available; using the encrypted-file fallback');\n return new EncryptedFileBackend(fallbackFile);\n}\n\n/**\n * Secrets are stored by NAME only in the index; values live in the backend and are\n * injected into tool environments. A value is never written to the transcript and is\n * never placed in the model's context (outline \u00A75, \"secure secret request\").\n */\nexport class SecretsService {\n private names = new Set<string>();\n constructor(\n private backend: SecretBackend,\n private indexFile: string,\n ) {\n if (fs.existsSync(indexFile)) {\n try { this.names = new Set(JSON.parse(fs.readFileSync(indexFile, 'utf8')) as string[]); } catch { /* ignore */ }\n }\n }\n private persist(): void {\n fs.mkdirSync(path.dirname(this.indexFile), { recursive: true });\n fs.writeFileSync(this.indexFile, JSON.stringify([...this.names]), { mode: 0o600 });\n }\n get backendName(): string { return this.backend.name; }\n async set(name: string, value: string): Promise<void> {\n await this.backend.set(name, value);\n this.names.add(name);\n this.persist();\n }\n async remove(name: string): Promise<void> {\n await this.backend.delete(name);\n this.names.delete(name);\n this.persist();\n }\n /** Names only \u2014 values are never returned to the API surface. */\n list(): string[] { return [...this.names]; }\n /**\n * Look up exactly the named secrets, for mounting a connector.\n *\n * Scoped on purpose. The unscoped `envOverlay()` below hands every stored secret to whatever\n * asks; a connector should only ever see the ones its own config references, so that adding a\n * third-party MCP server does not widen the blast radius of every other credential.\n *\n * A name with nothing behind it maps to null rather than being dropped, so the caller can tell\n * \"missing\" from \"empty string\" and skip the connector instead of mounting it half-configured.\n */\n async resolve(names: string[]): Promise<Map<string, string | null>> {\n const out = new Map<string, string | null>();\n for (const n of new Set(names)) {\n out.set(n, this.names.has(n) ? await this.backend.get(n) : null);\n }\n return out;\n }\n\n /**\n * Build an env overlay for a tool subprocess. Values never touch the transcript.\n *\n * Unused, and unscoped \u2014 it returns every secret at once. `resolve()` above is what connectors\n * use. Kept only because removing it is a separate decision; do not reach for it.\n */\n async envOverlay(): Promise<Record<string, string>> {\n const out: Record<string, string> = {};\n for (const n of this.names) {\n const v = await this.backend.get(n);\n if (v !== null) out[n] = v;\n }\n return out;\n }\n}\n", "import { query } from '@anthropic-ai/claude-agent-sdk';\nimport { buildEnv } from '../agent/session.js';\nimport type { Settings, Bot } from '@antbot/contract';\nimport { logger } from '../util/log.js';\n\nconst log = logger('groups');\n\n/**\n * Pick which bots should answer a group message.\n * Explicit @-mentions always win; otherwise a cheap Haiku pass routes it.\n * Falls back to the first member so a group is never silent.\n */\nexport async function routeGroupMessage(args: {\n text: string;\n members: Bot[];\n mentionBotIds?: string[];\n mentionEveryone?: boolean;\n settings: Settings;\n cwd: string;\n}): Promise<Bot[]> {\n const { text, members, mentionBotIds, mentionEveryone, settings, cwd } = args;\n if (mentionEveryone) return members;\n if (mentionBotIds?.length) {\n const picked = members.filter((m) => mentionBotIds.includes(m.id));\n if (picked.length) return picked;\n }\n\n const inline = members.filter((m) => new RegExp(`@${m.slug}\\\\b`, 'i').test(text));\n if (inline.length) return inline;\n\n try {\n const roster = members.map((m) => `- ${m.slug}: ${m.name}${m.title ? `, ${m.title}` : ''}. ${m.description.slice(0, 200)}`).join('\\n');\n const q = query({\n prompt: `Team:\\n${roster}\\n\\nMessage:\\n${text.slice(0, 2000)}\\n\\nWhich single teammate should own this? Reply with only the slug.`,\n options: {\n model: 'haiku',\n systemPrompt: 'You route work to the right teammate. Reply with exactly one slug from the list and nothing else.',\n cwd, settingSources: [], env: buildEnv(settings), maxTurns: 1, allowedTools: [],\n },\n });\n let out = '';\n for await (const m of q) {\n const msg = m as Record<string, any>;\n if (msg.type === 'result' && typeof msg.result === 'string') out = msg.result;\n }\n const slug = out.trim().toLowerCase().replace(/[^a-z0-9-]/g, '');\n const found = members.find((m) => m.slug === slug);\n if (found) return [found];\n } catch (err) {\n log.warn('group router failed; defaulting to first member', err);\n }\n return members.slice(0, 1);\n}\n\n/** Extract @slug mentions from raw composer text. */\nexport function parseMentions(text: string, members: Bot[]): { botIds: string[]; everyone: boolean } {\n const everyone = /@everyone\\b/i.test(text);\n const botIds = members.filter((m) => new RegExp(`@${m.slug}\\\\b`, 'i').test(text)).map((m) => m.id);\n return { botIds, everyone };\n}\n", "import type { FastifyInstance } from 'fastify';\nimport type { App } from '../app.js';\nimport {\n CreateBotRequest, UpdateBotRequest, CreateThreadRequest, PostMessageRequest,\n LimitError, type RosterEntry, type ThreadWithMessages,\n} from '@antbot/contract';\nimport { routeGroupMessage, parseMentions } from '../bots/groups.js';\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { readPackageVersion } from '../util/locate.js';\nimport { readMemory, writeMemory, deleteMemory } from '../memory/memory.js';\n\n// Read from package.json rather than hardcoded, so a release bump cannot leave /api/health\n// claiming a version the CLI disagrees with.\nexport const SERVER_VERSION = readPackageVersion(\n path.dirname(fileURLToPath(import.meta.url)),\n (p) => fs.existsSync(p),\n (p) => fs.readFileSync(p, 'utf8'),\n);\n\nexport function registerCoreRoutes(f: FastifyInstance, app: App): void {\n const { store, bus, manager } = app;\n\n f.get('/api/health', async () => ({\n ok: true,\n seq: bus.currentSeq,\n version: SERVER_VERSION,\n bots: store.listBots().length,\n }));\n\n /* ------------------------------- bots ------------------------------- */\n f.get('/api/bots', async (): Promise<RosterEntry[]> =>\n store.listBots().map((bot) => ({\n bot,\n thread: bot.threadId ? store.getThread(bot.threadId) : null,\n lastMessageAt: bot.threadId ? store.lastMessageAt(bot.threadId) : 0,\n })),\n );\n\n f.post('/api/bots', async (req, reply) => {\n const parsed = CreateBotRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: parsed.error.issues[0]?.message ?? 'Invalid body' });\n try {\n return store.createBot(parsed.data);\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.get<{ Params: { id: string } }>('/api/bots/:id', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n return bot ?? reply.code(404).send({ error: 'No such bot' });\n });\n\n f.patch<{ Params: { id: string } }>('/api/bots/:id', async (req, reply) => {\n const parsed = UpdateBotRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n const bot = store.updateBot(req.params.id, parsed.data);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n bus.publish({ type: 'bot.state', botId: bot.id, threadId: bot.threadId, state: bot.state, attention: bot.attention });\n return bot;\n });\n\n f.delete<{ Params: { id: string } }>('/api/bots/:id', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n manager.interrupt(req.params.id);\n store.deleteBot(req.params.id);\n return { ok: true };\n });\n\n /**\n * Start a fresh conversation: clears the thread and the SDK session, keeps the bot.\n *\n * Refused while the bot is working \u2014 resetting the session mid-turn would leave the running\n * turn writing into a message that no longer exists.\n */\n f.post<{ Params: { id: string } }>('/api/bots/:id/reset', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n if (bot.state === 'running' || bot.state === 'queued') {\n return reply.code(409).send({ error: 'This bot is working. Stop it first, then start fresh.' });\n }\n const result = store.resetBotSession(bot.id);\n if (!result) return reply.code(404).send({ error: 'No such bot' });\n if (bot.threadId) bus.publish({ type: 'thread.updated', threadId: bot.threadId, botId: bot.id, threadId2: bot.threadId });\n return { ok: true, ...result };\n });\n\n f.post<{ Params: { id: string } }>('/api/bots/:id/duplicate', async (req, reply) => {\n try {\n const copy = store.duplicateBot(req.params.id);\n return copy ?? reply.code(404).send({ error: 'No such bot' });\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.post<{ Params: { id: string } }>('/api/bots/:id/stop', async (req) => ({\n stopped: manager.interrupt(req.params.id),\n }));\n\n /* ------------------------------ memory ------------------------------ */\n f.get<{ Params: { id: string } }>('/api/bots/:id/memory', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n return readMemory(app.cfg.paths.workspace, bot.slug);\n });\n\n f.put<{ Params: { id: string }; Body: { name: string; content: string } }>('/api/bots/:id/memory', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n const { name, content } = req.body ?? {};\n if (!name || typeof content !== 'string') return reply.code(400).send({ error: 'name and content are required' });\n writeMemory(app.cfg.paths.workspace, bot.slug, name, content);\n return { ok: true };\n });\n\n f.delete<{ Params: { id: string; name: string } }>('/api/bots/:id/memory/:name', async (req, reply) => {\n const bot = store.getBot(req.params.id);\n if (!bot) return reply.code(404).send({ error: 'No such bot' });\n deleteMemory(app.cfg.paths.workspace, bot.slug, req.params.name);\n return { ok: true };\n });\n\n f.get<{ Params: { id: string } }>('/api/bots/:id/skills', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n return store.listBotSkills(req.params.id);\n });\n\n f.put<{ Params: { id: string }; Body: { skillIds: string[] } }>('/api/bots/:id/skills', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n store.setBotSkills(req.params.id, req.body?.skillIds ?? []);\n return { ok: true };\n });\n\n f.get<{ Params: { id: string } }>('/api/bots/:id/connectors', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n return store.listBotConnectors(req.params.id);\n });\n\n f.put<{ Params: { id: string }; Body: { connectorIds: string[] } }>('/api/bots/:id/connectors', async (req, reply) => {\n if (!store.getBot(req.params.id)) return reply.code(404).send({ error: 'No such bot' });\n store.setBotConnectors(req.params.id, req.body?.connectorIds ?? []);\n return { ok: true };\n });\n\n /* ----------------------------- threads ------------------------------ */\n f.get('/api/threads', async () => store.listThreads());\n\n f.post('/api/threads', async (req, reply) => {\n const parsed = CreateThreadRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n try {\n const members = parsed.data.memberBotIds.map((id) => store.getBot(id)).filter(Boolean);\n if (members.length !== parsed.data.memberBotIds.length)\n return reply.code(400).send({ error: 'One or more bots do not exist' });\n const title = parsed.data.title || members.map((m) => m!.name).join(', ');\n return store.createThread({ ...parsed.data, title });\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.get<{ Params: { id: string } }>('/api/threads/:id', async (req, reply) => {\n const thread = store.getThread(req.params.id);\n if (!thread) return reply.code(404).send({ error: 'No such thread' });\n const payload: ThreadWithMessages = { thread, messages: store.listMessages(thread.id) };\n return payload;\n });\n\n f.delete<{ Params: { id: string } }>('/api/threads/:id', async (req) => {\n store.deleteThread(req.params.id);\n return { ok: true };\n });\n\n f.post<{ Params: { id: string } }>('/api/threads/:id/read', async (req, reply) => {\n const thread = store.getThread(req.params.id);\n if (!thread) return reply.code(404).send({ error: 'No such thread' });\n store.updateThread(thread.id, { lastReadAt: Date.now() });\n for (const id of thread.memberBotIds) {\n const bot = store.getBot(id);\n if (bot && bot.attention !== 'needs_attention') {\n store.updateBot(id, { attention: 'none' });\n bus.publish({ type: 'bot.state', botId: id, threadId: thread.id, state: bot.state, attention: 'none' });\n }\n }\n return { ok: true };\n });\n\n /* ----------------------------- messages ----------------------------- */\n f.post<{ Params: { id: string } }>('/api/threads/:id/messages', async (req, reply) => {\n const parsed = PostMessageRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n const thread = store.getThread(req.params.id);\n if (!thread) return reply.code(404).send({ error: 'No such thread' });\n\n app.lastUserActivity.at = Date.now();\n\n const msg = store.createMessage({\n threadId: thread.id, authorKind: 'user', contentMd: parsed.data.contentMd,\n replyToId: parsed.data.replyToId ?? null,\n });\n if (parsed.data.attachmentIds?.length) {\n try {\n store.attachToMessage(parsed.data.attachmentIds, msg.id);\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n }\n bus.publish({ type: 'message.created', threadId: thread.id, botId: null, message: store.getMessage(msg.id)! });\n\n const attachments = store.listAttachmentsForMessage(msg.id);\n const attachNote = attachments.length\n ? `\\n\\nAttached files (read them from disk):\\n${attachments.map((a) => `- ${a.name} \u2192 ${a.path}`).join('\\n')}`\n : '';\n const prompt = parsed.data.contentMd + attachNote;\n\n const members = thread.memberBotIds.map((id) => store.getBot(id)).filter(Boolean) as NonNullable<ReturnType<typeof store.getBot>>[];\n if (!members.length) return msg;\n\n if (thread.kind === 'dm') {\n manager.enqueue({ botId: members[0]!.id, threadId: thread.id, prompt, origin: 'user', hops: 0 });\n } else {\n const inline = parseMentions(parsed.data.contentMd, members);\n const targets = await routeGroupMessage({\n text: parsed.data.contentMd,\n members,\n mentionBotIds: parsed.data.mentionBotIds ?? inline.botIds,\n mentionEveryone: parsed.data.mentionEveryone ?? inline.everyone,\n settings: app.getSettings(),\n cwd: app.cfg.paths.workspace,\n });\n for (const t of targets)\n manager.enqueue({ botId: t.id, threadId: thread.id, prompt, origin: 'user', hops: 0 });\n }\n return msg;\n });\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport type { FastifyInstance } from 'fastify';\nimport type { App } from '../app.js';\nimport { workspaceRelative } from '../app.js';\nimport {\n ApprovalDecisionRequest, CreateRuleRequest, CreateRoutineRequest, CreateSkillRequest,\n SettingsPatchSchema, LimitError, type UsageSummary, type SearchResult,\n CreateConnectorRequest, UpdateConnectorRequest, type Connector, type ApiConnector, type ApiCatalogEntry,\n} from '@antbot/contract';\nimport { computeMissingSecrets } from '../bots/connectors.js';\nimport { BUILTIN_CATALOG } from '../connectors/builtin/catalog.js';\nimport { redirectUri } from '../connectors/auth.js';\n\nexport function registerOpsRoutes(f: FastifyInstance, app: App): void {\n const { store, gateway, bus } = app;\n\n /* ---------------------------- approvals ---------------------------- */\n f.get('/api/approvals', async () => store.listPendingApprovals());\n\n f.post<{ Params: { id: string } }>('/api/approvals/:id', async (req, reply) => {\n const parsed = ApprovalDecisionRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n const updated = gateway.decide(req.params.id, parsed.data.decision, parsed.data.alwaysRule);\n return updated ?? reply.code(404).send({ error: 'No such approval' });\n });\n\n /* ------------------------------ rules ------------------------------ */\n f.get('/api/rules', async () => store.listRules());\n\n f.post('/api/rules', async (req, reply) => {\n const parsed = CreateRuleRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n try {\n new RegExp(parsed.data.inputPattern || '');\n } catch {\n return reply.code(400).send({ error: 'inputPattern is not a valid regular expression' });\n }\n return store.createRule(parsed.data);\n });\n\n f.patch<{ Params: { id: string }; Body: { enabled: boolean } }>('/api/rules/:id', async (req, reply) => {\n const rule = store.getRule(req.params.id);\n if (!rule) return reply.code(404).send({ error: 'No such rule' });\n store.setRuleEnabled(rule.id, Boolean(req.body?.enabled));\n return store.getRule(rule.id);\n });\n\n f.delete<{ Params: { id: string } }>('/api/rules/:id', async (req, reply) => {\n const rule = store.getRule(req.params.id);\n if (!rule) return reply.code(404).send({ error: 'No such rule' });\n if (rule.builtin) return reply.code(400).send({ error: 'Built-in rules cannot be deleted; disable it instead.' });\n store.deleteRule(rule.id);\n return { ok: true };\n });\n\n /* ---------------------------- connectors --------------------------- */\n const describe = (c: Connector): ApiConnector => ({\n ...c,\n missingSecrets: computeMissingSecrets(c, new Set(app.secrets?.list() ?? [])),\n // Names only \u2014 knowing a connector is signed in never requires reading its token.\n signedIn: app.connectorAuth?.isAuthorized(c.name) ?? false,\n });\n\n /** Secret values never appear here: rows hold `{{secret:NAME}}` references and nothing more. */\n f.get('/api/connectors', async () => store.listConnectors().map(describe));\n\n /** The built-in connectors ant-bot ships, with what setting each up involves. */\n f.get('/api/connectors/catalog', async (): Promise<ApiCatalogEntry[]> =>\n Object.values(BUILTIN_CATALOG).map((b) => ({\n name: b.name,\n displayName: b.displayName,\n description: b.description,\n provider: b.provider.displayName,\n needsClientCredentials: !b.provider.dynamicRegistration,\n setupSteps: b.provider.setupSteps.map((step) => step.replace('{redirectUri}', redirectUri(app.cfg.port))),\n })),\n );\n\n /**\n * Add a connector \u2014 a custom command/URL, or a built-in by catalog name \u2014 assign it to bots, and\n * check it, all in one call. The verdict comes back with the row so the caller can say what to\n * do next without a second round trip.\n */\n f.post('/api/connectors', async (req, reply) => {\n const parsed = CreateConnectorRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: parsed.error.issues[0]?.message ?? 'Invalid body' });\n const body = parsed.data;\n if (store.getConnectorByName(body.name)) {\n return reply.code(409).send({ error: `A connector named \"${body.name}\" already exists` });\n }\n let created: Connector;\n if (body.builtin) {\n const def = app.builtin?.get(body.builtin);\n if (!def) return reply.code(400).send({ error: `No built-in connector named \"${body.builtin}\"` });\n // The name is fixed: tool names (`mcp__gmail__send_message`) and the seeded rules that gate\n // them depend on it.\n if (body.name !== def.name) return reply.code(400).send({ error: `The built-in ${def.name} connector must be named \"${def.name}\"` });\n created = store.createConnector({\n name: def.name, description: body.description || def.description,\n config: app.builtin!.rowConfig(def.name), kind: 'builtin', enabled: body.enabled,\n });\n } else {\n created = store.createConnector({ name: body.name, description: body.description, config: body.config!, enabled: body.enabled });\n }\n for (const botId of body.botIds ?? []) {\n if (!store.getBot(botId)) continue;\n const current = store.listBotConnectors(botId).map((c) => c.id);\n store.setBotConnectors(botId, [...new Set([...current, created.id])]);\n }\n const check = await app.checkConnector(created);\n return { ...describe(store.getConnector(created.id)!), check };\n });\n\n f.patch<{ Params: { id: string } }>('/api/connectors/:id', async (req, reply) => {\n const parsed = UpdateConnectorRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n const existing = store.getConnector(req.params.id);\n if (!existing) return reply.code(404).send({ error: 'No such connector' });\n // A built-in's config is the daemon's own endpoint; only enabled/description may change.\n if (existing.kind === 'builtin' && parsed.data.config) return reply.code(400).send({ error: 'A built-in connector has no editable config' });\n return describe(store.updateConnector(req.params.id, parsed.data)!);\n });\n\n f.delete<{ Params: { id: string } }>('/api/connectors/:id', async (req, reply) => {\n const c = store.getConnector(req.params.id);\n if (!c) return reply.code(404).send({ error: 'No such connector' });\n await app.connectorAuth?.signOut(c.name);\n store.deleteConnector(req.params.id);\n return { ok: true };\n });\n\n /** One honest verdict: ready, needs sign-in, needs a credential, or unreachable. Persisted. */\n f.post<{ Params: { id: string } }>('/api/connectors/:id/check', async (req, reply) => {\n const connector = store.getConnector(req.params.id);\n if (!connector) return reply.code(404).send({ error: 'No such connector' });\n return app.checkConnector(connector);\n });\n\n /**\n * Begin an interactive sign-in. Returns the URL the human must open; the browser comes back to\n * the callback below. `clientId`/`clientSecret` are needed only for providers without dynamic\n * registration \u2014 Google, for the built-in connectors.\n */\n f.post<{ Params: { id: string }; Body: { clientId?: string; clientSecret?: string; scopes?: string[] } }>(\n '/api/connectors/:id/login',\n async (req, reply) => {\n const connector = store.getConnector(req.params.id);\n if (!connector) return reply.code(404).send({ error: 'No such connector' });\n if (!app.connectorAuth) return reply.code(503).send({ error: 'Secrets backend unavailable, so sign-in cannot be stored' });\n try {\n const authorizeUrl = connector.kind === 'builtin'\n ? await app.builtin!.beginLogin(connector, req.body ?? {})\n : (await app.connectorAuth.beginLogin(connector, req.body ?? {})).authorizeUrl;\n return { authorizeUrl };\n } catch (err) {\n return reply.code(400).send({ error: (err as Error).message });\n }\n },\n );\n\n f.delete<{ Params: { id: string } }>('/api/connectors/:id/login', async (req, reply) => {\n const connector = store.getConnector(req.params.id);\n if (!connector) return reply.code(404).send({ error: 'No such connector' });\n await app.connectorAuth?.signOut(connector.name);\n store.setConnectorStatus(connector.id, 'needs-sign-in', null);\n return { ok: true };\n });\n\n /**\n * Where the authorization server sends the human back. Renders a plain page rather than JSON:\n * this is the one route a person lands on in a browser.\n */\n f.get<{ Querystring: { code?: string; state?: string; error?: string; error_description?: string } }>(\n '/api/connectors/oauth/callback',\n async (req, reply) => {\n const page = (title: string, detail: string, ok: boolean): string =>\n `<!doctype html><meta charset=utf-8><title>${title}</title>\n <body style=\"font-family:system-ui;background:#0b0d10;color:#e6e8eb;padding:3rem;max-width:40rem\">\n <h1 style=\"color:${ok ? '#4ade80' : '#f87171'}\">${title}</h1><p>${detail}</p>\n <p style=\"color:#9aa4b2\">You can close this tab and return to ant-bot.</p>`;\n\n const { code, state, error, error_description: desc } = req.query;\n if (error) return reply.type('text/html').send(page('Sign-in failed', `${error}: ${desc ?? ''}`, false));\n if (!code || !state) return reply.type('text/html').send(page('Sign-in failed', 'The provider did not return a code.', false));\n if (!app.connectorAuth) return reply.type('text/html').send(page('Sign-in failed', 'The secrets backend is unavailable.', false));\n try {\n const { connectorId, connectorName } = await app.connectorAuth.completeLogin(state, code);\n const row = store.getConnector(connectorId);\n if (row) await app.checkConnector(row);\n bus.publish({ type: 'notify', botId: null, threadId: null, title: 'Connector signed in', body: `${connectorName} is now authorised.`, level: 'info' });\n return reply.type('text/html').send(page('Signed in', `<b>${connectorName}</b> is now authorised.`, true));\n } catch (err) {\n return reply.type('text/html').send(page('Sign-in failed', (err as Error).message, false));\n }\n },\n );\n\n /**\n * The daemon's own MCP endpoint for built-in connectors. Guarded by a per-boot bearer that only\n * the runtime is handed at mount time; the provider token stays on this side of the line.\n */\n f.post<{ Params: { name: string } }>('/mcp/:name', async (req, reply) => {\n if (!app.builtin) return reply.code(503).send({ error: 'Built-in connectors unavailable' });\n if (!app.builtin.checkBearer(req.headers.authorization)) return reply.code(401).send({ error: 'Unauthorized' });\n const res = await app.builtin.handle(req.params.name, req.body);\n if (res === null) return reply.code(202).send();\n return res;\n });\n f.delete<{ Params: { name: string } }>('/mcp/:name', async () => ({ ok: true }));\n\n /* ------------------------------ skills ----------------------------- */\n f.get('/api/skills', async () => store.listSkills());\n\n f.post('/api/skills', async (req, reply) => {\n const parsed = CreateSkillRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n if (!app.skills?.writeSkill) return reply.code(503).send({ error: 'Skills subsystem unavailable' });\n return app.skills.writeSkill(parsed.data);\n });\n\n // Install from a source (git repo, local path, or a raw SKILL.md URL). This is the\n // simple path: no hand-built JSON body, just the source string.\n f.post<{ Body: { source?: string } }>('/api/skills/install', async (req, reply) => {\n const source = (req.body?.source ?? '').trim();\n if (!source) return reply.code(400).send({ error: 'A \"source\" is required' });\n if (!app.skills?.installFromSource) return reply.code(503).send({ error: 'Skills subsystem unavailable' });\n try {\n // A human typing `antbot skill add owner/repo` is asking for that repository, whatever\n // it holds; the multi-skill guard exists for bots choosing a source on their own.\n const installed = await app.skills.installFromSource(source, { allowMultiple: true });\n return {\n installed: installed.map((i: { skill: unknown; executables: string[]; manifestText: string; replaced: boolean }) => ({\n skill: i.skill,\n executables: i.executables,\n manifest: i.manifestText,\n replaced: i.replaced,\n })),\n };\n } catch (err) {\n return reply.code(400).send({ error: (err as Error).message });\n }\n });\n\n f.get<{ Params: { id: string } }>('/api/skills/:id', async (req, reply) => {\n const skill = store.getSkill(req.params.id);\n if (!skill) return reply.code(404).send({ error: 'No such skill' });\n if (app.skills?.readSkill) return app.skills.readSkill(skill.id);\n return { ...skill, bodyMd: '' };\n });\n\n f.delete<{ Params: { id: string } }>('/api/skills/:id', async (req, reply) => {\n const skill = store.getSkill(req.params.id);\n if (!skill) return reply.code(404).send({ error: 'No such skill' });\n if (app.skills?.deleteSkill) app.skills.deleteSkill(skill.id);\n else store.deleteSkill(skill.id);\n return { ok: true };\n });\n\n /* ------------------------- secrets (WP-2.4) ------------------------ */\n // Values go straight to the OS keychain. Only NAMES are ever returned here, and a\n // value is never written to a transcript or placed in the model's context.\n f.get('/api/secrets', async () => ({\n backend: app.secrets?.backendName ?? 'unavailable',\n names: app.secrets?.list() ?? [],\n }));\n\n f.post<{ Body: { name?: string; value?: string } }>('/api/secrets', async (req, reply) => {\n if (!app.secrets) return reply.code(503).send({ error: 'Secrets backend unavailable' });\n const name = (req.body?.name ?? '').trim();\n const value = req.body?.value ?? '';\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))\n return reply.code(400).send({ error: 'Name must be a valid environment-variable identifier' });\n if (!value) return reply.code(400).send({ error: 'A value is required' });\n await app.secrets.set(name, value);\n return { ok: true, names: app.secrets.list() };\n });\n\n f.delete<{ Params: { name: string } }>('/api/secrets/:name', async (req, reply) => {\n if (!app.secrets) return reply.code(503).send({ error: 'Secrets backend unavailable' });\n await app.secrets.remove(req.params.name);\n return { ok: true, names: app.secrets.list() };\n });\n\n /* ----------------------------- routines ---------------------------- */\n f.get<{ Querystring: { botId?: string } }>('/api/routines', async (req) => store.listRoutines(req.query.botId));\n\n f.post('/api/routines', async (req, reply) => {\n const parsed = CreateRoutineRequest.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid body' });\n if (!store.getBot(parsed.data.botId)) return reply.code(400).send({ error: 'No such bot' });\n try {\n const routine = store.createRoutine({ ...parsed.data, timezone: parsed.data.timezone ?? app.getSettings().timezone });\n app.scheduler?.reload?.(routine.id);\n return routine;\n } catch (err) {\n if (err instanceof LimitError) return reply.code(409).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.patch<{ Params: { id: string } }>('/api/routines/:id', async (req, reply) => {\n const routine = store.updateRoutine(req.params.id, (req.body ?? {}) as Record<string, never>);\n if (!routine) return reply.code(404).send({ error: 'No such routine' });\n app.scheduler?.reload?.(routine.id);\n return routine;\n });\n\n f.delete<{ Params: { id: string } }>('/api/routines/:id', async (req, reply) => {\n if (!store.getRoutine(req.params.id)) return reply.code(404).send({ error: 'No such routine' });\n store.deleteRoutine(req.params.id);\n app.scheduler?.reload?.(req.params.id);\n return { ok: true };\n });\n\n f.get<{ Params: { id: string } }>('/api/routines/:id/runs', async (req) => store.listRuns(req.params.id));\n\n f.post<{ Params: { id: string } }>('/api/routines/:id/test-run', async (req, reply) => {\n const routine = store.getRoutine(req.params.id);\n if (!routine) return reply.code(404).send({ error: 'No such routine' });\n if (!app.scheduler?.testRun) return reply.code(503).send({ error: 'Scheduler unavailable' });\n const runId = await app.scheduler.testRun(routine.id);\n return { runId };\n });\n\n /* ---------------------------- attachments -------------------------- */\n f.post('/api/attachments', async (req, reply) => {\n const anyReq = req as unknown as { file?: () => Promise<any>; isMultipart?: () => boolean };\n if (typeof anyReq.file !== 'function') return reply.code(400).send({ error: 'Expected a multipart upload' });\n const part = await anyReq.file();\n if (!part) return reply.code(400).send({ error: 'No file in request' });\n const buf: Buffer = await part.toBuffer();\n const safe = String(part.filename ?? 'file').replace(/[^a-zA-Z0-9._-]/g, '_');\n const dest = path.join(app.cfg.paths.attachments, `${Date.now()}-${safe}`);\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.writeFileSync(dest, buf);\n try {\n return store.createAttachment({\n messageId: null, path: dest, name: safe,\n mime: part.mimetype ?? 'application/octet-stream', bytes: buf.byteLength,\n });\n } catch (err) {\n fs.unlinkSync(dest);\n if (err instanceof LimitError) return reply.code(413).send({ error: err.message, code: err.code });\n throw err;\n }\n });\n\n f.get<{ Params: { id: string } }>('/api/attachments/:id', async (req, reply) => {\n const a = store.getAttachment(req.params.id);\n if (!a || !fs.existsSync(a.path)) return reply.code(404).send({ error: 'No such attachment' });\n return reply.type(a.mime).send(fs.createReadStream(a.path));\n });\n\n /* ------------------------------ usage ------------------------------ */\n f.get('/api/usage', async (): Promise<UsageSummary> => {\n const rows = store.listUsage(0);\n const totals = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0 };\n const byBot = new Map<string, { inputTokens: number; outputTokens: number }>();\n const byDay = new Map<string, { inputTokens: number; outputTokens: number }>();\n const byModel = new Map<string, { inputTokens: number; outputTokens: number }>();\n for (const r of rows) {\n totals.inputTokens += r.inputTokens;\n totals.outputTokens += r.outputTokens;\n totals.cacheReadTokens += r.cacheReadTokens;\n const day = new Date(r.createdAt).toISOString().slice(0, 10);\n for (const [map, key] of [[byBot, r.botId], [byDay, day], [byModel, r.model]] as const) {\n const cur = map.get(key) ?? { inputTokens: 0, outputTokens: 0 };\n cur.inputTokens += r.inputTokens;\n cur.outputTokens += r.outputTokens;\n map.set(key, cur);\n }\n }\n return {\n totals,\n byBot: [...byBot].map(([botId, v]) => ({ botId, botName: store.getBot(botId)?.name ?? 'deleted', ...v })),\n byDay: [...byDay].map(([day, v]) => ({ day, ...v })).sort((a, b) => a.day.localeCompare(b.day)),\n byModel: [...byModel].map(([model, v]) => ({ model, ...v })),\n };\n });\n\n /* ------------------------------ search ----------------------------- */\n f.get<{ Querystring: { q?: string } }>('/api/search', async (req): Promise<SearchResult[]> => {\n const q = (req.query.q ?? '').trim();\n if (!q) return [];\n const out: SearchResult[] = [];\n for (const b of store.listBots()) {\n if (b.name.toLowerCase().includes(q.toLowerCase()) || b.title.toLowerCase().includes(q.toLowerCase()))\n out.push({ kind: 'bot', id: b.id, threadId: b.threadId, botId: b.id, title: b.name, snippet: b.title || b.description.slice(0, 120), createdAt: b.createdAt });\n }\n for (const m of store.searchMessages(q)) {\n const idx = m.contentMd.toLowerCase().indexOf(q.toLowerCase());\n const start = Math.max(0, idx - 60);\n out.push({\n kind: 'message', id: m.id, threadId: m.threadId, botId: m.authorBotId,\n title: m.authorKind === 'user' ? 'You' : store.getBot(m.authorBotId ?? '')?.name ?? 'Bot',\n snippet: `${start > 0 ? '\u2026' : ''}${m.contentMd.slice(start, start + 180)}`,\n createdAt: m.createdAt,\n });\n }\n for (const r of store.listRoutines()) {\n if (r.name.toLowerCase().includes(q.toLowerCase()))\n out.push({ kind: 'routine', id: r.id, threadId: null, botId: r.botId, title: r.name, snippet: r.cronExpr, createdAt: r.createdAt });\n }\n return out.slice(0, 50);\n });\n\n /* ----------------------------- settings ---------------------------- */\n f.get('/api/settings', async () => store.getSettings());\n\n f.patch('/api/settings', async (req, reply) => {\n const parsed = SettingsPatchSchema.safeParse(req.body);\n if (!parsed.success) return reply.code(400).send({ error: 'Invalid settings' });\n const next = store.patchSettings(parsed.data);\n app.scheduler?.syncAll?.();\n bus.publish({ type: 'notify', botId: null, threadId: null, title: 'Settings updated', body: '', level: 'info' });\n return next;\n });\n\n /* ---------------------------- workspace ---------------------------- */\n f.get<{ Querystring: { path?: string } }>('/api/workspace/tree', async (req, reply) => {\n const root = app.cfg.paths.workspace;\n const target = workspaceRelative(root, req.query.path ?? '.');\n if (!target) return reply.code(400).send({ error: 'Path is outside the workspace' });\n if (!fs.existsSync(target)) return [];\n return fs.readdirSync(target, { withFileTypes: true })\n .map((d) => {\n const full = path.join(target, d.name);\n let bytes = 0;\n try { bytes = d.isFile() ? fs.statSync(full).size : 0; } catch { /* ignore */ }\n return { name: d.name, path: path.relative(root, full), dir: d.isDirectory(), bytes };\n })\n .sort((a, b) => (a.dir === b.dir ? a.name.localeCompare(b.name) : a.dir ? -1 : 1));\n });\n\n f.get<{ Querystring: { path?: string } }>('/api/workspace/file', async (req, reply) => {\n const root = app.cfg.paths.workspace;\n const target = workspaceRelative(root, req.query.path ?? '');\n if (!target || !fs.existsSync(target) || !fs.statSync(target).isFile())\n return reply.code(404).send({ error: 'No such file' });\n const ext = path.extname(target).toLowerCase();\n const mime: Record<string, string> = {\n '.md': 'text/markdown', '.txt': 'text/plain', '.json': 'application/json',\n '.csv': 'text/csv', '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',\n '.gif': 'image/gif', '.svg': 'image/svg+xml', '.pdf': 'application/pdf', '.html': 'text/html',\n };\n return reply.type(mime[ext] ?? 'application/octet-stream').send(fs.createReadStream(target));\n });\n\n /* ----------------------------- computer ---------------------------- */\n f.get('/api/computer/status', async () => {\n if (!app.browser?.status) return { available: false, reason: 'Browser service not built', mode: 'host', headless: true, pages: [] };\n try {\n return await app.browser.status();\n } catch (err) {\n return { available: false, reason: (err as Error).message, mode: 'host', headless: true, pages: [] };\n }\n });\n\n f.post<{ Body: { botId?: string } }>('/api/computer/takeover', async (req, reply) => {\n if (!app.browser?.takeOver) return reply.code(503).send({ error: 'Browser service unavailable' });\n return app.browser.takeOver(req.body?.botId ?? 'shared');\n });\n\n f.delete<{ Body: { botId?: string } }>('/api/computer/takeover', async (req, reply) => {\n if (!app.browser?.returnControl) return reply.code(503).send({ error: 'Browser service unavailable' });\n await app.browser.returnControl(req.body?.botId ?? 'shared');\n return { ok: true };\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["path", "fileURLToPath", "fs", "path", "fs", "path", "b", "now", "err", "fs", "path", "log", "path", "log", "err", "query", "log", "err", "log", "query", "err", "path", "fs", "fs", "path", "log", "b", "path", "fs", "i", "err", "ok", "args", "crypto", "b", "path", "i", "now", "err", "redirectUri", "log", "crypto", "err", "crypto", "z", "tool", "path", "z", "crypto", "b", "log", "err", "err", "fs", "path", "fs", "fs", "fs", "path", "crypto", "log", "err", "fs", "path", "crypto", "log", "err", "opts", "i", "path", "fs", "query", "log", "query", "err", "fs", "path", "fileURLToPath", "path", "fileURLToPath", "fs", "err", "fs", "path", "b", "err", "ok", "i", "path", "fs", "log", "path", "fileURLToPath", "err", "b"]
|
|
7
7
|
}
|