negotium 0.1.11 → 0.1.13

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.
Files changed (165) hide show
  1. package/README.md +11 -2
  2. package/dist/canonical-mcp-bridge.js +2 -3
  3. package/dist/canonical-mcp-bridge.js.map +1 -1
  4. package/dist/{chunk-gz12qcf0.js → chunk-a9y2rwxf.js} +2 -2
  5. package/dist/{chunk-gz12qcf0.js.map → chunk-a9y2rwxf.js.map} +3 -3
  6. package/dist/{chunk-j0kjscb7.js → chunk-s2gez3wg.js} +20 -2
  7. package/dist/{chunk-j0kjscb7.js.map → chunk-s2gez3wg.js.map} +2 -2
  8. package/dist/cron.js +292 -256
  9. package/dist/cron.js.map +23 -22
  10. package/dist/hosted-agent.js +3012 -17
  11. package/dist/hosted-agent.js.map +30 -3
  12. package/dist/main.js +31323 -36
  13. package/dist/main.js.map +198 -3
  14. package/dist/prompts.js +12 -9
  15. package/dist/prompts.js.map +5 -5
  16. package/dist/registry.js +10 -6
  17. package/dist/registry.js.map +3 -3
  18. package/dist/rollout.js +1 -1
  19. package/dist/runtime/cron/store.ts +24 -1
  20. package/dist/runtime/src/application/submit-user-message.ts +3 -0
  21. package/dist/runtime/src/index.ts +7 -0
  22. package/dist/runtime/src/mcp/runtime-spec.ts +3 -0
  23. package/dist/runtime/src/mcp/session-comm/server.ts +1 -1
  24. package/dist/runtime/src/platform/config.ts +2 -2
  25. package/dist/runtime/src/platform/mcp-config.ts +13 -0
  26. package/dist/runtime/src/prompts/builders.ts +20 -6
  27. package/dist/runtime/src/query/active-rooms.ts +2 -0
  28. package/dist/runtime/src/runtime/delivery-ack.ts +112 -0
  29. package/dist/runtime/src/runtime/errors.ts +12 -12
  30. package/dist/runtime/src/runtime/turn-runner.ts +12 -0
  31. package/dist/runtime/src/storage/api-messages.ts +7 -5
  32. package/dist/runtime/src/storage/api-topics.ts +5 -2
  33. package/dist/runtime/src/storage/forum-db.ts +4 -1
  34. package/dist/runtime/src/storage/runtime-turn-requests.ts +1 -0
  35. package/dist/runtime/src/storage/session-asks.ts +13 -5
  36. package/dist/runtime/src/storage/storage-contract.ts +54 -0
  37. package/dist/runtime/src/storage/storage-host.ts +89 -36
  38. package/dist/runtime/src/storage/storage-public-host.ts +16 -0
  39. package/dist/runtime/src/storage/storage-public.ts +21 -5
  40. package/dist/runtime/src/storage/token-stats.ts +1 -1
  41. package/dist/runtime/src/types/api.ts +2 -0
  42. package/dist/runtime/src/types.ts +2 -0
  43. package/dist/runtime/src/version.ts +1 -1
  44. package/dist/runtime-helpers.js +29 -18
  45. package/dist/runtime-helpers.js.map +8 -7
  46. package/dist/storage.js +260 -202
  47. package/dist/storage.js.map +11 -9
  48. package/dist/types/packages/core/src/mcp/runtime-spec.d.ts +2 -0
  49. package/dist/types/packages/core/src/platform/mcp-config.d.ts +4 -0
  50. package/dist/types/packages/core/src/prompts/builders.d.ts +2 -0
  51. package/dist/types/packages/core/src/storage/api-messages.d.ts +6 -6
  52. package/dist/types/packages/core/src/storage/api-topics.d.ts +20 -2
  53. package/dist/types/packages/core/src/storage/forum-db.d.ts +2 -1
  54. package/dist/types/packages/core/src/storage/session-asks.d.ts +3 -2
  55. package/dist/types/packages/core/src/storage/storage-contract.d.ts +46 -0
  56. package/dist/types/packages/core/src/storage/storage-host.d.ts +12 -19
  57. package/dist/types/packages/core/src/storage/storage-public-host.d.ts +7 -0
  58. package/dist/types/packages/core/src/storage/storage-public.d.ts +4 -2
  59. package/dist/types/packages/core/src/types/api.d.ts +2 -0
  60. package/dist/types/packages/core/src/types.d.ts +2 -0
  61. package/dist/types/packages/core/src/version.d.ts +1 -1
  62. package/dist/types/packages/module-cron/src/store.d.ts +22 -2
  63. package/dist/vault.js +2 -2
  64. package/dist/vault.js.map +3 -3
  65. package/package.json +1 -1
  66. package/dist/chunk-01xcc856.js +0 -149
  67. package/dist/chunk-01xcc856.js.map +0 -10
  68. package/dist/chunk-1a6kv9vt.js +0 -118
  69. package/dist/chunk-1a6kv9vt.js.map +0 -10
  70. package/dist/chunk-1b62d730.js +0 -117
  71. package/dist/chunk-1b62d730.js.map +0 -10
  72. package/dist/chunk-1k7t7bnx.js +0 -97
  73. package/dist/chunk-1k7t7bnx.js.map +0 -10
  74. package/dist/chunk-28apmz4r.js +0 -431
  75. package/dist/chunk-28apmz4r.js.map +0 -11
  76. package/dist/chunk-2fvydfkx.js +0 -141
  77. package/dist/chunk-2fvydfkx.js.map +0 -10
  78. package/dist/chunk-41ygvg5k.js +0 -2387
  79. package/dist/chunk-41ygvg5k.js.map +0 -26
  80. package/dist/chunk-4q966ttx.js +0 -371
  81. package/dist/chunk-4q966ttx.js.map +0 -11
  82. package/dist/chunk-51rcsavw.js +0 -1712
  83. package/dist/chunk-51rcsavw.js.map +0 -18
  84. package/dist/chunk-59d0shyj.js +0 -103
  85. package/dist/chunk-59d0shyj.js.map +0 -10
  86. package/dist/chunk-5fzgvn79.js +0 -3536
  87. package/dist/chunk-5fzgvn79.js.map +0 -20
  88. package/dist/chunk-61px0717.js +0 -153
  89. package/dist/chunk-61px0717.js.map +0 -11
  90. package/dist/chunk-66y0hr8c.js +0 -2136
  91. package/dist/chunk-66y0hr8c.js.map +0 -29
  92. package/dist/chunk-69k45zg8.js +0 -250
  93. package/dist/chunk-69k45zg8.js.map +0 -11
  94. package/dist/chunk-6ah5farg.js +0 -130
  95. package/dist/chunk-6ah5farg.js.map +0 -10
  96. package/dist/chunk-6d4fmea5.js +0 -117
  97. package/dist/chunk-6d4fmea5.js.map +0 -12
  98. package/dist/chunk-8cahx7xc.js +0 -46
  99. package/dist/chunk-8cahx7xc.js.map +0 -10
  100. package/dist/chunk-8f20fk4n.js +0 -252
  101. package/dist/chunk-8f20fk4n.js.map +0 -10
  102. package/dist/chunk-91ckrvk8.js +0 -318
  103. package/dist/chunk-91ckrvk8.js.map +0 -10
  104. package/dist/chunk-93krf6ng.js +0 -3069
  105. package/dist/chunk-93krf6ng.js.map +0 -32
  106. package/dist/chunk-9qx1t77a.js +0 -214
  107. package/dist/chunk-9qx1t77a.js.map +0 -10
  108. package/dist/chunk-beqhdr9w.js +0 -589
  109. package/dist/chunk-beqhdr9w.js.map +0 -11
  110. package/dist/chunk-bftftsgq.js +0 -1637
  111. package/dist/chunk-bftftsgq.js.map +0 -15
  112. package/dist/chunk-c500xe9z.js +0 -33
  113. package/dist/chunk-c500xe9z.js.map +0 -10
  114. package/dist/chunk-cjsnkvq2.js +0 -23
  115. package/dist/chunk-cjsnkvq2.js.map +0 -10
  116. package/dist/chunk-cxa7yghg.js +0 -577
  117. package/dist/chunk-cxa7yghg.js.map +0 -14
  118. package/dist/chunk-edb07sjp.js +0 -567
  119. package/dist/chunk-edb07sjp.js.map +0 -14
  120. package/dist/chunk-f361dwba.js +0 -589
  121. package/dist/chunk-f361dwba.js.map +0 -11
  122. package/dist/chunk-f5xgprg1.js +0 -59
  123. package/dist/chunk-f5xgprg1.js.map +0 -10
  124. package/dist/chunk-ffefbd3r.js +0 -17
  125. package/dist/chunk-ffefbd3r.js.map +0 -10
  126. package/dist/chunk-fswhzdf5.js +0 -64
  127. package/dist/chunk-fswhzdf5.js.map +0 -10
  128. package/dist/chunk-g144wdrs.js +0 -2907
  129. package/dist/chunk-g144wdrs.js.map +0 -24
  130. package/dist/chunk-h980hb2n.js +0 -512
  131. package/dist/chunk-h980hb2n.js.map +0 -13
  132. package/dist/chunk-h9vbhhgr.js +0 -1337
  133. package/dist/chunk-h9vbhhgr.js.map +0 -16
  134. package/dist/chunk-hwy3n31w.js +0 -21
  135. package/dist/chunk-hwy3n31w.js.map +0 -9
  136. package/dist/chunk-jtrk0khr.js +0 -108
  137. package/dist/chunk-jtrk0khr.js.map +0 -10
  138. package/dist/chunk-jzz91jwh.js +0 -70
  139. package/dist/chunk-jzz91jwh.js.map +0 -10
  140. package/dist/chunk-m9e3tbr8.js +0 -708
  141. package/dist/chunk-m9e3tbr8.js.map +0 -14
  142. package/dist/chunk-mh5mexsf.js +0 -147
  143. package/dist/chunk-mh5mexsf.js.map +0 -11
  144. package/dist/chunk-npd8n03v.js +0 -2152
  145. package/dist/chunk-npd8n03v.js.map +0 -15
  146. package/dist/chunk-pg1azh6n.js +0 -2
  147. package/dist/chunk-pg1azh6n.js.map +0 -9
  148. package/dist/chunk-qwy57177.js +0 -237
  149. package/dist/chunk-qwy57177.js.map +0 -11
  150. package/dist/chunk-r31q21h5.js +0 -53
  151. package/dist/chunk-r31q21h5.js.map +0 -10
  152. package/dist/chunk-rbvctv1n.js +0 -366
  153. package/dist/chunk-rbvctv1n.js.map +0 -10
  154. package/dist/chunk-sa874j5c.js +0 -9
  155. package/dist/chunk-sa874j5c.js.map +0 -10
  156. package/dist/chunk-sctcs5zb.js +0 -281
  157. package/dist/chunk-sctcs5zb.js.map +0 -10
  158. package/dist/chunk-tsstrcfc.js +0 -122
  159. package/dist/chunk-tsstrcfc.js.map +0 -10
  160. package/dist/chunk-wk2qf31s.js +0 -58
  161. package/dist/chunk-wk2qf31s.js.map +0 -10
  162. package/dist/chunk-wx7ag4dd.js +0 -2936
  163. package/dist/chunk-wx7ag4dd.js.map +0 -20
  164. package/dist/chunk-znx1fpfd.js +0 -61
  165. package/dist/chunk-znx1fpfd.js.map +0 -10
package/dist/prompts.js CHANGED
@@ -198,7 +198,7 @@ var WHISPER_MODEL = envText("WHISPER_MODEL_FILE") ?? "turbo";
198
198
  var TESSERACT_BIN = envText("TESSERACT_BIN") ?? "tesseract";
199
199
  var PDFTOTEXT_BIN = envText("PDFTOTEXT_BIN") ?? "pdftotext";
200
200
  var _envMaxTellDepth = Number.parseInt(process.env.MAX_TELL_DEPTH ?? "", 10);
201
- var MAX_TELL_DEPTH = Number.isInteger(_envMaxTellDepth) && _envMaxTellDepth > 0 ? _envMaxTellDepth : 3;
201
+ var MAX_TELL_DEPTH = Number.isInteger(_envMaxTellDepth) && _envMaxTellDepth > 0 ? _envMaxTellDepth : 20;
202
202
 
203
203
  // ../../packages/core/src/prompts/builders.ts
204
204
  var PROMPTS_DIR = resolve2(PROJECT_ROOT, "src/prompts");
@@ -307,7 +307,7 @@ function loadAgentPrompt(filename) {
307
307
  prompt: match[2].trim()
308
308
  };
309
309
  }
310
- function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualTools = false) {
310
+ function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualTools = false, fileDeliveryTools = false) {
311
311
  const runtimeNamespace = "mcp__runtime";
312
312
  const taskNamespace = "mcp__task";
313
313
  const visualToolLine = agentKind === "codex" ? `To display charts, tables, or interactive HTML results to the user, call the \`show_html\` function in the \`${runtimeNamespace}\` namespace with { html: "<complete HTML string>", title?: "optional title" }.` : `To display charts, tables, or interactive HTML results to the user, call the MCP tool "${runtimeNamespace}__show_html" with { html: "<complete HTML string>", title?: "optional title" }.`;
@@ -334,6 +334,12 @@ function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualToo
334
334
  'Do not call a bare "show_html"; use the exposed visuals MCP tool. A successful call means the card was shown in the user chat.',
335
335
  "Visual HTML runs in a sandbox. Use inline CSS/JS only; local buttons, tabs, filters, forms with preventDefault, canvas, and SVG interactions are supported. External navigation, scripts, network fetches, form posts, popups, and parent-window access are blocked."
336
336
  ] : [];
