negotium 0.18.0 → 0.18.2
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/dist/agent-helpers.js +7082 -7062
- package/dist/agent-helpers.js.map +10 -10
- package/dist/{chunk-th3a0ew7.js → chunk-3d1pjgfw.js} +633 -195
- package/dist/{chunk-th3a0ew7.js.map → chunk-3d1pjgfw.js.map} +9 -6
- package/dist/{chunk-kgwgwc3r.js → chunk-44ajn328.js} +3 -3
- package/dist/{chunk-kgwgwc3r.js.map → chunk-44ajn328.js.map} +2 -2
- package/dist/{chunk-axa09pgx.js → chunk-q2s5f70x.js} +1 -1
- package/dist/hosted-agent.js +634 -196
- package/dist/hosted-agent.js.map +10 -7
- package/dist/main.js +5942 -5908
- package/dist/main.js.map +13 -13
- package/dist/mcp-factories.js +3418 -3393
- package/dist/mcp-factories.js.map +11 -11
- package/dist/prompts.js +18 -14
- package/dist/prompts.js.map +3 -3
- package/dist/registry.js +3 -3
- package/dist/rollout.js +2 -2
- package/dist/runtime/src/agents/mcp-tools/spawn-subagent.ts +43 -16
- package/dist/runtime/src/mcp/factories/decision.ts +11 -3
- package/dist/runtime/src/mcp/session-comm/server.ts +1 -1
- package/dist/runtime/src/platform/mcp-config.ts +79 -58
- package/dist/runtime/src/prompts/builders.ts +34 -17
- package/dist/runtime/src/prompts/sessions/surfaces/otium-manager.md +18 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/types/packages/core/src/agents/mcp-tools/spawn-subagent.d.ts +8 -4
- package/dist/types/packages/core/src/mcp/factories/decision.d.ts +2 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-axa09pgx.js.map → chunk-q2s5f70x.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../packages/core/src/agents/rollout/shared.ts", "../../../packages/core/src/platform/config.ts", "../../../packages/core/src/types.ts", "../../../packages/core/src/platform/config-helpers.ts", "../../../packages/core/src/platform/logger.ts", "../../../packages/core/src/platform/paths.ts", "../../../packages/core/src/runtime/user-turn-envelope.ts", "../../../packages/core/src/agents/execution-host.ts", "../../../packages/core/src/security/sensitive-path.ts", "../../../packages/core/src/agents/vault-tool-policy.ts", "../../../packages/core/src/mcp/canonical-bridge-config.ts", "../../../packages/core/src/mcp/runtime-spec.ts", "../../../packages/core/src/mcp/session-comm/bridge-ipc-config.ts", "../../../packages/core/src/platform/background-bash/manager.ts", "../../../packages/core/src/platform/delay.ts", "../../../packages/core/src/platform/background-bash/context.ts", "../../../packages/core/src/platform/mcp-catalog-policy.ts", "../../../packages/core/src/platform/playwright/capability.ts", "../../../packages/core/src/platform/playwright/mcp-transport.ts", "../../../packages/core/src/runtime/cron-sessions.ts", "../../../packages/core/src/platform/
|
|
3
|
+
"sources": ["../../../packages/core/src/agents/rollout/shared.ts", "../../../packages/core/src/platform/config.ts", "../../../packages/core/src/types.ts", "../../../packages/core/src/platform/config-helpers.ts", "../../../packages/core/src/platform/logger.ts", "../../../packages/core/src/platform/paths.ts", "../../../packages/core/src/runtime/user-turn-envelope.ts", "../../../packages/core/src/agents/execution-host.ts", "../../../packages/core/src/security/sensitive-path.ts", "../../../packages/core/src/agents/vault-tool-policy.ts", "../../../packages/core/src/mcp/canonical-bridge-config.ts", "../../../packages/core/src/mcp/runtime-spec.ts", "../../../packages/core/src/mcp/session-comm/bridge-ipc-config.ts", "../../../packages/core/src/platform/background-bash/manager.ts", "../../../packages/core/src/platform/delay.ts", "../../../packages/core/src/platform/background-bash/context.ts", "../../../packages/core/src/platform/mcp-catalog-policy.ts", "../../../packages/core/src/platform/playwright/capability.ts", "../../../packages/core/src/platform/playwright/mcp-transport.ts", "../../../packages/core/src/runtime/cron-sessions.ts", "../../../packages/core/src/platform/constants.ts", "../../../packages/core/src/storage/storage-host.ts", "../../../packages/core/src/storage/sqlite.ts", "../../../packages/core/src/storage/forum-db.ts", "../../../packages/core/src/storage/api-topics.ts", "../../../packages/core/src/platform/mcp-config.ts", "../../../packages/core/src/storage/vault.ts", "../../../packages/core/src/storage/vault-crypto-core.ts", "../../../packages/core/src/storage/vault-crypto.ts", "../../../packages/core/src/agents/rollout/codex.ts", "../../../packages/core/src/platform/jsonl.ts", "../../../packages/core/src/platform/file-utils.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * Helpers shared by every agent's rollout encoder.\n *\n * Each rollout file under `agents/rollout/<agent>.ts` materializes a\n * synthetic SDK-native JSONL from a provider-agnostic `ConversationEntry`\n * stream. The cwd validation, UUID shape check, and chat-pair extraction\n * are identical regardless of agent, so they live here.\n */\n\nimport { mkdirSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport {\n DM_WORKSPACE_DIR,\n PROJECT_ROOT,\n SESSION_WORKSPACE_DIR,\n TOPIC_WORKSPACE_DIR,\n WORKSPACE_DIR,\n} from \"#platform/config\";\nimport { logger } from \"#platform/logger\";\nimport { isInsideDir } from \"#platform/paths\";\nimport { renderUserPromptBatch } from \"#runtime/user-turn-envelope\";\nimport type { ConversationEntry } from \"#storage/conversations\";\nimport type { UnifiedEvent } from \"#types\";\n\nexport interface RolloutHostOptions {\n /** Absolute workspace roots under which synthetic provider sessions may be written. */\n workspaceRoots?: readonly string[];\n /** Directory containing the provider rollout fixture JSONL files. */\n fixturesDir?: string;\n}\n\nlet trustedWorkspaceRoots = [\n WORKSPACE_DIR,\n DM_WORKSPACE_DIR,\n SESSION_WORKSPACE_DIR,\n TOPIC_WORKSPACE_DIR,\n].map((root) => resolve(root));\n\n/** Configure the embedding host's trusted workspace roots. */\nexport function configureRolloutHost(options: RolloutHostOptions): () => void {\n if (!options.workspaceRoots && !options.fixturesDir) {\n throw new Error(\"configureRolloutHost requires workspaceRoots or fixturesDir\");\n }\n if (options.workspaceRoots?.length === 0) {\n throw new Error(\"configureRolloutHost requires at least one workspace root\");\n }\n const previousRoots = trustedWorkspaceRoots;\n const previousFixturesDir = FIXTURES_DIR;\n if (options.workspaceRoots) {\n trustedWorkspaceRoots = options.workspaceRoots.map((root) => resolve(root));\n }\n if (options.fixturesDir) FIXTURES_DIR = resolve(options.fixturesDir);\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n trustedWorkspaceRoots = previousRoots;\n FIXTURES_DIR = previousFixturesDir;\n };\n}\n\n/**\n * Captured fixture snapshots — `claude-attachments.jsonl`, `codex-shell.jsonl`,\n * etc. — live one level above the per-agent rollout files (under\n * `agents/fixtures/`) so each agent can pull from the same directory without\n * duplicating fixtures.\n *\n * To refresh fixtures: run any live Codex/Claude session, copy the first few\n * non-conversational entries from the resulting rollout file, and update\n * `src/agents/fixtures/{codex-shell,claude-attachments}.jsonl`.\n */\nexport let FIXTURES_DIR = resolve(PROJECT_ROOT, \"src\", \"agents\", \"fixtures\");\n\n/** Deep-clone to avoid mutating cached fixture objects. */\nexport function clone<T>(obj: T): T {\n return structuredClone(obj);\n}\n\n/**\n * UUID v4/v7 shape — both 36 chars with the standard 8-4-4-4-12 hex layout.\n * We do not enforce the version nibble because randomUUID (v4) and uuidv7\n * coexist; the only requirement for our caller is that the value is safe to\n * embed in a path component and that the SDK accepts it as a session/thread\n * identifier.\n */\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function assertUuidLike(label: string, value: string): void {\n if (!UUID_RE.test(value)) {\n throw new Error(`rollout: ${label} is not a UUID-shaped string: ${value}`);\n }\n}\n\n/**\n * Reject cwds that escape Otium-managed workspace roots. We use `path.resolve`\n * to normalize `..` traversal; symlink-based escapes are out of scope (the\n * workspace roots are not expected to contain attacker-controlled symlinks).\n */\nfunction assertCwdInWorkspace(cwd: string): void {\n const abs = resolve(cwd);\n // Synthetic rollouts for spawn/fork must be written under the same root as\n // live topic turns or provider resume looks in a different cwd hash than the\n // one we generated.\n const ok = trustedWorkspaceRoots.some((root) => isInsideDir(abs, root));\n if (!ok) {\n throw new Error(`rollout: cwd outside trusted workspace roots: ${cwd} (resolved=${abs})`);\n }\n}\n\n/** Best-effort guarantee that the resumed cwd will exist when the SDK stats it. */\nexport function ensureCwdExists(cwd: string): void {\n assertCwdInWorkspace(cwd);\n try {\n mkdirSync(cwd, { recursive: true });\n } catch (err) {\n logger.warn({ err, cwd }, \"rollout: ensureCwdExists failed — caller should pre-create cwd\");\n }\n}\n\n/**\n * Length-bound a string by Unicode code points rather than UTF-16 units, so a\n * truncation never lands in the middle of a multi-byte sequence and produces\n * a malformed character. Used for in-line tool annotations where we only need\n * a rough preview, not the full payload.\n */\nfunction truncate(text: string, n: number): string {\n const cps = Array.from(text);\n return cps.length > n ? `${cps.slice(0, n).join(\"\")}…` : text;\n}\n\n/**\n * Reduce a UnifiedEvent stream to user/assistant message pairs. Tool calls and\n * tool results are inlined as bracketed annotations on the surrounding\n * assistant turn so the historical narrative is preserved when synthesizing a\n * native rollout for a different SDK. Streaming text deltas are folded into\n * their final consolidated `text` event to avoid double-counting partial\n * tokens.\n */\nexport type ChatPair = { userText: string; assistantText: string };\n\nexport interface ExtractOptions {\n includeToolAnnotations: boolean;\n formatToolUse?: (event: Extract<UnifiedEvent, { type: \"tool_use\" }>) => string;\n formatToolResult?: (event: Extract<UnifiedEvent, { type: \"tool_result\" }>) => string;\n}\n\nexport function extractChatPairs(\n entries: ConversationEntry[],\n opts: ExtractOptions = { includeToolAnnotations: true },\n): ChatPair[] {\n const pairs: ChatPair[] = [];\n let pendingUsers: string[] = [];\n let pendingBatchSize: number | null = null;\n let pendingBatchNextIndex = 0;\n let pendingAssistantParts: string[] = [];\n let toolBuffer: string[] = [];\n\n const flushAssistant = () => {\n if (pendingUsers.length === 0) return;\n const tools =\n opts.includeToolAnnotations && toolBuffer.length > 0 ? `\\n\\n${toolBuffer.join(\"\\n\")}` : \"\";\n const assistantText = pendingAssistantParts.join(\"\").trim() + tools;\n if (assistantText.trim()) {\n pairs.push({ userText: renderUserPromptBatch(pendingUsers), assistantText });\n }\n pendingUsers = [];\n pendingBatchSize = null;\n pendingBatchNextIndex = 0;\n pendingAssistantParts = [];\n toolBuffer = [];\n };\n\n for (const entry of entries) {\n const ev = entry.event;\n switch (ev.type) {\n case \"user_message\": {\n const userEvent = ev as {\n content: string;\n consecutiveBatchSize?: number;\n consecutiveBatchIndex?: number;\n };\n if (pendingAssistantParts.length > 0 || toolBuffer.length > 0) {\n flushAssistant();\n }\n const batchSize = userEvent.consecutiveBatchSize;\n const batchIndex = userEvent.consecutiveBatchIndex;\n const marked =\n Number.isInteger(batchSize) &&\n Number.isInteger(batchIndex) &&\n (batchSize ?? 0) > 1 &&\n (batchIndex ?? -1) >= 0 &&\n (batchIndex ?? 0) < (batchSize ?? 0);\n if (!marked) {\n if (pendingUsers.length > 0) flushAssistant();\n pendingUsers.push(userEvent.content);\n pendingBatchSize = null;\n pendingBatchNextIndex = 0;\n break;\n }\n if (batchIndex === 0) {\n if (pendingUsers.length > 0) flushAssistant();\n pendingBatchSize = batchSize ?? null;\n pendingBatchNextIndex = 0;\n } else if (\n !(\n (pendingBatchSize !== null &&\n (batchSize ?? 0) >= pendingBatchSize &&\n pendingBatchNextIndex === batchIndex) ||\n (pendingBatchSize === null && pendingUsers.length === batchIndex)\n )\n ) {\n flushAssistant();\n }\n pendingUsers.push(userEvent.content);\n pendingBatchSize = batchSize ?? null;\n pendingBatchNextIndex = (batchIndex ?? 0) + 1;\n break;\n }\n case \"session\":\n // Session-id metadata. Provider sessions can change mid-conversation\n // (e.g. agent flip after rollout reconstruction), but the SDK normally\n // emits this *during* a turn — after the user prompt was already\n // recorded, before the assistant text arrives. Only flush when there\n // is actual assistant content in flight; otherwise we'd discard the\n // staged user prompt and the next text event would synthesize a bogus\n // \"(continued)\" pair.\n if (pendingAssistantParts.length > 0 || toolBuffer.length > 0) {\n flushAssistant();\n }\n break;\n case \"text\": {\n // Per-block assistant text. claudeProvider emits one of these per text\n // content block, so a single turn can yield multiple `text` events\n // interleaved with tool_use. Accumulate (do NOT flush yet) — the\n // turn's `result` event below carries the final concatenation and\n // is the proper boundary.\n if (pendingUsers.length === 0) {\n pendingUsers = [\"(continued)\"];\n }\n pendingAssistantParts.push((ev as { content: string }).content);\n break;\n }\n case \"result\": {\n // End-of-turn marker. `result.content` is the canonical final answer\n // produced by the provider, so prefer it over the accumulated `text`\n // chunks (which may be partial or out of order across SDKs).\n if (pendingUsers.length === 0) {\n pendingUsers = [\"(continued)\"];\n }\n pendingAssistantParts = [(ev as { content: string }).content];\n flushAssistant();\n break;\n }\n case \"text_delta\":\n // Skip — final `text`/`result` event carries the complete content.\n break;\n case \"tool_use\": {\n const u = ev as Extract<UnifiedEvent, { type: \"tool_use\" }>;\n toolBuffer.push(\n opts.formatToolUse?.(u) ??\n `<!-- Tool: ${u.name} ${truncate(JSON.stringify(u.input), 200)} -->`,\n );\n break;\n }\n case \"tool_result\": {\n const u = ev as Extract<UnifiedEvent, { type: \"tool_result\" }>;\n toolBuffer.push(\n opts.formatToolResult?.(u) ?? `<!-- Tool result: ${truncate(u.content, 200)} -->`,\n );\n break;\n }\n case \"error\": {\n const u = ev as { content: string };\n toolBuffer.push(`[Error: ${truncate(u.content, 200)}]`);\n break;\n }\n // Other UnifiedEvent variants (`tool_progress`, `tool_use_summary`,\n // `file`, `text_delta` already handled above) carry no conversational\n // content, so they do not contribute to a chat pair. We intentionally\n // omit a default branch — the explicit user_message variant introduced\n // by the recorder makes the previous \"treat unrecognized as user\" hack\n // unnecessary, and adding new UnifiedEvent variants in the future\n // should require an explicit decision here, not silent inheritance.\n case \"tool_progress\":\n case \"tool_use_summary\":\n case \"file\":\n case \"status\":\n break;\n }\n }\n flushAssistant();\n return pairs;\n}\n",
|
|
6
6
|
"import { execFileSync } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport {\n accessSync,\n chmodSync,\n constants,\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n parseRuntimePort,\n readEnvText,\n resolveFallbackAgent,\n safeRuntimePathSegment,\n} from \"#platform/config-helpers\";\nimport { logger } from \"#platform/logger\";\nimport { type AgentKind, EFFORT_VALUES, type EffortLevel } from \"#types\";\n\nexport function envText(envKey: string): string | undefined {\n return readEnvText(process.env, envKey);\n}\n\nconst HOME = homedir();\n\nfunction resolveStateDir(): string {\n const configured = envText(\"NEGOTIUM_STATE_DIR\");\n if (process.env.NODE_ENV === \"test\" && !configured) {\n throw new Error(\n \"NEGOTIUM_STATE_DIR must be set before importing #platform/config in test processes\",\n );\n }\n return configured ? resolve(configured) : resolve(HOME, \".negotium\");\n}\n\n// new URL(\"../..\", import.meta.url) causes webpack to treat \"../..\" as a module import.\n// Split into fileURLToPath → dirname → resolve to avoid that.\nfunction resolveProjectRoot(): string {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n const packagedRuntime = resolve(moduleDir, \"runtime\");\n if (existsSync(resolve(packagedRuntime, \"src\"))) return packagedRuntime;\n return resolve(moduleDir, \"../..\");\n}\n\nexport const PROJECT_ROOT = resolveProjectRoot();\n\n/** Resolve a dependency executable from either a package-local or hoisted install. */\n/**\n * Names a package-manager shim can carry in `node_modules/.bin`.\n *\n * POSIX gets one extension-less executable. Windows has no execute bit, so the\n * installer writes an extension instead — bun produces `<name>.exe` plus a\n * `<name>.bunx` stub, npm a `.cmd`/`.ps1` pair — and probing only the bare name\n * finds nothing, leaving the resolved path pointing at a file that does not\n * exist.\n */\nfunction dependencyBinNames(name: string): string[] {\n if (process.platform !== \"win32\") return [name];\n return [name, `${name}.exe`, `${name}.cmd`, `${name}.bat`, `${name}.bunx`];\n}\n\nfunction resolveDependencyBin(name: string): string {\n let dir = PROJECT_ROOT;\n while (true) {\n const binDir = resolve(dir, \"node_modules\", \".bin\");\n for (const candidate of dependencyBinNames(name)) {\n const path = resolve(binDir, candidate);\n if (existsSync(path)) return path;\n }\n const parent = dirname(dir);\n // Exhausted: hand back the canonical spelling so the failure names the\n // path that was expected.\n if (parent === dir) return resolve(binDir, name);\n dir = parent;\n }\n}\n\n// Each machine is one negotium node; all node state lives in one dotdir.\n// NEGOTIUM_STATE_DIR overrides (useful for tests and multi-node-on-one-box).\nexport const STATE_DIR = resolveStateDir();\n\nfunction resolveLocalStateDir(envKey: string, stateName: string): string {\n const envValue = envText(envKey);\n if (envValue) return resolve(envValue);\n return resolve(STATE_DIR, stateName);\n}\n\nfunction parsePortEnv(envValue: string | undefined, fallback: number): number {\n return parseRuntimePort(envValue, fallback);\n}\n\nexport const WORKSPACE_DIR = resolveLocalStateDir(\"NEGOTIUM_WORKSPACE_DIR\", \"workspace\");\nexport const TOPIC_WORKSPACE_DIR = resolve(WORKSPACE_DIR, \"topics\");\nexport const SHARED_WIKI_DIR = resolve(WORKSPACE_DIR, \"wiki\");\nexport const CRON_WORKSPACE_DIR = resolve(WORKSPACE_DIR, \"cron\");\nexport const BROWSER_DIR = resolveLocalStateDir(\"NEGOTIUM_BROWSER_DIR\", \"browser\");\nexport const BROWSER_PROFILES_DIR = resolve(BROWSER_DIR, \"profiles\");\nexport const BINARIES_DIR = resolve(STATE_DIR, \"binaries\");\nexport const SECRETS_DIR = resolve(STATE_DIR, \"secrets\");\n// Legacy names remain public, but their durable contents now live under data.\nexport const DM_WORKSPACE_DIR = resolve(STATE_DIR, \"data\", \"dm\");\nexport const SESSION_WORKSPACE_DIR = resolve(STATE_DIR, \"data\", \"sessions\");\n// The Claude Agent SDK ships a platform-matched Claude Code binary. Keep that\n// SDK/CLI pair together by default; only use an external executable when an\n// operator explicitly opts in. This avoids silently pairing an older SDK with\n// a newer globally installed Claude Code release.\nconst CLAUDE_EXECUTABLE_ENV = envText(\"NEGOTIUM_CLAUDE_EXECUTABLE\");\nexport const CLAUDE_EXECUTABLE = CLAUDE_EXECUTABLE_ENV ? resolve(CLAUDE_EXECUTABLE_ENV) : undefined;\n\n// Fallback output language for model-generated prose (topic/channel/manager\n// replies and the archiver's summaries, briefs, articles, completion reply).\n// Defaults to English; set `NEGOTIUM_LANG` to the user's mother tongue (e.g.\n// `Korean`, `ko`). The assistant still mirrors whatever language the user\n// writes in; `NEGOTIUM_MEMORY_LANG` can narrow just the archiver. Fixed system\n// chrome / degraded-path strings emitted by code stay English (can't translate\n// an arbitrary value at runtime).\nexport const DEFAULT_OUTPUT_LANGUAGE = \"English\";\n\nexport function resolveOutputLanguage(): string {\n const raw = envText(\"NEGOTIUM_LANG\")?.trim();\n return raw && raw.length > 0 ? raw : DEFAULT_OUTPUT_LANGUAGE;\n}\n\n/**\n * Suffix the managed Rust helpers carry on this platform.\n *\n * The installers write the binary under its plain name, which on Windows is\n * not executable — the release asset is `browser-rs.exe` and the resolver has\n * to look for exactly that. Empty everywhere else, so POSIX paths are\n * unchanged.\n */\nexport const BINARY_EXTENSION = process.platform === \"win32\" ? \".exe\" : \"\";\n\n/** Browser.rs release tested with this Negotium version. */\nexport const BROWSER_RS_VERSION = \"v0.6.0\";\n/** Require the authenticated listener and the current Browser.rs tool contract. */\nexport const BROWSER_RS_MIN_SECURE_VERSION = \"0.2.1\";\n\nfunction versionAtLeast(actualVersion: string, minimumVersion: string): boolean {\n const actual = actualVersion.split(\".\").map(Number);\n const minimum = minimumVersion.split(\".\").map(Number);\n if (actual.some(Number.isNaN) || minimum.some(Number.isNaN)) return false;\n for (let index = 0; index < minimum.length; index += 1) {\n if ((actual[index] ?? 0) > (minimum[index] ?? 0)) return true;\n if ((actual[index] ?? 0) < (minimum[index] ?? 0)) return false;\n }\n return true;\n}\n\n/**\n * Ceiling for the `--version` probe, not a latency expectation.\n *\n * The probe exists so a wedged binary cannot hang startup; a healthy one\n * answers in milliseconds. At 2s it also failed whenever the machine was merely\n * busy — process startup under a loaded test suite regularly exceeds that —\n * which turned a correctness check into a load measurement and made\n * `resolveBrowserRsBin` intermittently report a perfectly good binary as\n * unusable. Generous enough that only a genuinely stuck process trips it.\n */\nconst BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15_000;\n\nfunction browserRsMeetsMinimumVersion(candidate: string): boolean {\n try {\n const output = execFileSync(candidate, [\"--version\"], {\n encoding: \"utf8\",\n timeout: BROWSER_RS_VERSION_PROBE_TIMEOUT_MS,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n // This module is imported by every CLI invocation, so on Windows the\n // probe blinked a console window each time `negotium` was run. Ignored\n // on POSIX.\n windowsHide: true,\n }).trim();\n const match = output.match(/^browser-rs (\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!match) return false;\n return versionAtLeast(match.slice(1).join(\".\"), BROWSER_RS_MIN_SECURE_VERSION);\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve the preferred Browser.rs engine without consulting PATH. The\n * versioned private location keeps different Negotium releases reproducible\n * and avoids changing a user's global browser-rs installation.\n */\nexport function resolveBrowserRsBin(envValue?: string): string | undefined {\n const override = envValue?.trim();\n if (\n !override &&\n !versionAtLeast(BROWSER_RS_VERSION.replace(/^v/, \"\"), BROWSER_RS_MIN_SECURE_VERSION)\n ) {\n return undefined;\n }\n const candidate = override\n ? resolve(override)\n : resolve(BINARIES_DIR, \"browser-rs\", BROWSER_RS_VERSION, `browser-rs${BINARY_EXTENSION}`);\n try {\n accessSync(candidate, constants.X_OK);\n return browserRsMeetsMinimumVersion(candidate) ? candidate : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Backend that stores documents published by `publish_html` and serves them\n * at `<base>/snippets/<id>`. Unset means the deployment has nowhere to\n * publish, and the publish tools are omitted from the catalog rather than\n * offering a link that cannot be minted.\n */\nexport const SNIPPETS_API_URL = (\n envText(\"NEGOTIUM_SNIPPETS_API_URL\") ??\n envText(\"SNIPPETS_API_URL\") ??\n \"\"\n).replace(/\\/+$/, \"\");\n\nexport const BROWSER_RS_BIN = resolveBrowserRsBin(envText(\"NEGOTIUM_BROWSER_RS_BIN\"));\n\n/** bash-rs release tested with this Negotium version — see apps/negotium/install-bash-rs.mjs. */\nexport const BASH_RS_VERSION = \"v0.1.10\";\n\n/**\n * Resolve the bash-rs binary the same way `resolveBrowserRsBin` resolves\n * Browser.rs: a versioned private location, no PATH lookup, `undefined`\n * (rather than throwing) when it's missing. There is no substitute: the manager\n * throws when a turn tries to prepare background-bash without a binary (see\n * `background-bash/manager.ts`), the turn runner catches that and continues\n * with a reminder that the tools are gone, so background-bash is simply\n * unavailable on a platform without a prebuilt binary.\n */\nexport function resolveBashRsBin(envValue?: string): string | undefined {\n const override = envValue?.trim();\n const candidate = override\n ? resolve(override)\n : resolve(BINARIES_DIR, \"bash-rs\", BASH_RS_VERSION, `bash-rs${BINARY_EXTENSION}`);\n try {\n accessSync(candidate, constants.X_OK);\n return candidate;\n } catch {\n return undefined;\n }\n}\n\nexport const BASH_RS_BIN = resolveBashRsBin(envText(\"NEGOTIUM_BASH_RS_BIN\"));\n\n// Managed Browser.rs terminates MCP transports and security policy itself.\nexport function resolveBrowserMcpBin(envValue?: string): string {\n const override = envValue?.trim();\n if (override) return resolve(override);\n return (\n BROWSER_RS_BIN ??\n resolve(BINARIES_DIR, \"browser-rs\", BROWSER_RS_VERSION, `browser-rs${BINARY_EXTENSION}`)\n );\n}\n\nexport const PLAYWRIGHT_MCP_BIN = resolveBrowserMcpBin(envText(\"NEGOTIUM_BROWSER_MCP_BIN\"));\n\n// --- Browser egress proxy ---\n//\n// On a datacenter host (AWS) the browser's egress IP is a known cloud range,\n// so anti-bot services (Cloudflare, DataDome, reCAPTCHA) challenge or block it\n// far more than a residential IP would. Routing the automation browser through\n// a residential/ISP proxy moves the egress IP out of the datacenter range.\n//\n// Operators set BROWSER_PROXY_URL, e.g. http://user:pass@proxy.host:8080 or\n// socks5://proxy.host:1080. Credentials in the URL are split out because\n// Playwright takes them as separate fields. BROWSER_PROXY_BYPASS is an optional\n// comma-separated no-proxy list (e.g. \"localhost,127.0.0.1,*.internal\").\n//\n// NOTE: Chromium does not support authentication for SOCKS proxies — put\n// credentials only on http/https proxy URLs.\nexport type BrowserProxyConfig = {\n server: string;\n username?: string;\n password?: string;\n bypass?: string;\n};\n\nexport function resolveBrowserProxy(): BrowserProxyConfig | null {\n const raw = envText(\"BROWSER_PROXY_URL\");\n if (!raw) return null;\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n logger.warn({ raw }, \"Ignoring malformed BROWSER_PROXY_URL\");\n return null;\n }\n // Playwright wants the server without embedded credentials.\n const server = `${url.protocol}//${url.host}`;\n const proxy: BrowserProxyConfig = { server };\n if (url.username) proxy.username = decodeURIComponent(url.username);\n if (url.password) proxy.password = decodeURIComponent(url.password);\n const bypass = envText(\"BROWSER_PROXY_BYPASS\");\n if (bypass) proxy.bypass = bypass;\n return proxy;\n}\n\n// --- Node/tsx runtime for the `codex` agent's MCP servers ---\n//\n// codex 0.135's rmcp stdio MCP client cannot reliably complete the initialize\n// handshake with servers spawned via `bun` (the JSON-RPC initialize is\n// dropped/raced and no tools ever reach the model). Pure-node servers connect\n// reliably, so codex turns launch the SAME .ts servers via node + tsx instead\n// of `bun run`. claude/maestro keep using `bun run` (fast, native, unaffected).\n//\n// tsx transpiles .ts on the fly and resolves the `@/*` tsconfig path aliases,\n// but only when it can find the tsconfig — and MCP servers run with cwd set to\n// the user's workspace dir, not PROJECT_ROOT — so we pass TSX_TSCONFIG_PATH\n// explicitly via env. Requires package.json `\"type\": \"module\"` so the servers'\n// top-level `await` loads as ESM under node.\nexport const TSX_BIN = resolveDependencyBin(\"tsx\");\n/**\n * In-process tsx loader used by Node MCP entrypoints (avoids the tsx CLI child\n * process).\n *\n * `node --import` takes a module specifier, not a filesystem path. A POSIX\n * absolute path happens to be a valid one; a Windows `C:\\…` is not — Node reads\n * the drive letter as a URL scheme and refuses it with\n * ERR_UNSUPPORTED_ESM_URL_SCHEME, which took out every tsx-hosted MCP server\n * (the Codex tool surface) at spawn. Hand it a `file://` URL there, and leave\n * the POSIX value exactly as it was.\n */\nconst TSX_LOADER_PATH = createRequire(import.meta.url).resolve(\"tsx\");\nexport const TSX_LOADER =\n process.platform === \"win32\" ? pathToFileURL(TSX_LOADER_PATH).href : TSX_LOADER_PATH;\nexport const TSCONFIG_PATH = resolve(PROJECT_ROOT, \"tsconfig.json\");\n\nexport const SESSION_COMM_SERVER = resolve(PROJECT_ROOT, \"src/mcp/session-comm/server.ts\");\n\nexport const TASK_SERVER = resolve(PROJECT_ROOT, \"src/mcp/task-server.ts\");\nexport const DECISION_SERVER = resolve(PROJECT_ROOT, \"src/mcp/decision-server.ts\");\nexport const CANONICAL_MCP_PROXY_SERVER = resolve(\n PROJECT_ROOT,\n \"src/mcp/canonical-proxy-server.ts\",\n);\n\nexport const WIKI_SERVER = resolve(PROJECT_ROOT, \"src/mcp/wiki-server.ts\");\n\nexport const TOKEN_STATS_SERVER = resolve(PROJECT_ROOT, \"src/mcp/token-stats-server.ts\");\n\nexport const COMPACTION_LOG_SERVER = resolve(PROJECT_ROOT, \"src/mcp/compaction-log-server.ts\");\n\nexport const SYSTEM_HEALTH_SERVER = resolve(PROJECT_ROOT, \"src/mcp/system-health-server.ts\");\n\nexport const AGENT_HEALTH_SERVER = resolve(PROJECT_ROOT, \"src/mcp/agent-health-server.ts\");\n\nexport const VAULT_SERVER = resolve(PROJECT_ROOT, \"src/mcp/vault-server.ts\");\n\nexport const BG_BASH_BASE_PORT = parsePortEnv(process.env.BG_BASH_BASE_PORT, 9700);\nexport const BG_BASH_MAX_PORT = parsePortEnv(process.env.BG_BASH_MAX_PORT, 9799);\n\nfunction safeWorkspaceSegment(value: string, fallback: string): string {\n return safeRuntimePathSegment(value, fallback);\n}\n\n/** Resolve the shared filesystem workspace for an API topic. */\nexport function resolveTopicWorkspaceDir(topicId: string): string {\n return join(TOPIC_WORKSPACE_DIR, safeWorkspaceSegment(topicId, \"topic\"));\n}\n\nexport function isProductionEnv(): boolean {\n return process.env.NODE_ENV === \"production\";\n}\n\nfunction loadOrCreateLocalSecret(\n envKey: string,\n filename: string,\n options: { persistEnvValue?: boolean } = {},\n): string {\n const envValue = envText(envKey);\n const secretFile = resolve(SECRETS_DIR, filename);\n mkdirSync(dirname(secretFile), { recursive: true });\n if (envValue) {\n if (options.persistEnvValue) {\n writeFileSync(secretFile, `${envValue}\\n`, { mode: 0o600 });\n chmodSync(secretFile, 0o600);\n }\n return envValue;\n }\n\n if (existsSync(secretFile)) {\n const stored = readFileSync(secretFile, \"utf-8\").trim();\n if (stored) {\n chmodSync(secretFile, 0o600);\n return stored;\n }\n }\n\n const secret = randomBytes(32).toString(\"base64url\");\n try {\n writeFileSync(secretFile, `${secret}\\n`, { mode: 0o600, flag: \"wx\" });\n return secret;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n const stored = readFileSync(secretFile, \"utf-8\").trim();\n if (!stored) throw new Error(`Secret file exists but is empty: ${secretFile}`);\n chmodSync(secretFile, 0o600);\n return stored;\n }\n}\n\nexport const RUNTIME_MCP_SECRET = loadOrCreateLocalSecret(\n \"RUNTIME_MCP_SECRET\",\n \"runtime-mcp-secret\",\n);\n/** Local bearer token for the loopback node-control API. */\nexport const NODE_CONTROL_TOKEN = loadOrCreateLocalSecret(\n \"NEGOTIUM_CONTROL_TOKEN\",\n \"node-control-token\",\n);\n/**\n * Stable identity of this node's store, minted once and kept across restarts.\n *\n * Deliberately not a secret: it is published in the gateway health response so a\n * host can tell \"the node I recorded a mapping against\" apart from \"whatever is\n * answering on that port today\". Without it, pointing a host at a different node\n * makes every existing mapping look like a topic whose owner withdrew it, and the\n * same topics come back as duplicate rooms. It shares the secrets directory only\n * because that is already where per-install state that must survive restarts\n * lives; the stricter file mode costs nothing.\n */\nexport const NODE_ID = loadOrCreateLocalSecret(\"NEGOTIUM_NODE_ID\", \"node-id\");\nexport const VAULT_MASTER_KEY = loadOrCreateLocalSecret(\n \"NEGOTIUM_VAULT_MASTER_KEY\",\n \"vault-master-key\",\n { persistEnvValue: true },\n);\n// Agent/tool subprocesses inherit process.env. Keep the loaded key in this\n// process only so `env`/`ps` inside an agent workspace cannot reveal it.\ndelete process.env.NEGOTIUM_VAULT_MASTER_KEY;\n\n/** The node's single open port: runtime MCP endpoint + node API. */\nexport const NEGOTIUM_PORT = parseInt(process.env.NEGOTIUM_PORT || \"7777\", 10);\nexport const hostname = process.env.HOSTNAME || \"127.0.0.1\";\n\n// Persistent state (survives restarts, long-lived)\nexport const DATA_DIR = resolveLocalStateDir(\"NEGOTIUM_DATA_DIR\", \"data\");\nexport const LOG_DIR = resolveLocalStateDir(\"NEGOTIUM_LOG_DIR\", \"logs\");\nexport const UPLOADS_DIR = resolve(DATA_DIR, \"uploads\");\nexport const VAULT_DIR = resolve(DATA_DIR, \"vault\");\n// SESSIONS_DB_PATH env override lets tests point the DB singleton at a temp file.\nexport const SESSIONS_DB = process.env.SESSIONS_DB_PATH\n ? resolve(process.env.SESSIONS_DB_PATH)\n : resolve(DATA_DIR, \"sessions.db\");\nexport const DEBUG_FILE = resolve(DATA_DIR, \"debug-users.json\");\nexport const USERS_LOG_DIR = resolve(DATA_DIR, \"users\");\n\n// Runtime IPC queues (transient, safe to clear on restart)\n/** @deprecated Use the runtime layout name; NEGOTIUM_RUN_DIR remains a compatibility override. */\nexport const RUN_DIR = resolveLocalStateDir(\"NEGOTIUM_RUN_DIR\", \"runtime\");\nexport const RUNTIME_DIR = RUN_DIR;\nexport const PROGRESS_DIR = resolve(RUN_DIR, \"progress\");\nexport const DM_CMD_DIR = resolve(RUN_DIR, \"dm-commands\");\nexport const DM_RESP_DIR = resolve(RUN_DIR, \"dm-responses\");\nexport const SESSION_INBOX_DIR = resolve(RUN_DIR, \"session-inbox\");\nexport const SESSION_ASKS_DIR = resolve(RUN_DIR, \"session-asks\");\n/**\n * Passed to `bash-rs` as `BASHRS_SPILL_ROOT`. Each job gets a subdirectory\n * here (`{bash_id}/meta.json`, `result.json`, `stdout.log`, `stderr.log`) —\n * see bash-rs-mcp's `journal.rs`. `runtime/bashrs-completions.ts` watches\n * this directory and turns `result.json` into a session-inbox `tell`. The\n * retired TypeScript server used to write one directly instead.\n */\nexport const BASHRS_SPILL_ROOT = resolve(RUN_DIR, \"bashrs\");\nexport const PLAYWRIGHT_BASE_PORT = parsePortEnv(process.env.PLAYWRIGHT_BASE_PORT, 9100);\nexport const PLAYWRIGHT_MAX_PORT = parsePortEnv(process.env.PLAYWRIGHT_MAX_PORT, 9499);\nexport const PLAYWRIGHT_PORTS_DIR = resolve(RUN_DIR, \"playwright-ports\");\nmkdirSync(STATE_DIR, { recursive: true });\nmkdirSync(DATA_DIR, { recursive: true });\nmkdirSync(UPLOADS_DIR, { recursive: true });\nmkdirSync(VAULT_DIR, { recursive: true, mode: 0o700 });\nmkdirSync(LOG_DIR, { recursive: true });\nmkdirSync(PROGRESS_DIR, { recursive: true });\nmkdirSync(DM_CMD_DIR, { recursive: true });\nmkdirSync(DM_RESP_DIR, { recursive: true });\nmkdirSync(SESSION_INBOX_DIR, { recursive: true });\nmkdirSync(SESSION_ASKS_DIR, { recursive: true });\nmkdirSync(PLAYWRIGHT_PORTS_DIR, { recursive: true });\nmkdirSync(WORKSPACE_DIR, { recursive: true });\nmkdirSync(TOPIC_WORKSPACE_DIR, { recursive: true });\nmkdirSync(SHARED_WIKI_DIR, { recursive: true });\nmkdirSync(CRON_WORKSPACE_DIR, { recursive: true });\nmkdirSync(DM_WORKSPACE_DIR, { recursive: true });\nmkdirSync(SESSION_WORKSPACE_DIR, { recursive: true });\nmkdirSync(BROWSER_DIR, { recursive: true });\nmkdirSync(BROWSER_PROFILES_DIR, { recursive: true });\nmkdirSync(BINARIES_DIR, { recursive: true });\nmkdirSync(SECRETS_DIR, { recursive: true, mode: 0o700 });\n\n/** Stale threshold for active-query state files (crash recovery) */\nexport const ACTIVE_QUERY_STALE_MS = 10 * 60 * 1000; // 10 minutes\n\nexport const AGENTS_PROMPTS_DIR = resolve(PROJECT_ROOT, \"src/prompts/agents\");\nexport const RESOURCES_DIR = resolve(PROJECT_ROOT, \"src/resources\");\n\n/** Returns process.env without CLAUDECODE, to prevent nested claude-code detection in subprocesses. */\nexport function getCleanEnv(): NodeJS.ProcessEnv {\n const env = { ...process.env };\n delete env.CLAUDECODE;\n return env;\n}\n\n/**\n * How an absolute path can start.\n *\n * A POSIX root (`/`) is not the only form once the runtime also runs on\n * Windows, where the same tag carries `C:\\…` or a `\\\\server\\share` UNC path.\n * Anchoring on `/` alone silently dropped every Windows attachment: the tag\n * stayed in the visible text and no file was ever sent.\n */\nconst ABSOLUTE_PATH_PREFIX = String.raw`(?:[A-Za-z]:[\\\\/]|\\\\\\\\|\\/)`;\n\nexport const FILE_EXTENSIONS_REGEX = new RegExp(\n `(?:${ABSOLUTE_PATH_PREFIX}[^\\\\s\"'<>|*?[\\\\]]+\\\\.(?:png|jpg|jpeg|gif|webp|svg|pdf|csv|xlsx|xls|json|txt|md|html|zip|py|js|ts|tsx|jsx|css|xml|yaml|yml|docx|pptx))`,\n \"gi\",\n);\n\nexport const FILE_TAG_REGEX = new RegExp(`\\\\[FILE:(${ABSOLUTE_PATH_PREFIX}[^\\\\]]+)\\\\]`, \"gi\");\n\n// Canonical Claude model IDs — update here when Anthropic releases new versions\nexport const MODEL_SONNET = \"claude-sonnet-5\";\nexport const MODEL_OPUS = \"claude-opus-5\";\nexport const MODEL_HAIKU = \"claude-haiku-4-5-20251001\";\nexport const MODEL_FABLE = \"claude-fable-5-1\"; // Mythos-class, Fable 5.1 announced 2026-09-01 (was claude-fable-5)\n\n// DeepSeek V4 (released 2026-04-24). API is OpenAI-compatible at\n// https://api.deepseek.com/v1/chat/completions; thinking mode is enabled via\n// `extra_body.thinking.type` + `reasoning_effort`. Legacy `deepseek-chat` /\n// `deepseek-reasoner` are deprecated 2026-07-24.\nexport const MODEL_DEEPSEEK_V4_PRO = \"deepseek-v4-pro\";\nexport const MODEL_DEEPSEEK_V4_FLASH = \"deepseek-v4-flash\";\n\n// Single agent + model default for the whole node. DEFAULT_* remains a legacy alias.\nexport const FALLBACK_AGENT: AgentKind = resolveFallbackAgent(process.env);\nexport const FALLBACK_MODEL = envText(\"FALLBACK_MODEL\") ?? envText(\"DEFAULT_MODEL\");\n\n/**\n * Effort used when a caller (or an archiver assignment) names a model but no\n * effort. Deliberately one fixed node-wide value instead of each agent's\n * registry default: a model-derived agent switch would otherwise move effort —\n * and therefore cost — without anyone asking for it.\n */\nexport const DEFAULT_TOPIC_EFFORT: EffortLevel = ((): EffortLevel => {\n const raw = envText(\"NEGOTIUM_DEFAULT_EFFORT\")?.toLowerCase();\n return raw && (EFFORT_VALUES as readonly string[]).includes(raw)\n ? (raw as EffortLevel)\n : \"medium\";\n})();\n\n// ── External tool binaries + media pipeline env ───────────────────\n// (src/media/* 에서 사용. 미설정 시 fallback 의미는 기존 그대로:\n// FFMPEG_BIN은 text-extractor에서 필수(undefined면 spawn 시점 실패),\n// video.ts에서는 PATH의 ffmpeg/ffprobe로 fallback.)\nexport const FFMPEG_BIN = envText(\"FFMPEG_BIN\");\nexport const FFPROBE_BIN = envText(\"FFPROBE_BIN\");\nexport const PYTHON_BIN = envText(\"PYTHON_BIN\") ?? \"python3\";\nexport const FASTER_WHISPER_WRAPPER =\n envText(\"FASTER_WHISPER_WRAPPER\") ?? resolve(PROJECT_ROOT, \"scripts/faster-whisper-wrapper.py\");\nexport const WHISPER_MODEL = envText(\"WHISPER_MODEL_FILE\") ?? \"turbo\";\nexport const TESSERACT_BIN = envText(\"TESSERACT_BIN\") ?? \"tesseract\";\nexport const PDFTOTEXT_BIN = envText(\"PDFTOTEXT_BIN\") ?? \"pdftotext\";\n\n// ── Whisper backend selection ──────────────────────────────────────\n// Different hosts want different whisper runtimes: Apple Silicon Macs get\n// real acceleration from mlx-whisper (see clawgram's transcribe.ts, which\n// this mirrors), while Linux/Ubuntu hubs have no MLX and use the CPU-friendly\n// faster-whisper wrapper instead. Both CLIs accept the same\n// `INPUT --model M --language L --output-dir D --output-format txt` shape\n// and write `{basename}.txt`, so extractFromAudio only needs to pick which\n// binary/args to use — no per-backend parsing logic.\nexport type WhisperBackend = \"faster-whisper\" | \"mlx-whisper\";\nfunction resolveWhisperBackend(): WhisperBackend {\n return envText(\"WHISPER_BACKEND\") === \"mlx-whisper\" ? \"mlx-whisper\" : \"faster-whisper\";\n}\nexport const WHISPER_BACKEND = resolveWhisperBackend();\n/** Path to the `mlx_whisper` CLI (only used when WHISPER_BACKEND=mlx-whisper). */\nexport const MLX_WHISPER_BIN = envText(\"MLX_WHISPER_BIN\");\n/** mlx-whisper model id, e.g. \"mlx-community/whisper-large-v3-turbo\".\n *\n * Deliberately does NOT fall back to WHISPER_MODEL: that env defaults to the\n * bare alias \"turbo\", which faster-whisper's own model-name normalization\n * accepts but mlx_whisper's `--model` does not — it expects a full\n * HuggingFace repo id and otherwise fails hard with a 401\n * RepositoryNotFoundError trying to resolve \"turbo\" as a repo. Confirmed by\n * actually running mlx_whisper with each value while wiring up the\n * mlx-whisper hub in production. */\nexport const WHISPER_MODEL_MLX =\n envText(\"WHISPER_MODEL_MLX\") ?? \"mlx-community/whisper-large-v3-turbo\";\n\n// Max tell_session relay depth from origin user. ask_session forks reset to\n// depth=0, so this only caps tell_session chains. Override via MAX_TELL_DEPTH\n// (positive int); defaults to 20 when unset or invalid.\nconst _envMaxTellDepth = Number.parseInt(process.env.MAX_TELL_DEPTH ?? \"\", 10);\nexport const MAX_TELL_DEPTH =\n Number.isInteger(_envMaxTellDepth) && _envMaxTellDepth > 0 ? _envMaxTellDepth : 20;\n\n/** Codex CLI auth file. 호출 시점에 env를 읽는다 — 테스트가 런타임에\n * NEGOTIUM_CODEX_AUTH_FILE을 바꾸므로 모듈 로드 상수로 만들면 안 된다. */\nexport function codexAuthFilePath(): string {\n return (\n process.env.NEGOTIUM_CODEX_AUTH_FILE ||\n join(process.env.CODEX_HOME || join(homedir(), \".codex\"), \"auth.json\")\n );\n}\n\n// System defaults moved to per-agent registries\n// (`src/agents/{claude,codex}-registry.ts`). Read via\n// `getRegistry(agent).defaultModel` / `.defaultEffort`.\n\n// MCP server builders -> src/platform/mcp-config.ts\n",
|
|
@@ -22,17 +22,20 @@
|
|
|
22
22
|
"import { createHmac } from \"node:crypto\";\n\nexport function browserOwnerCapability(capability: string, owner: string): string {\n return createHmac(\"sha256\", capability).update(owner).digest(\"hex\");\n}\n",
|
|
23
23
|
"import type { AgentKind } from \"#types\";\n\nimport { browserOwnerCapability } from \"./capability\";\n\nexport const CODEX_BROWSER_CAPABILITY_ENV = \"NEGOTIUM_BROWSER_CAPABILITY\";\n\n/** Build the authenticated Browser.rs transport for one agent turn. */\nexport function buildPlaywrightMcpTransport(\n port: number,\n owner: string,\n capability: string,\n agent?: AgentKind,\n): Record<string, unknown> {\n const query = new URLSearchParams({ owner });\n const ownerCapability = browserOwnerCapability(capability, owner);\n\n if (agent === \"codex\") {\n return {\n url: `http://127.0.0.1:${port}/mcp?${query}`,\n env_http_headers: { \"X-Browser-Capability\": CODEX_BROWSER_CAPABILITY_ENV },\n };\n }\n if (agent === \"maestro\") {\n return {\n type: \"http\" as const,\n url: `http://127.0.0.1:${port}/mcp?${query}`,\n headers: { \"X-Browser-Capability\": ownerCapability },\n };\n }\n return {\n type: \"sse\" as const,\n url: `http://127.0.0.1:${port}/sse?${query}`,\n headers: { \"X-Browser-Capability\": ownerCapability },\n };\n}\n",
|
|
24
24
|
"import { logger } from \"#platform/logger\";\nimport type { AgentKind } from \"#types\";\n\nexport interface CronSessionRef {\n sessionId: string;\n ownerUserId: string;\n}\n\nexport type CronSessionProvider = (topicId: string, agent: AgentKind) => CronSessionRef | null;\n\nconst providers: Array<{ provider: CronSessionProvider }> = [];\n\nexport function getRegisteredCronSession(topicId: string, agent: AgentKind): CronSessionRef | null {\n const registration = providers.at(-1);\n if (!registration) return null;\n try {\n return registration.provider(topicId, agent);\n } catch (error) {\n logger.warn({ err: error, topicId, agent }, \"cron-session: provider lookup failed\");\n return null;\n }\n}\n\n/** Register the optional Cron module's session lookup without coupling core to the module. */\nexport function registerCronSessionProvider(next: CronSessionProvider): () => void {\n const registration = { provider: next };\n providers.push(registration);\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n const index = providers.indexOf(registration);\n if (index >= 0) providers.splice(index, 1);\n };\n}\n",
|
|
25
|
-
"import { accessSync, constants as fsConstants } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { canonicalMcpBridgeEnv } from \"#mcp/canonical-bridge-config\";\nimport {\n buildHostedMcpSpec,\n buildRuntimeMcpSpec,\n type HostedMcpSurface,\n RUNTIME_MCP_KEY,\n} from \"#mcp/runtime-spec\";\nimport { peerSessionBridgeIpcEnv } from \"#mcp/session-comm/bridge-ipc-config\";\nimport { bgBashContextCapability } from \"#platform/background-bash/manager\";\nimport {\n AGENT_HEALTH_SERVER,\n CANONICAL_MCP_PROXY_SERVER,\n DECISION_SERVER,\n envText,\n FALLBACK_AGENT,\n resolveTopicWorkspaceDir,\n SESSION_COMM_SERVER,\n SYSTEM_HEALTH_SERVER,\n TASK_SERVER,\n TOKEN_STATS_SERVER,\n TSCONFIG_PATH,\n TSX_LOADER,\n VAULT_SERVER,\n WIKI_SERVER,\n} from \"#platform/config\";\nimport { logger } from \"#platform/logger\";\nimport {\n classifyForumMcpServers,\n commonRuntimeMcpPolicy,\n type RuntimeMcpScope,\n} from \"#platform/mcp-catalog-policy\";\nimport { browserOwnerCapability } from \"#platform/playwright/capability\";\nimport {\n buildPlaywrightMcpTransport,\n CODEX_BROWSER_CAPABILITY_ENV,\n} from \"#platform/playwright/mcp-transport\";\nimport { getRegisteredCronSession } from \"#runtime/cron-sessions\";\nimport type { HostMcpServerSpec } from \"#runtime-gateway\";\nimport type { AgentKind, AgentQueryOptions, PeerRuntimeBridgeContext } from \"#types\";\n\nexport type { RuntimeMcpScope } from \"#platform/mcp-catalog-policy\";\n\n/**\n * Build the stdio transport spec for a Otium MCP server entry.\n *\n * claude/maestro launch the .ts server directly with `bun run` (fast, native\n * TypeScript + bun:sqlite). codex CANNOT — codex 0.135's rmcp stdio client\n * fails to handshake with bun-spawned servers (initialize is dropped/raced, so\n * no tools reach the model), while pure-node servers connect reliably. So for\n * the `codex` agent we launch the SAME server file via node + tsx, passing the\n * tsconfig explicitly (servers run with cwd ≠ PROJECT_ROOT, so tsx can't find\n * it on its own) so `@/*` path aliases resolve. Per-turn agent-aware config\n * means switching agents mid-topic just works: each turn re-spawns with the\n * right runtime.\n */\nexport function buildStdioMcpServer(\n agent: AgentKind | undefined,\n serverFile: string,\n serverArgs: string[],\n env?: Record<string, string>,\n): Record<string, unknown> {\n if (agent === \"codex\") {\n return {\n command: \"node\",\n args: [\"--import\", TSX_LOADER, serverFile, ...serverArgs],\n // Merged onto codex's inherited env (not a replacement) — verified.\n env: { TSX_TSCONFIG_PATH: TSCONFIG_PATH, ...env },\n };\n }\n return {\n command: \"bun\",\n args: [\"run\", serverFile, ...serverArgs],\n ...(env ? { env } : {}),\n };\n}\n\nfunction useHostedBuiltinMcp(): boolean {\n return envText(\"NEGOTIUM_BUILTIN_MCP_TRANSPORT\") !== \"stdio\";\n}\n\nfunction buildBuiltinMcpServer(\n surface: HostedMcpSurface,\n ctx: RuntimeMcpBuildContext,\n stdio: () => Record<string, unknown>,\n): Record<string, unknown> {\n if (!useHostedBuiltinMcp()) return stdio();\n const agent = ctx.agent ?? FALLBACK_AGENT;\n return buildHostedMcpSpec(agent, surface, {\n userId: ctx.userId,\n topicTitle: ctx.session,\n ...(ctx.topicId ? { topicId: ctx.topicId } : {}),\n ...(ctx.queryId ? { queryId: ctx.queryId } : {}),\n ...(ctx.wikiTopicId ? { wikiTopicId: ctx.wikiTopicId } : {}),\n ...(ctx.subagentParentTopicId ? { subagentParentTopicId: ctx.subagentParentTopicId } : {}),\n ...(ctx.threadRootId ? { threadRootId: ctx.threadRootId } : {}),\n cwd: ctx.cwd ?? (ctx.topicId ? resolveTopicWorkspaceDir(ctx.topicId) : process.cwd()),\n agent,\n ...(ctx.model ? { model: ctx.model } : {}),\n ...(ctx.depth !== undefined ? { depth: ctx.depth } : {}),\n ...(ctx.silent !== undefined ? { silent: ctx.silent } : {}),\n ...(ctx.peerBridge ? { peerBridge: ctx.peerBridge } : {}),\n });\n}\n\n// --- Playwright unavailable notifier + per-turn state ---\n//\n// When the playwright manager fails to allocate a long-lived MCP port,\n// the catalog used to fall back to a per-turn stdio chromium that ran as\n// a child of the agent CLI subprocess — which meant Chromium was bound\n// to the agent's process tree and died on cascade-kill. We now skip the\n// browser entry entirely (the playwright entry is omitted from the\n// catalog for that turn) AND surface the gap two ways:\n//\n// 1. `notifyPlaywrightUnavailable` — fire-and-forget callback for the host\n// (telegram bot) to push an alert to the current topic. Throttled\n// per (userId, topic) with a 5-minute cooldown so a flaky\n// manager doesn't spam the chat. Per-process state — restart clears.\n//\n// 2. `consumePlaywrightUnavailable` — the system-prompt builder reads\n// this flag to add an explicit \"Playwright unavailable this turn\"\n// reminder to the agent's user message, so the model knows to\n// route around browser tools instead of hallucinating a call to a\n// tool that was silently removed from the schema list.\n\ntype PlaywrightUnavailableContext = {\n userId: string;\n topic: string | undefined;\n agent: AgentKind | undefined;\n};\n\ntype PlaywrightUnavailableNotifier = (ctx: PlaywrightUnavailableContext) => void;\n\nlet _playwrightUnavailableNotifier: PlaywrightUnavailableNotifier | undefined;\nconst _playwrightUnavailableLastNotifiedAt = new Map<string, number>();\nconst _PLAYWRIGHT_UNAVAILABLE_COOLDOWN_MS = 5 * 60_000;\n\nconst _playwrightUnavailableThisTurn = new Set<string>();\n\nfunction _playwrightUnavailableKey(userId: string, topic: string | undefined): string {\n return `${userId}:${topic ?? \"\"}`;\n}\n\n/**\n * Register the host's \"playwright unavailable\" alert sink. Called once at bot\n * startup. Idempotent — last writer wins.\n */\nexport function setPlaywrightUnavailableNotifier(cb: PlaywrightUnavailableNotifier): void {\n _playwrightUnavailableNotifier = cb;\n}\n\n/**\n * Mark the current turn as missing long-lived Playwright and notify the host.\n * The playwright catalog entry calls this when it is built without a port, but\n * route-level callers can call it earlier after ensurePlaywright fails so the\n * system prompt for the same turn can include the unavailable reminder.\n */\nexport function markPlaywrightUnavailable(ctx: PlaywrightUnavailableContext): void {\n _markPlaywrightUnavailable(ctx);\n}\n\nfunction _markPlaywrightUnavailable(ctx: PlaywrightUnavailableContext): void {\n // Mark unavailable for the next system-prompt build, regardless of\n // notifier presence (the model-side reminder must always fire so the\n // agent doesn't try to call a missing tool).\n _playwrightUnavailableThisTurn.add(_playwrightUnavailableKey(ctx.userId, ctx.topic));\n\n if (!_playwrightUnavailableNotifier) return;\n const key = _playwrightUnavailableKey(ctx.userId, ctx.topic);\n const now = Date.now();\n const last = _playwrightUnavailableLastNotifiedAt.get(key) ?? 0;\n if (now - last < _PLAYWRIGHT_UNAVAILABLE_COOLDOWN_MS) return;\n _playwrightUnavailableLastNotifiedAt.set(key, now);\n try {\n _playwrightUnavailableNotifier(ctx);\n } catch (err) {\n logger.warn({ err }, \"playwright unavailable notifier threw\");\n }\n}\n\n/**\n * Read + clear the \"playwright unavailable this turn\" flag for a\n * (user, group, topic). Used by the system-prompt builder right before\n * the agent query starts. Single consumer pattern — calling more than\n * once per turn returns `false` for the second caller (intended; the\n * reminder only needs to ride one prompt).\n */\nexport function consumePlaywrightUnavailable(userId: string, topic: string | undefined): boolean {\n const key = _playwrightUnavailableKey(userId, topic);\n if (!_playwrightUnavailableThisTurn.has(key)) return false;\n _playwrightUnavailableThisTurn.delete(key);\n return true;\n}\n\n/**\n * Single source of truth for MCP server registration.\n *\n * Each entry declares which scopes it participates in (`dm`, `forum`, `fork`, `cron`)\n * and how to build its spawn config given a context. Public helpers\n * (`getDmMcpServers`, `getForumMcpServers`, `getForkMcpServers`) and the\n * derived forum-name views read from this catalog plus the node-assigned\n * manifest overlay installed below. Adding a built-in MCP server remains a\n * one-line append here instead of touching three places.\n *\n * Conventions:\n * - `scopes` lists every scope the server should appear in by default.\n * - `forumRequired: true` keeps the server even when a forum topic\n * restricts the enabled list via `configure_mcp` (forum scope only).\n * - `build(ctx)` returns the raw transport config (Claude-SDK shape).\n * Codex callers funnel through `toCodexMcpServers` separately.\n *\n * Insertion order is preserved by `Object.entries`, which determines the\n * order of server names in user-facing displays.\n */\n\nexport interface RuntimeMcpBuildContext {\n userId: string;\n /** Product actor identity when it differs from the execution principal. */\n actorUserId?: string;\n /** Vault namespace when credentials belong to a different principal. */\n vaultUserId?: string;\n /** \"dm\" for DM scope, topic/session name for forum/fork. */\n session: string;\n /** REST/WS topic id when known. Prefer for authorization/scope checks. */\n topicId?: string;\n /** Direct parent topic id when the current topic is a subagent room. */\n subagentParentTopicId?: string;\n /** REST/WS query id when known. */\n queryId?: string;\n /** Topic id whose wiki memory should be read/written. */\n wikiTopicId?: string;\n agent?: AgentKind;\n cwd?: string;\n model?: string;\n currentUserPrompt?: string;\n depth?: number;\n playwrightPort?: number;\n playwrightCapability?: string;\n bgBashPort?: number;\n autoContinue?: boolean;\n visualTools?: boolean;\n fileDeliveryTools?: boolean;\n silent?: boolean;\n /** Thread this turn answers inside; forwarded to the runtime MCP context. */\n threadRootId?: string;\n peerBridge?: PeerRuntimeBridgeContext;\n}\n\nexport interface RuntimeMcpCatalogEntry {\n scopes: readonly RuntimeMcpScope[];\n /** Forum scope only: cannot be removed via the enabled whitelist. */\n forumRequired?: boolean;\n /**\n * Returns the raw transport spec (Claude-SDK shape), or `null` to\n * signal \"this server is unavailable for this turn — omit it from the\n * catalog entirely.\" Used by the playwright entry when the manager\n * cannot provide a long-lived port.\n */\n build(ctx: RuntimeMcpBuildContext): Record<string, unknown> | null;\n}\n\n// --- Playwright transport builders ---\n\nexport { browserOwnerCapability, buildPlaywrightMcpTransport, CODEX_BROWSER_CAPABILITY_ENV };\n\nexport function browserOwnerForContext(ctx: {\n userId?: string;\n session?: string;\n topicId?: string;\n}): string | undefined {\n if (ctx.topicId) return `topic:${ctx.topicId}`;\n if (ctx.userId && ctx.session) return `user:${ctx.userId}:${ctx.session}`;\n return undefined;\n}\n\nfunction longLivedHttpMcp(agent: AgentKind | undefined, port: number) {\n return agent === \"codex\"\n ? { url: `http://127.0.0.1:${port}/mcp` }\n : { type: \"sse\" as const, url: `http://127.0.0.1:${port}/sse` };\n}\n\n// cua-rs implements Streamable HTTP only; unlike browser-rs, it does not\n// expose the legacy SSE endpoint. The port is installed by the node-owned\n// process manager once its singleton is ready.\nlet cuaRsMcpPort: number | undefined;\n// cua-rs 0.8.0 requires `Authorization: Bearer` on /mcp, because loopback is not\n// an authorization boundary -- any local process, a web page included, could\n// otherwise drive the whole desktop. The node picks the token, hands it to the\n// child as CUA_HTTP_TOKEN, and publishes it here so turns can present it. Kept\n// beside the port because they are one fact: without both, the URL is useless.\nlet cuaRsMcpToken: string | undefined;\n\nexport function setCuaRsMcpPort(port: number | undefined, token?: string): void {\n if (port !== undefined && (!Number.isInteger(port) || port < 1 || port > 65_535)) {\n throw new Error(`invalid cua-rs MCP port: ${port}`);\n }\n cuaRsMcpPort = port;\n cuaRsMcpToken = port === undefined ? undefined : token;\n}\n\nfunction cuaRsHttpMcp(agent: AgentKind | undefined, port: number, token: string | undefined) {\n const url = `http://127.0.0.1:${port}/mcp`;\n // No token means an older cua-rs that does not ask for one. Sending the header\n // anyway would be harmless, but omitting it keeps the config honest about what\n // the running server actually requires.\n const headers = token ? { Authorization: `Bearer ${token}` } : undefined;\n // The shape is otherwise unchanged from before the token existed, including\n // `type` for codex: only the header field is added, and only when there is a\n // token to put in it. Codex spells that field `http_headers`.\n const base = { type: \"http\" as const, url };\n if (!headers) return base;\n return agent === \"codex\" ? { ...base, http_headers: headers } : { ...base, headers };\n}\n\nfunction backgroundBashTransport(\n agent: AgentKind | undefined,\n port: number,\n userId: string,\n topic: string,\n) {\n const capability = bgBashContextCapability(userId, topic);\n const headers = {\n \"X-Background-Bash-User\": userId,\n \"X-Background-Bash-Topic\": topic,\n \"X-Background-Bash-Capability\": capability,\n };\n if (agent === \"codex\") return { url: `http://127.0.0.1:${port}/mcp`, http_headers: headers };\n if (agent === \"maestro\") {\n const query = new URLSearchParams({ user: userId, topic, capability });\n return { type: \"sse\" as const, url: `http://127.0.0.1:${port}/sse?${query}` };\n }\n return { type: \"sse\" as const, url: `http://127.0.0.1:${port}/sse`, headers };\n}\n\n// --- Catalog ---\n\nconst MCP_CATALOG: Record<string, RuntimeMcpCatalogEntry> = {\n playwright: {\n ...commonRuntimeMcpPolicy(\"playwright\"),\n build({ userId, session, topicId, playwrightPort, playwrightCapability, agent }) {\n // Codex and Maestro use Streamable HTTP while Claude uses SSE. Both\n // transports terminate at the same long-lived browser/profile server.\n if (playwrightPort && playwrightCapability) {\n const owner = browserOwnerForContext({ userId, session, topicId });\n if (!owner) return null;\n return buildPlaywrightMcpTransport(playwrightPort, owner, playwrightCapability, agent);\n }\n // No port available — the playwright manager could not allocate one\n // for this turn. The previous behavior was to fall back to a per-turn\n // stdio chromium, but that made Chromium a child of the agent CLI\n // process tree, so cascade-kill on agent exit took the browser down\n // with it (visible in pm2 as \"Chromium died with claude\"). We now\n // omit the playwright entry from this turn's catalog AND fire two\n // side-effects:\n // 1. notify the host so it can push an alert into the current\n // topic (rate-limited 5min per scope key);\n // 2. mark the (user, topic) as \"playwright unavailable\n // this turn\" so the system-prompt builder can tell the model\n // explicitly, instead of letting the model hallucinate a call\n // to a tool whose schema silently vanished.\n _markPlaywrightUnavailable({\n userId,\n topic: session,\n agent,\n });\n return null;\n },\n },\n [RUNTIME_MCP_KEY]: {\n ...commonRuntimeMcpPolicy(\"runtime\"),\n build({\n userId,\n actorUserId,\n session,\n topicId,\n queryId,\n agent,\n cwd,\n model,\n currentUserPrompt,\n autoContinue,\n visualTools,\n fileDeliveryTools,\n threadRootId,\n peerBridge,\n }) {\n if (!topicId || !agent) return null;\n return buildRuntimeMcpSpec(agent, {\n // Runtime tools mutate node-owned state, so authorization stays bound\n // to the canonical execution principal. Keep the product-side human\n // actor separately for attribution instead of replacing the identity\n // that appears in this node's topic participant roster.\n userId,\n ...(actorUserId ? { actorUserId } : {}),\n topicId,\n topicTitle: session,\n queryId,\n cwd: cwd ?? resolveTopicWorkspaceDir(topicId),\n agent,\n model,\n currentUserPrompt,\n autoContinue,\n visualTools,\n fileDeliveryTools,\n ...(threadRootId ? { threadRootId } : {}),\n peerBridge,\n });\n },\n },\n \"token-stats\": {\n ...commonRuntimeMcpPolicy(\"token-stats\"),\n build(ctx) {\n return buildBuiltinMcpServer(\"token-stats\", ctx, () =>\n buildStdioMcpServer(ctx.agent, TOKEN_STATS_SERVER, [`--user-id=${ctx.userId}`]),\n );\n },\n },\n // Otium-owned shared task system. This is the only authoritative task/todo\n // surface across claude/codex/maestro; provider-native task stores are\n // blocked or ignored because they do not survive agent switches.\n task: {\n ...commonRuntimeMcpPolicy(\"task\"),\n build(ctx) {\n const { userId, session, topicId, queryId, agent, peerBridge } = ctx;\n if (peerBridge) {\n if (!topicId || !queryId) return null;\n const env = canonicalMcpBridgeEnv({\n surface: \"task\",\n userId,\n topicId,\n queryId,\n peerBridge,\n });\n return env\n ? buildStdioMcpServer(agent, CANONICAL_MCP_PROXY_SERVER, [\"--surface=task\"], env)\n : null;\n }\n const args = [`--user-id=${userId}`, `--topic=${session}`];\n if (topicId) args.push(`--topic-id=${topicId}`);\n return buildBuiltinMcpServer(\"task\", ctx, () =>\n buildStdioMcpServer(agent, TASK_SERVER, args),\n );\n },\n },\n decision: {\n ...commonRuntimeMcpPolicy(\"decision\"),\n build(ctx) {\n const { userId, session, topicId, queryId, agent, model, peerBridge } = ctx;\n if (peerBridge) {\n if (!topicId || !queryId) return null;\n const env = canonicalMcpBridgeEnv({\n surface: \"decision\",\n userId,\n topicId,\n queryId,\n peerBridge,\n });\n return env\n ? buildStdioMcpServer(agent, CANONICAL_MCP_PROXY_SERVER, [\"--surface=decision\"], env)\n : null;\n }\n const args = [\n `--user-id=${userId}`,\n `--topic=${session}`,\n `--agent=${agent ?? FALLBACK_AGENT}`,\n ];\n if (topicId) args.push(`--topic-id=${topicId}`);\n if (model) args.push(`--model=${model}`);\n return buildBuiltinMcpServer(\"decision\", ctx, () =>\n buildStdioMcpServer(agent, DECISION_SERVER, args),\n );\n },\n },\n \"session-comm\": {\n // Exposed in `manager` scope as well so the General-topic manager agent\n // can wake fresh-created topics via tell_session/ask_session right after\n // create_topic. Without this, a newly-created topic would stay in the\n // \"fresh-start ready\" state until the user manually visits it.\n ...commonRuntimeMcpPolicy(\"session-comm\"),\n build(ctx) {\n const {\n userId,\n session,\n topicId,\n subagentParentTopicId,\n agent,\n depth = 0,\n silent,\n threadRootId,\n peerBridge,\n } = ctx;\n const effectiveAgent = agent ?? FALLBACK_AGENT;\n const cronSessionId = topicId\n ? getRegisteredCronSession(topicId, effectiveAgent)?.sessionId\n : undefined;\n const args = [\n `--user-id=${userId}`,\n `--topic=${session}`,\n ...(topicId ? [`--topic-id=${topicId}`] : []),\n ...(subagentParentTopicId ? [`--subagent-parent-topic-id=${subagentParentTopicId}`] : []),\n `--depth=${depth}`,\n `--agent=${effectiveAgent}`,\n ...(cronSessionId ? [`--cron-session-id=${cronSessionId}`] : []),\n ...(silent ? [\"--reply-only=true\"] : []),\n // Turn-scoped, like `--peer-host-query-id`: this config is rebuilt for\n // every turn, so an `ask_session` raised inside a thread can record\n // where its answer belongs.\n ...(threadRootId ? [`--thread-root-id=${threadRootId}`] : []),\n ...(peerBridge ? [`--peer-host-query-id=${peerBridge.hostQueryId}`] : []),\n ];\n return buildBuiltinMcpServer(\"session-comm\", ctx, () =>\n buildStdioMcpServer(\n effectiveAgent,\n SESSION_COMM_SERVER,\n args,\n peerBridge ? peerSessionBridgeIpcEnv() : undefined,\n ),\n );\n },\n },\n wiki: {\n ...commonRuntimeMcpPolicy(\"wiki\"),\n build(ctx) {\n const { userId, session, topicId, queryId, wikiTopicId, agent, peerBridge } = ctx;\n if (peerBridge) {\n if (!topicId || !queryId) return null;\n const env = canonicalMcpBridgeEnv({\n surface: \"wiki\",\n userId,\n topicId,\n queryId,\n peerBridge,\n });\n return env\n ? buildStdioMcpServer(agent, CANONICAL_MCP_PROXY_SERVER, [\"--surface=wiki\"], env)\n : null;\n }\n const args = [`--user-id=${userId}`];\n if (topicId) args.push(`--current-topic-id=${topicId}`);\n // Prefer the REST topic id so wiki_write writes filenames and SQLite\n // briefs keyed the same way the topic wiki API reads them.\n const resolvedWikiTopicId =\n wikiTopicId ?? topicId ?? (session !== \"dm\" ? session : undefined);\n if (resolvedWikiTopicId) args.push(`--topic-id=${resolvedWikiTopicId}`);\n args.push(\"--surface=wiki\");\n return buildBuiltinMcpServer(\"wiki\", { ...ctx, wikiTopicId: resolvedWikiTopicId }, () =>\n buildStdioMcpServer(agent, WIKI_SERVER, args),\n );\n },\n },\n skills: {\n ...commonRuntimeMcpPolicy(\"skills\"),\n build(ctx) {\n const { userId, topicId, agent } = ctx;\n const args = [`--user-id=${userId}`, \"--surface=skills\"];\n if (topicId) args.push(`--topic-id=${topicId}`);\n return buildBuiltinMcpServer(\"skills\", ctx, () =>\n buildStdioMcpServer(agent, WIKI_SERVER, args),\n );\n },\n },\n \"system-health\": {\n ...commonRuntimeMcpPolicy(\"system-health\"),\n build(ctx) {\n return buildBuiltinMcpServer(\"system-health\", ctx, () =>\n buildStdioMcpServer(ctx.agent, SYSTEM_HEALTH_SERVER, []),\n );\n },\n },\n \"background-bash\": {\n ...commonRuntimeMcpPolicy(\"background-bash\"),\n build({ agent, bgBashPort, userId, topicId }) {\n // Key the whole pipeline by the canonical topic id: it flows through the\n // capability, the request context, and the completion inbox filename\n // (sessionInboxPath) so the exiting process's output is routed back to\n // the exact originating topic. A title/session fallback would be encoded\n // as if it were an id and the inbox worker would fail to resolve it, so\n // background-bash is simply unavailable without a topic id.\n if (bgBashPort === undefined || !topicId) return null;\n return backgroundBashTransport(agent, bgBashPort, userId, topicId);\n },\n },\n \"agent-health\": {\n ...commonRuntimeMcpPolicy(\"agent-health\"),\n build(ctx) {\n const { userId, agent } = ctx;\n const args = [`--user-id=${userId}`];\n return buildBuiltinMcpServer(\"agent-health\", ctx, () =>\n buildStdioMcpServer(agent, AGENT_HEALTH_SERVER, args),\n );\n },\n },\n vault: {\n ...commonRuntimeMcpPolicy(\"vault\"),\n build(ctx) {\n const { userId, vaultUserId, agent } = ctx;\n // Normal turns use {{KEY}} directly in tool inputs. Keep the Vault MCP\n // surface focused on key discovery; broker tools remain available from\n // the public factory for compatibility but are no longer the default UX.\n const args = [`--user-id=${vaultUserId ?? userId}`];\n if (agent !== \"codex\") args.push(\"--list-only=true\");\n return buildBuiltinMcpServer(\"vault\", { ...ctx, userId: vaultUserId ?? userId }, () =>\n buildStdioMcpServer(agent, VAULT_SERVER, args),\n );\n },\n },\n // macOS desktop control, delegated to maestrojeong/cua-rs rather than\n // reimplemented. The node owns one persistent Streamable HTTP process;\n // turns only receive its loopback URL and must never spawn a stdio copy.\n \"cua-rs\": {\n ...commonRuntimeMcpPolicy(\"cua-rs\"),\n build({ agent }) {\n return cuaRsMcpPort ? cuaRsHttpMcp(agent, cuaRsMcpPort, cuaRsMcpToken) : null;\n },\n },\n};\n\n/**\n * Locate the `cua-rs` binary, or `null` when it is not installed.\n *\n * Checked in order of specificity: an explicit env override for anyone running\n * a local build, then the installer's default target, then `/usr/local/bin`\n * for a `--bin-dir` install. PATH is deliberately not consulted -- the server\n * is spawned by a supervised host process whose PATH is not the user's shell\n * PATH, so a PATH lookup would succeed in a terminal and fail under pm2.\n */\nexport function resolveCuaRsBinary(platform: NodeJS.Platform = process.platform): string | null {\n if (platform !== \"darwin\") return null;\n const candidates = [\n envText(\"NEGOTIUM_CUA_RS_BIN\"),\n join(homedir(), \".local\", \"bin\", \"cua-rs\"),\n \"/usr/local/bin/cua-rs\",\n ].filter((p): p is string => Boolean(p));\n for (const candidate of candidates) {\n try {\n accessSync(candidate, fsConstants.X_OK);\n return candidate;\n } catch {\n // Not there, or not executable. Try the next one.\n }\n }\n return null;\n}\n\n// --- Derived catalog views ---\n\nexport type NodeMcpEntry =\n | { key: string; kind: \"http\"; port: number }\n | {\n key: string;\n kind: \"http-instance\";\n ensurePort: (instanceKey: string) => Promise<number>;\n }\n | { key: string; kind: \"stdio\"; command: string; args?: string[]; env?: Record<string, string> };\n\nlet nodeMcpEntries: NodeMcpEntry[] = [];\nconst resolvedNodeMcpPorts = new WeakMap<\n Extract<NodeMcpEntry, { kind: \"http-instance\" }>,\n Map<string, number>\n>();\n\n/** All forum-eligible MCP server names, in display order. */\nconst allForumMcpServerNames: string[] = [];\nexport const ALL_FORUM_MCP_SERVER_NAMES: readonly string[] = allForumMcpServerNames;\n\n/** Forum servers that cannot be removed via the enabled whitelist. */\nconst requiredForumMcpServers: string[] = [];\nexport const REQUIRED_FORUM_MCP_SERVERS: readonly string[] = requiredForumMcpServers;\n\n/** Forum servers that can be toggled via the enabled whitelist (not required). */\nconst optionalForumMcpServers: string[] = [];\nexport const OPTIONAL_FORUM_MCP_SERVERS: readonly string[] = optionalForumMcpServers;\n\nfunction refreshForumCatalogViews(): void {\n const { all, required, optional } = classifyForumMcpServers(MCP_CATALOG);\n const nodeNames = nodeMcpEntries.map((entry) => entry.key);\n const allWithNodeEntries = [...new Set([...all, ...nodeNames])];\n const optionalWithNodeEntries = [...new Set([...optional, ...nodeNames])];\n allForumMcpServerNames.splice(0, allForumMcpServerNames.length, ...allWithNodeEntries);\n requiredForumMcpServers.splice(0, requiredForumMcpServers.length, ...required);\n optionalForumMcpServers.splice(0, optionalForumMcpServers.length, ...optionalWithNodeEntries);\n}\n\nrefreshForumCatalogViews();\n\n/**\n * Mount one MCP capability supplied by an optional node module.\n *\n * Registration happens once at node startup, never in the per-event hot path.\n * The returned cleanup closure only removes the exact entry installed by this\n * call, making module stop/restart safe.\n */\nexport function registerRuntimeMcpServer(name: string, entry: RuntimeMcpCatalogEntry): () => void {\n const key = name.trim();\n if (!key || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(key)) {\n throw new Error(`invalid runtime MCP server name: ${name}`);\n }\n if (MCP_CATALOG[key]) throw new Error(`runtime MCP server already registered: ${key}`);\n MCP_CATALOG[key] = entry;\n refreshForumCatalogViews();\n return () => {\n if (MCP_CATALOG[key] !== entry) return;\n delete MCP_CATALOG[key];\n refreshForumCatalogViews();\n };\n}\n\n/**\n * Format the active MCP config for display (used by get_mcp_config /\n * get_topic_mcp / configure_mcp response).\n *\n * In whitelist mode the DB stores only the user-chosen optional servers;\n * required servers are always active but never written to the whitelist.\n * This helper surfaces that split so the model never confuses \"not in\n * whitelist\" with \"not active\".\n */\nexport function formatMcpStatus(config: {\n enabled: string[] | null;\n extra?: Record<string, unknown>;\n}): string[] {\n const extraNames = Object.keys(config.extra ?? {});\n\n if (config.enabled === null) {\n const total = ALL_FORUM_MCP_SERVER_NAMES.length + extraNames.length;\n return [\n `설정 방식: 기본값 (전체 활성)`,\n `활성 서버 (${total}개): ${[...ALL_FORUM_MCP_SERVER_NAMES, ...extraNames].join(\", \")}`,\n `추가 서버: ${extraNames.length > 0 ? extraNames.join(\", \") : \"없음\"}`,\n ];\n }\n\n // whitelist mode: stored list may or may not include required servers\n // (old entries might have them; new entries won't). Either way, split\n // by required vs optional for display.\n const availableOptional = new Set(OPTIONAL_FORUM_MCP_SERVERS);\n const optionalActive = [...new Set(config.enabled)].filter((name) => availableOptional.has(name));\n const total = REQUIRED_FORUM_MCP_SERVERS.length + optionalActive.length + extraNames.length;\n return [\n `설정 방식: whitelist`,\n `필수 서버 (항상 활성, ${REQUIRED_FORUM_MCP_SERVERS.length}개): ${REQUIRED_FORUM_MCP_SERVERS.join(\", \")}`,\n `선택 서버 (whitelist, ${optionalActive.length}개): ${optionalActive.length > 0 ? optionalActive.join(\", \") : \"없음\"}`,\n `실제 활성 합계: ${total}개`,\n `추가 서버: ${extraNames.length > 0 ? extraNames.join(\", \") : \"없음\"}`,\n ``,\n `선택 가능 서버 전체 (${OPTIONAL_FORUM_MCP_SERVERS.length}개): ${OPTIONAL_FORUM_MCP_SERVERS.join(\", \")}`,\n ];\n}\n\n// --- Builders for each scope ---\n\n// ── Node-assigned MCP servers (mcp-host manifest) ───────────────────\n//\n// The per-node MCP manifest (`negotium mcp add`) lives in @negotium/mcp-host,\n// which depends on core — so core cannot read it directly. Instead the host\n// process resolves the manifest at node start (ensuring long-lived http\n// servers are running and have ports) and installs the result here. Entries\n// then ride every eligible scope's catalog, subject to the same per-topic\n// `enabled` whitelist as optional built-ins.\n\n/** Install the node's assigned MCP servers. Last writer wins (host restart-safe). */\nexport function setNodeMcpServers(entries: NodeMcpEntry[]): void {\n nodeMcpEntries = entries.filter((entry) => !(entry.key in MCP_CATALOG));\n const dropped = entries.length - nodeMcpEntries.length;\n if (dropped > 0) {\n logger.warn({ dropped }, \"setNodeMcpServers: entries shadowing built-in catalog keys ignored\");\n }\n refreshForumCatalogViews();\n}\n\nexport function getNodeMcpServers(): readonly NodeMcpEntry[] {\n return nodeMcpEntries;\n}\n\n/** Prevent host grants from replacing node-owned MCP servers. */\nexport function isReservedRuntimeMcpServerName(name: string): boolean {\n return Object.hasOwn(MCP_CATALOG, name) || nodeMcpEntries.some((entry) => entry.key === name);\n}\n\nfunction mergeHostMcpServers(\n base: Record<string, unknown>,\n hostMcpServers: Record<string, HostMcpServerSpec> | undefined,\n): Record<string, unknown> {\n if (!hostMcpServers) return base;\n for (const name of Object.keys(hostMcpServers)) {\n if (Object.hasOwn(base, name) || isReservedRuntimeMcpServerName(name)) {\n throw new Error(`host MCP server name conflicts with node catalog: ${name}`);\n }\n }\n return { ...base, ...hostMcpServers };\n}\n\nfunction buildNodeMcpSpecs(\n agent: AgentKind | undefined,\n filter: (name: string) => boolean,\n ctx: Pick<RuntimeMcpBuildContext, \"topicId\" | \"userId\" | \"session\">,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const entry of nodeMcpEntries) {\n if (!filter(entry.key)) continue;\n if (entry.kind === \"http\") {\n out[entry.key] = longLivedHttpMcp(agent, entry.port);\n continue;\n }\n if (entry.kind === \"http-instance\") {\n const port = resolvedNodeMcpPorts.get(entry)?.get(nodeMcpInstanceKey(ctx));\n if (port !== undefined) out[entry.key] = longLivedHttpMcp(agent, port);\n continue;\n }\n out[entry.key] = {\n command: entry.command,\n args: entry.args ?? [],\n ...(entry.env ? { env: entry.env } : {}),\n };\n }\n return out;\n}\n\nfunction nodeMcpInstanceKey(\n ctx: Pick<RuntimeMcpBuildContext, \"topicId\" | \"userId\" | \"session\">,\n): string {\n return ctx.topicId ?? `user:${ctx.userId}:session:${ctx.session}`;\n}\n\n/**\n * Lazily prepare per-topic HTTP manifest entries before a provider resolves\n * its otherwise-synchronous MCP config. One failed custom server is omitted\n * from that turn without taking down the rest of the runtime catalog.\n */\nexport async function prepareNodeMcpServersForQuery(opts: AgentQueryOptions): Promise<void> {\n if (\n opts.toolPolicy ||\n opts.sessionType === \"cron\" ||\n nodeMcpEntries.every((entry) => entry.kind !== \"http-instance\")\n ) {\n return;\n }\n\n const forum = ![\"dm\", \"ephemeral\", \"manager\"].includes(opts.sessionType ?? \"forum\");\n const enabled = opts.mcpEnabled ?? null;\n const instanceKey = nodeMcpInstanceKey({\n topicId: opts.topicId,\n userId: opts.userId || \"local\",\n session: opts.session || \"default\",\n });\n\n await Promise.all(\n nodeMcpEntries.map(async (entry) => {\n if (entry.kind !== \"http-instance\") return;\n if (forum && enabled !== null && !enabled.includes(entry.key)) return;\n let ports = resolvedNodeMcpPorts.get(entry);\n if (!ports) {\n ports = new Map();\n resolvedNodeMcpPorts.set(entry, ports);\n }\n try {\n const port = await entry.ensurePort(instanceKey);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(`invalid port ${port}`);\n }\n ports.set(instanceKey, port);\n } catch (err) {\n ports.delete(instanceKey);\n logger.warn(\n { err, key: entry.key, instanceKey },\n \"node mcp: failed to prepare instance-scoped server\",\n );\n }\n }),\n );\n}\n\nfunction buildScope(\n scope: RuntimeMcpScope,\n ctx: RuntimeMcpBuildContext,\n filter: (name: string) => boolean = () => true,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [name, entry] of Object.entries(MCP_CATALOG)) {\n if (!entry.scopes.includes(scope)) continue;\n if (!filter(name)) continue;\n // `null` from build() means \"skip this server for this turn\" —\n // currently used by the playwright entry when no long-lived port\n // is available.\n const spec = entry.build(ctx);\n if (spec === null) continue;\n out[name] = spec;\n }\n // Node-assigned MCPs join every scope except cron (scheduled runs keep the\n // deliberately narrow built-in set).\n if (scope !== \"cron\") {\n Object.assign(out, buildNodeMcpSpecs(ctx.agent, filter, ctx));\n }\n return out;\n}\n\n/** DM session: catalog entries with `dm` scope, no whitelist. */\nexport function getDmMcpServers(opts: {\n userId: string;\n session?: string;\n topicId?: string;\n agent?: AgentKind;\n playwrightPort?: number;\n playwrightCapability?: string;\n}) {\n return buildScope(\"dm\", {\n userId: opts.userId,\n session: opts.session ?? \"dm\",\n topicId: opts.topicId,\n agent: opts.agent,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n });\n}\n\n/**\n * Manager session: lives in the caller's private General API topic. Owns topic CRUD,\n * invite/user admin, and cross-topic MCP toggling through `topic-admin`,\n * plus general utilities. Browser-heavy work belongs in dedicated topics, so\n * Playwright is intentionally excluded here.\n * No whitelist — manager-scope catalog entries are loaded as-is.\n */\nexport function getManagerMcpServers(opts: {\n userId: string;\n session?: string;\n topicId?: string;\n queryId?: string;\n wikiTopicId?: string;\n agent?: AgentKind;\n cwd?: string;\n model?: string;\n currentUserPrompt?: string;\n playwrightPort?: number;\n playwrightCapability?: string;\n autoContinue?: boolean;\n visualTools?: boolean;\n fileDeliveryTools?: boolean;\n}) {\n if (!opts.topicId) {\n throw new Error(\"getManagerMcpServers: private General topicId is required\");\n }\n const topicId = opts.topicId;\n return buildScope(\"manager\", {\n userId: opts.userId,\n session: opts.session ?? \"General\",\n topicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId ?? topicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.currentUserPrompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n autoContinue: opts.autoContinue,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n });\n}\n\n/**\n * Forum session: catalog entries with `forum` scope.\n * - `enabled === null` → all forum servers.\n * - `enabled` is an array → whitelist; required servers are always included.\n * - `extra` is merged on top, allowing one-off injections per topic.\n */\nexport function getForumMcpServers(opts: {\n userId: string;\n actorUserId?: string;\n vaultUserId?: string;\n session: string;\n topicId?: string;\n subagentParentTopicId?: string;\n queryId?: string;\n wikiTopicId?: string;\n agent: AgentKind;\n cwd?: string;\n model?: string;\n currentUserPrompt?: string;\n playwrightPort?: number;\n playwrightCapability?: string;\n bgBashPort?: number;\n autoContinue?: boolean;\n visualTools?: boolean;\n fileDeliveryTools?: boolean;\n threadRootId?: string;\n depth?: number;\n enabled?: string[] | null;\n extra?: Record<string, unknown>;\n silent?: boolean;\n peerBridge?: PeerRuntimeBridgeContext;\n}) {\n const {\n userId,\n actorUserId,\n vaultUserId,\n session,\n topicId,\n subagentParentTopicId,\n queryId,\n wikiTopicId,\n agent,\n cwd,\n model,\n currentUserPrompt,\n playwrightPort,\n playwrightCapability,\n depth = 0,\n enabled = null,\n extra = {},\n silent = false,\n bgBashPort,\n autoContinue,\n visualTools,\n fileDeliveryTools,\n threadRootId,\n peerBridge,\n } = opts;\n\n const filter = (name: string) => {\n if (silent && (name === \"task\" || name === \"decision\")) return false;\n if (enabled === null) return true;\n return (\n enabled.includes(name) || (REQUIRED_FORUM_MCP_SERVERS as readonly string[]).includes(name)\n );\n };\n\n const base = buildScope(\n \"forum\",\n {\n userId,\n actorUserId,\n vaultUserId,\n session,\n topicId,\n subagentParentTopicId,\n queryId,\n wikiTopicId,\n agent,\n cwd,\n model,\n currentUserPrompt,\n depth,\n playwrightPort,\n playwrightCapability,\n bgBashPort,\n autoContinue,\n visualTools,\n fileDeliveryTools,\n threadRootId,\n silent,\n peerBridge,\n },\n filter,\n );\n\n return { ...base, ...extra };\n}\n\n/**\n * Cron session: scheduled background run for a concrete API topic. Keep the\n * catalog narrower than forum scope: runtime delivery, topic memory/status,\n * vault utilities and a caller-provided disposable Playwright port.\n */\nexport function getCronMcpServers(opts: {\n userId: string;\n session: string;\n topicId: string;\n queryId?: string;\n wikiTopicId?: string;\n agent: AgentKind;\n cwd?: string;\n model?: string;\n currentUserPrompt?: string;\n playwrightPort?: number;\n playwrightCapability?: string;\n visualTools?: boolean;\n fileDeliveryTools?: boolean;\n}) {\n return buildScope(\"cron\", {\n userId: opts.userId,\n session: opts.session,\n topicId: opts.topicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId ?? opts.topicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.currentUserPrompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n autoContinue: false,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n });\n}\n\n/**\n * Pick the right MCP server bundle for an agent query. DM/ephemeral sessions\n * get the DM bundle; forum sessions get the forum bundle with full options\n * forwarded. Returned shape is the Claude-SDK shape; Codex callers funnel it\n * through their own translator (`toCodexMcpServers`).\n */\nexport function getMcpServersForQuery(opts: AgentQueryOptions): Record<string, unknown> {\n if (opts.toolPolicy === \"none\") return {};\n if (opts.toolPolicy === \"compaction-log\") {\n const compactLog = opts.mcpExtra?.compact_log;\n return compactLog ? { compact_log: compactLog } : {};\n }\n if (opts.sessionType === \"cron\") {\n if (!opts.topicId) throw new Error(\"getMcpServersForQuery: cron sessionType requires topicId\");\n return getCronMcpServers({\n userId: opts.userId || \"local\",\n session: opts.session || \"cron\",\n topicId: opts.topicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.prompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n });\n }\n if (opts.sessionType === \"dm\" || opts.sessionType === \"ephemeral\") {\n return getDmMcpServers({\n userId: opts.userId || \"local\",\n session: opts.session,\n topicId: opts.topicId,\n agent: opts.agent,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n });\n }\n if (opts.sessionType === \"manager\") {\n return mergeHostMcpServers(\n getManagerMcpServers({\n userId: opts.userId || \"local\",\n session: opts.session,\n topicId: opts.topicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.prompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n autoContinue: opts.autoContinue,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n }),\n opts.hostMcpServers,\n );\n }\n return getForumMcpServers({\n userId: opts.userId || \"local\",\n actorUserId: opts.actorUserId,\n vaultUserId: opts.vaultUserId,\n session: opts.session || \"default\",\n topicId: opts.topicId,\n subagentParentTopicId: opts.subagentParentTopicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.prompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n bgBashPort: opts.bgBashPort,\n autoContinue: opts.autoContinue,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n threadRootId: opts.threadRootId,\n depth: opts.depth,\n enabled: opts.mcpEnabled,\n extra: opts.mcpExtra,\n silent: opts.silent,\n peerBridge: opts.peerBridge,\n });\n}\n",
|
|
26
|
-
"import { chmodSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { VAULT_MASTER_KEY } from \"#platform/config\";\nimport { closeDatabase, Database } from \"#storage/sqlite\";\nimport { resolveStorageDataDir } from \"#storage/storage-host\";\nimport { decryptVaultValue, encryptVaultValue, isEncryptedVaultValue } from \"#storage/vault-crypto\";\n\nexport type VaultDatabase = Pick<InstanceType<typeof Database>, \"exec\" | \"prepare\">;\n\nexport interface VaultStorageOptions {\n database?: VaultDatabase;\n dataDir?: string;\n masterKey?: string;\n /** Prior keys rows may still be encrypted under; migrated onto `masterKey`. */\n legacyMasterKeys?: readonly string[];\n}\n\nlet vaultDb: VaultDatabase | undefined;\nlet vaultMasterKey = VAULT_MASTER_KEY;\n\nfunction initializeVaultDatabase(database: VaultDatabase): void {\n database.exec(\"PRAGMA journal_mode = WAL\");\n database.exec(\"PRAGMA busy_timeout = 5000\");\n database.exec(`\n CREATE TABLE IF NOT EXISTS vault (\n user_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n PRIMARY KEY (user_id, key)\n )\n `);\n\n // Migrate legacy schema where user_id was INTEGER (Telegram numeric ids only).\n // The Otium API authenticates with string user ids (\"otium-user-…\"), so user_id\n // is now TEXT for every channel. Rebuild + CAST existing rows so old Telegram\n // secrets survive; idempotent (no-op once user_id is already TEXT).\n {\n const cols = database.prepare(\"PRAGMA table_info(vault)\").all() as {\n name: string;\n type: string;\n }[];\n const uid = cols.find((c) => c.name === \"user_id\");\n if (uid && uid.type.toUpperCase() === \"INTEGER\") {\n database.exec(\"BEGIN\");\n database.exec(`\n CREATE TABLE vault_migrated (\n user_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n PRIMARY KEY (user_id, key)\n )\n `);\n database.exec(\n \"INSERT INTO vault_migrated SELECT CAST(user_id AS TEXT), key, value, description FROM vault\",\n );\n database.exec(\"DROP TABLE vault\");\n database.exec(\"ALTER TABLE vault_migrated RENAME TO vault\");\n database.exec(\"COMMIT\");\n }\n }\n}\n\nfunction openVaultDatabase(dataDir: string): VaultDatabase {\n const vaultDir = join(dataDir, \"vault\");\n const path = join(vaultDir, \"vault.db\");\n mkdirSync(vaultDir, { recursive: true, mode: 0o700 });\n const database = new Database(path, { create: true });\n // Defense in depth: the database and its sidecars are owner-only, while each\n // value is also encrypted independently by vault-crypto.\n chmodSync(path, 0o600);\n initializeVaultDatabase(database);\n return database;\n}\n\nfunction activeVaultDatabase(): VaultDatabase {\n if (!vaultDb) {\n // `resolveStorageDataDir()`, not the import-time `DATA_DIR` constant: an\n // embedding host configures its data directory during bootstrap, and any\n // vault access that happens before `configureVaultStorage()` runs would\n // otherwise pin the vault to Negotium's own state directory for the life of\n // the process — silently, since both paths are valid and writable.\n vaultDb = openVaultDatabase(resolveStorageDataDir());\n }\n return vaultDb;\n}\n\n/** Re-encrypts rows only readable under `legacyKeys` onto `targetKey`, atomically. */\nfunction migrateLegacyMasterKeys(\n database: VaultDatabase,\n targetKey: string,\n legacyKeys: readonly string[],\n): void {\n if (legacyKeys.length === 0) return;\n const rows = database.prepare(\"SELECT user_id, key, value FROM vault\").all() as {\n user_id: string;\n key: string;\n value: string;\n }[];\n\n const rewrites: { userId: string; key: string; newValue: string }[] = [];\n for (const row of rows) {\n if (!isEncryptedVaultValue(row.value)) continue; // plaintext rows are handled by decryptRow()\n try {\n decryptVaultValue(row.user_id, row.key, row.value, targetKey);\n continue; // already readable under the target key\n } catch {\n // fall through to legacy recovery below\n }\n let recovered: string | undefined;\n for (const legacyKey of legacyKeys) {\n try {\n recovered = decryptVaultValue(row.user_id, row.key, row.value, legacyKey).value;\n break;\n } catch {\n // try the next legacy key\n }\n }\n if (recovered === undefined) {\n throw new Error(\n `vault migration: row \"${row.key}\" cannot be authenticated with the target master key or any legacy key`,\n );\n }\n rewrites.push({\n userId: row.user_id,\n key: row.key,\n newValue: encryptVaultValue(row.user_id, row.key, recovered, targetKey),\n });\n }\n if (rewrites.length === 0) return;\n\n database.exec(\"BEGIN IMMEDIATE\");\n try {\n const update = database.prepare(\"UPDATE vault SET value = ? WHERE user_id = ? AND key = ?\");\n for (const rewrite of rewrites) update.run(rewrite.newValue, rewrite.userId, rewrite.key);\n database.exec(\"COMMIT\");\n } catch (error) {\n database.exec(\"ROLLBACK\");\n throw error;\n }\n}\n\n/** Configure process-wide vault storage during embedding-host bootstrap. */\nexport function configureVaultStorage(options: VaultStorageOptions): () => void {\n if (options.database && options.dataDir) {\n throw new Error(\"configureVaultStorage accepts either database or dataDir, not both\");\n }\n const previousDb = vaultDb;\n const previousMasterKey = vaultMasterKey;\n const configuredDb =\n options.database ?? openVaultDatabase(options.dataDir ?? resolveStorageDataDir());\n const targetKey = options.masterKey ?? VAULT_MASTER_KEY;\n try {\n if (options.database) initializeVaultDatabase(configuredDb);\n if (options.legacyMasterKeys && options.legacyMasterKeys.length > 0) {\n migrateLegacyMasterKeys(configuredDb, targetKey, options.legacyMasterKeys);\n }\n } catch (error) {\n // A failed migration must not leak the connection this call opened: there\n // is no dispose to hand back, so nothing else can ever close it. Only a\n // database we opened ourselves is ours to close — an injected one is\n // borrowed.\n if (!options.database) {\n closeDatabase(configuredDb as VaultDatabase & { close(throwOnError?: boolean): void });\n }\n throw error;\n }\n vaultDb = configuredDb;\n vaultMasterKey = targetKey;\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n if (!options.database && \"close\" in configuredDb) {\n closeDatabase(configuredDb as VaultDatabase & { close(throwOnError?: boolean): void });\n }\n vaultDb = previousDb;\n vaultMasterKey = previousMasterKey;\n };\n}\n\nexport interface VaultEntry {\n key: string;\n description: string;\n}\n\nexport interface VaultEntryWithValue extends VaultEntry {\n value: string;\n}\n\nexport const VAULT_KEY_PATTERN = /^[A-Z][A-Z0-9_]{0,127}$/;\nexport const VAULT_VALUE_MIN_BYTES = 4;\nexport const VAULT_VALUE_MAX_BYTES = 64 * 1024;\nexport const VAULT_DESCRIPTION_MAX_LENGTH = 500;\n\nexport function normalizeVaultKey(key: string): string {\n return key.trim().toUpperCase();\n}\n\nexport function validateVaultKey(key: string): boolean {\n return VAULT_KEY_PATTERN.test(normalizeVaultKey(key));\n}\n\nfunction decryptRow(userId: string, key: string, storedValue: string): string {\n const database = activeVaultDatabase();\n const decoded = decryptVaultValue(userId, key, storedValue, vaultMasterKey);\n if (decoded.legacyPlaintext) {\n database\n .prepare(\"UPDATE vault SET value = ? WHERE user_id = ? AND key = ? AND value = ?\")\n .run(encryptVaultValue(userId, key, decoded.value, vaultMasterKey), userId, key, storedValue);\n }\n return decoded.value;\n}\n\nexport function vaultListWithValues(userId: string): VaultEntryWithValue[] {\n const rows = activeVaultDatabase()\n .prepare(\"SELECT key, description, value FROM vault WHERE user_id = ? ORDER BY key\")\n .all(userId) as VaultEntryWithValue[];\n return rows.map((row) => ({\n key: row.key,\n description: row.description,\n value: decryptRow(userId, row.key, row.value),\n }));\n}\n\n/**\n * Return only rows that can still be authenticated with the active master key.\n *\n * This is intentionally limited to redaction indexes: one damaged credential\n * must not disable unrelated tools, while direct access to that credential\n * continues to fail closed through vaultGetValue().\n */\nexport function vaultListDecryptableValues(userId: string): VaultEntryWithValue[] {\n const rows = activeVaultDatabase()\n .prepare(\"SELECT key, description, value FROM vault WHERE user_id = ? ORDER BY key\")\n .all(userId) as VaultEntryWithValue[];\n const entries: VaultEntryWithValue[] = [];\n for (const row of rows) {\n try {\n entries.push({\n key: row.key,\n description: row.description,\n value: decryptRow(userId, row.key, row.value),\n });\n } catch {\n // A value that cannot be authenticated cannot be exposed by substitution,\n // so there is no plaintext form available to add to the redaction index.\n }\n }\n return entries;\n}\n\nexport function vaultSet(userId: string, key: string, value: string, description = \"\"): void {\n const normalizedKey = normalizeVaultKey(key);\n activeVaultDatabase()\n .prepare(\n `INSERT INTO vault (user_id, key, value, description) VALUES (?, ?, ?, ?)\n ON CONFLICT (user_id, key) DO UPDATE\n SET value = excluded.value, description = excluded.description`,\n )\n .run(\n userId,\n normalizedKey,\n encryptVaultValue(userId, normalizedKey, value, vaultMasterKey),\n description,\n );\n}\n\nexport function vaultHasKey(userId: string, key: string): boolean {\n const row = activeVaultDatabase()\n .prepare(\"SELECT 1 FROM vault WHERE user_id = ? AND key = ?\")\n .get(userId, normalizeVaultKey(key));\n return row != null;\n}\n\nexport function vaultDel(userId: string, key: string): boolean {\n const result = activeVaultDatabase()\n .prepare(\"DELETE FROM vault WHERE user_id = ? AND key = ?\")\n .run(userId, normalizeVaultKey(key)) as { changes: number };\n return result.changes > 0;\n}\n\nexport function vaultDeleteAllForUser(userId: string): number {\n const result = activeVaultDatabase()\n .prepare(\"DELETE FROM vault WHERE user_id = ?\")\n .run(userId) as {\n changes: number;\n };\n return result.changes;\n}\n\nexport function vaultList(userId: string): VaultEntry[] {\n return activeVaultDatabase()\n .prepare(\"SELECT key, description FROM vault WHERE user_id = ? ORDER BY key\")\n .all(userId) as VaultEntry[];\n}\n\nexport function vaultGetValue(userId: string, key: string): string | undefined {\n const normalizedKey = normalizeVaultKey(key);\n const row = activeVaultDatabase()\n .prepare(\"SELECT key, value FROM vault WHERE user_id = ? AND key = ?\")\n .get(userId, normalizedKey) as { key: string; value: string } | undefined;\n return row ? decryptRow(userId, row.key, row.value) : undefined;\n}\n\nexport interface VaultSubstitutionResult {\n text: string;\n usedKeys: string[];\n}\n\n/** Replace {{KEY}} placeholders and report which credentials were consumed. */\nexport function vaultSubstituteDetailed(userId: string, text: string): VaultSubstitutionResult {\n const entries = new Map<string, string | undefined>();\n const usedKeys = new Set<string>();\n const substituted = text.replace(/\\{\\{([^}]+)\\}\\}/g, (match, rawKey: string) => {\n const key = normalizeVaultKey(rawKey);\n if (!entries.has(key)) entries.set(key, vaultGetValue(userId, key));\n const value = entries.get(key);\n if (value === undefined) return match;\n usedKeys.add(key);\n return value;\n });\n return { text: substituted, usedKeys: [...usedKeys] };\n}\n\n/** Detect real {{KEY}} references without decrypting any Vault values. */\nexport function valueReferencesVaultKey(userId: string, value: unknown): boolean {\n const keys = new Set(vaultList(userId).map((entry) => entry.key));\n const visit = (candidate: unknown): boolean => {\n if (typeof candidate === \"string\") {\n for (const match of candidate.matchAll(/\\{\\{([^}]+)\\}\\}/g)) {\n if (keys.has(normalizeVaultKey(match[1] ?? \"\"))) return true;\n }\n return false;\n }\n if (Array.isArray(candidate)) return candidate.some(visit);\n if (candidate && typeof candidate === \"object\") {\n return Object.values(candidate as Record<string, unknown>).some(visit);\n }\n return false;\n };\n return visit(value);\n}\n\nfunction encodedSecretForms(value: string): string[] {\n const forms = new Set<string>([\n value,\n encodeURIComponent(value),\n Buffer.from(value, \"utf8\").toString(\"base64\"),\n Buffer.from(value, \"utf8\").toString(\"base64url\"),\n Buffer.from(value, \"utf8\").toString(\"hex\"),\n ]);\n forms.delete(\"\");\n return [...forms].sort((a, b) => b.length - a.length);\n}\n\n/** Scrub raw and common encoded forms before tool output reaches a model. */\nexport function redactVaultSecrets(userId: string, text: string): string {\n const candidates = vaultListDecryptableValues(userId)\n .flatMap((entry) => encodedSecretForms(entry.value).map((form) => ({ form, key: entry.key })))\n .sort((a, b) => b.form.length - a.form.length || a.key.localeCompare(b.key));\n if (candidates.length === 0) return text;\n const candidatesByFirstCharacter = new Map<string, typeof candidates>();\n for (const candidate of candidates) {\n const first = candidate.form[0];\n if (!first) continue;\n const bucket = candidatesByFirstCharacter.get(first) ?? [];\n bucket.push(candidate);\n candidatesByFirstCharacter.set(first, bucket);\n }\n\n let redacted = \"\";\n let offset = 0;\n while (offset < text.length) {\n const match = candidatesByFirstCharacter\n .get(text[offset] ?? \"\")\n ?.find((candidate) => text.startsWith(candidate.form, offset));\n if (!match) {\n redacted += text[offset];\n offset += 1;\n continue;\n }\n redacted += `[REDACTED:${match.key}]`;\n offset += match.form.length;\n }\n return redacted;\n}\n",
|
|
27
|
-
"// Runtime-adaptive SQLite façade.\n//\n// Why this exists: Otium normally runs on bun and uses `bun:sqlite` (native,\n// fast, zero-build). But the `codex` agent's MCP servers must run on pure node\n// — codex 0.135's rmcp stdio client can't handshake with bun-spawned servers\n// (see serverLaunch in platform/mcp-config.ts). `bun:sqlite` doesn't exist\n// under node, so any MCP server that touches the DB would crash on import.\n//\n// This module picks the backend at runtime and re-exports it as `Database`:\n// - under bun → the real `bun:sqlite` Database (unchanged behavior)\n// - under node → a thin shim over node:sqlite's DatabaseSync exposing the\n// exact subset Otium uses: new Database(path, {readonly?,create?}),\n// .query()/.prepare() → statement, .exec(), .run(), .transaction(fn),\n// .close(); statements support positional `?` params via .run()/.get()/\n// .all(). (No named-object params / .values()/.iterate()/.as() are used in\n// this codebase, so the shim intentionally omits them.)\n//\n// The TYPE of the exported `Database` is bun:sqlite's own class type (imported\n// type-only, so it's erased at runtime and never resolved under node). That\n// keeps every existing call site — including generic `.query<Row, Params>()`\n// usages — type-checking exactly as before with zero changes.\n//\n// The bun branch uses a dynamic import so node never resolves the `bun:sqlite`\n// specifier (dead code under node), and the node branch's `node:sqlite` import\n// never runs under bun.\n\nimport type { Database as BunDatabase } from \"bun:sqlite\";\n\n// `mock.module()` can replace the Bun global while a test graph is being\n// evaluated. The runtime version flag is stable and is also the documented\n// cross-runtime discriminator.\nconst isBun = typeof process.versions.bun === \"string\";\n\ntype DatabaseCtor = typeof BunDatabase;\n\nlet Database: DatabaseCtor;\n\nif (isBun) {\n ({ Database } = await import(\"bun:sqlite\"));\n} else {\n // node:sqlite has no type declarations under our tsconfig (`types: bun-types`\n // only), and `bun-types` doesn't ship them — so type the dynamic import\n // locally and use a `string` specifier to keep tsc from trying to resolve it.\n type NodeStatement = {\n run(...params: unknown[]): unknown;\n get(...params: unknown[]): unknown;\n all(...params: unknown[]): unknown[];\n };\n type NodeDatabaseSync = {\n prepare(sql: string): NodeStatement;\n exec(sql: string): void;\n close(): void;\n };\n type NodeSqliteModule = {\n DatabaseSync: new (path: string, options?: { readOnly?: boolean }) => NodeDatabaseSync;\n };\n // Keep Bun's resolver from eagerly resolving the Node-only builtin even\n // though this branch is dead there (notably under `bun test` + mock.module).\n const nodeSqliteSpecifier = [\"node\", \"sqlite\"].join(\":\");\n const { DatabaseSync } = (await import(nodeSqliteSpecifier)) as NodeSqliteModule;\n\n type DbOptions = { readonly?: boolean; create?: boolean };\n\n class NodeDatabase {\n #db: NodeDatabaseSync;\n\n constructor(path: string, options: DbOptions = {}) {\n // node:sqlite opens read-write and creates-if-missing by default, which\n // matches bun's `{create:true}`. For readonly we must not create.\n this.#db = options.readonly\n ? new DatabaseSync(path, { readOnly: true })\n : new DatabaseSync(path);\n }\n\n query(sql: string) {\n return this.#db.prepare(sql);\n }\n\n prepare(sql: string) {\n return this.#db.prepare(sql);\n }\n\n exec(sql: string): void {\n this.#db.exec(sql);\n }\n\n run(sql: string, ...params: unknown[]) {\n return this.#db.prepare(sql).run(...params);\n }\n\n transaction<Args extends unknown[], R>(fn: (...args: Args) => R): (...args: Args) => R {\n // bun's db.transaction(fn) returns a function that runs fn inside a\n // transaction when called. node:sqlite has no helper, so emulate with\n // BEGIN/COMMIT/ROLLBACK. It also exposes deferred/immediate/exclusive\n // variants; mirror those so Node-launched MCP servers can share call\n // sites with Bun.\n const run =\n (begin: \"BEGIN\" | \"BEGIN DEFERRED\" | \"BEGIN IMMEDIATE\" | \"BEGIN EXCLUSIVE\") =>\n (...args: Args): R => {\n this.#db.exec(begin);\n try {\n const result = fn(...args);\n this.#db.exec(\"COMMIT\");\n return result;\n } catch (err) {\n this.#db.exec(\"ROLLBACK\");\n throw err;\n }\n };\n const tx = run(\"BEGIN\") as ((...args: Args) => R) & {\n deferred: (...args: Args) => R;\n immediate: (...args: Args) => R;\n exclusive: (...args: Args) => R;\n };\n tx.deferred = run(\"BEGIN DEFERRED\");\n tx.immediate = run(\"BEGIN IMMEDIATE\");\n tx.exclusive = run(\"BEGIN EXCLUSIVE\");\n return tx;\n }\n\n close(): void {\n this.#db.close();\n }\n }\n\n Database = NodeDatabase as unknown as DatabaseCtor;\n}\n\nexport { Database };\n\n/**\n * Close a database and release its underlying file handle.\n *\n * `bun:sqlite`'s no-argument `close()` does not finalize prepared statements\n * that are still reachable, so the file stays open. POSIX hides this — the\n * path can be unlinked while a handle remains — but Windows refuses to delete\n * or rename the file at all (`EBUSY`), which is how the leak surfaces. Passing\n * `true` finalizes eagerly and drops the handle.\n *\n * The node shim's `close()` ignores the argument, so one call covers both\n * backends; the fallback only matters for a backend that rejects the extra\n * parameter outright.\n */\nexport function closeDatabase(database: { close(throwOnError?: boolean): void }): void {\n try {\n database.close(true);\n } catch {\n try {\n database.close();\n } catch {\n // Already closed: nothing left to release.\n }\n }\n}\n",
|
|
25
|
+
"/** \"from\" field for session-inbox entries injected after a setting change. */\nexport const FROM_AUTO_CONTINUE = \"auto-continue\";\n\n/** \"from\" field for durable delayed continuations created by schedule_self. */\nexport const FROM_SELF_SCHEDULE = \"self-schedule\";\n\n/** Topic names that collide with internal sentinels and must not be used. */\nexport const RESERVED_TOPIC_NAMES: ReadonlySet<string> = new Set([\n FROM_AUTO_CONTINUE,\n FROM_SELF_SCHEDULE,\n \"general\",\n]);\n\n/** Legacy shared General id. New General rooms use per-user UUIDs. */\nexport const GENERAL_TOPIC_ID = \"general\";\n\n/**\n * Sanitized log name every private General resolves to.\n *\n * `general` is reserved above, so a manager room is the only room that can\n * produce it — which is what lets conversation storage qualify just that one\n * file per owner instead of namespacing the whole directory.\n */\nexport const MANAGER_TOPIC_LOG_NAME = \"general\";\n\n/** The principal a standalone node runs as when no hub names another. */\nexport const NODE_LOCAL_USER_ID = \"local\";\n\n/** Internal topic name for the forum manager session (General topic). */\nexport const TOPIC_MANAGER = \"__manager__\";\n",
|
|
28
26
|
"import { mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { closeDatabase, Database } from \"#storage/sqlite\";\nimport type { StorageDatabase, StorageHostConfig } from \"#storage/storage-contract\";\n\nexport type {\n StorageDatabase,\n StorageDatabaseAdapter,\n StorageDatabaseInput,\n StorageHostConfig,\n StorageHostOptions,\n StorageStatement,\n StorageTransaction,\n} from \"#storage/storage-contract\";\n\ntype InternalStorageDatabase = InstanceType<typeof Database>;\ntype OwnedStorageDatabase = InternalStorageDatabase & { close(): void };\n\ninterface StorageHostFrame {\n active: boolean;\n patch: Readonly<StorageHostConfig>;\n}\n\ntype StorageSchemaInitializer = (database: InternalStorageDatabase) => void;\ninterface RegisteredSchemaInitializer {\n initialize: StorageSchemaInitializer;\n priority: number;\n}\n\ninterface StorageHostState {\n configuredHost: Readonly<StorageHostConfig>;\n fallbackDatabase: OwnedStorageDatabase | null;\n fallbackDatabasePath: string | null;\n frames: StorageHostFrame[];\n schemaInitializers: RegisteredSchemaInitializer[];\n initializedSchemas: WeakMap<InternalStorageDatabase, Set<StorageSchemaInitializer>>;\n initializingDatabases: WeakSet<InternalStorageDatabase>;\n}\n\n/**\n * Which database an embedded Negotium uses is a property of the *process*, so\n * the state deciding it is keyed off a registered symbol rather than held in\n * module scope.\n *\n * Module scope would be equivalent only if every caller resolved to the same\n * module instance, and in the published package they do not:\n * `build-negotium-package.ts` emits most public entrypoints as independent\n * graphs, so each gets a private copy of this file. A host that configured\n * `negotium/storage` therefore left `negotium/agent-helpers` unconfigured, and\n * that copy opened a second database under the default state directory — with\n * no error, since both files are valid and writable.\n *\n * Merging those entrypoints into one graph looks tidier and does cut ~3MB from\n * `dist`, but Bun 1.2.15 (the pinned version) emits a shared chunk's export\n * list twice and the result is invalid ESM — \"Cannot export a duplicate name\".\n * That is bundler output with no counterpart in this source, so there is\n * nothing to de-duplicate here; it is fixed in Bun 1.3.14. Until the floor\n * moves, correctness cannot depend on how the package is chunked.\n */\nconst STORAGE_HOST_STATE = Symbol.for(\"negotium.storage-host.state.v1\");\n\nfunction storageState(): StorageHostState {\n const holder = globalThis as typeof globalThis & { [STORAGE_HOST_STATE]?: StorageHostState };\n const existing = holder[STORAGE_HOST_STATE];\n if (existing) return existing;\n const created: StorageHostState = {\n configuredHost: {},\n fallbackDatabase: null,\n fallbackDatabasePath: null,\n frames: [],\n schemaInitializers: [],\n initializedSchemas: new WeakMap(),\n initializingDatabases: new WeakSet(),\n };\n Object.defineProperty(holder, STORAGE_HOST_STATE, {\n value: created,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n return created;\n}\n\nfunction envPath(name: string, fallback: string): string {\n const value = process.env[name]?.trim();\n return resolve(value || fallback);\n}\n\nfunction defaultStateDir(): string {\n return envPath(\"NEGOTIUM_STATE_DIR\", join(homedir(), \".negotium\"));\n}\n\nfunction defaultDataDir(): string {\n return envPath(\"NEGOTIUM_DATA_DIR\", join(defaultStateDir(), \"data\"));\n}\n\nfunction defaultLogDir(): string {\n return envPath(\"NEGOTIUM_LOG_DIR\", join(defaultStateDir(), \"logs\"));\n}\n\nfunction defaultWorkspaceDir(): string {\n return envPath(\"NEGOTIUM_WORKSPACE_DIR\", join(defaultStateDir(), \"workspace\"));\n}\n\nfunction defaultSessionAsksDir(): string {\n const runDir = envPath(\"NEGOTIUM_RUN_DIR\", join(defaultStateDir(), \"runtime\"));\n return join(runDir, \"session-asks\");\n}\n\nfunction defaultSessionsDatabasePath(): string {\n return envPath(\"SESSIONS_DB_PATH\", join(resolveStorageDataDir(), \"sessions.db\"));\n}\n\nconst SQLITE_INIT_RETRY_MS = 25;\nconst SQLITE_INIT_TIMEOUT_MS = 5_000;\nconst SQLITE_INIT_SLEEP = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));\n\nfunction isSqliteBusy(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return /database is (?:locked|busy)|SQLITE_(?:BUSY|LOCKED)/i.test(message);\n}\n\nfunction execWithBusyRetry(\n database: InternalStorageDatabase,\n sql: string,\n timeoutMs = SQLITE_INIT_TIMEOUT_MS,\n): void {\n const deadline = Date.now() + timeoutMs;\n while (true) {\n try {\n database.exec(sql);\n return;\n } catch (error) {\n if (!isSqliteBusy(error) || Date.now() >= deadline) throw error;\n Atomics.wait(SQLITE_INIT_SLEEP, 0, 0, Math.min(SQLITE_INIT_RETRY_MS, deadline - Date.now()));\n }\n }\n}\n\nexport function initializeDatabase(database: InternalStorageDatabase): void {\n // busy_timeout FIRST. Switching to WAL needs a brief exclusive lock, so when\n // two processes open the same database at the same moment — the node daemon\n // and an adapter, or two MCP servers — one of them hits SQLITE_BUSY. With the\n // timeout configured afterwards there was no retry budget in effect for the\n // statement that needed it most. Older Bun releases can still surface\n // SQLITE_BUSY immediately for journal_mode, so keep a bounded host-level\n // retry around that one exclusive transition as well.\n database.exec(\"PRAGMA busy_timeout = 5000\");\n execWithBusyRetry(database, \"PRAGMA journal_mode = WAL\");\n database.exec(\"PRAGMA foreign_keys = ON\");\n database.exec(\"PRAGMA wal_autocheckpoint = 1000\");\n try {\n database.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n } catch {\n // Non-fatal; a concurrent writer may hold the WAL briefly.\n }\n}\n\nfunction defaultDatabase(): InternalStorageDatabase {\n const path = defaultSessionsDatabasePath();\n const state = storageState();\n if (state.fallbackDatabase && state.fallbackDatabasePath === path) return state.fallbackDatabase;\n if (state.fallbackDatabase) closeDatabase(state.fallbackDatabase);\n mkdirSync(dirname(path), { recursive: true });\n state.fallbackDatabase = new Database(path, { create: true }) as unknown as OwnedStorageDatabase;\n state.fallbackDatabasePath = path;\n initializeDatabase(state.fallbackDatabase);\n return state.fallbackDatabase;\n}\n\nexport function resolveStorageDatabase(): InternalStorageDatabase {\n return (storageState().configuredHost.database ?? defaultDatabase()) as InternalStorageDatabase;\n}\n\n/**\n * The host-injected connection, or null when Negotium owns its own store.\n *\n * Unlike {@link resolveStorageDatabase} this never opens anything. Callers that\n * manage their own short-lived connections need to know whether a host store\n * exists *before* deciding to open one by path: opening it anyway is how an\n * embedded Negotium ends up writing half its state into the host's database and\n * the other half into `~/.negotium`, with nothing reporting an error.\n */\nexport function configuredStorageDatabase(): InternalStorageDatabase | null {\n return (storageState().configuredHost.database as InternalStorageDatabase | undefined) ?? null;\n}\n\nexport function resolveStorageDataDir(): string {\n return storageState().configuredHost.dataDir ?? defaultDataDir();\n}\n\nexport function resolveStorageLogDir(): string {\n return storageState().configuredHost.logDir ?? defaultLogDir();\n}\n\nexport function resolveStorageSessionAsksDir(): string {\n return storageState().configuredHost.sessionAsksDir ?? defaultSessionAsksDir();\n}\n\nexport function resolveStorageWorkspaceDir(): string {\n return storageState().configuredHost.workspaceDir ?? defaultWorkspaceDir();\n}\n\nexport function resolveStorageSharedWikiDir(): string {\n return storageState().configuredHost.sharedWikiDir ?? join(resolveStorageWorkspaceDir(), \"wiki\");\n}\n\nexport function resolveStorageUsersLogDir(): string {\n return storageState().configuredHost.usersLogDir ?? join(resolveStorageDataDir(), \"users\");\n}\n\nconst STORAGE_PATH_KEYS = [\n \"dataDir\",\n \"logDir\",\n \"sessionAsksDir\",\n \"workspaceDir\",\n \"sharedWikiDir\",\n \"usersLogDir\",\n] as const;\n\nfunction normalizeStorageHostPatch(options: StorageHostConfig): Readonly<StorageHostConfig> {\n const patch: StorageHostConfig = {};\n if (options.database !== undefined) {\n options.database.exec(\"PRAGMA foreign_keys = ON\");\n patch.database = options.database;\n }\n for (const key of STORAGE_PATH_KEYS) {\n const value = options[key];\n if (value === undefined) continue;\n if (!value.trim()) throw new TypeError(`${key} must not be empty`);\n patch[key] = resolve(value);\n }\n return Object.freeze(patch);\n}\n\nfunction refreshConfiguredHost(): void {\n const state = storageState();\n state.configuredHost = Object.freeze(\n Object.assign({}, ...state.frames.filter((frame) => frame.active).map((frame) => frame.patch)),\n );\n}\n\n/**\n * Configure the process-local storage boundary for an embedding host.\n *\n * Resolution is lazy: importing `negotium/storage` never opens a database or\n * touches a filesystem path. The returned disposer restores the exact prior\n * host, which keeps tests and nested embeddings isolated.\n */\nexport function configureStorageHost(options: StorageHostConfig): () => void {\n const frame: StorageHostFrame = { active: true, patch: normalizeStorageHostPatch(options) };\n storageState().frames.push(frame);\n refreshConfiguredHost();\n return () => {\n if (!frame.active) return;\n frame.active = false;\n const frames = storageState().frames;\n const index = frames.indexOf(frame);\n if (index >= 0) frames.splice(index, 1);\n refreshConfiguredHost();\n };\n}\n\n/** Remove every configured host layer and restore standalone fallbacks. */\nexport function resetStorageHost(): void {\n const frames = storageState().frames;\n for (const frame of frames) frame.active = false;\n frames.length = 0;\n refreshConfiguredHost();\n}\n\n/** Close only Negotium's fallback connection. Injected connections are borrowed. */\nexport function closeStorageDatabase(): void {\n const state = storageState();\n if (!state.fallbackDatabase) return;\n closeDatabase(state.fallbackDatabase);\n state.fallbackDatabase = null;\n state.fallbackDatabasePath = null;\n}\n\nexport function registerStorageSchemaInitializer(\n initialize: StorageSchemaInitializer,\n priority = 100,\n): void {\n const initializers = storageState().schemaInitializers;\n initializers.push({ initialize, priority });\n initializers.sort((a, b) => a.priority - b.priority);\n}\n\nexport function ensureStorageSchemas(\n database: InternalStorageDatabase = resolveStorageDatabase(),\n): void {\n const state = storageState();\n if (state.initializingDatabases.has(database)) return;\n let initialized = state.initializedSchemas.get(database);\n if (!initialized) {\n initialized = new Set();\n state.initializedSchemas.set(database, initialized);\n }\n state.initializingDatabases.add(database);\n try {\n for (const entry of state.schemaInitializers) {\n if (initialized.has(entry.initialize)) continue;\n // Mark first so a migration that calls through the public db proxy does\n // not recursively invoke itself. Remove on failure so the next call can retry.\n initialized.add(entry.initialize);\n try {\n entry.initialize(database);\n } catch (error) {\n initialized.delete(entry.initialize);\n throw error;\n }\n }\n } finally {\n state.initializingDatabases.delete(database);\n }\n}\n\n/** Stable proxy identity used by legacy imports and embedding hosts. */\nexport const internalStorageDatabase = new Proxy({} as InternalStorageDatabase, {\n get(_target, property) {\n const database = resolveStorageDatabase();\n ensureStorageSchemas(database);\n const value = Reflect.get(database as object, property, database);\n return typeof value === \"function\" ? value.bind(database) : value;\n },\n set(_target, property, value) {\n const database = resolveStorageDatabase();\n ensureStorageSchemas(database);\n return Reflect.set(database as object, property, value, database);\n },\n});\n\n/** Structurally typed view intended for embedding hosts. */\nexport const storageDatabase = internalStorageDatabase as unknown as StorageDatabase;\n",
|
|
27
|
+
"// Runtime-adaptive SQLite façade.\n//\n// Why this exists: Otium normally runs on bun and uses `bun:sqlite` (native,\n// fast, zero-build). But the `codex` agent's MCP servers must run on pure node\n// — codex 0.135's rmcp stdio client can't handshake with bun-spawned servers\n// (see serverLaunch in platform/mcp-config.ts). `bun:sqlite` doesn't exist\n// under node, so any MCP server that touches the DB would crash on import.\n//\n// This module picks the backend at runtime and re-exports it as `Database`:\n// - under bun → the real `bun:sqlite` Database (unchanged behavior)\n// - under node → a thin shim over node:sqlite's DatabaseSync exposing the\n// exact subset Otium uses: new Database(path, {readonly?,create?}),\n// .query()/.prepare() → statement, .exec(), .run(), .transaction(fn),\n// .close(); statements support positional `?` params via .run()/.get()/\n// .all(). (No named-object params / .values()/.iterate()/.as() are used in\n// this codebase, so the shim intentionally omits them.)\n//\n// The TYPE of the exported `Database` is bun:sqlite's own class type (imported\n// type-only, so it's erased at runtime and never resolved under node). That\n// keeps every existing call site — including generic `.query<Row, Params>()`\n// usages — type-checking exactly as before with zero changes.\n//\n// The bun branch uses a dynamic import so node never resolves the `bun:sqlite`\n// specifier (dead code under node), and the node branch's `node:sqlite` import\n// never runs under bun.\n\nimport type { Database as BunDatabase } from \"bun:sqlite\";\n\n// `mock.module()` can replace the Bun global while a test graph is being\n// evaluated. The runtime version flag is stable and is also the documented\n// cross-runtime discriminator.\nconst isBun = typeof process.versions.bun === \"string\";\n\ntype DatabaseCtor = typeof BunDatabase;\n\nlet Database: DatabaseCtor;\n\nif (isBun) {\n ({ Database } = await import(\"bun:sqlite\"));\n} else {\n // node:sqlite has no type declarations under our tsconfig (`types: bun-types`\n // only), and `bun-types` doesn't ship them — so type the dynamic import\n // locally and use a `string` specifier to keep tsc from trying to resolve it.\n type NodeStatement = {\n run(...params: unknown[]): unknown;\n get(...params: unknown[]): unknown;\n all(...params: unknown[]): unknown[];\n };\n type NodeDatabaseSync = {\n prepare(sql: string): NodeStatement;\n exec(sql: string): void;\n close(): void;\n };\n type NodeSqliteModule = {\n DatabaseSync: new (path: string, options?: { readOnly?: boolean }) => NodeDatabaseSync;\n };\n // Keep Bun's resolver from eagerly resolving the Node-only builtin even\n // though this branch is dead there (notably under `bun test` + mock.module).\n const nodeSqliteSpecifier = [\"node\", \"sqlite\"].join(\":\");\n const { DatabaseSync } = (await import(nodeSqliteSpecifier)) as NodeSqliteModule;\n\n type DbOptions = { readonly?: boolean; create?: boolean };\n\n class NodeDatabase {\n #db: NodeDatabaseSync;\n\n constructor(path: string, options: DbOptions = {}) {\n // node:sqlite opens read-write and creates-if-missing by default, which\n // matches bun's `{create:true}`. For readonly we must not create.\n this.#db = options.readonly\n ? new DatabaseSync(path, { readOnly: true })\n : new DatabaseSync(path);\n }\n\n query(sql: string) {\n return this.#db.prepare(sql);\n }\n\n prepare(sql: string) {\n return this.#db.prepare(sql);\n }\n\n exec(sql: string): void {\n this.#db.exec(sql);\n }\n\n run(sql: string, ...params: unknown[]) {\n return this.#db.prepare(sql).run(...params);\n }\n\n transaction<Args extends unknown[], R>(fn: (...args: Args) => R): (...args: Args) => R {\n // bun's db.transaction(fn) returns a function that runs fn inside a\n // transaction when called. node:sqlite has no helper, so emulate with\n // BEGIN/COMMIT/ROLLBACK. It also exposes deferred/immediate/exclusive\n // variants; mirror those so Node-launched MCP servers can share call\n // sites with Bun.\n const run =\n (begin: \"BEGIN\" | \"BEGIN DEFERRED\" | \"BEGIN IMMEDIATE\" | \"BEGIN EXCLUSIVE\") =>\n (...args: Args): R => {\n this.#db.exec(begin);\n try {\n const result = fn(...args);\n this.#db.exec(\"COMMIT\");\n return result;\n } catch (err) {\n this.#db.exec(\"ROLLBACK\");\n throw err;\n }\n };\n const tx = run(\"BEGIN\") as ((...args: Args) => R) & {\n deferred: (...args: Args) => R;\n immediate: (...args: Args) => R;\n exclusive: (...args: Args) => R;\n };\n tx.deferred = run(\"BEGIN DEFERRED\");\n tx.immediate = run(\"BEGIN IMMEDIATE\");\n tx.exclusive = run(\"BEGIN EXCLUSIVE\");\n return tx;\n }\n\n close(): void {\n this.#db.close();\n }\n }\n\n Database = NodeDatabase as unknown as DatabaseCtor;\n}\n\nexport { Database };\n\n/**\n * Close a database and release its underlying file handle.\n *\n * `bun:sqlite`'s no-argument `close()` does not finalize prepared statements\n * that are still reachable, so the file stays open. POSIX hides this — the\n * path can be unlinked while a handle remains — but Windows refuses to delete\n * or rename the file at all (`EBUSY`), which is how the leak surfaces. Passing\n * `true` finalizes eagerly and drops the handle.\n *\n * The node shim's `close()` ignores the argument, so one call covers both\n * backends; the fallback only matters for a backend that rejects the extra\n * parameter outright.\n */\nexport function closeDatabase(database: { close(throwOnError?: boolean): void }): void {\n try {\n database.close(true);\n } catch {\n try {\n database.close();\n } catch {\n // Already closed: nothing left to release.\n }\n }\n}\n",
|
|
28
|
+
"import type { StorageDatabase } from \"#storage/storage-contract\";\nimport { internalStorageDatabase } from \"#storage/storage-host\";\n\nexport const db = internalStorageDatabase as unknown as StorageDatabase;\n",
|
|
29
|
+
"// Persistent topic store backed by shared SQLite.\n\nimport { resolveFallbackAgent } from \"#platform/config-helpers\";\nimport { GENERAL_TOPIC_ID } from \"#platform/constants\";\nimport { logger } from \"#platform/logger\";\nimport { db } from \"#storage/forum-db\";\nimport { registerStorageSchemaInitializer } from \"#storage/storage-host\";\nimport type { AgentKind, EffortLevel } from \"#types\";\nimport type {\n AiMode,\n ParticipantDto,\n SubagentReportMode,\n TopicDto,\n TopicKind,\n TopicSurface,\n TopicVisibility,\n} from \"#types/api\";\n\n/**\n * Surface used when a caller does not name one — and the value every existing\n * row is backfilled with on first boot after the surface migration.\n *\n * Hosts that only ever serve one surface declare it once in their environment\n * (`NEGOTIUM_DEFAULT_SURFACE=otium` on the Otium hub and worker); a developer\n * Mac leaves it unset and gets `terminal`, with the telegram adapter\n * reclassifying its own mapped rooms afterwards.\n */\nexport function defaultTopicSurface(): TopicSurface {\n return normalizeTopicSurface(process.env.NEGOTIUM_DEFAULT_SURFACE);\n}\n\nexport function normalizeTopicSurface(value: unknown): TopicSurface {\n return value === \"telegram\" || value === \"otium\" || value === \"terminal\" ? value : \"terminal\";\n}\n\n/**\n * The surface instance new rooms are filed under when the caller names none.\n *\n * `surface` alone is not enough once a node may be attached to several Otium\n * workspaces (M-2): two workspaces are two independent namespaces on the same\n * surface. The adapter that owns the attachment installs the active scope at\n * mount time; `terminal` and `telegram` are singletons and stay null.\n *\n * Kept as process state rather than an argument threaded through every creation\n * path because the value is a property of *this process's attachment*, not of\n * any individual call — the same reason `defaultTopicSurface()` exists.\n */\nlet activeSurfaceScope: string | null = null;\n\nexport function normalizeSurfaceScope(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed ? trimmed : null;\n}\n\nexport function defaultSurfaceScope(): string | null {\n return activeSurfaceScope ?? normalizeSurfaceScope(process.env.NEGOTIUM_SURFACE_SCOPE);\n}\n\n/** Install (or clear) the scope new rooms inherit. Returns the previous value. */\nexport function setDefaultSurfaceScope(scope: string | null): string | null {\n const previous = activeSurfaceScope;\n activeSurfaceScope = normalizeSurfaceScope(scope);\n return previous;\n}\n\n/**\n * Whether an Otium room must name a workspace to be created at all (M-3).\n *\n * Off by default, and off for every single-workspace host: an unscoped room is\n * then legacy, reachable, and perfectly usable. The adapter turns it on only\n * while several workspaces are attached, because there an unscoped room is\n * reachable from none of them (M-10) — a room nobody can see is worse than a\n * refusal that says so.\n */\nlet surfaceScopeRequired = false;\n\nexport function setSurfaceScopeRequired(required: boolean): void {\n surfaceScopeRequired = required;\n}\n\nexport function isSurfaceScopeRequired(): boolean {\n return surfaceScopeRequired;\n}\n\nfunction tableColumns(table: string): Set<string> {\n const rows = db.query(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>;\n return new Set(rows.map((row) => row.name));\n}\n\n/** Persist the authoritative agent and, when supplied, its normalized base defaults. */\nexport function setApiTopicAgent(\n topicId: string,\n agent: AgentKind,\n defaults?: { model: string; effort?: EffortLevel },\n): void {\n if (!defaults) {\n db.query(\"UPDATE api_topics SET agent = ? WHERE id = ?\").run(agent, topicId);\n return;\n }\n db.query(\"UPDATE api_topics SET agent = ?, base_model = ?, base_effort = ? WHERE id = ?\").run(\n agent,\n defaults.model,\n defaults.effort ?? null,\n topicId,\n );\n}\n\nfunction initializeApiTopicsSchema(): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS api_topics (\n id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n kind TEXT NOT NULL DEFAULT 'channel',\n description TEXT,\n agent TEXT,\n default_model TEXT,\n default_effort TEXT,\n participants TEXT,\n created_at TEXT NOT NULL,\n last_message_at TEXT,\n is_archived INTEGER NOT NULL DEFAULT 0,\n ai_mention INTEGER NOT NULL DEFAULT 0,\n ai_mode TEXT\n )\n`);\n\n const initialTopicColumns = tableColumns(\"api_topics\");\n const legacyTopicSchema = !initialTopicColumns.has(\"response_policy\");\n const needsCanonicalTopicRebuild = legacyTopicSchema || !initialTopicColumns.has(\"agent\");\n if (legacyTopicSchema) {\n // Rename the legacy column once; new databases are created with `agent`.\n try {\n db.exec(\"ALTER TABLE api_topics RENAME COLUMN default_agent TO agent\");\n } catch {\n // Already migrated or freshly created.\n }\n\n // Migrate existing DBs that predate the ai_mention column (team-mode topics).\n try {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN ai_mention INTEGER NOT NULL DEFAULT 0\");\n } catch {\n // Column already exists — nothing to do.\n }\n\n // Migrate for spawn/fork tracking (R1).\n try {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN parent_topic_id TEXT\");\n } catch {}\n try {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN is_fork INTEGER NOT NULL DEFAULT 0\");\n } catch {}\n\n // Migrate for agent-spawned subagent worker rooms.\n try {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN is_subagent INTEGER NOT NULL DEFAULT 0\");\n } catch {}\n\n // Migrate for session persistence.\n try {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN session_id TEXT\");\n } catch {}\n\n try {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN kind TEXT NOT NULL DEFAULT 'channel'\");\n } catch {}\n\n try {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN ai_mode TEXT\");\n } catch {}\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS api_schema_migrations (\n key TEXT PRIMARY KEY,\n applied_at TEXT NOT NULL\n )\n`);\n\n const ALWAYS_RESPOND_MIGRATION = \"api_topics_ai_invited_default_always_respond_20260623\";\n const alwaysRespondMigration = db\n .query(\"SELECT key FROM api_schema_migrations WHERE key = ?\")\n .get(ALWAYS_RESPOND_MIGRATION);\n if (!alwaysRespondMigration) {\n db.transaction(() => {\n db.query(\"UPDATE api_topics SET ai_mention = 0 WHERE agent IS NOT NULL\").run();\n db.query(\"INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)\").run(\n ALWAYS_RESPOND_MIGRATION,\n new Date().toISOString(),\n );\n })();\n }\n\n const GENERAL_AGENT_KIND_MIGRATION = \"api_topics_general_agent_kind_20260704\";\n const generalAgentKindMigration = db\n .query(\"SELECT key FROM api_schema_migrations WHERE key = ?\")\n .get(GENERAL_AGENT_KIND_MIGRATION);\n if (!generalAgentKindMigration) {\n db.transaction(() => {\n db.query(\"UPDATE api_topics SET kind = 'agent', ai_mention = 0 WHERE id = ?\").run(\n GENERAL_TOPIC_ID,\n );\n db.query(\"INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)\").run(\n GENERAL_AGENT_KIND_MIGRATION,\n new Date().toISOString(),\n );\n })();\n }\n\n const AI_MODE_MIGRATION = \"api_topics_ai_mode_20260704\";\n const aiModeMigration = db\n .query(\"SELECT key FROM api_schema_migrations WHERE key = ?\")\n .get(AI_MODE_MIGRATION);\n if (!aiModeMigration) {\n db.transaction(() => {\n db.query(\n `UPDATE api_topics\n SET\n kind = CASE\n WHEN id = ? THEN 'agent'\n WHEN kind = 'channel' AND agent IS NOT NULL AND ai_mention = 0 THEN 'agent'\n ELSE kind\n END,\n ai_mode = CASE\n WHEN id = ? THEN 'always'\n WHEN agent IS NULL THEN 'off'\n WHEN kind = 'agent' THEN 'always'\n WHEN kind = 'channel' AND ai_mention != 0 THEN 'mention'\n WHEN kind = 'channel' AND ai_mention = 0 THEN 'always'\n WHEN ai_mention != 0 THEN 'mention'\n ELSE 'always'\n END`,\n ).run(GENERAL_TOPIC_ID, GENERAL_TOPIC_ID);\n db.query(\"INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)\").run(\n AI_MODE_MIGRATION,\n new Date().toISOString(),\n );\n })();\n }\n\n const GENERAL_MANAGER_KIND_MIGRATION = \"api_topics_general_manager_kind_20260704\";\n const generalManagerKindMigration = db\n .query(\"SELECT key FROM api_schema_migrations WHERE key = ?\")\n .get(GENERAL_MANAGER_KIND_MIGRATION);\n if (!generalManagerKindMigration) {\n db.transaction(() => {\n db.query(\n \"UPDATE api_topics SET kind = 'manager', ai_mention = 0, ai_mode = 'always' WHERE id = ?\",\n ).run(GENERAL_TOPIC_ID);\n db.query(\"INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)\").run(\n GENERAL_MANAGER_KIND_MIGRATION,\n new Date().toISOString(),\n );\n })();\n }\n }\n\n function createCanonicalTopicsTable(name: string): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS ${name} (\n id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('channel','agent','manager')),\n description TEXT,\n agent TEXT CHECK (agent IS NULL OR agent IN ('maestro','claude','codex')),\n base_model TEXT,\n base_effort TEXT CHECK (base_effort IS NULL OR base_effort IN ('low','medium','high','xhigh','max')),\n response_policy TEXT NOT NULL CHECK (response_policy IN ('off','mention','always')),\n created_at TEXT NOT NULL,\n last_message_at TEXT,\n parent_topic_id TEXT,\n memory_topic_id TEXT,\n memory_key TEXT,\n is_fork INTEGER NOT NULL DEFAULT 0 CHECK (is_fork IN (0,1)),\n is_subagent INTEGER NOT NULL DEFAULT 0 CHECK (is_subagent IN (0,1)),\n visibility TEXT NOT NULL DEFAULT 'visible' CHECK (visibility IN ('visible','hidden')),\n surface TEXT NOT NULL DEFAULT 'terminal' CHECK (surface IN ('terminal','telegram','otium')),\n surface_scope TEXT,\n browser_profile TEXT NOT NULL DEFAULT 'default',\n browser_profile_owner TEXT,\n session_id TEXT,\n CHECK (\n (kind = 'channel' AND response_policy = 'off' AND agent IS NULL) OR\n (kind = 'channel' AND response_policy = 'mention' AND agent IS NOT NULL) OR\n (kind IN ('agent','manager') AND response_policy = 'always' AND agent IS NOT NULL)\n )\n )\n `);\n }\n\n function createTopicMembersTable(): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS topic_members (\n topic_id TEXT NOT NULL REFERENCES api_topics(id) ON DELETE CASCADE,\n user_id TEXT NOT NULL,\n role TEXT NOT NULL CHECK (role IN ('owner','member')),\n PRIMARY KEY (topic_id, user_id)\n )\n `);\n db.exec(\"CREATE INDEX IF NOT EXISTS idx_topic_members_user ON topic_members(user_id)\");\n }\n\n if (needsCanonicalTopicRebuild) {\n const legacyRows = db.query(\"SELECT * FROM api_topics\").all() as Array<Record<string, unknown>>;\n const existingMemberRows = tableColumns(\"topic_members\").has(\"topic_id\")\n ? (db.query(\"SELECT topic_id, user_id, role FROM topic_members\").all() as Array<{\n topic_id: string;\n user_id: string;\n role: string;\n }>)\n : [];\n const configColumns = tableColumns(\"api_topic_config\");\n const legacyAgentOverrides = configColumns.has(\"agent\")\n ? new Map(\n (\n db\n .query(\"SELECT topic_id, agent FROM api_topic_config WHERE agent IS NOT NULL\")\n .all() as Array<{ topic_id: string; agent: AgentKind }>\n ).map((row) => [row.topic_id, row.agent]),\n )\n : new Map<string, AgentKind>();\n const previousForeignKeys = db\n .query<{ foreign_keys: number }, []>(\"PRAGMA foreign_keys\")\n .get()?.foreign_keys;\n db.exec(\"PRAGMA foreign_keys = OFF\");\n try {\n db.transaction(() => {\n createCanonicalTopicsTable(\"api_topics_next\");\n for (const row of legacyRows) {\n const selectedAgent = (legacyAgentOverrides.get(String(row.id)) ??\n row.agent ??\n row.runtime_agent ??\n row.default_agent ??\n undefined) as AgentKind | undefined;\n const normalized = normalizeTopicState({\n id: String(row.id),\n kind: normalizeTopicKind(row.kind),\n agent: selectedAgent,\n aiMode: normalizeAiMode(row.response_policy ?? row.ai_mode),\n aiMention: Number(row.ai_mention ?? 0) !== 0,\n });\n const legacyBaseModel = row.base_model ?? row.default_model;\n const legacyBaseEffort = row.base_effort ?? row.default_effort;\n db.query(\n `INSERT INTO api_topics_next\n (id,title,kind,description,agent,base_model,base_effort,response_policy,\n created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,surface_scope,session_id)\n VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,\n ).run(\n String(row.id),\n String(row.title),\n normalized.kind,\n typeof row.description === \"string\" ? row.description : null,\n normalized.agent ?? null,\n typeof legacyBaseModel === \"string\" ? legacyBaseModel : null,\n typeof legacyBaseEffort === \"string\" ? legacyBaseEffort : null,\n normalized.aiMode,\n String(row.created_at),\n typeof row.last_message_at === \"string\" ? row.last_message_at : null,\n typeof row.parent_topic_id === \"string\" ? row.parent_topic_id : null,\n typeof row.memory_topic_id === \"string\" ? row.memory_topic_id : null,\n typeof row.memory_key === \"string\" ? row.memory_key : null,\n Number(row.is_fork ?? 0) !== 0 ? 1 : 0,\n Number(row.is_subagent ?? 0) !== 0 ? 1 : 0,\n row.visibility === \"hidden\" ? \"hidden\" : \"visible\",\n row.surface === undefined ? defaultTopicSurface() : normalizeTopicSurface(row.surface),\n normalizeSurfaceScope(row.surface_scope),\n typeof row.session_id === \"string\" ? row.session_id : null,\n );\n }\n db.exec(\"DROP TABLE IF EXISTS topic_members\");\n db.exec(\"DROP TABLE api_topics\");\n db.exec(\"ALTER TABLE api_topics_next RENAME TO api_topics\");\n createTopicMembersTable();\n if (existingMemberRows.length > 0) {\n for (const member of existingMemberRows) {\n db.query(\n \"INSERT OR REPLACE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)\",\n ).run(member.topic_id, member.user_id, member.role === \"owner\" ? \"owner\" : \"member\");\n }\n } else {\n for (const row of legacyRows) {\n let participants: ParticipantDto[] = [];\n try {\n const parsed = JSON.parse(String(row.participants ?? \"[]\"));\n if (Array.isArray(parsed)) participants = parsed as ParticipantDto[];\n } catch {\n participants = [];\n }\n for (const participant of participants) {\n if (!participant?.userId) continue;\n db.query(\n \"INSERT OR REPLACE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)\",\n ).run(\n String(row.id),\n participant.userId,\n participant.role === \"owner\" ? \"owner\" : \"member\",\n );\n }\n }\n }\n })();\n } finally {\n db.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? \"ON\" : \"OFF\"}`);\n }\n } else {\n createCanonicalTopicsTable(\"api_topics\");\n createTopicMembersTable();\n }\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS subagent_tell_grants (\n subagent_topic_id TEXT NOT NULL REFERENCES api_topics(id) ON DELETE CASCADE,\n target_topic_id TEXT NOT NULL REFERENCES api_topics(id) ON DELETE CASCADE,\n granted_by_topic_id TEXT NOT NULL REFERENCES api_topics(id) ON DELETE CASCADE,\n created_at TEXT NOT NULL,\n PRIMARY KEY (subagent_topic_id, target_topic_id)\n )\n `);\n db.exec(`\n DELETE FROM subagent_tell_grants\n WHERE subagent_topic_id NOT IN (SELECT id FROM api_topics)\n OR target_topic_id NOT IN (SELECT id FROM api_topics)\n OR granted_by_topic_id NOT IN (SELECT id FROM api_topics)\n `);\n db.exec(\"DELETE FROM topic_members WHERE topic_id NOT IN (SELECT id FROM api_topics)\");\n\n // Canonical databases created before explicit adapter visibility need a\n // lightweight additive migration; fresh/rebuilt databases already have it.\n if (!tableColumns(\"api_topics\").has(\"visibility\")) {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible'\");\n }\n if (!tableColumns(\"api_topics\").has(\"surface\")) {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN surface TEXT NOT NULL DEFAULT 'terminal'\");\n }\n if (!tableColumns(\"api_topics\").has(\"surface_scope\")) {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN surface_scope TEXT\");\n }\n // `access_mode` was replaced by `surface`: a topic is reachable from Otium\n // because it lives there, not because a flag was flipped (S-4). Dropping the\n // column removes the second, now-contradictory source of truth.\n if (tableColumns(\"api_topics\").has(\"access_mode\")) {\n try {\n db.exec(\"ALTER TABLE api_topics DROP COLUMN access_mode\");\n } catch (err) {\n logger.warn({ err }, \"api_topics: could not drop the retired access_mode column\");\n }\n }\n if (!tableColumns(\"api_topics\").has(\"browser_profile\")) {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN browser_profile TEXT NOT NULL DEFAULT 'default'\");\n }\n if (!tableColumns(\"api_topics\").has(\"browser_profile_owner\")) {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN browser_profile_owner TEXT\");\n }\n if (!tableColumns(\"api_topics\").has(\"subagent_report_mode\")) {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN subagent_report_mode TEXT NOT NULL DEFAULT 'auto'\");\n }\n if (!tableColumns(\"api_topics\").has(\"memory_topic_id\")) {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN memory_topic_id TEXT\");\n }\n if (!tableColumns(\"api_topics\").has(\"memory_key\")) {\n db.exec(\"ALTER TABLE api_topics ADD COLUMN memory_key TEXT\");\n }\n db.exec(`\n UPDATE api_topics\n SET browser_profile_owner = (\n SELECT m.user_id FROM topic_members m\n WHERE m.topic_id = api_topics.id AND m.role = 'owner'\n ORDER BY m.rowid\n LIMIT 1\n )\n WHERE browser_profile_owner IS NULL\n`);\n backfillTopicSurfaces();\n db.exec(\n \"CREATE INDEX IF NOT EXISTS idx_api_topics_last_message ON api_topics(last_message_at DESC)\",\n );\n db.exec(\"CREATE INDEX IF NOT EXISTS idx_api_topics_surface ON api_topics(surface)\");\n db.exec(\n \"CREATE INDEX IF NOT EXISTS idx_api_topics_surface_scope ON api_topics(surface, surface_scope)\",\n );\n}\n\nconst SURFACE_SCOPE_STAMP_MIGRATION = \"api_topics_surface_scope_stamp_20260809\";\n\n/**\n * M-9 — file every pre-existing Otium room under the workspace attached now.\n *\n * Deliberately *not* a schema-init step. The scope is only knowable after the\n * first successful Central contact (M-3), which happens long after the store\n * opens; a boot-time migration would see no scope, record itself as applied and\n * leave every room unstamped forever. The Otium runtime calls this instead, once,\n * as soon as it has resolved its workspace.\n *\n * Runs at most once per store: rooms created after this point are stamped at\n * creation, and a second workspace joined later must not swallow the first\n * one's rooms. Unlike the surface migration this can never rename anything —\n * the scope enters the uniqueness key in the same release, so nothing can start\n * colliding because of it.\n */\nexport function stampUnscopedOtiumTopics(scope: string): number {\n const normalized = normalizeSurfaceScope(scope);\n if (!normalized) return 0;\n db.exec(`\n CREATE TABLE IF NOT EXISTS api_schema_migrations (\n key TEXT PRIMARY KEY,\n applied_at TEXT NOT NULL\n )\n`);\n const applied = db\n .query(\"SELECT key FROM api_schema_migrations WHERE key = ?\")\n .get(SURFACE_SCOPE_STAMP_MIGRATION);\n if (applied) return 0;\n\n let stamped = 0;\n db.transaction(() => {\n stamped = Number(\n db\n .query(\n \"UPDATE api_topics SET surface_scope = ? WHERE surface = 'otium' AND surface_scope IS NULL\",\n )\n .run(normalized).changes ?? 0,\n );\n db.query(\"INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)\").run(\n SURFACE_SCOPE_STAMP_MIGRATION,\n new Date().toISOString(),\n );\n })();\n if (stamped > 0) {\n logger.info({ scope: normalized, stamped }, \"api_topics: surface scope stamped\");\n }\n return stamped;\n}\n\nconst SURFACE_BACKFILL_MIGRATION = \"api_topics_surface_backfill_20260808\";\n\n/**\n * One-time classification of pre-surface topics.\n *\n * Every row predates the column, so there is no per-row evidence in this store\n * to distinguish surfaces — the host declares it (`NEGOTIUM_DEFAULT_SURFACE`).\n * The telegram adapter owns the second pass: its chat↔topic mapping lives in a\n * different database file, so only it can reclassify the rooms it created.\n *\n * Names are unique per surface from now on, so collapsing three namespaces into\n * one can produce duplicates. Rather than failing the boot, the oldest room\n * keeps the name and the rest are suffixed — a rename is recoverable, a node\n * that refuses to start is not.\n */\nfunction backfillTopicSurfaces(): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS api_schema_migrations (\n key TEXT PRIMARY KEY,\n applied_at TEXT NOT NULL\n )\n`);\n const applied = db\n .query(\"SELECT key FROM api_schema_migrations WHERE key = ?\")\n .get(SURFACE_BACKFILL_MIGRATION);\n if (applied) return;\n\n const surface = defaultTopicSurface();\n db.transaction(() => {\n db.query(\"UPDATE api_topics SET surface = ?\").run(surface);\n renameSurfaceTitleCollisions();\n db.query(\"INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)\").run(\n SURFACE_BACKFILL_MIGRATION,\n new Date().toISOString(),\n );\n })();\n logger.info({ surface }, \"api_topics: surface backfilled\");\n}\n\n/**\n * Suffix duplicate `(surface, kind, title)` rows so the new uniqueness rule holds.\n *\n * Manager rooms are excluded: they are one per user, so on a multi-user host\n * every member has a personal room with the same title and none of them is a\n * duplicate. Renaming those relabels real rooms belonging to other people.\n */\nfunction renameSurfaceTitleCollisions(): void {\n const rows = db\n .query<{ id: string; title: string; kind: string; surface: string }, []>(\n \"SELECT id, title, kind, surface FROM api_topics WHERE kind != 'manager' ORDER BY created_at ASC, rowid ASC\",\n )\n .all();\n const keyOf = (surface: string, kind: string, title: string) =>\n [surface, kind, normalizedTitle(title)].join(\"\\u0000\");\n // Every original title is reserved up front. Allocating only against the\n // titles seen so far would let an earlier duplicate claim \"Foo (2)\" while a\n // real room already named \"Foo (2)\" sits later in the scan — that room would\n // then be pushed to \"Foo (2) (2)\" for no reason.\n const reserved = new Set(rows.map((row) => keyOf(row.surface, row.kind, row.title)));\n const used = new Set<string>();\n const update = db.query(\"UPDATE api_topics SET title = ? WHERE id = ?\");\n for (const row of rows) {\n const key = (title: string) => keyOf(row.surface, row.kind, title);\n if (!used.has(key(row.title))) {\n used.add(key(row.title));\n continue;\n }\n let suffix = 2;\n let candidate = `${row.title} (${suffix})`;\n while (reserved.has(key(candidate)) || used.has(key(candidate))) {\n suffix += 1;\n candidate = `${row.title} (${suffix})`;\n }\n used.add(key(candidate));\n update.run(candidate, row.id);\n logger.warn(\n { topicId: row.id, surface: row.surface, from: row.title, to: candidate },\n \"api_topics: renamed a duplicate title for surface-scoped uniqueness\",\n );\n }\n}\n\nregisterStorageSchemaInitializer(initializeApiTopicsSchema, 20);\n\nexport interface TopicRow {\n id: string;\n title: string;\n kind: string | null;\n description: string | null;\n agent: string | null;\n base_model: string | null;\n base_effort: string | null;\n response_policy: string;\n created_at: string;\n last_message_at: string | null;\n parent_topic_id: string | null;\n memory_topic_id: string | null;\n memory_key: string | null;\n is_fork: number;\n is_subagent: number;\n subagent_report_mode: string | null;\n visibility: string | null;\n surface: string | null;\n surface_scope: string | null;\n browser_profile_owner: string | null;\n session_id: string | null;\n}\n\nexport interface TopicSessionLogContext {\n reason?: string;\n queryId?: string;\n agent?: AgentKind;\n}\n\nfunction shortSessionId(sessionId: string | null | undefined): string | null {\n return sessionId ? sessionId.slice(0, 8) : null;\n}\n\nfunction getTopicParticipants(topicId: string): ParticipantDto[] {\n return db\n .query<{ user_id: string; role: \"owner\" | \"member\" }, string>(\n \"SELECT user_id, role FROM topic_members WHERE topic_id = ? ORDER BY rowid\",\n )\n .all(topicId)\n .map((row) => ({ userId: row.user_id, role: row.role }));\n}\n\nfunction getAllTopicParticipants(): Map<string, ParticipantDto[]> {\n const grouped = new Map<string, ParticipantDto[]>();\n const rows = db\n .query<{ topic_id: string; user_id: string; role: \"owner\" | \"member\" }, []>(\n \"SELECT topic_id, user_id, role FROM topic_members ORDER BY rowid\",\n )\n .all();\n for (const row of rows) {\n const participants = grouped.get(row.topic_id) ?? [];\n participants.push({ userId: row.user_id, role: row.role });\n grouped.set(row.topic_id, participants);\n }\n return grouped;\n}\n\nfunction getAllSubagentTellTargets(): Map<string, string[]> {\n const rows = db\n .query(\n \"SELECT subagent_topic_id, target_topic_id FROM subagent_tell_grants ORDER BY created_at\",\n )\n .all() as Array<{ subagent_topic_id: string; target_topic_id: string }>;\n const grouped = new Map<string, string[]>();\n for (const row of rows) {\n const targets = grouped.get(row.subagent_topic_id) ?? [];\n targets.push(row.target_topic_id);\n grouped.set(row.subagent_topic_id, targets);\n }\n return grouped;\n}\n\nfunction rowToDto(\n r: TopicRow,\n participants = getTopicParticipants(r.id),\n tellTargets?: Map<string, string[]>,\n): TopicDto {\n const normalized = normalizeTopicState({\n id: r.id,\n kind: normalizeTopicKind(r.kind),\n agent: (r.agent as AgentKind | null) ?? undefined,\n aiMode: normalizeAiMode(r.response_policy),\n });\n return {\n id: r.id,\n title: r.title,\n kind: normalized.kind,\n description: r.description ?? undefined,\n agent: normalized.agent,\n defaultModel: r.base_model ?? \"deepseek-pro\",\n defaultEffort: (r.base_effort as EffortLevel) ?? undefined,\n aiMode: normalized.aiMode,\n aiMention: aiMentionFromMode(normalized.aiMode),\n participants,\n createdAt: r.created_at,\n lastMessageAt: r.last_message_at ?? new Date().toISOString(),\n parentTopicId: r.parent_topic_id ?? undefined,\n memoryTopicId: r.memory_topic_id ?? undefined,\n memoryKey: r.memory_key ?? undefined,\n isFork: r.is_fork !== 0,\n ...(r.is_subagent !== 0 ? { isSubagent: true } : {}),\n ...(r.is_subagent !== 0\n ? {\n subagentTellTargetIds: tellTargets\n ? (tellTargets.get(r.id) ?? [])\n : listSubagentTellTargetIds(r.id),\n }\n : {}),\n ...(r.is_subagent !== 0\n ? {\n subagentReportMode: (r.subagent_report_mode === \"tell\" ||\n r.subagent_report_mode === \"status-only\"\n ? r.subagent_report_mode\n : \"auto\") as SubagentReportMode,\n }\n : {}),\n visibility: normalizeTopicVisibility(r.visibility),\n surface: normalizeTopicSurface(r.surface),\n surfaceScope: normalizeSurfaceScope(r.surface_scope),\n };\n}\n\nexport function normalizeTopicVisibility(value: unknown): TopicVisibility {\n return value === \"hidden\" ? \"hidden\" : \"visible\";\n}\n\n/** Discovery boundary shared by user-facing adapters. */\nexport function isTopicVisible(topic: Pick<TopicDto, \"visibility\">): boolean {\n return topic.visibility !== \"hidden\";\n}\n\nexport function normalizeTopicKind(value: unknown): TopicKind | null {\n return value === \"channel\" || value === \"agent\" || value === \"manager\" ? value : null;\n}\n\nexport function normalizeAiMode(value: unknown): AiMode | null {\n return value === \"off\" || value === \"mention\" || value === \"always\" ? value : null;\n}\n\nexport function aiMentionFromMode(mode: AiMode): boolean {\n return mode === \"mention\";\n}\n\nexport function inferTopicKind(input: {\n agent?: string | null;\n aiMention?: boolean | null;\n}): TopicKind {\n return input.agent && input.aiMention !== true ? \"agent\" : \"channel\";\n}\n\nexport function inferAiMode(input: {\n kind?: TopicKind | null;\n agent?: string | null;\n aiMode?: AiMode | null;\n aiMention?: boolean | null;\n}): AiMode {\n if (input.kind === \"manager\") return \"always\";\n if (input.kind === \"agent\") return \"always\";\n if (input.kind === \"channel\") {\n if (!input.agent) return \"off\";\n if (input.aiMode === \"mention\") return \"mention\";\n if (input.aiMention === true) return \"mention\";\n return \"mention\";\n }\n if (!input.agent) return \"off\";\n if (input.aiMode) return input.aiMode;\n return input.aiMention === true ? \"mention\" : \"always\";\n}\n\nexport function normalizeTopicState(input: {\n id?: string;\n kind?: TopicKind | null;\n agent?: AgentKind | null;\n aiMode?: AiMode | null;\n aiMention?: boolean | null;\n}): { kind: TopicKind; aiMode: AiMode; agent?: AgentKind } {\n if (input.kind === \"manager\" || input.id === GENERAL_TOPIC_ID) {\n return {\n kind: \"manager\",\n aiMode: \"always\",\n agent: input.agent ?? resolveFallbackAgent(),\n };\n }\n\n const requestedKind = input.kind;\n const kind =\n requestedKind ??\n (input.aiMode === \"always\"\n ? \"agent\"\n : input.aiMode === \"mention\" || input.aiMode === \"off\"\n ? \"channel\"\n : input.agent && input.aiMention !== true\n ? \"agent\"\n : \"channel\");\n\n if (kind === \"agent\") {\n return {\n kind: \"agent\",\n aiMode: \"always\",\n agent: input.agent ?? resolveFallbackAgent(),\n };\n }\n\n const agent = input.aiMode === \"off\" ? undefined : (input.agent ?? undefined);\n return {\n kind: \"channel\",\n aiMode: agent ? \"mention\" : \"off\",\n agent,\n };\n}\n\nfunction normalizedTitle(title: string): string {\n return title.trim().toLowerCase();\n}\n\n/**\n * The workspace a written row belongs to.\n *\n * `surfaceScope` partitions one surface into independent namespaces. Otium\n * uses a workspace scope and Telegram uses a forum-group scope. Terminal is\n * normally unscoped. An explicit value always wins; only Otium has a\n * process-level default because its workspace attachment is host state.\n */\nfunction surfaceScopeForWrite(t: TopicDto): string | null {\n if (t.surfaceScope !== undefined) return normalizeSurfaceScope(t.surfaceScope);\n return normalizeTopicSurface(t.surface ?? defaultTopicSurface()) === \"otium\"\n ? defaultSurfaceScope()\n : null;\n}\n\nexport function upsertTopic(t: TopicDto): void {\n const normalized = normalizeTopicState({\n id: t.id,\n kind: normalizeTopicKind(t.kind),\n agent: t.agent ?? undefined,\n aiMode: normalizeAiMode(t.aiMode),\n aiMention: t.aiMention,\n });\n db.transaction(() => {\n db.query(\n `INSERT INTO api_topics\n (id,title,kind,description,agent,base_model,base_effort,response_policy,\n created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,\n surface_scope,subagent_report_mode)\n VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)\n ON CONFLICT(id) DO UPDATE SET\n title = excluded.title,\n kind = excluded.kind,\n description = excluded.description,\n agent = excluded.agent,\n base_model = excluded.base_model,\n base_effort = excluded.base_effort,\n response_policy = excluded.response_policy,\n created_at = excluded.created_at,\n last_message_at = excluded.last_message_at,\n parent_topic_id = excluded.parent_topic_id,\n memory_topic_id = excluded.memory_topic_id,\n memory_key = excluded.memory_key,\n is_fork = excluded.is_fork,\n is_subagent = excluded.is_subagent,\n visibility = excluded.visibility,\n surface = excluded.surface,\n -- A room's workspace is fixed at creation (M-1). COALESCE, not\n -- assignment: an update may fill in a scope that was unknown when the\n -- room was created, but may never move a room to another workspace.\n surface_scope = COALESCE(api_topics.surface_scope, excluded.surface_scope),\n subagent_report_mode = excluded.subagent_report_mode`,\n ).run(\n t.id,\n t.title,\n normalized.kind,\n t.description ?? null,\n normalized.agent ?? null,\n t.defaultModel ?? null,\n t.defaultEffort ?? null,\n normalized.aiMode,\n t.createdAt,\n t.lastMessageAt ?? null,\n t.parentTopicId ?? null,\n t.memoryTopicId ?? null,\n t.memoryKey ?? null,\n t.isFork ? 1 : 0,\n t.isSubagent ? 1 : 0,\n normalizeTopicVisibility(t.visibility),\n // A DTO without a surface means \"wherever this host puts rooms\", not\n // \"terminal\": embedding hosts (Otium) build topic literals by hand and\n // never name one, so defaulting to the literal would file every hub room\n // on the wrong surface.\n normalizeTopicSurface(t.surface ?? defaultTopicSurface()),\n surfaceScopeForWrite(t),\n t.subagentReportMode ?? \"auto\",\n );\n db.query(\"DELETE FROM topic_members WHERE topic_id = ?\").run(t.id);\n for (const participant of t.participants) {\n db.query(\"INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)\").run(\n t.id,\n participant.userId,\n participant.role,\n );\n }\n const initialBrowserProfileOwner = t.participants.find(\n (participant) => participant.role === \"owner\",\n )?.userId;\n if (initialBrowserProfileOwner) {\n db.query(\n `UPDATE api_topics\n SET browser_profile_owner = COALESCE(browser_profile_owner, ?)\n WHERE id = ?`,\n ).run(initialBrowserProfileOwner, t.id);\n }\n })();\n}\n\n/**\n * List topics, optionally restricted to one surface.\n *\n * The filter lives here rather than in each adapter so a forgotten call site\n * cannot leak a telegram room into the terminal picker; adapters pass their own\n * surface and get a closed world back.\n */\nexport function listTopics(\n opts: { surface?: TopicSurface; surfaceScope?: string | null } = {},\n): TopicDto[] {\n // `surfaceScope: null` is a real filter (\"the unscoped rooms\"), so presence —\n // not truthiness — decides whether the scope narrows the query at all.\n const scoped = Object.hasOwn(opts, \"surfaceScope\");\n const rows = (\n opts.surface\n ? db\n .query(\n `SELECT * FROM api_topics WHERE surface = ?${scoped ? \" AND surface_scope IS ?\" : \"\"} ORDER BY last_message_at DESC`,\n )\n .all(\n ...(scoped\n ? [normalizeTopicSurface(opts.surface), normalizeSurfaceScope(opts.surfaceScope)]\n : [normalizeTopicSurface(opts.surface)]),\n )\n : db.query(\"SELECT * FROM api_topics ORDER BY last_message_at DESC\").all()\n ) as TopicRow[];\n const participants = getAllTopicParticipants();\n // Batch-load tell grants once: per-row queries would make every listTopics()\n // call O(N) extra statements as subagent counts grow.\n const tellTargets = rows.some((row) => row.is_subagent !== 0)\n ? getAllSubagentTellTargets()\n : undefined;\n return rows.map((row) => rowToDto(row, participants.get(row.id) ?? [], tellTargets));\n}\n\nexport function getTopic(id: string): TopicDto | null {\n const r = db.query(\"SELECT * FROM api_topics WHERE id = ?\").get(id) as TopicRow | undefined;\n return r ? rowToDto(r) : null;\n}\n\n/** Return the private manager room owned by a user, excluding the retired shared General row. */\n/**\n * The user's own manager room, optionally on one surface.\n *\n * A manager room is one per user **per surface**: Terminal and Telegram each\n * give the same person their own personal room, and returning one surface's\n * room to the other adapter lets that adapter bind to — and reclassify — a room\n * belonging to a different surface. Callers that represent an adapter pass\n * theirs; unscoped lookups stay for maintenance paths that work by user alone.\n */\nexport function getManagerTopicForUser(\n userId: string,\n surface?: TopicSurface,\n opts: { surfaceScope?: string | null } = {},\n): TopicDto | null {\n const scoped = Object.hasOwn(opts, \"surfaceScope\");\n const sql = `SELECT t.* FROM api_topics t\n JOIN topic_members m ON m.topic_id = t.id\n WHERE t.kind = 'manager'\n AND t.id != ?\n AND m.user_id = ?\n AND m.role = 'owner'\n ${surface ? \"AND t.surface = ?\" : \"\"}\n ${scoped ? \"AND t.surface_scope IS ?\" : \"\"}\n ORDER BY t.created_at ASC\n LIMIT 1`;\n const params: Array<string | null> = [GENERAL_TOPIC_ID, userId];\n if (surface) params.push(surface);\n if (scoped) params.push(normalizeSurfaceScope(opts.surfaceScope));\n const row = db.query<TopicRow, Array<string | null>>(sql).get(...params);\n return row ? rowToDto(row) : null;\n}\n\n/**\n * Resolve the topic whose wiki memory should be used for this topic.\n *\n * Derived rooms keep `parentTopicId` as an immediate UI link. Memory normally\n * follows the chain to its original root, while `memoryTopicId` can redirect a\n * subagent to another accessible topic's accumulated knowledge.\n */\nexport function getTopicMemoryOrigin(id: string): TopicDto | null {\n let current = getTopic(id);\n if (!current) return null;\n\n const seen = new Set<string>([current.id]);\n while (true) {\n const nextId = current.memoryTopicId ?? current.parentTopicId;\n if (!nextId || seen.has(nextId)) break;\n const next = getTopic(nextId);\n if (!next) {\n // An explicitly selected memory topic that no longer resolves must not\n // silently fall back to the parent chain — that would leak the parent\n // room's memory to a subagent that asked for something else. Stop at the\n // current topic instead so the broken source is visible.\n if (current.memoryTopicId) {\n console.warn(\n `[topics] memory topic ${current.memoryTopicId} for ${current.id} is unresolvable; using the topic's own memory`,\n );\n }\n break;\n }\n current = next;\n seen.add(current.id);\n }\n\n return current;\n}\n\n/** Look up a topic by its user-visible title (case-insensitive exact match). */\nexport function getTopicByName(title: string): TopicDto | null {\n const r = db.query(\"SELECT * FROM api_topics WHERE LOWER(title) = LOWER(?)\").get(title) as\n | TopicRow\n | undefined;\n return r ? rowToDto(r) : null;\n}\n\nexport function getTopicByNameAndKind(title: string, kind: TopicKind): TopicDto | null {\n const r = db\n .query(\"SELECT * FROM api_topics WHERE LOWER(title) = LOWER(?) AND kind = ?\")\n .get(title, kind) as TopicRow | undefined;\n return r ? rowToDto(r) : null;\n}\n\n/**\n * Titles are unique **per surface namespace**, not per node: the same title may\n * exist on terminal, in multiple Telegram groups, and in each attached Otium\n * workspace. Independent namespaces never see each other, so a name taken in\n * one says nothing about another.\n */\nexport function findTopicTitleConflict(\n title: string,\n kind: TopicKind,\n opts: { excludeTopicId?: string; surface?: TopicSurface; surfaceScope?: string | null } = {},\n): TopicDto | null {\n const wanted = normalizedTitle(title);\n const surface = normalizeTopicSurface(opts.surface ?? defaultTopicSurface());\n const surfaceScope = Object.hasOwn(opts, \"surfaceScope\")\n ? normalizeSurfaceScope(opts.surfaceScope)\n : surface === \"otium\"\n ? defaultSurfaceScope()\n : null;\n const generalTitleRequested = wanted === normalizedTitle(GENERAL_TOPIC_ID);\n if (generalTitleRequested && opts.excludeTopicId !== GENERAL_TOPIC_ID) {\n const general = db.query(\"SELECT * FROM api_topics WHERE id = ?\").get(GENERAL_TOPIC_ID) as\n | TopicRow\n | undefined;\n if (general) return rowToDto(general);\n }\n\n // Manager rooms are one-per-user and system-created, so several of them\n // legitimately share a title (every member's personal \"General\"). Comparing\n // them against each other is not a conflict, it is the design — on a\n // multi-user host it renamed real rooms out from under their owners.\n if (kind === \"manager\") return null;\n\n const params: Array<string | null> = [wanted, surface, surfaceScope, kind, GENERAL_TOPIC_ID];\n let sql =\n \"SELECT * FROM api_topics WHERE LOWER(TRIM(title)) = ? AND surface = ? AND surface_scope IS ? AND (kind = ? OR id = ?)\";\n if (opts.excludeTopicId) {\n sql += \" AND id != ?\";\n params.push(opts.excludeTopicId);\n }\n sql += \" LIMIT 1\";\n const row = db.query<TopicRow, string[]>(sql).get(...params);\n return row ? rowToDto(row) : null;\n}\n\n/**\n * Move topics onto a surface. Used by adapters that own a classification the\n * canonical store cannot derive on its own (the telegram chat↔topic mapping\n * lives in that adapter's database, not this one).\n */\nexport function setTopicSurfaces(topicIds: readonly string[], surface: TopicSurface): number {\n if (topicIds.length === 0) return 0;\n const normalized = normalizeTopicSurface(surface);\n let changed = 0;\n db.transaction(() => {\n const update = db.query(\"UPDATE api_topics SET surface = ? WHERE id = ? AND surface != ?\");\n for (const topicId of topicIds) {\n changed += Number(update.run(normalized, topicId, normalized).changes ?? 0);\n }\n })();\n return changed;\n}\n\n/**\n * File an existing topic into one surface namespace without changing its id.\n * Adapter-owned migrations use this when their local mapping store is the only\n * authority capable of deriving the namespace (for example Telegram chat id).\n */\nexport function setTopicSurfaceScope(\n topicId: string,\n surface: TopicSurface,\n surfaceScope: string | null,\n): boolean {\n const normalizedSurface = normalizeTopicSurface(surface);\n const normalizedScope = normalizeSurfaceScope(surfaceScope);\n const result = db\n .query(\n `UPDATE api_topics SET surface = ?, surface_scope = ?\n WHERE id = ? AND (surface IS NOT ? OR surface_scope IS NOT ?)`,\n )\n .run(normalizedSurface, normalizedScope, topicId, normalizedSurface, normalizedScope);\n return Number(result.changes ?? 0) > 0;\n}\n\n/**\n * How wide a title lookup is allowed to reach.\n *\n * `surface` is required rather than optional. It used to default to \"search\n * every surface\", which contradicted S-6's promise that a missed call site\n * \"cannot leak a topic across surfaces\" — the guarantee only held where a\n * caller remembered to opt in, and four did not: Telegram's `/load` and `/del`\n * (the latter could delete a terminal room), the runtime MCP id path, the cron\n * id path, and the session inbox. Every one of those was a silent leak with a\n * correct-looking call. Making the parameter explicit turns each future\n * omission into a compile error instead.\n *\n * `{ scope: \"all\" }` is the deliberate way to search every surface. It exists\n * for operator tooling — the CLI manages jobs across surfaces on purpose — and\n * reads as a decision at the call site rather than as an oversight.\n */\nexport type TopicNameLookupScope =\n | { surface: TopicSurface; surfaceScope?: string | null }\n | { scope: \"all\" };\n\n/**\n * Look up a topic by title, restricted to topics where `userId` participates.\n *\n * Answers only on a single match: a title is unique per surface (S-3), so an\n * `{ scope: \"all\" }` lookup of a name used on two surfaces resolves to null\n * rather than picking one.\n */\nexport function getTopicByNameForUser(\n title: string,\n userId: string,\n lookupScope: TopicNameLookupScope,\n): TopicDto | null {\n const opts: { surface?: TopicSurface; surfaceScope?: string | null } =\n \"scope\" in lookupScope ? {} : lookupScope;\n const trimmed = title.trim();\n const qualified = /^(agent|channel|manager):(.+)$/i.exec(trimmed);\n const requestedKind = qualified ? normalizeTopicKind(qualified[1]?.toLowerCase()) : null;\n const requestedTitle = qualified ? qualified[2]!.trim() : trimmed;\n const scoped = Object.hasOwn(opts, \"surfaceScope\");\n const rows = db\n .query(\n `SELECT t.* FROM api_topics t\n WHERE LOWER(t.title) = LOWER(?)\n AND t.id != ?\n AND t.visibility != 'hidden'\n AND (? IS NULL OR t.surface = ?)\n ${scoped ? \"AND t.surface_scope IS ?\" : \"\"}\n AND EXISTS (\n SELECT 1 FROM topic_members m WHERE m.topic_id = t.id AND m.user_id = ?\n )`,\n )\n .all(\n requestedTitle,\n GENERAL_TOPIC_ID,\n opts.surface ?? null,\n opts.surface ?? null,\n ...(scoped ? [normalizeSurfaceScope(opts.surfaceScope)] : []),\n userId,\n ) as TopicRow[];\n const matches = requestedKind ? rows.filter((row) => row.kind === requestedKind) : rows;\n return matches.length === 1 ? rowToDto(matches[0]!) : null;\n}\n\n/** Persist the agent session ID for a topic after a successful turn. */\nexport function setTopicSessionId(\n topicId: string,\n sessionId: string,\n context: TopicSessionLogContext = {},\n): void {\n const previous = getTopicSessionId(topicId);\n const result = db\n .query(\"UPDATE api_topics SET session_id = ? WHERE id = ?\")\n .run(sessionId, topicId);\n const changes = Number(result.changes ?? 0);\n const logContext = {\n topicId,\n previousSessionId: shortSessionId(previous),\n sessionId: shortSessionId(sessionId),\n reason: context.reason,\n queryId: context.queryId,\n agent: context.agent,\n };\n if (changes === 0) {\n logger.warn(logContext, \"api-topic session_id update missed topic\");\n } else if (previous !== sessionId) {\n logger.debug(logContext, \"api-topic session_id updated\");\n } else {\n logger.debug(logContext, \"api-topic session_id unchanged\");\n }\n}\n\n/** Clear the session ID (e.g. on topic reset). */\nexport function clearTopicSessionId(topicId: string, reason = \"unspecified\"): void {\n const previous = getTopicSessionId(topicId);\n const result = db.query(\"UPDATE api_topics SET session_id = NULL WHERE id = ?\").run(topicId);\n const changes = Number(result.changes ?? 0);\n const logContext = { topicId, previousSessionId: shortSessionId(previous), reason };\n if (changes === 0) {\n logger.warn(logContext, \"api-topic session_id clear missed topic\");\n } else if (previous) {\n logger.info(logContext, \"api-topic session_id cleared\");\n } else {\n logger.debug(logContext, \"api-topic session_id already clear\");\n }\n}\n\n/** Read the persisted session ID for a topic, or null if none. */\nexport function getTopicSessionId(topicId: string): string | null {\n const r = db\n .query<{ session_id: string | null }, string>(\"SELECT session_id FROM api_topics WHERE id = ?\")\n .get(topicId);\n return r?.session_id ?? null;\n}\n\n/**\n * Hard-delete a topic row. Irreversible — the caller is responsible for also\n * deleting the topic's messages (see `deleteMessagesForTopic`). Returns false\n * if the topic didn't exist.\n */\nexport function deleteTopic(id: string, options: { allowManager?: boolean } = {}): boolean {\n const r = db\n .query<{ id: string; kind: string }, string>(\"SELECT id, kind FROM api_topics WHERE id = ?\")\n .get(id);\n if (!r) return false;\n if (id === GENERAL_TOPIC_ID || (r.kind === \"manager\" && !options.allowManager)) return false;\n db.query(\n `DELETE FROM subagent_tell_grants\n WHERE subagent_topic_id = ? OR target_topic_id = ? OR granted_by_topic_id = ?`,\n ).run(id, id, id);\n db.query(\"DELETE FROM topic_members WHERE topic_id = ?\").run(id);\n db.query(\"DELETE FROM api_topics WHERE id = ?\").run(id);\n return true;\n}\n\nexport function listSubagentTellTargetIds(subagentTopicId: string): string[] {\n return db\n .query<{ target_topic_id: string }, string>(\n \"SELECT target_topic_id FROM subagent_tell_grants WHERE subagent_topic_id = ? ORDER BY created_at\",\n )\n .all(subagentTopicId)\n .map((row) => row.target_topic_id);\n}\n\nexport function grantSubagentTellTarget(\n subagentTopicId: string,\n targetTopicId: string,\n grantedByTopicId: string,\n): void {\n db.query(\n `INSERT INTO subagent_tell_grants\n (subagent_topic_id,target_topic_id,granted_by_topic_id,created_at)\n VALUES (?,?,?,?)\n ON CONFLICT(subagent_topic_id,target_topic_id) DO UPDATE SET\n granted_by_topic_id = excluded.granted_by_topic_id`,\n ).run(subagentTopicId, targetTopicId, grantedByTopicId, new Date().toISOString());\n}\n\nexport function revokeSubagentTellTarget(subagentTopicId: string, targetTopicId: string): boolean {\n return (\n db\n .query(\"DELETE FROM subagent_tell_grants WHERE subagent_topic_id = ? AND target_topic_id = ?\")\n .run(subagentTopicId, targetTopicId).changes > 0\n );\n}\n\n/**\n * Preserve a derived-topic chain when an intermediate parent is deleted.\n * Direct children move to the deleted topic's parent (or become roots) rather\n * than retaining a dangling parent id that would break memory-origin lookup.\n */\nexport function reparentTopicChildren(\n deletedTopicId: string,\n replacementParentTopicId: string | null,\n): string[] {\n const rows = db\n .query<{ id: string }, string>(\"SELECT id FROM api_topics WHERE parent_topic_id = ?\")\n .all(deletedTopicId);\n if (rows.length === 0) return [];\n db.query(\"UPDATE api_topics SET parent_topic_id = ? WHERE parent_topic_id = ?\").run(\n replacementParentTopicId,\n deletedTopicId,\n );\n // Reparenting can move a topic out of the subtree whose manager granted its\n // tell edges; purge involved grants (fail closed) — an ancestor can re-grant.\n for (const row of rows) {\n db.query(\n \"DELETE FROM subagent_tell_grants WHERE subagent_topic_id = ? OR target_topic_id = ?\",\n ).run(row.id, row.id);\n }\n return rows.map((row) => row.id);\n}\n\nexport function addParticipantToDB(\n topicId: string,\n userId: string,\n role: \"member\" | \"owner\",\n): boolean {\n if (!db.query(\"SELECT 1 FROM api_topics WHERE id = ?\").get(topicId)) return false;\n db.query(\"INSERT OR IGNORE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)\").run(\n topicId,\n userId,\n role,\n );\n return true;\n}\n\nexport function removeParticipantFromDB(topicId: string, userId: string): boolean {\n if (!db.query(\"SELECT 1 FROM api_topics WHERE id = ?\").get(topicId)) return false;\n db.query(\"DELETE FROM topic_members WHERE topic_id = ? AND user_id = ?\").run(topicId, userId);\n return true;\n}\n",
|
|
30
|
+
"import { accessSync, constants as fsConstants } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { canonicalMcpBridgeEnv } from \"#mcp/canonical-bridge-config\";\nimport {\n buildHostedMcpSpec,\n buildRuntimeMcpSpec,\n type HostedMcpSurface,\n RUNTIME_MCP_KEY,\n} from \"#mcp/runtime-spec\";\nimport { peerSessionBridgeIpcEnv } from \"#mcp/session-comm/bridge-ipc-config\";\nimport { bgBashContextCapability } from \"#platform/background-bash/manager\";\nimport {\n AGENT_HEALTH_SERVER,\n CANONICAL_MCP_PROXY_SERVER,\n DECISION_SERVER,\n envText,\n FALLBACK_AGENT,\n resolveTopicWorkspaceDir,\n SESSION_COMM_SERVER,\n SYSTEM_HEALTH_SERVER,\n TASK_SERVER,\n TOKEN_STATS_SERVER,\n TSCONFIG_PATH,\n TSX_LOADER,\n VAULT_SERVER,\n WIKI_SERVER,\n} from \"#platform/config\";\nimport { logger } from \"#platform/logger\";\nimport {\n classifyForumMcpServers,\n commonRuntimeMcpPolicy,\n type RuntimeMcpScope,\n} from \"#platform/mcp-catalog-policy\";\nimport { browserOwnerCapability } from \"#platform/playwright/capability\";\nimport {\n buildPlaywrightMcpTransport,\n CODEX_BROWSER_CAPABILITY_ENV,\n} from \"#platform/playwright/mcp-transport\";\nimport { getRegisteredCronSession } from \"#runtime/cron-sessions\";\nimport type { HostMcpServerSpec } from \"#runtime-gateway\";\nimport { getTopic } from \"#storage/api-topics\";\nimport type { AgentKind, AgentQueryOptions, PeerRuntimeBridgeContext } from \"#types\";\n\nexport type { RuntimeMcpScope } from \"#platform/mcp-catalog-policy\";\n\n/**\n * Build the stdio transport spec for a Otium MCP server entry.\n *\n * claude/maestro launch the .ts server directly with `bun run` (fast, native\n * TypeScript + bun:sqlite). codex CANNOT — codex 0.135's rmcp stdio client\n * fails to handshake with bun-spawned servers (initialize is dropped/raced, so\n * no tools reach the model), while pure-node servers connect reliably. So for\n * the `codex` agent we launch the SAME server file via node + tsx, passing the\n * tsconfig explicitly (servers run with cwd ≠ PROJECT_ROOT, so tsx can't find\n * it on its own) so `@/*` path aliases resolve. Per-turn agent-aware config\n * means switching agents mid-topic just works: each turn re-spawns with the\n * right runtime.\n */\nexport function buildStdioMcpServer(\n agent: AgentKind | undefined,\n serverFile: string,\n serverArgs: string[],\n env?: Record<string, string>,\n): Record<string, unknown> {\n if (agent === \"codex\") {\n return {\n command: \"node\",\n args: [\"--import\", TSX_LOADER, serverFile, ...serverArgs],\n // Merged onto codex's inherited env (not a replacement) — verified.\n env: { TSX_TSCONFIG_PATH: TSCONFIG_PATH, ...env },\n };\n }\n return {\n command: \"bun\",\n args: [\"run\", serverFile, ...serverArgs],\n ...(env ? { env } : {}),\n };\n}\n\nfunction useHostedBuiltinMcp(): boolean {\n return envText(\"NEGOTIUM_BUILTIN_MCP_TRANSPORT\") !== \"stdio\";\n}\n\nfunction buildBuiltinMcpServer(\n surface: HostedMcpSurface,\n ctx: RuntimeMcpBuildContext,\n stdio: () => Record<string, unknown>,\n): Record<string, unknown> {\n if (!useHostedBuiltinMcp()) return stdio();\n const agent = ctx.agent ?? FALLBACK_AGENT;\n return buildHostedMcpSpec(agent, surface, {\n userId: ctx.userId,\n topicTitle: ctx.session,\n ...(ctx.topicId ? { topicId: ctx.topicId } : {}),\n ...(ctx.queryId ? { queryId: ctx.queryId } : {}),\n ...(ctx.wikiTopicId ? { wikiTopicId: ctx.wikiTopicId } : {}),\n ...(ctx.subagentParentTopicId ? { subagentParentTopicId: ctx.subagentParentTopicId } : {}),\n ...(ctx.threadRootId ? { threadRootId: ctx.threadRootId } : {}),\n cwd: ctx.cwd ?? (ctx.topicId ? resolveTopicWorkspaceDir(ctx.topicId) : process.cwd()),\n agent,\n ...(ctx.model ? { model: ctx.model } : {}),\n ...(ctx.depth !== undefined ? { depth: ctx.depth } : {}),\n ...(ctx.silent !== undefined ? { silent: ctx.silent } : {}),\n ...(ctx.peerBridge ? { peerBridge: ctx.peerBridge } : {}),\n });\n}\n\n// --- Playwright unavailable notifier + per-turn state ---\n//\n// When the playwright manager fails to allocate a long-lived MCP port,\n// the catalog used to fall back to a per-turn stdio chromium that ran as\n// a child of the agent CLI subprocess — which meant Chromium was bound\n// to the agent's process tree and died on cascade-kill. We now skip the\n// browser entry entirely (the playwright entry is omitted from the\n// catalog for that turn) AND surface the gap two ways:\n//\n// 1. `notifyPlaywrightUnavailable` — fire-and-forget callback for the host\n// (telegram bot) to push an alert to the current topic. Throttled\n// per (userId, topic) with a 5-minute cooldown so a flaky\n// manager doesn't spam the chat. Per-process state — restart clears.\n//\n// 2. `consumePlaywrightUnavailable` — the system-prompt builder reads\n// this flag to add an explicit \"Playwright unavailable this turn\"\n// reminder to the agent's user message, so the model knows to\n// route around browser tools instead of hallucinating a call to a\n// tool that was silently removed from the schema list.\n\ntype PlaywrightUnavailableContext = {\n userId: string;\n topic: string | undefined;\n agent: AgentKind | undefined;\n};\n\ntype PlaywrightUnavailableNotifier = (ctx: PlaywrightUnavailableContext) => void;\n\nlet _playwrightUnavailableNotifier: PlaywrightUnavailableNotifier | undefined;\nconst _playwrightUnavailableLastNotifiedAt = new Map<string, number>();\nconst _PLAYWRIGHT_UNAVAILABLE_COOLDOWN_MS = 5 * 60_000;\n\nconst _playwrightUnavailableThisTurn = new Set<string>();\n\nfunction _playwrightUnavailableKey(userId: string, topic: string | undefined): string {\n return `${userId}:${topic ?? \"\"}`;\n}\n\n/**\n * Register the host's \"playwright unavailable\" alert sink. Called once at bot\n * startup. Idempotent — last writer wins.\n */\nexport function setPlaywrightUnavailableNotifier(cb: PlaywrightUnavailableNotifier): void {\n _playwrightUnavailableNotifier = cb;\n}\n\n/**\n * Mark the current turn as missing long-lived Playwright and notify the host.\n * The playwright catalog entry calls this when it is built without a port, but\n * route-level callers can call it earlier after ensurePlaywright fails so the\n * system prompt for the same turn can include the unavailable reminder.\n */\nexport function markPlaywrightUnavailable(ctx: PlaywrightUnavailableContext): void {\n _markPlaywrightUnavailable(ctx);\n}\n\nfunction _markPlaywrightUnavailable(ctx: PlaywrightUnavailableContext): void {\n // Mark unavailable for the next system-prompt build, regardless of\n // notifier presence (the model-side reminder must always fire so the\n // agent doesn't try to call a missing tool).\n _playwrightUnavailableThisTurn.add(_playwrightUnavailableKey(ctx.userId, ctx.topic));\n\n if (!_playwrightUnavailableNotifier) return;\n const key = _playwrightUnavailableKey(ctx.userId, ctx.topic);\n const now = Date.now();\n const last = _playwrightUnavailableLastNotifiedAt.get(key) ?? 0;\n if (now - last < _PLAYWRIGHT_UNAVAILABLE_COOLDOWN_MS) return;\n _playwrightUnavailableLastNotifiedAt.set(key, now);\n try {\n _playwrightUnavailableNotifier(ctx);\n } catch (err) {\n logger.warn({ err }, \"playwright unavailable notifier threw\");\n }\n}\n\n/**\n * Read + clear the \"playwright unavailable this turn\" flag for a\n * (user, group, topic). Used by the system-prompt builder right before\n * the agent query starts. Single consumer pattern — calling more than\n * once per turn returns `false` for the second caller (intended; the\n * reminder only needs to ride one prompt).\n */\nexport function consumePlaywrightUnavailable(userId: string, topic: string | undefined): boolean {\n const key = _playwrightUnavailableKey(userId, topic);\n if (!_playwrightUnavailableThisTurn.has(key)) return false;\n _playwrightUnavailableThisTurn.delete(key);\n return true;\n}\n\n/**\n * Single source of truth for MCP server registration.\n *\n * Each entry declares which scopes it participates in (`dm`, `forum`, `fork`, `cron`)\n * and how to build its spawn config given a context. Public helpers\n * (`getDmMcpServers`, `getForumMcpServers`, `getForkMcpServers`) and the\n * derived forum-name views read from this catalog plus the node-assigned\n * manifest overlay installed below. Adding a built-in MCP server remains a\n * one-line append here instead of touching three places.\n *\n * Conventions:\n * - `scopes` lists every scope the server should appear in by default.\n * - `forumRequired: true` keeps the server even when a forum topic\n * restricts the enabled list via `configure_mcp` (forum scope only).\n * - `build(ctx)` returns the raw transport config (Claude-SDK shape).\n * Codex callers funnel through `toCodexMcpServers` separately.\n *\n * Insertion order is preserved by `Object.entries`, which determines the\n * order of server names in user-facing displays.\n */\n\nexport interface RuntimeMcpBuildContext {\n userId: string;\n /** Product actor identity when it differs from the execution principal. */\n actorUserId?: string;\n /** Vault namespace when credentials belong to a different principal. */\n vaultUserId?: string;\n /** \"dm\" for DM scope, topic/session name for forum/fork. */\n session: string;\n /** REST/WS topic id when known. Prefer for authorization/scope checks. */\n topicId?: string;\n /** Direct parent topic id when the current topic is a subagent room. */\n subagentParentTopicId?: string;\n /** REST/WS query id when known. */\n queryId?: string;\n /** Topic id whose wiki memory should be read/written. */\n wikiTopicId?: string;\n agent?: AgentKind;\n cwd?: string;\n model?: string;\n currentUserPrompt?: string;\n depth?: number;\n playwrightPort?: number;\n playwrightCapability?: string;\n bgBashPort?: number;\n autoContinue?: boolean;\n visualTools?: boolean;\n fileDeliveryTools?: boolean;\n silent?: boolean;\n /** Thread this turn answers inside; forwarded to the runtime MCP context. */\n threadRootId?: string;\n peerBridge?: PeerRuntimeBridgeContext;\n}\n\nexport interface RuntimeMcpCatalogEntry {\n scopes: readonly RuntimeMcpScope[];\n /** Forum scope only: cannot be removed via the enabled whitelist. */\n forumRequired?: boolean;\n /**\n * Returns the raw transport spec (Claude-SDK shape), or `null` to\n * signal \"this server is unavailable for this turn — omit it from the\n * catalog entirely.\" Used by the playwright entry when the manager\n * cannot provide a long-lived port.\n */\n build(ctx: RuntimeMcpBuildContext): Record<string, unknown> | null;\n}\n\n// --- Playwright transport builders ---\n\nexport { browserOwnerCapability, buildPlaywrightMcpTransport, CODEX_BROWSER_CAPABILITY_ENV };\n\nexport function browserOwnerForContext(ctx: {\n userId?: string;\n session?: string;\n topicId?: string;\n}): string | undefined {\n if (ctx.topicId) return `topic:${ctx.topicId}`;\n if (ctx.userId && ctx.session) return `user:${ctx.userId}:${ctx.session}`;\n return undefined;\n}\n\nfunction longLivedHttpMcp(agent: AgentKind | undefined, port: number) {\n return agent === \"codex\"\n ? { url: `http://127.0.0.1:${port}/mcp` }\n : { type: \"sse\" as const, url: `http://127.0.0.1:${port}/sse` };\n}\n\n// cua-rs implements Streamable HTTP only; unlike browser-rs, it does not\n// expose the legacy SSE endpoint. The port is installed by the node-owned\n// process manager once its singleton is ready.\nlet cuaRsMcpPort: number | undefined;\n// cua-rs 0.8.0 requires `Authorization: Bearer` on /mcp, because loopback is not\n// an authorization boundary -- any local process, a web page included, could\n// otherwise drive the whole desktop. The node picks the token, hands it to the\n// child as CUA_HTTP_TOKEN, and publishes it here so turns can present it. Kept\n// beside the port because they are one fact: without both, the URL is useless.\nlet cuaRsMcpToken: string | undefined;\n\nexport function setCuaRsMcpPort(port: number | undefined, token?: string): void {\n if (port !== undefined && (!Number.isInteger(port) || port < 1 || port > 65_535)) {\n throw new Error(`invalid cua-rs MCP port: ${port}`);\n }\n cuaRsMcpPort = port;\n cuaRsMcpToken = port === undefined ? undefined : token;\n}\n\nfunction cuaRsHttpMcp(agent: AgentKind | undefined, port: number, token: string | undefined) {\n const url = `http://127.0.0.1:${port}/mcp`;\n // No token means an older cua-rs that does not ask for one. Sending the header\n // anyway would be harmless, but omitting it keeps the config honest about what\n // the running server actually requires.\n const headers = token ? { Authorization: `Bearer ${token}` } : undefined;\n // The shape is otherwise unchanged from before the token existed, including\n // `type` for codex: only the header field is added, and only when there is a\n // token to put in it. Codex spells that field `http_headers`.\n const base = { type: \"http\" as const, url };\n if (!headers) return base;\n return agent === \"codex\" ? { ...base, http_headers: headers } : { ...base, headers };\n}\n\nfunction backgroundBashTransport(\n agent: AgentKind | undefined,\n port: number,\n userId: string,\n topic: string,\n) {\n const capability = bgBashContextCapability(userId, topic);\n const headers = {\n \"X-Background-Bash-User\": userId,\n \"X-Background-Bash-Topic\": topic,\n \"X-Background-Bash-Capability\": capability,\n };\n if (agent === \"codex\") return { url: `http://127.0.0.1:${port}/mcp`, http_headers: headers };\n if (agent === \"maestro\") {\n const query = new URLSearchParams({ user: userId, topic, capability });\n return { type: \"sse\" as const, url: `http://127.0.0.1:${port}/sse?${query}` };\n }\n return { type: \"sse\" as const, url: `http://127.0.0.1:${port}/sse`, headers };\n}\n\n// --- Catalog ---\n\nconst MCP_CATALOG: Record<string, RuntimeMcpCatalogEntry> = {\n playwright: {\n ...commonRuntimeMcpPolicy(\"playwright\"),\n build({ userId, session, topicId, playwrightPort, playwrightCapability, agent }) {\n // Codex and Maestro use Streamable HTTP while Claude uses SSE. Both\n // transports terminate at the same long-lived browser/profile server.\n if (playwrightPort && playwrightCapability) {\n const owner = browserOwnerForContext({ userId, session, topicId });\n if (!owner) return null;\n return buildPlaywrightMcpTransport(playwrightPort, owner, playwrightCapability, agent);\n }\n // No port available — the playwright manager could not allocate one\n // for this turn. The previous behavior was to fall back to a per-turn\n // stdio chromium, but that made Chromium a child of the agent CLI\n // process tree, so cascade-kill on agent exit took the browser down\n // with it (visible in pm2 as \"Chromium died with claude\"). We now\n // omit the playwright entry from this turn's catalog AND fire two\n // side-effects:\n // 1. notify the host so it can push an alert into the current\n // topic (rate-limited 5min per scope key);\n // 2. mark the (user, topic) as \"playwright unavailable\n // this turn\" so the system-prompt builder can tell the model\n // explicitly, instead of letting the model hallucinate a call\n // to a tool whose schema silently vanished.\n _markPlaywrightUnavailable({\n userId,\n topic: session,\n agent,\n });\n return null;\n },\n },\n [RUNTIME_MCP_KEY]: {\n ...commonRuntimeMcpPolicy(\"runtime\"),\n build({\n userId,\n actorUserId,\n session,\n topicId,\n queryId,\n agent,\n cwd,\n model,\n currentUserPrompt,\n autoContinue,\n visualTools,\n fileDeliveryTools,\n threadRootId,\n peerBridge,\n }) {\n if (!topicId || !agent) return null;\n return buildRuntimeMcpSpec(agent, {\n // Runtime tools mutate node-owned state, so authorization stays bound\n // to the canonical execution principal. Keep the product-side human\n // actor separately for attribution instead of replacing the identity\n // that appears in this node's topic participant roster.\n userId,\n ...(actorUserId ? { actorUserId } : {}),\n topicId,\n topicTitle: session,\n queryId,\n cwd: cwd ?? resolveTopicWorkspaceDir(topicId),\n agent,\n model,\n currentUserPrompt,\n autoContinue,\n visualTools,\n fileDeliveryTools,\n ...(threadRootId ? { threadRootId } : {}),\n peerBridge,\n });\n },\n },\n \"token-stats\": {\n ...commonRuntimeMcpPolicy(\"token-stats\"),\n build(ctx) {\n return buildBuiltinMcpServer(\"token-stats\", ctx, () =>\n buildStdioMcpServer(ctx.agent, TOKEN_STATS_SERVER, [`--user-id=${ctx.userId}`]),\n );\n },\n },\n // Otium-owned shared task system. This is the only authoritative task/todo\n // surface across claude/codex/maestro; provider-native task stores are\n // blocked or ignored because they do not survive agent switches.\n task: {\n ...commonRuntimeMcpPolicy(\"task\"),\n build(ctx) {\n const { userId, session, topicId, queryId, agent, peerBridge } = ctx;\n if (peerBridge) {\n if (!topicId || !queryId) return null;\n const env = canonicalMcpBridgeEnv({\n surface: \"task\",\n userId,\n topicId,\n queryId,\n peerBridge,\n });\n return env\n ? buildStdioMcpServer(agent, CANONICAL_MCP_PROXY_SERVER, [\"--surface=task\"], env)\n : null;\n }\n const args = [`--user-id=${userId}`, `--topic=${session}`];\n if (topicId) args.push(`--topic-id=${topicId}`);\n return buildBuiltinMcpServer(\"task\", ctx, () =>\n buildStdioMcpServer(agent, TASK_SERVER, args),\n );\n },\n },\n decision: {\n ...commonRuntimeMcpPolicy(\"decision\"),\n build(ctx) {\n const { userId, session, topicId, queryId, agent, model, peerBridge } = ctx;\n if (peerBridge) {\n if (!topicId || !queryId) return null;\n const env = canonicalMcpBridgeEnv({\n surface: \"decision\",\n userId,\n topicId,\n queryId,\n peerBridge,\n });\n return env\n ? buildStdioMcpServer(agent, CANONICAL_MCP_PROXY_SERVER, [\"--surface=decision\"], env)\n : null;\n }\n const args = [\n `--user-id=${userId}`,\n `--topic=${session}`,\n `--agent=${agent ?? FALLBACK_AGENT}`,\n ];\n if (topicId) args.push(`--topic-id=${topicId}`);\n if (model) args.push(`--model=${model}`);\n return buildBuiltinMcpServer(\"decision\", ctx, () =>\n buildStdioMcpServer(agent, DECISION_SERVER, args),\n );\n },\n },\n \"session-comm\": {\n // Exposed in `manager` scope as well so the General-topic manager agent\n // can wake fresh-created topics via tell_session/ask_session right after\n // create_topic. Without this, a newly-created topic would stay in the\n // \"fresh-start ready\" state until the user manually visits it.\n ...commonRuntimeMcpPolicy(\"session-comm\"),\n build(ctx) {\n const {\n userId,\n session,\n topicId,\n subagentParentTopicId,\n agent,\n depth = 0,\n silent,\n threadRootId,\n peerBridge,\n } = ctx;\n const effectiveAgent = agent ?? FALLBACK_AGENT;\n const cronSessionId = topicId\n ? getRegisteredCronSession(topicId, effectiveAgent)?.sessionId\n : undefined;\n const args = [\n `--user-id=${userId}`,\n `--topic=${session}`,\n ...(topicId ? [`--topic-id=${topicId}`] : []),\n ...(subagentParentTopicId ? [`--subagent-parent-topic-id=${subagentParentTopicId}`] : []),\n `--depth=${depth}`,\n `--agent=${effectiveAgent}`,\n ...(cronSessionId ? [`--cron-session-id=${cronSessionId}`] : []),\n ...(silent ? [\"--reply-only=true\"] : []),\n // Turn-scoped, like `--peer-host-query-id`: this config is rebuilt for\n // every turn, so an `ask_session` raised inside a thread can record\n // where its answer belongs.\n ...(threadRootId ? [`--thread-root-id=${threadRootId}`] : []),\n ...(peerBridge ? [`--peer-host-query-id=${peerBridge.hostQueryId}`] : []),\n ];\n return buildBuiltinMcpServer(\"session-comm\", ctx, () =>\n buildStdioMcpServer(\n effectiveAgent,\n SESSION_COMM_SERVER,\n args,\n peerBridge ? peerSessionBridgeIpcEnv() : undefined,\n ),\n );\n },\n },\n wiki: {\n ...commonRuntimeMcpPolicy(\"wiki\"),\n build(ctx) {\n const { userId, session, topicId, queryId, wikiTopicId, agent, peerBridge } = ctx;\n if (peerBridge) {\n if (!topicId || !queryId) return null;\n const env = canonicalMcpBridgeEnv({\n surface: \"wiki\",\n userId,\n topicId,\n queryId,\n peerBridge,\n });\n return env\n ? buildStdioMcpServer(agent, CANONICAL_MCP_PROXY_SERVER, [\"--surface=wiki\"], env)\n : null;\n }\n const args = [`--user-id=${userId}`];\n if (topicId) args.push(`--current-topic-id=${topicId}`);\n // Prefer the REST topic id so wiki_write writes filenames and SQLite\n // briefs keyed the same way the topic wiki API reads them.\n const resolvedWikiTopicId =\n wikiTopicId ?? topicId ?? (session !== \"dm\" ? session : undefined);\n if (resolvedWikiTopicId) args.push(`--topic-id=${resolvedWikiTopicId}`);\n args.push(\"--surface=wiki\");\n return buildBuiltinMcpServer(\"wiki\", { ...ctx, wikiTopicId: resolvedWikiTopicId }, () =>\n buildStdioMcpServer(agent, WIKI_SERVER, args),\n );\n },\n },\n skills: {\n ...commonRuntimeMcpPolicy(\"skills\"),\n build(ctx) {\n const { userId, topicId, agent } = ctx;\n const args = [`--user-id=${userId}`, \"--surface=skills\"];\n if (topicId) args.push(`--topic-id=${topicId}`);\n return buildBuiltinMcpServer(\"skills\", ctx, () =>\n buildStdioMcpServer(agent, WIKI_SERVER, args),\n );\n },\n },\n \"system-health\": {\n ...commonRuntimeMcpPolicy(\"system-health\"),\n build(ctx) {\n return buildBuiltinMcpServer(\"system-health\", ctx, () =>\n buildStdioMcpServer(ctx.agent, SYSTEM_HEALTH_SERVER, []),\n );\n },\n },\n \"background-bash\": {\n ...commonRuntimeMcpPolicy(\"background-bash\"),\n build({ agent, bgBashPort, userId, topicId }) {\n // Key the whole pipeline by the canonical topic id: it flows through the\n // capability, the request context, and the completion inbox filename\n // (sessionInboxPath) so the exiting process's output is routed back to\n // the exact originating topic. A title/session fallback would be encoded\n // as if it were an id and the inbox worker would fail to resolve it, so\n // background-bash is simply unavailable without a topic id.\n if (bgBashPort === undefined || !topicId) return null;\n return backgroundBashTransport(agent, bgBashPort, userId, topicId);\n },\n },\n \"agent-health\": {\n ...commonRuntimeMcpPolicy(\"agent-health\"),\n build(ctx) {\n const { userId, agent } = ctx;\n const args = [`--user-id=${userId}`];\n return buildBuiltinMcpServer(\"agent-health\", ctx, () =>\n buildStdioMcpServer(agent, AGENT_HEALTH_SERVER, args),\n );\n },\n },\n vault: {\n ...commonRuntimeMcpPolicy(\"vault\"),\n build(ctx) {\n const { userId, vaultUserId, agent } = ctx;\n // Normal turns use {{KEY}} directly in tool inputs. Keep the Vault MCP\n // surface focused on key discovery; broker tools remain available from\n // the public factory for compatibility but are no longer the default UX.\n const args = [`--user-id=${vaultUserId ?? userId}`];\n if (agent !== \"codex\") args.push(\"--list-only=true\");\n return buildBuiltinMcpServer(\"vault\", { ...ctx, userId: vaultUserId ?? userId }, () =>\n buildStdioMcpServer(agent, VAULT_SERVER, args),\n );\n },\n },\n // macOS desktop control, delegated to maestrojeong/cua-rs rather than\n // reimplemented. The node owns one persistent Streamable HTTP process;\n // turns only receive its loopback URL and must never spawn a stdio copy.\n \"cua-rs\": {\n ...commonRuntimeMcpPolicy(\"cua-rs\"),\n build({ agent }) {\n return cuaRsMcpPort ? cuaRsHttpMcp(agent, cuaRsMcpPort, cuaRsMcpToken) : null;\n },\n },\n};\n\n/**\n * Locate the `cua-rs` binary, or `null` when it is not installed.\n *\n * Checked in order of specificity: an explicit env override for anyone running\n * a local build, then the installer's default target, then `/usr/local/bin`\n * for a `--bin-dir` install. PATH is deliberately not consulted -- the server\n * is spawned by a supervised host process whose PATH is not the user's shell\n * PATH, so a PATH lookup would succeed in a terminal and fail under pm2.\n */\nexport function resolveCuaRsBinary(platform: NodeJS.Platform = process.platform): string | null {\n if (platform !== \"darwin\") return null;\n const candidates = [\n envText(\"NEGOTIUM_CUA_RS_BIN\"),\n join(homedir(), \".local\", \"bin\", \"cua-rs\"),\n \"/usr/local/bin/cua-rs\",\n ].filter((p): p is string => Boolean(p));\n for (const candidate of candidates) {\n try {\n accessSync(candidate, fsConstants.X_OK);\n return candidate;\n } catch {\n // Not there, or not executable. Try the next one.\n }\n }\n return null;\n}\n\n// --- Derived catalog views ---\n\nexport type NodeMcpEntry =\n | { key: string; kind: \"http\"; port: number }\n | {\n key: string;\n kind: \"http-instance\";\n ensurePort: (instanceKey: string) => Promise<number>;\n }\n | { key: string; kind: \"stdio\"; command: string; args?: string[]; env?: Record<string, string> };\n\nlet nodeMcpEntries: NodeMcpEntry[] = [];\nconst resolvedNodeMcpPorts = new WeakMap<\n Extract<NodeMcpEntry, { kind: \"http-instance\" }>,\n Map<string, number>\n>();\n\n/** All forum-eligible MCP server names, in display order. */\nconst allForumMcpServerNames: string[] = [];\nexport const ALL_FORUM_MCP_SERVER_NAMES: readonly string[] = allForumMcpServerNames;\n\n/** Forum servers that cannot be removed via the enabled whitelist. */\nconst requiredForumMcpServers: string[] = [];\nexport const REQUIRED_FORUM_MCP_SERVERS: readonly string[] = requiredForumMcpServers;\n\n/** Forum servers that can be toggled via the enabled whitelist (not required). */\nconst optionalForumMcpServers: string[] = [];\nexport const OPTIONAL_FORUM_MCP_SERVERS: readonly string[] = optionalForumMcpServers;\n\nfunction refreshForumCatalogViews(): void {\n const { all, required, optional } = classifyForumMcpServers(MCP_CATALOG);\n const nodeNames = nodeMcpEntries.map((entry) => entry.key);\n const allWithNodeEntries = [...new Set([...all, ...nodeNames])];\n const optionalWithNodeEntries = [...new Set([...optional, ...nodeNames])];\n allForumMcpServerNames.splice(0, allForumMcpServerNames.length, ...allWithNodeEntries);\n requiredForumMcpServers.splice(0, requiredForumMcpServers.length, ...required);\n optionalForumMcpServers.splice(0, optionalForumMcpServers.length, ...optionalWithNodeEntries);\n}\n\nrefreshForumCatalogViews();\n\n/**\n * Mount one MCP capability supplied by an optional node module.\n *\n * Registration happens once at node startup, never in the per-event hot path.\n * The returned cleanup closure only removes the exact entry installed by this\n * call, making module stop/restart safe.\n */\nexport function registerRuntimeMcpServer(name: string, entry: RuntimeMcpCatalogEntry): () => void {\n const key = name.trim();\n if (!key || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(key)) {\n throw new Error(`invalid runtime MCP server name: ${name}`);\n }\n if (MCP_CATALOG[key]) throw new Error(`runtime MCP server already registered: ${key}`);\n MCP_CATALOG[key] = entry;\n refreshForumCatalogViews();\n return () => {\n if (MCP_CATALOG[key] !== entry) return;\n delete MCP_CATALOG[key];\n refreshForumCatalogViews();\n };\n}\n\n/**\n * Format the active MCP config for display (used by get_mcp_config /\n * get_topic_mcp / configure_mcp response).\n *\n * In whitelist mode the DB stores only the user-chosen optional servers;\n * required servers are always active but never written to the whitelist.\n * This helper surfaces that split so the model never confuses \"not in\n * whitelist\" with \"not active\".\n */\nexport function formatMcpStatus(config: {\n enabled: string[] | null;\n extra?: Record<string, unknown>;\n}): string[] {\n const extraNames = Object.keys(config.extra ?? {});\n\n if (config.enabled === null) {\n const total = ALL_FORUM_MCP_SERVER_NAMES.length + extraNames.length;\n return [\n `설정 방식: 기본값 (전체 활성)`,\n `활성 서버 (${total}개): ${[...ALL_FORUM_MCP_SERVER_NAMES, ...extraNames].join(\", \")}`,\n `추가 서버: ${extraNames.length > 0 ? extraNames.join(\", \") : \"없음\"}`,\n ];\n }\n\n // whitelist mode: stored list may or may not include required servers\n // (old entries might have them; new entries won't). Either way, split\n // by required vs optional for display.\n const availableOptional = new Set(OPTIONAL_FORUM_MCP_SERVERS);\n const optionalActive = [...new Set(config.enabled)].filter((name) => availableOptional.has(name));\n const total = REQUIRED_FORUM_MCP_SERVERS.length + optionalActive.length + extraNames.length;\n return [\n `설정 방식: whitelist`,\n `필수 서버 (항상 활성, ${REQUIRED_FORUM_MCP_SERVERS.length}개): ${REQUIRED_FORUM_MCP_SERVERS.join(\", \")}`,\n `선택 서버 (whitelist, ${optionalActive.length}개): ${optionalActive.length > 0 ? optionalActive.join(\", \") : \"없음\"}`,\n `실제 활성 합계: ${total}개`,\n `추가 서버: ${extraNames.length > 0 ? extraNames.join(\", \") : \"없음\"}`,\n ``,\n `선택 가능 서버 전체 (${OPTIONAL_FORUM_MCP_SERVERS.length}개): ${OPTIONAL_FORUM_MCP_SERVERS.join(\", \")}`,\n ];\n}\n\n// --- Builders for each scope ---\n\n// ── Node-assigned MCP servers (mcp-host manifest) ───────────────────\n//\n// The per-node MCP manifest (`negotium mcp add`) lives in @negotium/mcp-host,\n// which depends on core — so core cannot read it directly. Instead the host\n// process resolves the manifest at node start (ensuring long-lived http\n// servers are running and have ports) and installs the result here. Entries\n// then ride every eligible scope's catalog, subject to the same per-topic\n// `enabled` whitelist as optional built-ins.\n\n/** Install the node's assigned MCP servers. Last writer wins (host restart-safe). */\nexport function setNodeMcpServers(entries: NodeMcpEntry[]): void {\n nodeMcpEntries = entries.filter((entry) => !(entry.key in MCP_CATALOG));\n const dropped = entries.length - nodeMcpEntries.length;\n if (dropped > 0) {\n logger.warn({ dropped }, \"setNodeMcpServers: entries shadowing built-in catalog keys ignored\");\n }\n refreshForumCatalogViews();\n}\n\nexport function getNodeMcpServers(): readonly NodeMcpEntry[] {\n return nodeMcpEntries;\n}\n\n/** Prevent host grants from replacing node-owned MCP servers. */\nexport function isReservedRuntimeMcpServerName(name: string): boolean {\n return Object.hasOwn(MCP_CATALOG, name) || nodeMcpEntries.some((entry) => entry.key === name);\n}\n\nfunction mergeHostMcpServers(\n base: Record<string, unknown>,\n hostMcpServers: Record<string, HostMcpServerSpec> | undefined,\n): Record<string, unknown> {\n if (!hostMcpServers) return base;\n for (const name of Object.keys(hostMcpServers)) {\n if (Object.hasOwn(base, name) || isReservedRuntimeMcpServerName(name)) {\n throw new Error(`host MCP server name conflicts with node catalog: ${name}`);\n }\n }\n return { ...base, ...hostMcpServers };\n}\n\nfunction buildNodeMcpSpecs(\n agent: AgentKind | undefined,\n filter: (name: string) => boolean,\n ctx: Pick<RuntimeMcpBuildContext, \"topicId\" | \"userId\" | \"session\">,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const entry of nodeMcpEntries) {\n if (!filter(entry.key)) continue;\n if (entry.kind === \"http\") {\n out[entry.key] = longLivedHttpMcp(agent, entry.port);\n continue;\n }\n if (entry.kind === \"http-instance\") {\n const port = resolvedNodeMcpPorts.get(entry)?.get(nodeMcpInstanceKey(ctx));\n if (port !== undefined) out[entry.key] = longLivedHttpMcp(agent, port);\n continue;\n }\n out[entry.key] = {\n command: entry.command,\n args: entry.args ?? [],\n ...(entry.env ? { env: entry.env } : {}),\n };\n }\n return out;\n}\n\nfunction nodeMcpInstanceKey(\n ctx: Pick<RuntimeMcpBuildContext, \"topicId\" | \"userId\" | \"session\">,\n): string {\n return ctx.topicId ?? `user:${ctx.userId}:session:${ctx.session}`;\n}\n\n/**\n * Lazily prepare per-topic HTTP manifest entries before a provider resolves\n * its otherwise-synchronous MCP config. One failed custom server is omitted\n * from that turn without taking down the rest of the runtime catalog.\n */\nexport async function prepareNodeMcpServersForQuery(opts: AgentQueryOptions): Promise<void> {\n if (\n opts.toolPolicy ||\n opts.sessionType === \"cron\" ||\n nodeMcpEntries.every((entry) => entry.kind !== \"http-instance\")\n ) {\n return;\n }\n\n const forum = ![\"dm\", \"ephemeral\", \"manager\"].includes(opts.sessionType ?? \"forum\");\n const enabled = opts.mcpEnabled ?? null;\n const instanceKey = nodeMcpInstanceKey({\n topicId: opts.topicId,\n userId: opts.userId || \"local\",\n session: opts.session || \"default\",\n });\n\n await Promise.all(\n nodeMcpEntries.map(async (entry) => {\n if (entry.kind !== \"http-instance\") return;\n if (forum && enabled !== null && !enabled.includes(entry.key)) return;\n let ports = resolvedNodeMcpPorts.get(entry);\n if (!ports) {\n ports = new Map();\n resolvedNodeMcpPorts.set(entry, ports);\n }\n try {\n const port = await entry.ensurePort(instanceKey);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(`invalid port ${port}`);\n }\n ports.set(instanceKey, port);\n } catch (err) {\n ports.delete(instanceKey);\n logger.warn(\n { err, key: entry.key, instanceKey },\n \"node mcp: failed to prepare instance-scoped server\",\n );\n }\n }),\n );\n}\n\nfunction buildScope(\n scope: RuntimeMcpScope,\n ctx: RuntimeMcpBuildContext,\n filter: (name: string) => boolean = () => true,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [name, entry] of Object.entries(MCP_CATALOG)) {\n if (!entry.scopes.includes(scope)) continue;\n if (!filter(name)) continue;\n // `null` from build() means \"skip this server for this turn\" —\n // currently used by the playwright entry when no long-lived port\n // is available.\n const spec = entry.build(ctx);\n if (spec === null) continue;\n out[name] = spec;\n }\n // Node-assigned MCPs join every scope except cron (scheduled runs keep the\n // deliberately narrow built-in set).\n if (scope !== \"cron\") {\n Object.assign(out, buildNodeMcpSpecs(ctx.agent, filter, ctx));\n }\n return out;\n}\n\n/** DM session: catalog entries with `dm` scope, no whitelist. */\nexport function getDmMcpServers(opts: {\n userId: string;\n session?: string;\n topicId?: string;\n agent?: AgentKind;\n playwrightPort?: number;\n playwrightCapability?: string;\n}) {\n return buildScope(\"dm\", {\n userId: opts.userId,\n session: opts.session ?? \"dm\",\n topicId: opts.topicId,\n agent: opts.agent,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n });\n}\n\n/**\n * Manager session: lives in the caller's private General API topic. Owns topic CRUD,\n * invite/user admin, and cross-topic MCP toggling through `topic-admin`,\n * plus general utilities. Browser-heavy work belongs in dedicated topics, so\n * Playwright is intentionally excluded here.\n * No whitelist — manager-scope catalog entries are loaded as-is.\n */\nexport function getManagerMcpServers(opts: {\n userId: string;\n session?: string;\n topicId?: string;\n queryId?: string;\n wikiTopicId?: string;\n agent?: AgentKind;\n cwd?: string;\n model?: string;\n currentUserPrompt?: string;\n playwrightPort?: number;\n playwrightCapability?: string;\n autoContinue?: boolean;\n visualTools?: boolean;\n fileDeliveryTools?: boolean;\n}) {\n if (!opts.topicId) {\n throw new Error(\"getManagerMcpServers: private General topicId is required\");\n }\n const topicId = opts.topicId;\n return buildScope(\"manager\", {\n userId: opts.userId,\n session: opts.session ?? \"General\",\n topicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId ?? topicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.currentUserPrompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n autoContinue: opts.autoContinue,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n });\n}\n\n/**\n * Forum session: catalog entries with `forum` scope.\n * - `enabled === null` → all forum servers.\n * - `enabled` is an array → whitelist; required servers are always included.\n * - `extra` is merged on top, allowing one-off injections per topic.\n */\nexport function getForumMcpServers(opts: {\n userId: string;\n actorUserId?: string;\n vaultUserId?: string;\n session: string;\n topicId?: string;\n subagentParentTopicId?: string;\n queryId?: string;\n wikiTopicId?: string;\n agent: AgentKind;\n cwd?: string;\n model?: string;\n currentUserPrompt?: string;\n playwrightPort?: number;\n playwrightCapability?: string;\n bgBashPort?: number;\n autoContinue?: boolean;\n visualTools?: boolean;\n fileDeliveryTools?: boolean;\n threadRootId?: string;\n depth?: number;\n enabled?: string[] | null;\n extra?: Record<string, unknown>;\n silent?: boolean;\n peerBridge?: PeerRuntimeBridgeContext;\n}) {\n const {\n userId,\n actorUserId,\n vaultUserId,\n session,\n topicId,\n subagentParentTopicId,\n queryId,\n wikiTopicId,\n agent,\n cwd,\n model,\n currentUserPrompt,\n playwrightPort,\n playwrightCapability,\n depth = 0,\n enabled = null,\n extra = {},\n silent = false,\n bgBashPort,\n autoContinue,\n visualTools,\n fileDeliveryTools,\n threadRootId,\n peerBridge,\n } = opts;\n\n const filter = (name: string) => {\n if (silent && (name === \"task\" || name === \"decision\")) return false;\n if (enabled === null) return true;\n return (\n enabled.includes(name) || (REQUIRED_FORUM_MCP_SERVERS as readonly string[]).includes(name)\n );\n };\n\n const base = buildScope(\n \"forum\",\n {\n userId,\n actorUserId,\n vaultUserId,\n session,\n topicId,\n subagentParentTopicId,\n queryId,\n wikiTopicId,\n agent,\n cwd,\n model,\n currentUserPrompt,\n depth,\n playwrightPort,\n playwrightCapability,\n bgBashPort,\n autoContinue,\n visualTools,\n fileDeliveryTools,\n threadRootId,\n silent,\n peerBridge,\n },\n filter,\n );\n\n return { ...base, ...extra };\n}\n\n/**\n * Cron session: scheduled background run for a concrete API topic. Keep the\n * catalog narrower than forum scope: runtime delivery, topic memory/status,\n * vault utilities and a caller-provided disposable Playwright port.\n */\nexport function getCronMcpServers(opts: {\n userId: string;\n session: string;\n topicId: string;\n queryId?: string;\n wikiTopicId?: string;\n agent: AgentKind;\n cwd?: string;\n model?: string;\n currentUserPrompt?: string;\n playwrightPort?: number;\n playwrightCapability?: string;\n visualTools?: boolean;\n fileDeliveryTools?: boolean;\n}) {\n return buildScope(\"cron\", {\n userId: opts.userId,\n session: opts.session,\n topicId: opts.topicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId ?? opts.topicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.currentUserPrompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n autoContinue: false,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n });\n}\n\n/**\n * Pick the right MCP server bundle for an agent query. DM/ephemeral sessions\n * get the DM bundle; forum sessions get the forum bundle with full options\n * forwarded. Returned shape is the Claude-SDK shape; Codex callers funnel it\n * through their own translator (`toCodexMcpServers`).\n */\nexport function getMcpServersForQuery(opts: AgentQueryOptions): Record<string, unknown> {\n if (opts.toolPolicy === \"none\") return {};\n if (opts.toolPolicy === \"compaction-log\") {\n const compactLog = opts.mcpExtra?.compact_log;\n return compactLog ? { compact_log: compactLog } : {};\n }\n if (opts.sessionType === \"cron\") {\n if (!opts.topicId) throw new Error(\"getMcpServersForQuery: cron sessionType requires topicId\");\n return hideProviderIntrospectionForOtium(\n getCronMcpServers({\n userId: opts.userId || \"local\",\n session: opts.session || \"cron\",\n topicId: opts.topicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.prompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n }),\n opts.topicId,\n );\n }\n if (opts.sessionType === \"dm\" || opts.sessionType === \"ephemeral\") {\n return getDmMcpServers({\n userId: opts.userId || \"local\",\n session: opts.session,\n topicId: opts.topicId,\n agent: opts.agent,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n });\n }\n if (opts.sessionType === \"manager\") {\n return hideProviderIntrospectionForOtium(\n mergeHostMcpServers(\n getManagerMcpServers({\n userId: opts.userId || \"local\",\n session: opts.session,\n topicId: opts.topicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.prompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n autoContinue: opts.autoContinue,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n }),\n opts.hostMcpServers,\n ),\n opts.topicId,\n );\n }\n return hideProviderIntrospectionForOtium(\n getForumMcpServers({\n userId: opts.userId || \"local\",\n actorUserId: opts.actorUserId,\n vaultUserId: opts.vaultUserId,\n session: opts.session || \"default\",\n topicId: opts.topicId,\n subagentParentTopicId: opts.subagentParentTopicId,\n queryId: opts.queryId,\n wikiTopicId: opts.wikiTopicId,\n agent: opts.agent,\n cwd: opts.cwd,\n model: opts.model,\n currentUserPrompt: opts.prompt,\n playwrightPort: opts.playwrightPort,\n playwrightCapability: opts.playwrightCapability,\n bgBashPort: opts.bgBashPort,\n autoContinue: opts.autoContinue,\n visualTools: opts.visualTools,\n fileDeliveryTools: opts.fileDeliveryTools,\n threadRootId: opts.threadRootId,\n depth: opts.depth,\n enabled: opts.mcpEnabled,\n extra: opts.mcpExtra,\n silent: opts.silent,\n peerBridge: opts.peerBridge,\n }),\n opts.topicId,\n );\n}\n\nfunction hideProviderIntrospectionForOtium(\n servers: Record<string, unknown>,\n topicId: string | undefined,\n): Record<string, unknown> {\n if (!topicId || getTopic(topicId)?.surface !== \"otium\") return servers;\n const filtered = { ...servers };\n delete filtered[\"agent-health\"];\n delete filtered[\"token-stats\"];\n return filtered;\n}\n",
|
|
31
|
+
"import { chmodSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { VAULT_MASTER_KEY } from \"#platform/config\";\nimport { closeDatabase, Database } from \"#storage/sqlite\";\nimport { resolveStorageDataDir } from \"#storage/storage-host\";\nimport { decryptVaultValue, encryptVaultValue, isEncryptedVaultValue } from \"#storage/vault-crypto\";\n\nexport type VaultDatabase = Pick<InstanceType<typeof Database>, \"exec\" | \"prepare\">;\n\nexport interface VaultStorageOptions {\n database?: VaultDatabase;\n dataDir?: string;\n masterKey?: string;\n /** Prior keys rows may still be encrypted under; migrated onto `masterKey`. */\n legacyMasterKeys?: readonly string[];\n}\n\nlet vaultDb: VaultDatabase | undefined;\nlet vaultMasterKey = VAULT_MASTER_KEY;\n\nfunction initializeVaultDatabase(database: VaultDatabase): void {\n database.exec(\"PRAGMA journal_mode = WAL\");\n database.exec(\"PRAGMA busy_timeout = 5000\");\n database.exec(`\n CREATE TABLE IF NOT EXISTS vault (\n user_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n PRIMARY KEY (user_id, key)\n )\n `);\n\n // Migrate legacy schema where user_id was INTEGER (Telegram numeric ids only).\n // The Otium API authenticates with string user ids (\"otium-user-…\"), so user_id\n // is now TEXT for every channel. Rebuild + CAST existing rows so old Telegram\n // secrets survive; idempotent (no-op once user_id is already TEXT).\n {\n const cols = database.prepare(\"PRAGMA table_info(vault)\").all() as {\n name: string;\n type: string;\n }[];\n const uid = cols.find((c) => c.name === \"user_id\");\n if (uid && uid.type.toUpperCase() === \"INTEGER\") {\n database.exec(\"BEGIN\");\n database.exec(`\n CREATE TABLE vault_migrated (\n user_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n PRIMARY KEY (user_id, key)\n )\n `);\n database.exec(\n \"INSERT INTO vault_migrated SELECT CAST(user_id AS TEXT), key, value, description FROM vault\",\n );\n database.exec(\"DROP TABLE vault\");\n database.exec(\"ALTER TABLE vault_migrated RENAME TO vault\");\n database.exec(\"COMMIT\");\n }\n }\n}\n\nfunction openVaultDatabase(dataDir: string): VaultDatabase {\n const vaultDir = join(dataDir, \"vault\");\n const path = join(vaultDir, \"vault.db\");\n mkdirSync(vaultDir, { recursive: true, mode: 0o700 });\n const database = new Database(path, { create: true });\n // Defense in depth: the database and its sidecars are owner-only, while each\n // value is also encrypted independently by vault-crypto.\n chmodSync(path, 0o600);\n initializeVaultDatabase(database);\n return database;\n}\n\nfunction activeVaultDatabase(): VaultDatabase {\n if (!vaultDb) {\n // `resolveStorageDataDir()`, not the import-time `DATA_DIR` constant: an\n // embedding host configures its data directory during bootstrap, and any\n // vault access that happens before `configureVaultStorage()` runs would\n // otherwise pin the vault to Negotium's own state directory for the life of\n // the process — silently, since both paths are valid and writable.\n vaultDb = openVaultDatabase(resolveStorageDataDir());\n }\n return vaultDb;\n}\n\n/** Re-encrypts rows only readable under `legacyKeys` onto `targetKey`, atomically. */\nfunction migrateLegacyMasterKeys(\n database: VaultDatabase,\n targetKey: string,\n legacyKeys: readonly string[],\n): void {\n if (legacyKeys.length === 0) return;\n const rows = database.prepare(\"SELECT user_id, key, value FROM vault\").all() as {\n user_id: string;\n key: string;\n value: string;\n }[];\n\n const rewrites: { userId: string; key: string; newValue: string }[] = [];\n for (const row of rows) {\n if (!isEncryptedVaultValue(row.value)) continue; // plaintext rows are handled by decryptRow()\n try {\n decryptVaultValue(row.user_id, row.key, row.value, targetKey);\n continue; // already readable under the target key\n } catch {\n // fall through to legacy recovery below\n }\n let recovered: string | undefined;\n for (const legacyKey of legacyKeys) {\n try {\n recovered = decryptVaultValue(row.user_id, row.key, row.value, legacyKey).value;\n break;\n } catch {\n // try the next legacy key\n }\n }\n if (recovered === undefined) {\n throw new Error(\n `vault migration: row \"${row.key}\" cannot be authenticated with the target master key or any legacy key`,\n );\n }\n rewrites.push({\n userId: row.user_id,\n key: row.key,\n newValue: encryptVaultValue(row.user_id, row.key, recovered, targetKey),\n });\n }\n if (rewrites.length === 0) return;\n\n database.exec(\"BEGIN IMMEDIATE\");\n try {\n const update = database.prepare(\"UPDATE vault SET value = ? WHERE user_id = ? AND key = ?\");\n for (const rewrite of rewrites) update.run(rewrite.newValue, rewrite.userId, rewrite.key);\n database.exec(\"COMMIT\");\n } catch (error) {\n database.exec(\"ROLLBACK\");\n throw error;\n }\n}\n\n/** Configure process-wide vault storage during embedding-host bootstrap. */\nexport function configureVaultStorage(options: VaultStorageOptions): () => void {\n if (options.database && options.dataDir) {\n throw new Error(\"configureVaultStorage accepts either database or dataDir, not both\");\n }\n const previousDb = vaultDb;\n const previousMasterKey = vaultMasterKey;\n const configuredDb =\n options.database ?? openVaultDatabase(options.dataDir ?? resolveStorageDataDir());\n const targetKey = options.masterKey ?? VAULT_MASTER_KEY;\n try {\n if (options.database) initializeVaultDatabase(configuredDb);\n if (options.legacyMasterKeys && options.legacyMasterKeys.length > 0) {\n migrateLegacyMasterKeys(configuredDb, targetKey, options.legacyMasterKeys);\n }\n } catch (error) {\n // A failed migration must not leak the connection this call opened: there\n // is no dispose to hand back, so nothing else can ever close it. Only a\n // database we opened ourselves is ours to close — an injected one is\n // borrowed.\n if (!options.database) {\n closeDatabase(configuredDb as VaultDatabase & { close(throwOnError?: boolean): void });\n }\n throw error;\n }\n vaultDb = configuredDb;\n vaultMasterKey = targetKey;\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n if (!options.database && \"close\" in configuredDb) {\n closeDatabase(configuredDb as VaultDatabase & { close(throwOnError?: boolean): void });\n }\n vaultDb = previousDb;\n vaultMasterKey = previousMasterKey;\n };\n}\n\nexport interface VaultEntry {\n key: string;\n description: string;\n}\n\nexport interface VaultEntryWithValue extends VaultEntry {\n value: string;\n}\n\nexport const VAULT_KEY_PATTERN = /^[A-Z][A-Z0-9_]{0,127}$/;\nexport const VAULT_VALUE_MIN_BYTES = 4;\nexport const VAULT_VALUE_MAX_BYTES = 64 * 1024;\nexport const VAULT_DESCRIPTION_MAX_LENGTH = 500;\n\nexport function normalizeVaultKey(key: string): string {\n return key.trim().toUpperCase();\n}\n\nexport function validateVaultKey(key: string): boolean {\n return VAULT_KEY_PATTERN.test(normalizeVaultKey(key));\n}\n\nfunction decryptRow(userId: string, key: string, storedValue: string): string {\n const database = activeVaultDatabase();\n const decoded = decryptVaultValue(userId, key, storedValue, vaultMasterKey);\n if (decoded.legacyPlaintext) {\n database\n .prepare(\"UPDATE vault SET value = ? WHERE user_id = ? AND key = ? AND value = ?\")\n .run(encryptVaultValue(userId, key, decoded.value, vaultMasterKey), userId, key, storedValue);\n }\n return decoded.value;\n}\n\nexport function vaultListWithValues(userId: string): VaultEntryWithValue[] {\n const rows = activeVaultDatabase()\n .prepare(\"SELECT key, description, value FROM vault WHERE user_id = ? ORDER BY key\")\n .all(userId) as VaultEntryWithValue[];\n return rows.map((row) => ({\n key: row.key,\n description: row.description,\n value: decryptRow(userId, row.key, row.value),\n }));\n}\n\n/**\n * Return only rows that can still be authenticated with the active master key.\n *\n * This is intentionally limited to redaction indexes: one damaged credential\n * must not disable unrelated tools, while direct access to that credential\n * continues to fail closed through vaultGetValue().\n */\nexport function vaultListDecryptableValues(userId: string): VaultEntryWithValue[] {\n const rows = activeVaultDatabase()\n .prepare(\"SELECT key, description, value FROM vault WHERE user_id = ? ORDER BY key\")\n .all(userId) as VaultEntryWithValue[];\n const entries: VaultEntryWithValue[] = [];\n for (const row of rows) {\n try {\n entries.push({\n key: row.key,\n description: row.description,\n value: decryptRow(userId, row.key, row.value),\n });\n } catch {\n // A value that cannot be authenticated cannot be exposed by substitution,\n // so there is no plaintext form available to add to the redaction index.\n }\n }\n return entries;\n}\n\nexport function vaultSet(userId: string, key: string, value: string, description = \"\"): void {\n const normalizedKey = normalizeVaultKey(key);\n activeVaultDatabase()\n .prepare(\n `INSERT INTO vault (user_id, key, value, description) VALUES (?, ?, ?, ?)\n ON CONFLICT (user_id, key) DO UPDATE\n SET value = excluded.value, description = excluded.description`,\n )\n .run(\n userId,\n normalizedKey,\n encryptVaultValue(userId, normalizedKey, value, vaultMasterKey),\n description,\n );\n}\n\nexport function vaultHasKey(userId: string, key: string): boolean {\n const row = activeVaultDatabase()\n .prepare(\"SELECT 1 FROM vault WHERE user_id = ? AND key = ?\")\n .get(userId, normalizeVaultKey(key));\n return row != null;\n}\n\nexport function vaultDel(userId: string, key: string): boolean {\n const result = activeVaultDatabase()\n .prepare(\"DELETE FROM vault WHERE user_id = ? AND key = ?\")\n .run(userId, normalizeVaultKey(key)) as { changes: number };\n return result.changes > 0;\n}\n\nexport function vaultDeleteAllForUser(userId: string): number {\n const result = activeVaultDatabase()\n .prepare(\"DELETE FROM vault WHERE user_id = ?\")\n .run(userId) as {\n changes: number;\n };\n return result.changes;\n}\n\nexport function vaultList(userId: string): VaultEntry[] {\n return activeVaultDatabase()\n .prepare(\"SELECT key, description FROM vault WHERE user_id = ? ORDER BY key\")\n .all(userId) as VaultEntry[];\n}\n\nexport function vaultGetValue(userId: string, key: string): string | undefined {\n const normalizedKey = normalizeVaultKey(key);\n const row = activeVaultDatabase()\n .prepare(\"SELECT key, value FROM vault WHERE user_id = ? AND key = ?\")\n .get(userId, normalizedKey) as { key: string; value: string } | undefined;\n return row ? decryptRow(userId, row.key, row.value) : undefined;\n}\n\nexport interface VaultSubstitutionResult {\n text: string;\n usedKeys: string[];\n}\n\n/** Replace {{KEY}} placeholders and report which credentials were consumed. */\nexport function vaultSubstituteDetailed(userId: string, text: string): VaultSubstitutionResult {\n const entries = new Map<string, string | undefined>();\n const usedKeys = new Set<string>();\n const substituted = text.replace(/\\{\\{([^}]+)\\}\\}/g, (match, rawKey: string) => {\n const key = normalizeVaultKey(rawKey);\n if (!entries.has(key)) entries.set(key, vaultGetValue(userId, key));\n const value = entries.get(key);\n if (value === undefined) return match;\n usedKeys.add(key);\n return value;\n });\n return { text: substituted, usedKeys: [...usedKeys] };\n}\n\n/** Detect real {{KEY}} references without decrypting any Vault values. */\nexport function valueReferencesVaultKey(userId: string, value: unknown): boolean {\n const keys = new Set(vaultList(userId).map((entry) => entry.key));\n const visit = (candidate: unknown): boolean => {\n if (typeof candidate === \"string\") {\n for (const match of candidate.matchAll(/\\{\\{([^}]+)\\}\\}/g)) {\n if (keys.has(normalizeVaultKey(match[1] ?? \"\"))) return true;\n }\n return false;\n }\n if (Array.isArray(candidate)) return candidate.some(visit);\n if (candidate && typeof candidate === \"object\") {\n return Object.values(candidate as Record<string, unknown>).some(visit);\n }\n return false;\n };\n return visit(value);\n}\n\nfunction encodedSecretForms(value: string): string[] {\n const forms = new Set<string>([\n value,\n encodeURIComponent(value),\n Buffer.from(value, \"utf8\").toString(\"base64\"),\n Buffer.from(value, \"utf8\").toString(\"base64url\"),\n Buffer.from(value, \"utf8\").toString(\"hex\"),\n ]);\n forms.delete(\"\");\n return [...forms].sort((a, b) => b.length - a.length);\n}\n\n/** Scrub raw and common encoded forms before tool output reaches a model. */\nexport function redactVaultSecrets(userId: string, text: string): string {\n const candidates = vaultListDecryptableValues(userId)\n .flatMap((entry) => encodedSecretForms(entry.value).map((form) => ({ form, key: entry.key })))\n .sort((a, b) => b.form.length - a.form.length || a.key.localeCompare(b.key));\n if (candidates.length === 0) return text;\n const candidatesByFirstCharacter = new Map<string, typeof candidates>();\n for (const candidate of candidates) {\n const first = candidate.form[0];\n if (!first) continue;\n const bucket = candidatesByFirstCharacter.get(first) ?? [];\n bucket.push(candidate);\n candidatesByFirstCharacter.set(first, bucket);\n }\n\n let redacted = \"\";\n let offset = 0;\n while (offset < text.length) {\n const match = candidatesByFirstCharacter\n .get(text[offset] ?? \"\")\n ?.find((candidate) => text.startsWith(candidate.form, offset));\n if (!match) {\n redacted += text[offset];\n offset += 1;\n continue;\n }\n redacted += `[REDACTED:${match.key}]`;\n offset += match.form.length;\n }\n return redacted;\n}\n",
|
|
29
32
|
"import { createCipheriv, createDecipheriv, createHash, randomBytes } from \"node:crypto\";\n\nconst ENVELOPE_PREFIX = \"otium-vault:v1:\";\nconst IV_BYTES = 12;\nconst KEY_BYTES = 32;\n\nfunction encryptionKey(masterKey: string): Buffer {\n return createHash(\"sha256\")\n .update(\"otium-vault-value-v1\\0\", \"utf8\")\n .update(masterKey, \"utf8\")\n .digest()\n .subarray(0, KEY_BYTES);\n}\n\nfunction aad(userId: string, key: string): Buffer {\n return Buffer.from(`${userId}\\0${key.toUpperCase()}`, \"utf8\");\n}\n\nexport function isEncryptedVaultValue(value: string): boolean {\n return value.startsWith(ENVELOPE_PREFIX);\n}\n\nexport function encryptVaultValueWithKey(\n userId: string,\n key: string,\n value: string,\n masterKey: string,\n): string {\n const iv = randomBytes(IV_BYTES);\n const cipher = createCipheriv(\"aes-256-gcm\", encryptionKey(masterKey), iv);\n cipher.setAAD(aad(userId, key));\n const ciphertext = Buffer.concat([cipher.update(value, \"utf8\"), cipher.final()]);\n const tag = cipher.getAuthTag();\n return `${ENVELOPE_PREFIX}${iv.toString(\"base64url\")}.${ciphertext.toString(\"base64url\")}.${tag.toString(\"base64url\")}`;\n}\n\nexport function decryptVaultValueWithKey(\n userId: string,\n key: string,\n storedValue: string,\n masterKey: string,\n): { value: string; legacyPlaintext: boolean } {\n if (!isEncryptedVaultValue(storedValue)) {\n return { value: storedValue, legacyPlaintext: true };\n }\n\n const encoded = storedValue.slice(ENVELOPE_PREFIX.length);\n const [ivPart, ciphertextPart, tagPart, ...extra] = encoded.split(\".\");\n if (!ivPart || ciphertextPart === undefined || !tagPart || extra.length > 0) {\n throw new Error(\"Invalid encrypted vault value\");\n }\n\n const iv = Buffer.from(ivPart, \"base64url\");\n const ciphertext = Buffer.from(ciphertextPart, \"base64url\");\n const tag = Buffer.from(tagPart, \"base64url\");\n if (iv.length !== IV_BYTES || tag.length !== 16) {\n throw new Error(\"Invalid encrypted vault value\");\n }\n\n const decipher = createDecipheriv(\"aes-256-gcm\", encryptionKey(masterKey), iv);\n decipher.setAAD(aad(userId, key));\n decipher.setAuthTag(tag);\n const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n return { value: plaintext.toString(\"utf8\"), legacyPlaintext: false };\n}\n",
|
|
30
33
|
"import { VAULT_MASTER_KEY } from \"#platform/config\";\nimport {\n decryptVaultValueWithKey,\n encryptVaultValueWithKey,\n isEncryptedVaultValue,\n} from \"#storage/vault-crypto-core\";\n\nexport { isEncryptedVaultValue };\n\n/** Encrypt one vault row. The user/key binding prevents ciphertext row swapping. */\nexport function encryptVaultValue(\n userId: string,\n key: string,\n value: string,\n masterKey = VAULT_MASTER_KEY,\n): string {\n return encryptVaultValueWithKey(userId, key, value, masterKey);\n}\n\n/**\n * Decrypt a stored value. Plaintext rows are accepted for rolling upgrades and\n * are re-encrypted by the storage layer immediately after a successful read.\n */\nexport function decryptVaultValue(\n userId: string,\n key: string,\n storedValue: string,\n masterKey = VAULT_MASTER_KEY,\n): { value: string; legacyPlaintext: boolean } {\n return decryptVaultValueWithKey(userId, key, storedValue, masterKey);\n}\n",
|
|
31
34
|
"/**\n * Codex rollout encoder.\n *\n * Materializes a synthetic JSONL at\n * `~/.codex/sessions/<yyyy>/<mm>/<dd>/rollout-<ts>-<threadId>.jsonl` so a\n * subsequent `codex.resumeThread(threadId)` continues the cross-agent\n * conversation as if it had always been native. Verified by sandbox PoC\n * test-7c: the SDK accepts these without checksum gating, requiring only the\n * captured 5-entry SDK shell (`agents/fixtures/codex-shell.jsonl`) plus\n * synthesized `response_item`/`event_msg` pairs per turn.\n *\n * Tool history is folded into assistant text as `[Tool: ...]` annotations\n * (see shared.ts:extractChatPairs). Native same-agent forks use App Server's\n * `thread/fork`; this encoder remains the fallback and cross-agent bridge,\n * where synthetic tool_use IDs are too fragile to reconstruct structurally.\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { existsSync, readFileSync, realpathSync, statSync, unlinkSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { hostedCodexHomePath } from \"#agents/execution-host\";\nimport {\n assertUuidLike,\n type ChatPair,\n clone,\n ensureCwdExists,\n extractChatPairs,\n FIXTURES_DIR,\n} from \"#agents/rollout/shared\";\nimport { parseJsonlText, writeJsonlFile } from \"#platform/jsonl\";\nimport { logger } from \"#platform/logger\";\nimport type { ConversationEntry } from \"#storage/conversations\";\nimport type { EffortLevel } from \"#types\";\n\ninterface CodexShell {\n sessionMeta: Record<string, unknown>;\n taskStarted: Record<string, unknown>;\n developerSetup: Record<string, unknown>;\n envContext: Record<string, unknown>;\n turnContext: Record<string, unknown>;\n}\n\nfunction codexSessionsDir(): string {\n return join(hostedCodexHomePath(), \"sessions\");\n}\n\nlet _shellCache: CodexShell | null = null;\nfunction loadCodexShell(): CodexShell {\n if (_shellCache) return _shellCache;\n const raw = readFileSync(join(FIXTURES_DIR, \"codex-shell.jsonl\"), \"utf8\");\n const lines = parseJsonlText<Record<string, unknown>>(raw);\n if (lines.length < 5) {\n throw new Error(\n `loadCodexShell: expected >=5 entries in codex-shell.jsonl, got ${lines.length}`,\n );\n }\n _shellCache = {\n sessionMeta: lines[0],\n taskStarted: lines[1],\n developerSetup: lines[2],\n envContext: lines[3],\n turnContext: lines[4],\n };\n return _shellCache;\n}\n\n/** UUIDv7 (Codex thread_id format). */\nfunction uuidv7(): string {\n const ts = Date.now();\n const tsHex = ts.toString(16).padStart(12, \"0\");\n const rand = randomBytes(10);\n rand[0] = (rand[0] & 0x0f) | 0x70; // version 7\n rand[2] = (rand[2] & 0x3f) | 0x80; // variant\n return [\n tsHex.slice(0, 8),\n tsHex.slice(8, 12),\n rand.slice(0, 2).toString(\"hex\"),\n rand.slice(2, 4).toString(\"hex\"),\n rand.slice(4, 10).toString(\"hex\"),\n ].join(\"-\");\n}\n\n/** Replace captured developer metadata with the policy used for resumed turns. */\nfunction patchDeveloperSetup(developerSetup: Record<string, unknown>): void {\n const payload = developerSetup.payload as Record<string, unknown> | undefined;\n if (!payload) return;\n payload.content = [\n {\n type: \"input_text\",\n text: [\n \"<permissions instructions>\",\n \"Filesystem sandboxing is disabled for this runtime turn (`danger-full-access`).\",\n \"Approval policy is `never`.\",\n \"</permissions instructions>\",\n ].join(\"\\n\"),\n },\n ];\n}\n\n/** Mutate captured `<environment_context>` fields to the current runtime. */\nfunction patchEnvContext(\n envContext: Record<string, unknown>,\n cwd: string,\n currentDate: string,\n timezone: string,\n): void {\n const payload = envContext.payload as Record<string, unknown> | undefined;\n if (!payload) return;\n const content = payload.content as Array<Record<string, unknown>> | undefined;\n if (!Array.isArray(content)) return;\n for (const block of content) {\n if (block.type === \"input_text\" && typeof block.text === \"string\") {\n block.text = block.text\n .replace(/<cwd>[^<]*<\\/cwd>/, `<cwd>${cwd}</cwd>`)\n .replace(\n /<current_date>[^<]*<\\/current_date>/,\n `<current_date>${currentDate}</current_date>`,\n )\n .replace(/<timezone>[^<]*<\\/timezone>/, `<timezone>${timezone}</timezone>`);\n }\n }\n}\n\nexport interface CodexRolloutOptions {\n /** Working directory the resumed Codex thread will report. */\n cwd: string;\n /** Optional override; default = freshly generated UUIDv7. */\n threadId?: string;\n /** Override extracted pairs. */\n pairs?: ChatPair[];\n /** Source UnifiedEvent log when `pairs` is omitted. */\n entries?: ConversationEntry[];\n /** Effective model/effort that Codex will use when this thread is resumed. */\n model?: string;\n effort?: EffortLevel;\n}\n\nexport interface CodexRolloutResult {\n threadId: string;\n rolloutPath: string;\n}\n\nexport interface CodexContextUsage {\n contextTokens: number;\n contextWindow: number;\n}\n\nexport interface CodexTokenTotals {\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens: number;\n cacheWriteInputTokens: number;\n}\n\nexport interface CodexPatchChangePreview {\n path: string;\n before?: string;\n after?: string;\n diffPreview?: string;\n}\n\nexport interface CodexPatchPreview {\n callId: string;\n changes: CodexPatchChangePreview[];\n}\n\nfunction codexRolloutPath(threadId: string, fallback: Date): string {\n const threadCreatedAt = decodeUuidV7Timestamp(threadId);\n const createdAt = threadCreatedAt === null ? fallback : new Date(threadCreatedAt);\n const yyyy = String(createdAt.getFullYear());\n const mm = String(createdAt.getMonth() + 1).padStart(2, \"0\");\n const dd = String(createdAt.getDate()).padStart(2, \"0\");\n const hh = String(createdAt.getHours()).padStart(2, \"0\");\n const min = String(createdAt.getMinutes()).padStart(2, \"0\");\n const ss = String(createdAt.getSeconds()).padStart(2, \"0\");\n const dir = join(codexSessionsDir(), yyyy, mm, dd);\n return join(dir, `rollout-${yyyy}-${mm}-${dd}T${hh}-${min}-${ss}-${threadId}.jsonl`);\n}\n\nfunction canonicalFilePath(path: string): string {\n const absolute = resolve(path);\n try {\n return realpathSync(absolute);\n } catch {\n try {\n return join(realpathSync(dirname(absolute)), basename(absolute));\n } catch {\n return absolute;\n }\n }\n}\n\nfunction changedPatchLines(value: string): Omit<CodexPatchChangePreview, \"path\"> {\n const removed: string[] = [];\n const added: string[] = [];\n const diffPreview: string[] = [];\n let oldLine = 0;\n let newLine = 0;\n let sawHunk = false;\n for (const line of value.split(\"\\n\")) {\n const hunk = /^@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/.exec(line);\n if (hunk) {\n if (sawHunk) diffPreview.push(\"…\");\n sawHunk = true;\n oldLine = Number.parseInt(hunk[1] ?? \"0\", 10);\n newLine = Number.parseInt(hunk[2] ?? \"0\", 10);\n continue;\n }\n if (!sawHunk && (line.startsWith(\"--- \") || line.startsWith(\"+++ \"))) continue;\n if (line.startsWith(\"\\\\ No newline\")) continue;\n if (line.startsWith(\"-\")) {\n removed.push(line.slice(1));\n diffPreview.push(`${oldLine} -${line.slice(1)}`);\n oldLine += 1;\n continue;\n }\n if (line.startsWith(\"+\")) {\n added.push(line.slice(1));\n diffPreview.push(`${newLine} +${line.slice(1)}`);\n newLine += 1;\n continue;\n }\n if (line.startsWith(\" \")) {\n diffPreview.push(`${newLine} ${line.slice(1)}`);\n oldLine += 1;\n newLine += 1;\n }\n }\n return {\n ...(removed.length > 0 ? { before: removed.join(\"\\n\") } : {}),\n ...(added.length > 0 ? { after: added.join(\"\\n\") } : {}),\n ...(diffPreview.length > 0 ? { diffPreview: diffPreview.join(\"\\n\") } : {}),\n };\n}\n\n/**\n * Extract the newest native apply_patch result matching a Codex file_change.\n *\n * The public SDK intentionally reduces file changes to path + kind, while the\n * native rollout keeps the exact unified diff in patch_apply_end. Reading that\n * payload preserves the real per-edit +/- lines even when the topic cwd itself\n * is not a Git repository.\n */\nexport function extractLatestCodexPatchPreview(\n jsonl: string,\n expectedPaths: string[],\n consumedCallIds: ReadonlySet<string> = new Set(),\n expectedCallId?: string,\n): CodexPatchPreview | undefined {\n const expected = expectedPaths.map(canonicalFilePath);\n const lines = jsonl.trimEnd().split(\"\\n\");\n for (let index = lines.length - 1; index >= 0; index -= 1) {\n try {\n const entry = JSON.parse(lines[index] ?? \"\") as {\n type?: string;\n payload?: {\n type?: string;\n call_id?: string;\n changes?: Record<\n string,\n { type?: string; unified_diff?: string; content?: string; move_path?: string | null }\n >;\n };\n };\n if (entry.type !== \"event_msg\" || entry.payload?.type !== \"patch_apply_end\") continue;\n const callId = entry.payload.call_id;\n const rawChanges = entry.payload.changes;\n if (\n !callId ||\n consumedCallIds.has(callId) ||\n (expectedCallId !== undefined && callId !== expectedCallId) ||\n !rawChanges\n ) {\n continue;\n }\n\n const entries = Object.entries(rawChanges);\n const matched = expected.map((path) =>\n entries.find(([candidate]) => canonicalFilePath(candidate) === path),\n );\n const complete = matched.filter(\n (change): change is NonNullable<typeof change> => change !== undefined,\n );\n if (complete.length !== expected.length) continue;\n\n return {\n callId,\n changes: complete.map(([path, change]) => {\n if (typeof change.unified_diff === \"string\") {\n return { path, ...changedPatchLines(change.unified_diff) };\n }\n const content =\n typeof change.content === \"string\" ? change.content.replace(/\\n$/, \"\") : undefined;\n return {\n path,\n ...(change.type === \"delete\" && content !== undefined ? { before: content } : {}),\n ...(change.type === \"add\" && content !== undefined ? { after: content } : {}),\n };\n }),\n };\n } catch {\n // A concurrently appended final line may be incomplete; keep scanning.\n }\n }\n return undefined;\n}\n\nexport function extractCodexPatchCallIds(jsonl: string): string[] {\n const callIds: string[] = [];\n for (const line of jsonl.trimEnd().split(\"\\n\")) {\n try {\n const entry = JSON.parse(line) as {\n type?: string;\n payload?: { type?: string; call_id?: string };\n };\n if (\n entry.type === \"event_msg\" &&\n entry.payload?.type === \"patch_apply_end\" &&\n typeof entry.payload.call_id === \"string\"\n ) {\n callIds.push(entry.payload.call_id);\n }\n } catch {\n // A concurrently appended final line may be incomplete.\n }\n }\n return callIds;\n}\n\n/** List native patch calls that already existed before a resumed turn. */\nexport function readCodexPatchCallIds(threadId: string): string[] {\n const path = latestCodexRolloutPath(threadId);\n if (!path) return [];\n try {\n return extractCodexPatchCallIds(readFileSync(path, \"utf8\"));\n } catch (error) {\n logger.debug({ error, threadId }, \"codex patch ids: rollout read failed\");\n return [];\n }\n}\n\n/** Resolve a thread's newest native apply_patch preview. */\nexport function readLatestCodexPatchPreview(\n threadId: string,\n expectedPaths: string[],\n consumedCallIds: ReadonlySet<string> = new Set(),\n expectedCallId?: string,\n): CodexPatchPreview | undefined {\n const path = latestCodexRolloutPath(threadId);\n if (!path) return undefined;\n try {\n return extractLatestCodexPatchPreview(\n readFileSync(path, \"utf8\"),\n expectedPaths,\n consumedCallIds,\n expectedCallId,\n );\n } catch (error) {\n logger.debug({ error, threadId }, \"codex patch preview: rollout read failed\");\n return undefined;\n }\n}\n\n/** Read the latest per-request context measurement from a Codex rollout. */\nexport function extractLatestCodexContextUsage(jsonl: string): CodexContextUsage | undefined {\n const lines = jsonl.trimEnd().split(\"\\n\");\n for (let index = lines.length - 1; index >= 0; index -= 1) {\n try {\n const entry = JSON.parse(lines[index] ?? \"\") as {\n type?: string;\n payload?: {\n type?: string;\n info?: {\n last_token_usage?: { total_tokens?: number };\n model_context_window?: number;\n };\n };\n };\n if (entry.type !== \"event_msg\" || entry.payload?.type !== \"token_count\") continue;\n const contextTokens = entry.payload.info?.last_token_usage?.total_tokens;\n const contextWindow = entry.payload.info?.model_context_window;\n if (\n typeof contextTokens === \"number\" &&\n Number.isFinite(contextTokens) &&\n contextTokens >= 0 &&\n typeof contextWindow === \"number\" &&\n Number.isFinite(contextWindow) &&\n contextWindow > 0\n ) {\n return { contextTokens, contextWindow };\n }\n } catch {\n // A concurrently appended final line may be incomplete; keep scanning.\n }\n }\n return undefined;\n}\n\n/** Latest cumulative token counter persisted in a native Codex rollout. */\nexport function extractLatestCodexTokenTotals(jsonl: string): CodexTokenTotals | undefined {\n const lines = jsonl.trimEnd().split(\"\\n\");\n for (let index = lines.length - 1; index >= 0; index -= 1) {\n try {\n const entry = JSON.parse(lines[index] ?? \"\") as {\n type?: string;\n payload?: {\n type?: string;\n info?: {\n total_token_usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cached_input_tokens?: number;\n cache_write_input_tokens?: number;\n };\n };\n };\n };\n if (entry.type !== \"event_msg\" || entry.payload?.type !== \"token_count\") continue;\n const usage = entry.payload.info?.total_token_usage;\n if (!usage) continue;\n const values = [\n usage.input_tokens,\n usage.output_tokens,\n usage.cached_input_tokens,\n usage.cache_write_input_tokens,\n ];\n if (values.some((value) => value !== undefined && (!Number.isFinite(value) || value < 0))) {\n continue;\n }\n return {\n inputTokens: usage.input_tokens ?? 0,\n outputTokens: usage.output_tokens ?? 0,\n cachedInputTokens: usage.cached_input_tokens ?? 0,\n cacheWriteInputTokens: usage.cache_write_input_tokens ?? 0,\n };\n } catch {\n // A concurrently appended final line may be incomplete; keep scanning.\n }\n }\n return undefined;\n}\n\n/** Resolve a thread's current rollout and return its latest context measurement. */\nexport function readLatestCodexContextUsage(threadId: string): CodexContextUsage | undefined {\n const path = latestCodexRolloutPath(threadId);\n if (!path) return undefined;\n try {\n return extractLatestCodexContextUsage(readFileSync(path, \"utf8\"));\n } catch (error) {\n logger.debug({ error, threadId }, \"codex context usage: rollout read failed\");\n return undefined;\n }\n}\n\nexport function readLatestCodexTokenTotals(threadId: string): CodexTokenTotals | undefined {\n const path = latestCodexRolloutPath(threadId);\n if (!path) return undefined;\n try {\n return extractLatestCodexTokenTotals(readFileSync(path, \"utf8\"));\n } catch (error) {\n logger.debug({ error, threadId }, \"codex token totals: rollout read failed\");\n return undefined;\n }\n}\n\n/**\n * Old and metadata-free Codex rollouts resume as native multi-agent v1 even\n * when the feature flag is false. Rewrite their runtime metadata in place so\n * the same thread can resume without losing provider conversation history.\n */\nexport function migrateCodexRolloutNativeMultiAgentMetadata(threadId: string): boolean {\n const path = latestCodexRolloutPath(threadId);\n if (!path) return false;\n try {\n const entries = parseJsonlText<{\n type?: string;\n payload?: Record<string, unknown>;\n }>(readFileSync(path, \"utf8\"));\n let changed = false;\n for (const entry of entries) {\n if (entry.type !== \"session_meta\" && entry.type !== \"turn_context\") continue;\n if (!entry.payload) entry.payload = {};\n if (entry.payload.multi_agent_version !== \"disabled\") {\n entry.payload.multi_agent_version = \"disabled\";\n changed = true;\n }\n }\n if (changed) {\n writeJsonlFile(path, entries);\n logger.info({ threadId, path }, \"codex rollout native multi-agent metadata disabled\");\n }\n return changed;\n } catch (error) {\n logger.error({ error, threadId, path }, \"codex rollout native multi-agent migration failed\");\n throw new Error(`Failed to migrate Codex rollout '${threadId}'`, { cause: error });\n }\n}\n\nexport function latestCodexRolloutPath(threadId: string): string | undefined {\n const sessionsDir = codexSessionsDir();\n const candidates: string[] = [];\n const buckets = candidateDateBuckets(threadId);\n try {\n if (buckets) {\n for (const bucket of buckets) {\n const dir = join(sessionsDir, bucket);\n if (!existsSync(dir)) continue;\n const glob = new Bun.Glob(`rollout-*-${threadId}.jsonl`);\n for (const rel of glob.scanSync({ cwd: dir, onlyFiles: true })) {\n candidates.push(join(dir, rel));\n }\n }\n }\n // The UUIDv7 timestamp is UTC, but Codex names session directories by the\n // local date, so a session opened in the evening of a negative-offset\n // timezone lands in the previous day's bucket. When the date-derived\n // buckets miss (or none were computed), fall back to a whole-tree scan so\n // that skew never silently drops the rollout.\n if (candidates.length === 0) {\n const glob = new Bun.Glob(`**/rollout-*-${threadId}.jsonl`);\n for (const rel of glob.scanSync({ cwd: sessionsDir, onlyFiles: true })) {\n candidates.push(join(sessionsDir, rel));\n }\n }\n return candidates.sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs)[0];\n } catch (error) {\n logger.debug({ error, threadId }, \"codex rollout lookup failed\");\n return undefined;\n }\n}\n\n/**\n * Materialize a Codex rollout JSONL with the provided dialogue and place it\n * at `~/.codex/sessions/<yyyy>/<mm>/<dd>/rollout-<ts>-<threadId>.jsonl` so a\n * subsequent `codex.resumeThread(threadId)` continues the conversation.\n */\nexport function writeCodexRollout(opts: CodexRolloutOptions): CodexRolloutResult {\n const threadId = opts.threadId ?? uuidv7();\n assertUuidLike(\"threadId\", threadId);\n ensureCwdExists(opts.cwd);\n const pairs = opts.pairs ?? extractChatPairs(opts.entries ?? []);\n const now = new Date();\n const tsIso = now.toISOString();\n const currentDate = [\n now.getFullYear(),\n String(now.getMonth() + 1).padStart(2, \"0\"),\n String(now.getDate()).padStart(2, \"0\"),\n ].join(\"-\");\n const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || process.env.TZ || \"UTC\";\n\n // Captured 5-entry SDK shell (session_meta, task_started, developer setup,\n // environment_context, turn_context). Cloned per call so the cached\n // fixture is never mutated; only id/timestamp/cwd are patched.\n const shell = loadCodexShell();\n const sessionMeta = clone(shell.sessionMeta);\n (sessionMeta.payload as Record<string, unknown>).id = threadId;\n (sessionMeta.payload as Record<string, unknown>).timestamp = tsIso;\n (sessionMeta.payload as Record<string, unknown>).cwd = opts.cwd;\n (sessionMeta.payload as Record<string, unknown>).multi_agent_version = \"disabled\";\n (sessionMeta as Record<string, unknown>).timestamp = tsIso;\n\n const taskStarted = clone(shell.taskStarted);\n (taskStarted as Record<string, unknown>).timestamp = tsIso;\n\n const developerSetup = clone(shell.developerSetup);\n (developerSetup as Record<string, unknown>).timestamp = tsIso;\n patchDeveloperSetup(developerSetup);\n\n const envContext = clone(shell.envContext);\n (envContext as Record<string, unknown>).timestamp = tsIso;\n patchEnvContext(envContext, opts.cwd, currentDate, timezone);\n\n const turnContext = clone(shell.turnContext);\n (turnContext as Record<string, unknown>).timestamp = tsIso;\n const turnPayload = turnContext.payload as Record<string, unknown>;\n turnPayload.cwd = opts.cwd;\n turnPayload.current_date = currentDate;\n turnPayload.timezone = timezone;\n turnPayload.approval_policy = \"never\";\n turnPayload.sandbox_policy = { type: \"danger-full-access\" };\n turnPayload.multi_agent_version = \"disabled\";\n delete turnPayload.permission_profile;\n if (opts.model) turnPayload.model = opts.model;\n const collaborationMode = turnPayload.collaboration_mode as Record<string, unknown> | undefined;\n const collaborationSettings = collaborationMode?.settings as Record<string, unknown> | undefined;\n if (collaborationSettings) {\n if (opts.model) collaborationSettings.model = opts.model;\n if (opts.effort !== undefined) collaborationSettings.reasoning_effort = opts.effort;\n }\n\n const lines: unknown[] = [sessionMeta, taskStarted, developerSetup, envContext, turnContext];\n\n for (const pair of pairs) {\n lines.push({\n timestamp: tsIso,\n type: \"response_item\",\n payload: {\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text: pair.userText }],\n },\n });\n lines.push({\n timestamp: tsIso,\n type: \"event_msg\",\n payload: {\n type: \"user_message\",\n message: pair.userText,\n images: [],\n local_images: [],\n text_elements: [],\n },\n });\n lines.push({\n timestamp: tsIso,\n type: \"event_msg\",\n payload: {\n type: \"agent_message\",\n message: pair.assistantText,\n phase: \"final_answer\",\n memory_citation: null,\n },\n });\n lines.push({\n timestamp: tsIso,\n type: \"response_item\",\n payload: {\n type: \"message\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: pair.assistantText }],\n phase: \"final_answer\",\n },\n });\n }\n\n lines.push({\n timestamp: tsIso,\n type: \"event_msg\",\n payload: { type: \"task_complete\" },\n });\n\n // Codex indexes a thread by the local wall-clock timestamp encoded in its\n // UUIDv7 creation time. A cross-agent round-trip may rewrite the rollout\n // much later, but the path must remain the original canonical path or\n // `thread/resume` rejects it as missing and the provider starts fresh.\n const path = codexRolloutPath(threadId, now);\n\n // Round-trip cleanup: when the caller reused a threadId (claude→codex→...\n // or maestro→codex→... cycles via `findLastSessionIdForAgent`), the SDK's\n // original rollout for that threadId still sits at its canonical path.\n // Sweep every prior file for this threadId BEFORE replacing that path so\n // legacy writers cannot leave ambiguous duplicates behind.\n //\n // Synchronous on purpose: writeCodexRollout's signature is sync (called\n // inside set_agent's DB transaction), and an async sweep would race with\n // the following `writeJsonlFile` — Bun.Glob would re-scan once the\n // microtask queue drains and could unlink the file we just wrote if today\n // and the original-write-date are the same. Sync glob/unlink completes\n // before the new file ever lands on disk.\n //\n // Only runs when `opts.threadId` was supplied; fresh-mint threadIds can't\n // have prior files. Errors are logged but non-fatal — losing the sweep on\n // a permission glitch is preferable to crashing the whole switch.\n if (opts.threadId) {\n sweepPriorRolloutsForThread(opts.threadId);\n }\n\n writeJsonlFile(path, lines);\n logger.info(\n { threadId, path, pairs: pairs.length },\n \"writeCodexRollout: synthetic rollout placed\",\n );\n return { threadId, rolloutPath: path };\n}\n\n/**\n * Synchronous unlink of every existing `rollout-*-<threadId>.jsonl` under\n * `~/.codex/sessions/**`. Same glob shape `codexRegistry.cleanupRollouts`\n * uses (kept duplicate rather than imported to avoid the registry → rollout\n * → registry cycle).\n */\nfunction sweepPriorRolloutsForThread(threadId: string): void {\n const sessionsDir = codexSessionsDir();\n const buckets = candidateDateBuckets(threadId);\n if (!buckets) {\n // Couldn't pin a date from the threadId — fall back to the safer (but\n // much slower) whole-tree scan so we still find every prior rollout.\n sweepPriorRolloutsFullTree(threadId, sessionsDir);\n return;\n }\n for (const bucket of buckets) {\n const dir = join(sessionsDir, bucket);\n if (!existsSync(dir)) continue;\n try {\n const glob = new Bun.Glob(`rollout-*-${threadId}.jsonl`);\n for (const rel of glob.scanSync({ cwd: dir, onlyFiles: true })) {\n const fullPath = join(dir, rel);\n try {\n unlinkSync(fullPath);\n } catch (e) {\n if ((e as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n logger.warn(\n { err: e, path: fullPath },\n \"writeCodexRollout: prior-rollout unlink failed (continuing)\",\n );\n }\n }\n }\n } catch (e) {\n logger.warn(\n { err: e, threadId, bucket },\n \"writeCodexRollout: prior-rollout bucket scan failed (continuing)\",\n );\n }\n }\n}\n\n/** Legacy whole-tree scan. Used only when `candidateDateBuckets` can't pin a\n * date set from the threadId (non-UUIDv7 ids, e.g. some test fixtures). */\nfunction sweepPriorRolloutsFullTree(threadId: string, sessionsDir: string): void {\n try {\n const glob = new Bun.Glob(`**/rollout-*-${threadId}.jsonl`);\n for (const rel of glob.scanSync({ cwd: sessionsDir, onlyFiles: true })) {\n const fullPath = join(sessionsDir, rel);\n try {\n unlinkSync(fullPath);\n } catch (e) {\n if ((e as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n logger.warn(\n { err: e, path: fullPath },\n \"writeCodexRollout: prior-rollout unlink failed (continuing)\",\n );\n }\n }\n }\n } catch (e) {\n logger.warn(\n { err: e, threadId },\n \"writeCodexRollout: full-tree prior-rollout sweep failed (continuing)\",\n );\n }\n}\n\n/**\n * UUIDv7 ids encode their creation time in the first 48 bits. Current writers\n * always use that canonical birth-date bucket, but older writers used the\n * rewrite date during cross-agent bridges. Enumerate the inclusive range from\n * birth date to today so cleanup also removes those legacy misplaced files.\n *\n * Returns null when:\n * - threadId isn't a parseable UUIDv7 (atypical fixture / future format)\n * - the day span exceeds MAX_DAY_SPAN (a month+-old re-bridge isn't worth\n * per-day enumeration; safer to scan the full tree than to enumerate\n * hundreds of dirs and still maybe miss something)\n * In both cases the caller falls back to the whole-tree sweep so safety\n * never degrades below the original implementation.\n */\nconst MAX_DAY_SPAN = 30;\nconst DAY_MS = 86_400_000;\nconst LOCAL_DATE_SKEW_DAYS = 1;\n\nfunction candidateDateBuckets(threadId: string): Set<string> | null {\n const tidMs = decodeUuidV7Timestamp(threadId);\n if (tidMs === null) return null;\n const nowMs = Date.now();\n // Day-floor each end so DST / minutes-of-day noise doesn't bloat the span.\n const tidDay = Math.floor(tidMs / DAY_MS);\n const todayDay = Math.floor(nowMs / DAY_MS);\n const minDay = Math.min(tidDay, todayDay);\n const maxDay = Math.max(tidDay, todayDay);\n const span = maxDay - minDay;\n if (span > MAX_DAY_SPAN) return null;\n const buckets = new Set<string>();\n // Codex buckets sessions by local calendar date while UUIDv7 timestamps are\n // UTC. Include one day on each edge so every date-bucketed caller (context\n // usage, migration, and prior-rollout cleanup) covers timezone skew without\n // falling back to a whole-tree scan.\n for (let d = minDay - LOCAL_DATE_SKEW_DAYS; d <= maxDay + LOCAL_DATE_SKEW_DAYS; d++) {\n buckets.add(formatDateBucket(new Date(d * DAY_MS)));\n }\n return buckets;\n}\n\n/**\n * Decode the 48-bit unix-ms timestamp out of a UUIDv7. The first 12 hex\n * chars of the dash-separated form are the timestamp. Returns null when the\n * input doesn't look like a UUIDv7 or the decoded value is outside a\n * plausibility window (defensive: a malformed id that fits the regex but\n * decodes to year 1972 would point the sweep at a non-existent bucket —\n * better to fall back to the whole-tree scan than to silently no-op).\n *\n * Exported for tests.\n */\nexport function decodeUuidV7Timestamp(threadId: string): number | null {\n if (typeof threadId !== \"string\") return null;\n const m =\n /^([0-9a-fA-F]{8})-([0-9a-fA-F]{4})-7[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.exec(\n threadId,\n );\n if (!m) return null;\n const hex = `${m[1]}${m[2]}`;\n const ms = Number.parseInt(hex, 16);\n if (!Number.isFinite(ms)) return null;\n const MIN = 1577836800000; // 2020-01-01T00:00:00Z\n const MAX = 4102444800000; // 2100-01-01T00:00:00Z\n if (ms < MIN || ms > MAX) return null;\n return ms;\n}\n\nfunction formatDateBucket(d: Date): string {\n const yyyy = d.getUTCFullYear();\n const mm = String(d.getUTCMonth() + 1).padStart(2, \"0\");\n const dd = String(d.getUTCDate()).padStart(2, \"0\");\n return `${yyyy}/${mm}/${dd}`;\n}\n\n/** Internal export for tests. */\nexport const __candidateDateBuckets = candidateDateBuckets;\n",
|
|
32
35
|
"import {\n appendFileSync,\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { safeUnlink } from \"#platform/file-utils\";\n\nexport function readJsonlLines(filePath: string): string[] {\n return readFileSync(filePath, \"utf-8\").trim().split(\"\\n\").filter(Boolean);\n}\n\n/**\n * Parse a JSONL string (one JSON value per line) into an array of `T`.\n * Throws on malformed lines — use when a corrupt fixture/log should fail\n * loudly rather than silently drop entries (paired with `readJsonlLines`'\n * resilient counterpart for live data streams).\n */\nexport function parseJsonlText<T = unknown>(raw: string): T[] {\n return raw\n .trim()\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line) as T);\n}\n\n/**\n * Read and JSON-parse a file. Returns null if the file is missing or contains\n * invalid JSON. Use when a missing/corrupt file should fall through to a\n * default rather than throw.\n */\nexport function readJsonFile<T = unknown>(filePath: string): T | null {\n try {\n return JSON.parse(readFileSync(filePath, \"utf-8\")) as T;\n } catch {\n return null;\n }\n}\n\n/** Atomically replace a JSON file and fsync the new contents before rename. */\nexport function writeJsonFileAtomic(filePath: string, value: unknown): void {\n const dir = dirname(filePath);\n mkdirSync(dir, { recursive: true });\n const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}-${Math.random()\n .toString(16)\n .slice(2)}`;\n let fd: number | null = null;\n try {\n fd = openSync(tmpPath, \"wx\", 0o600);\n writeFileSync(fd, JSON.stringify(value, null, 2));\n fsyncSync(fd);\n closeSync(fd);\n fd = null;\n renameSync(tmpPath, filePath);\n fsyncDirectoryBestEffort(dir);\n } catch (err) {\n if (fd !== null) {\n try {\n closeSync(fd);\n } catch {}\n }\n safeUnlink(tmpPath);\n throw err;\n }\n}\n\n// --- Cross-process append lock ---\n// POSIX `O_APPEND` is only atomic when the write payload fits in PIPE_BUF\n// (Linux 4096, macOS 512). MCP servers and the bot run as separate\n// processes that all `appendFileSync` to shared inbox/outbox files; a long\n// `tell_session` prompt or large `ask_session` reply is comfortably above\n// PIPE_BUF, and a concurrent append from another process can interleave at\n// the byte level — the result fails JSON parse and the entire entry is\n// silently dropped by `parseOutboxLine`.\n//\n// Mitigation: a sidecar `<filePath>.lock` created with `O_EXCL` serializes\n// every append at the OS level. Lock is held for the duration of one\n// `appendFileSync`, so the contention window is microseconds. Stale locks\n// (process crashed mid-write) are detected via mtime and forcibly removed\n// after `LOCK_STALE_MS`.\n//\n// When the lock still cannot be acquired within `LOCK_TIMEOUT_MS`, the append\n// FAILS. It used to fall through to an unlocked `appendFileSync` on the theory\n// that a possibly-interleaved entry beats a dropped one — but an interleaved\n// write is exactly the corruption the lock exists to prevent, it can damage a\n// neighbouring well-formed entry as well as its own, and `parseOutboxLine`\n// discards the wreckage later and far from the cause. The caller was told the\n// write succeeded. Failing loudly lets each caller choose: surface the error to\n// its client, or log and continue.\n//\n// The timeout MUST outlast the staleness threshold. A writer killed while\n// holding the lock leaves the file behind, and only the mtime check reclaims\n// it. With a timeout shorter than `LOCK_STALE_MS` every append issued in the\n// first few seconds after such a crash gave up *before* the reclaim could fire\n// — measured as a ~3.5s window in which every append to that file failed, all\n// of which the pre-throw fallback used to deliver. Waiting past the staleness\n// threshold means a dead holder is always reclaimed rather than waited out, so\n// a timeout now means a *live* holder has been stuck for over five seconds,\n// which is a genuine fault worth reporting.\nconst LOCK_SUFFIX = \".lock\";\nconst LOCK_RETRY_MS = 5;\nconst DEFAULT_LOCK_STALE_MS = 5000;\n/** Headroom so a waiter never gives up exactly as the reclaim becomes due. */\nconst LOCK_TIMEOUT_HEADROOM_MS = 1500;\n\n/**\n * Staleness threshold, overridable so tests can exercise the timeout path\n * without blocking a real five seconds.\n *\n * Read per call rather than captured at import: the constants are consulted\n * once per append, which is nothing next to the file I/O that follows, and a\n * module-level snapshot could not be adjusted by a test that imports this\n * module transitively.\n */\nfunction lockStaleMs(): number {\n const raw = Number.parseInt(process.env.NEGOTIUM_JSONL_LOCK_STALE_MS ?? \"\", 10);\n return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_LOCK_STALE_MS;\n}\n\n/** Always > `lockStaleMs()`, so a dead holder is reclaimed rather than waited out. */\nfunction lockTimeoutMs(): number {\n return lockStaleMs() + LOCK_TIMEOUT_HEADROOM_MS;\n}\nconst LOCK_SLEEP = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));\n\n/**\n * The append lock could not be acquired, so nothing was written.\n *\n * Distinguishable from an I/O error so callers can retry, degrade, or report\n * contention specifically. Nothing was appended when this is thrown.\n */\nexport class JsonlLockTimeoutError extends Error {\n constructor(\n readonly filePath: string,\n readonly timeoutMs: number,\n ) {\n super(`jsonl append lock busy after ${timeoutMs}ms; nothing written to ${filePath}`);\n this.name = \"JsonlLockTimeoutError\";\n }\n}\n\n/** Synchronous, non-spinning sleep supported by both Bun and Node MCP workers. */\nfunction sleepForAppendLock(ms: number): void {\n Atomics.wait(LOCK_SLEEP, 0, 0, ms);\n}\n\nfunction tryAcquireAppendLock(lockPath: string): boolean {\n try {\n closeSync(openSync(lockPath, \"wx\")); // O_CREAT | O_EXCL — atomic\n return true;\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== \"EEXIST\") throw e;\n return false;\n }\n}\n\nfunction isStaleLock(lockPath: string): boolean {\n try {\n return Date.now() - statSync(lockPath).mtimeMs > lockStaleMs();\n } catch {\n return false;\n }\n}\n\n/**\n * Append a JSON-encoded entry + newline to a JSONL file. Ensures the parent\n * directory exists and serializes concurrent multi-process appends through a\n * sidecar lock so payloads larger than PIPE_BUF do not interleave.\n *\n * The drainer side (`outbox/file-ops.ts`) claims the file via atomic rename\n * and handles recovery of leftover `.processing` files from crashes.\n */\nexport function appendJsonlEntry(filePath: string, entry: unknown): void {\n appendJsonlLine(filePath, `${JSON.stringify(entry)}\\n`);\n}\n\n/**\n * Append an already-serialized JSONL line (must end with \"\\n\") under the\n * same cross-process append lock as `appendJsonlEntry`. Use when you\n * want to write back a raw line **exactly** — e.g. flusher tail-writeback\n * preserving lines that current parser can't decode, so a future parser\n * release still sees them.\n */\nexport function appendJsonlLine(filePath: string, line: string): void {\n mkdirSync(dirname(filePath), { recursive: true });\n const lockPath = `${filePath}${LOCK_SUFFIX}`;\n const payload = line.endsWith(\"\\n\") ? line : `${line}\\n`;\n\n let acquired = tryAcquireAppendLock(lockPath);\n // Pre-check: if the existing lock is already stale (writer crashed before\n // unlinking), reclaim it before sleeping. Saves the entire retry budget\n // for the common stale-leftover case.\n if (!acquired && isStaleLock(lockPath)) {\n safeUnlink(lockPath);\n acquired = tryAcquireAppendLock(lockPath);\n }\n if (!acquired) {\n const start = Date.now();\n const timeoutMs = lockTimeoutMs();\n while (!acquired && Date.now() - start < timeoutMs) {\n // Codex launches built-in stdio MCPs under Node+tsx while the runtime\n // itself uses Bun. Atomics.wait gives both processes a blocking sleep\n // without a CPU-spinning fallback or a Bun-only global.\n sleepForAppendLock(LOCK_RETRY_MS);\n acquired = tryAcquireAppendLock(lockPath);\n // Recheck staleness inside the loop so a writer that crashes mid-wait\n // doesn't leave us spinning the whole timeout.\n if (!acquired && isStaleLock(lockPath)) {\n safeUnlink(lockPath);\n acquired = tryAcquireAppendLock(lockPath);\n }\n }\n }\n\n if (!acquired) throw new JsonlLockTimeoutError(filePath, lockTimeoutMs());\n\n try {\n appendFileSync(filePath, payload);\n } finally {\n safeUnlink(lockPath);\n }\n}\n\n/** Overwrite a JSONL file with the given entries. Trailing newline included. */\nexport function writeJsonlFile(filePath: string, entries: readonly unknown[]): void {\n const dir = dirname(filePath);\n mkdirSync(dir, { recursive: true });\n const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}-${Math.random()\n .toString(16)\n .slice(2)}`;\n const payload = `${entries.map((e) => JSON.stringify(e)).join(\"\\n\")}\\n`;\n let fd: number | null = null;\n try {\n fd = openSync(tmpPath, \"w\");\n writeFileSync(fd, payload);\n fsyncSync(fd);\n closeSync(fd);\n fd = null;\n renameSync(tmpPath, filePath);\n fsyncDirectoryBestEffort(dir);\n } catch (err) {\n if (fd !== null) {\n try {\n closeSync(fd);\n } catch {}\n }\n try {\n unlinkSync(tmpPath);\n } catch {}\n throw err;\n }\n}\n\nfunction fsyncDirectoryBestEffort(dir: string): void {\n let fd: number | null = null;\n try {\n fd = openSync(dir, \"r\");\n fsyncSync(fd);\n } catch {\n // Directory fsync is not portable across every runtime/filesystem. The\n // file fsync + rename above is the important integrity boundary; this is\n // best-effort durability for the directory entry.\n } finally {\n if (fd !== null) {\n try {\n closeSync(fd);\n } catch {}\n }\n }\n}\n",
|
|
33
36
|
"import { unlinkSync } from \"node:fs\";\nimport { logger } from \"#platform/logger\";\n\nexport interface SafeUnlinkHost {\n unlink(path: string): void;\n warn(context: { err: unknown; path: string }, message: string): void;\n}\n\nexport type SafeUnlink = (path: string, warnLabel?: string) => void;\n\n/** Create an isolated best-effort unlink helper using caller-owned I/O and logging. */\nexport function createSafeUnlink(host: SafeUnlinkHost): SafeUnlink {\n return (path, warnLabel) => {\n try {\n host.unlink(path);\n } catch (e) {\n if ((e as NodeJS.ErrnoException)?.code === \"ENOENT\") return;\n if (warnLabel) host.warn({ err: e, path }, warnLabel);\n }\n };\n}\n\nconst defaultSafeUnlink = createSafeUnlink({\n unlink: unlinkSync,\n warn: (context, message) => logger.warn(context, message),\n});\n\n/**\n * Best-effort unlink. ENOENT is always swallowed (the file is already gone).\n * Other errors are silent unless `warnLabel` is provided, in which case they\n * are logged at warn level with `{ err, path }` context.\n */\nexport function safeUnlink(path: string, warnLabel?: string): void {\n defaultSafeUnlink(path, warnLabel);\n}\n"
|
|
34
37
|
],
|
|
35
|
-
"mappings": "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",
|
|
36
|
-
"debugId": "
|
|
38
|
+
"mappings": "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",
|
|
39
|
+
"debugId": "54820657F6417AF864756E2164756E21",
|
|
37
40
|
"names": []
|
|
38
41
|
}
|