open-multi-agent-kit 0.92.0 → 0.93.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 (116) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +2 -2
  3. package/dist/core/agent-session.d.ts +29 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +81 -14
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/compaction/branch-summarization.d.ts +5 -1
  8. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  9. package/dist/core/compaction/branch-summarization.js +5 -7
  10. package/dist/core/compaction/branch-summarization.js.map +1 -1
  11. package/dist/core/compaction/compaction.d.ts +12 -3
  12. package/dist/core/compaction/compaction.d.ts.map +1 -1
  13. package/dist/core/compaction/compaction.js +28 -15
  14. package/dist/core/compaction/compaction.js.map +1 -1
  15. package/dist/core/extensions/builtin/command-safety-gate.d.ts +8 -0
  16. package/dist/core/extensions/builtin/command-safety-gate.d.ts.map +1 -1
  17. package/dist/core/extensions/builtin/command-safety-gate.js +23 -0
  18. package/dist/core/extensions/builtin/command-safety-gate.js.map +1 -1
  19. package/dist/core/extensions/runner.d.ts.map +1 -1
  20. package/dist/core/extensions/runner.js +4 -0
  21. package/dist/core/extensions/runner.js.map +1 -1
  22. package/dist/core/extensions/types.d.ts +2 -0
  23. package/dist/core/extensions/types.d.ts.map +1 -1
  24. package/dist/core/extensions/types.js.map +1 -1
  25. package/dist/core/keybindings.d.ts +5 -0
  26. package/dist/core/keybindings.d.ts.map +1 -1
  27. package/dist/core/keybindings.js +5 -0
  28. package/dist/core/keybindings.js.map +1 -1
  29. package/dist/core/model-resolver.d.ts +41 -3
  30. package/dist/core/model-resolver.d.ts.map +1 -1
  31. package/dist/core/model-resolver.js +17 -9
  32. package/dist/core/model-resolver.js.map +1 -1
  33. package/dist/core/provider-resilience.d.ts.map +1 -1
  34. package/dist/core/provider-resilience.js +3 -1
  35. package/dist/core/provider-resilience.js.map +1 -1
  36. package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -1
  37. package/dist/core/reasoning-router-v4-weights.js +9 -3
  38. package/dist/core/reasoning-router-v4-weights.js.map +1 -1
  39. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  40. package/dist/core/reasoning-router-v4.js +94 -24
  41. package/dist/core/reasoning-router-v4.js.map +1 -1
  42. package/dist/core/resource-loader.d.ts.map +1 -1
  43. package/dist/core/resource-loader.js +11 -5
  44. package/dist/core/resource-loader.js.map +1 -1
  45. package/dist/core/session-file-compaction.d.ts.map +1 -1
  46. package/dist/core/session-file-compaction.js +39 -5
  47. package/dist/core/session-file-compaction.js.map +1 -1
  48. package/dist/core/session-termination.d.ts.map +1 -1
  49. package/dist/core/session-termination.js +1 -1
  50. package/dist/core/session-termination.js.map +1 -1
  51. package/dist/core/settings-manager.d.ts +3 -0
  52. package/dist/core/settings-manager.d.ts.map +1 -1
  53. package/dist/core/settings-manager.js +8 -0
  54. package/dist/core/settings-manager.js.map +1 -1
  55. package/dist/core/system-prompt.d.ts.map +1 -1
  56. package/dist/core/system-prompt.js +1 -1
  57. package/dist/core/system-prompt.js.map +1 -1
  58. package/dist/core/tools/bash.d.ts +2 -0
  59. package/dist/core/tools/bash.d.ts.map +1 -1
  60. package/dist/core/tools/bash.js +38 -11
  61. package/dist/core/tools/bash.js.map +1 -1
  62. package/dist/modes/interactive/components/control-panel-box.d.ts +27 -0
  63. package/dist/modes/interactive/components/control-panel-box.d.ts.map +1 -1
  64. package/dist/modes/interactive/components/control-panel-box.js +60 -8
  65. package/dist/modes/interactive/components/control-panel-box.js.map +1 -1
  66. package/dist/modes/interactive/components/control-panel-layout.d.ts.map +1 -1
  67. package/dist/modes/interactive/components/control-panel-layout.js +100 -45
  68. package/dist/modes/interactive/components/control-panel-layout.js.map +1 -1
  69. package/dist/modes/interactive/components/control-panel-runtime-status.d.ts +9 -0
  70. package/dist/modes/interactive/components/control-panel-runtime-status.d.ts.map +1 -1
  71. package/dist/modes/interactive/components/control-panel-runtime-status.js +10 -8
  72. package/dist/modes/interactive/components/control-panel-runtime-status.js.map +1 -1
  73. package/dist/modes/interactive/components/control-panel-sparkles.d.ts +5 -0
  74. package/dist/modes/interactive/components/control-panel-sparkles.d.ts.map +1 -1
  75. package/dist/modes/interactive/components/control-panel-sparkles.js +14 -9
  76. package/dist/modes/interactive/components/control-panel-sparkles.js.map +1 -1
  77. package/dist/modes/interactive/components/footer.d.ts +10 -0
  78. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  79. package/dist/modes/interactive/components/footer.js +3 -3
  80. package/dist/modes/interactive/components/footer.js.map +1 -1
  81. package/dist/modes/interactive/components/status-sidebar.d.ts +49 -0
  82. package/dist/modes/interactive/components/status-sidebar.d.ts.map +1 -0
  83. package/dist/modes/interactive/components/status-sidebar.js +253 -0
  84. package/dist/modes/interactive/components/status-sidebar.js.map +1 -0
  85. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  86. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  87. package/dist/modes/interactive/interactive-mode.js +94 -20
  88. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  89. package/dist/modes/interactive/theme/omk-neon-control.json +13 -13
  90. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  91. package/dist/modes/rpc/rpc-mode.js +1 -0
  92. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  93. package/dist/utils/clipboard.d.ts.map +1 -1
  94. package/dist/utils/clipboard.js +19 -8
  95. package/dist/utils/clipboard.js.map +1 -1
  96. package/docs/compaction.md +7 -0
  97. package/docs/docs.json +4 -0
  98. package/docs/environment-variables.md +90 -0
  99. package/docs/index.md +1 -0
  100. package/docs/rpc.md +5 -2
  101. package/docs/settings.md +1 -0
  102. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  103. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  104. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  105. package/examples/extensions/gondolin/package-lock.json +2 -2
  106. package/examples/extensions/gondolin/package.json +1 -1
  107. package/examples/extensions/sandbox/package-lock.json +2 -2
  108. package/examples/extensions/sandbox/package.json +1 -1
  109. package/examples/extensions/subagent/agents.test.ts +86 -0
  110. package/examples/extensions/subagent/agents.ts +18 -4
  111. package/examples/extensions/subagent/capabilities.ts +15 -1
  112. package/examples/extensions/subagent/domain-profiles.ts +272 -0
  113. package/examples/extensions/with-deps/package-lock.json +2 -2
  114. package/examples/extensions/with-deps/package.json +1 -1
  115. package/npm-shrinkwrap.json +15 -15
  116. package/package.json +10 -7