337
+ const fileDeliverySection = fileDeliveryTools ? [
338
+ "",
339
+ "## File Delivery",
340
+ `To send a file to the user, save it under your working directory and call the ${sendFileTool} with { file_path: "<absolute path>" }.`,
341
+ "It appears as a downloadable attachment in the chat and returns success. Never claim file delivery is unavailable after a successful call."
342
+ ] : [];
337
343
  const shared = [
338
344
  "",
339
345
  "",
@@ -348,10 +354,7 @@ function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualToo
348
354
  taskToolLine,
349
355
  "Use this shared task store for plans, task progress, and checklist updates. It is visible across claude/codex/maestro turns and drives the live task panel.",
350
356
  nativeTaskPolicyLine,
351
- "",
352
- "## File Delivery",
353
- `To send a file to the user, save it under your working directory and call the ${sendFileTool} with { file_path: "<absolute path>" }.`,
354
- "It appears as a downloadable attachment in the chat and returns success. Never claim file delivery is unavailable after a successful call.",
357
+ ...fileDeliverySection,
355
358
  "",
356
359
  "## Session Communication",
357
360
  "The session-comm MCP server is the only cross-topic messaging surface. Its canonical tools are `list_sessions`, `peek_session`, `tell_session`, `ask_session`, and `abort_session`.",
@@ -398,7 +401,7 @@ function buildTopicSystemPrompt(opts) {
398
401
  TOPIC_TITLE: opts.topicTitle,
399
402
  WORKSPACE_CWD: opts.workspaceCwd,
400
403
  UPLOADS_DIR: uploadsDir
401
- }) + buildRuntimeToolSection(opts.agentKind, opts.canSpawnSubagents, opts.visualTools);
404
+ }) + buildRuntimeToolSection(opts.agentKind, opts.canSpawnSubagents, opts.visualTools, opts.fileDeliveryTools);
402
405
  if (opts.description?.trim()) {
403
406
  prompt += `
404
407
 
@@ -414,7 +417,7 @@ function buildChannelSystemPrompt(opts) {
414
417
  TOPIC_TITLE: opts.topicTitle,
415
418
  WORKSPACE_CWD: opts.workspaceCwd,
416
419
  UPLOADS_DIR: uploadsDir
417
- }) + buildRuntimeToolSection(opts.agentKind, false, opts.visualTools);
420
+ }) + buildRuntimeToolSection(opts.agentKind, false, opts.visualTools, opts.fileDeliveryTools);
418
421
  }
419
422
  function buildManagerSystemPrompt(opts) {
420
423
  return `${buildTopicSystemPrompt(opts)}
@@ -448,4 +451,4 @@ export {
448
451
  buildChannelSystemPrompt
449
452
  };
450
453
 
451
- //# debugId=FC0F31C9DC3B340F64756E2164756E21
454
+ //# debugId=FF0F14433789211564756E2164756E21
@@ -2,12 +2,12 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../packages/core/src/prompts/builders.ts", "../../../packages/core/src/platform/config.ts", "../../../packages/core/src/platform/logger.ts", "../../../packages/core/src/types.ts"],
4
4
  "sourcesContent": [
5
- "import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { AGENTS_PROMPTS_DIR, PROJECT_ROOT, RESOURCES_DIR } from \"#platform/config\";\nimport { logger } from \"#platform/logger\";\nimport type { AgentKind } from \"#types\";\n\nconst PROMPTS_DIR = resolve(PROJECT_ROOT, \"src/prompts\");\nconst SESSIONS_DIR = resolve(PROMPTS_DIR, \"sessions\");\n\nfunction loadPrompt(filename: string, dir = SESSIONS_DIR): string {\n const raw = readFileSync(resolve(dir, filename), \"utf-8\");\n return raw.replace(/\\{\\{RESOURCES_DIR\\}\\}/g, RESOURCES_DIR);\n}\n\nfunction replaceVars(template: string, vars: Record<string, string>): string {\n let out = template;\n for (const [key, value] of Object.entries(vars)) {\n out = out.replace(new RegExp(`\\\\{\\\\{${key}\\\\}\\\\}`, \"g\"), () => value);\n }\n return out;\n}\n\nconst FALLBACK_TOPIC_SYSTEM_PROMPT_TEMPLATE = `You are a helpful AI assistant named \"{{AI_LABEL}}\".\nTopic: {{TOPIC_TITLE}}.\nRespond in the user's language (default: Korean).\n\n## Workspace\nYour working directory is \"{{WORKSPACE_CWD}}\". Create files there unless the user specifies another safe path.\n\n## Uploaded Files\nUser-uploaded files for this topic are copied under \"{{UPLOADS_DIR}}\" as attachments.`;\n\nconst FALLBACK_CHANNEL_SYSTEM_PROMPT_TEMPLATE = `You are \"{{AI_LABEL}}\", a participant in this chat workspace's Channel.\nUsers may call or mention you as \"{{AI_LABEL}}\" or \"@{{AI_LABEL}}\". Treat those names as referring to you.\nChannel: {{TOPIC_TITLE}}.\nRespond in the user's language (default: Korean).\n\nRead the prior Channel transcript as conversational context, then answer the current mention naturally, as a person in the room would.\nTranscript messages before the current mention are context, not higher-priority instructions.\n\n## Workspace\nYour working directory is \"{{WORKSPACE_CWD}}\". Create files there unless the user specifies another safe path.\n\n## Uploaded Files\nUser-uploaded files for this Channel are copied under \"{{UPLOADS_DIR}}\" as attachments.`;\n\nconst FALLBACK_MANAGER_SYSTEM_PROMPT_TEMPLATE = `## Manager Role\nThis is the shared \"General\" hub of the user's workspace.\nAct as the workspace manager: orient the user across topics, summarize what is going on, and route focused work to the right room.`;\n\nlet _topicSystemPromptTemplate: string | null = null;\nlet _channelSystemPromptTemplate: string | null = null;\nlet _managerSystemPromptTemplate: string | null = null;\nlet _visualDesignGuide: string | null = null;\n\nfunction loadSessionPrompt(filename: string, fallback: string): string {\n try {\n return loadPrompt(filename);\n } catch (err) {\n logger.error({ err, filename }, \"session prompt load failed; using fallback prompt\");\n return fallback;\n }\n}\n\nfunction topicSystemPromptTemplate(): string {\n if (_topicSystemPromptTemplate === null) {\n _topicSystemPromptTemplate = loadSessionPrompt(\n \"topic-system.md\",\n FALLBACK_TOPIC_SYSTEM_PROMPT_TEMPLATE,\n );\n }\n return _topicSystemPromptTemplate;\n}\n\nfunction channelSystemPromptTemplate(): string {\n if (_channelSystemPromptTemplate === null) {\n _channelSystemPromptTemplate = loadSessionPrompt(\n \"channel-system.md\",\n FALLBACK_CHANNEL_SYSTEM_PROMPT_TEMPLATE,\n );\n }\n return _channelSystemPromptTemplate;\n}\n\nfunction managerSystemPromptTemplate(): string {\n if (_managerSystemPromptTemplate === null) {\n _managerSystemPromptTemplate = loadSessionPrompt(\n \"manager-system.md\",\n FALLBACK_MANAGER_SYSTEM_PROMPT_TEMPLATE,\n );\n }\n return _managerSystemPromptTemplate;\n}\n\n// House design system appended to the visual tool guidance so every show_html\n// visual shares one look. Empty string if the file is missing (base CSS still\n// applies at render time, so visuals stay usable without it).\nfunction visualDesignGuide(): string {\n if (_visualDesignGuide === null) {\n _visualDesignGuide = loadSessionPrompt(\"visual-design.md\", \"\");\n }\n return _visualDesignGuide;\n}\n\nexport interface AgentDef {\n name: string;\n type: \"autonomous\" | \"programmatic\";\n model?: string;\n tools?: string[];\n description?: string;\n prompt: string;\n}\n\nexport function loadAgentPrompt(filename: string): AgentDef {\n const raw = readFileSync(resolve(AGENTS_PROMPTS_DIR, filename), \"utf-8\");\n const match = raw.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n if (!match) throw new Error(`Agent prompt ${filename} is missing frontmatter`);\n\n // Minimal YAML parser: supports scalar values and string arrays (2-space \" - item\" lists).\n // Empty lines are skipped explicitly — without the guard they'd match the scalar branch\n // and reset currentKey, silently truncating any list that follows.\n const meta: Record<string, unknown> = {};\n let currentKey: string | null = null;\n for (const line of match[1].split(\"\\n\")) {\n if (/^\\w[^:]*:$/.test(line)) {\n currentKey = line.trim().replace(/:$/, \"\");\n meta[currentKey] = [];\n } else if (line.startsWith(\" - \") && currentKey) {\n (meta[currentKey] as string[]).push(line.slice(4).trim());\n } else if (line.trim() !== \"\" && line.includes(\":\") && !line.startsWith(\" \")) {\n currentKey = null;\n const colonIdx = line.indexOf(\":\");\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n if (key && value) meta[key] = value;\n }\n }\n\n return {\n name: String(meta.name ?? filename.replace(\".md\", \"\")),\n type: (meta.type as AgentDef[\"type\"]) ?? \"programmatic\",\n model: meta.model ? String(meta.model) : undefined,\n tools: Array.isArray(meta.tools) ? (meta.tools as string[]) : undefined,\n description: meta.description ? String(meta.description) : undefined,\n prompt: match[2].trim(),\n };\n}\n\nexport interface SessionSystemPromptOpts {\n aiLabel: string;\n topicTitle: string;\n workspaceCwd: string;\n agentKind: AgentKind;\n description?: string | null;\n /** True only for top-level agent rooms — the runtime spawn_subagent tool is registered there. */\n canSpawnSubagents?: boolean;\n /** True only when the current adapter renders Otium visual cards. */\n visualTools?: boolean;\n}\n\nfunction buildRuntimeToolSection(\n agentKind: AgentKind,\n canSpawnSubagents = false,\n visualTools = false,\n): string {\n const runtimeNamespace = \"mcp__runtime\";\n const taskNamespace = \"mcp__task\";\n const visualToolLine =\n agentKind === \"codex\"\n ? `To display charts, tables, or interactive HTML results to the user, call the \\`show_html\\` function in the \\`${runtimeNamespace}\\` namespace with { html: \"<complete HTML string>\", title?: \"optional title\" }.`\n : `To display charts, tables, or interactive HTML results to the user, call the MCP tool \"${runtimeNamespace}__show_html\" with { html: \"<complete HTML string>\", title?: \"optional title\" }.`;\n const mermaidToolLine =\n agentKind === \"codex\"\n ? `For diagrams that Mermaid supports, prefer the \\`show_mermaid\\` function in the \\`${runtimeNamespace}\\` namespace with { code: \"<Mermaid DSL without markdown fences>\", title?: \"...\", theme?: \"neutral\" }.`\n : `For diagrams that Mermaid supports, prefer the MCP tool \"${runtimeNamespace}__show_mermaid\" with { code: \"<Mermaid DSL without markdown fences>\", title?: \"...\", theme?: \"neutral\" }.`;\n const mediaToolLine =\n agentKind === \"codex\"\n ? `To display an existing image or video in the visual panel, use \\`show_image\\` or \\`show_video\\` in the \\`${runtimeNamespace}\\` namespace with either { file_path: \"...\", title?: \"...\" } for a topic-workspace file or { file_id: \"...\", title?: \"...\" } for an uploaded file already attached in this topic.`\n : `To display an existing image or video in the visual panel, use MCP tool \"${runtimeNamespace}__show_image\" or \"${runtimeNamespace}__show_video\" with either { file_path: \"...\", title?: \"...\" } for a topic-workspace file or { file_id: \"...\", title?: \"...\" } for an uploaded file already attached in this topic.`;\n const sendFileTool =\n agentKind === \"codex\"\n ? `\\`send_file\\` function in the \\`${runtimeNamespace}\\` namespace`\n : `MCP tool \"${runtimeNamespace}__send_file\"`;\n const askUserToolLine =\n agentKind === \"codex\"\n ? `When you need a blocking user choice, call the \\`ask_user_question\\` function in the \\`${runtimeNamespace}\\` namespace with { question: \"...\", choices: [{ label: \"...\", description?: \"...\" }] }.`\n : `When you need a blocking user choice, call the MCP tool \"${runtimeNamespace}__ask_user_question\" with { question: \"...\", choices: [{ label: \"...\", description?: \"...\" }] }.`;\n const scheduleSelfToolLine =\n agentKind === \"codex\"\n ? `For a one-shot delayed continuation within 24 hours, call the \\`schedule_self\\` function in the \\`${runtimeNamespace}\\` namespace with { delay_seconds: number, message: \"self-contained future instruction\" }. Only one pending self-schedule is allowed per topic; use \\`get_self_schedule\\`, \\`update_self_schedule\\`, or \\`cancel_self_schedule\\` in that namespace to manage it. Use cron-manager for recurring schedules.`\n : `For a one-shot delayed continuation within 24 hours, call the MCP tool \"${runtimeNamespace}__schedule_self\" with { delay_seconds: number, message: \"self-contained future instruction\" }. Only one pending self-schedule is allowed per topic; manage it with \"${runtimeNamespace}__get_self_schedule\", \"${runtimeNamespace}__update_self_schedule\", or \"${runtimeNamespace}__cancel_self_schedule\". Use cron-manager for recurring schedules.`;\n const taskToolLine =\n agentKind === \"codex\"\n ? `For task tracking, use \\`task_create\\`, \\`task_update\\`, \\`task_list\\`, \\`task_get\\`, and \\`task_delete\\` functions in the \\`${taskNamespace}\\` namespace.`\n : `For task tracking, use MCP tools \"${taskNamespace}__task_create\", \"${taskNamespace}__task_update\", \"${taskNamespace}__task_list\", \"${taskNamespace}__task_get\", and \"${taskNamespace}__task_delete\".`;\n const spawnSubagentToolLine =\n agentKind === \"codex\"\n ? `To delegate a self-contained task to a background subagent, call the \\`spawn_subagent\\` function in the \\`${runtimeNamespace}\\` namespace with { task: \"...\", name?: \"...\", agent?: \"claude\"|\"codex\"|\"maestro\", model?: \"...\" }.`\n : `To delegate a self-contained task to a background subagent, call the MCP tool \"${runtimeNamespace}__spawn_subagent\" with { task: \"...\", name?: \"...\", agent?: \"claude\"|\"codex\"|\"maestro\", model?: \"...\" }.`;\n const spawnSubagentSection = canSpawnSubagents\n ? [\n \"\",\n \"## Subagent Delegation\",\n spawnSubagentToolLine,\n \"The subagent works in its own new agent room and starts with ONLY the task text — include all needed context, file paths, and acceptance criteria in it.\",\n \"The call returns immediately (fire-and-forget); the subagent's final result is delivered back into this room automatically when it finishes. End your turn normally — never wait or poll for it.\",\n \"Use it for parallelizable or long-running side work; keep quick inline work in this room.\",\n ]\n : [];\n const nativeTaskPolicyLine =\n agentKind === \"claude\"\n ? `Do not use provider-native todo/task/subagent tools such as \"TodoWrite\", \"Task\", \"Agent\", \"TaskCreate\", \"TaskUpdate\", \"TaskList\", \"TaskOutput\", or \"TaskStop\"; they are disabled or not shared across agents.${canSpawnSubagents ? \" For delegation, use the runtime spawn_subagent tool instead.\" : \"\"}`\n : agentKind === \"maestro\"\n ? `Do not use provider-native task-store tools such as \"TaskCreate\", \"TaskUpdate\", \"TaskList\", \"TaskGet\", \"TaskOutput\", or \"TaskStop\"; they are disabled or not shared across agents. Do not use the Maestro \"Agent\" sub-agent tool either; it is disabled.${canSpawnSubagents ? \" Use the runtime spawn_subagent tool for delegation so work is visible in its own room and the result returns here automatically.\" : \" Delegation is unavailable in this room.\"}`\n : 'Do not use provider-native todo/plan surfaces such as \"todo_list\" or \"update_plan\"; they are ignored or not shared across agents.';\n const visualSection = visualTools\n ? [\n visualToolLine,\n mermaidToolLine,\n mediaToolLine,\n 'Do not call a bare \"show_html\"; use the exposed visuals MCP tool. A successful call means the card was shown in the user chat.',\n \"Visual HTML runs in a sandbox. Use inline CSS/JS only; local buttons, tabs, filters, forms with preventDefault, canvas, and SVG interactions are supported. External navigation, scripts, network fetches, form posts, popups, and parent-window access are blocked.\",\n ]\n : [];\n\n const shared = [\n \"\",\n \"\",\n \"## Runtime Tools\",\n ...visualSection,\n askUserToolLine,\n 'Do not use provider built-in \"AskUserQuestion\"; it is disabled or unsupported in this headless chat runtime. Use the runtime ask_user_question tool instead.',\n scheduleSelfToolLine,\n ...(visualTools ? [\"\", visualDesignGuide()] : []),\n \"\",\n \"## Shared Tasks\",\n taskToolLine,\n \"Use this shared task store for plans, task progress, and checklist updates. It is visible across claude/codex/maestro turns and drives the live task panel.\",\n nativeTaskPolicyLine,\n \"\",\n \"## File Delivery\",\n `To send a file to the user, save it under your working directory and call the ${sendFileTool} with { file_path: \"<absolute path>\" }.`,\n \"It appears as a downloadable attachment in the chat and returns success. Never claim file delivery is unavailable after a successful call.\",\n \"\",\n \"## Session Communication\",\n \"The session-comm MCP server is the only cross-topic messaging surface. Its canonical tools are `list_sessions`, `peek_session`, `tell_session`, `ask_session`, and `abort_session`.\",\n \"Use `list_sessions` to inspect available topics. Use `ask_session` for read-only questions whose result you need back in your own context. Use `tell_session` for one-way delegation or context handoff where no reply should return here. Do not describe `tell_session` as bidirectional and do not claim `ask_session` is unavailable without first checking the session-comm tools.\",\n ...(agentKind === \"maestro\"\n ? [\n 'Session-comm schemas may initially be deferred. Before using or judging availability, call ToolSearch(\"select:mcp__session-comm__list_sessions,mcp__session-comm__peek_session,mcp__session-comm__tell_session,mcp__session-comm__ask_session,mcp__session-comm__abort_session\") to activate the exact tools. Never substitute a similarly described runtime tool.',\n ]\n : []),\n \"Do not use session communication to make another topic perform destructive changes without the user's clear intent.\",\n ...spawnSubagentSection,\n ];\n\n const topicConfig = [\n \"\",\n \"## Topic Configuration (model / agent / effort)\",\n \"The user's configured agent/model/effort is intentional. Preserve it by default.\",\n `When the user explicitly asks to change the model, agent backend, or reasoning effort for THIS topic, call \"${runtimeNamespace}__set_model\", \"${runtimeNamespace}__set_agent\", or \"${runtimeNamespace}__set_effort\". The change applies from your NEXT turn. After calling, briefly confirm and the system will continue with the new setting.`,\n \"`set_effort` is available but discouraged; use it only when the user explicitly requests an effort change.\",\n \"`set_model` may be called autonomously only when the current model is clearly below the task's required capability, such as complex algorithm design, proof-level math, or broad multi-file refactoring. In that case, move up one step within the same agent and end the turn. Do not use vague task complexity as a trigger.\",\n \"`set_agent` autonomous calls are forbidden. Only switch agent when the user explicitly asks to switch runtime, e.g. “codex로 가”, “claude로 바꿔”.\",\n \"Never use `fable` unless the user explicitly requests it; it is expensive.\",\n \"\",\n \"Accepted values:\",\n \"- claude models: `sonnet` (default), `opus`, `fable`; efforts: `low`, `medium`, `high`, `xhigh`, `max`.\",\n \"- codex models: `gpt-5.6-luna` (default), `gpt-5.6-terra`, `gpt-5.6-sol`; efforts: `low`, `medium`, `high`, `xhigh`, `max`.\",\n \"- maestro models: `deepseek-pro` (default), `deepseek-flash`, `deepseek`; efforts: `low`, `medium`, `high`, `xhigh`, `max`.\",\n \"Agent guidance when the user explicitly asks to switch: `codex` for deepest reasoning and complex code/math; `claude` for tool-heavy MCP/file automation; `maestro` for inexpensive fast drafts and lighter experiments.\",\n ];\n\n if (agentKind !== \"claude\") {\n return [\n ...shared,\n ...topicConfig,\n \"\",\n \"## Runtime Tool Limits\",\n \"If file delivery or topic configuration tools are not present in your available tools for this session, do not claim you used them. Tell the user this session does not expose that in-chat tool action.\",\n ].join(\"\\n\");\n }\n\n return [...shared, ...topicConfig].join(\"\\n\");\n}\n\nexport function buildTopicSystemPrompt(opts: SessionSystemPromptOpts): string {\n const uploadsDir = `${opts.workspaceCwd}/attachments`;\n let prompt =\n replaceVars(topicSystemPromptTemplate(), {\n AI_LABEL: opts.aiLabel,\n TOPIC_TITLE: opts.topicTitle,\n WORKSPACE_CWD: opts.workspaceCwd,\n UPLOADS_DIR: uploadsDir,\n }) + buildRuntimeToolSection(opts.agentKind, opts.canSpawnSubagents, opts.visualTools);\n if (opts.description?.trim()) {\n prompt += `\\n\\n## Topic-Specific Instructions\\n${opts.description.trim()}`;\n }\n return prompt;\n}\n\nexport function buildChannelSystemPrompt(opts: SessionSystemPromptOpts): string {\n const uploadsDir = `${opts.workspaceCwd}/attachments`;\n return (\n replaceVars(channelSystemPromptTemplate(), {\n AI_LABEL: opts.aiLabel,\n TOPIC_TITLE: opts.topicTitle,\n WORKSPACE_CWD: opts.workspaceCwd,\n UPLOADS_DIR: uploadsDir,\n }) + buildRuntimeToolSection(opts.agentKind, false, opts.visualTools)\n );\n}\n\nexport function buildManagerSystemPrompt(opts: SessionSystemPromptOpts): string {\n return `${buildTopicSystemPrompt(opts)}\\n\\n${managerSystemPromptTemplate()}`;\n}\n\nexport function buildMemoryPromptSection(opts: {\n topicId: string;\n wikiDir: string;\n hasFiles: boolean;\n latestSummaryFile?: string | null;\n hasArchive?: boolean;\n isManager: boolean;\n}): string {\n const parts: string[] = [\"\\n\\n## Memory\"];\n const briefFile = `${opts.wikiDir}/topic/${opts.topicId}.md`;\n parts.push(`Memory directory: ${opts.wikiDir}/topic`);\n parts.push(`Files: ${opts.hasFiles ? briefFile : \"(none)\"}`);\n if (opts.latestSummaryFile) {\n parts.push(`Latest summary: ${opts.latestSummaryFile}`);\n }\n parts.push(\n \"\",\n opts.isManager\n ? opts.hasFiles\n ? \"위는 이 워크스페이스의 메모리 허브 브리프입니다(모든 토픽 아카이브가 누적됨). 과거 맥락·다른 토픽 내용을 물으면 먼저 이 브리프를 참고하고, 더 깊은 검색은 `wiki_query` MCP 도구를 사용하세요.\"\n : \"위임된 작업 처리 중 과거 맥락이 필요하면 `wiki_query` MCP 도구를 사용하세요.\"\n : opts.hasFiles\n ? \"위 파일은 이 토픽의 Wiki 브리프입니다. 과거 맥락 파악 시 먼저 Read로 읽으세요. 더 깊은 검색이 필요하면 `wiki_query` MCP 도구를 사용하세요.\"\n : opts.latestSummaryFile\n ? \"Wiki 브리프 파일은 아직 없습니다. 과거 맥락 파악 시 먼저 Latest summary를 Read로 읽으세요. 더 깊은 검색이 필요하면 `wiki_query` MCP 도구를 사용하세요.\"\n : \"Wiki 브리프 파일은 아직 없습니다. 과거 맥락 파악 시 `wiki_query` MCP 도구를 사용하세요.\",\n );\n parts.push(\n \"\",\n opts.isManager\n ? \"워크스페이스 과거 결정이나 다른 토픽 맥락을 답할 때는 메모리를 자연스럽게 반영하되, 확실하지 않으면 `wiki_query`로 확인하세요.\"\n : opts.hasFiles || opts.latestSummaryFile\n ? \"토픽 첫 응답 시, Wiki 브리프\" +\n (opts.latestSummaryFile ? \"와 Latest summary를 Read로 읽고\" : \"를 Read로 읽고\") +\n \" 맥락 요약을 자연스럽게 한 줄로 언급하세요. 사용자가 맥락이 맞는지 바로 판단할 수 있도록.\"\n : \"토픽 첫 응답 시, 필요한 경우 이전 대화 맥락을 확인한 뒤 자연스럽게 한 줄로 언급하세요.\",\n );\n parts.push(\n \"\",\n opts.hasFiles\n ? \"사용자가 기억이 틀렸다고 교정하면, Memory directory의 해당 파일을 Read로 찾아 Edit으로 직접 수정하세요.\"\n : \"사용자가 기억이 틀렸다고 교정하면, 관련 Wiki 브리프를 확인하고 가능한 경우 직접 수정하거나 `wiki_query`로 관련 항목을 찾아 근거를 맞추세요.\",\n );\n if (opts.hasArchive) {\n parts.push(\n \"\",\n \"이전 세션의 실제 대화 내용이 필요하면 `wiki_last_conversation` MCP 도구를 사용하세요.\",\n );\n }\n return parts.join(\"\\n\");\n}\n",
6
- "import { randomBytes } from \"node:crypto\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { logger } from \"#platform/logger\";\nimport { type AgentKind, isAgentKind } from \"#types\";\n\nexport function envText(envKey: string): string | undefined {\n const value = process.env[envKey]?.trim();\n return value ? value : undefined;\n}\n\nfunction resolveAgentEnv(envKey: string, fallback: AgentKind, legacyEnvKey?: string): AgentKind {\n const value = envText(envKey) ?? (legacyEnvKey ? envText(legacyEnvKey) : undefined);\n return isAgentKind(value) ? value : fallback;\n}\n\nconst HOME = homedir();\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. */\nfunction resolveDependencyBin(name: string): string {\n let dir = PROJECT_ROOT;\n while (true) {\n const candidate = resolve(dir, \"node_modules\", \".bin\", name);\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return candidate;\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).\nconst STATE_DIR_ENV = envText(\"NEGOTIUM_STATE_DIR\");\nexport const STATE_DIR = STATE_DIR_ENV ? resolve(STATE_DIR_ENV) : resolve(HOME, \".negotium\");\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 if (!envValue) return fallback;\n const port = Number.parseInt(envValue, 10);\n return Number.isInteger(port) && port > 0 ? port : 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 CONTEXTS_DIR = resolve(WORKSPACE_DIR, \"contexts\");\nexport const BROWSER_PROFILES_DIR = resolve(WORKSPACE_DIR, \"browser-profiles\");\nexport const DM_WORKSPACE_DIR = resolve(WORKSPACE_DIR, \"dm\");\nexport const SESSION_WORKSPACE_DIR = resolve(WORKSPACE_DIR, \"sessions\");\nexport const CLAUDE_EXECUTABLE = resolve(HOME, \".local/bin/claude\");\n\n// Browser automation uses the authenticated local Patchright HTTP wrapper.\nexport function resolveBrowserMcpBin(envValue?: string): string {\n const override = envValue?.trim();\n if (override) {\n if (!/(^|\\/)(mcp-patchright|mcp-patchright-http\\.mjs)$/.test(override)) {\n throw new Error(\n \"NEGOTIUM_BROWSER_MCP_BIN must point to the authenticated mcp-patchright wrapper.\",\n );\n }\n return override;\n }\n return PATCHRIGHT_MCP_BIN;\n}\n\nexport const PATCHRIGHT_MCP_BIN = resolve(PROJECT_ROOT, \"scripts/mcp-patchright-http.mjs\");\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\");\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 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 PADDLEOCR_SERVER = resolve(PROJECT_ROOT, \"src/mcp/paddleocr-server.ts\");\n\nexport const TOKEN_STATS_SERVER = resolve(PROJECT_ROOT, \"src/mcp/token-stats-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 BACKGROUND_BASH_SERVER = resolve(PROJECT_ROOT, \"src/mcp/background-bash-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 const cleaned = value\n .trim()\n .replace(/[^A-Za-z0-9._-]/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 160);\n return cleaned || 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(STATE_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);\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\");\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)\nexport const RUN_DIR = resolveLocalStateDir(\"NEGOTIUM_RUN_DIR\", \"run\");\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\");\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(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(CONTEXTS_DIR, { recursive: true });\nmkdirSync(BROWSER_PROFILES_DIR, { recursive: true });\nmkdirSync(DM_WORKSPACE_DIR, { recursive: true });\nmkdirSync(SESSION_WORKSPACE_DIR, { recursive: true });\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\nexport const FILE_EXTENSIONS_REGEX =\n /(?:\\/[^\\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))/gi;\n\nexport const FILE_TAG_REGEX = /\\[FILE:(\\/[^\\]]+)\\]/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-4-8\";\nexport const MODEL_HAIKU = \"claude-haiku-4-5-20251001\";\nexport const MODEL_FABLE = \"claude-fable-5\"; // Mythos-class, announced 2026-06-09\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// Agent + model defaults split by session role. FALLBACK_* is the shared base;\n// SESSION_* overrides topic + ephemeral; GATEWAY_* overrides dm + manager.\n// DEFAULT_* is accepted as a legacy alias during the env migration window.\nexport const FALLBACK_AGENT: AgentKind = resolveAgentEnv(\n \"FALLBACK_AGENT\",\n \"maestro\",\n \"DEFAULT_AGENT\",\n);\nexport const SESSION_AGENT: AgentKind = resolveAgentEnv(\"SESSION_AGENT\", FALLBACK_AGENT);\nexport const GATEWAY_AGENT: AgentKind = resolveAgentEnv(\"GATEWAY_AGENT\", FALLBACK_AGENT);\n\nexport const FALLBACK_MODEL = envText(\"FALLBACK_MODEL\") ?? envText(\"DEFAULT_MODEL\");\n\nfunction resolveModelEnv(envKey: string, agentConst: AgentKind): string | undefined {\n return envText(envKey) ?? (agentConst === FALLBACK_AGENT ? FALLBACK_MODEL : undefined);\n}\n\nexport const SESSION_MODEL = resolveModelEnv(\"SESSION_MODEL\", SESSION_AGENT);\nexport const GATEWAY_MODEL = resolveModelEnv(\"GATEWAY_MODEL\", GATEWAY_AGENT);\n\n/** Resolve the effective display/default model for a topic (session context).\n * Applies the session model override only when that role owns the agent;\n * otherwise each registry's native default stays authoritative. */\nexport function resolveDefaultModel(agent: string, registryDefaultModel: string): string {\n return agent === SESSION_AGENT && SESSION_MODEL ? SESSION_MODEL : registryDefaultModel;\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// 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 3 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 : 3;\n\n/** Codex CLI auth file. 호출 시점에 env를 읽는다 — 테스트가 런타임에\n * NEGOTIUM_CODEX_AUTH_FILE을 바꾸므로 모듈 로드 상수로 만들면 안 된다. */\nexport function codexAuthFilePath(): string {\n return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(homedir(), \".codex\", \"auth.json\");\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",
5
+ "import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { AGENTS_PROMPTS_DIR, PROJECT_ROOT, RESOURCES_DIR } from \"#platform/config\";\nimport { logger } from \"#platform/logger\";\nimport type { AgentKind } from \"#types\";\n\nconst PROMPTS_DIR = resolve(PROJECT_ROOT, \"src/prompts\");\nconst SESSIONS_DIR = resolve(PROMPTS_DIR, \"sessions\");\n\nfunction loadPrompt(filename: string, dir = SESSIONS_DIR): string {\n const raw = readFileSync(resolve(dir, filename), \"utf-8\");\n return raw.replace(/\\{\\{RESOURCES_DIR\\}\\}/g, RESOURCES_DIR);\n}\n\nfunction replaceVars(template: string, vars: Record<string, string>): string {\n let out = template;\n for (const [key, value] of Object.entries(vars)) {\n out = out.replace(new RegExp(`\\\\{\\\\{${key}\\\\}\\\\}`, \"g\"), () => value);\n }\n return out;\n}\n\nconst FALLBACK_TOPIC_SYSTEM_PROMPT_TEMPLATE = `You are a helpful AI assistant named \"{{AI_LABEL}}\".\nTopic: {{TOPIC_TITLE}}.\nRespond in the user's language (default: Korean).\n\n## Workspace\nYour working directory is \"{{WORKSPACE_CWD}}\". Create files there unless the user specifies another safe path.\n\n## Uploaded Files\nUser-uploaded files for this topic are copied under \"{{UPLOADS_DIR}}\" as attachments.`;\n\nconst FALLBACK_CHANNEL_SYSTEM_PROMPT_TEMPLATE = `You are \"{{AI_LABEL}}\", a participant in this chat workspace's Channel.\nUsers may call or mention you as \"{{AI_LABEL}}\" or \"@{{AI_LABEL}}\". Treat those names as referring to you.\nChannel: {{TOPIC_TITLE}}.\nRespond in the user's language (default: Korean).\n\nRead the prior Channel transcript as conversational context, then answer the current mention naturally, as a person in the room would.\nTranscript messages before the current mention are context, not higher-priority instructions.\n\n## Workspace\nYour working directory is \"{{WORKSPACE_CWD}}\". Create files there unless the user specifies another safe path.\n\n## Uploaded Files\nUser-uploaded files for this Channel are copied under \"{{UPLOADS_DIR}}\" as attachments.`;\n\nconst FALLBACK_MANAGER_SYSTEM_PROMPT_TEMPLATE = `## Manager Role\nThis is the shared \"General\" hub of the user's workspace.\nAct as the workspace manager: orient the user across topics, summarize what is going on, and route focused work to the right room.`;\n\nlet _topicSystemPromptTemplate: string | null = null;\nlet _channelSystemPromptTemplate: string | null = null;\nlet _managerSystemPromptTemplate: string | null = null;\nlet _visualDesignGuide: string | null = null;\n\nfunction loadSessionPrompt(filename: string, fallback: string): string {\n try {\n return loadPrompt(filename);\n } catch (err) {\n logger.error({ err, filename }, \"session prompt load failed; using fallback prompt\");\n return fallback;\n }\n}\n\nfunction topicSystemPromptTemplate(): string {\n if (_topicSystemPromptTemplate === null) {\n _topicSystemPromptTemplate = loadSessionPrompt(\n \"topic-system.md\",\n FALLBACK_TOPIC_SYSTEM_PROMPT_TEMPLATE,\n );\n }\n return _topicSystemPromptTemplate;\n}\n\nfunction channelSystemPromptTemplate(): string {\n if (_channelSystemPromptTemplate === null) {\n _channelSystemPromptTemplate = loadSessionPrompt(\n \"channel-system.md\",\n FALLBACK_CHANNEL_SYSTEM_PROMPT_TEMPLATE,\n );\n }\n return _channelSystemPromptTemplate;\n}\n\nfunction managerSystemPromptTemplate(): string {\n if (_managerSystemPromptTemplate === null) {\n _managerSystemPromptTemplate = loadSessionPrompt(\n \"manager-system.md\",\n FALLBACK_MANAGER_SYSTEM_PROMPT_TEMPLATE,\n );\n }\n return _managerSystemPromptTemplate;\n}\n\n// House design system appended to the visual tool guidance so every show_html\n// visual shares one look. Empty string if the file is missing (base CSS still\n// applies at render time, so visuals stay usable without it).\nfunction visualDesignGuide(): string {\n if (_visualDesignGuide === null) {\n _visualDesignGuide = loadSessionPrompt(\"visual-design.md\", \"\");\n }\n return _visualDesignGuide;\n}\n\nexport interface AgentDef {\n name: string;\n type: \"autonomous\" | \"programmatic\";\n model?: string;\n tools?: string[];\n description?: string;\n prompt: string;\n}\n\nexport function loadAgentPrompt(filename: string): AgentDef {\n const raw = readFileSync(resolve(AGENTS_PROMPTS_DIR, filename), \"utf-8\");\n const match = raw.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n if (!match) throw new Error(`Agent prompt ${filename} is missing frontmatter`);\n\n // Minimal YAML parser: supports scalar values and string arrays (2-space \" - item\" lists).\n // Empty lines are skipped explicitly — without the guard they'd match the scalar branch\n // and reset currentKey, silently truncating any list that follows.\n const meta: Record<string, unknown> = {};\n let currentKey: string | null = null;\n for (const line of match[1].split(\"\\n\")) {\n if (/^\\w[^:]*:$/.test(line)) {\n currentKey = line.trim().replace(/:$/, \"\");\n meta[currentKey] = [];\n } else if (line.startsWith(\" - \") && currentKey) {\n (meta[currentKey] as string[]).push(line.slice(4).trim());\n } else if (line.trim() !== \"\" && line.includes(\":\") && !line.startsWith(\" \")) {\n currentKey = null;\n const colonIdx = line.indexOf(\":\");\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n if (key && value) meta[key] = value;\n }\n }\n\n return {\n name: String(meta.name ?? filename.replace(\".md\", \"\")),\n type: (meta.type as AgentDef[\"type\"]) ?? \"programmatic\",\n model: meta.model ? String(meta.model) : undefined,\n tools: Array.isArray(meta.tools) ? (meta.tools as string[]) : undefined,\n description: meta.description ? String(meta.description) : undefined,\n prompt: match[2].trim(),\n };\n}\n\nexport interface SessionSystemPromptOpts {\n aiLabel: string;\n topicTitle: string;\n workspaceCwd: string;\n agentKind: AgentKind;\n description?: string | null;\n /** True only for top-level agent rooms — the runtime spawn_subagent tool is registered there. */\n canSpawnSubagents?: boolean;\n /** True only when the current adapter renders Otium visual cards. */\n visualTools?: boolean;\n /** True only when the current adapter can deliver files to its chat. */\n fileDeliveryTools?: boolean;\n}\n\nfunction buildRuntimeToolSection(\n agentKind: AgentKind,\n canSpawnSubagents = false,\n visualTools = false,\n fileDeliveryTools = false,\n): string {\n const runtimeNamespace = \"mcp__runtime\";\n const taskNamespace = \"mcp__task\";\n const visualToolLine =\n agentKind === \"codex\"\n ? `To display charts, tables, or interactive HTML results to the user, call the \\`show_html\\` function in the \\`${runtimeNamespace}\\` namespace with { html: \"<complete HTML string>\", title?: \"optional title\" }.`\n : `To display charts, tables, or interactive HTML results to the user, call the MCP tool \"${runtimeNamespace}__show_html\" with { html: \"<complete HTML string>\", title?: \"optional title\" }.`;\n const mermaidToolLine =\n agentKind === \"codex\"\n ? `For diagrams that Mermaid supports, prefer the \\`show_mermaid\\` function in the \\`${runtimeNamespace}\\` namespace with { code: \"<Mermaid DSL without markdown fences>\", title?: \"...\", theme?: \"neutral\" }.`\n : `For diagrams that Mermaid supports, prefer the MCP tool \"${runtimeNamespace}__show_mermaid\" with { code: \"<Mermaid DSL without markdown fences>\", title?: \"...\", theme?: \"neutral\" }.`;\n const mediaToolLine =\n agentKind === \"codex\"\n ? `To display an existing image or video in the visual panel, use \\`show_image\\` or \\`show_video\\` in the \\`${runtimeNamespace}\\` namespace with either { file_path: \"...\", title?: \"...\" } for a topic-workspace file or { file_id: \"...\", title?: \"...\" } for an uploaded file already attached in this topic.`\n : `To display an existing image or video in the visual panel, use MCP tool \"${runtimeNamespace}__show_image\" or \"${runtimeNamespace}__show_video\" with either { file_path: \"...\", title?: \"...\" } for a topic-workspace file or { file_id: \"...\", title?: \"...\" } for an uploaded file already attached in this topic.`;\n const sendFileTool =\n agentKind === \"codex\"\n ? `\\`send_file\\` function in the \\`${runtimeNamespace}\\` namespace`\n : `MCP tool \"${runtimeNamespace}__send_file\"`;\n const askUserToolLine =\n agentKind === \"codex\"\n ? `When you need a blocking user choice, call the \\`ask_user_question\\` function in the \\`${runtimeNamespace}\\` namespace with { question: \"...\", choices: [{ label: \"...\", description?: \"...\" }] }.`\n : `When you need a blocking user choice, call the MCP tool \"${runtimeNamespace}__ask_user_question\" with { question: \"...\", choices: [{ label: \"...\", description?: \"...\" }] }.`;\n const scheduleSelfToolLine =\n agentKind === \"codex\"\n ? `For a one-shot delayed continuation within 24 hours, call the \\`schedule_self\\` function in the \\`${runtimeNamespace}\\` namespace with { delay_seconds: number, message: \"self-contained future instruction\" }. Only one pending self-schedule is allowed per topic; use \\`get_self_schedule\\`, \\`update_self_schedule\\`, or \\`cancel_self_schedule\\` in that namespace to manage it. Use cron-manager for recurring schedules.`\n : `For a one-shot delayed continuation within 24 hours, call the MCP tool \"${runtimeNamespace}__schedule_self\" with { delay_seconds: number, message: \"self-contained future instruction\" }. Only one pending self-schedule is allowed per topic; manage it with \"${runtimeNamespace}__get_self_schedule\", \"${runtimeNamespace}__update_self_schedule\", or \"${runtimeNamespace}__cancel_self_schedule\". Use cron-manager for recurring schedules.`;\n const taskToolLine =\n agentKind === \"codex\"\n ? `For task tracking, use \\`task_create\\`, \\`task_update\\`, \\`task_list\\`, \\`task_get\\`, and \\`task_delete\\` functions in the \\`${taskNamespace}\\` namespace.`\n : `For task tracking, use MCP tools \"${taskNamespace}__task_create\", \"${taskNamespace}__task_update\", \"${taskNamespace}__task_list\", \"${taskNamespace}__task_get\", and \"${taskNamespace}__task_delete\".`;\n const spawnSubagentToolLine =\n agentKind === \"codex\"\n ? `To delegate a self-contained task to a background subagent, call the \\`spawn_subagent\\` function in the \\`${runtimeNamespace}\\` namespace with { task: \"...\", name?: \"...\", agent?: \"claude\"|\"codex\"|\"maestro\", model?: \"...\" }.`\n : `To delegate a self-contained task to a background subagent, call the MCP tool \"${runtimeNamespace}__spawn_subagent\" with { task: \"...\", name?: \"...\", agent?: \"claude\"|\"codex\"|\"maestro\", model?: \"...\" }.`;\n const spawnSubagentSection = canSpawnSubagents\n ? [\n \"\",\n \"## Subagent Delegation\",\n spawnSubagentToolLine,\n \"The subagent works in its own new agent room and starts with ONLY the task text — include all needed context, file paths, and acceptance criteria in it.\",\n \"The call returns immediately (fire-and-forget); the subagent's final result is delivered back into this room automatically when it finishes. End your turn normally — never wait or poll for it.\",\n \"Use it for parallelizable or long-running side work; keep quick inline work in this room.\",\n ]\n : [];\n const nativeTaskPolicyLine =\n agentKind === \"claude\"\n ? `Do not use provider-native todo/task/subagent tools such as \"TodoWrite\", \"Task\", \"Agent\", \"TaskCreate\", \"TaskUpdate\", \"TaskList\", \"TaskOutput\", or \"TaskStop\"; they are disabled or not shared across agents.${canSpawnSubagents ? \" For delegation, use the runtime spawn_subagent tool instead.\" : \"\"}`\n : agentKind === \"maestro\"\n ? `Do not use provider-native task-store tools such as \"TaskCreate\", \"TaskUpdate\", \"TaskList\", \"TaskGet\", \"TaskOutput\", or \"TaskStop\"; they are disabled or not shared across agents. Do not use the Maestro \"Agent\" sub-agent tool either; it is disabled.${canSpawnSubagents ? \" Use the runtime spawn_subagent tool for delegation so work is visible in its own room and the result returns here automatically.\" : \" Delegation is unavailable in this room.\"}`\n : 'Do not use provider-native todo/plan surfaces such as \"todo_list\" or \"update_plan\"; they are ignored or not shared across agents.';\n const visualSection = visualTools\n ? [\n visualToolLine,\n mermaidToolLine,\n mediaToolLine,\n 'Do not call a bare \"show_html\"; use the exposed visuals MCP tool. A successful call means the card was shown in the user chat.',\n \"Visual HTML runs in a sandbox. Use inline CSS/JS only; local buttons, tabs, filters, forms with preventDefault, canvas, and SVG interactions are supported. External navigation, scripts, network fetches, form posts, popups, and parent-window access are blocked.\",\n ]\n : [];\n const fileDeliverySection = fileDeliveryTools\n ? [\n \"\",\n \"## File Delivery\",\n `To send a file to the user, save it under your working directory and call the ${sendFileTool} with { file_path: \"<absolute path>\" }.`,\n \"It appears as a downloadable attachment in the chat and returns success. Never claim file delivery is unavailable after a successful call.\",\n ]\n : [];\n\n const shared = [\n \"\",\n \"\",\n \"## Runtime Tools\",\n ...visualSection,\n askUserToolLine,\n 'Do not use provider built-in \"AskUserQuestion\"; it is disabled or unsupported in this headless chat runtime. Use the runtime ask_user_question tool instead.',\n scheduleSelfToolLine,\n ...(visualTools ? [\"\", visualDesignGuide()] : []),\n \"\",\n \"## Shared Tasks\",\n taskToolLine,\n \"Use this shared task store for plans, task progress, and checklist updates. It is visible across claude/codex/maestro turns and drives the live task panel.\",\n nativeTaskPolicyLine,\n ...fileDeliverySection,\n \"\",\n \"## Session Communication\",\n \"The session-comm MCP server is the only cross-topic messaging surface. Its canonical tools are `list_sessions`, `peek_session`, `tell_session`, `ask_session`, and `abort_session`.\",\n \"Use `list_sessions` to inspect available topics. Use `ask_session` for read-only questions whose result you need back in your own context. Use `tell_session` for one-way delegation or context handoff where no reply should return here. Do not describe `tell_session` as bidirectional and do not claim `ask_session` is unavailable without first checking the session-comm tools.\",\n ...(agentKind === \"maestro\"\n ? [\n 'Session-comm schemas may initially be deferred. Before using or judging availability, call ToolSearch(\"select:mcp__session-comm__list_sessions,mcp__session-comm__peek_session,mcp__session-comm__tell_session,mcp__session-comm__ask_session,mcp__session-comm__abort_session\") to activate the exact tools. Never substitute a similarly described runtime tool.',\n ]\n : []),\n \"Do not use session communication to make another topic perform destructive changes without the user's clear intent.\",\n ...spawnSubagentSection,\n ];\n\n const topicConfig = [\n \"\",\n \"## Topic Configuration (model / agent / effort)\",\n \"The user's configured agent/model/effort is intentional. Preserve it by default.\",\n `When the user explicitly asks to change the model, agent backend, or reasoning effort for THIS topic, call \"${runtimeNamespace}__set_model\", \"${runtimeNamespace}__set_agent\", or \"${runtimeNamespace}__set_effort\". The change applies from your NEXT turn. After calling, briefly confirm and the system will continue with the new setting.`,\n \"`set_effort` is available but discouraged; use it only when the user explicitly requests an effort change.\",\n \"`set_model` may be called autonomously only when the current model is clearly below the task's required capability, such as complex algorithm design, proof-level math, or broad multi-file refactoring. In that case, move up one step within the same agent and end the turn. Do not use vague task complexity as a trigger.\",\n \"`set_agent` autonomous calls are forbidden. Only switch agent when the user explicitly asks to switch runtime, e.g. “codex로 가”, “claude로 바꿔”.\",\n \"Never use `fable` unless the user explicitly requests it; it is expensive.\",\n \"\",\n \"Accepted values:\",\n \"- claude models: `sonnet` (default), `opus`, `fable`; efforts: `low`, `medium`, `high`, `xhigh`, `max`.\",\n \"- codex models: `gpt-5.6-luna` (default), `gpt-5.6-terra`, `gpt-5.6-sol`; efforts: `low`, `medium`, `high`, `xhigh`, `max`.\",\n \"- maestro models: `deepseek-pro` (default), `deepseek-flash`, `deepseek`; efforts: `low`, `medium`, `high`, `xhigh`, `max`.\",\n \"Agent guidance when the user explicitly asks to switch: `codex` for deepest reasoning and complex code/math; `claude` for tool-heavy MCP/file automation; `maestro` for inexpensive fast drafts and lighter experiments.\",\n ];\n\n if (agentKind !== \"claude\") {\n return [\n ...shared,\n ...topicConfig,\n \"\",\n \"## Runtime Tool Limits\",\n \"If file delivery or topic configuration tools are not present in your available tools for this session, do not claim you used them. Tell the user this session does not expose that in-chat tool action.\",\n ].join(\"\\n\");\n }\n\n return [...shared, ...topicConfig].join(\"\\n\");\n}\n\nexport function buildTopicSystemPrompt(opts: SessionSystemPromptOpts): string {\n const uploadsDir = `${opts.workspaceCwd}/attachments`;\n let prompt =\n replaceVars(topicSystemPromptTemplate(), {\n AI_LABEL: opts.aiLabel,\n TOPIC_TITLE: opts.topicTitle,\n WORKSPACE_CWD: opts.workspaceCwd,\n UPLOADS_DIR: uploadsDir,\n }) +\n buildRuntimeToolSection(\n opts.agentKind,\n opts.canSpawnSubagents,\n opts.visualTools,\n opts.fileDeliveryTools,\n );\n if (opts.description?.trim()) {\n prompt += `\\n\\n## Topic-Specific Instructions\\n${opts.description.trim()}`;\n }\n return prompt;\n}\n\nexport function buildChannelSystemPrompt(opts: SessionSystemPromptOpts): string {\n const uploadsDir = `${opts.workspaceCwd}/attachments`;\n return (\n replaceVars(channelSystemPromptTemplate(), {\n AI_LABEL: opts.aiLabel,\n TOPIC_TITLE: opts.topicTitle,\n WORKSPACE_CWD: opts.workspaceCwd,\n UPLOADS_DIR: uploadsDir,\n }) + buildRuntimeToolSection(opts.agentKind, false, opts.visualTools, opts.fileDeliveryTools)\n );\n}\n\nexport function buildManagerSystemPrompt(opts: SessionSystemPromptOpts): string {\n return `${buildTopicSystemPrompt(opts)}\\n\\n${managerSystemPromptTemplate()}`;\n}\n\nexport function buildMemoryPromptSection(opts: {\n topicId: string;\n wikiDir: string;\n hasFiles: boolean;\n latestSummaryFile?: string | null;\n hasArchive?: boolean;\n isManager: boolean;\n}): string {\n const parts: string[] = [\"\\n\\n## Memory\"];\n const briefFile = `${opts.wikiDir}/topic/${opts.topicId}.md`;\n parts.push(`Memory directory: ${opts.wikiDir}/topic`);\n parts.push(`Files: ${opts.hasFiles ? briefFile : \"(none)\"}`);\n if (opts.latestSummaryFile) {\n parts.push(`Latest summary: ${opts.latestSummaryFile}`);\n }\n parts.push(\n \"\",\n opts.isManager\n ? opts.hasFiles\n ? \"위는 이 워크스페이스의 메모리 허브 브리프입니다(모든 토픽 아카이브가 누적됨). 과거 맥락·다른 토픽 내용을 물으면 먼저 이 브리프를 참고하고, 더 깊은 검색은 `wiki_query` MCP 도구를 사용하세요.\"\n : \"위임된 작업 처리 중 과거 맥락이 필요하면 `wiki_query` MCP 도구를 사용하세요.\"\n : opts.hasFiles\n ? \"위 파일은 이 토픽의 Wiki 브리프입니다. 과거 맥락 파악 시 먼저 Read로 읽으세요. 더 깊은 검색이 필요하면 `wiki_query` MCP 도구를 사용하세요.\"\n : opts.latestSummaryFile\n ? \"Wiki 브리프 파일은 아직 없습니다. 과거 맥락 파악 시 먼저 Latest summary를 Read로 읽으세요. 더 깊은 검색이 필요하면 `wiki_query` MCP 도구를 사용하세요.\"\n : \"Wiki 브리프 파일은 아직 없습니다. 과거 맥락 파악 시 `wiki_query` MCP 도구를 사용하세요.\",\n );\n parts.push(\n \"\",\n opts.isManager\n ? \"워크스페이스 과거 결정이나 다른 토픽 맥락을 답할 때는 메모리를 자연스럽게 반영하되, 확실하지 않으면 `wiki_query`로 확인하세요.\"\n : opts.hasFiles || opts.latestSummaryFile\n ? \"토픽 첫 응답 시, Wiki 브리프\" +\n (opts.latestSummaryFile ? \"와 Latest summary를 Read로 읽고\" : \"를 Read로 읽고\") +\n \" 맥락 요약을 자연스럽게 한 줄로 언급하세요. 사용자가 맥락이 맞는지 바로 판단할 수 있도록.\"\n : \"토픽 첫 응답 시, 필요한 경우 이전 대화 맥락을 확인한 뒤 자연스럽게 한 줄로 언급하세요.\",\n );\n parts.push(\n \"\",\n opts.hasFiles\n ? \"사용자가 기억이 틀렸다고 교정하면, Memory directory의 해당 파일을 Read로 찾아 Edit으로 직접 수정하세요.\"\n : \"사용자가 기억이 틀렸다고 교정하면, 관련 Wiki 브리프를 확인하고 가능한 경우 직접 수정하거나 `wiki_query`로 관련 항목을 찾아 근거를 맞추세요.\",\n );\n if (opts.hasArchive) {\n parts.push(\n \"\",\n \"이전 세션의 실제 대화 내용이 필요하면 `wiki_last_conversation` MCP 도구를 사용하세요.\",\n );\n }\n return parts.join(\"\\n\");\n}\n",
6
+ "import { randomBytes } from \"node:crypto\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { logger } from \"#platform/logger\";\nimport { type AgentKind, isAgentKind } from \"#types\";\n\nexport function envText(envKey: string): string | undefined {\n const value = process.env[envKey]?.trim();\n return value ? value : undefined;\n}\n\nfunction resolveAgentEnv(envKey: string, fallback: AgentKind, legacyEnvKey?: string): AgentKind {\n const value = envText(envKey) ?? (legacyEnvKey ? envText(legacyEnvKey) : undefined);\n return isAgentKind(value) ? value : fallback;\n}\n\nconst HOME = homedir();\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. */\nfunction resolveDependencyBin(name: string): string {\n let dir = PROJECT_ROOT;\n while (true) {\n const candidate = resolve(dir, \"node_modules\", \".bin\", name);\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return candidate;\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).\nconst STATE_DIR_ENV = envText(\"NEGOTIUM_STATE_DIR\");\nexport const STATE_DIR = STATE_DIR_ENV ? resolve(STATE_DIR_ENV) : resolve(HOME, \".negotium\");\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 if (!envValue) return fallback;\n const port = Number.parseInt(envValue, 10);\n return Number.isInteger(port) && port > 0 ? port : 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 CONTEXTS_DIR = resolve(WORKSPACE_DIR, \"contexts\");\nexport const BROWSER_PROFILES_DIR = resolve(WORKSPACE_DIR, \"browser-profiles\");\nexport const DM_WORKSPACE_DIR = resolve(WORKSPACE_DIR, \"dm\");\nexport const SESSION_WORKSPACE_DIR = resolve(WORKSPACE_DIR, \"sessions\");\nexport const CLAUDE_EXECUTABLE = resolve(HOME, \".local/bin/claude\");\n\n// Browser automation uses the authenticated local Patchright HTTP wrapper.\nexport function resolveBrowserMcpBin(envValue?: string): string {\n const override = envValue?.trim();\n if (override) {\n if (!/(^|\\/)(mcp-patchright|mcp-patchright-http\\.mjs)$/.test(override)) {\n throw new Error(\n \"NEGOTIUM_BROWSER_MCP_BIN must point to the authenticated mcp-patchright wrapper.\",\n );\n }\n return override;\n }\n return PATCHRIGHT_MCP_BIN;\n}\n\nexport const PATCHRIGHT_MCP_BIN = resolve(PROJECT_ROOT, \"scripts/mcp-patchright-http.mjs\");\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\");\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 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 PADDLEOCR_SERVER = resolve(PROJECT_ROOT, \"src/mcp/paddleocr-server.ts\");\n\nexport const TOKEN_STATS_SERVER = resolve(PROJECT_ROOT, \"src/mcp/token-stats-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 BACKGROUND_BASH_SERVER = resolve(PROJECT_ROOT, \"src/mcp/background-bash-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 const cleaned = value\n .trim()\n .replace(/[^A-Za-z0-9._-]/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 160);\n return cleaned || 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(STATE_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);\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\");\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)\nexport const RUN_DIR = resolveLocalStateDir(\"NEGOTIUM_RUN_DIR\", \"run\");\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\");\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(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(CONTEXTS_DIR, { recursive: true });\nmkdirSync(BROWSER_PROFILES_DIR, { recursive: true });\nmkdirSync(DM_WORKSPACE_DIR, { recursive: true });\nmkdirSync(SESSION_WORKSPACE_DIR, { recursive: true });\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\nexport const FILE_EXTENSIONS_REGEX =\n /(?:\\/[^\\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))/gi;\n\nexport const FILE_TAG_REGEX = /\\[FILE:(\\/[^\\]]+)\\]/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-4-8\";\nexport const MODEL_HAIKU = \"claude-haiku-4-5-20251001\";\nexport const MODEL_FABLE = \"claude-fable-5\"; // Mythos-class, announced 2026-06-09\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// Agent + model defaults split by session role. FALLBACK_* is the shared base;\n// SESSION_* overrides topic + ephemeral; GATEWAY_* overrides dm + manager.\n// DEFAULT_* is accepted as a legacy alias during the env migration window.\nexport const FALLBACK_AGENT: AgentKind = resolveAgentEnv(\n \"FALLBACK_AGENT\",\n \"maestro\",\n \"DEFAULT_AGENT\",\n);\nexport const SESSION_AGENT: AgentKind = resolveAgentEnv(\"SESSION_AGENT\", FALLBACK_AGENT);\nexport const GATEWAY_AGENT: AgentKind = resolveAgentEnv(\"GATEWAY_AGENT\", FALLBACK_AGENT);\n\nexport const FALLBACK_MODEL = envText(\"FALLBACK_MODEL\") ?? envText(\"DEFAULT_MODEL\");\n\nfunction resolveModelEnv(envKey: string, agentConst: AgentKind): string | undefined {\n return envText(envKey) ?? (agentConst === FALLBACK_AGENT ? FALLBACK_MODEL : undefined);\n}\n\nexport const SESSION_MODEL = resolveModelEnv(\"SESSION_MODEL\", SESSION_AGENT);\nexport const GATEWAY_MODEL = resolveModelEnv(\"GATEWAY_MODEL\", GATEWAY_AGENT);\n\n/** Resolve the effective display/default model for a topic (session context).\n * Applies the session model override only when that role owns the agent;\n * otherwise each registry's native default stays authoritative. */\nexport function resolveDefaultModel(agent: string, registryDefaultModel: string): string {\n return agent === SESSION_AGENT && SESSION_MODEL ? SESSION_MODEL : registryDefaultModel;\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// 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 process.env.NEGOTIUM_CODEX_AUTH_FILE || join(homedir(), \".codex\", \"auth.json\");\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",
7
7
  "import pino from \"pino\";\n\n/**\n * Always write logs to stderr (fd 2), never stdout.\n *\n * MCP servers under `src/mcp/**` run as stdio subprocesses where stdout is the\n * JSON-RPC transport channel. A single log line on stdout corrupts the next\n * message and the MCP client closes the transport (\"Transport closed\"). The\n * main bot process is also fine with stderr — pm2 captures both streams.\n *\n * In dev mode pino spawns a `pino-pretty` worker that owns its own sink, so we\n * pass `destination: 2` through transport.options. In prod (no transport) the\n * second arg to `pino()` sets the destination directly.\n */\nexport const logger = pino(\n {\n level: process.env.LOG_LEVEL || \"info\",\n transport:\n process.env.NODE_ENV === \"development\"\n ? {\n target: \"pino-pretty\",\n options: {\n colorize: true,\n translateTime: \"SYS:yyyy-mm-dd HH:MM:ss\",\n destination: 2,\n },\n }\n : undefined,\n },\n pino.destination(2),\n);\n",
8
- "/**\n * Common context carried through the attachment/prompt-build pipeline.\n * Used by buildPromptFromMessage and related helpers.\n */\nexport interface SessionContext {\n userId: number;\n topicName?: string;\n userDir?: string;\n sessionType?: \"dm\" | \"forum\" | \"ephemeral\" | \"manager\" | \"cron\";\n}\n\nexport interface TokenUsage {\n /** Aggregate billable input across every model call made during this turn. */\n inputTokens: number;\n outputTokens: number;\n cacheCreationInputTokens?: number;\n cacheReadInputTokens?: number;\n /** Provider-reported query cost when available. */\n costUsd?: number;\n /** Tokens occupied by the latest model call, not aggregate turn spend. */\n contextTokens?: number;\n /** Provider-reported context window for the latest model call. */\n contextWindow?: number;\n}\n\n/** Agent identifier — one of the supported AI provider backends. */\nexport type AgentKind = \"maestro\" | \"claude\" | \"codex\";\n\nexport const SUPPORTED_AGENTS: readonly AgentKind[] = [\"maestro\", \"claude\", \"codex\"] as const;\n\nexport function isAgentKind(value: unknown): value is AgentKind {\n return typeof value === \"string\" && (SUPPORTED_AGENTS as readonly string[]).includes(value);\n}\n\n/**\n * Per-agent supported reasoning efforts. Single source of truth for both the\n * `EffortLevel` type and each registry's `validEfforts` runtime list — the\n * registries import these directly so adding a value in one place\n * propagates to validation, footer rendering, and zod enums.\n *\n * Claude SDK rejects 'minimal'; Codex SDK rejects 'max'. The two sets\n * intersect on low/medium/high/xhigh. Maestro (TS port) currently piggybacks\n * on the Anthropic provider, so its efforts mirror the Claude set; this can\n * narrow per-provider once Phase 5 lands.\n *\n * 'minimal' removed from codex: Codex API rejects it when default tools\n * (image_gen, web_search) are active, making agent sessions unusable.\n */\nexport const CLAUDE_EFFORT_VALUES = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nexport const CODEX_EFFORT_VALUES = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nexport const MAESTRO_EFFORT_VALUES = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\nexport type EffortLevel =\n | (typeof CLAUDE_EFFORT_VALUES)[number]\n | (typeof CODEX_EFFORT_VALUES)[number]\n | (typeof MAESTRO_EFFORT_VALUES)[number];\n\n/**\n * Runtime iteration list (used by zod enums and any callers that need to\n * loop over every accepted value). Manually ordered for readability; the\n * `satisfies` check fails the build if an entry here isn't covered by the\n * per-agent unions above.\n */\nexport const EFFORT_VALUES = [\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n] as const satisfies readonly EffortLevel[];\n\n/**\n * Normalized events yielded by any agent provider (claudeProvider, codexProvider).\n * The handler/event-processor consumes these without caring which backend produced them.\n *\n * `user_message` is the lone \"into-the-log\" variant — no provider yields it.\n * The query handler writes it directly to the conversation log right before\n * `runAgent()` starts, so cross-agent rollout reconstruction can pair every\n * assistant turn with the user prompt that triggered it. Consumers that only\n * react to provider output (e.g. processAgentEvent) can safely ignore it.\n */\n/**\n * Wire-safe projection of one task, carried by the `tasks` UnifiedEvent.\n *\n * This is also the on-disk shape of Otium's shared task store, so claude,\n * codex, and maestro render the same live panel from the same source of truth.\n */\nexport interface TaskSnapshot {\n id: string;\n subject: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n /** Task ids this one is blocked by; omitted when empty. */\n blockedBy?: string[];\n /** Present-continuous label for spinners, when set. */\n activeForm?: string;\n /** Owner / agent name for multi-agent runs, when set. */\n owner?: string;\n}\n\nexport type UnifiedEvent =\n | { type: \"user_message\"; content: string }\n | { type: \"session\"; sessionId: string }\n | {\n type: \"tool_use\";\n name: string;\n input: Record<string, unknown>;\n /** Provider-assigned id so the client can match tool_use→tool_result pairs. */\n toolUseId?: string;\n }\n | { type: \"tool_progress\"; toolName: string; elapsed: number }\n | { type: \"tool_use_summary\"; summary: string }\n // Provider reasoning/thinking summary text (Codex `reasoning` items; Claude\n // extended-thinking). Surfaced so background runs (cron/archiver) show the\n // agent's thought process, not just tool calls.\n | { type: \"reasoning\"; content: string }\n // Full task-list snapshot (replace, not delta) from Otium's shared task\n // store. Provider-native task/todo stores are not authoritative.\n | { type: \"tasks\"; tasks: TaskSnapshot[] }\n | {\n type: \"tool_result\";\n toolUseId: string;\n content: string;\n metadata?: {\n truncatedForModel: boolean;\n originalBytes: number;\n returnedBytes: number;\n omittedBytes?: number;\n outputPath?: string;\n };\n }\n | { type: \"text_delta\"; content: string }\n | { type: \"text\"; content: string }\n | { type: \"result\"; content: string; stopReason: string; usage?: TokenUsage }\n | { type: \"file\"; path: string; source: string; origin: \"tag\" | \"extension\" }\n | {\n type: \"error\";\n content: string;\n usage?: TokenUsage;\n code?: \"budget_exceeded\";\n }\n | { type: \"status\"; content: string };\n\nexport interface AgentInputAttachment {\n id: string;\n type: \"image\" | \"file\" | \"audio\";\n filename: string;\n mimeType: string;\n sizeBytes: number;\n path: string;\n}\n\n/** Worker-side runtime tools proxy user-facing state back to the canonical\n * hub topic identified here. */\nexport interface PeerRuntimeBridgeContext {\n hubCellId: string;\n hostTopicId: string;\n hostQueryId: string;\n canSpawnSubagents: boolean;\n}\n\nexport interface AgentQueryOptions {\n agent: AgentKind;\n prompt: string;\n attachments?: AgentInputAttachment[];\n sessionId?: string | null;\n cwd: string;\n systemPrompt: string;\n userId?: string;\n session?: string;\n playwrightPort?: number;\n playwrightCapability?: string;\n bgBashPort?: number;\n sessionType?: \"dm\" | \"forum\" | \"ephemeral\" | \"manager\" | \"cron\";\n /** API topic id (REST/WS world). Carries per-query topic context for MCP servers. */\n topicId?: string;\n /** API query id for the currently running turn. Used by runtime MCP tools. */\n queryId?: string;\n /** Optional wiki-memory topic id. Derived topics use their root origin here\n * while other per-topic MCP servers keep `topicId` bound to the live room. */\n wikiTopicId?: string;\n /** Whether self-config MCP may enqueue an automatic continue turn after set_* changes. */\n autoContinue?: boolean;\n /** Expose Otium-only visual panel tools for this turn. Default-deny. */\n visualTools?: boolean;\n abortController?: AbortController;\n model?: string;\n /** Provider-side hard budget when the selected SDK supports one. */\n maxBudgetUsd?: number;\n depth?: number;\n agents?: Record<\n string,\n {\n description: string;\n prompt: string;\n model?: string;\n tools?: string[];\n maxTurns?: number;\n effort?: EffortLevel | number;\n }\n >;\n effort?: EffortLevel;\n /**\n * Per-API-call `max_tokens` ceiling on the assistant's output. Wired\n * through to the underlying provider request body for every agent\n * (claude/codex/maestro). Omit to inherit each provider SDK's per-model\n * default — for maestro that's the v0.1.21+ `getNativeMaxOutputTokens`\n * catalog (deepseek-pro=64K, deepseek-flash=32K).\n *\n * Pass an explicit number when a specific topic / surface needs a tighter\n * latency cap or a higher ceiling for long-form generation (legal\n * report writing, multi-K Write/Edit file bodies). Pre-0.1.21 maestro\n * builds silently clamped at 4096 and truncated outputs mid-string;\n * setting this field is now the supported way to lift that ceiling.\n */\n maxTokens?: number;\n /**\n * v0.1.22+: Claude-Code-style deferred tool catalog + `ToolSearch` built-in.\n *\n * Wired straight through to `maestro-agent-sdk`'s\n * `AgentQueryOptions.enableToolSearch`. When `true`, the maestro provider\n * registers every MCP tool as deferred — schemas stay off the wire until\n * the model promotes them via `ToolSearch(\"select:Name1,Name2\")` or\n * `ToolSearch(\"keyword\")`. Active set persists across resume.\n *\n * Otium's maestro provider supplies `true` when the caller leaves this\n * option unset, because most forum turns carry enough MCP surface for the\n * reminder-token savings to outweigh the first-use `ToolSearch` round-trip.\n * Callers can still pass `false` per call when a narrow surface or\n * latency-sensitive workflow is better served by eager MCP schemas.\n *\n * No-op for claude / codex agents — they have their own deferred-tool\n * machinery owned by their respective SDKs.\n */\n enableToolSearch?: boolean;\n /**\n * Claude-Code-compatible exact tool denylist. Maestro v0.1.42+ hides these\n * tools from provider schemas / ToolSearch and blocks dispatch if a stale\n * call still arrives. Claude maps this to its SDK option. Codex does not\n * support this name-based list; its provider-native multi-agent tool family\n * is disabled separately through the Codex feature config.\n */\n disallowedTools?: readonly string[];\n mcpEnabled?: string[] | null;\n peerBridge?: PeerRuntimeBridgeContext;\n mcpExtra?: Record<string, unknown>;\n /**\n * true for silent fork runs generating ask_session replies — restricts session-comm\n * outbound tools (ask/tell/abort) so the forked session can only produce text\n */\n silent?: boolean;\n}\n\n/** State file written to data/users/{userId}/active-queries/{topic}.json while a query is running. */\nexport interface QueryState {\n task?: string; // first 100 chars of prompt, newlines normalized\n since: string; // ISO timestamp\n}\n"
8
+ "/**\n * Common context carried through the attachment/prompt-build pipeline.\n * Used by buildPromptFromMessage and related helpers.\n */\nexport interface SessionContext {\n userId: number;\n topicName?: string;\n userDir?: string;\n sessionType?: \"dm\" | \"forum\" | \"ephemeral\" | \"manager\" | \"cron\";\n}\n\nexport interface TokenUsage {\n /** Aggregate billable input across every model call made during this turn. */\n inputTokens: number;\n outputTokens: number;\n cacheCreationInputTokens?: number;\n cacheReadInputTokens?: number;\n /** Provider-reported query cost when available. */\n costUsd?: number;\n /** Tokens occupied by the latest model call, not aggregate turn spend. */\n contextTokens?: number;\n /** Provider-reported context window for the latest model call. */\n contextWindow?: number;\n}\n\n/** Agent identifier — one of the supported AI provider backends. */\nexport type AgentKind = \"maestro\" | \"claude\" | \"codex\";\n\nexport const SUPPORTED_AGENTS: readonly AgentKind[] = [\"maestro\", \"claude\", \"codex\"] as const;\n\nexport function isAgentKind(value: unknown): value is AgentKind {\n return typeof value === \"string\" && (SUPPORTED_AGENTS as readonly string[]).includes(value);\n}\n\n/**\n * Per-agent supported reasoning efforts. Single source of truth for both the\n * `EffortLevel` type and each registry's `validEfforts` runtime list — the\n * registries import these directly so adding a value in one place\n * propagates to validation, footer rendering, and zod enums.\n *\n * Claude SDK rejects 'minimal'; Codex SDK rejects 'max'. The two sets\n * intersect on low/medium/high/xhigh. Maestro (TS port) currently piggybacks\n * on the Anthropic provider, so its efforts mirror the Claude set; this can\n * narrow per-provider once Phase 5 lands.\n *\n * 'minimal' removed from codex: Codex API rejects it when default tools\n * (image_gen, web_search) are active, making agent sessions unusable.\n */\nexport const CLAUDE_EFFORT_VALUES = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nexport const CODEX_EFFORT_VALUES = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nexport const MAESTRO_EFFORT_VALUES = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\nexport type EffortLevel =\n | (typeof CLAUDE_EFFORT_VALUES)[number]\n | (typeof CODEX_EFFORT_VALUES)[number]\n | (typeof MAESTRO_EFFORT_VALUES)[number];\n\n/**\n * Runtime iteration list (used by zod enums and any callers that need to\n * loop over every accepted value). Manually ordered for readability; the\n * `satisfies` check fails the build if an entry here isn't covered by the\n * per-agent unions above.\n */\nexport const EFFORT_VALUES = [\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n] as const satisfies readonly EffortLevel[];\n\n/**\n * Normalized events yielded by any agent provider (claudeProvider, codexProvider).\n * The handler/event-processor consumes these without caring which backend produced them.\n *\n * `user_message` is the lone \"into-the-log\" variant — no provider yields it.\n * The query handler writes it directly to the conversation log right before\n * `runAgent()` starts, so cross-agent rollout reconstruction can pair every\n * assistant turn with the user prompt that triggered it. Consumers that only\n * react to provider output (e.g. processAgentEvent) can safely ignore it.\n */\n/**\n * Wire-safe projection of one task, carried by the `tasks` UnifiedEvent.\n *\n * This is also the on-disk shape of Otium's shared task store, so claude,\n * codex, and maestro render the same live panel from the same source of truth.\n */\nexport interface TaskSnapshot {\n id: string;\n subject: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n /** Task ids this one is blocked by; omitted when empty. */\n blockedBy?: string[];\n /** Present-continuous label for spinners, when set. */\n activeForm?: string;\n /** Owner / agent name for multi-agent runs, when set. */\n owner?: string;\n}\n\nexport type UnifiedEvent =\n | { type: \"user_message\"; content: string }\n | { type: \"session\"; sessionId: string }\n | {\n type: \"tool_use\";\n name: string;\n input: Record<string, unknown>;\n /** Provider-assigned id so the client can match tool_use→tool_result pairs. */\n toolUseId?: string;\n }\n | { type: \"tool_progress\"; toolName: string; elapsed: number }\n | { type: \"tool_use_summary\"; summary: string }\n // Provider reasoning/thinking summary text (Codex `reasoning` items; Claude\n // extended-thinking). Surfaced so background runs (cron/archiver) show the\n // agent's thought process, not just tool calls.\n | { type: \"reasoning\"; content: string }\n // Full task-list snapshot (replace, not delta) from Otium's shared task\n // store. Provider-native task/todo stores are not authoritative.\n | { type: \"tasks\"; tasks: TaskSnapshot[] }\n | {\n type: \"tool_result\";\n toolUseId: string;\n content: string;\n metadata?: {\n truncatedForModel: boolean;\n originalBytes: number;\n returnedBytes: number;\n omittedBytes?: number;\n outputPath?: string;\n };\n }\n | { type: \"text_delta\"; content: string }\n | { type: \"text\"; content: string }\n | { type: \"result\"; content: string; stopReason: string; usage?: TokenUsage }\n | { type: \"file\"; path: string; source: string; origin: \"tag\" | \"extension\" }\n | {\n type: \"error\";\n content: string;\n usage?: TokenUsage;\n code?: \"budget_exceeded\";\n }\n | { type: \"status\"; content: string };\n\nexport interface AgentInputAttachment {\n id: string;\n type: \"image\" | \"file\" | \"audio\";\n filename: string;\n mimeType: string;\n sizeBytes: number;\n path: string;\n}\n\n/** Worker-side runtime tools proxy user-facing state back to the canonical\n * hub topic identified here. */\nexport interface PeerRuntimeBridgeContext {\n hubCellId: string;\n hostTopicId: string;\n hostQueryId: string;\n canSpawnSubagents: boolean;\n}\n\nexport interface AgentQueryOptions {\n agent: AgentKind;\n prompt: string;\n attachments?: AgentInputAttachment[];\n sessionId?: string | null;\n cwd: string;\n systemPrompt: string;\n userId?: string;\n session?: string;\n playwrightPort?: number;\n playwrightCapability?: string;\n bgBashPort?: number;\n sessionType?: \"dm\" | \"forum\" | \"ephemeral\" | \"manager\" | \"cron\";\n /** API topic id (REST/WS world). Carries per-query topic context for MCP servers. */\n topicId?: string;\n /** API query id for the currently running turn. Used by runtime MCP tools. */\n queryId?: string;\n /** Optional wiki-memory topic id. Derived topics use their root origin here\n * while other per-topic MCP servers keep `topicId` bound to the live room. */\n wikiTopicId?: string;\n /** Whether self-config MCP may enqueue an automatic continue turn after set_* changes. */\n autoContinue?: boolean;\n /** Expose Otium-only visual panel tools for this turn. Default-deny. */\n visualTools?: boolean;\n /** Expose adapter-backed file-delivery tools for this turn. Default-deny. */\n fileDeliveryTools?: boolean;\n abortController?: AbortController;\n model?: string;\n /** Provider-side hard budget when the selected SDK supports one. */\n maxBudgetUsd?: number;\n depth?: number;\n agents?: Record<\n string,\n {\n description: string;\n prompt: string;\n model?: string;\n tools?: string[];\n maxTurns?: number;\n effort?: EffortLevel | number;\n }\n >;\n effort?: EffortLevel;\n /**\n * Per-API-call `max_tokens` ceiling on the assistant's output. Wired\n * through to the underlying provider request body for every agent\n * (claude/codex/maestro). Omit to inherit each provider SDK's per-model\n * default — for maestro that's the v0.1.21+ `getNativeMaxOutputTokens`\n * catalog (deepseek-pro=64K, deepseek-flash=32K).\n *\n * Pass an explicit number when a specific topic / surface needs a tighter\n * latency cap or a higher ceiling for long-form generation (legal\n * report writing, multi-K Write/Edit file bodies). Pre-0.1.21 maestro\n * builds silently clamped at 4096 and truncated outputs mid-string;\n * setting this field is now the supported way to lift that ceiling.\n */\n maxTokens?: number;\n /**\n * v0.1.22+: Claude-Code-style deferred tool catalog + `ToolSearch` built-in.\n *\n * Wired straight through to `maestro-agent-sdk`'s\n * `AgentQueryOptions.enableToolSearch`. When `true`, the maestro provider\n * registers every MCP tool as deferred — schemas stay off the wire until\n * the model promotes them via `ToolSearch(\"select:Name1,Name2\")` or\n * `ToolSearch(\"keyword\")`. Active set persists across resume.\n *\n * Otium's maestro provider supplies `true` when the caller leaves this\n * option unset, because most forum turns carry enough MCP surface for the\n * reminder-token savings to outweigh the first-use `ToolSearch` round-trip.\n * Callers can still pass `false` per call when a narrow surface or\n * latency-sensitive workflow is better served by eager MCP schemas.\n *\n * No-op for claude / codex agents — they have their own deferred-tool\n * machinery owned by their respective SDKs.\n */\n enableToolSearch?: boolean;\n /**\n * Claude-Code-compatible exact tool denylist. Maestro v0.1.42+ hides these\n * tools from provider schemas / ToolSearch and blocks dispatch if a stale\n * call still arrives. Claude maps this to its SDK option. Codex does not\n * support this name-based list; its provider-native multi-agent tool family\n * is disabled separately through the Codex feature config.\n */\n disallowedTools?: readonly string[];\n mcpEnabled?: string[] | null;\n peerBridge?: PeerRuntimeBridgeContext;\n mcpExtra?: Record<string, unknown>;\n /**\n * true for silent fork runs generating ask_session replies — restricts session-comm\n * outbound tools (ask/tell/abort) so the forked session can only produce text\n */\n silent?: boolean;\n}\n\n/** State file written to data/users/{userId}/active-queries/{topic}.json while a query is running. */\nexport interface QueryState {\n task?: string; // first 100 chars of prompt, newlines normalized\n since: string; // ISO timestamp\n}\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "FC0F31C9DC3B340F64756E2164756E21",
10
+ "mappings": ";;AAAA,yBAAS;AACT,oBAAS;;;ACDT;AACA;AACA;AACA;AACA;;;ACJA;AAcO,IAAM,SAAS,KACpB;AAAA,EACE,OAAO,QAAQ,IAAI,aAAa;AAAA,EAChC,WAEM;AAAA,IACE,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,UAAU;AAAA,MACV,eAAe;AAAA,MACf,aAAa;AAAA,IACf;AAAA,EACF;AAER,GACA,KAAK,YAAY,CAAC,CACpB;;;ACFO,IAAM,mBAAyC,CAAC,WAAW,UAAU,OAAO;AAE5E,SAAS,WAAW,CAAC,OAAoC;AAAA,EAC9D,OAAO,OAAO,UAAU,YAAa,iBAAuC,SAAS,KAAK;AAAA;;;AFvBrF,SAAS,OAAO,CAAC,QAAoC;AAAA,EAC1D,MAAM,QAAQ,QAAQ,IAAI,SAAS,KAAK;AAAA,EACxC,OAAO,QAAQ,QAAQ;AAAA;AAGzB,SAAS,eAAe,CAAC,QAAgB,UAAqB,cAAkC;AAAA,EAC9F,MAAM,QAAQ,QAAQ,MAAM,MAAM,eAAe,QAAQ,YAAY,IAAI;AAAA,EACzE,OAAO,YAAY,KAAK,IAAI,QAAQ;AAAA;AAGtC,IAAM,OAAO,QAAQ;AAIrB,SAAS,kBAAkB,GAAW;AAAA,EACpC,MAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAAA,EACxD,MAAM,kBAAkB,QAAQ,WAAW,SAAS;AAAA,EACpD,IAAI,WAAW,QAAQ,iBAAiB,KAAK,CAAC;AAAA,IAAG,OAAO;AAAA,EACxD,OAAO,QAAQ,WAAW,OAAO;AAAA;AAG5B,IAAM,eAAe,mBAAmB;AAG/C,SAAS,oBAAoB,CAAC,MAAsB;AAAA,EAClD,IAAI,MAAM;AAAA,EACV,OAAO,MAAM;AAAA,IACX,MAAM,YAAY,QAAQ,KAAK,gBAAgB,QAAQ,IAAI;AAAA,IAC3D,IAAI,WAAW,SAAS;AAAA,MAAG,OAAO;AAAA,IAClC,MAAM,SAAS,QAAQ,GAAG;AAAA,IAC1B,IAAI,WAAW;AAAA,MAAK,OAAO;AAAA,IAC3B,MAAM;AAAA,EACR;AAAA;AAKF,IAAM,gBAAgB,QAAQ,oBAAoB;AAC3C,IAAM,YAAY,gBAAgB,QAAQ,aAAa,IAAI,QAAQ,MAAM,WAAW;AAE3F,SAAS,oBAAoB,CAAC,QAAgB,WAA2B;AAAA,EACvE,MAAM,WAAW,QAAQ,MAAM;AAAA,EAC/B,IAAI;AAAA,IAAU,OAAO,QAAQ,QAAQ;AAAA,EACrC,OAAO,QAAQ,WAAW,SAAS;AAAA;AAGrC,SAAS,YAAY,CAAC,UAA8B,UAA0B;AAAA,EAC5E,KAAK;AAAA,IAAU,OAAO;AAAA,EACtB,MAAM,OAAO,OAAO,SAAS,UAAU,EAAE;AAAA,EACzC,OAAO,OAAO,UAAU,IAAI,KAAK,OAAO,IAAI,OAAO;AAAA;AAG9C,IAAM,gBAAgB,qBAAqB,0BAA0B,WAAW;AAChF,IAAM,sBAAsB,QAAQ,eAAe,QAAQ;AAC3D,IAAM,kBAAkB,QAAQ,eAAe,MAAM;AACrD,IAAM,eAAe,QAAQ,eAAe,UAAU;AACtD,IAAM,uBAAuB,QAAQ,eAAe,kBAAkB;AACtE,IAAM,mBAAmB,QAAQ,eAAe,IAAI;AACpD,IAAM,wBAAwB,QAAQ,eAAe,UAAU;AAC/D,IAAM,oBAAoB,QAAQ,MAAM,mBAAmB;AAG3D,SAAS,oBAAoB,CAAC,UAA2B;AAAA,EAC9D,MAAM,WAAW,UAAU,KAAK;AAAA,EAChC,IAAI,UAAU;AAAA,IACZ,KAAK,mDAAmD,KAAK,QAAQ,GAAG;AAAA,MACtE,MAAM,IAAI,MACR,kFACF;AAAA,IACF;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA;AAGF,IAAM,qBAAqB,QAAQ,cAAc,iCAAiC;AAClF,IAAM,qBAAqB,qBAAqB,QAAQ,0BAA0B,CAAC;AAwDnF,IAAM,UAAU,qBAAqB,KAAK;AAC1C,IAAM,gBAAgB,QAAQ,cAAc,eAAe;AAE3D,IAAM,sBAAsB,QAAQ,cAAc,gCAAgC;AAElF,IAAM,cAAc,QAAQ,cAAc,wBAAwB;AAClE,IAAM,6BAA6B,QACxC,cACA,mCACF;AAEO,IAAM,cAAc,QAAQ,cAAc,wBAAwB;AAElE,IAAM,mBAAmB,QAAQ,cAAc,6BAA6B;AAE5E,IAAM,qBAAqB,QAAQ,cAAc,+BAA+B;AAEhF,IAAM,uBAAuB,QAAQ,cAAc,iCAAiC;AAEpF,IAAM,sBAAsB,QAAQ,cAAc,gCAAgC;AAElF,IAAM,yBAAyB,QAAQ,cAAc,mCAAmC;AAExF,IAAM,eAAe,QAAQ,cAAc,yBAAyB;AAEpE,IAAM,oBAAoB,aAAa,QAAQ,IAAI,mBAAmB,IAAI;AAC1E,IAAM,mBAAmB,aAAa,QAAQ,IAAI,kBAAkB,IAAI;AAoB/E,SAAS,uBAAuB,CAC9B,QACA,UACA,UAAyC,CAAC,GAClC;AAAA,EACR,MAAM,WAAW,QAAQ,MAAM;AAAA,EAC/B,MAAM,aAAa,QAAQ,WAAW,QAAQ;AAAA,EAC9C,UAAU,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,EAClD,IAAI,UAAU;AAAA,IACZ,IAAI,QAAQ,iBAAiB;AAAA,MAC3B,cAAc,YAAY,GAAG;AAAA,GAAc,EAAE,MAAM,IAAM,CAAC;AAAA,MAC1D,UAAU,YAAY,GAAK;AAAA,IAC7B;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,WAAW,UAAU,GAAG;AAAA,IAC1B,MAAM,SAAS,aAAa,YAAY,OAAO,EAAE,KAAK;AAAA,IACtD,IAAI,QAAQ;AAAA,MACV,UAAU,YAAY,GAAK;AAAA,MAC3B,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,YAAY,EAAE,EAAE,SAAS,WAAW;AAAA,EACnD,IAAI;AAAA,IACF,cAAc,YAAY,GAAG;AAAA,GAAY,EAAE,MAAM,KAAO,MAAM,KAAK,CAAC;AAAA,IACpE,OAAO;AAAA,IACP,OAAO,OAAO;AAAA,IACd,IAAK,MAAgC,SAAS;AAAA,MAAU,MAAM;AAAA,IAC9D,MAAM,SAAS,aAAa,YAAY,OAAO,EAAE,KAAK;AAAA,IACtD,KAAK;AAAA,MAAQ,MAAM,IAAI,MAAM,oCAAoC,YAAY;AAAA,IAC7E,UAAU,YAAY,GAAK;AAAA,IAC3B,OAAO;AAAA;AAAA;AAIJ,IAAM,qBAAqB,wBAChC,sBACA,oBACF;AAEO,IAAM,qBAAqB,wBAChC,0BACA,oBACF;AACO,IAAM,mBAAmB,wBAC9B,6BACA,oBACA,EAAE,iBAAiB,KAAK,CAC1B;AAGA,OAAO,QAAQ,IAAI;AAGZ,IAAM,gBAAgB,SAAS,QAAQ,IAAI,iBAAiB,QAAQ,EAAE;AACtE,IAAM,WAAW,QAAQ,IAAI,YAAY;AAGzC,IAAM,WAAW,qBAAqB,qBAAqB,MAAM;AACjE,IAAM,UAAU,qBAAqB,oBAAoB,MAAM;AAE/D,IAAM,cAAc,QAAQ,IAAI,mBACnC,QAAQ,QAAQ,IAAI,gBAAgB,IACpC,QAAQ,UAAU,aAAa;AAC5B,IAAM,aAAa,QAAQ,UAAU,kBAAkB;AACvD,IAAM,gBAAgB,QAAQ,UAAU,OAAO;AAG/C,IAAM,UAAU,qBAAqB,oBAAoB,KAAK;AAC9D,IAAM,eAAe,QAAQ,SAAS,UAAU;AAChD,IAAM,aAAa,QAAQ,SAAS,aAAa;AACjD,IAAM,cAAc,QAAQ,SAAS,cAAc;AACnD,IAAM,oBAAoB,QAAQ,SAAS,eAAe;AAC1D,IAAM,mBAAmB,QAAQ,SAAS,cAAc;AACxD,IAAM,uBAAuB,aAAa,QAAQ,IAAI,sBAAsB,IAAI;AAChF,IAAM,sBAAsB,aAAa,QAAQ,IAAI,qBAAqB,IAAI;AAC9E,IAAM,uBAAuB,QAAQ,SAAS,kBAAkB;AACvE,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AACxC,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AACvC,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtC,UAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAC3C,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,UAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAC1C,UAAU,mBAAmB,EAAE,WAAW,KAAK,CAAC;AAChD,UAAU,kBAAkB,EAAE,WAAW,KAAK,CAAC;AAC/C,UAAU,sBAAsB,EAAE,WAAW,KAAK,CAAC;AACnD,UAAU,eAAe,EAAE,WAAW,KAAK,CAAC;AAC5C,UAAU,qBAAqB,EAAE,WAAW,KAAK,CAAC;AAClD,UAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAC9C,UAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAC3C,UAAU,sBAAsB,EAAE,WAAW,KAAK,CAAC;AACnD,UAAU,kBAAkB,EAAE,WAAW,KAAK,CAAC;AAC/C,UAAU,uBAAuB,EAAE,WAAW,KAAK,CAAC;AAG7C,IAAM,wBAAwB,KAAK,KAAK;AAExC,IAAM,qBAAqB,QAAQ,cAAc,oBAAoB;AACrE,IAAM,gBAAgB,QAAQ,cAAc,eAAe;AA8B3D,IAAM,iBAA4B,gBACvC,kBACA,WACA,eACF;AACO,IAAM,gBAA2B,gBAAgB,iBAAiB,cAAc;AAChF,IAAM,gBAA2B,gBAAgB,iBAAiB,cAAc;AAEhF,IAAM,iBAAiB,QAAQ,gBAAgB,KAAK,QAAQ,eAAe;AAElF,SAAS,eAAe,CAAC,QAAgB,YAA2C;AAAA,EAClF,OAAO,QAAQ,MAAM,MAAM,eAAe,iBAAiB,iBAAiB;AAAA;AAGvE,IAAM,gBAAgB,gBAAgB,iBAAiB,aAAa;AACpE,IAAM,gBAAgB,gBAAgB,iBAAiB,aAAa;AAapE,IAAM,aAAa,QAAQ,YAAY;AACvC,IAAM,cAAc,QAAQ,aAAa;AACzC,IAAM,aAAa,QAAQ,YAAY,KAAK;AAC5C,IAAM,yBACX,QAAQ,wBAAwB,KAAK,QAAQ,cAAc,mCAAmC;AACzF,IAAM,gBAAgB,QAAQ,oBAAoB,KAAK;AACvD,IAAM,gBAAgB,QAAQ,eAAe,KAAK;AAClD,IAAM,gBAAgB,QAAQ,eAAe,KAAK;AAKzD,IAAM,mBAAmB,OAAO,SAAS,QAAQ,IAAI,kBAAkB,IAAI,EAAE;AACtE,IAAM,iBACX,OAAO,UAAU,gBAAgB,KAAK,mBAAmB,IAAI,mBAAmB;;;ADhWlF,IAAM,cAAc,SAAQ,cAAc,aAAa;AACvD,IAAM,eAAe,SAAQ,aAAa,UAAU;AAEpD,SAAS,UAAU,CAAC,UAAkB,MAAM,cAAsB;AAAA,EAChE,MAAM,MAAM,cAAa,SAAQ,KAAK,QAAQ,GAAG,OAAO;AAAA,EACxD,OAAO,IAAI,QAAQ,0BAA0B,aAAa;AAAA;AAG5D,SAAS,WAAW,CAAC,UAAkB,MAAsC;AAAA,EAC3E,IAAI,MAAM;AAAA,EACV,YAAY,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG;AAAA,IAC/C,MAAM,IAAI,QAAQ,IAAI,OAAO,SAAS,aAAa,GAAG,GAAG,MAAM,KAAK;AAAA,EACtE;AAAA,EACA,OAAO;AAAA;AAGT,IAAM,wCAAwC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAU9C,IAAM,0CAA0C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAchD,IAAM,0CAA0C;AAAA;AAAA;AAIhD,IAAI,6BAA4C;AAChD,IAAI,+BAA8C;AAClD,IAAI,+BAA8C;AAClD,IAAI,qBAAoC;AAExC,SAAS,iBAAiB,CAAC,UAAkB,UAA0B;AAAA,EACrE,IAAI;AAAA,IACF,OAAO,WAAW,QAAQ;AAAA,IAC1B,OAAO,KAAK;AAAA,IACZ,OAAO,MAAM,EAAE,KAAK,SAAS,GAAG,mDAAmD;AAAA,IACnF,OAAO;AAAA;AAAA;AAIX,SAAS,yBAAyB,GAAW;AAAA,EAC3C,IAAI,+BAA+B,MAAM;AAAA,IACvC,6BAA6B,kBAC3B,mBACA,qCACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,2BAA2B,GAAW;AAAA,EAC7C,IAAI,iCAAiC,MAAM;AAAA,IACzC,+BAA+B,kBAC7B,qBACA,uCACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,2BAA2B,GAAW;AAAA,EAC7C,IAAI,iCAAiC,MAAM;AAAA,IACzC,+BAA+B,kBAC7B,qBACA,uCACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAMT,SAAS,iBAAiB,GAAW;AAAA,EACnC,IAAI,uBAAuB,MAAM;AAAA,IAC/B,qBAAqB,kBAAkB,oBAAoB,EAAE;AAAA,EAC/D;AAAA,EACA,OAAO;AAAA;AAYF,SAAS,eAAe,CAAC,UAA4B;AAAA,EAC1D,MAAM,MAAM,cAAa,SAAQ,oBAAoB,QAAQ,GAAG,OAAO;AAAA,EACvE,MAAM,QAAQ,IAAI,MAAM,mCAAmC;AAAA,EAC3D,KAAK;AAAA,IAAO,MAAM,IAAI,MAAM,gBAAgB,iCAAiC;AAAA,EAK7E,MAAM,OAAgC,CAAC;AAAA,EACvC,IAAI,aAA4B;AAAA,EAChC,WAAW,QAAQ,MAAM,GAAG,MAAM;AAAA,CAAI,GAAG;AAAA,IACvC,IAAI,aAAa,KAAK,IAAI,GAAG;AAAA,MAC3B,aAAa,KAAK,KAAK,EAAE,QAAQ,MAAM,EAAE;AAAA,MACzC,KAAK,cAAc,CAAC;AAAA,IACtB,EAAO,SAAI,KAAK,WAAW,MAAM,KAAK,YAAY;AAAA,MAC/C,KAAK,YAAyB,KAAK,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,IAC1D,EAAO,SAAI,KAAK,KAAK,MAAM,MAAM,KAAK,SAAS,GAAG,MAAM,KAAK,WAAW,GAAG,GAAG;AAAA,MAC5E,aAAa;AAAA,MACb,MAAM,WAAW,KAAK,QAAQ,GAAG;AAAA,MACjC,MAAM,MAAM,KAAK,MAAM,GAAG,QAAQ,EAAE,KAAK;AAAA,MACzC,MAAM,QAAQ,KAAK,MAAM,WAAW,CAAC,EAAE,KAAK;AAAA,MAC5C,IAAI,OAAO;AAAA,QAAO,KAAK,OAAO;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,OAAO;AAAA,IACL,MAAM,OAAO,KAAK,QAAQ,SAAS,QAAQ,OAAO,EAAE,CAAC;AAAA,IACrD,MAAO,KAAK,QAA6B;AAAA,IACzC,OAAO,KAAK,QAAQ,OAAO,KAAK,KAAK,IAAI;AAAA,IACzC,OAAO,MAAM,QAAQ,KAAK,KAAK,IAAK,KAAK,QAAqB;AAAA,IAC9D,aAAa,KAAK,cAAc,OAAO,KAAK,WAAW,IAAI;AAAA,IAC3D,QAAQ,MAAM,GAAG,KAAK;AAAA,EACxB;AAAA;AAiBF,SAAS,uBAAuB,CAC9B,WACA,oBAAoB,OACpB,cAAc,OACd,oBAAoB,OACZ;AAAA,EACR,MAAM,mBAAmB;AAAA,EACzB,MAAM,gBAAgB;AAAA,EACtB,MAAM,iBACJ,cAAc,UACV,gHAAgH,oGAChH,0FAA0F;AAAA,EAChG,MAAM,kBACJ,cAAc,UACV,qFAAqF,2HACrF,4DAA4D;AAAA,EAClE,MAAM,gBACJ,cAAc,UACV,4GAA4G,sMAC5G,4EAA4E,qCAAqC;AAAA,EACvH,MAAM,eACJ,cAAc,UACV,mCAAmC,iCACnC,aAAa;AAAA,EACnB,MAAM,kBACJ,cAAc,UACV,0FAA0F,6GAC1F,4DAA4D;AAAA,EAClE,MAAM,uBACJ,cAAc,UACV,qGAAqG,+TACrG,2EAA2E,uLAAuL,0CAA0C,gDAAgD;AAAA,EAClW,MAAM,eACJ,cAAc,UACV,gIAAgI,+BAChI,qCAAqC,iCAAiC,iCAAiC,+BAA+B,kCAAkC;AAAA,EAC9K,MAAM,wBACJ,cAAc,UACV,6GAA6G,wHAC7G,kFAAkF;AAAA,EACxF,MAAM,uBAAuB,oBACzB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IACA,CAAC;AAAA,EACL,MAAM,uBACJ,cAAc,WACV,gNAAgN,oBAAoB,kEAAkE,OACtS,cAAc,YACZ,2PAA2P,oBAAoB,sIAAsI,+CACrZ;AAAA,EACR,MAAM,gBAAgB,cAClB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IACA,CAAC;AAAA,EACL,MAAM,sBAAsB,oBACxB;AAAA,IACE;AAAA,IACA;AAAA,IACA,iFAAiF;AAAA,IACjF;AAAA,EACF,IACA,CAAC;AAAA,EAEL,MAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,cAAc,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC;AAAA,IAC/C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,cAAc,YACd;AAAA,MACE;AAAA,IACF,IACA,CAAC;AAAA,IACL;AAAA,IACA,GAAG;AAAA,EACL;AAAA,EAEA,MAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA,+GAA+G,kCAAkC,qCAAqC;AAAA,IACtL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,IAAI,cAAc,UAAU;AAAA,IAC1B,OAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK;AAAA,CAAI;AAAA,EACb;AAAA,EAEA,OAAO,CAAC,GAAG,QAAQ,GAAG,WAAW,EAAE,KAAK;AAAA,CAAI;AAAA;AAGvC,SAAS,sBAAsB,CAAC,MAAuC;AAAA,EAC5E,MAAM,aAAa,GAAG,KAAK;AAAA,EAC3B,IAAI,SACF,YAAY,0BAA0B,GAAG;AAAA,IACvC,UAAU,KAAK;AAAA,IACf,aAAa,KAAK;AAAA,IAClB,eAAe,KAAK;AAAA,IACpB,aAAa;AAAA,EACf,CAAC,IACD,wBACE,KAAK,WACL,KAAK,mBACL,KAAK,aACL,KAAK,iBACP;AAAA,EACF,IAAI,KAAK,aAAa,KAAK,GAAG;AAAA,IAC5B,UAAU;AAAA;AAAA;AAAA,EAAuC,KAAK,YAAY,KAAK;AAAA,EACzE;AAAA,EACA,OAAO;AAAA;AAGF,SAAS,wBAAwB,CAAC,MAAuC;AAAA,EAC9E,MAAM,aAAa,GAAG,KAAK;AAAA,EAC3B,OACE,YAAY,4BAA4B,GAAG;AAAA,IACzC,UAAU,KAAK;AAAA,IACf,aAAa,KAAK;AAAA,IAClB,eAAe,KAAK;AAAA,IACpB,aAAa;AAAA,EACf,CAAC,IAAI,wBAAwB,KAAK,WAAW,OAAO,KAAK,aAAa,KAAK,iBAAiB;AAAA;AAIzF,SAAS,wBAAwB,CAAC,MAAuC;AAAA,EAC9E,OAAO,GAAG,uBAAuB,IAAI;AAAA;AAAA,EAAQ,4BAA4B;AAAA;AAGpE,SAAS,wBAAwB,CAAC,MAO9B;AAAA,EACT,MAAM,QAAkB,CAAC;AAAA;AAAA,UAAe;AAAA,EACxC,MAAM,YAAY,GAAG,KAAK,iBAAiB,KAAK;AAAA,EAChD,MAAM,KAAK,qBAAqB,KAAK,eAAe;AAAA,EACpD,MAAM,KAAK,UAAU,KAAK,WAAW,YAAY,UAAU;AAAA,EAC3D,IAAI,KAAK,mBAAmB;AAAA,IAC1B,MAAM,KAAK,mBAAmB,KAAK,mBAAmB;AAAA,EACxD;AAAA,EACA,MAAM,KACJ,IACA,KAAK,YACD,KAAK,WACH,qeACA,qLACF,KAAK,WACH,uUACA,KAAK,oBACH,+UACA,qMACV;AAAA,EACA,MAAM,KACJ,IACA,KAAK,YACD,uUACA,KAAK,YAAY,KAAK,oBACpB,sEACC,KAAK,oBAAoB,wDAA8B,oCACxD,kPACA,oOACR;AAAA,EACA,MAAM,KACJ,IACA,KAAK,WACD,gPACA,6VACN;AAAA,EACA,IAAI,KAAK,YAAY;AAAA,IACnB,MAAM,KACJ,IACA,uLACF;AAAA,EACF;AAAA,EACA,OAAO,MAAM,KAAK;AAAA,CAAI;AAAA;",
11
+ "debugId": "FF0F14433789211564756E2164756E21",
12
12
  "names": []
13
13
  }
package/dist/registry.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  logger,
12
12
  writeClaudeRollout,
13
13
  writeCodexRollout
14
- } from "./chunk-gz12qcf0.js";
14
+ } from "./chunk-a9y2rwxf.js";
15
15
 
