negotium 0.23.3 → 0.23.4

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 (30) hide show
  1. package/dist/agent-helpers.js +171 -12
  2. package/dist/agent-helpers.js.map +8 -7
  3. package/dist/{chunk-6gt62j1j.js → chunk-ggdwn8d5.js} +3 -3
  4. package/dist/{chunk-6gt62j1j.js.map → chunk-ggdwn8d5.js.map} +2 -2
  5. package/dist/{chunk-9zn0bkc9.js → chunk-jarf6nb2.js} +2 -2
  6. package/dist/{chunk-9zn0bkc9.js.map → chunk-jarf6nb2.js.map} +1 -1
  7. package/dist/{chunk-cez5m5hm.js → chunk-pwafy9bb.js} +1 -1
  8. package/dist/{chunk-q5djsg78.js → chunk-qekt5bnd.js} +1 -1
  9. package/dist/{chunk-6cnpkzkb.js → chunk-vtd5kn4n.js} +1 -1
  10. package/dist/{chunk-6cnpkzkb.js.map → chunk-vtd5kn4n.js.map} +3 -3
  11. package/dist/hosted-agent.js +166 -13
  12. package/dist/hosted-agent.js.map +8 -7
  13. package/dist/main.js +190 -12
  14. package/dist/main.js.map +9 -8
  15. package/dist/mcp-factories.js +171 -12
  16. package/dist/mcp-factories.js.map +8 -7
  17. package/dist/registry.js +3 -3
  18. package/dist/rollout.js +2 -2
  19. package/dist/runtime/src/agents/claude-notices.ts +130 -0
  20. package/dist/runtime/src/agents/claude-provider.ts +9 -11
  21. package/dist/runtime/src/agents/codex-provider.ts +51 -6
  22. package/dist/runtime/src/agents/rollout/codex.ts +58 -0
  23. package/dist/runtime/src/version.ts +1 -1
  24. package/dist/types/packages/core/src/agents/claude-notices.d.ts +15 -0
  25. package/dist/types/packages/core/src/agents/codex-provider.d.ts +6 -0
  26. package/dist/types/packages/core/src/agents/rollout/codex.d.ts +12 -0
  27. package/dist/types/packages/core/src/version.d.ts +1 -1
  28. package/package.json +1 -1
  29. /package/dist/{chunk-cez5m5hm.js.map → chunk-pwafy9bb.js.map} +0 -0
  30. /package/dist/{chunk-q5djsg78.js.map → chunk-qekt5bnd.js.map} +0 -0
@@ -42,7 +42,7 @@ import {
42
42
  logger,
43
43
  resolveFallbackAgent,
44
44
  resolveTopicWorkspaceDir
45
- } from "./chunk-9zn0bkc9.js";
45
+ } from "./chunk-jarf6nb2.js";
46
46
  import {
47
47
  __require
48
48
  } from "./chunk-2mx7fq49.js";
@@ -52,6 +52,93 @@ import { spawn as spawn2 } from "child_process";
52
52
  import { existsSync, readFileSync as readFileSync2 } from "fs";
53
53
  import { query } from "@anthropic-ai/claude-agent-sdk";
54
54
 
