maka-agent 0.2.0-dev.30.20260912 → 0.2.0-dev.31.20260913

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 (194) hide show
  1. package/THIRD_PARTY_NOTICES.txt +392 -0
  2. package/dist/acp/maka-acp-agent.js +8 -2
  3. package/dist/acp/prompt-content.js +225 -0
  4. package/dist/acp/session-event-mapper.js +103 -0
  5. package/dist/acp/session-registry.js +654 -17
  6. package/dist/acp/stdio-server.js +10 -1
  7. package/dist/cli-core.js +1 -1
  8. package/dist/pi-transcript-tools.js +3 -2
  9. package/dist/pi-transcript.js +12 -2
  10. package/dist/runtime-host-session-channel.js +63 -9
  11. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  12. package/node_modules/@maka/core/dist/artifacts.js +6 -0
  13. package/node_modules/@maka/core/dist/attachments.js +7 -2
  14. package/node_modules/@maka/core/dist/durable-tool-result-projection.js +3 -1
  15. package/node_modules/@maka/core/dist/events.js +21 -0
  16. package/node_modules/@maka/core/dist/goal.js +44 -2
  17. package/node_modules/@maka/core/dist/permission.js +0 -1
  18. package/node_modules/@maka/core/dist/runtime-boundary.js +73 -29
  19. package/node_modules/@maka/core/dist/runtime-event.js +6 -3
  20. package/node_modules/@maka/core/dist/runtime-handoff.js +10 -2
  21. package/node_modules/@maka/core/dist/runtime-logical-execution.js +39 -14
  22. package/node_modules/@maka/core/dist/tool-result-archive-evidence.js +3 -1
  23. package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
  24. package/node_modules/@maka/core/dist/unified-diff.js +33 -26
  25. package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +49 -178
  26. package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +7 -2
  27. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +15 -53
  28. package/node_modules/@maka/runtime/dist/bash-model-output.js +7 -1
  29. package/node_modules/@maka/runtime/dist/bash-tail-buffer.js +13 -52
  30. package/node_modules/@maka/runtime/dist/builtin-tools.js +59 -111
  31. package/node_modules/@maka/runtime/dist/child-fd-input.js +3 -2
  32. package/node_modules/@maka/runtime/dist/context-budget-policy.js +1 -11
  33. package/node_modules/@maka/runtime/dist/context-budget.js +12 -1
  34. package/node_modules/@maka/runtime/dist/conversation-copy.js +104 -9
  35. package/node_modules/@maka/runtime/dist/filesystem-executor.js +10 -6
  36. package/node_modules/@maka/runtime/dist/filesystem-worker/client.js +77 -19
  37. package/node_modules/@maka/runtime/dist/filesystem-worker/launch-spec.js +66 -55
  38. package/node_modules/@maka/runtime/dist/filesystem-worker/operations.js +34 -97
  39. package/node_modules/@maka/runtime/dist/filesystem-worker/protocol.js +25 -10
  40. package/node_modules/@maka/runtime/dist/filesystem-worker/worker-entry.js +2 -0
  41. package/node_modules/@maka/runtime/dist/glob-search.js +74 -0
  42. package/node_modules/@maka/runtime/dist/goal-continuation.js +78 -8
  43. package/node_modules/@maka/runtime/dist/goal-state.js +7 -0
  44. package/node_modules/@maka/runtime/dist/grep-search.js +155 -0
  45. package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +84 -94
  46. package/node_modules/@maka/runtime/dist/model-history.js +25 -3
  47. package/node_modules/@maka/runtime/dist/pipe-tail-collector.js +6 -9
  48. package/node_modules/@maka/runtime/dist/read-page.js +231 -0
  49. package/node_modules/@maka/runtime/dist/request-projection.js +2 -15
  50. package/node_modules/@maka/runtime/dist/ripgrep-executable.js +62 -0
  51. package/node_modules/@maka/runtime/dist/ripgrep-guidance.js +81 -0
  52. package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +187 -20
  53. package/node_modules/@maka/runtime/dist/runtime-read-model.js +2 -1
  54. package/node_modules/@maka/runtime/dist/sandbox/linux-profile-path.js +7 -1
  55. package/node_modules/@maka/runtime/dist/sandbox/linux-sandbox.js +20 -5
  56. package/node_modules/@maka/runtime/dist/session-manager.js +6 -6
  57. package/node_modules/@maka/runtime/dist/session-recap.js +9 -5
  58. package/node_modules/@maka/runtime/dist/shell-exec.js +7 -25
  59. package/node_modules/@maka/runtime/dist/shell-run-manager.js +1 -1
  60. package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +1 -1
  61. package/node_modules/@maka/runtime/dist/shell-tools.js +6 -12
  62. package/node_modules/@maka/runtime/dist/tool-availability.js +0 -1
  63. package/node_modules/@maka/runtime/dist/tool-output.js +1 -1
  64. package/node_modules/@maka/runtime/dist/tool-result-archive-capability.js +24 -36
  65. package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +32 -527
  66. package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +17 -119
  67. package/node_modules/@maka/runtime/dist/tool-result-archive.js +7 -25
  68. package/node_modules/@maka/runtime/dist/tool-runtime.js +7 -5
  69. package/node_modules/@maka/runtime/dist/workers/filesystem-worker.js +6933 -3681
  70. package/node_modules/@maka/runtime/dist/workspace-executor.js +20 -24
  71. package/node_modules/@maka/runtime/package.json +2 -0
  72. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +185 -191
  73. package/node_modules/@maka/runtime-host/dist/client/reconnecting-connection.js +3 -0
  74. package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
  75. package/node_modules/@maka/runtime-host/dist/protocol/message.js +2 -2
  76. package/node_modules/@maka/runtime-host/dist/protocol/operations.js +1 -0
  77. package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +2 -2
  78. package/node_modules/@maka/runtime-host/dist/protocol/turn.js +10 -2
  79. package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +38 -0
  80. package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +2 -8
  81. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +2 -0
  82. package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +81 -7
  83. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +13 -13
  84. package/node_modules/@maka/runtime-host/dist/server/interaction-coordinator.js +65 -0
  85. package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +1 -0
  86. package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +5 -2
  87. package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +88 -72
  88. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +21 -4
  89. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +145 -1
  90. package/node_modules/@maka/storage/dist/agent-run-store.js +5 -2
  91. package/node_modules/@maka/storage/dist/execution-stores.js +2 -1
  92. package/node_modules/@maka/storage/dist/runtime-transcript-query.js +27 -14
  93. package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +69 -3
  94. package/node_modules/balanced-match/LICENSE.md +23 -0
  95. package/node_modules/balanced-match/README.md +57 -0
  96. package/node_modules/balanced-match/dist/commonjs/index.js +59 -0
  97. package/node_modules/balanced-match/dist/commonjs/package.json +3 -0
  98. package/node_modules/balanced-match/dist/esm/index.js +54 -0
  99. package/node_modules/balanced-match/dist/esm/package.json +3 -0
  100. package/node_modules/balanced-match/package.json +68 -0
  101. package/node_modules/brace-expansion/LICENSE +23 -0
  102. package/node_modules/brace-expansion/README.md +105 -0
  103. package/node_modules/brace-expansion/dist/commonjs/index.js +289 -0
  104. package/node_modules/brace-expansion/dist/commonjs/package.json +3 -0
  105. package/node_modules/brace-expansion/dist/esm/index.js +285 -0
  106. package/node_modules/brace-expansion/dist/esm/package.json +3 -0
  107. package/node_modules/brace-expansion/package.json +64 -0
  108. package/node_modules/glob/LICENSE.md +63 -0
  109. package/node_modules/glob/README.md +1203 -0
  110. package/node_modules/glob/dist/commonjs/glob.js +248 -0
  111. package/node_modules/glob/dist/commonjs/has-magic.js +27 -0
  112. package/node_modules/glob/dist/commonjs/ignore.js +119 -0
  113. package/node_modules/glob/dist/commonjs/index.js +68 -0
  114. package/node_modules/glob/dist/commonjs/index.min.js +4 -0
  115. package/node_modules/glob/dist/commonjs/package.json +3 -0
  116. package/node_modules/glob/dist/commonjs/pattern.js +223 -0
  117. package/node_modules/glob/dist/commonjs/processor.js +301 -0
  118. package/node_modules/glob/dist/commonjs/walker.js +387 -0
  119. package/node_modules/glob/dist/esm/glob.js +244 -0
  120. package/node_modules/glob/dist/esm/has-magic.js +23 -0
  121. package/node_modules/glob/dist/esm/ignore.js +115 -0
  122. package/node_modules/glob/dist/esm/index.js +55 -0
  123. package/node_modules/glob/dist/esm/index.min.js +4 -0
  124. package/node_modules/glob/dist/esm/package.json +3 -0
  125. package/node_modules/glob/dist/esm/pattern.js +219 -0
  126. package/node_modules/glob/dist/esm/processor.js +294 -0
  127. package/node_modules/glob/dist/esm/walker.js +381 -0
  128. package/node_modules/glob/package.json +98 -0
  129. package/node_modules/minimatch/LICENSE.md +55 -0
  130. package/node_modules/minimatch/README.md +528 -0
  131. package/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js +14 -0
  132. package/node_modules/minimatch/dist/commonjs/ast.js +845 -0
  133. package/node_modules/minimatch/dist/commonjs/brace-expressions.js +150 -0
  134. package/node_modules/minimatch/dist/commonjs/escape.js +30 -0
  135. package/node_modules/minimatch/dist/commonjs/index.js +1127 -0
  136. package/node_modules/minimatch/dist/commonjs/package.json +3 -0
  137. package/node_modules/minimatch/dist/commonjs/unescape.js +38 -0
  138. package/node_modules/minimatch/dist/esm/assert-valid-pattern.js +10 -0
  139. package/node_modules/minimatch/dist/esm/ast.js +841 -0
  140. package/node_modules/minimatch/dist/esm/brace-expressions.js +146 -0
  141. package/node_modules/minimatch/dist/esm/escape.js +26 -0
  142. package/node_modules/minimatch/dist/esm/index.js +1114 -0
  143. package/node_modules/minimatch/dist/esm/package.json +3 -0
  144. package/node_modules/minimatch/dist/esm/unescape.js +34 -0
  145. package/node_modules/minimatch/package.json +73 -0
  146. package/node_modules/minipass/LICENSE.md +55 -0
  147. package/node_modules/minipass/README.md +825 -0
  148. package/node_modules/minipass/dist/commonjs/index.js +1038 -0
  149. package/node_modules/minipass/dist/commonjs/package.json +3 -0
  150. package/node_modules/minipass/dist/esm/index.js +1020 -0
  151. package/node_modules/minipass/dist/esm/package.json +3 -0
  152. package/node_modules/minipass/package.json +77 -0
  153. package/node_modules/path-scurry/LICENSE.md +55 -0
  154. package/node_modules/path-scurry/README.md +636 -0
  155. package/node_modules/path-scurry/dist/commonjs/index.js +2018 -0
  156. package/node_modules/path-scurry/dist/commonjs/package.json +3 -0
  157. package/node_modules/path-scurry/dist/esm/index.js +1983 -0
  158. package/node_modules/path-scurry/dist/esm/package.json +3 -0
  159. package/node_modules/path-scurry/node_modules/lru-cache/LICENSE.md +55 -0
  160. package/node_modules/path-scurry/node_modules/lru-cache/README.md +469 -0
  161. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.js +7 -0
  162. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js +1726 -0
  163. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js +2 -0
  164. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js +10 -0
  165. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.d.cts.map +1 -0
  166. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.js +7 -0
  167. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js +1726 -0
  168. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js +2 -0
  169. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.js +9 -0
  170. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js +1726 -0
  171. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js +2 -0
  172. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js +10 -0
  173. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/package.json +3 -0
  174. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js +10 -0
  175. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.js +4 -0
  176. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js +1722 -0
  177. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js +2 -0
  178. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js +7 -0
  179. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.d.mts.map +1 -0
  180. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.js +19 -0
  181. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js +1722 -0
  182. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js +2 -0
  183. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.js +6 -0
  184. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js +1722 -0
  185. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js +2 -0
  186. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js +7 -0
  187. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/package.json +3 -0
  188. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js +7 -0
  189. package/node_modules/path-scurry/node_modules/lru-cache/package.json +154 -0
  190. package/node_modules/path-scurry/package.json +72 -0
  191. package/package.json +1 -1
  192. package/node_modules/@maka/runtime/dist/active-tool-result-prune.js +0 -248
  193. package/node_modules/@maka/runtime/dist/active-tool-result-working-set.js +0 -218
  194. package/node_modules/@maka/runtime/dist/archive-read-tool.js +0 -115
