negotium 0.6.13 → 0.6.17

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 (31) hide show
  1. package/dist/agent-helpers.js +760 -142
  2. package/dist/agent-helpers.js.map +13 -12
  3. package/dist/{chunk-sr48tc2c.js → chunk-ax6tqx0s.js} +2 -2
  4. package/dist/{chunk-sr48tc2c.js.map → chunk-ax6tqx0s.js.map} +2 -2
  5. package/dist/hosted-agent.js +64 -3
  6. package/dist/hosted-agent.js.map +4 -4
  7. package/dist/main.js +783 -297
  8. package/dist/main.js.map +18 -17
  9. package/dist/mcp-factories.js +850 -261
  10. package/dist/mcp-factories.js.map +13 -12
  11. package/dist/registry.js +1 -1
  12. package/dist/runtime/cron/background-sessions.ts +5 -2
  13. package/dist/runtime/src/agents/archiver.ts +8 -5
  14. package/dist/runtime/src/agents/claude-provider.ts +88 -1
  15. package/dist/runtime/src/agents/idle-compact.ts +178 -0
  16. package/dist/runtime/src/node-host.ts +8 -1
  17. package/dist/runtime/src/runtime/background-sessions.ts +21 -8
  18. package/dist/runtime/src/runtime/turn-event-stream.ts +54 -1
  19. package/dist/runtime/src/runtime/turn-runner.ts +63 -0
  20. package/dist/runtime/src/topics/lifecycle.ts +2 -0
  21. package/dist/runtime/src/topics/session.ts +60 -3
  22. package/dist/runtime/src/version.ts +1 -1
  23. package/dist/types/packages/core/src/agents/archiver.d.ts +2 -2
  24. package/dist/types/packages/core/src/agents/idle-compact.d.ts +28 -0
  25. package/dist/types/packages/core/src/runtime/background-sessions.d.ts +10 -2
  26. package/dist/types/packages/core/src/runtime/turn-event-stream.d.ts +14 -0
  27. package/dist/types/packages/core/src/runtime/turn-runner.d.ts +2 -0
  28. package/dist/types/packages/core/src/topics/session.d.ts +11 -0
  29. package/dist/types/packages/core/src/version.d.ts +1 -1
  30. package/dist/types/packages/module-cron/src/background-sessions.d.ts +1 -1
  31. package/package.json +1 -1
@@ -23,7 +23,7 @@ import { createRequire } from "module";
23
23
  import { dirname, join } from "path";
24
24
 
25
25
  // ../../packages/core/src/version.ts
26
- var NEGOTIUM_VERSION = "0.6.13";
26
+ var NEGOTIUM_VERSION = "0.6.17";
27
27
 
28
28
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
29
29
  var moduleRequire = createRequire(import.meta.url);
@@ -157,4 +157,4 @@ export {
157
157
  createCodexAppServerForker
158
158
  };
159
159
 