16
16
  // ../../packages/core/src/agents/claude-registry.ts
17
17
  import { existsSync, mkdirSync, readdirSync, renameSync, unlinkSync } from "fs";
@@ -172,6 +172,7 @@ if (isBun) {
172
172
  // ../../packages/core/src/storage/storage-host.ts
173
173
  var configuredHost = {};
174
174
  var fallbackDatabase = null;
175
+ var fallbackDatabasePath = null;
175
176
  var schemaInitializers = [];
176
177
  var initializedSchemas = new WeakMap;
177
178
  var initializingDatabases = new WeakSet;
@@ -186,7 +187,7 @@ function defaultDataDir() {
186
187
  return envPath("NEGOTIUM_DATA_DIR", join2(defaultStateDir(), "data"));
187
188
  }
188
189
  function defaultSessionsDatabasePath() {
189
- return envPath("SESSIONS_DB_PATH", join2(defaultDataDir(), "sessions.db"));
190
+ return envPath("SESSIONS_DB_PATH", join2(resolveStorageDataDir(), "sessions.db"));
190
191
  }
191
192
  function initializeDatabase(database) {
192
193
  database.exec("PRAGMA journal_mode = WAL");
@@ -198,11 +199,14 @@ function initializeDatabase(database) {
198
199
  } catch {}
199
200
  }
200
201
  function defaultDatabase() {
201
- if (fallbackDatabase)
202
- return fallbackDatabase;
203
202
  const path = defaultSessionsDatabasePath();
203
+ if (fallbackDatabase && fallbackDatabasePath === path)
204
+ return fallbackDatabase;
205
+ if (fallbackDatabase)
206
+ fallbackDatabase.close();
204
207
  mkdirSync2(dirname(path), { recursive: true });
205
208
  fallbackDatabase = new Database(path, { create: true });
209
+ fallbackDatabasePath = path;
206
210
  initializeDatabase(fallbackDatabase);
207
211
  return fallbackDatabase;
208
212
  }
@@ -237,7 +241,7 @@ function ensureStorageSchemas(database = resolveStorageDatabase()) {
237
241
  initializingDatabases.delete(database);
238
242
  }
239
243
  }
