open-multi-agent-kit 0.95.2 → 0.96.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 (70) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +15 -0
  3. package/dist/approvals/approval-receipt-store.d.ts.map +1 -1
  4. package/dist/approvals/approval-receipt-store.js +25 -0
  5. package/dist/approvals/approval-receipt-store.js.map +1 -1
  6. package/dist/core/agent-session.d.ts +2 -2
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +41 -17
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/provider-resilience.d.ts +7 -0
  11. package/dist/core/provider-resilience.d.ts.map +1 -1
  12. package/dist/core/provider-resilience.js +11 -0
  13. package/dist/core/provider-resilience.js.map +1 -1
  14. package/dist/core/subagent-orchestration.d.ts.map +1 -1
  15. package/dist/core/subagent-orchestration.js +4 -2
  16. package/dist/core/subagent-orchestration.js.map +1 -1
  17. package/dist/core/tools/diagnostics.d.ts.map +1 -1
  18. package/dist/core/tools/diagnostics.js +8 -2
  19. package/dist/core/tools/diagnostics.js.map +1 -1
  20. package/dist/guardrails/evidence-protocol.d.ts +10 -0
  21. package/dist/guardrails/evidence-protocol.d.ts.map +1 -0
  22. package/dist/guardrails/evidence-protocol.js +34 -0
  23. package/dist/guardrails/evidence-protocol.js.map +1 -0
  24. package/dist/guardrails/evidence-system.d.ts +3 -1
  25. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  26. package/dist/guardrails/evidence-system.js +22 -14
  27. package/dist/guardrails/evidence-system.js.map +1 -1
  28. package/dist/guardrails/replay-ledger-lock-owner.d.ts.map +1 -1
  29. package/dist/guardrails/replay-ledger-lock-owner.js +3 -1
  30. package/dist/guardrails/replay-ledger-lock-owner.js.map +1 -1
  31. package/dist/guardrails/replay-payload-hash.d.ts +6 -0
  32. package/dist/guardrails/replay-payload-hash.d.ts.map +1 -0
  33. package/dist/guardrails/replay-payload-hash.js +24 -0
  34. package/dist/guardrails/replay-payload-hash.js.map +1 -0
  35. package/dist/index.d.ts +2 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -0
  38. package/dist/index.js.map +1 -1
  39. package/dist/types/evidence.d.ts +11 -3
  40. package/dist/types/evidence.d.ts.map +1 -1
  41. package/dist/types/evidence.js.map +1 -1
  42. package/docs/book-to-skill.md +79 -0
  43. package/docs/compaction.md +10 -0
  44. package/docs/docs.json +8 -0
  45. package/docs/index.md +3 -0
  46. package/docs/models.md +12 -0
  47. package/docs/provider-resilience.md +37 -56
  48. package/docs/providers.md +4 -0
  49. package/docs/run-protocol.md +72 -0
  50. package/docs/sdk.md +15 -2
  51. package/docs/sessions.md +6 -0
  52. package/docs/settings.md +2 -0
  53. package/docs/skills.md +9 -1
  54. package/docs/usage.md +1 -1
  55. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  56. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  57. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  58. package/examples/extensions/gondolin/package-lock.json +2 -2
  59. package/examples/extensions/gondolin/package.json +1 -1
  60. package/examples/extensions/sandbox/package-lock.json +2 -2
  61. package/examples/extensions/sandbox/package.json +1 -1
  62. package/examples/extensions/with-deps/package-lock.json +2 -2
  63. package/examples/extensions/with-deps/package.json +1 -1
  64. package/npm-shrinkwrap.json +37 -15
  65. package/package.json +8 -5
  66. package/dist/core/context-budget-compressors.d.ts +0 -50
  67. package/dist/core/context-budget-compressors.d.ts.map +0 -1
  68. package/dist/core/context-budget-compressors.js +0 -166
  69. package/dist/core/context-budget-compressors.js.map +0 -1
  70. package/dist/core/extensions/loader.js.bak-sharedjiti-20260812-111246 +0 -553
@@ -50,6 +50,8 @@ import { buildRuntimeProvenance } from "./runtime-provenance.js";
50
50
  import { TurnMetricsSink } from "./turn-metrics.js";
51
51
  /** Values that disable a session-level feature through its environment variable. */
52
52
  const DISABLED_ENV_VALUES = new Set(["0", "false", "off", "disable", "disabled"]);
53
+ const MAX_OVERFLOW_RECOVERY_ATTEMPTS = 2;
54
+ const OVERFLOW_RECOVERY_EMERGENCY_TOKENS = 4_096;
53
55
  function isDisabledEnvValue(value) {
54
56
  return value !== undefined && DISABLED_ENV_VALUES.has(value.trim().toLowerCase());
55
57
  }