55
+ // ../../packages/core/src/agents/claude-notices.ts
56
+ var API_ERROR_TEXT = {
57
+ overloaded: "Claude is overloaded",
58
+ rate_limit: "Claude rate limit hit",
59
+ server_error: "Claude API error",
60
+ unknown: "Claude request failed",
61
+ authentication_failed: "Claude sign-in failed",
62
+ oauth_org_not_allowed: "Organization not allowed for Claude",
63
+ account_on_hold: "Claude account is on hold",
64
+ verification_required: "Claude account needs verification",
65
+ billing_error: "Claude billing issue",
66
+ invalid_request: "Claude rejected the request",
67
+ model_not_found: "Claude model not found",
68
+ max_output_tokens: "Claude reply hit the length limit",
69
+ cloud_credential_error: "Cloud credentials failed"
70
+ };
71
+ var RATE_LIMIT_TEXT = {
72
+ five_hour: "5-hour",
73
+ seven_day: "weekly",
74
+ seven_day_opus: "weekly Opus",
75
+ seven_day_sonnet: "weekly Sonnet",
76
+ seven_day_overage_included: "weekly",
77
+ overage: "extra usage"
78
+ };
79
+ var DENIAL_TEXT = {
80
+ rule: "by a permission rule",
81
+ mode: "by the permission mode",
82
+ classifier: "by the safety check",
83
+ asyncAgent: "for a background agent"
84
+ };
85
+ function modelLabel(id) {
86
+ const match = /^claude-([a-z]+)-(\d+)-(\d+)/.exec(id);
87
+ if (!match)
88
+ return id;
89
+ const [, family = "", major, minor] = match;
90
+ return `${family.charAt(0).toUpperCase()}${family.slice(1)} ${major}.${minor}`;
91
+ }
92
+ var SYSTEM_NOTICES = {
93
+ api_retry: (m) => {
94
+ const reason = m.error_status === null ? "Lost connection to Claude" : API_ERROR_TEXT[m.error] ?? "Claude request failed";
95
+ const delay = Math.round(m.retry_delay_ms / 1000);
96
+ const when = delay > 0 ? `in ${delay}s` : "now";
97
+ return `${reason} \xB7 retrying ${when} (${m.attempt}/${m.max_retries})`;
98
+ },
99
+ model_refusal_fallback: (m) => m.direction === "retry" ? `${modelLabel(m.original_model)} declined \xB7 ${modelLabel(m.fallback_model)} is answering instead` : m.content || undefined,
100
+ model_refusal_no_fallback: (m) => `${modelLabel(m.original_model)} declined this request`,
101
+ permission_denied: (m) => {
102
+ const tool = m.tool_name.split("__").at(-1) || m.tool_name;
103
+ const why = m.decision_reason ? `: ${m.decision_reason}` : ` ${DENIAL_TEXT[m.decision_reason_type ?? ""] ?? ""}`.trimEnd();
104
+ return `${tool} was blocked${why}`;
105
+ },
106
+ informational: (m) => m.prevent_continuation || m.level === "warning" || m.level === "suggestion" ? m.content : undefined,
107
+ mirror_error: (m) => {
108
+ logger.warn({ error: m.error }, "claudeProvider: transcript mirror batch dropped");
109
+ return;
110
+ }
111
+ };
112
+ function rateLimitNotice(m) {
113
+ const { status, rateLimitType } = m.rate_limit_info;
114
+ const limit = rateLimitType ? `${RATE_LIMIT_TEXT[rateLimitType] ?? ""} `.trimStart() : "";
115
+ if (status === "allowed_warning")
116
+ return `Nearing your ${limit}Claude usage limit`;
117
+ if (status === "rejected")
118
+ return `Reached your ${limit}Claude usage limit`;
119
+ return;
120
+ }
121
+ function claudeNoticeStatus(message) {
122
+ try {
123
+ if (message.type === "rate_limit_event")
124
+ return rateLimitNotice(message);
125
+ if (message.type !== "system")
126
+ return;
127
+ const handler = SYSTEM_NOTICES[message.subtype];
128
+ if (!handler) {
129
+ logger.debug({ subtype: message.subtype, msg: message }, "claudeProvider: system message (unhandled subtype)");
130
+ return;
131
+ }
132
+ const status = handler(message);
133
+ if (status)
134
+ logger.warn({ subtype: message.subtype, status }, "claudeProvider: notice");
135
+ return status;
136
+ } catch (err) {
137
+ logger.debug({ err, msg: message }, "claudeProvider: notice mapping failed");
138
+ return;
139
+ }
140
+ }
141
+
55
142
  // ../../packages/core/src/agents/rollout/shared.ts
56
143
  import { resolve as resolve2 } from "path";
57
144
 
@@ -3459,12 +3546,13 @@ async function* claudeProvider(opts) {
3459
3546
  yield { type: "tool_use_summary", summary: m.summary };
3460
3547
  continue;
3461
3548
  }