160
- //# debugId=D4006ACCD3AA80F364756E2164756E21
160
+ //# debugId=8D1F66EA2DA501DB64756E2164756E21
@@ -4,9 +4,9 @@
4
4
  "sourcesContent": [
5
5
  "import { type ChildProcessWithoutNullStreams, spawn } from \"node:child_process\";\nimport { codexCliScriptPath } from \"#agents/codex-native-multi-agent\";\nimport { hostedCodexHomePath } from \"#agents/execution-host\";\nimport { latestCodexRolloutPath } from \"#agents/rollout/codex\";\nimport { NEGOTIUM_VERSION } from \"#version\";\n\ninterface CodexAppServerForkResult {\n forkId: string;\n rolloutPath: string;\n}\n\ninterface CodexAppServerForkHost {\n spawnServer(): ChildProcessWithoutNullStreams;\n findRolloutPath(threadId: string): string | undefined;\n timeoutMs: number;\n}\n\ntype JsonRpcResponse = {\n id?: number;\n result?: { thread?: { id?: unknown } };\n error?: { message?: unknown };\n};\n\nexport function createCodexAppServerForker(host: CodexAppServerForkHost) {\n return async (parentThreadId: string): Promise<CodexAppServerForkResult> => {\n const child = host.spawnServer();\n\n return await new Promise<CodexAppServerForkResult>((resolve, reject) => {\n let settled = false;\n let stdoutBuffer = \"\";\n let stderr = \"\";\n const timer = setTimeout(\n () => finish(new Error(\"Codex thread fork timed out\")),\n host.timeoutMs,\n );\n\n const finish = (error?: Error, result?: CodexAppServerForkResult) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n try {\n child.stdin.end();\n child.kill();\n } catch {\n // The app server may already have exited after stdin closed.\n }\n if (error) reject(error);\n else if (result) resolve(result);\n else reject(new Error(\"Codex thread fork returned no result\"));\n };\n\n const send = (message: Record<string, unknown>) => {\n child.stdin.write(`${JSON.stringify(message)}\\n`);\n };\n\n child.stderr.on(\"data\", (chunk) => {\n if (stderr.length < 8_192) stderr += String(chunk);\n });\n child.on(\"error\", (error) => finish(error));\n child.on(\"exit\", (code, signal) => {\n if (settled) return;\n const detail = signal ? `signal ${signal}` : `code ${code ?? 1}`;\n finish(\n new Error(\n `Codex app server exited with ${detail}${stderr.trim() ? `: ${stderr.trim()}` : \"\"}`,\n ),\n );\n });\n child.stdout.on(\"data\", (chunk) => {\n stdoutBuffer += String(chunk);\n for (;;) {\n const newline = stdoutBuffer.indexOf(\"\\n\");\n if (newline < 0) break;\n const line = stdoutBuffer.slice(0, newline);\n stdoutBuffer = stdoutBuffer.slice(newline + 1);\n let message: JsonRpcResponse;\n try {\n message = JSON.parse(line) as JsonRpcResponse;\n } catch {\n continue;\n }\n\n if (message.id === 1) {\n if (message.error) {\n finish(new Error(String(message.error.message || \"Codex initialization failed\")));\n return;\n }\n send({ method: \"initialized\" });\n send({ id: 2, method: \"thread/fork\", params: { threadId: parentThreadId } });\n continue;\n }\n if (message.id !== 2) continue;\n if (message.error) {\n finish(new Error(String(message.error.message || \"Codex thread fork failed\")));\n return;\n }\n const forkId = message.result?.thread?.id;\n if (typeof forkId !== \"string\" || !forkId) {\n finish(new Error(\"Codex thread fork returned no thread id\"));\n return;\n }\n const rolloutPath = host.findRolloutPath(forkId);\n if (!rolloutPath) {\n finish(new Error(`Codex thread fork rollout was not found for ${forkId}`));\n return;\n }\n finish(undefined, { forkId, rolloutPath });\n return;\n }\n });\n\n send({\n id: 1,\n method: \"initialize\",\n params: {\n clientInfo: { name: \"negotium\", version: NEGOTIUM_VERSION },\n },\n });\n });\n };\n}\n\nconst forkCodexThread = createCodexAppServerForker({\n spawnServer() {\n return spawn(process.execPath, [codexCliScriptPath(), \"app-server\", \"--stdio\"], {\n env: { ...process.env, CODEX_HOME: hostedCodexHomePath() },\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n },\n findRolloutPath: latestCodexRolloutPath,\n timeoutMs: 15_000,\n});\n\nexport async function forkCodexSession(parentThreadId: string): Promise<CodexAppServerForkResult> {\n return await forkCodexThread(parentThreadId);\n}\n",
6
6
  "import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n mkdtempSync,\n readFileSync,\n renameSync,\n rmSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { NEGOTIUM_VERSION } from \"#version\";\n\ntype CodexModel = Record<string, unknown>;\ntype CodexModelCache = {\n client_version?: unknown;\n models?: unknown;\n};\n\nconst moduleRequire = createRequire(import.meta.url);\nconst codexSdkPackagePath = moduleRequire.resolve(\"@openai/codex-sdk/package.json\");\nconst codexSdkRequire = createRequire(codexSdkPackagePath);\nconst bundledCodexPackagePath = codexSdkRequire.resolve(\"@openai/codex/package.json\");\n\nfunction readPackageVersion(packageJsonPath: string): string {\n const parsed = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { version?: unknown };\n if (typeof parsed.version !== \"string\" || !parsed.version.trim()) {\n throw new Error(`Codex package has no valid version: ${packageJsonPath}`);\n }\n return parsed.version;\n}\n\nexport const BUNDLED_CODEX_VERSION = readPackageVersion(bundledCodexPackagePath);\nconst SAFE_BUNDLED_CODEX_VERSION = BUNDLED_CODEX_VERSION.replace(/[^a-zA-Z0-9._-]/g, \"_\");\nconst NEGOTIUM_MODEL_CACHE = `negotium-models-cache-${SAFE_BUNDLED_CODEX_VERSION}.json`;\nconst NEGOTIUM_MODEL_CATALOG = `negotium-model-catalog-${SAFE_BUNDLED_CODEX_VERSION}.json`;\n\nexport function codexCliScriptPath(): string {\n return join(dirname(bundledCodexPackagePath), \"bin\", \"codex.js\");\n}\n\nfunction parseCodexModelCache(contents: string, sourcePath: string): CodexModelCache {\n let parsed: CodexModelCache;\n try {\n parsed = JSON.parse(contents) as CodexModelCache;\n } catch (error) {\n throw new Error(`Codex model cache is invalid JSON: ${sourcePath}`, { cause: error });\n }\n if (!Array.isArray(parsed.models) || parsed.models.length === 0) {\n throw new Error(`Codex model cache has no models: ${sourcePath}`);\n }\n return parsed;\n}\n\nfunction readCodexModelCache(cachePath: string): {\n contents: string;\n parsed: CodexModelCache;\n} {\n const contents = readFileSync(cachePath, \"utf8\");\n return { contents, parsed: parseCodexModelCache(contents, cachePath) };\n}\n\nfunction readCompatibleCodexModelCache(cachePath: string): {\n contents: string;\n parsed: CodexModelCache;\n} {\n const cache = readCodexModelCache(cachePath);\n if (cache.parsed.client_version !== BUNDLED_CODEX_VERSION) {\n const found =\n typeof cache.parsed.client_version === \"string\"\n ? cache.parsed.client_version\n : \"missing or invalid\";\n throw new Error(\n `Codex model cache version ${found} does not match Negotium's bundled Codex ${BUNDLED_CODEX_VERSION}: ${cachePath}`,\n );\n }\n return cache;\n}\n\nfunction writePrivateFileAtomic(path: string, contents: string): void {\n if (existsSync(path) && readFileSync(path, \"utf8\") === contents) return;\n\n const tempPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeFileSync(tempPath, contents, { encoding: \"utf8\", mode: 0o600 });\n renameSync(tempPath, path);\n chmodSync(path, 0o600);\n } finally {\n try {\n unlinkSync(tempPath);\n } catch {\n // renameSync normally consumed the temporary file.\n }\n }\n}\n\nexport function bundledCodexModelCachePath(authFilePath: string): string {\n return join(dirname(authFilePath), NEGOTIUM_MODEL_CACHE);\n}\n\nasync function bootstrapCodexModelCache(codexHome: string, cachePath: string): Promise<void> {\n const child = spawn(process.execPath, [codexCliScriptPath(), \"app-server\", \"--stdio\"], {\n env: { ...process.env, CODEX_HOME: codexHome },\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n let stdoutBuffer = \"\";\n let stderr = \"\";\n const timer = setTimeout(\n () => finish(new Error(\"timed out while refreshing the Codex model catalog\")),\n 15_000,\n );\n\n const finish = (error?: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n try {\n child.stdin.end();\n child.kill();\n } catch {\n // The app server may already have exited after stdin closed.\n }\n if (error) reject(error);\n else if (!existsSync(cachePath)) reject(new Error(\"Codex did not create its model cache\"));\n else resolve();\n };\n\n const send = (message: Record<string, unknown>) => {\n child.stdin.write(`${JSON.stringify(message)}\\n`);\n };\n\n child.stderr.on(\"data\", (chunk) => {\n if (stderr.length < 4_096) stderr += String(chunk);\n });\n child.on(\"error\", (error) => finish(error));\n child.on(\"exit\", (code, signal) => {\n if (!settled) {\n finish(\n new Error(\n `Codex model catalog refresh exited with ${signal ? `signal ${signal}` : `code ${code ?? 1}`}${stderr.trim() ? `: ${stderr.trim()}` : \"\"}`,\n ),\n );\n }\n });\n child.stdout.on(\"data\", (chunk) => {\n stdoutBuffer += String(chunk);\n for (;;) {\n const newline = stdoutBuffer.indexOf(\"\\n\");\n if (newline < 0) break;\n const line = stdoutBuffer.slice(0, newline);\n stdoutBuffer = stdoutBuffer.slice(newline + 1);\n let message: { id?: number; error?: { message?: string } };\n try {\n message = JSON.parse(line) as typeof message;\n } catch {\n continue;\n }\n if (message.id === 1) {\n if (message.error) {\n finish(new Error(message.error.message || \"Codex initialization failed\"));\n return;\n }\n send({ method: \"initialized\" });\n send({ id: 2, method: \"model/list\", params: { includeHidden: true } });\n } else if (message.id === 2) {\n if (message.error) {\n finish(new Error(message.error.message || \"Codex model listing failed\"));\n } else {\n finish();\n }\n return;\n }\n }\n });\n\n send({\n id: 1,\n method: \"initialize\",\n params: {\n clientInfo: { name: \"negotium\", version: NEGOTIUM_VERSION },\n capabilities: { experimentalApi: true },\n },\n });\n });\n}\n\nasync function bootstrapIsolatedCodexModelCache(\n authFilePath: string,\n bootstrap: (codexHome: string, cachePath: string) => Promise<void>,\n): Promise<string> {\n const sourceHome = dirname(authFilePath);\n const isolatedHome = mkdtempSync(join(tmpdir(), \"negotium-codex-models-\"));\n const isolatedCachePath = join(isolatedHome, \"models_cache.json\");\n\n try {\n const isolatedAuthPath = join(isolatedHome, \"auth.json\");\n copyFileSync(authFilePath, isolatedAuthPath);\n chmodSync(isolatedAuthPath, 0o600);\n\n // Preserve custom provider configuration while keeping the bundled CLI's\n // cache write completely outside the user's shared CODEX_HOME.\n const sourceConfigPath = join(sourceHome, \"config.toml\");\n if (existsSync(sourceConfigPath)) {\n const isolatedConfigPath = join(isolatedHome, \"config.toml\");\n copyFileSync(sourceConfigPath, isolatedConfigPath);\n chmodSync(isolatedConfigPath, 0o600);\n }\n\n await bootstrap(isolatedHome, isolatedCachePath);\n return readCompatibleCodexModelCache(isolatedCachePath).contents;\n } finally {\n rmSync(isolatedHome, { recursive: true, force: true });\n }\n}\n\nexport async function ensureCodexModelCache(\n authFilePath: string,\n bootstrap: (codexHome: string, cachePath: string) => Promise<void> = bootstrapCodexModelCache,\n): Promise<string> {\n const codexHome = dirname(authFilePath);\n const configuredCachePath = process.env.NEGOTIUM_CODEX_MODELS_CACHE_FILE;\n if (configuredCachePath) {\n if (!existsSync(configuredCachePath)) {\n throw new Error(`Configured Codex model cache does not exist: ${configuredCachePath}`);\n }\n readCompatibleCodexModelCache(configuredCachePath);\n return configuredCachePath;\n }\n\n // The global Codex CLI owns models_cache.json and may update it to a schema\n // newer than the SDK bundled by Negotium. Snapshot a cache generated for our\n // exact bundled version so later global CLI updates cannot break turns.\n const bundledCachePath = bundledCodexModelCachePath(authFilePath);\n const sharedCachePath = join(codexHome, \"models_cache.json\");\n if (existsSync(sharedCachePath)) {\n try {\n const shared = readCompatibleCodexModelCache(sharedCachePath);\n // Keep model metadata fresh while the global CLI remains compatible.\n writePrivateFileAtomic(bundledCachePath, shared.contents);\n return bundledCachePath;\n } catch {\n // A compatible private snapshot is safer than failing because another\n // process briefly exposed an incomplete shared-cache write.\n }\n }\n\n if (existsSync(bundledCachePath)) {\n try {\n readCompatibleCodexModelCache(bundledCachePath);\n return bundledCachePath;\n } catch {\n // Re-bootstrap below instead of passing a corrupt or version-mismatched\n // private snapshot into this SDK version.\n }\n }\n\n const refreshedContents = await bootstrapIsolatedCodexModelCache(authFilePath, bootstrap);\n writePrivateFileAtomic(bundledCachePath, refreshedContents);\n return bundledCachePath;\n}\n\n/**\n * Codex can resolve model metadata before `features.multi_agent=false`, so a\n * model-advertised v1/v2 value may still register native collaboration tools.\n * Feed Codex an authoritative copy of its own catalog with only that field\n * disabled. Runtime MCP delegation remains available independently.\n */\nexport function writeCodexCatalogWithNativeMultiAgentDisabled(\n authFilePath: string,\n sourcePath: string,\n): string {\n const codexHome = dirname(authFilePath);\n const outputPath = join(codexHome, NEGOTIUM_MODEL_CATALOG);\n\n const parsed = readCodexModelCache(sourcePath).parsed;\n\n const models = (parsed.models as unknown[]).map((model, index): CodexModel => {\n if (!model || typeof model !== \"object\" || Array.isArray(model)) {\n throw new Error(`Codex model cache entry ${index} is invalid: ${sourcePath}`);\n }\n return { ...(model as CodexModel), multi_agent_version: \"disabled\" };\n });\n const contents = `${JSON.stringify({ models }, null, 2)}\\n`;\n writePrivateFileAtomic(outputPath, contents);\n return outputPath;\n}\n",
7
- "export const NEGOTIUM_VERSION = \"0.6.13\";\n"
7
+ "export const NEGOTIUM_VERSION = \"0.6.17\";\n"
8
8
  ],