@@ -286,6 +286,9 @@ export class AgentSession {
286
286
  // Retry state
287
287
  _retryAbortController = undefined;
288
288
  _retryAttempt = 0;
289
+ // v10.3-Ω: models that already refused/failed this turn — failover must advance,
290
+ // not re-pick the same candidate (claude-opus-5 → grok → grok → grok loop fix).
291
+ _refusedModels = new Set();
289
292
  // Bash execution state
290
293
  _bashAbortController = undefined;
291
294
  _pendingBashMessages = [];
@@ -927,6 +930,7 @@ export class AgentSession {
927
930
  attempt: this._retryAttempt,
928
931
  });
929
932
  this._retryAttempt = 0;
933
+ this._refusedModels.clear();
930
934
  }
931
935
  }
932
936
  }
@@ -1463,6 +1467,7 @@ export class AgentSession {
1463
1467
  finalError: msg.errorMessage,
1464
1468
  });
1465
1469
  this._retryAttempt = 0;
1470
+ this._refusedModels.clear();
1466
1471
  }
1467
1472
  if (await this._checkCompaction(msg)) {
1468
1473
  return true;
@@ -2743,7 +2748,7 @@ export class AgentSession {
2743
2748
  }
2744
2749
  else {
2745
2750
  // Generate compaction result
2746
- const result = await compact(preparation, compactionModel, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.agent.streamFn);
2751
+ const result = await compact(preparation, compactionModel, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.agent.streamFn, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason: "manual" }));
2747
2752
  summary = result.summary;
2748
2753
  firstKeptEntryId = result.firstKeptEntryId;
2749
2754
  tokensBefore = result.tokensBefore;
@@ -3019,7 +3024,7 @@ export class AgentSession {
3019
3024
  }
