open-multi-agent-kit 0.97.0 → 0.98.1

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 (261) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/README.md +41 -9
  3. package/dist/cli/args.d.ts +2 -3
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +13 -189
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/help.d.ts +3 -0
  8. package/dist/cli/help.d.ts.map +1 -0
  9. package/dist/cli/help.js +194 -0
  10. package/dist/cli/help.js.map +1 -0
  11. package/dist/cli/initial-message.d.ts.map +1 -1
  12. package/dist/cli/initial-message.js +2 -1
  13. package/dist/cli/initial-message.js.map +1 -1
  14. package/dist/cli/resource-paths.d.ts +4 -0
  15. package/dist/cli/resource-paths.d.ts.map +1 -0
  16. package/dist/cli/resource-paths.js +59 -0
  17. package/dist/cli/resource-paths.js.map +1 -0
  18. package/dist/commands/adaptorch-doctor-cli.d.ts +13 -0
  19. package/dist/commands/adaptorch-doctor-cli.d.ts.map +1 -0
  20. package/dist/commands/adaptorch-doctor-cli.js +115 -0
  21. package/dist/commands/adaptorch-doctor-cli.js.map +1 -0
  22. package/dist/commands/resource-doctor-cli.d.ts +4 -0
  23. package/dist/commands/resource-doctor-cli.d.ts.map +1 -1
  24. package/dist/commands/resource-doctor-cli.js +35 -5
  25. package/dist/commands/resource-doctor-cli.js.map +1 -1
  26. package/dist/core/adaptorch-bridge.d.ts +11 -13
  27. package/dist/core/adaptorch-bridge.d.ts.map +1 -1
  28. package/dist/core/adaptorch-bridge.js +11 -13
  29. package/dist/core/adaptorch-bridge.js.map +1 -1
  30. package/dist/core/agent-session-snapshot.d.ts +16 -0
  31. package/dist/core/agent-session-snapshot.d.ts.map +1 -0
  32. package/dist/core/agent-session-snapshot.js +111 -0
  33. package/dist/core/agent-session-snapshot.js.map +1 -0
  34. package/dist/core/agent-session.d.ts +5 -9
  35. package/dist/core/agent-session.d.ts.map +1 -1
  36. package/dist/core/agent-session.js +27 -219
  37. package/dist/core/agent-session.js.map +1 -1
  38. package/dist/core/agent-tool-settings.d.ts +10 -0
  39. package/dist/core/agent-tool-settings.d.ts.map +1 -1
  40. package/dist/core/agent-tool-settings.js +10 -1
  41. package/dist/core/agent-tool-settings.js.map +1 -1
  42. package/dist/core/compaction/compaction.d.ts +7 -0
  43. package/dist/core/compaction/compaction.d.ts.map +1 -1
  44. package/dist/core/compaction/compaction.js +25 -61
  45. package/dist/core/compaction/compaction.js.map +1 -1
  46. package/dist/core/compaction/index.d.ts +1 -0
  47. package/dist/core/compaction/index.d.ts.map +1 -1
  48. package/dist/core/compaction/index.js +1 -0
  49. package/dist/core/compaction/index.js.map +1 -1
  50. package/dist/core/compaction/knowledge-triage-format.d.ts +9 -0
  51. package/dist/core/compaction/knowledge-triage-format.d.ts.map +1 -0
  52. package/dist/core/compaction/knowledge-triage-format.js +71 -0
  53. package/dist/core/compaction/knowledge-triage-format.js.map +1 -0
  54. package/dist/core/compaction/knowledge-triage-types.d.ts +7 -0
  55. package/dist/core/compaction/knowledge-triage-types.d.ts.map +1 -0
  56. package/dist/core/compaction/knowledge-triage-types.js +2 -0
  57. package/dist/core/compaction/knowledge-triage-types.js.map +1 -0
  58. package/dist/core/compaction/knowledge-triage.d.ts +29 -0
  59. package/dist/core/compaction/knowledge-triage.d.ts.map +1 -0
  60. package/dist/core/compaction/knowledge-triage.js +189 -0
  61. package/dist/core/compaction/knowledge-triage.js.map +1 -0
  62. package/dist/core/compaction/transaction.d.ts.map +1 -1
  63. package/dist/core/compaction/transaction.js +1 -1
  64. package/dist/core/compaction/transaction.js.map +1 -1
  65. package/dist/core/compaction/utils.d.ts +4 -0
  66. package/dist/core/compaction/utils.d.ts.map +1 -1
  67. package/dist/core/compaction/utils.js +37 -0
  68. package/dist/core/compaction/utils.js.map +1 -1
  69. package/dist/core/completion-sound-io.d.ts +14 -0
  70. package/dist/core/completion-sound-io.d.ts.map +1 -0
  71. package/dist/core/completion-sound-io.js +64 -0
  72. package/dist/core/completion-sound-io.js.map +1 -0
  73. package/dist/core/completion-sound.d.ts +4 -10
  74. package/dist/core/completion-sound.d.ts.map +1 -1
  75. package/dist/core/completion-sound.js +28 -58
  76. package/dist/core/completion-sound.js.map +1 -1
  77. package/dist/core/context-budget-relevance.d.ts +15 -2
  78. package/dist/core/context-budget-relevance.d.ts.map +1 -1
  79. package/dist/core/context-budget-relevance.js +21 -9
  80. package/dist/core/context-budget-relevance.js.map +1 -1
  81. package/dist/core/context-budget-system-prompt-items.d.ts +1 -1
  82. package/dist/core/context-budget-system-prompt-items.d.ts.map +1 -1
  83. package/dist/core/context-budget-system-prompt-items.js.map +1 -1
  84. package/dist/core/context-budget-system-prompt.d.ts +1 -1
  85. package/dist/core/context-budget-system-prompt.d.ts.map +1 -1
  86. package/dist/core/context-budget-system-prompt.js.map +1 -1
  87. package/dist/core/context-file.d.ts +23 -0
  88. package/dist/core/context-file.d.ts.map +1 -0
  89. package/dist/core/context-file.js +17 -0
  90. package/dist/core/context-file.js.map +1 -0
  91. package/dist/core/keybindings.d.ts +1 -1
  92. package/dist/core/keybindings.d.ts.map +1 -1
  93. package/dist/core/keybindings.js +6 -1
  94. package/dist/core/keybindings.js.map +1 -1
  95. package/dist/core/model-prompt-policy.d.ts +1 -1
  96. package/dist/core/model-prompt-policy.d.ts.map +1 -1
  97. package/dist/core/model-prompt-policy.js.map +1 -1
  98. package/dist/core/prompt-settlement.d.ts +6 -3
  99. package/dist/core/prompt-settlement.d.ts.map +1 -1
  100. package/dist/core/prompt-settlement.js +10 -14
  101. package/dist/core/prompt-settlement.js.map +1 -1
  102. package/dist/core/reasoning-router-promotion.d.ts +41 -1
  103. package/dist/core/reasoning-router-promotion.d.ts.map +1 -1
  104. package/dist/core/reasoning-router-promotion.js +31 -2
  105. package/dist/core/reasoning-router-promotion.js.map +1 -1
  106. package/dist/core/reasoning-router-replay-stability.d.ts +65 -0
  107. package/dist/core/reasoning-router-replay-stability.d.ts.map +1 -0
  108. package/dist/core/reasoning-router-replay-stability.js +67 -0
  109. package/dist/core/reasoning-router-replay-stability.js.map +1 -0
  110. package/dist/core/reasoning-router-v4-weights.d.ts +6 -6
  111. package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -1
  112. package/dist/core/reasoning-router-v4-weights.js +3 -3
  113. package/dist/core/reasoning-router-v4-weights.js.map +1 -1
  114. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  115. package/dist/core/reasoning-router-v4.js +6 -6
  116. package/dist/core/reasoning-router-v4.js.map +1 -1
  117. package/dist/core/redaction.d.ts.map +1 -1
  118. package/dist/core/redaction.js +1 -1
  119. package/dist/core/redaction.js.map +1 -1
  120. package/dist/core/resource-admission.d.ts +2 -1
  121. package/dist/core/resource-admission.d.ts.map +1 -1
  122. package/dist/core/resource-admission.js +11 -0
  123. package/dist/core/resource-admission.js.map +1 -1
  124. package/dist/core/resource-governor-format.d.ts +1 -1
  125. package/dist/core/resource-governor-format.d.ts.map +1 -1
  126. package/dist/core/resource-governor-format.js.map +1 -1
  127. package/dist/core/resource-governor-settings.d.ts +6 -12
  128. package/dist/core/resource-governor-settings.d.ts.map +1 -1
  129. package/dist/core/resource-governor-settings.js.map +1 -1
  130. package/dist/core/resource-governor-types.d.ts +24 -0
  131. package/dist/core/resource-governor-types.d.ts.map +1 -0
  132. package/dist/core/resource-governor-types.js +15 -0
  133. package/dist/core/resource-governor-types.js.map +1 -0
  134. package/dist/core/resource-loader.d.ts +1 -7
  135. package/dist/core/resource-loader.d.ts.map +1 -1
  136. package/dist/core/resource-loader.js.map +1 -1
  137. package/dist/core/resource-observation-journal.d.ts +2 -1
  138. package/dist/core/resource-observation-journal.d.ts.map +1 -1
  139. package/dist/core/resource-observation-journal.js +4 -3
  140. package/dist/core/resource-observation-journal.js.map +1 -1
  141. package/dist/core/resource-observation-report-reader.d.ts +7 -0
  142. package/dist/core/resource-observation-report-reader.d.ts.map +1 -0
  143. package/dist/core/resource-observation-report-reader.js +157 -0
  144. package/dist/core/resource-observation-report-reader.js.map +1 -0
  145. package/dist/core/resource-observation-report.d.ts +24 -0
  146. package/dist/core/resource-observation-report.d.ts.map +1 -0
  147. package/dist/core/resource-observation-report.js +101 -0
  148. package/dist/core/resource-observation-report.js.map +1 -0
  149. package/dist/core/router-feedback-collector.d.ts +1 -1
  150. package/dist/core/router-feedback-collector.d.ts.map +1 -1
  151. package/dist/core/router-feedback-collector.js.map +1 -1
  152. package/dist/core/session-failure-cause.d.ts +33 -0
  153. package/dist/core/session-failure-cause.d.ts.map +1 -0
  154. package/dist/core/session-failure-cause.js +141 -0
  155. package/dist/core/session-failure-cause.js.map +1 -0
  156. package/dist/core/session-system-prompt.d.ts +1 -1
  157. package/dist/core/session-system-prompt.d.ts.map +1 -1
  158. package/dist/core/session-system-prompt.js.map +1 -1
  159. package/dist/core/settings-manager.d.ts +1 -1
  160. package/dist/core/settings-manager.d.ts.map +1 -1
  161. package/dist/core/settings-manager.js.map +1 -1
  162. package/dist/core/system-prompt.d.ts +1 -1
  163. package/dist/core/system-prompt.d.ts.map +1 -1
  164. package/dist/core/system-prompt.js.map +1 -1
  165. package/dist/core/tools/bash.d.ts.map +1 -1
  166. package/dist/core/tools/bash.js +7 -7
  167. package/dist/core/tools/bash.js.map +1 -1
  168. package/dist/core/workload-classifier.d.ts +2 -10
  169. package/dist/core/workload-classifier.d.ts.map +1 -1
  170. package/dist/core/workload-classifier.js +17 -0
  171. package/dist/core/workload-classifier.js.map +1 -1
  172. package/dist/core/workload-family-matcher.d.ts +1 -1
  173. package/dist/core/workload-family-matcher.d.ts.map +1 -1
  174. package/dist/core/workload-family-matcher.js.map +1 -1
  175. package/dist/core/workload-shard-execution-types.d.ts +40 -0
  176. package/dist/core/workload-shard-execution-types.d.ts.map +1 -0
  177. package/dist/core/workload-shard-execution-types.js +14 -0
  178. package/dist/core/workload-shard-execution-types.js.map +1 -0
  179. package/dist/core/workload-shard-executor.d.ts +3 -27
  180. package/dist/core/workload-shard-executor.d.ts.map +1 -1
  181. package/dist/core/workload-shard-executor.js.map +1 -1
  182. package/dist/core/workload-shard-runner.d.ts +1 -1
  183. package/dist/core/workload-shard-runner.d.ts.map +1 -1
  184. package/dist/core/workload-shard-runner.js.map +1 -1
  185. package/dist/core/workload-types.d.ts +24 -0
  186. package/dist/core/workload-types.d.ts.map +1 -0
  187. package/dist/core/workload-types.js +15 -0
  188. package/dist/core/workload-types.js.map +1 -0
  189. package/dist/main.d.ts +2 -0
  190. package/dist/main.d.ts.map +1 -1
  191. package/dist/main.js +27 -47
  192. package/dist/main.js.map +1 -1
  193. package/dist/modes/interactive/theme/omk-control-panel.json +1 -1
  194. package/dist/utils/clipboard-image.d.ts.map +1 -1
  195. package/dist/utils/clipboard-image.js +42 -33
  196. package/dist/utils/clipboard-image.js.map +1 -1
  197. package/dist/utils/clipboard.d.ts.map +1 -1
  198. package/dist/utils/clipboard.js +14 -2
  199. package/dist/utils/clipboard.js.map +1 -1
  200. package/docs/adaptorch-preview-spec.md +20 -18
  201. package/docs/adaptorch-preview.md +9 -9
  202. package/docs/compaction.md +24 -3
  203. package/docs/correctness-wall.md +10 -10
  204. package/docs/docs.json +12 -0
  205. package/docs/environment-variables.md +9 -2
  206. package/docs/index.md +3 -0
  207. package/docs/runtime-algorithms.md +359 -0
  208. package/docs/sdk.md +2 -2
  209. package/docs/settings.md +11 -10
  210. package/docs/usage.md +18 -2
  211. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  212. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  213. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  214. package/examples/extensions/gondolin/package-lock.json +2 -2
  215. package/examples/extensions/gondolin/package.json +1 -1
  216. package/examples/extensions/sandbox/package-lock.json +2 -2
  217. package/examples/extensions/sandbox/package.json +1 -1
  218. package/examples/extensions/with-deps/package-lock.json +2 -2
  219. package/examples/extensions/with-deps/package.json +1 -1
  220. package/npm-shrinkwrap.json +18 -18
  221. package/package.json +6 -6
  222. package/dist/core/context-budget-governor.d.ts +0 -67
  223. package/dist/core/context-budget-governor.d.ts.map +0 -1
  224. package/dist/core/context-budget-governor.js +0 -224
  225. package/dist/core/context-budget-governor.js.map +0 -1
  226. package/dist/core/lean-ctx.d.ts +0 -99
  227. package/dist/core/lean-ctx.d.ts.map +0 -1
  228. package/dist/core/lean-ctx.js +0 -225
  229. package/dist/core/lean-ctx.js.map +0 -1
  230. package/dist/core/read-anchors.d.ts +0 -110
  231. package/dist/core/read-anchors.d.ts.map +0 -1
  232. package/dist/core/read-anchors.js +0 -193
  233. package/dist/core/read-anchors.js.map +0 -1
  234. package/dist/core/recovery-checkpoint.d.ts +0 -196
  235. package/dist/core/recovery-checkpoint.d.ts.map +0 -1
  236. package/dist/core/recovery-checkpoint.js +0 -382
  237. package/dist/core/recovery-checkpoint.js.map +0 -1
  238. package/dist/core/sandbox-policy-v2.d.ts +0 -49
  239. package/dist/core/sandbox-policy-v2.d.ts.map +0 -1
  240. package/dist/core/sandbox-policy-v2.js +0 -368
  241. package/dist/core/sandbox-policy-v2.js.map +0 -1
  242. package/dist/guardrails/audit-logger.d.ts +0 -4
  243. package/dist/guardrails/audit-logger.d.ts.map +0 -1
  244. package/dist/guardrails/audit-logger.js +0 -28
  245. package/dist/guardrails/audit-logger.js.map +0 -1
  246. package/dist/guardrails/freedomd-adapter.d.ts +0 -16
  247. package/dist/guardrails/freedomd-adapter.d.ts.map +0 -1
  248. package/dist/guardrails/freedomd-adapter.js +0 -87
  249. package/dist/guardrails/freedomd-adapter.js.map +0 -1
  250. package/dist/orchestration/lane-grant-auditor.d.ts +0 -4
  251. package/dist/orchestration/lane-grant-auditor.d.ts.map +0 -1
  252. package/dist/orchestration/lane-grant-auditor.js +0 -87
  253. package/dist/orchestration/lane-grant-auditor.js.map +0 -1
  254. package/dist/types/guardrails.d.ts +0 -61
  255. package/dist/types/guardrails.d.ts.map +0 -1
  256. package/dist/types/guardrails.js +0 -9
  257. package/dist/types/guardrails.js.map +0 -1
  258. package/dist/types/lane-grant.d.ts +0 -58
  259. package/dist/types/lane-grant.d.ts.map +0 -1
  260. package/dist/types/lane-grant.js +0 -9
  261. package/dist/types/lane-grant.js.map +0 -1
