negotium 0.3.13 → 0.4.0

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 (39) hide show
  1. package/README.md +2 -6
  2. package/dist/agent-helpers.js +328 -185
  3. package/dist/agent-helpers.js.map +9 -8
  4. package/dist/{chunk-0ynjwr50.js → chunk-zq2tcq4k.js} +12 -29
  5. package/dist/{chunk-0ynjwr50.js.map → chunk-zq2tcq4k.js.map} +4 -4
  6. package/dist/hosted-agent.js +207 -64
  7. package/dist/hosted-agent.js.map +8 -7
  8. package/dist/main.js +753 -886
  9. package/dist/main.js.map +13 -13
  10. package/dist/mcp-factories.js +300 -468
  11. package/dist/mcp-factories.js.map +9 -10
  12. package/dist/registry.js +3 -3
  13. package/dist/registry.js.map +2 -2
  14. package/dist/rollout.js +1 -1
  15. package/dist/runtime/src/agents/codex-provider.ts +33 -8
  16. package/dist/runtime/src/agents/codex-vault-hook-bridge.ts +192 -0
  17. package/dist/runtime/src/agents/codex-vault-hook.mjs +48 -0
  18. package/dist/runtime/src/agents/execution-host.ts +1 -14
  19. package/dist/runtime/src/agents/public-helpers.ts +0 -9
  20. package/dist/runtime/src/agents/vault-tool-policy.ts +9 -51
  21. package/dist/runtime/src/mcp/factories/index.ts +1 -8
  22. package/dist/runtime/src/mcp/factories/vault.ts +6 -104
  23. package/dist/runtime/src/mcp/vault-server.ts +4 -20
  24. package/dist/runtime/src/prompts/sessions/_shared-tools.md +1 -1
  25. package/dist/runtime/src/version.ts +1 -1
  26. package/dist/types/packages/core/src/agents/codex-vault-hook-bridge.d.ts +27 -0
  27. package/dist/types/packages/core/src/agents/execution-host.d.ts +0 -2
  28. package/dist/types/packages/core/src/agents/public-helpers.d.ts +0 -1
  29. package/dist/types/packages/core/src/agents/vault-tool-policy.d.ts +1 -14
  30. package/dist/types/packages/core/src/mcp/factories/index.d.ts +1 -3
  31. package/dist/types/packages/core/src/mcp/factories/vault.d.ts +4 -13
  32. package/dist/types/packages/core/src/version.d.ts +1 -1
  33. package/package.json +1 -1
  34. package/dist/runtime/src/mcp/factories/vault-host.ts +0 -8
  35. package/dist/runtime/src/mcp/vault-http.ts +0 -235
  36. package/dist/runtime/src/mcp/vault-run.ts +0 -154
  37. package/dist/types/packages/core/src/mcp/factories/vault-host.d.ts +0 -7
  38. package/dist/types/packages/core/src/mcp/vault-http.d.ts +0 -23
  39. package/dist/types/packages/core/src/mcp/vault-run.d.ts +0 -19
@@ -69,30 +69,21 @@ function shouldSubstituteVaultToolInput(toolName) {
69
69
  const leaf = leafToolName(toolName);
70
70
  return leaf.startsWith("browser_") || DIRECT_VAULT_EXECUTION_TOOLS.has(leaf);
71
71
  }