3020
3025
  else {
3021
3026
  // Generate compaction result
3022
- const compactResult = await compact(preparation, compactionModel, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this.agent.streamFn);
3027
+ const compactResult = await compact(preparation, compactionModel, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this.agent.streamFn, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }));
3023
3028
  summary = compactResult.summary;
3024
3029
  firstKeptEntryId = compactResult.firstKeptEntryId;
3025
3030
  tokensBefore = compactResult.tokensBefore;
@@ -3050,7 +3055,21 @@ export class AgentSession {
3050
3055
  fromExtension,
3051
3056
  });
3052
3057
  }
3053
- const emitWillRetry = compactionEmitWillRetry(willRetry, this.agent.hasQueuedMessages());
3058
+ // Whether the agent loop will resume after this compaction. Shared by
3059
+ // the compaction_end event (so the TUI flushes its queued messages
3060
+ // correctly) and the return value below.
3061
+ const resumeMessages = this.agent.state.messages;
3062
+ let lastAssistantMsg;
3063
+ for (let i = resumeMessages.length - 1; i >= 0; i--) {
3064
+ const candidate = resumeMessages[i];
3065
+ if (candidate.role === "assistant") {
3066
+ lastAssistantMsg = candidate;
3067
+ break;
3068
+ }
3069
+ }
3070
+ const endedCleanly = lastAssistantMsg?.stopReason === "stop";
3071
+ const willResume = this.agent.hasQueuedMessages() || !endedCleanly;
3072
+ const emitWillRetry = compactionEmitWillRetry(willRetry, willResume);
3054
3073
  this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry: emitWillRetry });
3055
3074
  if (willRetry) {
3056
3075
  const messages = this.agent.state.messages;
@@ -3060,9 +3079,16 @@ export class AgentSession {
3060
3079
  }
3061
3080
  return true;
3062
3081
  }
3063
- // Auto-compaction can complete while follow-up/steering/custom messages are waiting.
3064
- // Continue once so queued messages are delivered.
3065
- return this.agent.hasQueuedMessages();
3082
+ // Resume the agent loop after a successful auto-compaction unless the
3083
+ // agent had already finished cleanly. Previously this returned
3084
+ // `hasQueuedMessages()`, which made the agent stall right after the
3085
+ // purple "Auto-compacting..." indicator whenever no steer/follow-up
3086
+ // messages were queued — even when the last turn was cut off mid-task
3087
+ // (stopReason toolUse/length/error/aborted). Continue in that case so
3088
+ // the task runs to completion on the compacted context. Hysteresis
3089
+ // (disarmed until context drops below rearmRatio) prevents an immediate
3090
+ // re-trigger; a clean "stop" with nothing queued still ends the loop.
3091
+ return willResume;
3066
3092
  }