@@ -17,7 +17,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
17
  import { basename, dirname, join as joinPath } from "node:path";
18
18
  import { isDeepStrictEqual } from "node:util";
19
19
  import { getVisionRouteModel } from "omk-agent-core";
20
- import { clampThinkingLevel, cleanupSessionResources, deriveContextPromptCacheKey, getSupportedThinkingLevels, isContextOverflow, modelsAreEqual, resetApiProviders, streamSimple, } from "omk-ai";
20
+ import { clampThinkingLevel, cleanupSessionResources, deriveContextPromptCacheKey, getSupportedThinkingLevels, isBuiltinStreamFn, modelsAreEqual, resetApiProviders, } from "omk-ai";
21
21
  import { APP_NAME, VERSION } from "../config.js";
22
22
  import { theme } from "../modes/interactive/theme/theme.js";
23
23
  import { stripFrontmatter } from "../utils/frontmatter.js";
@@ -72,12 +72,13 @@ function firstTextContent(result) {
72
72
  }
73
73
  return undefined;
74
74
  }
75
+ import { createImmutableMessageSnapshot } from "./agent-session-snapshot.js";
75
76
  import { redactCredentialShapedContent } from "./compaction/transaction.js";
76
77
  import { selectContextFilesForModel } from "./model-prompt-policy.js";