72
- function createVaultToolPolicy(host) {
73
- function isVaultBrokerTool(toolName) {
74
- return toolName.includes("vault_run") || toolName.includes("vault_http_request");
75
- }
76
- function referencesRuntimeSecretStorage(value) {
77
- if (typeof value === "string") {
78
- const lower = value.toLowerCase();
79
- if (SENSITIVE_RUNTIME_NAMES.some((name) => lower.includes(name)))
80
- return true;
81
- return value.startsWith("/") && host.isSensitivePath(value);
82
- }
83
- if (Array.isArray(value))
84
- return value.some(referencesRuntimeSecretStorage);
85
- if (value && typeof value === "object") {
86
- return Object.values(value).some(referencesRuntimeSecretStorage);
87
- }
88
- return false;
72
+ function referencesRuntimeSecretStorage(value) {
73
+ if (typeof value === "string") {
74
+ const lower = value.toLowerCase();
75
+ if (SENSITIVE_RUNTIME_NAMES.some((name) => lower.includes(name)))
76
+ return true;
77
+ return value.startsWith("/") && isSensitivePath(value);
89
78
  }
90
- function shouldRedirectVaultTool(userId, toolName, input) {
91
- return false;
79
+ if (Array.isArray(value))
80
+ return value.some(referencesRuntimeSecretStorage);
81
+ if (value && typeof value === "object") {
82
+ return Object.values(value).some(referencesRuntimeSecretStorage);
92
83
  }
93
- return { isVaultBrokerTool, referencesRuntimeSecretStorage, shouldRedirectVaultTool };
84
+ return false;
94
85
  }
95
- var SENSITIVE_RUNTIME_NAMES, DIRECT_VAULT_EXECUTION_TOOLS, VAULT_BROKER_REDIRECT_ERROR = "Vault broker redirection is disabled; use {{KEY}} directly in normal tool inputs.", defaultVaultToolPolicy, isVaultBrokerTool, referencesRuntimeSecretStorage, shouldRedirectVaultTool;
86
+ var SENSITIVE_RUNTIME_NAMES, DIRECT_VAULT_EXECUTION_TOOLS;
96
87
  var init_vault_tool_policy = __esm(() => {
97
88
  init_sensitive_path();
98
89
  SENSITIVE_RUNTIME_NAMES = [
@@ -102,13 +93,6 @@ var init_vault_tool_policy = __esm(() => {
102
93
  "sessions.db"
103
94
  ];
104
95
  DIRECT_VAULT_EXECUTION_TOOLS = new Set(["Bash", "WebFetch"]);
105
- defaultVaultToolPolicy = createVaultToolPolicy({
106
- isSensitivePath,
107
- valueReferencesVaultKey: () => false
108
- });
109
- isVaultBrokerTool = defaultVaultToolPolicy.isVaultBrokerTool;
110
- referencesRuntimeSecretStorage = defaultVaultToolPolicy.referencesRuntimeSecretStorage;
111
- shouldRedirectVaultTool = defaultVaultToolPolicy.shouldRedirectVaultTool;
112
96
  });
113
97
 
114
98
  // ../../packages/core/src/platform/config-helpers.ts
@@ -1870,7 +1854,6 @@ var init_execution_host = __esm(async () => {
1870
1854
  redactVaultSecrets,
1871
1855
  substituteVaultSecrets: (userId, value) => vaultSubstituteDetailed(userId, value).text,
1872
1856
  referencesRuntimeSecretStorage,
1873
- shouldRedirectVaultTool,
1874
1857
  claudeCodeExecutablePath: () => CLAUDE_EXECUTABLE,
1875
1858
  codexAuthFilePath
1876
1859
  };
@@ -2429,7 +2412,7 @@ var init_claude_registry = __esm(() => {
2429
2412
  });
2430
2413
 
2431
2414
  // ../../packages/core/src/version.ts
2432
- var NEGOTIUM_VERSION = "0.3.13";
2415
+ var NEGOTIUM_VERSION = "0.4.0";
2433
2416
 
2434
2417
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
2435
2418
  import { spawn as spawn2 } from "child_process";
@@ -4594,9 +4577,163 @@ var init_codex_tree_kill = __esm(() => {
4594
4577
  killOwnedCodexTreesForShutdown = manager.killOwnedTreesForShutdown;
4595
4578
  });
4596
4579
 
4580
+ // ../../packages/core/src/agents/codex-vault-hook-bridge.ts
4581
+ import { randomBytes as randomBytes5 } from "crypto";
4582
+ import { existsSync as existsSync11 } from "fs";
4583
+ import { chmod, mkdtemp, rm, writeFile } from "fs/promises";
4584
+ import { createServer } from "net";
4585
+ import { tmpdir as tmpdir2 } from "os";
4586
+ import { dirname as dirname9, join as join12, resolve as resolve7 } from "path";
4587
+ import { fileURLToPath as fileURLToPath2 } from "url";
4588
+ function evaluateCodexVaultPreToolUse(input, userId, operations) {
4589
+ if (operations.referencesSensitiveStorage(input.tool_input)) {
4590
+ return {
4591
+ hookSpecificOutput: {
4592
+ hookEventName: "PreToolUse",
4593
+ permissionDecision: "deny",
4594
+ permissionDecisionReason: SENSITIVE_STORAGE_DENIAL
4595
+ }
4596
+ };
4597
+ }
4598
+ if (!shouldSubstituteVaultToolInput(input.tool_name))
4599
+ return {};
4600
+ const updatedInput = deepMapStrings(input.tool_input, (value) => operations.substitute(userId, value));
4601
+ if (JSON.stringify(updatedInput) === JSON.stringify(input.tool_input))
4602
+ return {};
4603
+ return {
4604
+ hookSpecificOutput: {
4605
+ hookEventName: "PreToolUse",
4606
+ permissionDecision: "allow",
4607
+ updatedInput
4608
+ }
4609
+ };
4610
+ }
4611
+ function shellQuote(value) {
4612
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
4613
+ }
4614
+ function hookClientPath() {
4615
+ const moduleDir = dirname9(fileURLToPath2(import.meta.url));
4616
+ const adjacent = resolve7(moduleDir, "codex-vault-hook.mjs");
4617
+ if (existsSync11(adjacent))
4618
+ return adjacent;
4619
+ const packaged = resolve7(moduleDir, "runtime/src/agents/codex-vault-hook.mjs");
4620
+ if (existsSync11(packaged))
4621
+ return packaged;
4622
+ throw new Error("Codex Vault hook client is missing from this installation");
4623
+ }
4624
+ function privateCodexWrapper(codexScript) {
4625
+ return [
4626
+ "#!/bin/sh",
4627
+ 'if [ "$1" = "exec" ]; then',
4628
+ " shift",
4629
+ ` exec ${shellQuote(process.execPath)} ${shellQuote(codexScript)} exec --dangerously-bypass-hook-trust "$@"`,
4630
+ "fi",
4631
+ `exec ${shellQuote(process.execPath)} ${shellQuote(codexScript)} "$@"`,
4632
+ ""
4633
+ ].join(`
4634
+ `);
4635
+ }
4636
+ async function createCodexVaultHookBridge(userId) {
4637
+ const root = await mkdtemp(join12(tmpdir2(), "negotium-codex-vault-"));
4638
+ await chmod(root, 448);
4639
+ const socketPath = join12(root, "hook.sock");
4640
+ const wrapperPath = join12(root, "codex-with-hooks");
4641
+ const token = randomBytes5(32).toString("hex");
4642
+ const connections = new Set;
4643
+ const server = createServer((socket) => {
4644
+ connections.add(socket);
4645
+ socket.once("close", () => connections.delete(socket));
4646
+ socket.setEncoding("utf8");
4647
+ let request = "";
4648
+ let handled = false;
4649
+ const handleRequest = () => {
4650
+ if (handled)
4651
+ return;
4652
+ handled = true;
4653
+ try {
4654
+ const parsed = JSON.parse(request.trimEnd());
4655
+ if (parsed.token !== token)
4656
+ throw new Error("invalid hook capability");
4657
+ if (!parsed.input || typeof parsed.input !== "object" || typeof parsed.input.tool_name !== "string") {
4658
+ throw new Error("invalid PreToolUse payload");
4659
+ }
4660
+ const output = evaluateCodexVaultPreToolUse(parsed.input, userId, {
4661
+ referencesSensitiveStorage: referencesHostedSecretStorage,
4662
+ substitute: substituteHostedSecrets
4663
+ });
4664
+ socket.end(JSON.stringify({ ok: true, output }));
4665
+ } catch (error) {
4666
+ const message = error instanceof Error ? error.message : String(error);
4667
+ socket.end(JSON.stringify({ ok: false, error: message }));
4668
+ }
4669
+ };
4670
+ socket.on("data", (chunk) => {
4671
+ request += chunk;
4672
+ if (Buffer.byteLength(request) > MAX_HOOK_REQUEST_BYTES)
4673
+ socket.destroy();
4674
+ else if (request.endsWith(`
4675
+ `))
4676
+ handleRequest();
4677
+ });
4678
+ socket.on("end", handleRequest);
4679
+ });
4680
+ try {
4681
+ await new Promise((resolveListen, reject) => {
4682
+ server.once("error", reject);
4683
+ server.listen(socketPath, () => {
4684
+ server.off("error", reject);
4685
+ resolveListen();
4686
+ });
4687
+ });
4688
+ await chmod(socketPath, 384);
4689
+ await writeFile(wrapperPath, privateCodexWrapper(codexCliScriptPath()), { mode: 448 });
4690
+ const command = [
4691
+ shellQuote(process.execPath),
4692
+ shellQuote(hookClientPath()),
4693
+ shellQuote(socketPath),
4694
+ shellQuote(token)
4695
+ ].join(" ");
4696
+ return {
4697
+ codexPathOverride: wrapperPath,
4698
+ hooks: {
4699
+ PreToolUse: [
4700
+ {
4701
+ matcher: "*",
4702
+ hooks: [
4703
+ {
4704
+ type: "command",
4705
+ command,
4706
+ timeout: 30,
4707
+ statusMessage: "Resolving Vault placeholders"
4708
+ }
4709
+ ]
4710
+ }
4711
+ ]
4712
+ },
4713
+ async close() {
4714
+ for (const socket of connections)
4715
+ socket.destroy();
4716
+ await new Promise((resolveClose) => server.close(() => resolveClose()));
4717
+ await rm(root, { recursive: true, force: true });
4718
+ }
4719
+ };
4720
+ } catch (error) {
4721
+ server.close();
4722
+ await rm(root, { recursive: true, force: true });
4723
+ throw error;
4724
+ }
4725
+ }
4726
+ var MAX_HOOK_REQUEST_BYTES, SENSITIVE_STORAGE_DENIAL = "Runtime secret storage access is not permitted";
4727
+ var init_codex_vault_hook_bridge = __esm(async () => {
4728
+ init_codex_native_multi_agent();
4729
+ await init_execution_host();
4730
+ init_vault_tool_policy();
4731
+ MAX_HOOK_REQUEST_BYTES = 1024 * 1024;
4732
+ });
4733
+
4597
4734
  // ../../packages/core/src/agents/tool-format.ts
4598
4735
  import { readFileSync as readFileSync10, statSync as statSync4 } from "fs";
4599
- import { isAbsolute, resolve as resolve7 } from "path";
4736
+ import { isAbsolute, resolve as resolve8 } from "path";
4600
4737
  import { diffLines as computeLineDiff } from "diff";
4601
4738
  function summarizeDisplayText(value) {
4602
4739
  const normalized = value.replace(/\s+/g, " ").trim();
@@ -4920,7 +5057,7 @@ function sourceStartLine(input, before, after, cwd) {
4920
5057
  const rawPath = input.file_path ?? input.path;
4921
5058
  if (typeof rawPath !== "string" || !rawPath.trim())
4922
5059
  return 1;
4923
- const path = isAbsolute(rawPath) ? rawPath : resolve7(cwd ?? process.cwd(), rawPath);
5060
+ const path = isAbsolute(rawPath) ? rawPath : resolve8(cwd ?? process.cwd(), rawPath);
4924
5061
  try {
4925
5062
  if (statSync4(path).size > TOOL_DIFF_SOURCE_MAX_BYTES)
4926
5063
  return 1;
@@ -5118,9 +5255,9 @@ __export(exports_codex_provider, {
5118
5255
  codexProvider: () => codexProvider
5119
5256
  });
5120
5257
  import { execFileSync as execFileSync4 } from "child_process";
5121
- import { existsSync as existsSync11, readFileSync as readFileSync11, realpathSync as realpathSync3, statSync as statSync5 } from "fs";
5258
+ import { existsSync as existsSync12, readFileSync as readFileSync11, realpathSync as realpathSync3, statSync as statSync5 } from "fs";
5122
5259
  import { homedir as homedir6 } from "os";
5123
- import { dirname as dirname9, isAbsolute as isAbsolute2, join as join12, relative, resolve as resolve8 } from "path";
5260
+ import { dirname as dirname10, isAbsolute as isAbsolute2, join as join13, relative, resolve as resolve9 } from "path";
5124
5261
  import { Codex } from "@openai/codex-sdk";
5125
5262
  function sameCodexUsage(usage, total) {
5126
5263
  return usage.input_tokens === total.inputTokens && usage.output_tokens === total.outputTokens && (usage.cached_input_tokens ?? 0) === total.cachedInputTokens && (usage.cache_write_input_tokens ?? 0) === total.cacheWriteInputTokens;
@@ -5148,8 +5285,8 @@ function codexMcpServerName(name) {
5148
5285
  return CODEX_MCP_SERVER_NAME_OVERRIDES[name] ?? name;
5149
5286
  }
5150
5287
  function globalCodexMcpServerNames(authFilePath) {
5151
- const configPath = join12(dirname9(authFilePath), "config.toml");
5152
- if (!existsSync11(configPath))
5288
+ const configPath = join13(dirname10(authFilePath), "config.toml");
5289
+ if (!existsSync12(configPath))
5153
5290
  return [];
5154
5291
  try {
5155
5292
  const names = new Set;
@@ -5244,13 +5381,13 @@ function summarizeMcpToolCallResult(item) {
5244
5381
  }
5245
5382
  function canonicalPath(path) {
5246
5383
  try {
5247
- return realpathSync3(resolve8(path));
5384
+ return realpathSync3(resolve9(path));
5248
5385
  } catch {
5249
- return resolve8(path);
5386
+ return resolve9(path);
5250
5387
  }
5251
5388
  }
5252
5389
  function textFile(path, maxBytes = CODEX_DIFF_FILE_LIMIT) {
5253
- if (!existsSync11(path))
5390
+ if (!existsSync12(path))
5254
5391
  return null;
5255
5392
  try {
5256
5393
  const byteLimit = Math.min(CODEX_DIFF_FILE_LIMIT, Math.max(0, maxBytes));
@@ -5290,7 +5427,7 @@ class CodexFilePreviewTracker {
5290
5427
  const code = record.slice(0, 2);
5291
5428
  const path = record.slice(3);
5292
5429
  const remainingBytes = CODEX_DIFF_BASELINE_BYTE_LIMIT - loadedBytes;
5293
- const content = loadedFiles < CODEX_DIFF_BASELINE_FILE_LIMIT && remainingBytes > 0 ? textFile(resolve8(this.#root, path), remainingBytes) : undefined;
5430
+ const content = loadedFiles < CODEX_DIFF_BASELINE_FILE_LIMIT && remainingBytes > 0 ? textFile(resolve9(this.#root, path), remainingBytes) : undefined;
5294
5431
  this.#baseline.set(path, content);
5295
5432
  if (typeof content === "string") {
5296
5433
  loadedFiles += 1;
@@ -5303,7 +5440,7 @@ class CodexFilePreviewTracker {
5303
5440
  preview(path, succeeded) {
5304
5441
  if (!this.#root || !this.#baselineAvailable || !succeeded)
5305
5442
  return {};
5306
- const absolute = canonicalPath(isAbsolute2(path) ? path : resolve8(this.#cwd, path));
5443
+ const absolute = canonicalPath(isAbsolute2(path) ? path : resolve9(this.#cwd, path));
5307
5444
  const relativePath = relative(this.#root, absolute);
5308
5445
  if (!relativePath || relativePath.startsWith("..") || isAbsolute2(relativePath))
5309
5446
  return {};
@@ -5338,7 +5475,7 @@ class CodexFilePreviewTracker {
5338
5475
  }
5339
5476
  }
5340
5477
  async function fileChangeEvents(item, previews, cwd, threadId, consumedPatchCallIds) {
5341
- const expectedPaths = item.changes.map((change) => isAbsolute2(change.path) ? change.path : resolve8(cwd, change.path));
5478
+ const expectedPaths = item.changes.map((change) => isAbsolute2(change.path) ? change.path : resolve9(cwd, change.path));
5342
5479
  let nativePreview;
5343
5480
  if (threadId && item.status === "completed") {
5344
5481
  await new Promise((resolveDelay) => setTimeout(resolveDelay, 20));
@@ -5462,7 +5599,7 @@ async function* codexProvider(opts) {
5462
5599
  const filePreviews = new CodexFilePreviewTracker(opts.cwd);
5463
5600
  const consumedPatchCallIds = new Set(opts.sessionId ? readCodexPatchCallIds(opts.sessionId) : []);
5464
5601
  const codexAuthPath = hostedCodexAuthFilePath();
5465
- if (!existsSync11(codexAuthPath)) {
5602
+ if (!existsSync12(codexAuthPath)) {
5466
5603
  yield {
5467
5604
  type: "error",
5468
5605
  content: `Codex auth file not found at ${codexAuthPath}. Run \`codex login\` to authenticate.`
@@ -5501,21 +5638,30 @@ async function* codexProvider(opts) {
5501
5638
  model: opts.model ?? "(sdk default)",
5502
5639
  effort: opts.effort ?? "(off)",
5503
5640
  cwd: opts.cwd,
5504
- cwdExists: existsSync11(opts.cwd),
5641
+ cwdExists: existsSync12(opts.cwd),
5505
5642
  resume: Boolean(opts.sessionId),
5506
5643
  mcpServerCount: Object.keys(codexMcpServers).length
5507
5644
  }, "codexProvider: starting turn");
5508
5645
  const hostedCodexHome = hostedCodexHomePath();
5509
- const inheritedCodexHome = process.env.CODEX_HOME || join12(homedir6(), ".codex");
5510
- const codexEnvironment = scopedBrowserCapability || resolve8(hostedCodexHome) !== resolve8(inheritedCodexHome) ? {
5646
+ const inheritedCodexHome = process.env.CODEX_HOME || join13(homedir6(), ".codex");
5647
+ const codexEnvironment = scopedBrowserCapability || resolve9(hostedCodexHome) !== resolve9(inheritedCodexHome) ? {
5511
5648
  ...Object.fromEntries(Object.entries(process.env).filter((entry) => typeof entry[1] === "string")),
5512
5649
  CODEX_HOME: hostedCodexHome,
5513
5650
  ...scopedBrowserCapability ? { [CODEX_BROWSER_CAPABILITY_ENV]: scopedBrowserCapability } : {}
5514
5651
  } : undefined;
5652
+ let vaultHook;
5653
+ try {
5654
+ vaultHook = await createCodexVaultHookBridge(opts.vaultUserId ?? opts.userId ?? "");
5655
+ } catch (err) {
5656
+ yield { type: "error", content: `Failed to initialize Codex Vault hooks: ${errMsg(err)}` };
5657
+ return;
5658
+ }
5515
5659
  const codex = new Codex({
5660
+ codexPathOverride: vaultHook.codexPathOverride,
5516
5661
  ...codexEnvironment ? { env: codexEnvironment } : {},
5517
5662
  config: {
5518
- features: { multi_agent: false, multi_agent_v2: false, enable_fanout: false },
5663
+ features: { hooks: true, multi_agent: false, multi_agent_v2: false, enable_fanout: false },
5664
+ hooks: vaultHook.hooks,
5519
5665
  model_catalog_json: codexModelCatalogPath,
5520
5666
  mcp_servers: codexMcpServers,
5521
5667
  ...opts.toolPolicy ? { sandbox_permissions: [] } : {}
@@ -5619,7 +5765,7 @@ async function* codexProvider(opts) {
5619
5765
  if (!item)
5620
5766
  break;
5621
5767
  if (item.type === "command_execution") {
5622
- const command = String(item.command ?? "");
5768
+ const command = redactHostedSecrets(opts.vaultUserId ?? opts.userId ?? "", String(item.command ?? ""));
5623
5769
  yield {
5624
5770
  type: "tool_use",
5625
5771
  name: "Bash",
@@ -5627,10 +5773,11 @@ async function* codexProvider(opts) {
5627
5773
  toolUseId: String(item.id ?? "")
5628
5774
  };
5629
5775
  } else if (item.type === "mcp_tool_call") {
5776
+ const input = item.arguments && typeof item.arguments === "object" ? item.arguments : {};
5630
5777
  yield {
5631
5778
  type: "tool_use",
5632
5779
  name: String(item.tool ?? "unknown"),
5633
- input: item.arguments && typeof item.arguments === "object" ? item.arguments : {},
5780
+ input: deepMapStrings(input, (value) => redactHostedSecrets(opts.vaultUserId ?? opts.userId ?? "", value)),
5634
5781
  toolUseId: String(item.id ?? "")
5635
5782
  };
5636
5783
  }
@@ -5673,7 +5820,7 @@ async function* codexProvider(opts) {
5673
5820
  yield {
5674
5821
  type: "tool_result",
5675
5822
  toolUseId: String(item.id ?? ""),
5676
- content: summarizeMcpToolCallResult(item),
5823
+ content: redactHostedSecrets(opts.vaultUserId ?? opts.userId ?? "", summarizeMcpToolCallResult(item)),
5677
5824
  ...isError ? { isError: true } : {}
5678
5825
  };
5679
5826
  } else if (item.type === "command_execution") {
@@ -5681,7 +5828,7 @@ async function* codexProvider(opts) {
5681
5828
  yield {
5682
5829
  type: "tool_result",
5683
5830
  toolUseId: String(item.id ?? ""),
5684
- content: String(item.aggregated_output ?? "").slice(0, 200),
5831
+ content: redactHostedSecrets(opts.vaultUserId ?? opts.userId ?? "", String(item.aggregated_output ?? "").slice(0, 200)),
5685
5832
  ...isError ? { isError: true } : {}
5686
5833
  };
5687
5834
  } else if (item.type === "file_change") {
@@ -5778,12 +5925,14 @@ async function* codexProvider(opts) {
5778
5925
  abortSignal?.removeEventListener("abort", onAbortKill);
5779
5926
  if (trackedPids.pids.length > 0)
5780
5927
  unregisterOwnedCodexPids(trackedPids.pids);
5928
+ await vaultHook.close();
5781
5929
  }
5782
5930
  }
5783
5931
  var CODEX_MCP_SERVER_NAME_OVERRIDES, CODEX_DIFF_FILE_LIMIT, CODEX_DIFF_BASELINE_FILE_LIMIT = 200, CODEX_DIFF_BASELINE_BYTE_LIMIT, CODEX_STARTUP_TIMEOUT_MS = 90000;
5784
5932
  var init_codex_provider = __esm(async () => {
5785
5933
  init_codex_native_multi_agent();
5786
5934
  init_codex_tree_kill();
5935
+ await init_codex_vault_hook_bridge();
5787
5936
  await init_execution_host();
5788
5937
  await init_codex();
5789
5938
  init_tool_format();
@@ -5811,7 +5960,7 @@ __export(exports_maestro_provider, {
5811
5960
  buildMaestroToolHooks: () => buildMaestroToolHooks,
5812
5961
  buildMaestroDisallowedTools: () => buildMaestroDisallowedTools
5813
5962
  });
5814
- import { resolve as resolve9 } from "path";
5963
+ import { resolve as resolve10 } from "path";
5815
5964
  import { maestroProvider as sdkMaestroProvider, setMcpResolver } from "maestro-agent-sdk";
5816
5965
  function buildMaestroDisallowedTools(callerDisallowedTools = [], toolPolicy) {
5817
5966
  return [
@@ -5945,13 +6094,13 @@ var init_maestro_provider = __esm(async () => {
5945
6094
  "ToolSearch",
5946
6095
  ...DEFAULT_MAESTRO_DISALLOWED_TOOLS
5947
6096
  ];
5948
- MAESTRO_TOOL_OUTPUT_DIR = resolve9(RUN_DIR, "maestro-tool-outputs");
6097
+ MAESTRO_TOOL_OUTPUT_DIR = resolve10(RUN_DIR, "maestro-tool-outputs");
5949
6098
  });
5950
6099
 
5951
6100
  // ../../packages/core/src/agents/index.ts
5952
- import { existsSync as existsSync12 } from "fs";
6101
+ import { existsSync as existsSync13 } from "fs";
5953
6102
  import { homedir as homedir7 } from "os";
5954
- import { join as join13 } from "path";
6103
+ import { join as join14 } from "path";
5955
6104
  async function* dispatchAgent(opts) {
5956
6105
  switch (opts.agent) {
5957
6106
  case "claude": {
@@ -5985,11 +6134,11 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
5985
6134
  switch (agent) {
5986
6135
  case "claude": {
5987
6136
  const encodedCwd = encodeClaudeCwd(cwd);
5988
- const path = join13(homedir7(), ".claude", "projects", encodedCwd, `${sessionId}.jsonl`);
5989
- return !existsSync12(path);
6137
+ const path = join14(homedir7(), ".claude", "projects", encodedCwd, `${sessionId}.jsonl`);
6138
+ return !existsSync13(path);
5990
6139
  }
5991
6140
  case "codex": {
5992
- const sessionsDir = join13(hostedCodexHomePath(), "sessions");
6141
+ const sessionsDir = join14(hostedCodexHomePath(), "sessions");
5993
6142
  const glob = new Bun.Glob(`**/rollout-*-${sessionId}.jsonl`);
5994
6143
  for await (const _rel of glob.scan({ cwd: sessionsDir, onlyFiles: true })) {
5995
6144
  return false;
@@ -5998,7 +6147,7 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
5998
6147
  }
5999
6148
  case "maestro": {
6000
6149
  const { hasActiveMaestroSession, maestroSessionPath: maestroSessionPath2 } = await import("maestro-agent-sdk");
6001
- return !existsSync12(maestroSessionPath2(sessionId)) && !hasActiveMaestroSession(sessionId);
6150
+ return !existsSync13(maestroSessionPath2(sessionId)) && !hasActiveMaestroSession(sessionId);
6002
6151
  }
6003
6152
  default: {
6004
6153
  const _exhaustive = agent;
@@ -6526,9 +6675,9 @@ var init_model_catalog = __esm(() => {
6526
6675
 
6527
6676
  // ../../packages/core/src/prompts/builders.ts
6528
6677
  import { readFileSync as readFileSync12 } from "fs";
6529
- import { resolve as resolve10 } from "path";
6678
+ import { resolve as resolve11 } from "path";
6530
6679
  function loadPrompt(filename, dir = SESSIONS_DIR) {
6531
- const raw = readFileSync12(resolve10(dir, filename), "utf-8");
6680
+ const raw = readFileSync12(resolve11(dir, filename), "utf-8");
6532
6681
  return raw.replace(/\{\{RESOURCES_DIR\}\}/g, RESOURCES_DIR);
6533
6682
  }
6534
6683
  function replaceVars(template, vars) {
@@ -6577,7 +6726,7 @@ function visualDesignGuide() {
6577
6726
  return _visualDesignGuide;
6578
6727
  }
6579
6728
  function loadAgentPrompt(filename) {
6580
- const raw = readFileSync12(resolve10(AGENTS_PROMPTS_DIR, filename), "utf-8");
6729
+ const raw = readFileSync12(resolve11(AGENTS_PROMPTS_DIR, filename), "utf-8");
6581
6730
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
6582
6731
  if (!match)
6583
6732
  throw new Error(`Agent prompt ${filename} is missing frontmatter`);
@@ -6892,8 +7041,8 @@ var init_builders = __esm(() => {
6892
7041
  init_model_catalog();
6893
7042
  init_config();
6894
7043
  init_logger();
6895
- PROMPTS_DIR = resolve10(PROJECT_ROOT, "src/prompts");
6896
- SESSIONS_DIR = resolve10(PROMPTS_DIR, "sessions");
7044
+ PROMPTS_DIR = resolve11(PROJECT_ROOT, "src/prompts");
7045
+ SESSIONS_DIR = resolve11(PROMPTS_DIR, "sessions");
6897
7046
  defaultPromptBuilders = createPromptBuilders();
6898
7047
  buildTopicSystemPrompt = defaultPromptBuilders.buildTopicSystemPrompt;
6899
7048
  buildChannelSystemPrompt = defaultPromptBuilders.buildChannelSystemPrompt;
@@ -7244,9 +7393,9 @@ var init_api_topic_brief = __esm(async () => {
7244
7393
  });
7245
7394
 
7246
7395
  // ../../packages/core/src/storage/wiki.ts
7247
- import { basename as basename2, dirname as dirname10, join as join14 } from "path";
7396
+ import { basename as basename2, dirname as dirname11, join as join15 } from "path";
7248
7397
  function getSharedWikiDir(workspaceDir = resolveStorageWorkspaceDir()) {
7249
- return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() : join14(workspaceDir, "wiki");
7398
+ return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() : join15(workspaceDir, "wiki");
7250
7399
  }
7251
7400
  var init_wiki = __esm(async () => {
7252
7401
  await init_storage_host();
@@ -8080,8 +8229,8 @@ var init_personal_general = __esm(async () => {
8080
8229
 
8081
8230
  // ../../packages/core/src/agents/archiver.ts
8082
8231
  import { randomUUID as randomUUID6 } from "crypto";
8083
- import { existsSync as existsSync13, readdirSync as readdirSync2, readFileSync as readFileSync13, statSync as statSync6 } from "fs";
8084
- import { join as join15 } from "path";
8232
+ import { existsSync as existsSync14, readdirSync as readdirSync2, readFileSync as readFileSync13, statSync as statSync6 } from "fs";
8233
+ import { join as join16 } from "path";
8085
8234
  function resolveMemoryLanguage() {
8086
8235
  const override = process.env.NEGOTIUM_MEMORY_LANG?.trim();
8087
8236
  return override && override.length > 0 ? override : resolveOutputLanguage();
@@ -8332,10 +8481,10 @@ function distillOneLine(summaryMd) {
8332
8481
  return "";
8333
8482
  }
8334
8483
  function findSummaryFile(storage, topicTitle, date, sinceMs, topicId) {
8335
- const dir = join15(storage.getWikiDir(), "summaries");
8484
+ const dir = join16(storage.getWikiDir(), "summaries");
8336
8485
  if (!storage.fileExists(dir))
8337
8486
  return null;
8338
- const predicted = join15(dir, wikiSummaryFilename(date, topicTitle, topicId));
8487
+ const predicted = join16(dir, wikiSummaryFilename(date, topicTitle, topicId));
8339
8488
  if (storage.fileExists(predicted) && storage.fileModifiedAt(predicted) >= sinceMs)
8340
8489
  return predicted;
8341
8490
  let best = null;
@@ -8343,7 +8492,7 @@ function findSummaryFile(storage, topicTitle, date, sinceMs, topicId) {
8343
8492
  if (!f.startsWith(`${date}-`) || !isTopicSummaryFile(f, topicId ?? "", topicTitle)) {
8344
8493
  continue;
8345
8494
  }
8346
- const p = join15(dir, f);
8495
+ const p = join16(dir, f);
8347
8496
  try {
8348
8497
  const m = storage.fileModifiedAt(p);
8349
8498
  if (m >= sinceMs && (!best || m > best.mtime))
@@ -8424,7 +8573,7 @@ var init_archiver = __esm(async () => {
8424
8573
  defaultArchiverRuntime = createArchiverRuntime({
8425
8574
  storage: {
8426
8575
  getWikiDir: getSharedWikiDir,
8427
- fileExists: existsSync13,
8576
+ fileExists: existsSync14,
8428
8577
  listDirectory: readdirSync2,
8429
8578
  readTextFile: (path) => readFileSync13(path, "utf-8"),
8430
8579
  fileSize: (path) => statSync6(path).size,
@@ -8469,9 +8618,9 @@ __export(exports_auth_check, {
8469
8618
  checkAgentAuth: () => checkAgentAuth
8470
8619
  });
8471
8620
  import { execFileSync as execFileSync5 } from "child_process";
8472
- import { existsSync as existsSync14 } from "fs";
8621
+ import { existsSync as existsSync15 } from "fs";
8473
8622
  import { homedir as homedir8, platform } from "os";
8474
- import { join as join16 } from "path";
8623
+ import { join as join17 } from "path";
8475
8624
  function hasMaestroCredential(host, key, userId) {
8476
8625
  if (userId && host.getVaultValue(userId, key)?.trim())
8477
8626
  return true;
@@ -8491,7 +8640,7 @@ function checkAgentAuth(agent, host = defaultAgentAuthHost, userId) {
8491
8640
  case "claude": {
8492
8641
  if (host.environment.ANTHROPIC_API_KEY)
8493
8642
  return { ok: true };
8494
- const path = join16(host.homeDirectory(), ".claude", ".credentials.json");
8643
+ const path = join17(host.homeDirectory(), ".claude", ".credentials.json");
8495
8644
  if (host.operatingSystem() === "darwin") {
8496
8645
  if (host.hasMacOsCredential("Claude Code-credentials") || host.exists(path)) {
8497
8646
  return { ok: true };
@@ -8542,7 +8691,7 @@ var init_auth_check = __esm(async () => {
8542
8691
  await init_vault();
8543
8692
  defaultAgentAuthHost = {
8544
8693
  codexAuthFilePath,
8545
- exists: existsSync14,
8694
+ exists: existsSync15,
8546
8695
  environment: process.env,
8547
8696
  homeDirectory: homedir8,
8548
8697
  operatingSystem: platform,
@@ -8559,7 +8708,7 @@ var init_auth_check = __esm(async () => {
8559
8708
  });
8560
8709
 
8561
8710
  // ../../packages/core/src/agents/fork.ts
8562
- import { existsSync as existsSync15, unlinkSync as unlinkSync8 } from "fs";
8711
+ import { existsSync as existsSync16, unlinkSync as unlinkSync8 } from "fs";
8563
8712
  function createAgentForkHelpers(host) {
8564
8713
  return {
8565
8714
  async forkAgentSession(options) {
@@ -8596,7 +8745,7 @@ var init_fork = __esm(async () => {
8596
8745
  init_logger();
8597
8746
  defaultForkHelpers = createAgentForkHelpers({
8598
8747
  forkSession: (agent, options) => getRegistryOperations(agent).forkSession(options),
8599
- exists: existsSync15,
8748
+ exists: existsSync16,
8600
8749
  unlink: unlinkSync8,
8601
8750
  warn: (details, message) => logger.warn(details, message)
8602
8751
  });
@@ -9252,13 +9401,13 @@ function formatTopicArchiveTranscriptRecord(row, topicTitle, index) {
9252
9401
 
9253
9402
  // ../../packages/core/src/storage/topic-archive.ts
9254
9403
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync8 } from "fs";
9255
- import { join as join17 } from "path";
9404
+ import { join as join18 } from "path";
9256
9405
  function archiveTopicMessages(topicId, topicTitle, options = {}) {
9257
9406
  const rows = options.afterRowid !== undefined ? getMessagesForTopicAfterRowid(topicId, options.afterRowid) : getAllMessagesForTopic(topicId);
9258
9407
  if (rows.length === 0)
9259
9408
  return null;
9260
9409
  const safeTopic = sanitizeTopicName(topicTitle, true);
9261
- const archiveDir = join17(getSharedWikiDir(), "archive");
9410
+ const archiveDir = join18(getSharedWikiDir(), "archive");
9262
9411
  mkdirSync10(archiveDir, { recursive: true });
9263
9412
  const date = new Date().toISOString().slice(0, 10);
9264
9413
  const reasonSuffix = options.reason && options.reason !== "delete" ? `_${options.reason}` : "";
@@ -9271,7 +9420,7 @@ function archiveTopicMessages(topicId, topicTitle, options = {}) {
9271
9420
  let path;
9272
9421
  while (true) {
9273
9422
  filename = `${safeTopic}_${date}${reasonSuffix}${counter === 1 ? "" : `_${counter}`}.jsonl`;
9274
- path = join17(archiveDir, filename);
9423
+ path = join18(archiveDir, filename);
9275
9424
  try {
9276
9425
  writeFileSync8(path, body, { flag: "wx" });
9277
9426
  break;
@@ -9316,7 +9465,7 @@ function archiveConversationEvents(topicId, topicTitle, userId, options = {}) {
9316
9465
  const entries = readRawConversation(userId, topicTitle);
9317
9466
  if (entries.length === 0)
9318
9467
  return null;
9319
- const archiveDir = join17(getSharedWikiDir(), "archive");
9468
+ const archiveDir = join18(getSharedWikiDir(), "archive");
9320
9469
  mkdirSync10(archiveDir, { recursive: true });
9321
9470
  const safeTopic = sanitizeTopicName(topicTitle, true);
9322
9471
  const date = new Date().toISOString().slice(0, 10);
@@ -9344,7 +9493,7 @@ function archiveConversationEvents(topicId, topicTitle, userId, options = {}) {
9344
9493
  let counter = 1;
9345
9494
  while (true) {
9346
9495
  const suffix = counter === 1 ? "" : `_${counter}`;
9347
- const path = join17(archiveDir, `${safeTopic}_${date}${reasonSuffix}_events${suffix}.jsonl`);
9496
+ const path = join18(archiveDir, `${safeTopic}_${date}${reasonSuffix}_events${suffix}.jsonl`);
9348
9497
  try {
9349
9498
  writeFileSync8(path, body, { flag: "wx" });
9350
9499
  logger.info({ topicId, topicTitle, archive: path, eventCount: entries.length }, "archiveConversationEvents: archived raw conversation events");
@@ -10255,8 +10404,8 @@ function createAskUserRuntime(host) {
10255
10404
  return errorResult(`Error: failed to persist ask_user_question: ${error instanceof Error ? error.message : String(error)}`);
10256
10405
  }
10257
10406
  let resolveAnswer;
10258
- const promise = new Promise((resolve11) => {
10259
- resolveAnswer = resolve11;
10407
+ const promise = new Promise((resolve12) => {
10408
+ resolveAnswer = resolve12;
10260
10409
  });
10261
10410
  pendingAsks.set(message.id, {
10262
10411
  topicId: ctx.topicId,
@@ -10510,11 +10659,11 @@ var init_manager_utils = () => {};
10510
10659
  // ../../packages/core/src/platform/playwright/browser-processes.ts
10511
10660
  import { execFileSync as execFileSync6 } from "child_process";
10512
10661
  import { readdirSync as readdirSync3, unlinkSync as unlinkSync10 } from "fs";
10513
- import { createServer } from "net";
10514
- import { resolve as resolve12, sep } from "path";
10662
+ import { createServer as createServer2 } from "net";
10663
+ import { resolve as resolve13, sep } from "path";
10515
10664
  function isPortInUse(port) {
10516
10665
  return new Promise((resolveProbe) => {
10517
- const server = createServer();
10666
+ const server = createServer2();
10518
10667
  let settled = false;
10519
10668
  const finish = (occupied) => {
10520
10669
  if (settled)
@@ -10544,8 +10693,8 @@ async function reserveAvailableLoopbackPort(minPort, maxPort, reservedPorts, pro
10544
10693
  return null;
10545
10694
  }
10546
10695
  function killBrowserProcsForUserDataDir(userDataDir) {
10547
- const target = resolve12(userDataDir);
10548
- const profileRoot = resolve12(BROWSER_PROFILES_DIR);
10696
+ const target = resolve13(userDataDir);
10697
+ const profileRoot = resolve13(BROWSER_PROFILES_DIR);
10549
10698
  if (target !== profileRoot && !target.startsWith(`${profileRoot}${sep}`))
10550
10699
  return;
10551
10700
  let pids;
@@ -10566,7 +10715,7 @@ function killBrowserProcsForUserDataDir(userDataDir) {
10566
10715
  stdio: "pipe"
10567
10716
  }).toString().trim();
10568
10717
  const argDir = extractUserDataDirArg(cmdline);
10569
- if (!argDir || resolve12(argDir) !== target)
10718
+ if (!argDir || resolve13(argDir) !== target)
10570
10719
  continue;
10571
10720
  killProcessTreeChildren(pidNum);
10572
10721
  process.kill(pidNum, "SIGKILL");
@@ -10577,13 +10726,13 @@ function killBrowserProcsForUserDataDir(userDataDir) {
10577
10726
  }
10578
10727
  }
10579
10728
  function selectOrphanBrowserPids(procs, liveUserDataDirs, profileRoot, selfPid) {
10580
- const root = resolve12(profileRoot);
10581
- const live = new Set([...liveUserDataDirs].map((d) => resolve12(d)));
10729
+ const root = resolve13(profileRoot);
10730
+ const live = new Set([...liveUserDataDirs].map((d) => resolve13(d)));
10582
10731
  const out = [];
10583
10732
  for (const { pid, userDataDir } of procs) {
10584
10733
  if (pid === selfPid || !userDataDir)
10585
10734
  continue;
10586
- const dir = resolve12(userDataDir);
10735
+ const dir = resolve13(userDataDir);
10587
10736
  if (dir !== root && !dir.startsWith(`${root}${sep}`))
10588
10737
  continue;
10589
10738
  if (live.has(dir))
@@ -10599,7 +10748,7 @@ function reapOrphanBrowsers(liveUserDataDirs) {
10599
10748
  const daemonLease = getRuntimeProcessLease("node-daemon", Date.now(), Number.POSITIVE_INFINITY);
10600
10749
  if (!isBrowserJanitorOwner(daemonLease?.pid ?? null, process.pid))
10601
10750
  return;
10602
- const profileRoot = resolve12(BROWSER_PROFILES_DIR);
10751
+ const profileRoot = resolve13(BROWSER_PROFILES_DIR);
10603
10752
  let pids;
10604
10753
  try {
10605
10754
  pids = execFileSync6("pgrep", ["-f", "--", profileRoot], { stdio: "pipe" }).toString().trim();
@@ -10638,7 +10787,7 @@ function cleanSingletonFiles(userDataDir) {
10638
10787
  for (const f of files) {
10639
10788
  if (f.startsWith("Singleton")) {
10640
10789
  try {
10641
- unlinkSync10(resolve12(userDataDir, f));
10790
+ unlinkSync10(resolve13(userDataDir, f));
10642
10791
  logger.info({ file: f, userDataDir }, "Removed stale Singleton file");
10643
10792
  } catch (e) {
10644
10793
  logger.warn({ err: e, file: f }, "Failed to remove stale Chrome Singleton file");
@@ -10678,9 +10827,9 @@ var init_browser_processes = __esm(async () => {
10678
10827
 
10679
10828
  // ../../packages/core/src/platform/playwright/headed-launch.ts
10680
10829
  import { accessSync as accessSync2, constants as constants2 } from "fs";
10681
- import { delimiter, isAbsolute as isAbsolute4, resolve as resolve13 } from "path";
10830
+ import { delimiter, isAbsolute as isAbsolute4, resolve as resolve14 } from "path";
10682
10831
  function findExecutableOnPath(command, environment = process.env) {
10683
- const candidates = isAbsolute4(command) ? [command] : (environment.PATH ?? "").split(delimiter).filter(Boolean).map((directory) => resolve13(directory, command));
10832
+ const candidates = isAbsolute4(command) ? [command] : (environment.PATH ?? "").split(delimiter).filter(Boolean).map((directory) => resolve14(directory, command));
10684
10833
  for (const candidate of candidates) {
10685
10834
  try {
10686
10835
  accessSync2(candidate, constants2.X_OK);
@@ -10778,11 +10927,11 @@ var init_vault_public = __esm(async () => {
10778
10927
  });
10779
10928
 
10780
10929
  // ../../packages/core/src/platform/playwright/vault-broker.ts
10781
- import { randomBytes as randomBytes5, timingSafeEqual as timingSafeEqual2 } from "crypto";
10930
+ import { randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual2 } from "crypto";
10782
10931
  import { chmodSync as chmodSync4 } from "fs";
10783
- import { createServer as createServer2 } from "net";
10784
- import { tmpdir as tmpdir2 } from "os";
10785
- import { join as join18 } from "path";
10932
+ import { createServer as createServer3 } from "net";
10933
+ import { tmpdir as tmpdir3 } from "os";
10934
+ import { join as join19 } from "path";
10786
10935
  function deepMapStrings2(value, transform) {
10787
10936
  if (typeof value === "string")
10788
10937
  return transform(value);
@@ -10868,8 +11017,8 @@ function authorized(actual, expected) {
10868
11017
  return left.length === right.length && timingSafeEqual2(left, right);
10869
11018
  }
10870
11019
  async function createBrowserVaultBroker(userId) {
10871
- const token = randomBytes5(32).toString("hex");
10872
- const socketPath = join18(process.platform === "win32" ? tmpdir2() : "/tmp", `negotium-browser-vault-${process.pid}-${randomBytes5(8).toString("hex")}.sock`);
11020
+ const token = randomBytes6(32).toString("hex");
11021
+ const socketPath = join19(process.platform === "win32" ? tmpdir3() : "/tmp", `negotium-browser-vault-${process.pid}-${randomBytes6(8).toString("hex")}.sock`);
10873
11022
  const retainedForms = new Map;
10874
11023
  const leases = new Map;
10875
11024
  const sockets = new Set;
@@ -10908,7 +11057,7 @@ async function createBrowserVaultBroker(userId) {
10908
11057
  return result.text;
10909
11058
  });
10910
11059
  const prepared = prepareInput(request.tool, substituted);
10911
- const lease = randomBytes5(24).toString("hex");
11060
+ const lease = randomBytes6(24).toString("hex");
10912
11061
  leases.set(lease, { boundary: prepared.boundary, createdAt: Date.now() });
10913
11062
  return {
10914
11063
  id,
@@ -10940,7 +11089,7 @@ async function createBrowserVaultBroker(userId) {
10940
11089
  }
10941
11090
  return { id, ok: false, error: "unknown operation" };
10942
11091
  };
10943
- const server = createServer2((socket) => {
11092
+ const server = createServer3((socket) => {
10944
11093
  sockets.add(socket);
10945
11094
  let pending = "";
10946
11095
  socket.setEncoding("utf8");
@@ -11068,24 +11217,24 @@ var init_browser_profiles = __esm(async () => {
11068
11217
 
11069
11218
  // ../../packages/core/src/platform/playwright/manager.ts
11070
11219
  import { execFileSync as execFileSync7, spawn as spawn5 } from "child_process";
11071
- import { createHash as createHash4, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual3 } from "crypto";
11220
+ import { createHash as createHash4, randomBytes as randomBytes7, timingSafeEqual as timingSafeEqual3 } from "crypto";
11072
11221
  import {
11073
11222
  cpSync,
11074
- existsSync as existsSync17,
11223
+ existsSync as existsSync18,
11075
11224
  mkdirSync as mkdirSync11,
11076
11225
  readFileSync as readFileSync15,
11077
11226
  rmSync as rmSync3,
11078
11227
  unlinkSync as unlinkSync11,
11079
11228
  writeFileSync as writeFileSync9
11080
11229
  } from "fs";
11081
- import { dirname as dirname11, join as join19, resolve as resolve14 } from "path";
11230
+ import { dirname as dirname12, join as join20, resolve as resolve15 } from "path";
11082
11231
  function removeDefaultProfileDataDir(userDataDir) {
11083
- const root = resolve14(BROWSER_PROFILES_DIR);
11084
- const target = resolve14(userDataDir);
11085
- if (dirname11(target) !== root) {
11232
+ const root = resolve15(BROWSER_PROFILES_DIR);
11233
+ const target = resolve15(userDataDir);
11234
+ if (dirname12(target) !== root) {
11086
11235
  throw new Error(`Refusing to delete browser profile outside managed root: ${target}`);
11087
11236
  }
11088
- const existed = existsSync17(target);
11237
+ const existed = existsSync18(target);
11089
11238
  rmSync3(target, { recursive: true, force: true });
11090
11239
  return existed;
11091
11240
  }
@@ -11168,14 +11317,14 @@ function portFileName(instanceKey) {
11168
11317
  function writePortFile(instanceKey, port) {
11169
11318
  try {
11170
11319
  mkdirSync11(managerHost.portsDir, { recursive: true });
11171
- writeFileSync9(join19(managerHost.portsDir, portFileName(instanceKey)), String(port));
11320
+ writeFileSync9(join20(managerHost.portsDir, portFileName(instanceKey)), String(port));
11172
11321
  } catch (e) {
11173
11322
  logger.warn({ err: e, instanceKey, port }, "Failed to save playwright port file");
11174
11323
  }
11175
11324
  }
11176
11325
  function deletePortFile(instanceKey) {
11177
11326
  try {
11178
- unlinkSync11(join19(managerHost.portsDir, portFileName(instanceKey)));
11327
+ unlinkSync11(join20(managerHost.portsDir, portFileName(instanceKey)));
11179
11328
  } catch (e) {
11180
11329
  if (e.code === "ENOENT")
11181
11330
  return;
@@ -11299,7 +11448,7 @@ function releasePort(port) {
11299
11448
  usedPorts.delete(port);
11300
11449
  }
11301
11450
  function defaultProfileDir(_ownerId, profile) {
11302
- return resolve14(BROWSER_PROFILES_DIR, profile);
11451
+ return resolve15(BROWSER_PROFILES_DIR, profile);
11303
11452
  }
11304
11453
  function resolveUserDataDir(instanceKey) {
11305
11454
  return managerHost.resolveInstanceDataDir(instanceKey);
@@ -11391,8 +11540,8 @@ async function spawnPlaywright(instanceKey, ownerId, reservedPort, browserBin =
11391
11540
  releasePort(port);
11392
11541
  throw new Error("Browser.rs managed mode does not support authenticated egress proxies");
11393
11542
  }
11394
- const capability = randomBytes6(32).toString("hex");
11395
- const spawnNonce = randomBytes6(32).toString("hex");
11543
+ const capability = randomBytes7(32).toString("hex");
11544
+ const spawnNonce = randomBytes7(32).toString("hex");
11396
11545
  let vaultBroker;
11397
11546
  try {
11398
11547
  vaultBroker = await createBrowserVaultBroker(ownerId);
@@ -11660,14 +11809,14 @@ async function cloneProfileForChild(opts) {
11660
11809
  killInstance(dstKey);
11661
11810
  await delay(500);
11662
11811
  }
11663
- if (!existsSync17(srcDir)) {
11812
+ if (!existsSync18(srcDir)) {
11664
11813
  return { copied: false, srcDir, dstDir, reason: "src-missing" };
11665
11814
  }
11666
11815
  try {
11667
- if (existsSync17(dstDir)) {
11816
+ if (existsSync18(dstDir)) {
11668
11817
  rmSync3(dstDir, { recursive: true, force: true });
11669
11818
  }
11670
- mkdirSync11(dirname11(dstDir), { recursive: true });
11819
+ mkdirSync11(dirname12(dstDir), { recursive: true });
11671
11820
  if (process.platform === "darwin") {
11672
11821
  try {
11673
11822
  execFileSync7("cp", ["-cR", srcDir, dstDir], { stdio: "pipe" });
@@ -11685,7 +11834,7 @@ async function cloneProfileForChild(opts) {
11685
11834
  cleanSingletonFiles(dstDir);
11686
11835
  for (const f of ["DevToolsActivePort", "LOCK"]) {
11687
11836
  try {
11688
- unlinkSync11(resolve14(dstDir, f));
11837
+ unlinkSync11(resolve15(dstDir, f));
11689
11838
  } catch {}
11690
11839
  }
11691
11840
  logger.info({ srcKey, dstKey, srcDir, dstDir }, "Cloned Playwright profile for child topic");
@@ -11813,7 +11962,7 @@ RULES:
11813
11962
 
11814
11963
  // ../../packages/core/src/agents/topic-cleanup.ts
11815
11964
  import { mkdirSync as mkdirSync12, renameSync as renameSync6, unlinkSync as unlinkSync12, writeFileSync as writeFileSync10 } from "fs";
11816
- import { dirname as dirname12 } from "path";
11965
+ import { dirname as dirname13 } from "path";
11817
11966
  function collectSessionIdsByAgent(entries, extraSessions = []) {
11818
11967
  const out = new Map;
11819
11968
  for (const e of entries) {
@@ -11879,7 +12028,7 @@ function createTopicLogMaintenance(host) {
11879
12028
  const path = runtimeHost.activeConversationPath(opts.userId, opts.topicName);
11880
12029
  const tempPath = `${path}.${process.pid}.${Date.now()}.tmp`;
11881
12030
  try {
11882
- mkdirSync12(dirname12(path), { recursive: true });
12031
+ mkdirSync12(dirname13(path), { recursive: true });
11883
12032
  writeFileSync10(tempPath, retained.length > 0 ? `${retained.map((entry) => JSON.stringify(entry)).join(`
11884
12033
  `)}
11885
12034
  ` : "", { flag: "wx" });
@@ -12333,8 +12482,8 @@ var init_runtime_turn_requests = __esm(async () => {
12333
12482
  // ../../packages/core/src/topics/session.ts
12334
12483
  import { randomUUID as randomUUID11 } from "crypto";
12335
12484
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "fs";
12336
- import { tmpdir as tmpdir3 } from "os";
12337
- import { join as join20 } from "path";
12485
+ import { tmpdir as tmpdir4 } from "os";
12486
+ import { join as join21 } from "path";
12338
12487
  function previousCompactedSummary(entries) {
12339
12488
  for (let index = entries.length - 2;index >= 0; index -= 1) {
12340
12489
  const request = entries[index]?.event;
@@ -12464,7 +12613,7 @@ function formatCompactElapsed(startedAt) {
12464
12613
  async function summarizeTopicContext(request) {
12465
12614
  const startedAt = Date.now();
12466
12615
  const sessionIds = [];
12467
- const compactCwd = mkdtempSync2(join20(tmpdir3(), "negotium-compact-"));
12616
+ const compactCwd = mkdtempSync2(join21(tmpdir4(), "negotium-compact-"));
12468
12617
  const abortController = new AbortController;
12469
12618
  const relayAbort = () => abortController.abort(request.signal?.reason);
12470
12619
  if (request.signal?.aborted)
@@ -12491,7 +12640,7 @@ async function summarizeTopicContext(request) {
12491
12640
  let error = "";
12492
12641
  let toolViolation = false;
12493
12642
  let compactionLogCalls = 0;
12494
- const compactionLogPath = join20(compactCwd, "conversation.log");
12643
+ const compactionLogPath = join21(compactCwd, "conversation.log");
12495
12644
  try {
12496
12645
  const compactionMcp = useCompactionLog ? {
12497
12646
  compact_log: {
@@ -13110,14 +13259,14 @@ var init_derive = __esm(async () => {
13110
13259
  });
13111
13260
 
13112
13261
  // ../../packages/core/src/query/session-inbox-path.ts
13113
- import { join as join21 } from "path";
13262
+ import { join as join22 } from "path";
13114
13263
  function sessionInboxPath(userId, topicId) {
13115
13264
  const key = Buffer.from(topicId, "utf8").toString("base64url");
13116
- return join21(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${JSONL_SUFFIX}`);
13265
+ return join22(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${JSONL_SUFFIX}`);
13117
13266
  }
13118
13267
  function scheduledSessionInboxPath(userId, topicId) {
13119
13268
  const key = Buffer.from(topicId, "utf8").toString("base64url");
13120
- return join21(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${SCHEDULE_SUFFIX}`);
13269
+ return join22(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${SCHEDULE_SUFFIX}`);
13121
13270
  }
13122
13271
  var TOPIC_ID_FILE_PREFIX = "topic-id-", JSONL_SUFFIX = ".jsonl", SCHEDULE_SUFFIX = ".schedule";
13123
13272
  var init_session_inbox_path = __esm(() => {
@@ -13126,13 +13275,13 @@ var init_session_inbox_path = __esm(() => {
13126
13275
 
13127
13276
  // ../../packages/core/src/query/session-inbox-cleanup.ts
13128
13277
  import { unlinkSync as unlinkSync14 } from "fs";
13129
- import { basename as basename3, join as join22 } from "path";
13278
+ import { basename as basename3, join as join23 } from "path";
13130
13279
  function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
13131
13280
  const live = sessionInboxPath(userId, topicId);
13132
13281
  const scheduled = scheduledSessionInboxPath(userId, topicId);
13133
13282
  const candidates = new Set([live, `${live}.processing`, scheduled, `${scheduled}.processing`]);
13134
13283
  if (legacyTopicTitle && legacyTopicTitle !== "." && legacyTopicTitle !== ".." && basename3(legacyTopicTitle) === legacyTopicTitle) {
13135
- const legacyBase = join22(SESSION_INBOX_DIR, userId, legacyTopicTitle);
13284
+ const legacyBase = join23(SESSION_INBOX_DIR, userId, legacyTopicTitle);
13136
13285
  for (const suffix of [".jsonl", ".jsonl.processing", ".schedule", ".schedule.processing"]) {
13137
13286
  candidates.add(`${legacyBase}${suffix}`);
13138
13287
  }
@@ -13158,16 +13307,16 @@ var init_session_inbox_cleanup = __esm(() => {
13158
13307
 
13159
13308
  // ../../packages/core/src/query/state.ts
13160
13309
  import { mkdirSync as mkdirSync14, renameSync as renameSync7, unlinkSync as unlinkSync15, writeFileSync as writeFileSync12 } from "fs";
13161
- import { basename as basename4, join as join23 } from "path";
13310
+ import { basename as basename4, join as join24 } from "path";
13162
13311
  function createQueryStateStore(options) {
13163
13312
  const sanitize = options.sanitizeTopicId ?? sanitizeId;
13164
- const queryStateDirPath = (userId) => join23(options.usersLogDir, String(userId), "active-queries");
13165
- const queryStateFile = (userId, topicId) => join23(queryStateDirPath(userId), `${sanitize(topicId)}.json`);
13313
+ const queryStateDirPath = (userId) => join24(options.usersLogDir, String(userId), "active-queries");
13314
+ const queryStateFile = (userId, topicId) => join24(queryStateDirPath(userId), `${sanitize(topicId)}.json`);
13166
13315
  const legacyQueryStateFile = (userId, topicName) => {
13167
13316
  if (!topicName || topicName === "." || topicName === ".." || basename4(topicName) !== topicName) {
13168
13317
  return null;
13169
13318
  }
13170
- return join23(queryStateDirPath(userId), `${topicName}.json`);
13319
+ return join24(queryStateDirPath(userId), `${topicName}.json`);
13171
13320
  };
13172
13321
  return {
13173
13322
  write(userId, topicId, topicName, task) {
@@ -13328,30 +13477,30 @@ import {
13328
13477
  unlinkSync as unlinkSync16,
13329
13478
  writeFileSync as writeFileSync13
13330
13479
  } from "fs";
13331
- import { dirname as dirname13, join as join24 } from "path";
13480
+ import { dirname as dirname14, join as join25 } from "path";
13332
13481
  function pendingAskDir(userId) {
13333
13482
  const rawUserId = String(userId);
13334
13483
  const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash6("sha256").update(rawUserId).digest("hex")}`;
13335
- return join24(resolveStorageSessionAsksDir(), safeUserId);
13484
+ return join25(resolveStorageSessionAsksDir(), safeUserId);
13336
13485
  }
13337
13486
  function encodeAskKey(key) {
13338
13487
  return JSON.stringify([key.from, key.to]);
13339
13488
  }
13340
13489
  function pendingAskPath(key) {
13341
13490
  const digest = createHash6("sha256").update(encodeAskKey(key)).digest("hex");
13342
- return join24(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
13491
+ return join25(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
13343
13492
  }
13344
13493
  function v2PendingAskPath(key) {
13345
13494
  const encoded = Buffer.from(encodeAskKey(key), "utf8").toString("base64url");
13346
- return join24(pendingAskDir(key.userId), `${V2_ASK_FILENAME_PREFIX}${encoded}.pending`);
13495
+ return join25(pendingAskDir(key.userId), `${V2_ASK_FILENAME_PREFIX}${encoded}.pending`);
13347
13496
  }
13348
13497
  function legacyPendingAskPath(key) {
13349
13498
  if (key.from.includes("/") || key.from.includes("\\") || key.to.includes("/") || key.to.includes("\\") || key.from.includes("\x00") || key.to.includes("\x00")) {
13350
13499
  return null;
13351
13500
  }
13352
13501
  const dir = pendingAskDir(key.userId);
13353
- const candidate = join24(dir, `${key.from}___${key.to}.pending`);
13354
- return dirname13(candidate) === dir ? candidate : null;
13502
+ const candidate = join25(dir, `${key.from}___${key.to}.pending`);
13503
+ return dirname14(candidate) === dir ? candidate : null;
13355
13504
  }
13356
13505
  function parsePendingAskFilename(fileName) {
13357
13506
  if (!fileName.endsWith(".pending"))
@@ -13591,7 +13740,7 @@ function listPendingAsksForCaller(args) {
13591
13740
  const parsed = isV3 ? { from: args.from, to: "" } : parsePendingAskFilename(fileName);
13592
13741
  if (!parsed)
13593
13742
  continue;
13594
- const path = join24(dir, fileName);
13743
+ const path = join25(dir, fileName);
13595
13744
  const record = readPendingAskFile(path, {
13596
13745
  userId: args.userId,
13597
13746
  from: parsed.from,
@@ -13633,7 +13782,7 @@ function deletePendingAsksForTopic(args) {
13633
13782
  }
13634
13783
  let deleted = 0;
13635
13784
  for (const fileName of files) {
13636
- const path = join24(dir, fileName);
13785
+ const path = join25(dir, fileName);
13637
13786
  const parsed = parsePendingAskFilename(fileName);
13638
13787
  const record = readPendingAskFile(path, {
13639
13788
  userId: args.userId,
@@ -14033,7 +14182,7 @@ body{font-family:system-ui,-apple-system,"Segoe UI",sans-serif;background:var(--
14033
14182
  // ../../packages/core/src/storage/token-stats.ts
14034
14183
  import { createHash as createHash7 } from "crypto";
14035
14184
  import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync14 } from "fs";
14036
- import { join as join25 } from "path";
14185
+ import { join as join26 } from "path";
14037
14186
  function tokenStatsFileId(userId) {
14038
14187
  const rawUserId = String(userId);
14039
14188
  return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash7("sha256").update(rawUserId).digest("hex")}`;
@@ -14042,7 +14191,7 @@ function queriesPath(userId) {
14042
14191
  const fileId = tokenStatsFileId(userId);
14043
14192
  const logDir = resolveStorageLogDir();
14044
14193
  mkdirSync16(logDir, { recursive: true });
14045
- return join25(logDir, `token-queries-${fileId}.jsonl`);
14194
+ return join26(logDir, `token-queries-${fileId}.jsonl`);
14046
14195
  }
14047
14196
  function estimateUsageCost(agent, model, usage) {
14048
14197
  const prices = TOKEN_PRICES[`${agent}:${model}`];
@@ -14358,7 +14507,7 @@ var init_lifecycle = __esm(async () => {
14358
14507
  // ../../packages/core/src/runtime/attachments.ts
14359
14508
  import { randomUUID as randomUUID14 } from "crypto";
14360
14509
  import { copyFileSync as copyFileSync2, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
14361
- import { basename as basename5, join as join26 } from "path";
14510
+ import { basename as basename5, join as join27 } from "path";
14362
14511
  function workspaceCwdFor(topicId) {
14363
14512
  return resolveTopicWorkspaceDir(topicId);
14364
14513
  }
@@ -14371,7 +14520,7 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
14371
14520
  if (!attachmentIds?.length)
14372
14521
  return [];
14373
14522
  const out = [];
14374
- const destDir = join26(workspaceCwdFor(topicId), "attachments", queryId);
14523
+ const destDir = join27(workspaceCwdFor(topicId), "attachments", queryId);
14375
14524
  for (const rawId of attachmentIds) {
14376
14525
  if (typeof rawId !== "string")
14377
14526
  continue;
@@ -14388,7 +14537,7 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
14388
14537
  mkdirSync17(destDir, { recursive: true });
14389
14538
  const index = String(out.length + 1).padStart(2, "0");
14390
14539
  const safeName = safeAttachmentFilename(attachment.filename, fileId);
14391
- const destPath = join26(destDir, `${index}-${fileId.slice(0, 8)}-${safeName}`);
14540
+ const destPath = join27(destDir, `${index}-${fileId.slice(0, 8)}-${safeName}`);
14392
14541
  copyFileSync2(sourcePath, destPath);
14393
14542
  out.push({
14394
14543
  id: attachment.id,
@@ -14418,10 +14567,10 @@ function promptWithAttachments(prompt, attachments) {
14418
14567
  return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
14419
14568
  }
14420
14569
  function ingestAttachment(args) {
14421
- const destDir = join26(UPLOADS_DIR, args.topicId);
14570
+ const destDir = join27(UPLOADS_DIR, args.topicId);
14422
14571
  mkdirSync17(destDir, { recursive: true });
14423
14572
  const safeName = safeAttachmentFilename(args.filename, "upload");
14424
- const destPath = join26(destDir, `${Date.now()}-${randomUUID14().slice(0, 8)}-${safeName}`);
14573
+ const destPath = join27(destDir, `${Date.now()}-${randomUUID14().slice(0, 8)}-${safeName}`);
14425
14574
  if (args.sourcePath !== undefined) {
14426
14575
  copyFileSync2(args.sourcePath, destPath);
14427
14576
  } else if (args.bytes !== undefined) {
@@ -14596,12 +14745,12 @@ var init_errors = __esm(() => {
14596
14745
 
14597
14746
  // ../../packages/core/src/runtime/event-heartbeat.ts
14598
14747
  function nextOrHeartbeat(pending, intervalMs) {
14599
- return new Promise((resolve15, reject) => {
14600
- const timer = setTimeout(() => resolve15({ kind: "heartbeat" }), intervalMs);
14748
+ return new Promise((resolve16, reject) => {
14749
+ const timer = setTimeout(() => resolve16({ kind: "heartbeat" }), intervalMs);
14601
14750
  timer.unref?.();
14602
14751
  pending.then((result) => {
14603
14752
  clearTimeout(timer);
14604
- resolve15({ kind: "event", result });
14753
+ resolve16({ kind: "event", result });
14605
14754
  }, (error) => {
14606
14755
  clearTimeout(timer);
14607
14756
  reject(error);
@@ -14922,7 +15071,7 @@ var init_visual_html = __esm(() => {
14922
15071
 
14923
15072
  // ../../packages/core/src/runtime/visuals.ts
14924
15073
  import { realpathSync as realpathSync4 } from "fs";
14925
- import { isAbsolute as isAbsolute5, resolve as resolve15 } from "path";
15074
+ import { isAbsolute as isAbsolute5, resolve as resolve16 } from "path";
14926
15075
  function activeVisualHtmlForPrompt(html) {
14927
15076
  if (html.length <= ACTIVE_VISUAL_PROMPT_MAX_CHARS) {
14928
15077
  return { html, omittedChars: 0 };
@@ -14973,8 +15122,8 @@ function topicAllowsVisualFileId(topicId, fileId) {
14973
15122
  return topicHasAttachmentFileId(topicId, fileId) || topicHasVisualFileId(topicId, fileId);
14974
15123
  }
14975
15124
  function isPathInside(baseDir, filePath) {
14976
- const base = resolve15(baseDir);
14977
- const normalized = resolve15(filePath);
15125
+ const base = resolve16(baseDir);
15126
+ const normalized = resolve16(filePath);
14978
15127
  try {
14979
15128
  const realBase = realpathSync4(base);
14980
15129
  const real = realpathSync4(normalized);
@@ -15036,7 +15185,7 @@ function resolveVisualMediaInput(topicId, input) {
15036
15185
  }
15037
15186
  const rawPath = input.file_path.trim();
15038
15187
  const cwd = workspaceCwdFor(topicId);
15039
- const candidate = isAbsolute5(rawPath) ? rawPath : resolve15(cwd, rawPath);
15188
+ const candidate = isAbsolute5(rawPath) ? rawPath : resolve16(cwd, rawPath);
15040
15189
  if (!isPathInside(cwd, candidate)) {
15041
15190
  return { error: "file_path must be inside the topic workspace" };
15042
15191
  }
@@ -15074,7 +15223,7 @@ var init_visuals = __esm(async () => {
15074
15223
  // ../../packages/core/src/runtime/turn-event-stream.ts
15075
15224
  import { randomUUID as randomUUID15 } from "crypto";
15076
15225
  import { realpathSync as realpathSync5, statSync as statSync9 } from "fs";
15077
- import { isAbsolute as isAbsolute6, resolve as resolve16 } from "path";
15226
+ import { isAbsolute as isAbsolute6, resolve as resolve17 } from "path";
15078
15227
  function sessionEventMatchesCurrentExecution(topicId, queryId, agent, model) {
15079
15228
  if (getRoomQuery(topicId)?.queryId !== queryId)
15080
15229
  return false;
@@ -15427,7 +15576,7 @@ ${JSON.stringify(event.input ?? {})}`);
15427
15576
  case "file":
15428
15577
  if (!silent && peerBridge) {
15429
15578
  const cwd = workspaceCwdFor(topicId);
15430
- const path = isAbsolute6(event.path) ? event.path : resolve16(cwd, event.path);
15579
+ const path = isAbsolute6(event.path) ? event.path : resolve17(cwd, event.path);
15431
15580
  if (!isPathInside(cwd, path)) {
15432
15581
  logger.warn({ topicId, path }, "peer output file is outside the topic workspace");
15433
15582
  break;
@@ -15709,15 +15858,15 @@ var init_turn_session = __esm(async () => {
15709
15858
  });
15710
15859
 
15711
15860
  // ../../packages/core/src/storage/app-settings.ts
15712
- import { existsSync as existsSync18, mkdirSync as mkdirSync18, readFileSync as readFileSync17, writeFileSync as writeFileSync16 } from "fs";
15713
- import { dirname as dirname14, join as join27 } from "path";
15861
+ import { existsSync as existsSync19, mkdirSync as mkdirSync18, readFileSync as readFileSync17, writeFileSync as writeFileSync16 } from "fs";
15862
+ import { dirname as dirname15, join as join28 } from "path";
15714
15863
  function settingsFile() {
15715
- return join27(resolveStorageDataDir(), "otium-settings.json");
15864
+ return join28(resolveStorageDataDir(), "otium-settings.json");
15716
15865
  }
15717
15866
  function getGlobalAiName() {
15718
15867
  const path = settingsFile();
15719
15868
  try {
15720
- if (existsSync18(path)) {
15869
+ if (existsSync19(path)) {
15721
15870
  const data = JSON.parse(readFileSync17(path, "utf8"));
15722
15871
  if (typeof data.aiName === "string" && data.aiName.trim()) {
15723
15872
  return data.aiName.trim();
@@ -15806,8 +15955,8 @@ __export(exports_turn_runner, {
15806
15955
  AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
15807
15956
  });
15808
15957
  import { randomUUID as randomUUID16 } from "crypto";
15809
- import { existsSync as existsSync19, mkdirSync as mkdirSync19, readdirSync as readdirSync5, statSync as statSync10 } from "fs";
15810
- import { join as join28 } from "path";
15958
+ import { existsSync as existsSync20, mkdirSync as mkdirSync19, readdirSync as readdirSync5, statSync as statSync10 } from "fs";
15959
+ import { join as join29 } from "path";
15811
15960
  function withDefaultPlaywright(configuredMcp, isManager) {
15812
15961
  if (isManager)
15813
15962
  return configuredMcp;
@@ -15862,8 +16011,8 @@ function appendAskReplyMessage(topicId, text2, agentType) {
15862
16011
  return message;
15863
16012
  }
15864
16013
  function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, matchesTitle, preferExact = true) {
15865
- const preferred = join28(directory, preferredFilename);
15866
- if (preferExact && existsSync19(preferred))
16014
+ const preferred = join29(directory, preferredFilename);
16015
+ if (preferExact && existsSync20(preferred))
15867
16016
  return preferred;
15868
16017
  let newestLegacyId = null;
15869
16018
  let newestTitle = null;
@@ -15873,7 +16022,7 @@ function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, ma
15873
16022
  const legacyIdMatch = !titleMatch && matchesLegacyId(filename);
15874
16023
  if (!titleMatch && !legacyIdMatch)
15875
16024
  continue;
15876
- const path = join28(directory, filename);
16025
+ const path = join29(directory, filename);
15877
16026
  const mtimeMs = statSync10(path).mtimeMs;
15878
16027
  if (titleMatch) {
15879
16028
  if (!newestTitle || mtimeMs > newestTitle.mtimeMs) {
@@ -15887,10 +16036,10 @@ function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, ma
15887
16036
  return newestTitle?.path ?? newestLegacyId?.path ?? preferred;
15888
16037
  }
15889
16038
  function resolveWikiMemoryMirror(wikiDir, topicId, topicTitle) {
15890
- const briefFile = resolveWikiMirrorPath(join28(wikiDir, "topic"), `${wikiBriefStorageKey(topicTitle, topicId)}.md`, (filename) => isTopicBriefFile(filename, topicId), (filename) => isTopicBriefFile(filename, topicId, topicTitle));
15891
- const hasBriefFile = existsSync19(briefFile) && statSync10(briefFile).isFile();
15892
- const latestSummaryCandidate = resolveWikiMirrorPath(join28(wikiDir, "summaries"), `__missing__-${wikiSummaryFilename("0000-00-00", topicTitle, topicId)}`, (filename) => isTopicSummaryFile(filename, topicId), (filename) => isTopicSummaryFile(filename, topicId, topicTitle), false);
15893
- const latestSummaryFile = existsSync19(latestSummaryCandidate) && statSync10(latestSummaryCandidate).isFile() ? latestSummaryCandidate : null;
16039
+ const briefFile = resolveWikiMirrorPath(join29(wikiDir, "topic"), `${wikiBriefStorageKey(topicTitle, topicId)}.md`, (filename) => isTopicBriefFile(filename, topicId), (filename) => isTopicBriefFile(filename, topicId, topicTitle));
16040
+ const hasBriefFile = existsSync20(briefFile) && statSync10(briefFile).isFile();
16041
+ const latestSummaryCandidate = resolveWikiMirrorPath(join29(wikiDir, "summaries"), `__missing__-${wikiSummaryFilename("0000-00-00", topicTitle, topicId)}`, (filename) => isTopicSummaryFile(filename, topicId), (filename) => isTopicSummaryFile(filename, topicId, topicTitle), false);
16042
+ const latestSummaryFile = existsSync20(latestSummaryCandidate) && statSync10(latestSummaryCandidate).isFile() ? latestSummaryCandidate : null;
15894
16043
  return { briefFile, hasBriefFile, latestSummaryFile };
15895
16044
  }
15896
16045
  async function streamAgentEvents(topicId, topicTitle, queryId, events, control, agentType, model, effort, userId, retryableSessionExpired = true, onSessionId, execution) {
@@ -17924,8 +18073,8 @@ init_common();
17924
18073
  import { z as z2 } from "zod";
17925
18074
 
17926
18075
  // ../../packages/core/src/agents/mcp-tools/inline-assets.ts
17927
- import { existsSync as existsSync16, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
17928
- import { extname, isAbsolute as isAbsolute3, resolve as resolve11 } from "path";
18076
+ import { existsSync as existsSync17, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
18077
+ import { extname, isAbsolute as isAbsolute3, resolve as resolve12 } from "path";
17929
18078
  var MIME_BY_EXT = {
17930
18079
  ".apng": "image/apng",
17931
18080
  ".avif": "image/avif",
@@ -17970,10 +18119,10 @@ function inlineLocalAssets(html, options) {
17970
18119
  const relPath = stripSuffix(ref);
17971
18120
  if (!relPath)
17972
18121
  return null;
17973
- const abs = isAbsolute3(relPath) ? relPath : resolve11(baseDir, relPath);
18122
+ const abs = isAbsolute3(relPath) ? relPath : resolve12(baseDir, relPath);
17974
18123
  let bytes;
17975
18124
  try {
17976
- if (!existsSync16(abs) || !statSync7(abs).isFile()) {
18125
+ if (!existsSync17(abs) || !statSync7(abs).isFile()) {
17977
18126
  unresolved.push(ref);
17978
18127
  cache.set(ref, null);
17979
18128
  return null;
@@ -18930,7 +19079,6 @@ var otiumVisualToolDefinitions = [
18930
19079
  await init_task_events();
18931
19080
  init_tool_format();
18932
19081
  await init_topic_cleanup();
18933
- init_vault_tool_policy();
18934
19082
  export {
18935
19083
  withTaskSnapshots,
18936
19084
  withCodexSpawnSerial,
@@ -18945,23 +19093,19 @@ export {
18945
19093
  showMermaidTool,
18946
19094
  showImageTool,
18947
19095
  showHtmlTool,
18948
- shouldRedirectVaultTool,
18949
19096
  rotateTopicLogs,
18950
19097
  resolveTaskEventScope,
18951
19098
  registerOwnedCodexPids,
18952
- referencesRuntimeSecretStorage,
18953
19099
  purgeTopicLogs,
18954
19100
  otiumVisualToolDefinitions,
18955
19101
  normalizeAskUserQuestionInput,
18956
19102
  normalizeAskUserChoices,
18957
19103
  killOwnedCodexTreesForShutdown,
18958
19104
  killCodexTrees,
18959
- isVaultBrokerTool,
18960
19105
  formatToolUse,
18961
19106
  forkAgentSession,
18962
19107
  findNewCodexChildren,
18963
19108
  defaultAskUserDurabilityHost,
18964
- createVaultToolPolicy,
18965
19109
  createTopicLogMaintenance,
18966
19110
  createSubagentLifecycle,
18967
19111
  createSelfConfigToolDefinitionsForCore,
@@ -18982,9 +19126,8 @@ export {
18982
19126
  archiveActiveTopicForMemory,
18983
19127
  acquireCodexSpawnLock,
18984
19128
  VISUALS_MCP_KEY,
18985
- VAULT_BROKER_REDIRECT_ERROR,
18986
19129
  MIN_MEMORY_ARCHIVE_EXCHANGES,
18987
19130
  DEFAULT_SELF_CONFIG_PRODUCT
18988
19131
  };
18989
19132
 
18990
- //# debugId=7AE75D5760B13E7D64756E2164756E21
19133
+ //# debugId=0F776DB92A8B6B8F64756E2164756E21