@@ -33,7 +33,7 @@ import { composeRequestProjection, } from './request-projection.js';
33
33
  import { decodePlaintextResponsesReasoningState, responsesReasoningItemId, } from './responses-reasoning-state.js';
34
34
  import { finitePositive } from './context-budget-helpers.js';
35
35
  import { contextDiagnosticsCompactionOf, } from './context-diagnostics.js';
36
- import { hasActiveToolResultPruneDiagnosticPatch, hasBlockingReplayDiagnostics, } from './ai-sdk-compaction.js';
36
+ import { hasBlockingReplayDiagnostics } from './ai-sdk-compaction.js';
37
37
  import { RunTrace } from './run-trace.js';
38
38
  import { REQUEST_SANDBOX_BOUNDARY_TOOL_NAME, SANDBOX_BOUNDARY_DENIED_FOR_TURN, SANDBOX_BOUNDARY_FINALIZATION_PROMPT, } from './sandbox-boundary-tool.js';
39
39
  import { buildRuntimeEventModelReplayPlan, buildSteeringEnvelope, collectToolActivityTurnIds, compatibleProviderReasoningReplayEventIds, formatTextWithInlineRefs, steeringMessagesMissingFromBase, steeringModelMessage, } from './model-history.js';
@@ -42,7 +42,7 @@ import { toolAvailabilityHash } from './tool-availability.js';
42
42
  import { renderSwarmModePrompt } from './swarm-mode.js';