77
78
  import { findExactModelReferenceMatch } from "./model-resolver.js";
78
79
  import { computePromptTokenBudget } from "./prompt-budget.js";
79
80
  import { classifyPromptCacheTransition } from "./prompt-cache.js";
80
- import { createPromptSettlementState, reducePromptSettlement, settlePromptIfReady, } from "./prompt-settlement.js";
81
+ import * as promptSettlement from "./prompt-settlement.js";
81
82
  import { expandPromptTemplate } from "./prompt-templates.js";
82
83
  import { isQuotaExhaustionMessage, isStickySafetyModel, isUpstreamUnavailableMessage, pickFailoverCandidate, resolveFailoverCandidates, resolveProviderResilience, sameModelRouteCandidates, shouldEjectStickySafetyModel, shouldHonorSafetyFailover, stickySafetyBlockMessage, } from "./provider-resilience.js";
83
84
  import { computeRetryDelayMs, failoverModelKey, isFailoverTriggerError, isRetryableAssistantError, nextRetryAttempt, retryBudgetForAssistantError, } from "./provider-retry.js";
@@ -95,6 +96,7 @@ import { RunResourceLeaseController } from "./run-resource-lease.js";
95
96
  import { SessionBashRuntime } from "./session-bash-runtime.js";
96
97
  import { SessionBashService } from "./session-bash-service.js";