@@ -70,7 +72,7 @@ function firstTextContent(result) {
70
72
  import { redactCredentialShapedContent } from "./compaction/transaction.js";
71
73
  import { findExactModelReferenceMatch } from "./model-resolver.js";
72
74
  import { expandPromptTemplate } from "./prompt-templates.js";
73
- import { isContentSafetyStopMessage, isStickySafetyModel, isTransientProviderErrorMessage, pickFailoverCandidate, resolveProviderResilience, stickySafetyBlockMessage, } from "./provider-resilience.js";
75
+ import { isContentSafetyStopMessage, isQuotaExhaustionMessage, isStickySafetyModel, isTransientProviderErrorMessage, pickFailoverCandidate, resolveProviderResilience, stickySafetyBlockMessage, } from "./provider-resilience.js";
74
76
  import { getBiasStepsForCell, parseRouterBiasSnapshot } from "./reasoning-router-bias.js";
75
77
  import { classifyTaskV4, deriveRouterFeedbackFeaturesV4, resolveThinkingLevelV4WithUncertainty, TASK_CLASS_THINKING_LEVELS_V4, } from "./reasoning-router-v4.js";
76
78
  import { redactSensitiveText, redactSensitiveTextForced } from "./redaction.js";
@@ -302,7 +304,7 @@ export class AgentSession {
302
304
  // Compaction state
303
305
  _compactionAbortController = undefined;
304
306
  _autoCompactionAbortController = undefined;
305
- _overflowRecoveryAttempted = false;
307
+ _overflowRecoveryAttempts = 0;
306
308
  _thresholdCompactionEmergency = false;
307
309
  _compactionHysteresisState = createCompactionHysteresisState();
308
310
  // Branch summarization state
@@ -585,12 +587,15 @@ export class AgentSession {
585
587
  if (/stop_reason\s*=\s*(refusal|sensitive)|content\/safety stop|safety stop|provider\.refusal|kind=provider_refusal/i.test(text)) {
586
588
  return { area: "provider", code: "refusal" };
587
589
  }
590
+ // Quota/billing exhaustion is checked BEFORE the generic 401/403 auth
591
+ // patterns: "403 ... usage limit for this billing cycle" is transient per
592
+ // cycle and must fail over, not terminate the turn as an auth error.
593
+ if (isQuotaExhaustionMessage(text) || /rate.?limit|too many requests|429/i.test(text)) {
594
+ return { area: "provider", code: "rate_limit" };
595
+ }
588
596
  if (/auth|unauthori[sz]ed|forbidden|invalid.?api.?key|no api key|401|403|\/login/i.test(text)) {
589
597
  return { area: "provider", code: "auth" };
590
598
  }
591
- if (/rate.?limit|too many requests|429|quota|available balance|billing/i.test(text)) {
592
- return { area: "provider", code: "rate_limit" };
593
- }
594
599
  // Kimi/K3 + OpenAI-compat: orphan tool results after dropped error assistants.
595
600
  // Sanitize-and-retry (transform-messages drops orphans), not a hard tool fatal.
596
601
  if (/tool_call_id\s+is\s+not\s+found|tool_call_id\s+not\s+found|unknown\s+tool_call_id/i.test(text)) {
@@ -609,6 +614,9 @@ export class AgentSession {
609
614
  if (!this.model || /no model|model selected|model is required/i.test(message)) {
610
615
  return { area: "configuration", code: "invalid" };
611
616
  }
617
+ if (isQuotaExhaustionMessage(message)) {
618
+ return { area: "provider", code: "rate_limit" };
619
+ }
612
620
  if (/auth|api key|unauthori[sz]ed|forbidden|401|403|\/login/i.test(message)) {
613
621
  return { area: "provider", code: "auth" };
614
622
  }
@@ -966,7 +974,7 @@ export class AgentSession {
966
974
  // When a user message starts, check if it's from either queue and remove it BEFORE emitting
967
975
  // This ensures the UI sees the updated queue state
968
976
  if (event.type === "message_start" && event.message.role === "user") {
969
- this._overflowRecoveryAttempted = false;
977
+ this._overflowRecoveryAttempts = 0;
970
978
  const messageText = this._getUserMessageText(event.message);
971
979
  if (messageText) {
972
980
  // Check steering queue first
@@ -1017,7 +1025,7 @@ export class AgentSession {
1017
1025
  this._lastAssistantMessage = finalizedEvent.message;
1018
1026
  const assistantMsg = finalizedEvent.message;
1019
1027
  if (assistantMsg.stopReason !== "error") {
1020
- this._overflowRecoveryAttempted = false;
1028
+ this._overflowRecoveryAttempts = 0;
1021
1029
  }
1022
1030
  // Reset retry counter immediately on successful assistant response
1023
1031
  // This prevents accumulation across multiple LLM calls within a turn
@@ -2977,18 +2985,18 @@ export class AgentSession {
2977
2985
  }
2978
2986
  // Case 1: Overflow - LLM returned context overflow error
2979
2987
  if ((sameModel || visionRouteOverflow) && isContextOverflow(assistantMessage, contextWindow)) {
2980
- if (this._overflowRecoveryAttempted) {
2988
+ if (this._overflowRecoveryAttempts >= MAX_OVERFLOW_RECOVERY_ATTEMPTS) {
2981
2989
  this._emit({
2982
2990
  type: "compaction_end",
2983
2991
  reason: "overflow",
2984
2992
  result: undefined,
2985
2993
  aborted: false,
2986
2994
  willRetry: false,
2987
- errorMessage: "Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.",
2995
+ errorMessage: "Context overflow recovery failed after two staged compact-and-retry attempts. Reduce the latest input or switch to a model with a larger effective context window.",
2988
2996
  });
2989
2997
  return false;
2990
2998
  }
2991
- this._overflowRecoveryAttempted = true;
2999
+ this._overflowRecoveryAttempts++;
2992
3000
  // Remove the error message from agent state (it IS saved to session for history,
2993
3001
  // but we don't want it in context for the retry)
2994
3002
  const messages = this.agent.state.messages;
@@ -3026,11 +3034,24 @@ export class AgentSession {
3026
3034
  }
3027
3035
  return false;
3028
3036
  }
3037
+ _overflowCompactionSettings(settings, attempt) {
3038
+ if (attempt < MAX_OVERFLOW_RECOVERY_ATTEMPTS)
3039
+ return settings;
3040
+ return {
3041
+ ...settings,
3042
+ reserveTokens: Math.min(settings.reserveTokens, OVERFLOW_RECOVERY_EMERGENCY_TOKENS),
3043
+ reservedOutputTokens: Math.min(settings.reservedOutputTokens ?? settings.reserveTokens, OVERFLOW_RECOVERY_EMERGENCY_TOKENS),
3044
+ keepRecentTokens: Math.min(settings.keepRecentTokens, OVERFLOW_RECOVERY_EMERGENCY_TOKENS),
3045
+ };
3046
+ }
3029
3047
  /**
3030
3048
  * Internal: Run auto-compaction with events.
3031
3049
  */
3032
3050
  async _runAutoCompaction(reason, willRetry, emergency = reason === "overflow" || this._thresholdCompactionEmergency) {
3033
- const settings = this.settingsManager.getCompactionSettings();
3051
+ const configuredSettings = this.settingsManager.getCompactionSettings();
3052
+ const settings = reason === "overflow"
3053
+ ? this._overflowCompactionSettings(configuredSettings, this._overflowRecoveryAttempts)
3054
+ : configuredSettings;
3034
3055
  this._emit({ type: "compaction_start", reason });
3035
3056
  this._autoCompactionAbortController = new AbortController();
3036
3057
  try {
@@ -3666,9 +3687,6 @@ export class AgentSession {
3666
3687
  // =========================================================================
3667
3688
  // Auto-Retry
3668
3689
  // =========================================================================
3669
- _isNonRetryableProviderLimitError(errorMessage) {
3670
- return /GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(errorMessage);
3671
- }
3672
3690
  /**
3673
3691
  * Check if an error is retryable (overloaded, rate limit, server errors).
3674
3692
  * Context overflow errors are NOT retryable (handled by compaction instead).
@@ -3681,8 +3699,11 @@ export class AgentSession {
3681
3699
  if (isContextOverflow(message, contextWindow))
3682
3700
  return false;
3683
3701
  const err = message.errorMessage;
3684
- if (this._isNonRetryableProviderLimitError(err))
3685
- return false;
3702
+ // Billing/quota exhaustion: useless to retry the same model until the
3703
+ // cycle resets, but the turn may still be saved by failing over to the
3704
+ // next candidate, so let _prepareRetry run its failover path.
3705
+ if (isQuotaExhaustionMessage(err))
3706
+ return true;
3686
3707
  // Shared contract with provider-resilience.ts (Fable safety stop, K3 orphan tool_call_id, terminated).
3687
3708
  return isTransientProviderErrorMessage(err);
3688
3709
  }
@@ -3752,8 +3773,11 @@ export class AgentSession {
3752
3773
  const resilience = resolveProviderResilience(this.settingsManager.getProviderResilienceSettings());
3753
3774
  if (!resilience.autoFailoverOnSafetyStop)
3754
3775
  return undefined;
3755
- if (!isContentSafetyStopMessage(message.errorMessage))
3776
+ // Fire on safety-stop FPs AND on billing/quota exhaustion: both mean the
3777
+ // current model cannot finish this turn and same-model retry is useless.
3778
+ if (!isContentSafetyStopMessage(message.errorMessage) && !isQuotaExhaustionMessage(message.errorMessage)) {
3756
3779
  return undefined;
3780
+ }
3757
3781
  const current = this.model;
3758
3782
  // v10.0-Ω: do NOT gate on isStickySafetyModel(source).
3759
3783
  // claude-opus-5 emits the same stop_reason=refusal FP; same-model retry is useless.