9
9
  "mappings": "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",
10
- "debugId": "D4006ACCD3AA80F364756E2164756E21",
10
+ "debugId": "8D1F66EA2DA501DB64756E2164756E21",
11
11
  "names": []
12
12
  }
@@ -1941,6 +1941,7 @@ var CLAUDE_DEFAULT_DISALLOWED_TOOLS = [
1941
1941
  "TaskUpdate",
1942
1942
  "TaskList",
1943
1943
  "TaskGet",
1944
+ "Monitor",
1944
1945
  "ScheduleWakeup",
1945
1946
  "CronCreate",
1946
1947
  "CronList",
@@ -2029,6 +2030,36 @@ function buildClaudePrompt(opts) {
2029
2030
  });
2030
2031
  }
2031
2032
  var CLAUDE_ABORT_SIGKILL_DELAY_MS = 2500;
2033
+ var claudeProcessExitListeners = new WeakMap;
2034
+ function watchClaudeProcessExit(signal) {
2035
+ let listener;
2036
+ const exited = new Promise((resolve5) => {
2037
+ listener = resolve5;
2038
+ const listeners = claudeProcessExitListeners.get(signal) ?? new Set;
2039
+ listeners.add(listener);
2040
+ claudeProcessExitListeners.set(signal, listeners);
2041
+ });
2042
+ return {
2043
+ exited,
2044
+ dispose: () => {
2045
+ if (!listener)
2046
+ return;
2047
+ const listeners = claudeProcessExitListeners.get(signal);
2048
+ listeners?.delete(listener);
2049
+ if (listeners?.size === 0)
2050
+ claudeProcessExitListeners.delete(signal);
2051
+ listener = undefined;
2052
+ }
2053
+ };
2054
+ }
2055
+ function notifyClaudeProcessExit(signal, exit) {
2056
+ const listeners = claudeProcessExitListeners.get(signal);
2057
+ if (!listeners)
2058
+ return;
2059
+ claudeProcessExitListeners.delete(signal);
2060
+ for (const listener of listeners)
2061
+ listener(exit);
2062
+ }
2032
2063
  function signalProcessTree(pid, signal) {
2033
2064
  try {
2034
2065
  process.kill(-pid, signal);
@@ -2090,6 +2121,7 @@ function spawnClaudeCodeProcessWithTreeKill(options) {
2090
2121
  clearKillTimer();
2091
2122
  options.signal.removeEventListener("abort", onAbort);
2092
2123
  logger.debug({ pid: child.pid, code, signal }, "Claude Code process exited");
2124
+ notifyClaudeProcessExit(options.signal, { code, signal });
2093
2125
  });
2094
2126
  child.once("error", (err) => {
2095
2127
  exited = true;
@@ -2100,6 +2132,7 @@ function spawnClaudeCodeProcessWithTreeKill(options) {
2100
2132
  command: options.command,
2101
2133
  err: err instanceof Error ? err.message : String(err)
2102
2134
  }, "Claude Code process error event");
2135
+ notifyClaudeProcessExit(options.signal, { code: null, signal: null });
2103
2136
  });