97
98
  import { SessionCompactionService } from "./session-compaction-service.js";
99
+ import { preflightFailureCause, providerFailureCause, runtimeFailureCause, terminationMessage, } from "./session-failure-cause.js";
98
100
  import { CURRENT_SESSION_VERSION, getLatestCompactionEntry } from "./session-manager.js";
99
101
  import { acquireSessionOwnerLeaseSync } from "./session-owner-lease.js";
100
102
  import { assembleSessionSystemPrompt } from "./session-system-prompt.js";
@@ -171,103 +173,6 @@ function toolNameSetsEqual(left, right) {
171
173
  return (normalizedLeft.length === normalizedRight.length &&
172
174
  normalizedLeft.every((toolName, index) => toolName === normalizedRight[index]));
173
175
  }
174
- function snapshotContractError(reason) {
175
- return new Error(`Finalized message replacement must be a plain serializable snapshot: ${reason}`);
176
- }
177
- /**
178
- * Clone a finalized message replacement into the JSON-compatible snapshot
179
- * persisted by SessionManager. Undefined remains allowed as ordinary optional
180
- * message data: JSON omits object properties with undefined values and writes
181
- * undefined array elements as null.
182
- */
183
- function clonePlainSnapshot(value, ancestors = new WeakSet(), copies = new WeakMap()) {
184
- if (value === null)
185
- return value;
186
- switch (typeof value) {
187
- case "string":
188
- case "boolean":
189
- case "undefined":
190
- return value;
191
- case "number":
192
- if (!Number.isFinite(value)) {
193
- throw snapshotContractError("non-finite number values are not allowed");
194
- }
195
- return value;
196
- case "bigint":
197
- throw snapshotContractError("bigint values are not allowed");
198
- case "function":
199
- case "symbol":
200
- throw snapshotContractError(`${typeof value} values are not allowed`);
201
- case "object":
202
- break;
203
- default:
204
- throw snapshotContractError(`${typeof value} values are not allowed`);
205
- }
206
- if (ancestors.has(value)) {
207
- throw snapshotContractError("cyclic values are not allowed");
208
- }
209
- if (copies.has(value)) {
210
- return copies.get(value);
211
- }
212
- ancestors.add(value);
213
- try {
214
- if (Array.isArray(value)) {
215
- const copy = [];
216
- copy.length = value.length;
217
- copies.set(value, copy);
218
- for (const key of Reflect.ownKeys(value)) {
219
- if (key === "length")
220
- continue;
221
- if (typeof key !== "string" || !/^(0|[1-9]\d*)$/.test(key) || Number(key) >= value.length) {
222
- throw snapshotContractError("arrays may only contain indexed values");
223
- }
224
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
225
- if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
226
- throw snapshotContractError("accessor or non-enumerable properties are not allowed");
227
- }
228
- copy[Number(key)] = clonePlainSnapshot(descriptor.value, ancestors, copies);
229
- }
230
- return copy;
231
- }
232
- const prototype = Object.getPrototypeOf(value);
233
- if (prototype !== Object.prototype && prototype !== null) {
234
- throw snapshotContractError("non-plain objects are not allowed");
235
- }
236
- const copy = Object.create(prototype);
237
- copies.set(value, copy);
238
- for (const key of Reflect.ownKeys(value)) {
239
- if (typeof key !== "string") {
240
- throw snapshotContractError("symbol-keyed properties are not allowed");
241
- }
242
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
243
- if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
244
- throw snapshotContractError("accessor or non-enumerable properties are not allowed");
245
- }
246
- Object.defineProperty(copy, key, {
247
- value: clonePlainSnapshot(descriptor.value, ancestors, copies),
248
- enumerable: true,
249
- configurable: true,
250
- writable: true,
251
- });
252
- }
253
- return copy;
254
- }
255
- finally {
256
- ancestors.delete(value);
257
- }
258
- }
259
- function freezeSnapshot(value, seen = new WeakSet()) {
260
- if (value === null || typeof value !== "object" || seen.has(value))
261
- return value;
262
- seen.add(value);
263
- for (const child of Object.values(value)) {
264
- freezeSnapshot(child, seen);
265
- }
266
- return Object.freeze(value);
267
- }
268
- function createImmutableMessageSnapshot(message) {
269
- return freezeSnapshot(clonePlainSnapshot(message));
270
- }
271
176
  // ============================================================================