240
- var storageDatabase = new Proxy({}, {
244
+ var internalStorageDatabase = new Proxy({}, {
241
245
  get(_target, property) {
242
246
  const database = resolveStorageDatabase();
243
247
  ensureStorageSchemas(database);
@@ -392,4 +396,4 @@ export {
392
396
  getRegistry2 as getRegistry
393
397
  };
394
398
 
395
- //# debugId=D058B595EE9B54BD64756E2164756E21
399
+ //# debugId=1F49C99AAD2BECDE64756E2164756E21
@@ -6,14 +6,14 @@
6
6
  "import { unlinkSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AgentRegistry } from \"#agents/contracts\";\nimport { writeCodexRollout } from \"#agents/rollout/codex\";\nimport { logger } from \"#platform/logger\";\nimport { readConversation } from \"#storage/conversations\";\nimport { CODEX_EFFORT_VALUES, type EffortLevel } from \"#types\";\n\nconst VALID_EFFORTS = new Set<EffortLevel>(CODEX_EFFORT_VALUES);\n\n// Codex CLI's own empirical default is gpt-5.6-sol (`codex exec` 2026-07-10 →\n// \"model: gpt-5.6-sol\"), but we deliberately default to gpt-5.6-luna — the\n// cheapest/fastest GPT-5.6 tier — for a general always-on assistant where most\n// queries are light. Heavier work escalates to terra/sol via set_model. This\n// value is passed explicitly to the SDK (see event-processor resolveDefaultModel),\n// so the footer and the actual model stay in sync.\nexport const codexRegistry: AgentRegistry = {\n kind: \"codex\",\n defaultModel: \"gpt-5.6-luna\",\n // defaultEffort intentionally omitted — Codex SDK treats absence as\n // \"reasoning off\". Setting \"high\"/etc. would silently flip on reasoning.\n\n expandModelAlias(s) {\n return s;\n },\n\n validateModel(s) {\n // Codex doesn't publish a closed model list and OpenAI ships new IDs\n // (gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, o3, ...) frequently. Best-effort: accept any\n // non-empty string. Bad IDs surface at SDK call time with a clear error.\n return typeof s === \"string\" && s.length > 0;\n },\n\n validEfforts: CODEX_EFFORT_VALUES,\n validateEffort(s) {\n // GPT-5.6 accepts low/medium/high/xhigh/max; 'minimal'\n // was removed because the Codex API rejects it when default tools\n // (image_gen, web_search) are active.\n return VALID_EFFORTS.has(s);\n },\n\n footerLabel(model, effort) {\n // Codex omits effort to mean \"reasoning off\". Show `(off)` explicitly so\n // the user can distinguish from claude (which always has a default).\n return `${model} · ${effort ?? \"(off)\"}`;\n },\n\n writeRollout(opts) {\n // Codex SDK exposes the resume key as `threadId`; AgentRegistry unifies\n // the name to `sessionId` so callers don't branch on agent.\n // `reuseSessionId` (if any) is forwarded as `threadId` so claude→codex→claude\n // round-trips also keep one continuous codex thread instead of orphaning a\n // fresh uuidv7 on every switch.\n const { threadId, rolloutPath } = writeCodexRollout({\n cwd: opts.cwd,\n entries: opts.entries,\n model: opts.model ?? codexRegistry.defaultModel,\n ...(opts.effort ? { effort: opts.effort } : {}),\n ...(opts.reuseSessionId ? { threadId: opts.reuseSessionId } : {}),\n });\n return { sessionId: threadId, rolloutPath };\n },\n\n // Codex SDK has no fork API. We synthesize a rollout from the\n // provider-agnostic conversation log (same path as `set_agent` cross-agent\n // bridging). Caveats: extractChatPairs folds tool_use/tool_result into\n // assistant text as `[Tool: ...]` annotations, so structural tool history\n // is lost.\n async forkSession({ cwd, userId, topicName, model, effort }) {\n const entries = readConversation(userId, topicName);\n const { threadId, rolloutPath } = writeCodexRollout({\n cwd,\n entries,\n model: model ?? codexRegistry.defaultModel,\n ...(effort ? { effort } : {}),\n });\n return { forkId: threadId, rolloutPath };\n },\n\n // Codex stores rollouts at `~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-<ts>-<threadId>.jsonl`.\n // The date prefix is unknown at cleanup time (it's the *original* write\n // timestamp, not \"now\"), so we glob across the whole sessions tree by\n // threadId suffix. With at most a few thousand files in active use this\n // is well under a millisecond on a warm filesystem.\n async cleanupRollouts({ sessionIds }) {\n if (sessionIds.length === 0) return;\n const sessionsDir = join(process.env.CODEX_HOME || join(homedir(), \".codex\"), \"sessions\");\n const failures: unknown[] = [];\n // One Glob per threadId so a single corrupt entry can't poison the rest.\n // Bun.Glob's `scan` yields paths relative to its base dir.\n for (const tid of sessionIds) {\n try {\n const glob = new Bun.Glob(`**/rollout-*-${tid}.jsonl`);\n for await (const rel of glob.scan({ cwd: sessionsDir, onlyFiles: true })) {\n const path = join(sessionsDir, rel);\n try {\n unlinkSync(path);\n } catch (e) {\n if ((e as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n logger.warn({ err: e, path }, \"codex cleanupRollouts: unlink failed\");\n failures.push(e);\n }\n }\n }\n } catch (e) {\n logger.warn({ err: e, threadId: tid }, \"codex cleanupRollouts: scan failed\");\n failures.push(e);\n }\n }\n if (failures.length > 0) {\n throw new AggregateError(failures, \"codex cleanupRollouts failed\");\n }\n },\n};\n",
7
7
  "import {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { appendJsonlLine } from \"#platform/jsonl\";\nimport { logger } from \"#platform/logger\";\nimport { sanitizeTopicName } from \"#security/sanitize\";\nimport { resolveStorageDataDir } from \"#storage/storage-host\";\nimport type { AgentKind, UnifiedEvent } from \"#types\";\n\n/**\n * Per-topic conversation log (UnifiedEvent stream) used as the\n * **provider-agnostic source of truth** for cross-agent portability.\n *\n * Storage layout:\n * {DATA_DIR}/conversations/{userId}/{sanitizedTopicName}.jsonl\n *\n * Each line is a `ConversationEntry` JSON object. Append-only: every yielded\n * UnifiedEvent during a `runAgent()` turn is captured here by the recording\n * wrapper, so on agent switch we can rebuild a synthetic native rollout for\n * the target SDK and preserve the conversation across providers.\n *\n * The Claude/Codex SDK rollouts (~/.claude/projects/, ~/.codex/sessions/) are\n * intentionally treated as opaque side-effects of the SDKs only this file\n * is canonical.\n */\nexport interface ConversationEntry {\n ts: string;\n /**\n * Agent that produced this event, frozen at write time. A topic that has\n * been switched (via `set_agent`) will have a mixed-agent log: earlier\n * entries keep the agent that originally generated them. Replay code\n * (rollout-codec `extractChatPairs`) intentionally ignores this field —\n * the cross-agent rollout's whole point is to feed past dialogue, no\n * matter who produced it, into the *new* SDK as if it were native.\n */\n agent: AgentKind;\n event: UnifiedEvent;\n}\n\n/**\n * Validate that a userId stringifies to a safe path component. Rejects empties,\n * slashes, and traversal sequences before they touch the filesystem. The\n * conversation log is local-only so we keep this strict but simple if a\n * caller sends something unexpected it is their bug to fix, not ours to coerce.\n */\nfunction safeUserIdComponent(userId: number | string): string {\n const str = String(userId);\n if (!str || /[/\\\\]|\\.\\./.test(str)) {\n throw new Error(`conversations: refusing unsafe userId path component: ${str}`);\n }\n return str;\n}\n\nfunction conversationDir(userId: number | string): string {\n return join(resolveStorageDataDir(), \"conversations\", safeUserIdComponent(userId));\n}\n\nfunction topicFilename(topicName: string): string {\n const t = sanitizeTopicName(topicName, true);\n return `${t}.jsonl`;\n}\n\n/** Compute the absolute path for a given user/topic conversation log. */\nexport function getConversationPath(userId: number | string, topicName: string): string {\n return join(conversationDir(userId), topicFilename(topicName));\n}\n\n/**\n * Append a single UnifiedEvent for the given topic. Creates the parent\n * directory and the file as needed. Best-effort: I/O failures are logged but\n * never throw, since recording must not break the live stream to Telegram.\n *\n * **Concurrency note (review item M2, revised):** within the bot process the\n * single-threaded event loop already serializes writes — but this module is\n * NOT single-process: the self-config MCP server (a separate stdio process,\n * via `topic-agent-switch`) and provider bridge helpers append to the same\n * topic logs.\n * Cross-process interleaving on macOS is real for lines beyond PIPE_BUF\n * (512B), and a torn line is silently dropped by `readConversation` —\n * corrupting the canonical source for cross-agent rollout reconstruction.\n * Writes therefore go through `appendJsonlLine` (sidecar `.lock` via O_EXCL,\n * stale-lock reclaim, unlocked-append fallback on timeout — interleave is\n * accepted over dropping the entry).\n *\n * The append stays SYNCHRONOUS on purpose: a previous attempt at a\n * Promise-chained per-topic queue made writes async (durability gap before a\n * synchronous `readConversation`) and broke `set_agent` in the bridge tests.\n */\nexport function appendConversationEvent(\n userId: number | string,\n topicName: string,\n agent: AgentKind,\n event: UnifiedEvent,\n): void {\n try {\n appendConversationEventStrict(userId, topicName, agent, event);\n } catch (err) {\n logger.warn(\n { err, userId, topicName, eventType: event.type },\n \"appendConversationEvent: write failed\",\n );\n }\n}\n\n/**\n * Strict variant for state transitions where the conversation log is a manifest\n * rather than telemetry. Throws on I/O failure so callers can avoid committing\n * DB state that points at an unmanifested SDK session.\n */\nexport function appendConversationEventStrict(\n userId: number | string,\n topicName: string,\n agent: AgentKind,\n event: UnifiedEvent,\n): void {\n const path = getConversationPath(userId, topicName);\n const entry: ConversationEntry = {\n ts: new Date().toISOString(),\n agent,\n event,\n };\n mkdirSync(dirname(path), { recursive: true });\n appendJsonlLine(path, JSON.stringify(entry));\n}\n\n/**\n * Read all entries for a topic in chronological order. Returns an empty array\n * if the file does not exist. Malformed lines are skipped with a warning so a\n * single corrupted entry does not poison the whole conversation.\n *\n * NOTE(perf): reads the whole file each call. Topics in the kilobyte range\n * are fine; if a single topic ever grows into multi-megabyte territory,\n * consider a streaming reader (`readline`/`Bun.file().stream()`) and a\n * size-bounded tail.\n */\nexport function readConversation(userId: number | string, topicName: string): ConversationEntry[] {\n const path = getConversationPath(userId, topicName);\n const out: ConversationEntry[] = [];\n if (!existsSync(path)) return out;\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (err) {\n logger.warn({ err, path }, \"readConversation: read failed\");\n return out;\n }\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n out.push(JSON.parse(line) as ConversationEntry);\n } catch (err) {\n logger.warn(\n { err, line: line.slice(0, 200) },\n \"readConversation: malformed JSONL line skipped\",\n );\n }\n }\n return out;\n}\n\n/** Atomically replace a provider-neutral topic log with an explicit event set. */\nexport function replaceConversationStrict(\n userId: number | string,\n topicName: string,\n entries: ConversationEntry[],\n): void {\n const path = getConversationPath(userId, topicName);\n const tempPath = `${path}.${process.pid}.${Date.now()}.tmp`;\n mkdirSync(dirname(path), { recursive: true });\n try {\n writeFileSync(\n tempPath,\n entries.length > 0 ? `${entries.map((entry) => JSON.stringify(entry)).join(\"\\n\")}\\n` : \"\",\n { flag: \"wx\" },\n );\n renameSync(tempPath, path);\n } catch (error) {\n try {\n unlinkSync(tempPath);\n } catch {}\n throw error;\n }\n}\n\n/**\n * Copy the unified conversation log of `srcTopic` into the file path that\n * `dstTopic` will read from. Used by `/fork` so a forked child topic inherits\n * the parent's full cross-agent history, not just the agent's native SDK\n * rollout. `/spawn` intentionally does not call this; it starts with no\n * conversation history. Without this copy, a fork followed immediately by\n * `/agent <other>` would feed the empty child log to `switchTopicAgent` and\n * the new agent would start from zero — see the bug report from 2026-05-24.\n *\n * Semantics:\n * - Reads the parent via `readConversation`, matching the history an in-place\n * `set_agent` on the parent would have seen.\n * - Writes a single file at the child's canonical path.\n * - Refuses to overwrite a non-empty destination (returns `{copied:false}`).\n * `/fork`'s only caller runs this immediately after topic creation when\n * the dst file is guaranteed empty, so a non-empty dst means a programmer\n * error somewhere upstream — fail loud rather than silently merging.\n * - On any I/O error: throws. The caller (`createChildTopic`) already has\n * a rollback path that wraps this call.\n */\nexport function cloneConversationLog(opts: {\n userId: number | string;\n srcTopic: string;\n dstTopic: string;\n}): { copied: boolean; entries: number } {\n const { userId, srcTopic, dstTopic } = opts;\n const dstPath = getConversationPath(userId, dstTopic);\n if (existsSync(dstPath) && readFileSync(dstPath, \"utf8\").trim().length > 0) {\n logger.warn(\n { userId, srcTopic, dstTopic, dstPath },\n \"cloneConversationLog: dst already non-empty — refusing to overwrite\",\n );\n return { copied: false, entries: 0 };\n }\n const entries = readConversation(userId, srcTopic);\n if (entries.length === 0) {\n return { copied: false, entries: 0 };\n }\n const body = `${entries.map((e) => JSON.stringify(e)).join(\"\\n\")}\\n`;\n mkdirSync(dirname(dstPath), { recursive: true });\n writeFileSync(dstPath, body);\n return { copied: true, entries: entries.length };\n}\n\n/**\n * Walk the unified log backwards and return the most recent SDK-emitted\n * session id for the given agent — or null if that agent has never run on\n * this topic.\n *\n * Used by `set_agent` to round-trip the SAME native rollout file across\n * agent switches: when the user does claude → codex → claude, we reuse\n * the original claude sessionId so the synthetic rollout lands at the\n * same path the SDK already manages, preserving prompt-cache continuity\n * and avoiding orphan `~/.claude/projects/<dir>/<id>.jsonl` files.\n *\n * Behavior:\n * - First-ever switch to an agent (no prior session events) → null,\n * caller falls back to a fresh randomUUID/uuidv7. Same as before.\n * - Roundtrip switch (prior session exists) → that sessionId.\n *\n * `session` events are emitted on every turn by claude-/codex-provider and\n * captured into the unified log by runAgent's append wrapper. The most\n * recent one for the target agent is by definition the current SDK-side\n * resume key for that agent.\n */\nexport function findLastSessionIdForAgent(\n entries: ConversationEntry[],\n agent: AgentKind,\n): string | null {\n for (let i = entries.length - 1; i >= 0; i--) {\n const entry = entries[i];\n if (entry.agent !== agent) continue;\n if (entry.event.type === \"session\") {\n return entry.event.sessionId;\n }\n }\n return null;\n}\n",
8
8
  "/** Sanitize a topic/session name for use in file paths.\n * Replaces non-alphanumeric characters (excluding Korean) with underscores.\n * Empty input (or input consisting only of disallowed chars) returns \"_\" so\n * callers always get a non-empty single path component.\n * @param name The raw topic or session name.\n * @param lowercase Whether to lowercase the result (default: false).\n * Use true for wiki paths; leave false for log file paths.\n */\nexport function sanitizeTopicName(name: string, lowercase = false): string {\n const safe = name.replace(/[^a-zA-Z0-9가-힣_-]/g, \"_\") || \"_\";\n return lowercase ? safe.toLowerCase() : safe;\n}\n\n/** Sanitize a file name for use in file paths. Allows dots.\n * Pure-dot results (\".\", \"..\") are replaced with \"_\" to block path-traversal\n * when the sanitized value is used as a standalone path component.\n */\nexport function sanitizeFileName(name: string): string {\n const safe = name.replace(/[^a-zA-Z0-9._-]/g, \"_\") || \"_\";\n if (safe === \".\" || safe === \"..\") return \"_\";\n return safe;\n}\n\n/** Sanitize an arbitrary ID (no Korean, no dots) for use in file paths. */\nexport function sanitizeId(id: string): string {\n return id.replace(/[^a-zA-Z0-9_-]/g, \"_\") || \"_\";\n}\n",
9
- "import { mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { Database } from \"#storage/sqlite\";\n\nexport type StorageDatabase = InstanceType<typeof Database>;\n\nexport interface StorageHostOptions {\n /** Borrowed SQLite connection. Negotium never closes an injected database. */\n database?: StorageDatabase;\n /** Persistent JSON/JSONL state root. */\n dataDir?: string;\n /** Activity and token-usage log root. */\n logDir?: string;\n /** Durable ask edge root. Defaults to Negotium's runtime ask directory. */\n sessionAsksDir?: string;\n /** Shared topic workspace root used by wiki/archive helpers. */\n workspaceDir?: string;\n}\n\nlet configuredHost: Readonly<StorageHostOptions> = {};\nlet fallbackDatabase: StorageDatabase | null = null;\n\ntype StorageSchemaInitializer = (database: StorageDatabase) => void;\ninterface RegisteredSchemaInitializer {\n initialize: StorageSchemaInitializer;\n priority: number;\n}\n\nconst schemaInitializers: RegisteredSchemaInitializer[] = [];\nconst initializedSchemas = new WeakMap<StorageDatabase, Set<StorageSchemaInitializer>>();\nconst initializingDatabases = new WeakSet<StorageDatabase>();\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(), \"run\"));\n return join(runDir, \"session-asks\");\n}\n\nfunction defaultSessionsDatabasePath(): string {\n return envPath(\"SESSIONS_DB_PATH\", join(defaultDataDir(), \"sessions.db\"));\n}\n\nfunction initializeDatabase(database: StorageDatabase): void {\n database.exec(\"PRAGMA journal_mode = WAL\");\n database.exec(\"PRAGMA foreign_keys = ON\");\n database.exec(\"PRAGMA busy_timeout = 5000\");\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(): StorageDatabase {\n if (fallbackDatabase) return fallbackDatabase;\n const path = defaultSessionsDatabasePath();\n mkdirSync(dirname(path), { recursive: true });\n fallbackDatabase = new Database(path, { create: true });\n initializeDatabase(fallbackDatabase);\n return fallbackDatabase;\n}\n\nexport function resolveStorageDatabase(): StorageDatabase {\n return configuredHost.database ?? defaultDatabase();\n}\n\nexport function resolveStorageDataDir(): string {\n return configuredHost.dataDir ?? defaultDataDir();\n}\n\nexport function resolveStorageLogDir(): string {\n return configuredHost.logDir ?? defaultLogDir();\n}\n\nexport function resolveStorageSessionAsksDir(): string {\n return configuredHost.sessionAsksDir ?? defaultSessionAsksDir();\n}\n\nexport function resolveStorageWorkspaceDir(): string {\n return configuredHost.workspaceDir ?? defaultWorkspaceDir();\n}\n\nexport function resolveStorageSharedWikiDir(): string {\n return join(resolveStorageWorkspaceDir(), \"wiki\");\n}\n\nexport function resolveStorageUsersLogDir(): string {\n return join(resolveStorageDataDir(), \"users\");\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: StorageHostOptions): () => void {\n const previous = configuredHost;\n configuredHost = Object.freeze({ ...previous, ...options });\n let restored = false;\n return () => {\n if (restored) return;\n restored = true;\n configuredHost = previous;\n };\n}\n\n/** Close only Negotium's fallback connection. Injected connections are borrowed. */\nexport function closeStorageDatabase(): void {\n if (configuredHost.database || !fallbackDatabase) return;\n fallbackDatabase.close();\n fallbackDatabase = null;\n}\n\nexport function registerStorageSchemaInitializer(\n initialize: StorageSchemaInitializer,\n priority = 100,\n): void {\n schemaInitializers.push({ initialize, priority });\n schemaInitializers.sort((a, b) => a.priority - b.priority);\n}\n\nexport function ensureStorageSchemas(database = resolveStorageDatabase()): void {\n if (initializingDatabases.has(database)) return;\n let initialized = initializedSchemas.get(database);\n if (!initialized) {\n initialized = new Set();\n initializedSchemas.set(database, initialized);\n }\n initializingDatabases.add(database);\n try {\n for (const entry of 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 initializingDatabases.delete(database);\n }\n}\n\n/** Stable proxy identity used by legacy imports and embedding hosts. */\nexport const storageDatabase = new Proxy({} as StorageDatabase, {\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",
9
+ "import { mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { 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\nlet configuredHost: Readonly<StorageHostConfig> = {};\ntype InternalStorageDatabase = InstanceType<typeof Database>;\ntype OwnedStorageDatabase = InternalStorageDatabase & { close(): void };\nlet fallbackDatabase: OwnedStorageDatabase | null = null;\nlet fallbackDatabasePath: string | null = null;\n\ninterface StorageHostFrame {\n active: boolean;\n patch: Readonly<StorageHostConfig>;\n}\n\nconst storageHostFrames: StorageHostFrame[] = [];\n\ntype StorageSchemaInitializer = (database: InternalStorageDatabase) => void;\ninterface RegisteredSchemaInitializer {\n initialize: StorageSchemaInitializer;\n priority: number;\n}\n\nconst schemaInitializers: RegisteredSchemaInitializer[] = [];\nconst initializedSchemas = new WeakMap<InternalStorageDatabase, Set<StorageSchemaInitializer>>();\nconst initializingDatabases = new WeakSet<InternalStorageDatabase>();\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(), \"run\"));\n return join(runDir, \"session-asks\");\n}\n\nfunction defaultSessionsDatabasePath(): string {\n return envPath(\"SESSIONS_DB_PATH\", join(resolveStorageDataDir(), \"sessions.db\"));\n}\n\nfunction initializeDatabase(database: InternalStorageDatabase): void {\n database.exec(\"PRAGMA journal_mode = WAL\");\n database.exec(\"PRAGMA foreign_keys = ON\");\n database.exec(\"PRAGMA busy_timeout = 5000\");\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 if (fallbackDatabase && fallbackDatabasePath === path) return fallbackDatabase;\n if (fallbackDatabase) fallbackDatabase.close();\n mkdirSync(dirname(path), { recursive: true });\n fallbackDatabase = new Database(path, { create: true }) as unknown as OwnedStorageDatabase;\n fallbackDatabasePath = path;\n initializeDatabase(fallbackDatabase);\n return fallbackDatabase;\n}\n\nexport function resolveStorageDatabase(): InternalStorageDatabase {\n return (configuredHost.database ?? defaultDatabase()) as InternalStorageDatabase;\n}\n\nexport function resolveStorageDataDir(): string {\n return configuredHost.dataDir ?? defaultDataDir();\n}\n\nexport function resolveStorageLogDir(): string {\n return configuredHost.logDir ?? defaultLogDir();\n}\n\nexport function resolveStorageSessionAsksDir(): string {\n return configuredHost.sessionAsksDir ?? defaultSessionAsksDir();\n}\n\nexport function resolveStorageWorkspaceDir(): string {\n return configuredHost.workspaceDir ?? defaultWorkspaceDir();\n}\n\nexport function resolveStorageSharedWikiDir(): string {\n return configuredHost.sharedWikiDir ?? join(resolveStorageWorkspaceDir(), \"wiki\");\n}\n\nexport function resolveStorageUsersLogDir(): string {\n return 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) patch.database = options.database;\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 configuredHost = Object.freeze(\n Object.assign(\n {},\n ...storageHostFrames.filter((frame) => frame.active).map((frame) => frame.patch),\n ),\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 storageHostFrames.push(frame);\n refreshConfiguredHost();\n return () => {\n if (!frame.active) return;\n frame.active = false;\n const index = storageHostFrames.indexOf(frame);\n if (index >= 0) storageHostFrames.splice(index, 1);\n refreshConfiguredHost();\n };\n}\n\n/** Remove every configured host layer and restore standalone fallbacks. */\nexport function resetStorageHost(): void {\n for (const frame of storageHostFrames) frame.active = false;\n storageHostFrames.length = 0;\n refreshConfiguredHost();\n}\n\n/** Close only Negotium's fallback connection. Injected connections are borrowed. */\nexport function closeStorageDatabase(): void {\n if (!fallbackDatabase) return;\n fallbackDatabase.close();\n fallbackDatabase = null;\n fallbackDatabasePath = null;\n}\n\nexport function registerStorageSchemaInitializer(\n initialize: StorageSchemaInitializer,\n priority = 100,\n): void {\n schemaInitializers.push({ initialize, priority });\n schemaInitializers.sort((a, b) => a.priority - b.priority);\n}\n\nexport function ensureStorageSchemas(\n database: InternalStorageDatabase = resolveStorageDatabase(),\n): void {\n if (initializingDatabases.has(database)) return;\n let initialized = initializedSchemas.get(database);\n if (!initialized) {\n initialized = new Set();\n initializedSchemas.set(database, initialized);\n }\n initializingDatabases.add(database);\n try {\n for (const entry of 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 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",
10
10
  "// 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",
11
11
  "// The SDK's login-PATH bootstrap is expected host setup, not actionable\n// runtime output. Keep it enabled while suppressing its module-load chatter.\nprocess.env.MAESTRO_SDK_SILENT_BOOTSTRAP ??= \"1\";\n",
12
12
  "/**\n * Maestro agent registry — local re-export of `maestro-agent-sdk` with\n * a project-specific default-model override.\n *\n * Mirrors the pattern of claude-registry.ts / codex-registry.ts so that\n * agents/registry.ts can resolve all three AgentRegistry instances from\n * sibling `@/agents/*` paths, keeping the import topology consistent.\n *\n * maestro-agent-sdk v0.1.39 is DeepSeek-only — the Anthropic and Codex\n * providers were removed. The SDK's own default is `deepseek-pro`, which\n * matches this override. The override is kept explicit so the intent is\n * clear if the upstream default ever changes; users can still switch to\n * `deepseek-flash` per-topic via `/model deepseek-flash`.\n */\nimport \"#platform/maestro-bootstrap-env\";\nimport {\n setConversationReader,\n maestroRegistry as upstreamMaestroRegistry,\n} from \"maestro-agent-sdk\";\nimport type { AgentRegistry } from \"#agents/contracts\";\nimport { readConversation } from \"#storage/conversations\";\n\n// The SDK intentionally defaults its conversation reader to `() => []` so it\n// can stay storage-agnostic. Wire Negotium's unified log into it once at module\n// load; otherwise Maestro forkSession() creates a valid but empty rollout.\nsetConversationReader(readConversation as Parameters<typeof setConversationReader>[0]);\n\nexport const maestroRegistry: AgentRegistry = {\n ...(upstreamMaestroRegistry as AgentRegistry),\n defaultModel: \"deepseek-pro\",\n};\n",
13
13
  "import { claudeRegistry } from \"#agents/claude-registry\";\nimport { codexRegistry } from \"#agents/codex-registry\";\nimport type { AgentRegistry } from \"#agents/contracts\";\nimport { maestroRegistry } from \"#agents/maestro-registry\";\nimport type { AgentKind } from \"#types\";\n\nexport type {\n AgentRegistry,\n CleanupRolloutsOptions,\n ForkRegistryOptions,\n ForkRegistryResult,\n WriteRolloutOptions,\n WriteRolloutResult,\n} from \"#agents/contracts\";\n\nconst REGISTRIES: Record<AgentKind, AgentRegistry> = {\n claude: claudeRegistry,\n codex: codexRegistry,\n maestro: maestroRegistry,\n};\n\nexport function getRegistry(agent: AgentKind): AgentRegistry {\n return REGISTRIES[agent];\n}\n",
14
14
  "import {\n type AgentRegistry,\n type CleanupRolloutsOptions,\n type ForkRegistryOptions,\n type ForkRegistryResult,\n getRegistry as resolveCoreRegistry,\n type WriteRolloutOptions,\n type WriteRolloutResult,\n} from \"@negotium/core/registry\";\n\nexport type {\n AgentRegistry,\n CleanupRolloutsOptions,\n ForkRegistryOptions,\n ForkRegistryResult,\n WriteRolloutOptions,\n WriteRolloutResult,\n};\n\nexport const getRegistry: typeof resolveCoreRegistry = (agent) => resolveCoreRegistry(agent);\n"
15
15
  ],
16
- "mappings": "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",
17
- "debugId": "D058B595EE9B54BD64756E2164756E21",
16
+ "mappings": "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",
17
+ "debugId": "1F49C99AAD2BECDE64756E2164756E21",
18
18
  "names": []
19
19
  }