3462
- if (message.type === "system") {
3463
- const m = message;
3464
- if (m.subtype === "init") {
3465
- yield { type: "session", sessionId: m.session_id };
3549
+ if (message.type === "system" || message.type === "rate_limit_event") {
3550
+ if (message.type === "system" && message.subtype === "init") {
3551
+ yield { type: "session", sessionId: message.session_id };
3466
3552
  } else {
3467
- logger.debug({ subtype: m.subtype, msg: m }, "claudeProvider: system message (unhandled subtype)");
3553
+ const status = claudeNoticeStatus(message);
3554
+ if (status)
3555
+ yield { type: "status", content: status };
3468
3556
  }
3469
3557
  continue;
3470
3558
  }
@@ -3600,7 +3688,7 @@ import { dirname as dirname5, join as join3 } from "path";
3600
3688
  import { fileURLToPath } from "url";
3601
3689
 
3602
3690
  // ../../packages/core/src/version.ts
3603
- var NEGOTIUM_VERSION = "0.23.3";
3691
+ var NEGOTIUM_VERSION = "0.23.4";
3604
3692
 
3605
3693
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
3606
3694
  function findPackageJson(specifier, searchFromDir) {
@@ -4405,7 +4493,7 @@ async function createCodexVaultHookBridge(userId) {
4405
4493
  });
4406
4494
  restrictIpcEndpoint(socketPath);
4407
4495
  if (IS_WINDOWS2) {
4408
- const { BINARIES_DIR } = await import("./chunk-q5djsg78.js");
4496
+ const { BINARIES_DIR } = await import("./chunk-qekt5bnd.js");
4409
4497
  const cached = await ensureCodexWindowsWrapperExe(join5(BINARIES_DIR, "codex-hook-wrapper"));
4410
4498
  await copyFile(cached, wrapperPath);
4411
4499
  await writeFile2(join5(root, "codex-with-hooks.cfg"), [process.execPath, codexCliScriptPath(), socketPath, token].join(`
@@ -4657,6 +4745,49 @@ function extractCodexForkedFromId(jsonl) {
4657
4745
  return;
4658
4746
  }
4659
4747
  }
4748
+ function extractLatestCodexSystemInstructionsTurn(jsonl) {
4749
+ const lines = jsonl.trimEnd().split(`
4750
+ `);
4751
+ for (let index = lines.length - 1;index >= 0; index -= 1) {
4752
+ const line = lines[index] ?? "";
4753
+ if (!line.includes("[System Instructions]"))
4754
+ continue;
4755
+ try {
4756
+ const entry = JSON.parse(line);
4757
+ if (entry.type !== "response_item")
4758
+ continue;
4759
+ if (entry.payload?.type !== "message" || entry.payload.role !== "user")
4760
+ continue;
4761
+ const text = (entry.payload.content ?? []).map((part) => typeof part.text === "string" ? part.text : "").join("");
4762
+ if (text.startsWith(`[System Instructions]
4763
+ `))
4764
+ return text;
4765
+ } catch {}
4766
+ }
4767
+ return;
4768
+ }
4769
+ function codexThreadHasSystemPrompt(threadId, systemPrompt, depth = 0) {
4770
+ const path = latestCodexRolloutPath(threadId);
4771
+ if (!path)
4772
+ return false;
4773
+ try {
4774
+ const jsonl = readFileSync4(path, "utf8");
4775
+ const latest = extractLatestCodexSystemInstructionsTurn(jsonl);
4776
+ if (latest !== undefined) {
4777
+ return latest.startsWith(`[System Instructions]
4778
+ ${systemPrompt}
4779
+
4780
+ `);
4781
+ }
4782
+ if (depth >= 8)
4783
+ return false;
4784
+ const parentId = extractCodexForkedFromId(jsonl);
4785
+ return parentId && parentId !== threadId ? codexThreadHasSystemPrompt(parentId, systemPrompt, depth + 1) : false;
4786
+ } catch (error) {
4787
+ logger.debug({ error, threadId }, "codex system prompt: rollout read failed");
4788
+ return false;
4789
+ }
4790
+ }
4660
4791
  function readLatestCodexTokenTotals(threadId, depth = 0) {
4661
4792
  const path = latestCodexRolloutPath(threadId);
4662
4793
  if (!path)
@@ -4843,6 +4974,14 @@ function buildNumberedDiffSummary(before, after, startLine = 1) {
4843
4974
 
4844
4975
  // ../../packages/core/src/agents/codex-provider.ts
4845
4976
  var CODEX_HOOK_TRUST_BYPASS_NOTICE = "`--dangerously-bypass-hook-trust` is enabled. Enabled hooks may run without review for this invocation.";
4977
+ function codexNoticeStatus(message) {
4978
+ const firstLine = message.trim().split(`
4979
+ `)[0]?.trim() ?? "";
4980
+ const sentence = /^.*?[.!?](?=\s|$)/.exec(firstLine)?.[0] ?? firstLine;
4981
+ if (!sentence)
4982
+ return "Codex notice";
4983
+ return /^codex\b/i.test(sentence) ? sentence : `Codex: ${sentence}`;
4984
+ }
4846
4985
  function sameCodexUsage(usage, total) {
4847
4986
  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;
4848
4987
  }
@@ -5268,8 +5407,7 @@ async function* codexProvider(opts) {
5268
5407
  },
5269
5408
  hooks: vaultHook.hooks,
5270
5409
  model_catalog_json: codexModelCatalogPath,
5271
- mcp_servers: codexMcpServers,
5272
- ...opts.toolPolicy ? { sandbox_permissions: [] } : {}
5410
+ mcp_servers: codexMcpServers
5273
5411
  }
5274
5412
  });
5275
5413
  const threadOptions = {
@@ -5290,7 +5428,7 @@ async function* codexProvider(opts) {
5290
5428
  let currentSessionId = opts.sessionId;
5291
5429
  let usageBaseline = currentSessionId ? readLatestCodexTokenTotals(currentSessionId) : undefined;
5292
5430
  let thread = currentSessionId ? codex.resumeThread(currentSessionId, threadOptions) : codex.startThread(threadOptions);
5293
- let prompt = promptForThread(opts, true);
5431
+ let prompt = promptForThread(opts, !currentSessionId || !opts.systemPrompt || !codexThreadHasSystemPrompt(currentSessionId, opts.systemPrompt));
5294
5432
  let agentTextSoFar = "";
5295
5433
  let currentAgentMessageId;
5296
5434
  let finalText = "";
@@ -5318,6 +5456,8 @@ async function* codexProvider(opts) {
5318
5456
  trackedPids.pids = [];
5319
5457
  let heartbeatTriggered = false;
5320
5458
  let attemptCompleted = false;
5459
+ let turnFailed = false;
5460
+ let streamError;
5321
5461
  let heartbeatTimer = null;
5322
5462
  const scheduleHeartbeat = () => {
5323
5463
  if (heartbeatTimer !== null)
@@ -5446,7 +5586,8 @@ async function* codexProvider(opts) {
5446
5586
  } else if (item.type === "error") {
5447
5587
  const message = String(item.message ?? "");
5448
5588
  if (message !== CODEX_HOOK_TRUST_BYPASS_NOTICE) {
5449
- yield { type: "error", content: message };
5589
+ logger.warn({ message }, "codexProvider: codex non-fatal error item");
5590
+ yield { type: "status", content: codexNoticeStatus(message) };
5450
5591
  }
5451
5592
  }
5452
5593
  break;
@@ -5474,7 +5615,15 @@ async function* codexProvider(opts) {
5474
5615
  yield* extractFileEvents(finalText, "result");
5475
5616
  break;
5476
5617
  }
5618
+ case "error": {
5619
+ const message = event.message || "Codex stream error";
5620
+ logger.warn({ message }, "codexProvider: codex stream error event");
5621
+ streamError = message;
5622
+ yield { type: "status", content: codexNoticeStatus(message) };
5623
+ break;
5624
+ }
5477
5625
  case "turn.failed": {
5626
+ turnFailed = true;
5478
5627
  stopReason = "error";
5479
5628
  yield {
5480
5629
  type: "error",
@@ -5486,6 +5635,10 @@ async function* codexProvider(opts) {
5486
5635
  break;
5487
5636
  }
5488
5637
  }
5638
+ if (!attemptCompleted && !turnFailed && streamError) {
5639
+ stopReason = "error";
5640
+ yield { type: "error", content: streamError };
5641
+ }
5489
5642
  } catch (err) {
5490
5643
  if (abortSignal?.aborted)
5491
5644
  return;
@@ -5738,4 +5891,4 @@ export {
5738
5891
  buildClaudeDisallowedTools
5739
5892
  };
5740
5893
 
5741
- //# debugId=E09EB735E1E552E264756E2164756E21
5894
+ //# debugId=0B04340869E81C4364756E2164756E21