2104
2137
  return {
2105
2138
  stdin: child.stdin,
@@ -2147,6 +2180,20 @@ async function* claudeProvider(opts) {
2147
2180
  delete cleanEnv.CLAUDECODE;
2148
2181
  cleanEnv.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT ??= "300000";
2149
2182
  cleanEnv.CLAUDE_CODE_DISABLE_WORKFLOWS = "1";
2183
+ const sdkAbortController = new AbortController;
2184
+ const onCallerAbort = () => sdkAbortController.abort();
2185
+ if (opts.abortController?.signal.aborted)
2186
+ sdkAbortController.abort();
2187
+ else
2188
+ opts.abortController?.signal.addEventListener("abort", onCallerAbort, { once: true });
2189
+ const processExitWatch = watchClaudeProcessExit(sdkAbortController.signal);
2190
+ let unexpectedProcessExit;
2191
+ processExitWatch.exited.then((exit) => {
2192
+ if (opts.abortController?.signal.aborted)
2193
+ return;
2194
+ unexpectedProcessExit = exit;
2195
+ sdkAbortController.abort();
2196
+ });
2150
2197
  const queryOptions = {
2151
2198
  ...claudeExecutable ? { pathToClaudeCodeExecutable: claudeExecutable } : {},
2152
2199
  spawnClaudeCodeProcess: spawnClaudeCodeProcessWithTreeKill,
@@ -2157,7 +2204,7 @@ async function* claudeProvider(opts) {
2157
2204
  env: cleanEnv,
2158
2205
  mcpServers: hostedMcpServers(opts),
2159
2206
  ...claudeBuiltInTools(opts) ? { tools: claudeBuiltInTools(opts) } : {},
2160
- abortController: opts.abortController,
2207
+ abortController: sdkAbortController,
2161
2208
  disallowedTools: buildClaudeDisallowedTools(opts.disallowedTools),
2162
2209
  ...opts.model ? { model: opts.model } : {},
2163
2210
  ...opts.maxBudgetUsd ? { maxBudgetUsd: opts.maxBudgetUsd } : {},
@@ -2395,11 +2442,25 @@ async function* claudeProvider(opts) {
2395
2442
  }
2396
2443
  }
2397
2444
  }
2445
+ if (unexpectedProcessExit) {
2446
+ const detail = unexpectedProcessExit.signal ? `signal ${unexpectedProcessExit.signal}` : unexpectedProcessExit.code === null ? "before it could start" : `exit code ${unexpectedProcessExit.code}`;
2447
+ logger.error({ detail }, "claudeProvider: CLI exited before terminal SDK event");
2448
+ yield { type: "error", content: `Claude CLI exited unexpectedly (${detail}).` };
2449
+ }
2398
2450
  } catch (e) {
2451
+ if (unexpectedProcessExit) {
2452
+ const detail = unexpectedProcessExit.signal ? `signal ${unexpectedProcessExit.signal}` : unexpectedProcessExit.code === null ? "before it could start" : `exit code ${unexpectedProcessExit.code}`;
2453
+ logger.error({ err: e, detail }, "claudeProvider: CLI exited before terminal SDK event");
2454
+ yield { type: "error", content: `Claude CLI exited unexpectedly (${detail}).` };
2455
+ return;
2456
+ }
2399
2457
  if (isAbortError(e) || opts.abortController?.signal.aborted)
2400
2458
  return;
2401
2459
  logger.error({ err: e }, "claudeProvider: SDK iteration failed");
2402
2460
  yield { type: "error", content: errMsg(e) };
2461
+ } finally {
2462
+ processExitWatch.dispose();
2463
+ opts.abortController?.signal.removeEventListener("abort", onCallerAbort);
2403
2464
  }
2404
2465
  }
2405
2466
 
@@ -2429,7 +2490,7 @@ import { tmpdir } from "os";
2429
2490
  import { dirname as dirname5, join as join4 } from "path";
2430
2491
 
2431
2492
  // ../../packages/core/src/version.ts
2432
- var NEGOTIUM_VERSION = "0.6.13";
2493
+ var NEGOTIUM_VERSION = "0.6.17";
2433
2494
 
2434
2495
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
2435
2496
  var moduleRequire = createRequire2(import.meta.url);
@@ -4265,4 +4326,4 @@ export {
4265
4326
  buildClaudeDisallowedTools
4266
4327
  };
4267
4328
 
4268
- //# debugId=2F5C7E84616556B564756E2164756E21
4329
+ //# debugId=9D98467563F11D8C64756E2164756E21