3067
3093
  catch (error) {
3068
3094
  const errorMessage = error instanceof Error ? error.message : "compaction failed";
@@ -3476,6 +3502,34 @@ export class AgentSession {
3476
3502
  // Shared contract with provider-resilience.ts (Fable safety stop, K3 orphan tool_call_id, terminated).
3477
3503
  return isTransientProviderErrorMessage(err);
3478
3504
  }
3505
+ /**
3506
+ * Retry policy + callbacks shared by compaction and branch-summary summarization calls.
3507
+ * Uses the same `settings.retry` budget/backoff as agent-turn retries so a single transient
3508
+ * stream drop no longer fails the whole operation. `source` carries the context
3509
+ * the TUI needs to render the retry and recreate the underlying indicator.
3510
+ */
3511
+ _summarizationRetryCallbacks(source) {
3512
+ return {
3513
+ onRetryScheduled: (attempt, maxAttempts, delayMs, errorMessage) => {
3514
+ this._emit({
3515
+ type: "summarization_retry_scheduled",
3516
+ attempt,
3517
+ maxAttempts,
3518
+ delayMs,
3519
+ errorMessage,
3520
+ });
3521
+ },
3522
+ onRetryAttemptStart: () => {
3523
+ this._emit({
3524
+ type: "summarization_retry_attempt_start",
3525
+ ...source,
3526
+ });
3527
+ },
3528
+ onRetryFinished: () => {
3529
+ this._emit({ type: "summarization_retry_finished" });
3530
+ },
3531
+ };
3532
+ }
3479
3533
  /**
3480
3534
  * Prepare a retryable error for continuation with exponential backoff.
3481
3535
  * @returns true if the caller should continue the agent, false otherwise
@@ -3504,8 +3558,9 @@ export class AgentSession {
3504
3558
  await this.setModel(next);
3505
3559
  }
3506
3560
  /**
3507
- * Sticky safety models (e.g. claude-fable-5) often false-positive on coding turns.
3508
- * Retrying the same model repeats the refusal — switch via provider-resilience chain first.
3561
+ * Content/safety stops (stop_reason=refusal) are often false positives on coding turns
3562
+ * for Fable AND Claude Opus/Sonnet. Retrying the same model usually reprints the refusal —
3563
+ * switch via provider-resilience chain first. Failover targets still skip sticky models.
3509
3564
  */
3510
3565
  async _maybeFailoverFromSafetyStop(message) {
3511
3566
  const resilience = resolveProviderResilience(this.settingsManager.getProviderResilienceSettings());
@@ -3514,11 +3569,15 @@ export class AgentSession {
3514
3569
  if (!isContentSafetyStopMessage(message.errorMessage))
3515
3570
  return undefined;
3516
3571
  const current = this.model;
3517
- const currentId = message.model || current?.id || "";
3518
- const currentProvider = message.provider || current?.provider || "";
3519
- if (!isStickySafetyModel(currentId, currentProvider))
3520
- return undefined;
3572
+ // v10.0-Ω: do NOT gate on isStickySafetyModel(source).
3573
+ // claude-opus-5 emits the same stop_reason=refusal FP; same-model retry is useless.
3574
+ // v10.3-Ω: mark the model that just refused so we never re-pick it this turn.
3575
+ if (current)
3576
+ this._refusedModels.add(`${current.provider}/${current.id}`);
3521
3577
  const pick = pickFailoverCandidate(resilience.failoverCandidates, current ? { provider: current.provider, id: current.id } : undefined, (c) => {
3578
+ // Skip any model that already refused/failed this turn → advance the chain.
3579
+ if (this._refusedModels.has(`${c.provider}/${c.id}`))
3580
+ return false;
3522
3581
  const next = this._modelRegistry.find(c.provider, c.id);
3523
3582
  return !!next && this._modelRegistry.hasConfiguredAuth(next);
3524
3583
  });
@@ -3532,6 +3591,8 @@ export class AgentSession {
3532
3591
  return `${next.provider}/${next.id}`;
3533
3592
  }
3534
3593
  catch {
3594
+ // setModel failed (auth/guard) — blacklist so next retry advances further.
3595
+ this._refusedModels.add(`${pick.provider}/${pick.id}`);
3535
3596
  return undefined;
3536
3597
  }
3537
3598
  }
@@ -3546,7 +3607,7 @@ export class AgentSession {
3546
3607
  this._retryAttempt--;
3547
3608
  return false;
3548
3609
  }
3549
- // Content/safety stop on Fable: switch model BEFORE delay so the retry is not another Fable refusal.
3610
+ // Content/safety stop (Fable/Opus/Sonnet): switch model BEFORE delay so retry is not same-model refusal.
3550
3611
  const failoverTo = await this._maybeFailoverFromSafetyStop(message);
3551
3612
  // Safety stops are usually immediate false positives — short delay after failover, full backoff otherwise.
3552
3613
  const delayMs = failoverTo
@@ -3576,6 +3637,7 @@ export class AgentSession {
3576
3637
  // Aborted during sleep - emit end event so UI can clean up
3577
3638
  const attempt = this._retryAttempt;
3578
3639
  this._retryAttempt = 0;
3640
+ this._refusedModels.clear();
3579
3641
  this._emit({
3580
3642
  type: "auto_retry_end",
3581
3643
  success: false,
@@ -3662,7 +3724,10 @@ export class AgentSession {
3662
3724
  shellPath,
3663
3725
  sandboxPolicy: this._getBashSandboxPreflight(options?.sandboxPolicy),
3664
3726
  }), {
3665
- onChunk,
3727
+ onChunk: (delta) => {
3728
+ onChunk?.(delta);
3729
+ this._emit({ type: "bash_execution_update", id: options?.id, delta });
3730
+ },
3666
3731
  signal: this._bashAbortController.signal,
3667
3732
  });
3668
3733
  this.recordBashResult(command, result, options);
@@ -3838,6 +3903,8 @@ export class AgentSession {
3838
3903
  replaceInstructions,
3839
3904
  reserveTokens: branchSummarySettings.reserveTokens,
3840
3905
  streamFn: this.agent.streamFn,
3906
+ retry: this.settingsManager.getRetrySettings(),
3907
+ callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
3841
3908
  });
3842
3909
  if (result.aborted) {
3843
3910
  return { cancelled: true, aborted: true };