272
177
  // AgentSession Class
273
178
  // ============================================================================
@@ -387,7 +292,7 @@ export class AgentSession {
387
292
  _workspaceMutationCount = 0;
388
293
  // Model registry for API key resolution
389
294
  _modelRegistry;
390
- /** Lazy, in-memory only; never shared across sessions or persisted. */
295
+ /** Lazy provider: representations persist per workspace by default; plans stay session-memory-only. */
391
296
  _contextBudgetCacheProvider;
392
297
  _contextCacheInvalidationSnapshot;
393
298
  // Tool registry for extension getTools/setTools
@@ -599,87 +504,6 @@ export class AgentSession {
599
504
  });
600
505
  this._appendReplayEvent(event, details);
601
506
  }
602
- _terminationMessage(value, fallback) {
603
- const redacted = redactSensitiveText(value?.trim() || fallback)
604
- .replace(/\0/g, "")
605
- .slice(0, 512);
606
- return redacted || fallback;
607
- }
608
- _providerFailureCause(message) {
609
- const text = message.errorMessage ?? "";
610
- if (isContextOverflow(message, this.model?.contextWindow ?? 0)) {
611
- return { area: "provider", code: "context_overflow" };
612
- }
613
- // Fable/Claude often emit stop_reason=refusal on benign turns (false positive).
614
- // Match broadly so we never mislabel these as provider.protocol.
615
- if (/stop_reason\s*=\s*(refusal|sensitive)|content\/safety stop|safety stop|provider\.refusal|kind=provider_refusal/i.test(text)) {
616
- return { area: "provider", code: "refusal" };
617
- }
618
- // Quota/billing exhaustion is checked BEFORE the generic 401/403 auth
619
- // patterns: "403 ... usage limit for this billing cycle" is transient per
620
- // cycle and must fail over, not terminate the turn as an auth error.
621
- if (isQuotaExhaustionMessage(text) || /rate.?limit|too many requests|429/i.test(text)) {
622
- return { area: "provider", code: "rate_limit" };
623
- }
624
- if (/auth|unauthori[sz]ed|forbidden|invalid.?api.?key|no api key|401|403|\/login/i.test(text)) {
625
- return { area: "provider", code: "auth" };
626
- }
627
- // Gateway/upstream 5xx and dropped streams are transport failures, not
628
- // transcript-shape problems. Classify as network so the guidance points to
629
- // retry/model-switch instead of the protocol sanitize path.
630
- if (isUpstreamUnavailableMessage(text)) {
631
- return { area: "provider", code: "network" };
632
- }
633
- // Kimi/K3 + OpenAI-compat: orphan tool results after dropped error assistants.
634
- // Sanitize-and-retry (transform-messages drops orphans), not a hard tool fatal.
635
- 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)) {
636
- return { area: "provider", code: "protocol" };
637
- }
638
- if (/tool.+timed? out|tool.+timeout/i.test(text))
639
- return { area: "tool", code: "timeout" };
640
- if (/\btool\b/i.test(text) && !/tool_call_id/i.test(text))
641
- return { area: "tool", code: "fatal" };
642
- if (/network|fetch failed|connection|socket|websocket|timed? out|timeout|dns|econn|^terminated$/i.test(text)) {
643
- return { area: "provider", code: "network" };
644
- }
645
- return { area: "provider", code: "protocol" };
646
- }
647
- _classifyPreflightCause(message) {
648
- if (!this.model || /no model|model selected|model is required/i.test(message)) {
649
- return { area: "configuration", code: "invalid" };
650
- }
651
- if (isQuotaExhaustionMessage(message)) {
652
- return { area: "provider", code: "rate_limit" };
653
- }
654
- if (/auth|api key|unauthori[sz]ed|forbidden|401|403|\/login/i.test(message)) {
655
- return { area: "provider", code: "auth" };
656
- }
657
- if (isUpstreamUnavailableMessage(message)) {
658
- return { area: "provider", code: "network" };
659
- }
660
- if (/context.+overflow|context window|too many tokens/i.test(message)) {
661
- return { area: "provider", code: "context_overflow" };
662
- }
663
- if (/duplicate.?result/i.test(message))
664
- return { area: "transcript", code: "duplicate_result" };
665
- if (/orphan.?result/i.test(message))
666
- return { area: "transcript", code: "orphan_result" };
667
- if (/duplicate.?call/i.test(message))
668
- return { area: "transcript", code: "duplicate_call_id" };
669
- if (/transcript|missing.?result/i.test(message))
670
- return { area: "transcript", code: "missing_result" };
671
- if (/compaction/i.test(message))
672
- return { area: "compaction", code: "failed" };
673
- if (/fsync/i.test(message))
674
- return { area: "persistence", code: "fsync_failed" };
675
- if (/lock/i.test(message))
676
- return { area: "persistence", code: "lock_failed" };
677
- if (/append|persist|write/i.test(message))
678
- return { area: "persistence", code: "append_failed" };
679
- if (/tool/i.test(message))
680
- return { area: "tool", code: "fatal" };
681
- return { area: "internal", code: "unclassified" };
682
- }
683
507
  _classifyRunTermination(runId, event) {
684
508
  const timestamp = new Date().toISOString();
685
509
  let assistant;
@@ -708,11 +532,11 @@ export class AgentSession {
708
532
  }
709
533
  else if (assistant.stopReason === "aborted") {
710
534
  cause = this._userAbortRequested ? { area: "user", code: "abort" } : { area: "provider", code: "abort" };
711
- message = this._terminationMessage(assistant.errorMessage, this._userAbortRequested ? "The user aborted the run." : "The provider aborted the run.");
535
+ message = terminationMessage(assistant.errorMessage, this._userAbortRequested ? "The user aborted the run." : "The provider aborted the run.");
712
536
  }
713
537
  else if (assistant.stopReason === "error") {
714
- cause = this._providerFailureCause(assistant);
715
- message = this._terminationMessage(assistant.errorMessage, "The provider request failed.");
538
+ cause = providerFailureCause(assistant, this.model?.contextWindow ?? 0);
539
+ message = terminationMessage(assistant.errorMessage, "The provider request failed.");
716
540
  }
717
541
  else {
718
542
  cause = { area: "completed" };
@@ -742,24 +566,8 @@ export class AgentSession {
742
566
  this._lastTermination = termination;
743
567
  this._emit({ type: "session_termination", termination });
744
568
  }
745
- _runtimeFailureCause(error) {
746
- if (this._pendingRuntimeTerminationCause)
747
- return this._pendingRuntimeTerminationCause;
748
- const code = typeof error === "object" && error !== null && "code" in error ? Reflect.get(error, "code") : undefined;
749
- if (typeof code === "string" &&
750
- new Set(["EACCES", "EDQUOT", "EFBIG", "EIO", "EISDIR", "EMFILE", "ENFILE", "ENOSPC", "EPERM", "EROFS"]).has(code)) {
751
- return { area: "persistence", code: "append_failed" };
752
- }
753
- const message = error instanceof Error ? error.message : String(error);
754
- if (/compaction.+stale|session changed during compaction/i.test(message)) {
755
- return { area: "compaction", code: "stale" };
756
- }
757
- if (/compaction/i.test(message))
758
- return { area: "compaction", code: "failed" };
759
- return { area: "internal", code: "unclassified" };
760
- }
761
569
  _publishRuntimeFailure(error) {
762
- const cause = this._runtimeFailureCause(error);
570
+ const cause = this._pendingRuntimeTerminationCause ?? runtimeFailureCause(error);
763
571
  const runId = this._activeRunId ?? `runtime-${randomUUID()}`;
764
572
  const timestamp = new Date().toISOString();
765
573
  let message = "The AgentSession runtime failed before completing the run.";
@@ -924,7 +732,7 @@ export class AgentSession {
924
732
  throw new Error(formatNoApiKeyFoundMessage(model.provider));
925
733
  }
926
734
  async _getCompactionRequestAuth(model) {
927
- if (this.agent.streamFn === streamSimple) {
735
+ if (isBuiltinStreamFn(this.agent.streamFn)) {
928
736
  return this._getRequiredRequestAuth(model);
929
737
  }
930
738
  const result = await this._modelRegistry.getApiKeyAndHeaders(model);
@@ -1708,12 +1516,12 @@ export class AgentSession {
1708
1516
  }
1709
1517
  }
1710
1518
  catch (error) {
1711
- outcome =
1712
- this._userAbortRequested || (error instanceof Error && /abort/i.test(error.message)) ? "aborted" : "failed";
1519
+ outcome = "failed";
1713
1520
  this._publishRuntimeFailure(error);
1714
1521
  throw error;
1715
1522
  }
1716
1523
  finally {
1524
+ outcome = promptSettlement.resolvePromptSettlementOutcome(outcome, this._lastTermination?.kind);
1717
1525
  if (resourceLease !== null) {
1718
1526
  // Generation-safe: a stale release after another run acquired the
1719
1527
  // lease is a no-op instead of clobbering the newer cap (§8.1).
@@ -1734,15 +1542,15 @@ export class AgentSession {
1734
1542
  */
1735
1543
  _emitPromptSettledIfReady(input) {
1736
1544
  try {
1737
- let state = createPromptSettlementState(input.promptRunId, input.startedAtEpochMs);
1738
- state = reducePromptSettlement(state, { kind: "terminal", outcome: input.outcome });
1545
+ let state = promptSettlement.createPromptSettlementState(input.promptRunId, input.startedAtEpochMs);
1546
+ state = promptSettlement.reducePromptSettlement(state, { kind: "terminal", outcome: input.outcome });
1739
1547
  if (this.isStreaming) {
1740
- state = reducePromptSettlement(state, { kind: "tool", delta: 1 });
1548
+ state = promptSettlement.reducePromptSettlement(state, { kind: "tool", delta: 1 });
1741
1549
  }
1742
1550
  if (this.agent.hasQueuedMessages()) {
1743
- state = reducePromptSettlement(state, { kind: "continuation", delta: 1 });
1551
+ state = promptSettlement.reducePromptSettlement(state, { kind: "continuation", delta: 1 });
1744
1552
  }
1745
- const settled = settlePromptIfReady(state, Date.now());
1553
+ const settled = promptSettlement.settlePromptIfReady(state, Date.now());
1746
1554
  if (settled.event !== null) {
1747
1555
  input.resourceObservations?.record("prompt_settled_v1", settledObservationFacts(settled.event));
1748
1556
  this._emit(settled.event);
@@ -2031,7 +1839,7 @@ export class AgentSession {
2031
1839
  // Emit input event for extension interception (before skill/template expansion)
2032
1840
  let currentImages = options?.images;
2033
1841
  if (this._extensionRunner.hasHandlers("input")) {
2034
- const inputResult = await this._extensionRunner.emitInput(currentText, currentImages, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
1842
+ const inputResult = await this._extensionRunner.emitInput(currentText, currentImages, options?.source ?? "interactive", this.isStreaming || this.isRetrying ? options?.streamingBehavior : undefined);
2035
1843
  if (inputResult.action === "handled") {
2036
1844
  preflightResult?.(true);
2037
1845
  return;
@@ -2048,8 +1856,8 @@ export class AgentSession {
2048
1856
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
2049
1857
  }
2050
1858
  expandedText = redactSensitiveText(expandedText);
2051
- // If streaming, queue via steer() or followUp() based on option
2052
- if (this.isStreaming) {
1859
+ // While a run or its retry backoff owns the session, queue instead of starting a competing top-level prompt.
1860
+ if (this.isStreaming || this.isRetrying) {
2053
1861
  if (!options?.streamingBehavior) {
2054
1862
  throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
2055
1863
  }
@@ -2157,14 +1965,14 @@ export class AgentSession {
2157
1965
  catch (error) {
2158
1966
  preflightResult?.(false);
2159
1967
  const rawMessage = error instanceof Error ? error.message : String(error);
2160
- const cause = this._classifyPreflightCause(rawMessage);
1968
+ const cause = preflightFailureCause(rawMessage, Boolean(this.model));
2161
1969
  const timestamp = new Date().toISOString();
2162
1970
  this._publishTermination(classifySessionTermination({
2163
1971
  sessionId: this.sessionId,
2164
1972
  runId: `preflight-${randomUUID()}`,
2165
1973
  timestamp,
2166
1974
  source: "observed",
2167
- message: this._terminationMessage(rawMessage, "Prompt preflight failed."),
1975
+ message: terminationMessage(rawMessage, "Prompt preflight failed."),
2168
1976
  cause,
2169
1977
  sideEffects: "none",
2170
1978
  ...(this.model ? { provider: this.model.provider, model: this.model.id } : {}),
@@ -2546,7 +2354,7 @@ export class AgentSession {
2546
2354
  }
2547
2355
  async _cycleAvailableModel(direction) {
2548
2356
  const resilience = resolveProviderResilience(this.settingsManager.getProviderResilienceSettings());
2549
- const raw = await this._modelRegistry.getAvailable();
2357
+ const raw = this._modelRegistry.getAvailable();
2550
2358
  // Hard-kill sticky safety models from the cycle list (Fable must not re-enter via hotkey).
2551
2359
  const availableModels = resilience.blockStickySafetyModels
2552
2360
  ? raw.filter((m) => !isStickySafetyModel(m.id, m.provider))
@@ -2750,8 +2558,8 @@ export class AgentSession {
2750
2558
  /**
2751
2559
  * Context-pressure band 0..3 from the projected token estimate over the
2752
2560
  * model context window (reuses estimateProjectedContextTokens). 0..<0.5,
2753
- * 1..<0.75, 2..<0.9, 3..>=0.9. Inert under DEFAULT_WEIGHTS (no pressure
2754
- * coefficient); computed for future calibrated weight presets.
2561
+ * 1..<0.75, 2..<0.9, 3..>=0.9. The released default pressure coefficient
2562
+ * is 1 and participates only after the classifier has prompt evidence.
2755
2563
  */
2756
2564
  _computePressureBucket() {
2757
2565
  const contextWindow = this.model?.contextWindow ?? 0;
@@ -3130,7 +2938,7 @@ export class AgentSession {
3130
2938
  runId: `compaction-${randomUUID()}`,
3131
2939
  timestamp,
3132
2940
  source: "observed",
3133
- message: this._terminationMessage(message, "Manual compaction failed."),
2941
+ message: terminationMessage(message, "Manual compaction failed."),
3134
2942
  cause: { area: "compaction", code: compactionCode },
3135
2943
  sideEffects: committedCompaction ? "confirmed" : "none",
3136
2944
  ...(this.model ? { provider: this.model.provider, model: this.model.id } : {}),
@@ -3340,7 +3148,7 @@ export class AgentSession {
3340
3148
  const compactionModel = this._resolveCompactionModel(this.model);
3341
3149
  let apiKey;
3342
3150
  let headers;
3343
- if (this.agent.streamFn === streamSimple) {
3151
+ if (isBuiltinStreamFn(this.agent.streamFn)) {
3344
3152
  const authResult = await this._modelRegistry.getApiKeyAndHeaders(compactionModel);
3345
3153
  if (!authResult.ok || !authResult.apiKey) {
3346
3154
  const providerLabel = compactionModel.provider;