43
43
  import { renderGraphModePrompt } from './graph-mode.js';
44
44
  import { modelUsesNativeOpenAiResponses } from './model-runtime.js';
45
- import { applyRuntimeEventContextBudget, buildContextBudgetDiagnosticShell, mergeContextBudgetDiagnostic, mergeContextBudgetDiagnosticPatches, minimalContextBudgetDiagnostic, shouldAppendContextCompactedNote, shouldAppendContextCompactionFailedOpenNote, } from './context-budget.js';
45
+ import { applyRuntimeEventContextBudget, buildContextBudgetDiagnosticShell, mergeContextBudgetDiagnostic, addToolResultPruneStats, minimalContextBudgetDiagnostic, shouldAppendContextCompactedNote, shouldAppendContextCompactionFailedOpenNote, } from './context-budget.js';
46
46
  import { isHistoryCompactContentEvent } from './history-compaction.js';
47
47
  import { canContinueHistoryCompactCheckpointForModel, historyCompactSourceDigest, isProviderHistoryCompactCheckpoint, matchHistoryCompactCheckpointPrefix, projectHistoryCompactCheckpointReplay, } from './history-compact-checkpoint.js';
48
48
  import { resolveSelectedModelContextWindow } from './context-budget-policy.js';
@@ -834,8 +834,6 @@ export class AiSdkTurn {
834
834
  return { plan, providerTools: plan.providerTools, modelTools, nestedTools };
835
835
  };
836
836
  let { plan, providerTools, modelTools, nestedTools } = snapshotStepTools();
837
- let activeToolResultPruneDiagnosticPatch = {};
838
- let midTurnCompactDiagnosticPatch;
839
837
  // Tool names the repair path matches a mis-cased call against — follows the
840
838
  // current step's snapshot so a tool activated mid-turn is repairable on the
841
839
  // step it becomes active, not routed to `invalid`.
@@ -979,6 +977,12 @@ export class AiSdkTurn {
979
977
  };
980
978
  const loadDurableTurnProjection = async () => {
981
979
  const turnEvents = await loadDurableTurnEvents();
980
+ const pruned = await this.deps.compaction.pruneToolResults(turnEvents, turnId);
981
+ if (pruned.stats) {
982
+ if (pruned.stats.prunedToolResults > 0)
983
+ pruneAppliedAtStep = runtimeSteps;
984
+ contextBudgetForTelemetry = addToolResultPruneStats(contextBudgetForTelemetry ?? minimalContextBudgetDiagnostic(), pruned.stats);
985
+ }
982
986
  const projectionCheckpoint = midTurnState?.projectionCheckpoint;
983
987
  const rawProjectionEvents = projectionCheckpoint
984
988
  ? [
@@ -999,7 +1003,7 @@ export class AiSdkTurn {
999
1003
  // built from. Replay without the stale block — the provider
1000
1004
  // decides fit and overflow recovery re-folds (#4845 review).
1001
1005
  const pinnedEffectiveDigest = projectionCheckpoint.coverage.effectiveSourceDigest;
1002
- const coveredEffective = await this.deps.compaction.foldEffectiveModelHistory(checkpointMatch.coveredRuntimeEvents);
1006
+ const coveredEffective = await this.deps.compaction.foldEffectiveModelHistory(checkpointMatch.coveredRuntimeEvents, pruned.projectionSnapshot);
1003
1007
  if (pinnedEffectiveDigest === undefined ||
1004
1008
  historyCompactSourceDigest(coveredEffective) !== pinnedEffectiveDigest) {
1005
1009
  effectiveProjectionCheckpoint = undefined;
@@ -1016,7 +1020,7 @@ export class AiSdkTurn {
1016
1020
  // folded through the same reducer before it becomes messages. Without
1017
1021
  // this, a result archived at step N is rebuilt in full at step N+1 and
1018
1022
  // the ledger's account of what the model sees stops being true.
1019
- const foldedReplayEvents = await this.deps.compaction.foldEffectiveModelHistory(replayEvents);
1023
+ const foldedReplayEvents = await this.deps.compaction.foldEffectiveModelHistory(replayEvents, pruned.projectionSnapshot);
1020
1024
  const replayPlan = buildRuntimeEventModelReplayPlan(foldedReplayEvents, {
1021
1025
  toolActivityTurnIds: collectToolActivityTurnIds([
1022
1026
  ...(input.runtimeContext ?? []),
@@ -1049,7 +1053,7 @@ export class AiSdkTurn {
1049
1053
  ...(priorReplay.contextBudget ? { contextBudget: priorReplay.contextBudget } : {}),
1050
1054
  });
1051
1055
  const onMidTurnDiagnosticPatch = (patch) => {
1052
- midTurnCompactDiagnosticPatch = mergeContextBudgetDiagnosticPatches(midTurnCompactDiagnosticPatch, patch);
1056
+ contextBudgetForTelemetry = mergeContextBudgetDiagnostic(contextBudgetForTelemetry ?? minimalContextBudgetDiagnostic(), patch);
1053
1057
  };
1054
1058
  const capacityProviderTools = [...providerTools];
1055
1059
  const midTurnCapacityHook = this.deps.compaction.buildMidTurnCapacityCompactProjection(turnId, midTurnState, queue, capacityProviderTools, onMidTurnDiagnosticPatch, this, this.automaticMemoryCompactionSupported()
@@ -1057,15 +1061,8 @@ export class AiSdkTurn {
1057
1061
  : undefined, this.automaticMemoryCompactionSupported()
1058
1062
  ? (dispatch) => this.dispatchAutomaticMemoryCompaction(dispatch)
1059
1063
  : undefined, turnAbortController.signal);
1060
- // When mid-turn capacity compaction is active, the prune must also cover
1061
- // the newest completed step; see collectPrunableCompletedStepToolCallIds.
1062
- const activeToolResultPruneIncludesNewestStep = midTurnState !== undefined;
1063
- const activeToolResultPruneHook = this.deps.compaction.buildActiveToolResultPruneProjection(turnId, activeToolResultPruneIncludesNewestStep, (patch) => {
1064
- pruneAppliedAtStep = runtimeSteps;
1065
- activeToolResultPruneDiagnosticPatch = mergeActiveToolResultPruneDiagnosticPatches(activeToolResultPruneDiagnosticPatch, patch);
1066
- });
1067
1064
  const projectCurrentToolAvailability = (options) => plan.projectActiveTools?.(options);
1068
- const shapedProjection = composeRequestProjection(projectCurrentToolAvailability, midTurnCapacityHook, activeToolResultPruneHook);
1065
+ const shapedProjection = composeRequestProjection(projectCurrentToolAvailability, midTurnCapacityHook);
1069
1066
  // Hooks shape; nothing measures the final payload. Whether it fits is
1070
1067
  // the provider's answer (#4559).
1071
1068
  const requestProjection = shapedProjection;
@@ -1655,21 +1652,7 @@ export class AiSdkTurn {
1655
1652
  : undefined;
1656
1653
  if (recovered) {
1657
1654
  overflowRetryUsed = true;
1658
- // Recovery rebuilds the request from the durable ledger, whose
1659
- // tool results intentionally retain their full bodies. Re-enter
1660
- // the active-result projection before dispatch so an archived
1661
- // result cannot reappear in provider context on the retry.
1662
- const recoveredProjection = activeToolResultPruneHook
1663
- ? await activeToolResultPruneHook({
1664
- completedSteps: completedProviderSteps,
1665
- stepNumber: runtimeSteps,
1666
- model,
1667
- messages: recovered.messages,
1668
- activeTools: activeToolsForRequest,
1669
- resolveDispatch,
1670
- })
1671
- : undefined;
1672
- attemptMessages = recoveredProjection?.messages ?? recovered.messages;
1655
+ attemptMessages = recovered.messages;
1673
1656
  continue;
1674
1657
  }
1675
1658
  // Window suggestion (#4559): the provider rejected a request and
@@ -2006,7 +1989,7 @@ export class AiSdkTurn {
2006
1989
  tokenUsage = sawUnusableStepUsage ? undefined : (completedStepUsage ?? attemptTotalUsage);
2007
1990
  if (tokenUsage) {
2008
1991
  tokenUsageCostUsd = this.deps.providerTelemetry.normalizedUsageCostUsd(tokenUsage);
2009
- const contextBudgetForUsage = contextBudgetWithRequestProjectionDiagnostics(contextBudgetForTelemetry, activeToolResultPruneDiagnosticPatch, midTurnCompactDiagnosticPatch);
1992
+ const contextBudgetForUsage = contextBudgetForTelemetry;
2010
1993
  // Persisted alongside the live event so transcript rebuilds from
2011
1994
  // stored messages keep the TUI ctx segment instead of degrading to
2012
1995
  // `?/<window>` (#4019). Computed once; both writers share it.
@@ -2169,7 +2152,6 @@ export class AiSdkTurn {
2169
2152
  watchdogState.current?.stop();
2170
2153
  if (this.watchdog === watchdogState.current)
2171
2154
  this.watchdog = null;
2172
- contextBudgetForTelemetry = contextBudgetWithRequestProjectionDiagnostics(contextBudgetForTelemetry, activeToolResultPruneDiagnosticPatch, midTurnCompactDiagnosticPatch);
2173
2155
  // `tokenUsage` still backfills from the completed steps when the send
2174
2156
  // ended without a final `usage`: the terminal outcome and the
2175
2157
  // `token_usage` SessionEvent below both read it. An unusable sample in
@@ -2393,7 +2375,7 @@ export class AiSdkTurn {
2393
2375
  // transition reducer before it becomes messages, so a committed
2394
2376
  // transition still cannot resurrect content for the model (#4283).
2395
2377
  const budgeted = applyRuntimeEventContextBudget(rawPriorRuntimeContext, contextBudget);
2396
- let runtimeContext = await this.deps.compaction.foldEffectiveModelHistory(budgeted?.events ?? rawPriorRuntimeContext);
2378
+ let runtimeContext = await this.deps.compaction.foldEffectiveModelHistory(budgeted?.events ?? rawPriorRuntimeContext, preparedContextBudget.projectionSnapshot);
2397
2379
  let contextBudgetDiagnostic = budgeted?.diagnostic;
2398
2380
  let projectedHistoryCompactCheckpoint = budgeted?.historyCompactCheckpoint;
2399
2381
  if (preparedContextBudget.diagnosticPatch) {
@@ -2656,15 +2638,6 @@ class ContinuationReplayEmptyError extends Error {
2656
2638
  this.name = 'ContinuationReplayEmptyError';
2657
2639
  }
2658
2640
  }
2659
- function mergeActiveToolResultPruneDiagnosticPatches(left, right) {
2660
- return {
2661
- ...sumOptionalCounts('activePrunedToolResults', left, right),
2662
- ...sumOptionalCounts('activeSupersededToolResults', left, right),
2663
- ...sumOptionalCounts('activeDuplicateToolResults', left, right),
2664
- ...sumOptionalCounts('activeArchiveFailures', left, right),
2665
- ...sumOptionalCounts('activeEstimatedTokensSaved', left, right),
2666
- };
2667
- }
2668
2641
  function mergeNormalizedUsage(current, next) {
2669
2642
  if (!current)
2670
2643
  return next;
@@ -2685,17 +2658,6 @@ function mergeNormalizedUsage(current, next) {
2685
2658
  cachedInputTokens: cacheHitInputTokens,
2686
2659
  };
2687
2660
  }
2688
- function sumOptionalCounts(key, left, right) {
2689
- const total = (left[key] ?? 0) + (right[key] ?? 0);
2690
- return total > 0 ? { [key]: total } : {};
2691
- }
2692
- function contextBudgetWithRequestProjectionDiagnostics(base, patch, compactionPatch) {
2693
- const prunePatch = hasActiveToolResultPruneDiagnosticPatch(patch) ? patch : undefined;
2694
- const mergedPatch = mergeContextBudgetDiagnosticPatches(prunePatch, compactionPatch);
2695
- if (!mergedPatch)
2696
- return base;
2697
- return mergeContextBudgetDiagnostic(base ?? minimalContextBudgetDiagnostic(), mergedPatch);
2698
- }
2699
2661
  function projectMemoryConversationPrefix(messages, eventMessagePositions) {
2700
2662
  // Context visibility and durable evidence authority are separate boundaries.
2701
2663
  // Keep the exact source prefix so the auxiliary request preserves referents
@@ -32,5 +32,11 @@ export function projectBashToolResultForModel(output) {
32
32
  return projected;
33
33
  }
34
34
  export function bashToolResultToModelOutput(output) {
35
- return toolResultOutput(projectBashToolResultForModel(output), false);
35
+ const isError = output !== null &&
36
+ typeof output === 'object' &&
37
+ 'kind' in output &&
38
+ output.kind === 'terminal' &&
39
+ 'status' in output &&
40
+ output.status !== 'completed';
41
+ return toolResultOutput(projectBashToolResultForModel(output), isError);
36
42
  }
@@ -21,48 +21,17 @@
21
21
  // Memory-bounded tail accumulator for streaming shell output. A runaway command
22
22
  // must not be able to grow the captured result without limit (the old Bash path
23
23
  // instead discarded ALL output past a hard cap), so we retain only the last
24
- // `cap` characters.
25
- //
26
- // SECURITY: the retained tail is later passed through redactSecrets before it
27
- // reaches the model / UI. redactSecrets matches on full tokens and their
28
- // prefixes (e.g. `Authorization: Bearer …`, `sk-…`), so a tail that begins in
29
- // the MIDDLE of a secret-bearing line would defeat redaction and leak the
30
- // suffix. To prevent that, when the buffer actually drops content it also drops
31
- // the (partial) leading line, so the retained tail always starts at a line
32
- // boundary and redaction sees whole lines.
24
+ // `cap` characters. Trimming avoids splitting a UTF-16 surrogate pair.
33
25
  export class BashTailBuffer {
34
26
  cap;
35
27
  chunks = [];
36
28
  retained = 0;
37
- // True when we dropped an unterminated oversized line: subsequent chunks are
38
- // still part of that compromised line and must be discarded until the next
39
- // newline, otherwise a continuation chunk (a secret's severed suffix) would
40
- // be retained as if it were a clean line and defeat downstream redaction.
41
- insideDroppedLine = false;
42
- // Latches true once we drop an oversized no-newline line entirely (the case
43
- // above). Callers surface a marker so a result that looks empty is not
44
- // mistaken for "the command produced nothing" — content existed but could not
45
- // be safely truncated.
46
- droppedUnsafe = false;
47
29
  constructor(cap) {
48
30
  this.cap = cap;
49
31
  }
50
- /** Whether an oversized, unsafe-to-truncate line was dropped from the tail. */
51
- hasDroppedUnsafe() {
52
- return this.droppedUnsafe;
53
- }
54
32
  push(chunk) {
55
33
  if (!chunk)
56
34
  return;
57
- if (this.insideDroppedLine) {
58
- const nl = chunk.indexOf('\n');
59
- if (nl < 0)
60
- return; // whole chunk is still the dropped line — discard it
61
- this.insideDroppedLine = false;
62
- chunk = chunk.slice(nl + 1); // resume from the first clean line boundary
63
- if (!chunk)
64
- return;
65
- }
66
35
  this.chunks.push(chunk);
67
36
  this.retained += chunk.length;
68
37
  // Amortize: allow growth to 2x cap before compacting back to cap so appends
@@ -78,28 +47,20 @@ export class BashTailBuffer {
78
47
  if (this.chunks.length <= 1 && this.retained <= this.cap)
79
48
  return;
80
49
  const joined = this.chunks.join('');
81
- let kept = joined.length > this.cap ? joined.slice(joined.length - this.cap) : joined;
82
- if (kept.length < joined.length) {
83
- // We sliced mid-stream. Drop the partial leading line so the retained tail
84
- // starts at a line boundary and downstream redaction never sees a secret
85
- // whose prefix was cut off (see SECURITY note above). With no newline the
86
- // whole tail is one partial line we cannot make safe — drop it entirely
87
- // rather than risk leaking a severed secret. (A single line larger than
88
- // the cap is pathological; the common single-line case is <= cap and is
89
- // never sliced here.)
90
- const nl = kept.indexOf('\n');
91
- if (nl >= 0) {
92
- kept = kept.slice(nl + 1);
93
- }
94
- else {
95
- // No line boundary in the retained tail: drop it and stay "inside" the
96
- // dropped line so its continuation chunks are discarded until a newline.
97
- kept = '';
98
- this.insideDroppedLine = true;
99
- this.droppedUnsafe = true;
100
- }
50
+ let start = Math.max(0, joined.length - this.cap);
51
+ if (start > 0 &&
52
+ isLowSurrogate(joined.charCodeAt(start)) &&
53
+ isHighSurrogate(joined.charCodeAt(start - 1))) {
54
+ start += 1;
101
55
  }
56
+ const kept = joined.slice(start);
102
57
  this.chunks = kept ? [kept] : [];
103
58
  this.retained = kept.length;
104
59
  }
105
60
  }
61
+ function isHighSurrogate(code) {
62
+ return code >= 0xd800 && code <= 0xdbff;
63
+ }
64
+ function isLowSurrogate(code) {
65
+ return code >= 0xdc00 && code <= 0xdfff;
66
+ }
@@ -21,7 +21,7 @@
21
21
  // execution facts, while the active session ExecutionBoundary constrains local
22
22
  // filesystem, shell, and network effects.
23
23
  import { z } from 'zod';
24
- import { jsonSchema, zodSchema } from 'ai';
24
+ import { READ_DESCRIPTION, readParameters, readToolResultPage, resolveReadInput, } from './read-page.js';
25
25
  import { closeSync, constants, fstatSync, futimesSync, lstatSync, openSync, realpathSync, unlinkSync, } from 'node:fs';
26
26
  import { tmpdir } from 'node:os';
27
27
  import { basename, dirname } from 'node:path';
@@ -30,6 +30,8 @@ import { parseAttachmentResourceRef } from '@maka/core/attachments';
30
30
  import { isStorageRef } from '@maka/core/events';
31
31
  import { bashToolResultToModelOutput } from './bash-model-output.js';
32
32
  import { fileWriteToolResultToModelOutput } from './file-tool-model-output.js';
33
+ import { toolResultOutput } from './tool-result-output.js';
34
+ import { GREP_MAX_LINES, GREP_MAX_LINES_PER_FILE, GREP_MAX_MATCH_BYTES } from './grep-search.js';
33
35
  import { openAiApplyPatchInputSchema } from './openai-apply-patch.js';
34
36
  import { parseCodexV4aPatch } from './codex-v4a-patch.js';
35
37
  import { executeApplyPatchOperations } from './apply-patch-batch.js';
@@ -104,87 +106,6 @@ export function buildBuiltinTools(options = {}) {
104
106
  ...(options.permissionProfile ? { permissionProfile: options.permissionProfile } : {}),
105
107
  });
106
108
  const executionFacts = executor.facts;
107
- const acceptsResourceRefs = Boolean(options.runtimeResources || options.attachmentResources);
108
- const readDescription = `Read a text file${options.snapshotImage ? ' or supported image' : ''} from disk${acceptsResourceRefs ? ', or read a whole runtime resource using ref' : ''}.`;
109
- const pathField = z
110
- .string()
111
- .describe('A file path; relative paths are resolved from the session cwd');
112
- const offsetField = z
113
- .number()
114
- .int()
115
- .nonnegative()
116
- .describe('Zero-based text file line offset')
117
- .optional();
118
- const limitField = z
119
- .number()
120
- .int()
121
- .positive()
122
- .describe('Maximum text file lines to read')
123
- .optional();
124
- const refField = z
125
- .string()
126
- .describe('A runtime resource ref provided in the conversation or returned by another tool');
127
- const fileReadParameters = z
128
- .object({
129
- path: pathField,
130
- offset: offsetField,
131
- limit: limitField,
132
- })
133
- .strict();
134
- const runtimeResourceReadParameters = z
135
- .object({
136
- ref: refField,
137
- })
138
- .strict();
139
- // Some providers serialize every optional field with a default. Normalize
140
- // only empty fields that cannot carry intent, then let the strict union keep
141
- // rejecting genuinely ambiguous file-and-resource requests.
142
- const normalizeProviderReadInput = (value) => {
143
- if (typeof value !== 'object' || value === null || Array.isArray(value))
144
- return value;
145
- const input = value;
146
- const ref = input.ref;
147
- const path = input.path;
148
- if (typeof ref === 'string' && ref.trim() !== '') {
149
- if (typeof path !== 'string' || path.trim() !== '')
150
- return value;
151
- return Object.fromEntries(Object.entries(input).filter(([key]) => key !== 'path' && key !== 'offset' && key !== 'limit'));
152
- }
153
- if (typeof ref !== 'string' || ref.trim() !== '')
154
- return value;
155
- return Object.fromEntries(Object.entries(input).filter(([key]) => key !== 'ref'));
156
- };
157
- const strictReadParameters = z.preprocess(normalizeProviderReadInput, z
158
- .union([fileReadParameters, runtimeResourceReadParameters])
159
- .describe('Read a file with path, or a whole runtime resource with ref; provide exactly one'));
160
- // Provider-facing schema: a single top-level object with every field optional.
161
- // Anthropic rejects a tool definition whose input schema carries a top-level
162
- // `anyOf`, so the file-vs-ref exclusivity is stated in the field descriptions
163
- // here and enforced authoritatively by the strict union in `validate` below
164
- // (see #1228 — a union-generated `anyOf` had been leaking onto the wire).
165
- const providerReadParameters = z
166
- .object({
167
- path: pathField
168
- .describe('A file path; relative paths are resolved from the session cwd. Provide either path (optionally with offset/limit) or ref, never both.')
169
- .optional(),
170
- offset: offsetField,
171
- limit: limitField,
172
- ref: refField
173
- .describe('A runtime resource ref provided in the conversation or returned by another tool. Provide ref on its own, without path/offset/limit; omit it (or leave it empty) when reading a file.')
174
- .optional(),
175
- })
176
- .describe('Read a file with path (optionally offset/limit), or a whole runtime resource with ref; provide exactly one of path or ref.');
177
- const providerReadSchema = zodSchema(providerReadParameters);
178
- const readParameters = acceptsResourceRefs
179
- ? jsonSchema(async () => await providerReadSchema.jsonSchema, {
180
- validate: async (value) => {
181
- const result = await strictReadParameters.safeParseAsync(value);
182
- return result.success
183
- ? { success: true, value: result.data }
184
- : { success: false, error: result.error };
185
- },
186
- })
187
- : fileReadParameters;
188
109
  const shell = options.shell ?? { plan: defaultShellPlan() };
189
110
  const sandboxPlatform = options.sandboxPlatform ?? process.platform;
190
111
  const bashTools = options.shellRuns
@@ -253,9 +174,29 @@ export function buildBuiltinTools(options = {}) {
253
174
  {
254
175
  name: 'Read',
255
176
  activityKind: 'read',
256
- description: readDescription,
177
+ description: READ_DESCRIPTION,
257
178
  parameters: readParameters,
258
179
  executionFacts,
180
+ toModelOutput: ({ input, output }) => {
181
+ const args = input;
182
+ const { path } = resolveReadInput(args);
183
+ if (classifyRuntimeResourceRef(path) !== 'runtime' ||
184
+ path.startsWith('maka://runtime/tool-results/'))
185
+ return undefined;
186
+ if (output && typeof output === 'object' && 'kind' in output && output.kind === 'image')
187
+ return undefined;
188
+ try {
189
+ return toolResultOutput(readToolResultPage(JSON.stringify(output), args), false);
190
+ }
191
+ catch (error) {
192
+ return {
193
+ type: 'error-text',
194
+ value: error instanceof Error
195
+ ? error.message
196
+ : 'This Read page could not be generated. Read the original path again.',
197
+ };
198
+ }
199
+ },
259
200
  ...(options.releaseImageSnapshot
260
201
  ? {
261
202
  compensateDurableOutcomeCommitFailure: async (input) => {
@@ -280,35 +221,35 @@ export function buildBuiltinTools(options = {}) {
280
221
  : {}),
281
222
  impl: async (input, ctx) => {
282
223
  const { cwd, sessionId, abortSignal } = ctx;
283
- if ('ref' in input) {
284
- const { ref } = input;
285
- if (classifyRuntimeResourceRef(ref) !== 'runtime') {
286
- throw new Error(`Unsupported runtime resource ref: ${ref}`);
287
- }
288
- const attachment = parseAttachmentResourceRef(ref);
224
+ const resolved = resolveReadInput(input);
225
+ const path = resolved.path;
226
+ const runtimeRef = classifyRuntimeResourceRef(path);
227
+ if (runtimeRef === 'unsupported')
228
+ throw new Error(`Unsupported Maka address: ${path}. Use a path returned by a tool.`);
229
+ if (runtimeRef === 'runtime') {
230
+ const attachment = parseAttachmentResourceRef(path);
289
231
  if (attachment) {
290
- if (!options.attachmentResources) {
232
+ if (!options.attachmentResources)
291
233
  throw new Error('Attachment resources are not available in this toolset');
292
- }
293
- return await options.attachmentResources.readAttachmentResource(sessionId, attachment.artifactId, abortSignal);
234
+ const result = await options.attachmentResources.readAttachmentResource(sessionId, attachment.artifactId, abortSignal);
235
+ return result;
294
236
  }
295
237
  if (!options.runtimeResources)
296
238
  throw new Error('Runtime resources are not available in this toolset');
297
- return await options.runtimeResources.readRuntimeResource(sessionId, ref, abortSignal);
298
- }
299
- const { path, offset, limit } = input;
300
- const runtimeRef = classifyRuntimeResourceRef(path);
301
- if (runtimeRef === 'unsupported')
302
- throw new Error(`Unsupported runtime resource ref: ${path}`);
303
- if (runtimeRef === 'runtime') {
304
- throw new Error('Runtime resources must be read with the ref parameter, not path');
239
+ const result = await options.runtimeResources.readRuntimeResource(sessionId, path, abortSignal);
240
+ return result;
305
241
  }
306
242
  const result = await filesystem.execute({
307
243
  operation: {
308
244
  kind: 'read',
309
245
  path,
310
- ...(offset !== undefined ? { offset } : {}),
311
- ...(limit !== undefined ? { limit } : {}),
246
+ ...(input.offset === undefined ? {} : { offset: input.offset }),
247
+ ...(input.limit === undefined ? {} : { limit: input.limit }),
248
+ ...(resolved.position === undefined
249
+ ? {}
250
+ : {
251
+ continuation: { position: resolved.position, digest: resolved.digest },
252
+ }),
312
253
  },
313
254
  ...filesystemCall(ctx),
314
255
  });
@@ -328,7 +269,8 @@ export function buildBuiltinTools(options = {}) {
328
269
  }
329
270
  if (result.kind !== 'read')
330
271
  throw internalFilesystemReadFailure('Read', 'no file content came back', 'the file is empty or missing');
331
- return { content: result.content };
272
+ const { kind: _kind, ...page } = result;
273
+ return page;
332
274
  },
333
275
  },
334
276
  ...(executor.applyPatch ? [applyPatchTool] : []),
@@ -461,11 +403,16 @@ export function buildBuiltinTools(options = {}) {
461
403
  {
462
404
  name: 'Grep',
463
405
  activityKind: 'search',
464
- description: 'Search file contents with a regex via ripgrep.',
406
+ description: `Search file contents with a ripgrep regex. Scans files as text, including binary files; directory traversal respects ripgrep ignore rules and glob filters. Returns path:line:content matches and exact matchedLines, returnedLines, omittedLines, and truncated from one completed search. Keeps at most ${GREP_MAX_LINES_PER_FILE} lines per file, ${GREP_MAX_LINES} total, and ${GREP_MAX_MATCH_BYTES / 1024} KiB of JSON matches; oversized or non-UTF8 lines/paths may be omitted. Narrow path, glob, or pattern for more matches, or use Read to inspect a file. Failed searches have unknown totals.`,
465
407
  parameters: z.object({
466
- pattern: z.string(),
467
- path: z.string().optional(),
468
- glob: z.string().optional(),
408
+ pattern: z
409
+ .string()
410
+ .describe('Ripgrep regular expression; use an empty pattern to match every line.'),
411
+ path: z
412
+ .string()
413
+ .optional()
414
+ .describe('File or directory to search; defaults to the session working directory.'),
415
+ glob: z.string().optional().describe('Optional ripgrep file glob, for example **/*.ts.'),
469
416
  }),
470
417
  executionFacts,
471
418
  impl: async ({ pattern, path, glob }, ctx) => {
@@ -476,18 +423,19 @@ export function buildBuiltinTools(options = {}) {
476
423
  const result = await filesystem.execute({
477
424
  operation: {
478
425
  kind: 'grep',
479
- path: path ?? '.',
426
+ path: path || '.',
480
427
  pattern,
481
428
  ...(glob ? { glob } : {}),
482
- maxCountPerFile: 50,
483
- limit: 200,
429
+ maxCountPerFile: GREP_MAX_LINES_PER_FILE,
430
+ limit: GREP_MAX_LINES,
484
431
  timeoutMs: GREP_TIMEOUT_MS,
485
432
  },
486
433
  ...filesystemCall(ctx),
487
434
  });
488
435
  if (result.kind !== 'grep')
489
436
  throw internalFilesystemReadFailure('Grep', 'no search result came back', 'the pattern is absent');
490
- return { matches: result.matches };
437
+ const { kind: _kind, ...searchResult } = result;
438
+ return searchResult;
491
439
  },
492
440
  },
493
441
  ];
@@ -17,11 +17,12 @@
17
17
  * under the License.
18
18
  */
19
19
  import { closeSync } from 'node:fs';
20
+ export const MAX_CHILD_FD = 64;
20
21
  export function buildSpawnStdio(fdInputs, stdin = 'ignore') {
21
22
  const stdio = [stdin, 'pipe', 'pipe'];
22
23
  for (const input of fdInputs ?? []) {
23
- if (!Number.isInteger(input.fd) || input.fd < 3 || input.fd > 64) {
24
- throw new Error(`Child fd input must use an integer fd between 3 and 64; received ${input.fd}`);
24
+ if (!Number.isInteger(input.fd) || input.fd < 3 || input.fd > MAX_CHILD_FD) {
25
+ throw new Error(`Child fd input must use an integer fd between 3 and ${MAX_CHILD_FD}; received ${input.fd}`);
25
26
  }
26
27
  if ('sourceFd' in input && (!Number.isInteger(input.sourceFd) || input.sourceFd < 0)) {
27
28
  throw new Error(`Child fd input source must be a non-negative integer; received ${input.sourceFd}`);
@@ -29,22 +29,12 @@ export function buildDefaultContextBudgetPolicy(options = {}) {
29
29
  const surfaceName = (options.name ?? 'default-history-budget').replace(/-default-history-budget$/, '');
30
30
  return {
31
31
  name: options.name ?? 'default-history-budget',
32
- staleToolResultPrune: {
33
- enabled: true,
34
- maxResultEstimatedTokens: 2_048,
35
- minRecentTurnsFull: 2,
36
- },
32
+ toolResultPrune: { enabled: true },
37
33
  historyCompact: {
38
34
  enabled: true,
39
35
  highWaterName: `${surfaceName}-history-compact`,
40
36
  midTurn: { enabled: true },
41
37
  },
42
- activeToolResultPrune: {
43
- enabled: true,
44
- maxCurrentResultEstimatedTokens: 2_048,
45
- minSupersededResultEstimatedTokens: 256,
46
- minStepNumber: 1,
47
- },
48
38
  };
49
39
  }
50
40
  /**
@@ -24,7 +24,7 @@ export { estimateRuntimeEventsTokens } from './model-history.js';
24
24
  export { ARCHIVED_TOOL_RESULT_PLACEHOLDER_KIND, ARCHIVED_TOOL_RESULT_REWRITE_VERSION, isArchivedToolResultPlaceholder, deserializeToolResultArchive, serializeToolResultForArchive, } from './tool-result-archive.js';
25
25
  import { applyRuntimeEventHistoryCompact as applyRuntimeEventHistoryCompactNarrow, } from './history-compaction.js';
26
26
  export function applyRuntimeEventContextBudget(events, policy) {
27
- const prunePolicy = policy?.staleToolResultPrune;
27
+ const prunePolicy = policy?.toolResultPrune;
28
28
  const pruneEnabled = prunePolicy?.enabled === true;
29
29
  const historyCompactEnabled = policy?.historyCompact?.enabled === true;
30
30
  const enabled = pruneEnabled || historyCompactEnabled;
@@ -110,6 +110,17 @@ export function mergeContextBudgetDiagnostic(base, patch) {
110
110
  ...mergeCompactionDecisionDiagnostics(base.compactionDecisions, patch.compactionDecisions),
111
111
  };
112
112
  }
113
+ export function addToolResultPruneStats(snapshot, delta) {
114
+ return {
115
+ ...snapshot,
116
+ prunedToolResults: (snapshot.prunedToolResults ?? 0) + delta.prunedToolResults,
117
+ archiveWriteFailures: (snapshot.archiveWriteFailures ?? 0) + delta.archiveWriteFailures,
118
+ prunedToolResultEstimatedTokensBefore: (snapshot.prunedToolResultEstimatedTokensBefore ?? 0) +
119
+ delta.prunedToolResultEstimatedTokensBefore,
120
+ prunedToolResultEstimatedTokensAfter: (snapshot.prunedToolResultEstimatedTokensAfter ?? 0) +
121
+ delta.prunedToolResultEstimatedTokensAfter,
122
+ };
123
+ }
113
124
  export function mergeContextBudgetDiagnosticPatches(left, right) {
114
125
  if (!left && !right)
115
126
  return undefined;