@sema-ai/core 1.275.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.
- package/CHANGELOG.md +5433 -0
- package/LICENSE +27 -0
- package/NOTICE.md +30 -0
- package/README.md +1040 -0
- package/dist/agents/agent-definition.d.ts +10 -0
- package/dist/agents/agent-definition.d.ts.map +1 -0
- package/dist/agents/agent-definition.js +18 -0
- package/dist/agents/agent-definition.js.map +1 -0
- package/dist/agents/builtin-agents.d.ts +69 -0
- package/dist/agents/builtin-agents.d.ts.map +1 -0
- package/dist/agents/builtin-agents.js +177 -0
- package/dist/agents/builtin-agents.js.map +1 -0
- package/dist/agents/cascade.d.ts +101 -0
- package/dist/agents/cascade.d.ts.map +1 -0
- package/dist/agents/cascade.js +189 -0
- package/dist/agents/cascade.js.map +1 -0
- package/dist/agents/observer.d.ts +209 -0
- package/dist/agents/observer.d.ts.map +1 -0
- package/dist/agents/observer.js +495 -0
- package/dist/agents/observer.js.map +1 -0
- package/dist/agents/repair-loop.d.ts +236 -0
- package/dist/agents/repair-loop.d.ts.map +1 -0
- package/dist/agents/repair-loop.js +293 -0
- package/dist/agents/repair-loop.js.map +1 -0
- package/dist/agents/session-util.d.ts +8 -0
- package/dist/agents/session-util.d.ts.map +1 -0
- package/dist/agents/session-util.js +9 -0
- package/dist/agents/session-util.js.map +1 -0
- package/dist/agents/subagent-steps.d.ts +93 -0
- package/dist/agents/subagent-steps.d.ts.map +1 -0
- package/dist/agents/subagent-steps.js +206 -0
- package/dist/agents/subagent-steps.js.map +1 -0
- package/dist/agents/subagent.d.ts +441 -0
- package/dist/agents/subagent.d.ts.map +1 -0
- package/dist/agents/subagent.js +2492 -0
- package/dist/agents/subagent.js.map +1 -0
- package/dist/agents/suspend-guard.d.ts +35 -0
- package/dist/agents/suspend-guard.d.ts.map +1 -0
- package/dist/agents/suspend-guard.js +48 -0
- package/dist/agents/suspend-guard.js.map +1 -0
- package/dist/agents/teacher.d.ts +137 -0
- package/dist/agents/teacher.d.ts.map +1 -0
- package/dist/agents/teacher.js +575 -0
- package/dist/agents/teacher.js.map +1 -0
- package/dist/agents/team.d.ts +211 -0
- package/dist/agents/team.d.ts.map +1 -0
- package/dist/agents/team.js +293 -0
- package/dist/agents/team.js.map +1 -0
- package/dist/agents/tool-filter.d.ts +29 -0
- package/dist/agents/tool-filter.d.ts.map +1 -0
- package/dist/agents/tool-filter.js +50 -0
- package/dist/agents/tool-filter.js.map +1 -0
- package/dist/agents/verify.d.ts +177 -0
- package/dist/agents/verify.d.ts.map +1 -0
- package/dist/agents/verify.js +305 -0
- package/dist/agents/verify.js.map +1 -0
- package/dist/bench/metrics.d.ts +714 -0
- package/dist/bench/metrics.d.ts.map +1 -0
- package/dist/bench/metrics.js +618 -0
- package/dist/bench/metrics.js.map +1 -0
- package/dist/bin/sema-tb.d.ts +3 -0
- package/dist/bin/sema-tb.d.ts.map +1 -0
- package/dist/bin/sema-tb.js +516 -0
- package/dist/bin/sema-tb.js.map +1 -0
- package/dist/bin/tb-env.d.ts +13 -0
- package/dist/bin/tb-env.d.ts.map +1 -0
- package/dist/bin/tb-env.js +26 -0
- package/dist/bin/tb-env.js.map +1 -0
- package/dist/brain/anthropic.d.ts +46 -0
- package/dist/brain/anthropic.d.ts.map +1 -0
- package/dist/brain/anthropic.js +830 -0
- package/dist/brain/anthropic.js.map +1 -0
- package/dist/brain/circuit-breaker.d.ts +46 -0
- package/dist/brain/circuit-breaker.d.ts.map +1 -0
- package/dist/brain/circuit-breaker.js +173 -0
- package/dist/brain/circuit-breaker.js.map +1 -0
- package/dist/brain/degrading.d.ts +98 -0
- package/dist/brain/degrading.d.ts.map +1 -0
- package/dist/brain/degrading.js +249 -0
- package/dist/brain/degrading.js.map +1 -0
- package/dist/brain/errors.d.ts +31 -0
- package/dist/brain/errors.d.ts.map +1 -0
- package/dist/brain/errors.js +58 -0
- package/dist/brain/errors.js.map +1 -0
- package/dist/brain/failover.d.ts +18 -0
- package/dist/brain/failover.d.ts.map +1 -0
- package/dist/brain/failover.js +118 -0
- package/dist/brain/failover.js.map +1 -0
- package/dist/brain/model-presets.d.ts +36 -0
- package/dist/brain/model-presets.d.ts.map +1 -0
- package/dist/brain/model-presets.js +54 -0
- package/dist/brain/model-presets.js.map +1 -0
- package/dist/brain/openai.d.ts +43 -0
- package/dist/brain/openai.d.ts.map +1 -0
- package/dist/brain/openai.js +784 -0
- package/dist/brain/openai.js.map +1 -0
- package/dist/brain/reasoning.d.ts +138 -0
- package/dist/brain/reasoning.d.ts.map +1 -0
- package/dist/brain/reasoning.js +146 -0
- package/dist/brain/reasoning.js.map +1 -0
- package/dist/brain/repetition.d.ts +60 -0
- package/dist/brain/repetition.d.ts.map +1 -0
- package/dist/brain/repetition.js +121 -0
- package/dist/brain/repetition.js.map +1 -0
- package/dist/brain/request-params.d.ts +29 -0
- package/dist/brain/request-params.d.ts.map +1 -0
- package/dist/brain/request-params.js +78 -0
- package/dist/brain/request-params.js.map +1 -0
- package/dist/brain/retry.d.ts +18 -0
- package/dist/brain/retry.d.ts.map +1 -0
- package/dist/brain/retry.js +42 -0
- package/dist/brain/retry.js.map +1 -0
- package/dist/brain/routing.d.ts +19 -0
- package/dist/brain/routing.d.ts.map +1 -0
- package/dist/brain/routing.js +44 -0
- package/dist/brain/routing.js.map +1 -0
- package/dist/brain/status-sink.d.ts +46 -0
- package/dist/brain/status-sink.d.ts.map +1 -0
- package/dist/brain/status-sink.js +36 -0
- package/dist/brain/status-sink.js.map +1 -0
- package/dist/brain/stream-engine.d.ts +85 -0
- package/dist/brain/stream-engine.d.ts.map +1 -0
- package/dist/brain/stream-engine.js +391 -0
- package/dist/brain/stream-engine.js.map +1 -0
- package/dist/brain/timeout.d.ts +44 -0
- package/dist/brain/timeout.d.ts.map +1 -0
- package/dist/brain/timeout.js +41 -0
- package/dist/brain/timeout.js.map +1 -0
- package/dist/brain/tool-call-repair.d.ts +15 -0
- package/dist/brain/tool-call-repair.d.ts.map +1 -0
- package/dist/brain/tool-call-repair.js +67 -0
- package/dist/brain/tool-call-repair.js.map +1 -0
- package/dist/brain/walltime.d.ts +14 -0
- package/dist/brain/walltime.d.ts.map +1 -0
- package/dist/brain/walltime.js +14 -0
- package/dist/brain/walltime.js.map +1 -0
- package/dist/core/arg-summary.d.ts +19 -0
- package/dist/core/arg-summary.d.ts.map +1 -0
- package/dist/core/arg-summary.js +96 -0
- package/dist/core/arg-summary.js.map +1 -0
- package/dist/core/ask-question.d.ts +113 -0
- package/dist/core/ask-question.d.ts.map +1 -0
- package/dist/core/ask-question.js +246 -0
- package/dist/core/ask-question.js.map +1 -0
- package/dist/core/auto-compaction.d.ts +341 -0
- package/dist/core/auto-compaction.d.ts.map +1 -0
- package/dist/core/auto-compaction.js +495 -0
- package/dist/core/auto-compaction.js.map +1 -0
- package/dist/core/auto-promote.d.ts +126 -0
- package/dist/core/auto-promote.d.ts.map +1 -0
- package/dist/core/auto-promote.js +171 -0
- package/dist/core/auto-promote.js.map +1 -0
- package/dist/core/background-shell.d.ts +128 -0
- package/dist/core/background-shell.d.ts.map +1 -0
- package/dist/core/background-shell.js +42 -0
- package/dist/core/background-shell.js.map +1 -0
- package/dist/core/cache-break-detector.d.ts +63 -0
- package/dist/core/cache-break-detector.d.ts.map +1 -0
- package/dist/core/cache-break-detector.js +0 -0
- package/dist/core/cache-break-detector.js.map +1 -0
- package/dist/core/canonical-json.d.ts +45 -0
- package/dist/core/canonical-json.d.ts.map +1 -0
- package/dist/core/canonical-json.js +132 -0
- package/dist/core/canonical-json.js.map +1 -0
- package/dist/core/checkpoint-store.d.ts +1101 -0
- package/dist/core/checkpoint-store.d.ts.map +1 -0
- package/dist/core/checkpoint-store.js +514 -0
- package/dist/core/checkpoint-store.js.map +1 -0
- package/dist/core/consolidate-scope.d.ts +94 -0
- package/dist/core/consolidate-scope.d.ts.map +1 -0
- package/dist/core/consolidate-scope.js +158 -0
- package/dist/core/consolidate-scope.js.map +1 -0
- package/dist/core/context-edit.d.ts +82 -0
- package/dist/core/context-edit.d.ts.map +1 -0
- package/dist/core/context-edit.js +149 -0
- package/dist/core/context-edit.js.map +1 -0
- package/dist/core/context-guard.d.ts +43 -0
- package/dist/core/context-guard.d.ts.map +1 -0
- package/dist/core/context-guard.js +171 -0
- package/dist/core/context-guard.js.map +1 -0
- package/dist/core/dynamic-recall.d.ts +100 -0
- package/dist/core/dynamic-recall.d.ts.map +1 -0
- package/dist/core/dynamic-recall.js +108 -0
- package/dist/core/dynamic-recall.js.map +1 -0
- package/dist/core/exec-gate.d.ts +74 -0
- package/dist/core/exec-gate.d.ts.map +1 -0
- package/dist/core/exec-gate.js +143 -0
- package/dist/core/exec-gate.js.map +1 -0
- package/dist/core/exec-output-tail.d.ts +37 -0
- package/dist/core/exec-output-tail.d.ts.map +1 -0
- package/dist/core/exec-output-tail.js +63 -0
- package/dist/core/exec-output-tail.js.map +1 -0
- package/dist/core/file-snapshot-store.d.ts +137 -0
- package/dist/core/file-snapshot-store.d.ts.map +1 -0
- package/dist/core/file-snapshot-store.js +319 -0
- package/dist/core/file-snapshot-store.js.map +1 -0
- package/dist/core/git-worktree-env.d.ts +41 -0
- package/dist/core/git-worktree-env.d.ts.map +1 -0
- package/dist/core/git-worktree-env.js +64 -0
- package/dist/core/git-worktree-env.js.map +1 -0
- package/dist/core/hooks.d.ts +372 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +269 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/lsp-diagnostics.d.ts +74 -0
- package/dist/core/lsp-diagnostics.d.ts.map +1 -0
- package/dist/core/lsp-diagnostics.js +125 -0
- package/dist/core/lsp-diagnostics.js.map +1 -0
- package/dist/core/lsp-protocol.d.ts +28 -0
- package/dist/core/lsp-protocol.d.ts.map +1 -0
- package/dist/core/lsp-protocol.js +179 -0
- package/dist/core/lsp-protocol.js.map +1 -0
- package/dist/core/lsp-session.d.ts +56 -0
- package/dist/core/lsp-session.d.ts.map +1 -0
- package/dist/core/lsp-session.js +185 -0
- package/dist/core/lsp-session.js.map +1 -0
- package/dist/core/lsp.d.ts +132 -0
- package/dist/core/lsp.d.ts.map +1 -0
- package/dist/core/lsp.js +147 -0
- package/dist/core/lsp.js.map +1 -0
- package/dist/core/mcp.d.ts +294 -0
- package/dist/core/mcp.d.ts.map +1 -0
- package/dist/core/mcp.js +992 -0
- package/dist/core/mcp.js.map +1 -0
- package/dist/core/media-byte-cap.d.ts +34 -0
- package/dist/core/media-byte-cap.d.ts.map +1 -0
- package/dist/core/media-byte-cap.js +76 -0
- package/dist/core/media-byte-cap.js.map +1 -0
- package/dist/core/memory-engine/data-plane.d.ts +103 -0
- package/dist/core/memory-engine/data-plane.d.ts.map +1 -0
- package/dist/core/memory-engine/data-plane.js +272 -0
- package/dist/core/memory-engine/data-plane.js.map +1 -0
- package/dist/core/memory-engine/dual-root.d.ts +40 -0
- package/dist/core/memory-engine/dual-root.d.ts.map +1 -0
- package/dist/core/memory-engine/dual-root.js +95 -0
- package/dist/core/memory-engine/dual-root.js.map +1 -0
- package/dist/core/memory-engine/engine.d.ts +161 -0
- package/dist/core/memory-engine/engine.d.ts.map +1 -0
- package/dist/core/memory-engine/engine.js +1110 -0
- package/dist/core/memory-engine/engine.js.map +1 -0
- package/dist/core/memory-engine/file-backend.d.ts +162 -0
- package/dist/core/memory-engine/file-backend.d.ts.map +1 -0
- package/dist/core/memory-engine/file-backend.js +948 -0
- package/dist/core/memory-engine/file-backend.js.map +1 -0
- package/dist/core/memory-engine/frontmatter.d.ts +24 -0
- package/dist/core/memory-engine/frontmatter.d.ts.map +1 -0
- package/dist/core/memory-engine/frontmatter.js +135 -0
- package/dist/core/memory-engine/frontmatter.js.map +1 -0
- package/dist/core/memory-engine/index.d.ts +13 -0
- package/dist/core/memory-engine/index.d.ts.map +1 -0
- package/dist/core/memory-engine/index.js +28 -0
- package/dist/core/memory-engine/index.js.map +1 -0
- package/dist/core/memory-engine/layout.d.ts +123 -0
- package/dist/core/memory-engine/layout.d.ts.map +1 -0
- package/dist/core/memory-engine/layout.js +643 -0
- package/dist/core/memory-engine/layout.js.map +1 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts +22 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts.map +1 -0
- package/dist/core/memory-engine/memory-backend-contract.js +271 -0
- package/dist/core/memory-engine/memory-backend-contract.js.map +1 -0
- package/dist/core/memory-engine/migrate.d.ts +17 -0
- package/dist/core/memory-engine/migrate.d.ts.map +1 -0
- package/dist/core/memory-engine/migrate.js +35 -0
- package/dist/core/memory-engine/migrate.js.map +1 -0
- package/dist/core/memory-engine/scan.d.ts +20 -0
- package/dist/core/memory-engine/scan.d.ts.map +1 -0
- package/dist/core/memory-engine/scan.js +84 -0
- package/dist/core/memory-engine/scan.js.map +1 -0
- package/dist/core/memory-engine/scope-contract.d.ts +104 -0
- package/dist/core/memory-engine/scope-contract.d.ts.map +1 -0
- package/dist/core/memory-engine/scope-contract.js +288 -0
- package/dist/core/memory-engine/scope-contract.js.map +1 -0
- package/dist/core/memory-engine/sync-client.d.ts +100 -0
- package/dist/core/memory-engine/sync-client.d.ts.map +1 -0
- package/dist/core/memory-engine/sync-client.js +328 -0
- package/dist/core/memory-engine/sync-client.js.map +1 -0
- package/dist/core/memory-engine/sync.d.ts +97 -0
- package/dist/core/memory-engine/sync.d.ts.map +1 -0
- package/dist/core/memory-engine/sync.js +91 -0
- package/dist/core/memory-engine/sync.js.map +1 -0
- package/dist/core/memory-engine/types.d.ts +279 -0
- package/dist/core/memory-engine/types.d.ts.map +1 -0
- package/dist/core/memory-engine/types.js +9 -0
- package/dist/core/memory-engine/types.js.map +1 -0
- package/dist/core/memory-recall.d.ts +261 -0
- package/dist/core/memory-recall.d.ts.map +1 -0
- package/dist/core/memory-recall.js +600 -0
- package/dist/core/memory-recall.js.map +1 -0
- package/dist/core/memory-vector.d.ts +24 -0
- package/dist/core/memory-vector.d.ts.map +1 -0
- package/dist/core/memory-vector.js +51 -0
- package/dist/core/memory-vector.js.map +1 -0
- package/dist/core/memory.d.ts +502 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +881 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/message-utils.d.ts +7 -0
- package/dist/core/message-utils.d.ts.map +1 -0
- package/dist/core/message-utils.js +10 -0
- package/dist/core/message-utils.js.map +1 -0
- package/dist/core/oracle-isolation.d.ts +85 -0
- package/dist/core/oracle-isolation.d.ts.map +1 -0
- package/dist/core/oracle-isolation.js +121 -0
- package/dist/core/oracle-isolation.js.map +1 -0
- package/dist/core/permission-rules.d.ts +102 -0
- package/dist/core/permission-rules.d.ts.map +1 -0
- package/dist/core/permission-rules.js +357 -0
- package/dist/core/permission-rules.js.map +1 -0
- package/dist/core/present-plan-tool.d.ts +28 -0
- package/dist/core/present-plan-tool.d.ts.map +1 -0
- package/dist/core/present-plan-tool.js +119 -0
- package/dist/core/present-plan-tool.js.map +1 -0
- package/dist/core/pricing.d.ts +48 -0
- package/dist/core/pricing.d.ts.map +1 -0
- package/dist/core/pricing.js +46 -0
- package/dist/core/pricing.js.map +1 -0
- package/dist/core/property-harness.d.ts +126 -0
- package/dist/core/property-harness.d.ts.map +1 -0
- package/dist/core/property-harness.js +192 -0
- package/dist/core/property-harness.js.map +1 -0
- package/dist/core/push-queue.d.ts +10 -0
- package/dist/core/push-queue.d.ts.map +1 -0
- package/dist/core/push-queue.js +42 -0
- package/dist/core/push-queue.js.map +1 -0
- package/dist/core/remote-env.d.ts +432 -0
- package/dist/core/remote-env.d.ts.map +1 -0
- package/dist/core/remote-env.js +77 -0
- package/dist/core/remote-env.js.map +1 -0
- package/dist/core/roles.d.ts +74 -0
- package/dist/core/roles.d.ts.map +1 -0
- package/dist/core/roles.js +272 -0
- package/dist/core/roles.js.map +1 -0
- package/dist/core/runner/active-skill-scope.d.ts +64 -0
- package/dist/core/runner/active-skill-scope.d.ts.map +1 -0
- package/dist/core/runner/active-skill-scope.js +197 -0
- package/dist/core/runner/active-skill-scope.js.map +1 -0
- package/dist/core/runner/assemble-result.d.ts +191 -0
- package/dist/core/runner/assemble-result.d.ts.map +1 -0
- package/dist/core/runner/assemble-result.js +250 -0
- package/dist/core/runner/assemble-result.js.map +1 -0
- package/dist/core/runner/call-cap.d.ts +130 -0
- package/dist/core/runner/call-cap.d.ts.map +1 -0
- package/dist/core/runner/call-cap.js +151 -0
- package/dist/core/runner/call-cap.js.map +1 -0
- package/dist/core/runner/grounding-signal.d.ts +12 -0
- package/dist/core/runner/grounding-signal.d.ts.map +1 -0
- package/dist/core/runner/grounding-signal.js +94 -0
- package/dist/core/runner/grounding-signal.js.map +1 -0
- package/dist/core/runner/image.d.ts +23 -0
- package/dist/core/runner/image.d.ts.map +1 -0
- package/dist/core/runner/image.js +151 -0
- package/dist/core/runner/image.js.map +1 -0
- package/dist/core/runner/memory-consolidation.d.ts +112 -0
- package/dist/core/runner/memory-consolidation.d.ts.map +1 -0
- package/dist/core/runner/memory-consolidation.js +372 -0
- package/dist/core/runner/memory-consolidation.js.map +1 -0
- package/dist/core/runner/prepare-task.d.ts +583 -0
- package/dist/core/runner/prepare-task.d.ts.map +1 -0
- package/dist/core/runner/prepare-task.js +3612 -0
- package/dist/core/runner/prepare-task.js.map +1 -0
- package/dist/core/runner/prompt-suggestions.d.ts +33 -0
- package/dist/core/runner/prompt-suggestions.d.ts.map +1 -0
- package/dist/core/runner/prompt-suggestions.js +116 -0
- package/dist/core/runner/prompt-suggestions.js.map +1 -0
- package/dist/core/runner/runtask.d.ts +274 -0
- package/dist/core/runner/runtask.d.ts.map +1 -0
- package/dist/core/runner/runtask.js +4606 -0
- package/dist/core/runner/runtask.js.map +1 -0
- package/dist/core/runner/session-rule-policy.d.ts +28 -0
- package/dist/core/runner/session-rule-policy.d.ts.map +1 -0
- package/dist/core/runner/session-rule-policy.js +110 -0
- package/dist/core/runner/session-rule-policy.js.map +1 -0
- package/dist/core/runner/strict-output-schema.d.ts +36 -0
- package/dist/core/runner/strict-output-schema.d.ts.map +1 -0
- package/dist/core/runner/strict-output-schema.js +365 -0
- package/dist/core/runner/strict-output-schema.js.map +1 -0
- package/dist/core/runner/synthetic-tools.d.ts +72 -0
- package/dist/core/runner/synthetic-tools.d.ts.map +1 -0
- package/dist/core/runner/synthetic-tools.js +203 -0
- package/dist/core/runner/synthetic-tools.js.map +1 -0
- package/dist/core/runner/tool-disclosure.d.ts +117 -0
- package/dist/core/runner/tool-disclosure.d.ts.map +1 -0
- package/dist/core/runner/tool-disclosure.js +0 -0
- package/dist/core/runner/tool-disclosure.js.map +1 -0
- package/dist/core/runner/turn-attachments.d.ts +381 -0
- package/dist/core/runner/turn-attachments.d.ts.map +1 -0
- package/dist/core/runner/turn-attachments.js +596 -0
- package/dist/core/runner/turn-attachments.js.map +1 -0
- package/dist/core/runner/usage-accounting.d.ts +35 -0
- package/dist/core/runner/usage-accounting.d.ts.map +1 -0
- package/dist/core/runner/usage-accounting.js +45 -0
- package/dist/core/runner/usage-accounting.js.map +1 -0
- package/dist/core/runtime.d.ts +9 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +17 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/safety-axis-vocab.d.ts +33 -0
- package/dist/core/safety-axis-vocab.d.ts.map +1 -0
- package/dist/core/safety-axis-vocab.js +35 -0
- package/dist/core/safety-axis-vocab.js.map +1 -0
- package/dist/core/safety-merge-corpus.d.ts +48 -0
- package/dist/core/safety-merge-corpus.d.ts.map +1 -0
- package/dist/core/safety-merge-corpus.js +203 -0
- package/dist/core/safety-merge-corpus.js.map +1 -0
- package/dist/core/scheduler.d.ts +126 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +54 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/secret-env.d.ts +23 -0
- package/dist/core/secret-env.d.ts.map +1 -0
- package/dist/core/secret-env.js +35 -0
- package/dist/core/secret-env.js.map +1 -0
- package/dist/core/select-model.d.ts +26 -0
- package/dist/core/select-model.d.ts.map +1 -0
- package/dist/core/select-model.js +58 -0
- package/dist/core/select-model.js.map +1 -0
- package/dist/core/sensitive-path-policy.d.ts +24 -0
- package/dist/core/sensitive-path-policy.d.ts.map +1 -0
- package/dist/core/sensitive-path-policy.js +96 -0
- package/dist/core/sensitive-path-policy.js.map +1 -0
- package/dist/core/session-policy-store.d.ts +102 -0
- package/dist/core/session-policy-store.d.ts.map +1 -0
- package/dist/core/session-policy-store.js +177 -0
- package/dist/core/session-policy-store.js.map +1 -0
- package/dist/core/session-reconcile.d.ts +63 -0
- package/dist/core/session-reconcile.d.ts.map +1 -0
- package/dist/core/session-reconcile.js +71 -0
- package/dist/core/session-reconcile.js.map +1 -0
- package/dist/core/session-store.d.ts +99 -0
- package/dist/core/session-store.d.ts.map +1 -0
- package/dist/core/session-store.js +298 -0
- package/dist/core/session-store.js.map +1 -0
- package/dist/core/session.d.ts +144 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +56 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/spec-contract.d.ts +147 -0
- package/dist/core/spec-contract.d.ts.map +1 -0
- package/dist/core/spec-contract.js +340 -0
- package/dist/core/spec-contract.js.map +1 -0
- package/dist/core/strategy-store.d.ts +50 -0
- package/dist/core/strategy-store.d.ts.map +1 -0
- package/dist/core/strategy-store.js +100 -0
- package/dist/core/strategy-store.js.map +1 -0
- package/dist/core/stub-env.d.ts +35 -0
- package/dist/core/stub-env.d.ts.map +1 -0
- package/dist/core/stub-env.js +69 -0
- package/dist/core/stub-env.js.map +1 -0
- package/dist/core/task-notification.d.ts +115 -0
- package/dist/core/task-notification.d.ts.map +1 -0
- package/dist/core/task-notification.js +247 -0
- package/dist/core/task-notification.js.map +1 -0
- package/dist/core/task-outcome.d.ts +80 -0
- package/dist/core/task-outcome.d.ts.map +1 -0
- package/dist/core/task-outcome.js +40 -0
- package/dist/core/task-outcome.js.map +1 -0
- package/dist/core/task-registry.d.ts +349 -0
- package/dist/core/task-registry.d.ts.map +1 -0
- package/dist/core/task-registry.js +1751 -0
- package/dist/core/task-registry.js.map +1 -0
- package/dist/core/tighten-task-spec.d.ts +27 -0
- package/dist/core/tighten-task-spec.d.ts.map +1 -0
- package/dist/core/tighten-task-spec.js +95 -0
- package/dist/core/tighten-task-spec.js.map +1 -0
- package/dist/core/tool-detach.d.ts +31 -0
- package/dist/core/tool-detach.d.ts.map +1 -0
- package/dist/core/tool-detach.js +62 -0
- package/dist/core/tool-detach.js.map +1 -0
- package/dist/core/tool-errors.d.ts +72 -0
- package/dist/core/tool-errors.d.ts.map +1 -0
- package/dist/core/tool-errors.js +194 -0
- package/dist/core/tool-errors.js.map +1 -0
- package/dist/core/tool-name-aliases.d.ts +5 -0
- package/dist/core/tool-name-aliases.d.ts.map +1 -0
- package/dist/core/tool-name-aliases.js +130 -0
- package/dist/core/tool-name-aliases.js.map +1 -0
- package/dist/core/tool-policy.d.ts +295 -0
- package/dist/core/tool-policy.d.ts.map +1 -0
- package/dist/core/tool-policy.js +567 -0
- package/dist/core/tool-policy.js.map +1 -0
- package/dist/core/tool-result-budget.d.ts +44 -0
- package/dist/core/tool-result-budget.d.ts.map +1 -0
- package/dist/core/tool-result-budget.js +140 -0
- package/dist/core/tool-result-budget.js.map +1 -0
- package/dist/core/tool-result-store.d.ts +136 -0
- package/dist/core/tool-result-store.d.ts.map +1 -0
- package/dist/core/tool-result-store.js +219 -0
- package/dist/core/tool-result-store.js.map +1 -0
- package/dist/core/tools.d.ts +14 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +98 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/trace.d.ts +340 -0
- package/dist/core/trace.d.ts.map +1 -0
- package/dist/core/trace.js +12 -0
- package/dist/core/trace.js.map +1 -0
- package/dist/core/types.d.ts +2828 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/untrusted-egress.d.ts +32 -0
- package/dist/core/untrusted-egress.d.ts.map +1 -0
- package/dist/core/untrusted-egress.js +49 -0
- package/dist/core/untrusted-egress.js.map +1 -0
- package/dist/core/untrusted-text.d.ts +64 -0
- package/dist/core/untrusted-text.d.ts.map +1 -0
- package/dist/core/untrusted-text.js +119 -0
- package/dist/core/untrusted-text.js.map +1 -0
- package/dist/core/warm-resume.d.ts +23 -0
- package/dist/core/warm-resume.d.ts.map +1 -0
- package/dist/core/warm-resume.js +28 -0
- package/dist/core/warm-resume.js.map +1 -0
- package/dist/core/with-retry.d.ts +43 -0
- package/dist/core/with-retry.d.ts.map +1 -0
- package/dist/core/with-retry.js +59 -0
- package/dist/core/with-retry.js.map +1 -0
- package/dist/core/workflow-journal-store.d.ts +44 -0
- package/dist/core/workflow-journal-store.d.ts.map +1 -0
- package/dist/core/workflow-journal-store.js +47 -0
- package/dist/core/workflow-journal-store.js.map +1 -0
- package/dist/core/workflow-run-store-contract.d.ts +31 -0
- package/dist/core/workflow-run-store-contract.d.ts.map +1 -0
- package/dist/core/workflow-run-store-contract.js +191 -0
- package/dist/core/workflow-run-store-contract.js.map +1 -0
- package/dist/core/workflow-run-store.d.ts +149 -0
- package/dist/core/workflow-run-store.d.ts.map +1 -0
- package/dist/core/workflow-run-store.js +110 -0
- package/dist/core/workflow-run-store.js.map +1 -0
- package/dist/engine/compaction/compaction.d.ts +139 -0
- package/dist/engine/compaction/compaction.d.ts.map +1 -0
- package/dist/engine/compaction/compaction.js +1030 -0
- package/dist/engine/compaction/compaction.js.map +1 -0
- package/dist/engine/compaction/utils.d.ts +45 -0
- package/dist/engine/compaction/utils.d.ts.map +1 -0
- package/dist/engine/compaction/utils.js +203 -0
- package/dist/engine/compaction/utils.js.map +1 -0
- package/dist/engine/execution-env/kill-tree.d.ts +20 -0
- package/dist/engine/execution-env/kill-tree.d.ts.map +1 -0
- package/dist/engine/execution-env/kill-tree.js +183 -0
- package/dist/engine/execution-env/kill-tree.js.map +1 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +133 -0
- package/dist/engine/execution-env/node-execution-env.d.ts.map +1 -0
- package/dist/engine/execution-env/node-execution-env.js +1031 -0
- package/dist/engine/execution-env/node-execution-env.js.map +1 -0
- package/dist/engine/harness/agent-harness.d.ts +174 -0
- package/dist/engine/harness/agent-harness.d.ts.map +1 -0
- package/dist/engine/harness/agent-harness.js +1053 -0
- package/dist/engine/harness/agent-harness.js.map +1 -0
- package/dist/engine/harness/messages.d.ts +17 -0
- package/dist/engine/harness/messages.d.ts.map +1 -0
- package/dist/engine/harness/messages.js +122 -0
- package/dist/engine/harness/messages.js.map +1 -0
- package/dist/engine/harness/types.d.ts +713 -0
- package/dist/engine/harness/types.d.ts.map +1 -0
- package/dist/engine/harness/types.js +100 -0
- package/dist/engine/harness/types.js.map +1 -0
- package/dist/engine/llm/diagnostics.d.ts +23 -0
- package/dist/engine/llm/diagnostics.d.ts.map +1 -0
- package/dist/engine/llm/diagnostics.js +32 -0
- package/dist/engine/llm/diagnostics.js.map +1 -0
- package/dist/engine/llm/event-stream.d.ts +25 -0
- package/dist/engine/llm/event-stream.d.ts.map +1 -0
- package/dist/engine/llm/event-stream.js +103 -0
- package/dist/engine/llm/event-stream.js.map +1 -0
- package/dist/engine/llm/index.d.ts +12 -0
- package/dist/engine/llm/index.d.ts.map +1 -0
- package/dist/engine/llm/index.js +12 -0
- package/dist/engine/llm/index.js.map +1 -0
- package/dist/engine/llm/types.d.ts +753 -0
- package/dist/engine/llm/types.d.ts.map +1 -0
- package/dist/engine/llm/types.js +2 -0
- package/dist/engine/llm/types.js.map +1 -0
- package/dist/engine/llm/validation.d.ts +8 -0
- package/dist/engine/llm/validation.d.ts.map +1 -0
- package/dist/engine/llm/validation.js +318 -0
- package/dist/engine/llm/validation.js.map +1 -0
- package/dist/engine/loop/agent-loop.d.ts +74 -0
- package/dist/engine/loop/agent-loop.d.ts.map +1 -0
- package/dist/engine/loop/agent-loop.js +1490 -0
- package/dist/engine/loop/agent-loop.js.map +1 -0
- package/dist/engine/loop/runtime-deps.d.ts +17 -0
- package/dist/engine/loop/runtime-deps.d.ts.map +1 -0
- package/dist/engine/loop/runtime-deps.js +21 -0
- package/dist/engine/loop/runtime-deps.js.map +1 -0
- package/dist/engine/loop/types.d.ts +609 -0
- package/dist/engine/loop/types.d.ts.map +1 -0
- package/dist/engine/loop/types.js +2 -0
- package/dist/engine/loop/types.js.map +1 -0
- package/dist/engine/lsp/frame-decoder.d.ts +16 -0
- package/dist/engine/lsp/frame-decoder.d.ts.map +1 -0
- package/dist/engine/lsp/frame-decoder.js +53 -0
- package/dist/engine/lsp/frame-decoder.js.map +1 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +105 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts.map +1 -0
- package/dist/engine/lsp/node-lsp-manager.js +343 -0
- package/dist/engine/lsp/node-lsp-manager.js.map +1 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts +37 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts.map +1 -0
- package/dist/engine/lsp/stdio-lsp-transport.js +185 -0
- package/dist/engine/lsp/stdio-lsp-transport.js.map +1 -0
- package/dist/engine/session/import-validate.d.ts +44 -0
- package/dist/engine/session/import-validate.d.ts.map +1 -0
- package/dist/engine/session/import-validate.js +92 -0
- package/dist/engine/session/import-validate.js.map +1 -0
- package/dist/engine/session/memory-repo.d.ts +25 -0
- package/dist/engine/session/memory-repo.d.ts.map +1 -0
- package/dist/engine/session/memory-repo.js +59 -0
- package/dist/engine/session/memory-repo.js.map +1 -0
- package/dist/engine/session/memory-storage.d.ts +14 -0
- package/dist/engine/session/memory-storage.d.ts.map +1 -0
- package/dist/engine/session/memory-storage.js +17 -0
- package/dist/engine/session/memory-storage.js.map +1 -0
- package/dist/engine/session/repo-utils.d.ts +11 -0
- package/dist/engine/session/repo-utils.d.ts.map +1 -0
- package/dist/engine/session/repo-utils.js +40 -0
- package/dist/engine/session/repo-utils.js.map +1 -0
- package/dist/engine/session/session.d.ts +34 -0
- package/dist/engine/session/session.d.ts.map +1 -0
- package/dist/engine/session/session.js +227 -0
- package/dist/engine/session/session.js.map +1 -0
- package/dist/engine/session/storage-base.d.ts +38 -0
- package/dist/engine/session/storage-base.d.ts.map +1 -0
- package/dist/engine/session/storage-base.js +157 -0
- package/dist/engine/session/storage-base.js.map +1 -0
- package/dist/engine/session/timestamps.d.ts +3 -0
- package/dist/engine/session/timestamps.d.ts.map +1 -0
- package/dist/engine/session/timestamps.js +15 -0
- package/dist/engine/session/timestamps.js.map +1 -0
- package/dist/engine/session/uuid.d.ts +2 -0
- package/dist/engine/session/uuid.d.ts.map +1 -0
- package/dist/engine/session/uuid.js +50 -0
- package/dist/engine/session/uuid.js.map +1 -0
- package/dist/index.d.ts +160 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +374 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/harness.d.ts +26 -0
- package/dist/internal/harness.d.ts.map +1 -0
- package/dist/internal/harness.js +24 -0
- package/dist/internal/harness.js.map +1 -0
- package/dist/internal/llm.d.ts +9 -0
- package/dist/internal/llm.d.ts.map +1 -0
- package/dist/internal/llm.js +8 -0
- package/dist/internal/llm.js.map +1 -0
- package/dist/orchestration/builtin-workflows.d.ts +44 -0
- package/dist/orchestration/builtin-workflows.d.ts.map +1 -0
- package/dist/orchestration/builtin-workflows.js +165 -0
- package/dist/orchestration/builtin-workflows.js.map +1 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts +24 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts.map +1 -0
- package/dist/orchestration/dev-vm-script-runner.js +106 -0
- package/dist/orchestration/dev-vm-script-runner.js.map +1 -0
- package/dist/orchestration/goal.d.ts +97 -0
- package/dist/orchestration/goal.d.ts.map +1 -0
- package/dist/orchestration/goal.js +248 -0
- package/dist/orchestration/goal.js.map +1 -0
- package/dist/orchestration/run-spec.d.ts +63 -0
- package/dist/orchestration/run-spec.d.ts.map +1 -0
- package/dist/orchestration/run-spec.js +274 -0
- package/dist/orchestration/run-spec.js.map +1 -0
- package/dist/orchestration/run-workflow-tool.d.ts +187 -0
- package/dist/orchestration/run-workflow-tool.d.ts.map +1 -0
- package/dist/orchestration/run-workflow-tool.js +612 -0
- package/dist/orchestration/run-workflow-tool.js.map +1 -0
- package/dist/orchestration/workflow-governance.d.ts +70 -0
- package/dist/orchestration/workflow-governance.d.ts.map +1 -0
- package/dist/orchestration/workflow-governance.js +176 -0
- package/dist/orchestration/workflow-governance.js.map +1 -0
- package/dist/orchestration/workflow-meta.d.ts +41 -0
- package/dist/orchestration/workflow-meta.d.ts.map +1 -0
- package/dist/orchestration/workflow-meta.js +426 -0
- package/dist/orchestration/workflow-meta.js.map +1 -0
- package/dist/orchestration/workflow-observe.d.ts +77 -0
- package/dist/orchestration/workflow-observe.d.ts.map +1 -0
- package/dist/orchestration/workflow-observe.js +177 -0
- package/dist/orchestration/workflow-observe.js.map +1 -0
- package/dist/orchestration/workflow-primitives.d.ts +31 -0
- package/dist/orchestration/workflow-primitives.d.ts.map +1 -0
- package/dist/orchestration/workflow-primitives.js +104 -0
- package/dist/orchestration/workflow-primitives.js.map +1 -0
- package/dist/orchestration/workflow-sandbox-conformance.d.ts +34 -0
- package/dist/orchestration/workflow-sandbox-conformance.d.ts.map +1 -0
- package/dist/orchestration/workflow-sandbox-conformance.js +301 -0
- package/dist/orchestration/workflow-sandbox-conformance.js.map +1 -0
- package/dist/orchestration/workflow-script-runner.d.ts +127 -0
- package/dist/orchestration/workflow-script-runner.d.ts.map +1 -0
- package/dist/orchestration/workflow-script-runner.js +48 -0
- package/dist/orchestration/workflow-script-runner.js.map +1 -0
- package/dist/orchestration/workflow-script-store.d.ts +99 -0
- package/dist/orchestration/workflow-script-store.d.ts.map +1 -0
- package/dist/orchestration/workflow-script-store.js +133 -0
- package/dist/orchestration/workflow-script-store.js.map +1 -0
- package/dist/orchestration/workflow-size-guideline.d.ts +50 -0
- package/dist/orchestration/workflow-size-guideline.d.ts.map +1 -0
- package/dist/orchestration/workflow-size-guideline.js +78 -0
- package/dist/orchestration/workflow-size-guideline.js.map +1 -0
- package/dist/orchestration/workflow.d.ts +624 -0
- package/dist/orchestration/workflow.d.ts.map +1 -0
- package/dist/orchestration/workflow.js +1596 -0
- package/dist/orchestration/workflow.js.map +1 -0
- package/dist/prompts/default.d.ts +474 -0
- package/dist/prompts/default.d.ts.map +1 -0
- package/dist/prompts/default.js +676 -0
- package/dist/prompts/default.js.map +1 -0
- package/dist/prompts/supervisor.d.ts +60 -0
- package/dist/prompts/supervisor.d.ts.map +1 -0
- package/dist/prompts/supervisor.js +162 -0
- package/dist/prompts/supervisor.js.map +1 -0
- package/dist/scenarios/env.d.ts +41 -0
- package/dist/scenarios/env.d.ts.map +1 -0
- package/dist/scenarios/env.js +65 -0
- package/dist/scenarios/env.js.map +1 -0
- package/dist/scenarios/full-body.d.ts +47 -0
- package/dist/scenarios/full-body.d.ts.map +1 -0
- package/dist/scenarios/full-body.js +36 -0
- package/dist/scenarios/full-body.js.map +1 -0
- package/dist/scenarios/scenario-registry.d.ts +107 -0
- package/dist/scenarios/scenario-registry.d.ts.map +1 -0
- package/dist/scenarios/scenario-registry.js +192 -0
- package/dist/scenarios/scenario-registry.js.map +1 -0
- package/dist/scenarios/teacher-quickstart.d.ts +41 -0
- package/dist/scenarios/teacher-quickstart.d.ts.map +1 -0
- package/dist/scenarios/teacher-quickstart.js +32 -0
- package/dist/scenarios/teacher-quickstart.js.map +1 -0
- package/dist/server/http.d.ts +36 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +144 -0
- package/dist/server/http.js.map +1 -0
- package/dist/stores/file/checkpoint-store.d.ts +62 -0
- package/dist/stores/file/checkpoint-store.d.ts.map +1 -0
- package/dist/stores/file/checkpoint-store.js +250 -0
- package/dist/stores/file/checkpoint-store.js.map +1 -0
- package/dist/stores/file/file-snapshot-store.d.ts +43 -0
- package/dist/stores/file/file-snapshot-store.d.ts.map +1 -0
- package/dist/stores/file/file-snapshot-store.js +374 -0
- package/dist/stores/file/file-snapshot-store.js.map +1 -0
- package/dist/stores/file/fs-atomic.d.ts +95 -0
- package/dist/stores/file/fs-atomic.d.ts.map +1 -0
- package/dist/stores/file/fs-atomic.js +415 -0
- package/dist/stores/file/fs-atomic.js.map +1 -0
- package/dist/stores/file/index.d.ts +98 -0
- package/dist/stores/file/index.d.ts.map +1 -0
- package/dist/stores/file/index.js +109 -0
- package/dist/stores/file/index.js.map +1 -0
- package/dist/stores/file/memory-store.d.ts +95 -0
- package/dist/stores/file/memory-store.d.ts.map +1 -0
- package/dist/stores/file/memory-store.js +393 -0
- package/dist/stores/file/memory-store.js.map +1 -0
- package/dist/stores/file/session-policy-store.d.ts +24 -0
- package/dist/stores/file/session-policy-store.d.ts.map +1 -0
- package/dist/stores/file/session-policy-store.js +123 -0
- package/dist/stores/file/session-policy-store.js.map +1 -0
- package/dist/stores/file/session-store.d.ts +34 -0
- package/dist/stores/file/session-store.d.ts.map +1 -0
- package/dist/stores/file/session-store.js +175 -0
- package/dist/stores/file/session-store.js.map +1 -0
- package/dist/stores/file/tool-result-store.d.ts +23 -0
- package/dist/stores/file/tool-result-store.d.ts.map +1 -0
- package/dist/stores/file/tool-result-store.js +61 -0
- package/dist/stores/file/tool-result-store.js.map +1 -0
- package/dist/stores/file/workflow-journal-store.d.ts +36 -0
- package/dist/stores/file/workflow-journal-store.d.ts.map +1 -0
- package/dist/stores/file/workflow-journal-store.js +157 -0
- package/dist/stores/file/workflow-journal-store.js.map +1 -0
- package/dist/stores/file/workflow-run-store.d.ts +58 -0
- package/dist/stores/file/workflow-run-store.d.ts.map +1 -0
- package/dist/stores/file/workflow-run-store.js +178 -0
- package/dist/stores/file/workflow-run-store.js.map +1 -0
- package/dist/stores/pg.d.ts +210 -0
- package/dist/stores/pg.d.ts.map +1 -0
- package/dist/stores/pg.js +652 -0
- package/dist/stores/pg.js.map +1 -0
- package/dist/tools/fs/encoding.d.ts +51 -0
- package/dist/tools/fs/encoding.d.ts.map +1 -0
- package/dist/tools/fs/encoding.js +74 -0
- package/dist/tools/fs/encoding.js.map +1 -0
- package/dist/tools/fs/gh-rate-limit.d.ts +19 -0
- package/dist/tools/fs/gh-rate-limit.d.ts.map +1 -0
- package/dist/tools/fs/gh-rate-limit.js +35 -0
- package/dist/tools/fs/gh-rate-limit.js.map +1 -0
- package/dist/tools/fs/index.d.ts +246 -0
- package/dist/tools/fs/index.d.ts.map +1 -0
- package/dist/tools/fs/index.js +2130 -0
- package/dist/tools/fs/index.js.map +1 -0
- package/dist/tools/fs/pdf.d.ts +106 -0
- package/dist/tools/fs/pdf.d.ts.map +1 -0
- package/dist/tools/fs/pdf.js +178 -0
- package/dist/tools/fs/pdf.js.map +1 -0
- package/dist/tools/fs/repo-map.d.ts +15 -0
- package/dist/tools/fs/repo-map.d.ts.map +1 -0
- package/dist/tools/fs/repo-map.js +251 -0
- package/dist/tools/fs/repo-map.js.map +1 -0
- package/dist/tools/fs/safety.d.ts +168 -0
- package/dist/tools/fs/safety.d.ts.map +1 -0
- package/dist/tools/fs/safety.js +479 -0
- package/dist/tools/fs/safety.js.map +1 -0
- package/dist/tools/fs/search.d.ts +118 -0
- package/dist/tools/fs/search.d.ts.map +1 -0
- package/dist/tools/fs/search.js +650 -0
- package/dist/tools/fs/search.js.map +1 -0
- package/dist/tools/gitea-issue.d.ts +39 -0
- package/dist/tools/gitea-issue.d.ts.map +1 -0
- package/dist/tools/gitea-issue.js +91 -0
- package/dist/tools/gitea-issue.js.map +1 -0
- package/dist/tools/monitor.d.ts +64 -0
- package/dist/tools/monitor.d.ts.map +1 -0
- package/dist/tools/monitor.js +135 -0
- package/dist/tools/monitor.js.map +1 -0
- package/dist/tools/scheduler-tools.d.ts +48 -0
- package/dist/tools/scheduler-tools.d.ts.map +1 -0
- package/dist/tools/scheduler-tools.js +449 -0
- package/dist/tools/scheduler-tools.js.map +1 -0
- package/dist/tools/sql-adapters.d.ts +32 -0
- package/dist/tools/sql-adapters.d.ts.map +1 -0
- package/dist/tools/sql-adapters.js +31 -0
- package/dist/tools/sql-adapters.js.map +1 -0
- package/dist/tools/sql.d.ts +36 -0
- package/dist/tools/sql.d.ts.map +1 -0
- package/dist/tools/sql.js +131 -0
- package/dist/tools/sql.js.map +1 -0
- package/dist/tools/task-list.d.ts +26 -0
- package/dist/tools/task-list.d.ts.map +1 -0
- package/dist/tools/task-list.js +352 -0
- package/dist/tools/task-list.js.map +1 -0
- package/dist/tools/todo.d.ts +11 -0
- package/dist/tools/todo.d.ts.map +1 -0
- package/dist/tools/todo.js +126 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/web.d.ts +59 -0
- package/dist/tools/web.d.ts.map +1 -0
- package/dist/tools/web.js +607 -0
- package/dist/tools/web.js.map +1 -0
- package/dist/tools/worktree.d.ts +88 -0
- package/dist/tools/worktree.d.ts.map +1 -0
- package/dist/tools/worktree.js +434 -0
- package/dist/tools/worktree.js.map +1 -0
- package/docs/A1-ATTRIBUTION-ROUND1-2026-07-09.md +181 -0
- package/docs/AB-ORACLE-GATE-VERDICT-2026-07-10.md +100 -0
- package/docs/ANCHOR-GAP-INVENTORY-2026-07-09.md +143 -0
- package/docs/ARCHITECTURE.md +125 -0
- package/docs/BUGHUNT-2026-07-05-NIGHT.md +98 -0
- package/docs/BUILD.md +63 -0
- package/docs/CANCEL-ASYNC-ATTRIBUTION-2026-07-09.md +98 -0
- package/docs/CC-198-VS-201-DRIFT-2026-07-09.md +70 -0
- package/docs/CC-BASELINE-FAKE-ZERO-AUDIT-2026-07-09.md +51 -0
- package/docs/CC-DRIFT-198-206-AGENT-TYPES-2026-07-10.md +82 -0
- package/docs/CC-DRIFT-198-206-CHANGELOG-2026-07-10.md +82 -0
- package/docs/CC-DRIFT-198-206-REMINDERS-2026-07-10.md +96 -0
- package/docs/CC-DRIFT-198-206-ROADMAP-2026-07-10.md +110 -0
- package/docs/CC-DRIFT-198-206-TOOL-INVENTORY-2026-07-10.md +53 -0
- package/docs/CC-DRIFT-198-206-USAGE-CONSTANTS-2026-07-10.md +64 -0
- package/docs/CC-DRIFT-198-206-WORKFLOW-2026-07-10.md +83 -0
- package/docs/CC-PARITY-CHECKLIST.md +220 -0
- package/docs/CC-PARITY-DEEP-SWEEP-2026-07-07.md +149 -0
- package/docs/CC-SUBAGENT-PROMPT-STUDY-2026-07-09.md +219 -0
- package/docs/CC-TASK-REMINDER-CADENCE-STUDY-2026-07-09.md +396 -0
- package/docs/CC-TOOL-PARITY-SWEEP-2026-07.md +56 -0
- package/docs/CC-TOOL-PROMPT-DEEP-DIFF-2026-07-08.md +274 -0
- package/docs/CC-TOOLSURFACE-DEEP-DIVE-2026-07-07.md +197 -0
- package/docs/CC206-OBSERVER-ANCHORS-2026-07-11.md +463 -0
- package/docs/CC207-CORE-SWEEP-BACKLOG-2026-07-12.md +155 -0
- package/docs/CENTER-CONTROL-PLANE-SEAM.md +86 -0
- package/docs/CLEANUP-CONTRACT-ANCHOR-2026-07-09.md +83 -0
- package/docs/COLD-START-RSI-2026-07-09.md +72 -0
- package/docs/COMPACTION-LIVE-AUDIT-2026-07-09.md +114 -0
- package/docs/CONTEXT-lifecycle-extension-points-and-stop-attribution.md +71 -0
- package/docs/COREWARS-POLYGLOT-TRIAGE-2026-07-09.md +85 -0
- package/docs/DEADTARGET-OVERFULL-HBOX-2026-07-10.md +92 -0
- package/docs/DEADTARGET-PATH-TRACING-REVERSE-2026-07-10.md +87 -0
- package/docs/DEADTARGET-WINNING-AVG-COREWARS-2026-07-10.md +96 -0
- package/docs/DEEPSEEK-API-LIMITS-PROBE-2026-07-09.md +118 -0
- package/docs/DESIGN-140-MOCK-VERIFY-2026-07-11.md +79 -0
- package/docs/DESIGN-140-VERIFICATION-2026-07-11.md +43 -0
- package/docs/DESIGN-DRAFT-workflow-collab-2026-07-11.md +56 -0
- package/docs/DESIGN-ORACLE-GROUNDING-GATE-2026-07-10.md +167 -0
- package/docs/DESIGN-TFRAG-RECONCILE-SCAFFOLD-2026-07-09.md +102 -0
- package/docs/EXP-PA2-PE-DESIGN-2026-07-11.md +220 -0
- package/docs/EXT-DOGFOOD-2026-07-12.md +50 -0
- package/docs/FINAL-VERIFY-SURFACE-AUDIT-2026-07-09.md +44 -0
- package/docs/FRAG-RECON-INVESTIGATION-2026-07-09.md +183 -0
- package/docs/HANDOFF.md +121 -0
- package/docs/KNOWN-ISSUES.md +96 -0
- package/docs/LEGW-WINDOW-TAX-2026-07-10.md +82 -0
- package/docs/LIVE-PROBE-BATCH-2026-07-11.md +207 -0
- package/docs/M2-CERT-ATTRIBUTION-2026-07-10.md +61 -0
- package/docs/M25-LEG-VARIANCE-ATTRIBUTION-2026-07-10.md +81 -0
- package/docs/MAILMAN-TIMEOUT-ATTRIBUTION-2026-07-10.md +88 -0
- package/docs/MEMORY-BACKEND-DIALECT-NOTES.md +69 -0
- package/docs/MTEB-ESCAPE-HATCH-ATTRIBUTION-2026-07-09.md +57 -0
- package/docs/MTEB-LEADERBOARD-ATTRIBUTION-2026-07-10.md +134 -0
- package/docs/ORACLE-GATE-NEGATIVE-SAMPLE-2026-07-11.md +28 -0
- package/docs/PARITY-CONTEXT-TRANSACTIONS-2026-07-10.md +67 -0
- package/docs/PARITY-PROGRESS-MATRIX-2026-07-10.md +37 -0
- package/docs/PARITY-SPOT-AGENT-TYPES-2026-07-10.md +70 -0
- package/docs/PARITY-SPOT-REMINDERS-2026-07-10.md +144 -0
- package/docs/PARITY-SPOT-TOOL-INVENTORY-2026-07-10.md +61 -0
- package/docs/PARITY-SPOT-USAGE-CONSTANTS-2026-07-10.md +95 -0
- package/docs/PARITY-SPOT-WORKFLOW-2026-07-10.md +93 -0
- package/docs/PASSWORD-RECOVERY-PANEL-VERDICT-2026-07-10.md +62 -0
- package/docs/R8-R9-FINALIZE-COORDINATION-2026-07-09.md +124 -0
- package/docs/REPL-CODE-MODE-EVALUATION-2026-07-10.md +187 -0
- package/docs/REPORT-1249-TARGETED.md +48 -0
- package/docs/RESEARCH-3P-MEMORY-SWAP-2026-07-12.md +273 -0
- package/docs/ROADMAP.md +111 -0
- package/docs/RSI-CLOUD-DEPLOY-2026-07-06.md +289 -0
- package/docs/RSI-PROCESS-AI-COLDSTART-2026-07-11.md +68 -0
- package/docs/S18-THOROUGHNESS-AUDIT-2026-07-09.md +113 -0
- package/docs/SERVICE-INTEGRATION-GUIDE.md +298 -0
- package/docs/SUBAGENT-STREAM-RESILIENCE-PARITY-2026-07-10.md +118 -0
- package/docs/SWEBENCH-PRO-RECON-2026-07-11.md +31 -0
- package/docs/TB-EFFICIENCY-TELEMETRY-2026-07-08.md +114 -0
- package/docs/TB-FAILURE-AUTOPSY-2026-07-05-RERUN.md +67 -0
- package/docs/TB-FAIRNESS-AUDIT-2026-07-08.md +141 -0
- package/docs/TB-FULL-1257-2026-07-08.md +77 -0
- package/docs/TB-LEG-GAP-ATTRIBUTION-1261-1263-2026-07-11.md +154 -0
- package/docs/TB-REGRESSION-DAEMON-KILL-2026-07-08.md +58 -0
- package/docs/TB-RSI-CROSSCHECK-2026-07-06.md +68 -0
- package/docs/TB-RSI-LEDGER.md +30 -0
- package/docs/TB-STABLE-SET-2026-07-08.md +127 -0
- package/docs/TB21-RECON-2026-07-11.md +28 -0
- package/docs/TEST-DESIGN-BATCH-1-2-3.md +97 -0
- package/docs/THIRD-PARTY-INTEGRATION.md +45 -0
- package/docs/TOKEN-ESTIMATE-CALIBRATION-LIVE-2026-07-09.md +102 -0
- package/docs/audit-2026-06-10-/347/254/254/344/272/214/350/275/256-/347/251/272/347/231/275/345/214/272/344/270/216/345/277/230/346/216/245/347/272/277.md +147 -0
- package/docs/audit-2026-06-10-/350/256/241/347/256/227bug/346/211/253/346/217/217.md +163 -0
- package/docs/audit-2026-06-11-/344/277/256/345/244/215/345/244/215/345/256/241/344/270/216/345/233/236/345/275/222/344/270/223/346/211/253.md +95 -0
- package/docs/audit-2026-06-12-design71-P1/346/275/234/344/274/217/351/235/242/350/243/201/345/206/263/344/270/216/345/220/236/351/224/231/345/256/241/350/256/241.md +45 -0
- package/docs/audit-2026-06-12-/345/205/254/345/274/200/346/227/213/351/222/256/346/264/273/346/200/247/344/270/216vendored/346/255/273/350/267/257.md +63 -0
- package/docs/audit-2026-06-15/ADDENDUM-second-pass.md +88 -0
- package/docs/audit-2026-06-15/ARCHITECTURE-AND-ROADMAP.md +187 -0
- package/docs/audit-2026-06-15/DOC-CORRECTIONS.md +105 -0
- package/docs/audit-2026-06-15/INDEX.md +49 -0
- package/docs/audit-2026-06-15/ORCHESTRATION-STATUS.md +98 -0
- package/docs/audit-2026-06-15/PRODUCTION-ISSUES.md +189 -0
- package/docs/audit-2026-06-15/REFERENCES-literature.md +139 -0
- package/docs/audit-2026-06-15/VENDOR-REFACTOR-PLAN.md +96 -0
- package/docs/cc-probe-198/README.md +72 -0
- package/docs/cc-probe-198/STABILITY-AUDIT.md +118 -0
- package/docs/cc-probe-198/live-schema-monitor-worktree-2026-07-09.json +56 -0
- package/docs/cc-probe-198/mount-variants.json +536 -0
- package/docs/cc-probe-198/plan-mode-run.json +1 -0
- package/docs/cc-probe-198/probe-bash-bg.json +224 -0
- package/docs/cc-probe-198/probe-edit-mismatch.json +120 -0
- package/docs/cc-probe-198/probe-read-missing.json +62 -0
- package/docs/cc-probe-198/probe-search-empty.json +127 -0
- package/docs/cc-probe-198/probe-task-family.json +227 -0
- package/docs/cc-probe-198/probes.status +6 -0
- package/docs/cc-probe-198/raw-capture-interactive.json +948 -0
- package/docs/cc-probe-198/raw-capture-print.json +787 -0
- package/docs/cc-probe-198/raw-capture2-interactive.json +948 -0
- package/docs/cc-probe-198/raw-capture2-print.json +787 -0
- package/docs/cc-probe-198/system-prompt.txt +135 -0
- package/docs/cc-probe-198/tools-array.json +962 -0
- package/docs/durability-boundary.md +63 -0
- package/docs/fix-2026-06-10-/350/256/241/347/256/227bug/344/277/256/345/244/215-search/346/211/271.md +75 -0
- package/docs/fix-2026-06-11-/347/254/254/344/272/214/350/275/256-/344/277/256/345/244/215-search/346/211/271.md +62 -0
- package/docs/parity-sweep/REPORT-DYNAMIC.md +97 -0
- package/docs/parity-sweep/REPORT-STATIC-GGB.md +127 -0
- package/docs/parity-sweep/REPORT-STATIC-RWE.md +133 -0
- package/docs/vendor-history.md +385 -0
- package/docs/vendored-upstream-diff-2026-07.md +83 -0
- package/package.json +70 -0
|
@@ -0,0 +1,1030 @@
|
|
|
1
|
+
import { resolveAgentCoreCompleteFn, } from "../loop/runtime-deps.js";
|
|
2
|
+
import { asAgentMessage, convertToLlm, createCompactionSummaryMessage, createCustomMessage, } from "../harness/messages.js";
|
|
3
|
+
import { buildSessionContext } from "../session/session.js";
|
|
4
|
+
import { CompactionError, err, ok, } from "../harness/types.js";
|
|
5
|
+
import { computeFileLists, createFileOps, extractFileOpsFromMessage, formatFileOperations, serializeConversation, stripFileOperationsFooter, } from "./utils.js";
|
|
6
|
+
function safeJsonStringify(value) {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(value) ?? "undefined";
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return "[unserializable]";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function extractFileOperations(messages, entries, prevCompactionIndex) {
|
|
15
|
+
const fileOps = createFileOps();
|
|
16
|
+
if (prevCompactionIndex >= 0) {
|
|
17
|
+
const prevCompaction = entries[prevCompactionIndex];
|
|
18
|
+
if (!prevCompaction.fromHook && prevCompaction.details) {
|
|
19
|
+
const details = prevCompaction.details;
|
|
20
|
+
if (Array.isArray(details.readFiles)) {
|
|
21
|
+
for (const f of details.readFiles) {
|
|
22
|
+
fileOps.read.add(f);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(details.modifiedFiles)) {
|
|
26
|
+
for (const f of details.modifiedFiles) {
|
|
27
|
+
fileOps.edited.add(f);
|
|
28
|
+
}
|
|
29
|
+
// Seed recency from the previous compaction when it recorded one (newest-first → insert in
|
|
30
|
+
// reverse so the order set stays oldest→newest); files touched by THIS range's messages are
|
|
31
|
+
// extracted after this and move to newer positions naturally.
|
|
32
|
+
const prevRecency = details.modifiedFilesByRecency;
|
|
33
|
+
if (Array.isArray(prevRecency)) {
|
|
34
|
+
for (const f of prevRecency.toReversed()) {
|
|
35
|
+
fileOps.modifiedOrder.add(f);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
for (const msg of messages) {
|
|
42
|
+
extractFileOpsFromMessage(msg, fileOps);
|
|
43
|
+
}
|
|
44
|
+
return fileOps;
|
|
45
|
+
}
|
|
46
|
+
function getMessageFromEntry(entry) {
|
|
47
|
+
if (entry.type === "message") {
|
|
48
|
+
return entry.message;
|
|
49
|
+
}
|
|
50
|
+
if (entry.type === "custom_message") {
|
|
51
|
+
return asAgentMessage(createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp));
|
|
52
|
+
}
|
|
53
|
+
if (entry.type === "compaction") {
|
|
54
|
+
return asAgentMessage(createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp));
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
function getMessageFromEntryForCompaction(entry) {
|
|
59
|
+
if (entry.type === "compaction") {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
return getMessageFromEntry(entry);
|
|
63
|
+
}
|
|
64
|
+
/** Default compaction settings used by the harness. */
|
|
65
|
+
export const DEFAULT_COMPACTION_SETTINGS = {
|
|
66
|
+
enabled: true,
|
|
67
|
+
reserveTokens: 16384,
|
|
68
|
+
keepRecentTokens: 20000,
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* design/123 D2 — default structural coefficient (chars per token) for every structural token
|
|
72
|
+
* estimate. 4 = the historical chars/4 heuristic (CC 198's legacy-family value); per-model override
|
|
73
|
+
* via `Model.charsPerToken` (newer families → 3, CJK-heavy → 2–3). Threaded as an explicit parameter
|
|
74
|
+
* through the estimate chain so caller-side coordinates never split (estimate vs cut-point vs defense).
|
|
75
|
+
*/
|
|
76
|
+
export const DEFAULT_CHARS_PER_TOKEN = 4;
|
|
77
|
+
/**
|
|
78
|
+
* design/123 D2 image pin — an inline image contributes a FIXED token weight, deliberately NOT
|
|
79
|
+
* derived from `chars / charsPerToken`: the old `chars += 4800` shape would silently re-price an
|
|
80
|
+
* image from 1200 to 1600 tokens under charsPerToken=3. Image-size specialization stays deferred;
|
|
81
|
+
* this constant keeps the estimate coefficient-invariant.
|
|
82
|
+
*
|
|
83
|
+
* 批③ P2 value bump 1200→2000 = the CC estimate ("Images/documents are approximately 2000 tokens
|
|
84
|
+
* regardless of format" — services/compact/microCompact.ts:152; services/tokenEstimation.ts:409-411
|
|
85
|
+
* returns 2000 per image, noting the API actually charges ~2000 where naive base64/4 estimated ~325k).
|
|
86
|
+
* At 1200 a vision-heavy session under-estimated by ~40% per image ⇒ compaction fired late ⇒
|
|
87
|
+
* provider-side overflow risk. Mechanism (fixed pin) unchanged; value only.
|
|
88
|
+
*/
|
|
89
|
+
const IMAGE_TOKEN_ESTIMATE = 2000;
|
|
90
|
+
/** Calculate total context tokens from provider usage. */
|
|
91
|
+
export function calculateContextTokens(usage) {
|
|
92
|
+
return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
93
|
+
}
|
|
94
|
+
// VENDORED EDIT (design/64 §26.5 council #1): anchor on USAGE SIGNAL, not on stopReason alone.
|
|
95
|
+
// - An "error" assistant often carries VALID usage (the provider billed the request before failing) —
|
|
96
|
+
// the old unconditional skip could drop the anchor entirely when the visible history holds only
|
|
97
|
+
// error assistants (shared session across failed tasks), silently falling back to the chars/4
|
|
98
|
+
// heuristic for the WHOLE history, which underestimates code-dense content (≈2×) → compaction
|
|
99
|
+
// skipped → provider-side truncation.
|
|
100
|
+
// - Conversely, zero/empty usage (a synthetic loop-failure message carries EMPTY_USAGE — a truthy
|
|
101
|
+
// object) must NEVER anchor: anchoring at 0 would swallow the entire prior history from the
|
|
102
|
+
// estimate, far worse than the chars/4 fallback.
|
|
103
|
+
// "aborted" stays excluded: its usage may reflect a partially consumed stream.
|
|
104
|
+
function getAssistantUsage(msg) {
|
|
105
|
+
if (msg.role === "assistant" && "usage" in msg) {
|
|
106
|
+
const assistantMsg = msg;
|
|
107
|
+
if (assistantMsg.stopReason !== "aborted" &&
|
|
108
|
+
assistantMsg.usage &&
|
|
109
|
+
calculateContextTokens(assistantMsg.usage) > 0) {
|
|
110
|
+
return assistantMsg.usage;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Return usage from the last successful assistant message in session entries.
|
|
117
|
+
*
|
|
118
|
+
* design/123 D1 stale-anchor note (fable-m2, same-family point): this scans RAW session entries, so
|
|
119
|
+
* unlike `buildSessionContext` (which shallow-strips the usage of kept-tail assistants replayed
|
|
120
|
+
* across a compaction boundary — the anchor "naturally disappears", CC 198 parity) it CAN still see
|
|
121
|
+
* a pre-compaction anchor. Any consumer using this across a compaction boundary must treat such an
|
|
122
|
+
* anchor as STALE: it reflects the pre-compaction request and overestimates the post-compaction
|
|
123
|
+
* context. (Currently exported with no in-repo production consumer.)
|
|
124
|
+
*/
|
|
125
|
+
export function getLastAssistantUsage(entries) {
|
|
126
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
127
|
+
const entry = entries[i];
|
|
128
|
+
if (entry.type === "message") {
|
|
129
|
+
const usage = getAssistantUsage(entry.message);
|
|
130
|
+
if (usage) {
|
|
131
|
+
return usage;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
function getLastAssistantUsageInfo(messages) {
|
|
138
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
139
|
+
const usage = getAssistantUsage(messages[i]);
|
|
140
|
+
if (usage) {
|
|
141
|
+
return { usage, index: i };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
/** Estimate context tokens for messages using provider usage when available.
|
|
147
|
+
* `charsPerToken` (design/123 D2): structural coefficient for the anchor-less fallback and the
|
|
148
|
+
* trailing (post-anchor) increment — pass `Model.charsPerToken` so the estimate matches the model. */
|
|
149
|
+
export function estimateContextTokens(messages, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
|
|
150
|
+
const usageInfo = getLastAssistantUsageInfo(messages);
|
|
151
|
+
if (!usageInfo) {
|
|
152
|
+
let estimated = 0;
|
|
153
|
+
for (const message of messages) {
|
|
154
|
+
estimated += estimateTokens(message, charsPerToken);
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
tokens: estimated,
|
|
158
|
+
usageTokens: 0,
|
|
159
|
+
trailingTokens: estimated,
|
|
160
|
+
lastUsageIndex: null,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const usageTokens = calculateContextTokens(usageInfo.usage);
|
|
164
|
+
let trailingTokens = 0;
|
|
165
|
+
for (let i = usageInfo.index + 1; i < messages.length; i++) {
|
|
166
|
+
trailingTokens += estimateTokens(messages[i], charsPerToken);
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
tokens: usageTokens + trailingTokens,
|
|
170
|
+
usageTokens,
|
|
171
|
+
trailingTokens,
|
|
172
|
+
lastUsageIndex: usageInfo.index,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** Return whether context usage exceeds the configured compaction threshold. */
|
|
176
|
+
export function shouldCompact(contextTokens, contextWindow, settings) {
|
|
177
|
+
if (!settings.enabled) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
return contextTokens > contextWindow - settings.reserveTokens;
|
|
181
|
+
}
|
|
182
|
+
/** Estimate token count for one message using a conservative character heuristic.
|
|
183
|
+
* `charsPerToken` (design/123 D2): per-model structural coefficient (default 4 = byte-compatible
|
|
184
|
+
* legacy heuristic). Images contribute a FIXED token weight independent of the coefficient. */
|
|
185
|
+
export function estimateTokens(message, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
|
|
186
|
+
let chars = 0;
|
|
187
|
+
const harnessMessage = message;
|
|
188
|
+
switch (harnessMessage.role) {
|
|
189
|
+
case "user": {
|
|
190
|
+
const content = harnessMessage.content;
|
|
191
|
+
let imageTokens = 0;
|
|
192
|
+
if (typeof content === "string") {
|
|
193
|
+
chars = content.length;
|
|
194
|
+
}
|
|
195
|
+
else if (Array.isArray(content)) {
|
|
196
|
+
for (const block of content) {
|
|
197
|
+
if (block.type === "text" && block.text) {
|
|
198
|
+
chars += block.text.length;
|
|
199
|
+
}
|
|
200
|
+
// Upstream-parity fix (2026-07 diff, openclaw 2ece2945ae class): user-message image blocks
|
|
201
|
+
// previously counted 0 tokens, so image-heavy sessions systematically UNDER-estimated context
|
|
202
|
+
// and compaction triggered late. Mirror the toolResult branch's fixed-weight accounting
|
|
203
|
+
// (image pin + PDF page approximation) so the estimate is symmetric across roles.
|
|
204
|
+
if (block.type === "image") {
|
|
205
|
+
imageTokens += IMAGE_TOKEN_ESTIMATE;
|
|
206
|
+
}
|
|
207
|
+
if (block.type === "document" && typeof block.data === "string") {
|
|
208
|
+
imageTokens += Math.max(IMAGE_TOKEN_ESTIMATE, Math.ceil(block.data.length / 36));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return Math.ceil(chars / charsPerToken) + imageTokens;
|
|
213
|
+
}
|
|
214
|
+
case "assistant": {
|
|
215
|
+
const assistant = harnessMessage;
|
|
216
|
+
for (const block of assistant.content) {
|
|
217
|
+
if (block.type === "text") {
|
|
218
|
+
chars += block.text.length;
|
|
219
|
+
}
|
|
220
|
+
else if (block.type === "thinking") {
|
|
221
|
+
// Count the signature payload too: redacted thinking carries its (billed) content in
|
|
222
|
+
// `thinkingSignature` with an EMPTY `thinking` text, and the block is replayed to the
|
|
223
|
+
// provider on the next request — a structural estimate blind to it under-counts exactly
|
|
224
|
+
// the content the anchor legitimately billed (stale-anchor gate false positive; verify
|
|
225
|
+
// leg F1 on docs/TOKEN-ESTIMATE-CALIBRATION-LIVE-2026-07-09.md). No-op for providers
|
|
226
|
+
// that don't return signatures (e.g. deepseek).
|
|
227
|
+
chars += block.thinking.length + (block.thinkingSignature?.length ?? 0);
|
|
228
|
+
}
|
|
229
|
+
else if (block.type === "toolCall") {
|
|
230
|
+
chars += block.name.length + safeJsonStringify(block.arguments).length;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return Math.ceil(chars / charsPerToken);
|
|
234
|
+
}
|
|
235
|
+
case "custom":
|
|
236
|
+
case "toolResult": {
|
|
237
|
+
let imageTokens = 0;
|
|
238
|
+
if (typeof harnessMessage.content === "string") {
|
|
239
|
+
chars = harnessMessage.content.length;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
for (const block of harnessMessage.content) {
|
|
243
|
+
if (block.type === "text" && block.text) {
|
|
244
|
+
chars += block.text.length;
|
|
245
|
+
}
|
|
246
|
+
if (block.type === "image") {
|
|
247
|
+
// Fixed token weight (design/123 D2 image pin): NOT chars-derived, so the estimate does
|
|
248
|
+
// not drift when the coefficient changes (4800 chars was 1200 tokens at /4 but would
|
|
249
|
+
// become 1600 at /3).
|
|
250
|
+
imageTokens += IMAGE_TOKEN_ESTIMATE;
|
|
251
|
+
}
|
|
252
|
+
if (block.type === "document" && typeof block.data === "string") {
|
|
253
|
+
// PDF read: a document block's cost scales with PAGE COUNT (Anthropic bills ~1,500-3,000
|
|
254
|
+
// tokens/page: each page is charged as an image plus its extracted text), which we cannot
|
|
255
|
+
// see here — approximate pages from payload size (~60KB raw ≈ 80K base64 chars per typical
|
|
256
|
+
// page ⇒ tokens ≈ base64Len × 0.75/61440 × 2250 ≈ len/36), floored at one IMAGE-pin worth
|
|
257
|
+
// so a tiny PDF never under-counts below the CC "≈2000 tokens regardless of format" floor.
|
|
258
|
+
imageTokens += Math.max(IMAGE_TOKEN_ESTIMATE, Math.ceil(block.data.length / 36));
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return Math.ceil(chars / charsPerToken) + imageTokens;
|
|
263
|
+
}
|
|
264
|
+
case "bashExecution": {
|
|
265
|
+
chars = harnessMessage.command.length + harnessMessage.output.length;
|
|
266
|
+
return Math.ceil(chars / charsPerToken);
|
|
267
|
+
}
|
|
268
|
+
case "compactionSummary": {
|
|
269
|
+
chars = harnessMessage.summary.length;
|
|
270
|
+
return Math.ceil(chars / charsPerToken);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return 0;
|
|
274
|
+
}
|
|
275
|
+
function findValidCutPoints(entries, startIndex, endIndex) {
|
|
276
|
+
const cutPoints = [];
|
|
277
|
+
// message-identity Phase 1 coupling (verified 2026-06-28): the chosen cut point becomes `firstKeptEntryId`
|
|
278
|
+
// (the `compacted.preserved_segment` floor a consumer resolves via the `message_committed` wire event, which
|
|
279
|
+
// covers user/assistant/toolResult). This switch ALSO admits `bashExecution`/`custom`/`compactionSummary`
|
|
280
|
+
// message roles + `custom_message` entries as floors — but those have NO producer in this engine (no
|
|
281
|
+
// appendMessage of those roles; nothing queues a `custom_message` write; compactionSummary/custom are
|
|
282
|
+
// build-context reconstructions, not persisted message entries), so a real floor is always user/assistant. If a
|
|
283
|
+
// future change ADDS such a producer, a floor could land on an entry `message_committed` does not emit → extend
|
|
284
|
+
// message-identity coverage (or adopt the first-party `onEntryCommitted` escape hatch). The compaction-floor
|
|
285
|
+
// tripwire in `test/compaction.test.ts` ("message-identity Phase 1") goes RED if that invariant ever breaks.
|
|
286
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
287
|
+
const entry = entries[i];
|
|
288
|
+
switch (entry.type) {
|
|
289
|
+
case "message": {
|
|
290
|
+
const role = entry.message.role;
|
|
291
|
+
switch (role) {
|
|
292
|
+
case "bashExecution":
|
|
293
|
+
case "custom":
|
|
294
|
+
case "compactionSummary":
|
|
295
|
+
case "user":
|
|
296
|
+
case "assistant":
|
|
297
|
+
cutPoints.push(i);
|
|
298
|
+
break;
|
|
299
|
+
case "toolResult":
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
// VENDORED EDIT (design/71 council fold, 2026-06-13): custom_message used to sit in the no-op
|
|
305
|
+
// fall-through AND get pushed by a standalone if AFTER the switch (upstream shape, shared with
|
|
306
|
+
// the deleted branch_summary) — a maintenance trap where editing the switch silently misses the
|
|
307
|
+
// out-of-band push. One source of truth: it IS a valid cut point, said in its own case.
|
|
308
|
+
case "custom_message":
|
|
309
|
+
cutPoints.push(i);
|
|
310
|
+
break;
|
|
311
|
+
case "thinking_level_change":
|
|
312
|
+
case "model_change":
|
|
313
|
+
case "compaction":
|
|
314
|
+
case "custom":
|
|
315
|
+
case "label":
|
|
316
|
+
case "session_info":
|
|
317
|
+
case "leaf":
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return cutPoints;
|
|
322
|
+
}
|
|
323
|
+
/** Find the user-visible message that starts the turn containing an entry. */
|
|
324
|
+
export function findTurnStartIndex(entries, entryIndex, startIndex) {
|
|
325
|
+
for (let i = entryIndex; i >= startIndex; i--) {
|
|
326
|
+
const entry = entries[i];
|
|
327
|
+
if (entry.type === "custom_message") {
|
|
328
|
+
return i;
|
|
329
|
+
}
|
|
330
|
+
if (entry.type === "message") {
|
|
331
|
+
const role = entry.message.role;
|
|
332
|
+
if (role === "user" || role === "bashExecution") {
|
|
333
|
+
return i;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return -1;
|
|
338
|
+
}
|
|
339
|
+
/** Find the compaction cut point that keeps approximately the requested recent-token budget.
|
|
340
|
+
* `charsPerToken` (design/123 D2): the keep-recent accumulation must live in the SAME structural
|
|
341
|
+
* coordinate as the trigger estimate, or the kept tail is systematically over/under-sized. */
|
|
342
|
+
export function findCutPoint(entries, startIndex, endIndex, keepRecentTokens, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
|
|
343
|
+
const cutPoints = findValidCutPoints(entries, startIndex, endIndex);
|
|
344
|
+
if (cutPoints.length === 0) {
|
|
345
|
+
return { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };
|
|
346
|
+
}
|
|
347
|
+
let accumulatedTokens = 0;
|
|
348
|
+
let cutIndex = cutPoints[0];
|
|
349
|
+
for (let i = endIndex - 1; i >= startIndex; i--) {
|
|
350
|
+
const entry = entries[i];
|
|
351
|
+
if (entry.type !== "message") {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
const messageTokens = estimateTokens(entry.message, charsPerToken);
|
|
355
|
+
accumulatedTokens += messageTokens;
|
|
356
|
+
if (accumulatedTokens >= keepRecentTokens) {
|
|
357
|
+
let found = false;
|
|
358
|
+
for (const cutPoint of cutPoints) {
|
|
359
|
+
if (cutPoint >= i) {
|
|
360
|
+
cutIndex = cutPoint;
|
|
361
|
+
found = true;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// VENDORED EDIT (audit A-2 / design/64 §28.3): when the keep budget is exhausted INSIDE the
|
|
366
|
+
// trailing tool-result batch (tool results are not valid cut points, so no cutPoint ≥ i
|
|
367
|
+
// exists — e.g. two parallel 50KB reads ≥ keepRecentTokens at a within-task boundary), the
|
|
368
|
+
// old fallback was cutPoints[0] = the EARLIEST cut point: nearly the whole history was kept,
|
|
369
|
+
// messagesToSummarize came out empty, the model hallucinated a summary from an empty
|
|
370
|
+
// conversation (bypassing the empty-summary guard), context GREW, freedTokens=0 inflated the
|
|
371
|
+
// §25.2 regrowth floor past the window, and within-task compaction shut down for the rest of
|
|
372
|
+
// the task. Correct fallback: the LARGEST cut point ≤ i — keep the oversized batch (slightly
|
|
373
|
+
// over budget) and summarize everything before it. The normal path (a cut point at/after i
|
|
374
|
+
// exists) is unchanged.
|
|
375
|
+
if (!found) {
|
|
376
|
+
for (let c = cutPoints.length - 1; c >= 0; c--) {
|
|
377
|
+
if (cutPoints[c] <= i) {
|
|
378
|
+
cutIndex = cutPoints[c];
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
while (cutIndex > startIndex) {
|
|
387
|
+
const prevEntry = entries[cutIndex - 1];
|
|
388
|
+
if (prevEntry.type === "compaction") {
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
if (prevEntry.type === "message") {
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
cutIndex--;
|
|
395
|
+
}
|
|
396
|
+
const cutEntry = entries[cutIndex];
|
|
397
|
+
const isUserMessage = cutEntry.type === "message" && cutEntry.message.role === "user";
|
|
398
|
+
const turnStartIndex = isUserMessage ? -1 : findTurnStartIndex(entries, cutIndex, startIndex);
|
|
399
|
+
return {
|
|
400
|
+
firstKeptEntryIndex: cutIndex,
|
|
401
|
+
turnStartIndex,
|
|
402
|
+
isSplitTurn: !isUserMessage && turnStartIndex !== -1,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
export const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.
|
|
406
|
+
|
|
407
|
+
Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;
|
|
408
|
+
// VENDORED EDIT (design/64 §22 / design/66 D / channel [73], clay 2026-06-10 vendored-edit policy), realigned
|
|
409
|
+
// 2026-07-08 (CC 2.1.198 compaction parity batch W:C1/C2/C3, bench/cc-parity-toolsuite/
|
|
410
|
+
// compaction-cc198-verbatim-capture-2026-07-08.md §A1a): the 9 section names, the analysis checklist, and the
|
|
411
|
+
// security-relevant-instructions preservation clauses (two occurrences — analysis checklist + section 6) are
|
|
412
|
+
// CC 198 T$n VERBATIM. Deliberate sema supersets kept: the fenced `<conversation>` input framing (C9/H5
|
|
413
|
+
// posture — CC sees the raw fork context instead) and the `<analysis>` scratch block being STRIPPED before
|
|
414
|
+
// persisting (maybeCompact; CC keeps its own <analysis>/<summary> post-processing). No `<summary>` output tag
|
|
415
|
+
// requested: our injection adds the fencing at render time (COMPACTION_SUMMARY_PREFIX/SUFFIX).
|
|
416
|
+
// Mirrored in UPDATE_SUMMARIZATION_PROMPT (the update pass is a sema superset — CC is fresh-pass only).
|
|
417
|
+
const SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
|
|
418
|
+
This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context. Another LLM will use it to continue the work.
|
|
419
|
+
|
|
420
|
+
Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. This analysis is scratch work — it will be stripped and NOT kept, so it is only to help you write a faithful summary. In your analysis process:
|
|
421
|
+
|
|
422
|
+
1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
|
|
423
|
+
- The user's explicit requests and intents
|
|
424
|
+
- Your approach to addressing the user's requests
|
|
425
|
+
- Key decisions, technical concepts and code patterns
|
|
426
|
+
- Specific details like:
|
|
427
|
+
- file names
|
|
428
|
+
- full code snippets
|
|
429
|
+
- function signatures
|
|
430
|
+
- file edits
|
|
431
|
+
- Errors that you ran into and how you fixed them
|
|
432
|
+
- Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
|
|
433
|
+
- Note any security-relevant instructions or constraints the user stated (e.g., sensitive files or data to avoid, operations that must not be performed, credential or secret handling rules). These MUST be preserved verbatim in the summary so they continue to apply after compaction.
|
|
434
|
+
2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.
|
|
435
|
+
|
|
436
|
+
Then, after </analysis>, write the summary. Your summary should include the following sections:
|
|
437
|
+
|
|
438
|
+
1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
|
|
439
|
+
2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
|
|
440
|
+
3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
|
|
441
|
+
4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
|
|
442
|
+
5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
|
|
443
|
+
6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent. Preserve any security-relevant instructions or constraints verbatim so they remain in effect after compaction.
|
|
444
|
+
7. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
|
|
445
|
+
8. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
|
|
446
|
+
9. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests or really old requests that were already completed without confirming with the user first.
|
|
447
|
+
If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.
|
|
448
|
+
|
|
449
|
+
Please provide your summary based on the conversation so far, following this structure and ensuring precision and thoroughness in your response.
|
|
450
|
+
|
|
451
|
+
Keep each section concise. Preserve exact file paths, function names, and error messages.`;
|
|
452
|
+
const UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.
|
|
453
|
+
|
|
454
|
+
Update the existing structured summary with new information. RULES:
|
|
455
|
+
- PRESERVE all existing information from the previous summary
|
|
456
|
+
- ADD new progress, decisions, and context from the new messages
|
|
457
|
+
- UPDATE "Pending Tasks" and "Current Work" based on what was accomplished
|
|
458
|
+
- UPDATE "Optional Next Step" based on the most recent work
|
|
459
|
+
- PRESERVE exact file paths, function names, and error messages
|
|
460
|
+
- Preserve any security-relevant instructions or constraints verbatim so they remain in effect after compaction
|
|
461
|
+
- If something is no longer relevant, you may remove it
|
|
462
|
+
|
|
463
|
+
First, inside an <analysis>...</analysis> block, note what is new since the previous summary and what must change. This analysis is scratch work — it will be stripped and NOT kept. Then, after </analysis>, write the updated summary with the following sections:
|
|
464
|
+
|
|
465
|
+
1. Primary Request and Intent: [Preserve existing requests and intents, add new ones if the task expanded]
|
|
466
|
+
2. Key Technical Concepts: [Preserve existing, add newly discussed concepts, technologies, and frameworks]
|
|
467
|
+
3. Files and Code Sections: [Preserve entries still relevant; add newly examined, modified, or created files with full code snippets where applicable]
|
|
468
|
+
4. Errors and fixes: [Preserve previous errors and fixes and add new ones; keep any user correction or "change of approach" feedback verbatim.]
|
|
469
|
+
5. Problem Solving: [Update problems solved and any ongoing troubleshooting efforts]
|
|
470
|
+
6. All user messages: [Preserve previously-recorded user messages VERBATIM and append any new ones that are not tool results, in order. To bound growth across repeated compactions, keep roughly the most recent 20 messages verbatim; older ones beyond that may be condensed to a single line each — but NEVER drop or paraphrase a user correction or change of direction. The exact words of recent messages are the strongest anti-drift signal. Preserve any security-relevant instructions or constraints verbatim so they remain in effect after compaction.]
|
|
471
|
+
7. Pending Tasks: [Update based on progress — remove completed tasks, add newly requested ones]
|
|
472
|
+
8. Current Work: [Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant]
|
|
473
|
+
9. Optional Next Step: [Update based on current state. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request — include a direct verbatim quote of that request. Do not start on tangential requests or really old requests that were already completed.]
|
|
474
|
+
|
|
475
|
+
Keep each section concise. Preserve exact file paths, function names, and error messages.`;
|
|
476
|
+
function createSummarizationOptions(model, maxTokens, apiKey, headers, signal, thinkingLevel) {
|
|
477
|
+
const options = { maxTokens, signal, apiKey, headers };
|
|
478
|
+
if (model.reasoning && thinkingLevel && thinkingLevel !== "off") {
|
|
479
|
+
options.reasoning = thinkingLevel;
|
|
480
|
+
}
|
|
481
|
+
return options;
|
|
482
|
+
}
|
|
483
|
+
async function completeSummarization(model, context, options, streamFn, runtime) {
|
|
484
|
+
if (streamFn) {
|
|
485
|
+
return (await streamFn(model, context, options)).result();
|
|
486
|
+
}
|
|
487
|
+
return await resolveAgentCoreCompleteFn(runtime)(model, context, options);
|
|
488
|
+
}
|
|
489
|
+
// design/118 follow-up (live-caught 2026-07-02): a reserve-derived output budget (0.8×/0.5× reserveTokens —
|
|
490
|
+
// 320/200 tokens at the 400 default) is fully consumed by REASONING before any summary text on a reasoning
|
|
491
|
+
// model. Proven live on Qwen with thinking:"off": the gateway reasons by DEFAULT regardless of the requested
|
|
492
|
+
// thinking level, and the brain surfaces "max_tokens cut with no answer text" as `stopReason:"error"` +
|
|
493
|
+
// `errorKind:"length_empty"` — NOT a "length" stop (see brain/openai.ts `truncatedEmpty`). Both summary paths
|
|
494
|
+
// (history AND turn-prefix — the live-observed failure was the turn-prefix one) then fail at every boundary
|
|
495
|
+
// and compaction never lands. Recovery, shared by both paths:
|
|
496
|
+
// (a) a reasoning model's budget is floored at SUMMARY_REASONING_FLOOR up front — gated on `model.reasoning`
|
|
497
|
+
// alone, because the thinking level is irrelevant when the gateway thinks by default;
|
|
498
|
+
// (b) `length_empty` errors escalate the budget to at least the floor and then ×2 per retry
|
|
499
|
+
// (≤SUMMARY_MAX_ESCALATIONS) — the error is DIRECT evidence the model reasons (stronger than the
|
|
500
|
+
// catalog flag), so a mis-catalogued `reasoning:false` model jumps straight to the floor instead of
|
|
501
|
+
// doubling from a tiny reserve-derived base that three retries can never rescue;
|
|
502
|
+
// (c) a "length"-truncated response whose text is ONLY <analysis> scratch (closed, or an unterminated
|
|
503
|
+
// LINE-ANCHORED tail — provably scratch: the cut landed before the summary) escalates the same way
|
|
504
|
+
// instead of flowing a scratch-only "summary" upstream (the persisted strip removes closed pairs only,
|
|
505
|
+
// by design).
|
|
506
|
+
// Budget legality (dual-track review MAJOR): every candidate is clamped to the WINDOW headroom left by the
|
|
507
|
+
// summarization request itself — compaction fires when the context is at its fullest, and on strict gateways
|
|
508
|
+
// `input + max_tokens > contextWindow` is a hard HTTP 400 (no finish_reason, no errorKind → unrecoverable).
|
|
509
|
+
// The reserve-derived base is constructively safe (< reserveTokens ≤ headroom), so the clamp never goes
|
|
510
|
+
// below it; the floor/escalations get whatever headroom actually exists.
|
|
511
|
+
// The floor deliberately lets the OUTPUT budget exceed the reserve-derived cap: the summary TEXT length is
|
|
512
|
+
// bounded by the prompt's format/brevity constraints, the headroom is for reasoning scratch, and the
|
|
513
|
+
// alternative is proven to produce NO summary at all (maybeCompact's empty-summary and freed-tokens guards
|
|
514
|
+
// bound the pathological cases).
|
|
515
|
+
const SUMMARY_REASONING_FLOOR = 2048;
|
|
516
|
+
const SUMMARY_MAX_ESCALATIONS = 2;
|
|
517
|
+
const SUMMARY_WINDOW_MARGIN = 256; // slack for the chars/4 input estimate vs the gateway's real tokenizer
|
|
518
|
+
// design/123 D2 (应改): coefficient-aware — the input estimated here is sent to the SUMMARY model,
|
|
519
|
+
// so the caller passes that model's charsPerToken. An underestimate risks a strict-gateway 400
|
|
520
|
+
// (`input + max_tokens > contextWindow`); on cpt=3-class models chars/4 was exactly that underestimate.
|
|
521
|
+
function estimateSummarizationInputTokens(context, charsPerToken) {
|
|
522
|
+
let chars = context.systemPrompt?.length ?? 0;
|
|
523
|
+
for (const m of context.messages) {
|
|
524
|
+
const content = m.content;
|
|
525
|
+
if (typeof content === "string") {
|
|
526
|
+
chars += content.length;
|
|
527
|
+
}
|
|
528
|
+
else if (Array.isArray(content)) {
|
|
529
|
+
for (const c of content) {
|
|
530
|
+
chars += c.text?.length ?? 0;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return Math.ceil(chars / charsPerToken);
|
|
535
|
+
}
|
|
536
|
+
// MF-18 修② (blackboard [496]③ E-leg): the summarization INPUT was unbounded — generateSummary
|
|
537
|
+
// serialized the WHOLE summarized span into one prompt, so a ~300K-token session became a request far
|
|
538
|
+
// past the COMPACTION model's own window. A strict gateway hard-rejects it (prompt-too-long →
|
|
539
|
+
// CompactionError("summarization_failed")) at EVERY boundary; three strikes open the §17.4 breaker,
|
|
540
|
+
// which then silently moots a later manual /compact — the diagnosed E→C compound. Clamp the
|
|
541
|
+
// CONVERSATION text (never the instructions / system prompt) to the window headroom left after the
|
|
542
|
+
// fixed prompt parts, the output budget the length-recovery loop may escalate to (the reasoning
|
|
543
|
+
// floor), and the estimate margin. Shape: head + elision marker + tail — the head keeps the
|
|
544
|
+
// objective / early decisions, the tail keeps the span closest to the kept history (and on an UPDATE
|
|
545
|
+
// pass `previousSummary` already covers the older ground); the middle is the cheapest loss for a
|
|
546
|
+
// summary. A lossy-but-landing summary strictly beats the status quo (no summary, breaker open,
|
|
547
|
+
// compaction dead for the rest of the task — trimToBudget then drops the same content with zero
|
|
548
|
+
// summarization at all).
|
|
549
|
+
const SUMMARY_INPUT_HEAD_RATIO = 0.25;
|
|
550
|
+
const SUMMARY_INPUT_MIN_KEEP_CHARS = 1024; // pathological tiny window: still send SOMETHING (the gateway, not core, is then the honest failure)
|
|
551
|
+
const SUMMARY_INPUT_MARKER_RESERVE = 200; // elision marker + splice slack, chars
|
|
552
|
+
function clampSummarizationConversation(conversationText, model, charsPerToken, fixedPromptChars, baseMaxTokens,
|
|
553
|
+
// W:C16 — a reactive PTL retry tightens the budget below the window-derived estimate (the gateway's
|
|
554
|
+
// real tokenizer proved the estimate too generous). Applies even when the window is unknown: the
|
|
555
|
+
// gateway's prompt-too-long error is then the only budget evidence there is.
|
|
556
|
+
budgetCapChars) {
|
|
557
|
+
let budgetChars = Number.POSITIVE_INFINITY;
|
|
558
|
+
if (model.contextWindow > 0) {
|
|
559
|
+
// Output reservation matches summarizeWithLengthRecovery's worst legal ask: the reasoning floor
|
|
560
|
+
// (length_empty/scratch escalation jumps straight to it, even on a mis-catalogued model) or the
|
|
561
|
+
// reserve-derived base when that is already larger. Double margin: input estimate slack on top of
|
|
562
|
+
// the same slack the windowCap math applies on the output side.
|
|
563
|
+
const outputReserve = Math.max(baseMaxTokens, SUMMARY_REASONING_FLOOR);
|
|
564
|
+
budgetChars =
|
|
565
|
+
(model.contextWindow - outputReserve - 2 * SUMMARY_WINDOW_MARGIN) * charsPerToken - fixedPromptChars;
|
|
566
|
+
}
|
|
567
|
+
if (budgetCapChars !== undefined) {
|
|
568
|
+
budgetChars = Math.min(budgetChars, budgetCapChars);
|
|
569
|
+
}
|
|
570
|
+
if (!Number.isFinite(budgetChars) || conversationText.length <= budgetChars) {
|
|
571
|
+
return { text: conversationText, droppedChars: 0, keptChars: conversationText.length }; // in budget (or window unknown and no retry cap — nothing sound to clamp against)
|
|
572
|
+
}
|
|
573
|
+
const keep = Math.max(budgetChars - SUMMARY_INPUT_MARKER_RESERVE, SUMMARY_INPUT_MIN_KEEP_CHARS);
|
|
574
|
+
const headChars = Math.floor(keep * SUMMARY_INPUT_HEAD_RATIO);
|
|
575
|
+
const tailChars = keep - headChars;
|
|
576
|
+
const elided = conversationText.length - headChars - tailChars;
|
|
577
|
+
const text = conversationText.slice(0, headChars) +
|
|
578
|
+
`\n\n[... ${elided} characters of the conversation elided so the summarization request fits the compaction model's context window ...]\n\n` +
|
|
579
|
+
conversationText.slice(conversationText.length - tailChars);
|
|
580
|
+
return { text, droppedChars: elided, keptChars: headChars + tailChars };
|
|
581
|
+
}
|
|
582
|
+
// ---------------------------------------------------------------------------------------------------
|
|
583
|
+
// W:C16 (CC 2.1.198 compaction parity batch 2026-07-08) — REACTIVE prompt-too-long retry, the CC-family
|
|
584
|
+
// complement to the proactive clamp above. CC has NO pre-send truncation at all: T$n + the full
|
|
585
|
+
// conversation are sent as-is and a PTL error drives the KNl retry loop (≤ VNl=3 attempts, dropping
|
|
586
|
+
// whole message GROUPS from the head, gap-guided by the token counts in the error text, marking the
|
|
587
|
+
// cut with the jNl meta message). sema keeps the clamp as first line of defense (estimate-based,
|
|
588
|
+
// prevents most PTLs before they happen) and adds this loop as the second: when the gateway's REAL
|
|
589
|
+
// tokenizer still rejects the clamped request (chars/N is an estimate; strict gateways count exactly),
|
|
590
|
+
// tighten the budget by the reported gap, drop the OLDEST assistant-turn groups to fit, mark the cut
|
|
591
|
+
// with CC's verbatim retry marker, and try again — only an unrecoverable failure after
|
|
592
|
+
// COMPACTION_PTL_MAX_RETRIES walks the existing failure path (CompactionError → caller breaker).
|
|
593
|
+
// ---------------------------------------------------------------------------------------------------
|
|
594
|
+
const COMPACTION_PTL_MAX_RETRIES = 3; // CC 198 VNl = 3
|
|
595
|
+
/** CC 198 jNl — verbatim marker inserted where the oldest conversation groups were dropped. */
|
|
596
|
+
export const COMPACTION_PTL_RETRY_MARKER = "[earlier conversation truncated for compaction retry]";
|
|
597
|
+
const PTL_NO_GAP_DROP_FRACTION = 0.2; // CC 198 KNl fallback: gap unparsable → shave ~20% (at least one group)
|
|
598
|
+
const PTL_GAP_SAFETY = 1.2; // slack when converting a token gap to chars — under-shaving guarantees another PTL
|
|
599
|
+
// CC 198 L231884 verbatim gap regex ("prompt is too long: 12345 tokens > 10000 maximum" family).
|
|
600
|
+
const PTL_CC_GAP_RE = /prompt is too long[^0-9]*(\d+) tokens? > (\d+)/i;
|
|
601
|
+
// OpenAI-completions-family gateways (our brain surfaces the provider text verbatim in errorMessage):
|
|
602
|
+
// "This model's maximum context length is 128000 tokens. However, your messages resulted in 131072 tokens".
|
|
603
|
+
const PTL_OPENAI_GAP_RE = /maximum context length is (\d+) tokens?[^0-9]*?(\d+) tokens?/i;
|
|
604
|
+
// Classifier for gap-less PTL variants across gateways. Consulted ONLY for summarization-request
|
|
605
|
+
// failures, and a false positive merely burns ≤3 bounded, smaller retries.
|
|
606
|
+
const PTL_CLASS_RE = /prompt is too long|too many tokens|input is too long|context[ _-]?length|context window|exceeds? the (?:model'?s? )?context/i;
|
|
607
|
+
// 双轨复审 1.257.3 (codex LOW + opus confirmed): the gap-less class above is deliberately broad (missing
|
|
608
|
+
// a real PTL variant opens the breaker permanently — worse than ≤3 bounded retries), but a message that
|
|
609
|
+
// merely MENTIONS the context window while being a server/config fault must not trigger history-dropping
|
|
610
|
+
// retries. Deny wins over the class match; the gap'd regexes above stay authoritative either way.
|
|
611
|
+
const PTL_DENY_RE = /internal (?:server )?error|http 5\d\d|status(?: code)?[: ]5\d\d|invalid (?:api key|request)|configuration|unauthorized|permission/i;
|
|
612
|
+
function parsePromptTooLong(message) {
|
|
613
|
+
if (!message) {
|
|
614
|
+
return { isPtl: false };
|
|
615
|
+
}
|
|
616
|
+
const cc = PTL_CC_GAP_RE.exec(message);
|
|
617
|
+
if (cc) {
|
|
618
|
+
const actual = Number(cc[1]);
|
|
619
|
+
const limit = Number(cc[2]);
|
|
620
|
+
return { isPtl: true, ...(actual > limit ? { gapTokens: actual - limit } : {}) };
|
|
621
|
+
}
|
|
622
|
+
const oa = PTL_OPENAI_GAP_RE.exec(message);
|
|
623
|
+
if (oa) {
|
|
624
|
+
const limit = Number(oa[1]);
|
|
625
|
+
const requested = Number(oa[2]);
|
|
626
|
+
return { isPtl: true, ...(requested > limit ? { gapTokens: requested - limit } : {}) };
|
|
627
|
+
}
|
|
628
|
+
return { isPtl: PTL_CLASS_RE.test(message) && !PTL_DENY_RE.test(message) };
|
|
629
|
+
}
|
|
630
|
+
/** CC 198 wpt-family grouping: one assistant turn = one group (the assistant message plus its tool
|
|
631
|
+
* results; any user/context messages leading into that turn ride with it). Dropping whole groups from
|
|
632
|
+
* the head keeps tool_use/tool_result pairs and turn coherence intact — a mid-turn char cut does not. */
|
|
633
|
+
function splitMessageGroups(messages) {
|
|
634
|
+
const groups = [];
|
|
635
|
+
let current = [];
|
|
636
|
+
let sawAssistant = false;
|
|
637
|
+
for (const m of messages) {
|
|
638
|
+
if (sawAssistant && m.role !== "toolResult") {
|
|
639
|
+
groups.push(current);
|
|
640
|
+
current = [];
|
|
641
|
+
sawAssistant = false;
|
|
642
|
+
}
|
|
643
|
+
current.push(m);
|
|
644
|
+
if (m.role === "assistant") {
|
|
645
|
+
sawAssistant = true;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
if (current.length > 0) {
|
|
649
|
+
groups.push(current);
|
|
650
|
+
}
|
|
651
|
+
return groups;
|
|
652
|
+
}
|
|
653
|
+
/** Serialize → clamp (proactive, sema superset) → summarize; on a gateway prompt-too-long, tighten the
|
|
654
|
+
* budget by the reported token gap, drop the OLDEST groups (CC KNl shape), mark the cut with
|
|
655
|
+
* {@link COMPACTION_PTL_RETRY_MARKER}, and retry ≤ {@link COMPACTION_PTL_MAX_RETRIES} times. Each drop
|
|
656
|
+
* is disclosed through the same `compaction.input_truncated` observer the clamp uses. */
|
|
657
|
+
async function summarizeWithPtlRetry(req) {
|
|
658
|
+
const disclose = (droppedChars, keptChars) => {
|
|
659
|
+
if (droppedChars <= 0) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
// Observer isolation: a throwing callback must never fail the compaction it merely observes.
|
|
663
|
+
try {
|
|
664
|
+
req.onInputTruncated?.({ label: req.truncationLabel, droppedChars, keptChars });
|
|
665
|
+
}
|
|
666
|
+
catch {
|
|
667
|
+
/* observe-only */
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
let groups = splitMessageGroups(req.llmMessages);
|
|
671
|
+
let droppedForRetry = false;
|
|
672
|
+
let budgetCapChars;
|
|
673
|
+
for (let retry = 0;; retry++) {
|
|
674
|
+
const serialized = serializeConversation(groups.flat());
|
|
675
|
+
const conversationText = droppedForRetry
|
|
676
|
+
? `${COMPACTION_PTL_RETRY_MARKER}\n\n${serialized}`
|
|
677
|
+
: serialized;
|
|
678
|
+
const clamped = clampSummarizationConversation(conversationText, req.model, req.cpt, req.fixedPromptChars, req.baseMaxTokens, budgetCapChars);
|
|
679
|
+
// Fired BEFORE the summary call (fidelity disclosure survives a later failure).
|
|
680
|
+
disclose(clamped.droppedChars, clamped.keptChars);
|
|
681
|
+
const context = {
|
|
682
|
+
systemPrompt: SUMMARIZATION_SYSTEM_PROMPT,
|
|
683
|
+
messages: [
|
|
684
|
+
{
|
|
685
|
+
role: "user",
|
|
686
|
+
content: [{ type: "text", text: req.buildPromptText(clamped.text) }],
|
|
687
|
+
timestamp: Date.now(),
|
|
688
|
+
},
|
|
689
|
+
],
|
|
690
|
+
};
|
|
691
|
+
let result;
|
|
692
|
+
let thrown;
|
|
693
|
+
let didThrow = false;
|
|
694
|
+
try {
|
|
695
|
+
result = await summarizeWithLengthRecovery(req.label, req.model, context, req.baseMaxTokens, req.apiKey, req.headers, req.signal, req.thinkingLevel, req.streamFn, req.runtime, req.charsPerToken);
|
|
696
|
+
}
|
|
697
|
+
catch (e) {
|
|
698
|
+
// A strict gateway may surface the 400 as a THROW instead of a stopReason:"error" response —
|
|
699
|
+
// classify it the same way; anything non-PTL rethrows untouched.
|
|
700
|
+
didThrow = true;
|
|
701
|
+
thrown = e;
|
|
702
|
+
}
|
|
703
|
+
if (!didThrow && result && result.ok) {
|
|
704
|
+
return result;
|
|
705
|
+
}
|
|
706
|
+
const failureMessage = didThrow
|
|
707
|
+
? thrown instanceof Error
|
|
708
|
+
? thrown.message
|
|
709
|
+
: String(thrown)
|
|
710
|
+
: result && !result.ok
|
|
711
|
+
? result.error.message
|
|
712
|
+
: "";
|
|
713
|
+
const ptl = parsePromptTooLong(failureMessage);
|
|
714
|
+
if (!ptl.isPtl || retry >= COMPACTION_PTL_MAX_RETRIES || req.signal?.aborted) {
|
|
715
|
+
if (didThrow) {
|
|
716
|
+
throw thrown;
|
|
717
|
+
}
|
|
718
|
+
return result;
|
|
719
|
+
}
|
|
720
|
+
// Gap-guided budget tightening (CC w_a shape): the error's own token counts say how far over the
|
|
721
|
+
// request was; without them fall back to a fixed fraction. The tightened budget also caps every
|
|
722
|
+
// LATER attempt's clamp (monotonically decreasing — the loop cannot oscillate).
|
|
723
|
+
const sentChars = clamped.text.length;
|
|
724
|
+
const gapChars = ptl.gapTokens !== undefined
|
|
725
|
+
? Math.ceil(ptl.gapTokens * req.cpt * PTL_GAP_SAFETY)
|
|
726
|
+
: Math.ceil(sentChars * PTL_NO_GAP_DROP_FRACTION);
|
|
727
|
+
budgetCapChars = Math.max(SUMMARY_INPUT_MIN_KEEP_CHARS, sentChars - Math.max(gapChars, 1));
|
|
728
|
+
// CC-family group rollback: drop the OLDEST assistant-turn groups until the remaining serialized
|
|
729
|
+
// conversation fits the tightened budget. Always keep at least one group — the clamp cap above is
|
|
730
|
+
// the backstop when a single group is itself oversized (head+tail char cut, sema shape).
|
|
731
|
+
// opus 1.257.3 review (LOW, scale fix): the rollback target lives on the PRE-clamp serialized scale,
|
|
732
|
+
// so it must be derived on that scale too (beforeChars − gap) — comparing the full serialized length
|
|
733
|
+
// against the POST-clamp budgetCapChars would, after a heavy proactive clamp (serialized ≫ sent),
|
|
734
|
+
// shed almost every group on the first retry regardless of the reported gap. budgetCapChars (the
|
|
735
|
+
// clamp's cap, post-clamp scale) is unchanged — each leg tightens on its own scale.
|
|
736
|
+
const beforeChars = serialized.length;
|
|
737
|
+
const rollbackTargetChars = Math.max(SUMMARY_INPUT_MIN_KEEP_CHARS, beforeChars - Math.max(gapChars, 1));
|
|
738
|
+
let remainingChars = beforeChars;
|
|
739
|
+
while (groups.length > 1 && remainingChars > rollbackTargetChars) {
|
|
740
|
+
const dropped = groups.shift();
|
|
741
|
+
remainingChars -= serializeConversation(dropped).length + 2; // +2 ≈ the "\n\n" part joiner
|
|
742
|
+
}
|
|
743
|
+
droppedForRetry = true;
|
|
744
|
+
disclose(beforeChars - Math.max(remainingChars, 0), Math.max(remainingChars, 0));
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
function stripAnalysisScratch(text, lengthTruncated) {
|
|
748
|
+
// Closed pairs always (mirrors the persisted strip in maybeCompact); an UNTERMINATED trailing block only
|
|
749
|
+
// when the response was length-truncated — then the tail is provably scratch. Outside the truncation case
|
|
750
|
+
// an unterminated tag is left intact rather than swallowing a real summary (design/66 D #1).
|
|
751
|
+
let out = text.replace(/<analysis>[\s\S]*?<\/analysis>\s*/gi, "");
|
|
752
|
+
if (lengthTruncated) {
|
|
753
|
+
// Line-anchored (dual-track review): the model's scratch block always opens at the start of the response
|
|
754
|
+
// or of a line, while a literal "<analysis>" QUOTED by the summary (verbatim user messages / error text —
|
|
755
|
+
// the prompt demands verbatim preservation) is almost always mid-line. Anchoring keeps the target case
|
|
756
|
+
// (pure-scratch tail) while not swallowing real summary text from a mid-line quotation onward.
|
|
757
|
+
out = out.replace(/(?:^|\n)<analysis>[\s\S]*$/i, "");
|
|
758
|
+
}
|
|
759
|
+
return out;
|
|
760
|
+
}
|
|
761
|
+
async function summarizeWithLengthRecovery(label, model, context, baseMaxTokens, apiKey, headers, signal, thinkingLevel, streamFn, runtime, charsPerToken) {
|
|
762
|
+
// design/123 D2: the structural coefficient for the SUMMARY model's input estimate — explicit
|
|
763
|
+
// caller override first, then the model's own declaration, then the /4 default.
|
|
764
|
+
const cpt = charsPerToken ?? model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN;
|
|
765
|
+
const modelCap = model.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY;
|
|
766
|
+
const windowCap = model.contextWindow > 0
|
|
767
|
+
? Math.max(baseMaxTokens, model.contextWindow - estimateSummarizationInputTokens(context, cpt) - SUMMARY_WINDOW_MARGIN)
|
|
768
|
+
: Number.POSITIVE_INFINITY;
|
|
769
|
+
const cap = Math.min(modelCap, windowCap);
|
|
770
|
+
let maxTokens = Math.min(cap, model.reasoning ? Math.max(baseMaxTokens, SUMMARY_REASONING_FLOOR) : baseMaxTokens);
|
|
771
|
+
for (let attempt = 0;; attempt++) {
|
|
772
|
+
const canEscalate = attempt < SUMMARY_MAX_ESCALATIONS && maxTokens < cap;
|
|
773
|
+
const response = await completeSummarization(model, context, createSummarizationOptions(model, maxTokens, apiKey, headers, signal, thinkingLevel), streamFn, runtime);
|
|
774
|
+
if (response.stopReason === "aborted") {
|
|
775
|
+
return err(new CompactionError("aborted", response.errorMessage || `${label} aborted`));
|
|
776
|
+
}
|
|
777
|
+
if (response.stopReason === "error") {
|
|
778
|
+
if (response.errorKind === "length_empty") {
|
|
779
|
+
if (canEscalate) {
|
|
780
|
+
// Direct evidence the model reasons → jump to at least the floor (see header note (b)).
|
|
781
|
+
maxTokens = Math.min(cap, Math.max(maxTokens * 2, SUMMARY_REASONING_FLOOR));
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
// Unified diagnostics (codex review): an exhausted length_empty IS the empty-summary outcome —
|
|
785
|
+
// keep the C5 "empty summary" phrase so outer matchers see ONE contract for both empty paths.
|
|
786
|
+
return err(new CompactionError("summarization_failed", `${label} produced an empty summary (stopReason=error, max_tokens exhausted by reasoning ` +
|
|
787
|
+
`after ${attempt + 1} attempt(s): ${response.errorMessage || "no detail"})`));
|
|
788
|
+
}
|
|
789
|
+
return err(new CompactionError("summarization_failed", `${label} failed: ${response.errorMessage || "Unknown error"}`));
|
|
790
|
+
}
|
|
791
|
+
const lengthTruncated = response.stopReason === "length";
|
|
792
|
+
const raw = response.content
|
|
793
|
+
.filter((c) => c.type === "text")
|
|
794
|
+
.map((c) => c.text)
|
|
795
|
+
.join("\n");
|
|
796
|
+
const usable = stripAnalysisScratch(raw, lengthTruncated);
|
|
797
|
+
if (usable.trim() !== "") {
|
|
798
|
+
// Partial-but-present beats a skipped compaction. On a length cut return the text minus the
|
|
799
|
+
// provably-scratch unterminated tail; otherwise return raw (the persisted closed-pair strip is upstream).
|
|
800
|
+
return ok(lengthTruncated ? usable : raw);
|
|
801
|
+
}
|
|
802
|
+
if (lengthTruncated && canEscalate) {
|
|
803
|
+
maxTokens = Math.min(cap, Math.max(maxTokens * 2, SUMMARY_REASONING_FLOOR));
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
// Empty after the scratch strip and no (further) escalation: fail LOUDLY instead of returning "" — an
|
|
807
|
+
// empty ok() would reach compact()'s file-ops footer append and could persist a footer-only "summary"
|
|
808
|
+
// (the maybeCompact empty guard only sees the combined string). Wording keeps the C5 vendor-contract
|
|
809
|
+
// phrase "empty summary" (test/compaction.test.ts §26.7 pins it).
|
|
810
|
+
// Deliberate tradeoff (dual-track review): on the SPLIT-TURN path this also turns the old "empty
|
|
811
|
+
// turn-prefix quietly degrades to a landed history summary + dangling Turn-Context header" into a whole-
|
|
812
|
+
// boundary failure that counts toward maybeCompact's breaker. A silent half-summary hid real gateway
|
|
813
|
+
// flakiness; the breaker exists precisely to surface repeated summary failures.
|
|
814
|
+
return err(new CompactionError("summarization_failed", `${label} produced an empty summary (stopReason=${response.stopReason}` +
|
|
815
|
+
`${lengthTruncated ? ", the output was analysis scratch cut at max_tokens" : ""})`));
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
/** Generate or update a conversation summary for compaction. */
|
|
819
|
+
export async function generateSummary(currentMessages, model, reserveTokens, apiKey, headers, signal, customInstructions, previousSummary, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated) {
|
|
820
|
+
let basePrompt = previousSummary ? UPDATE_SUMMARIZATION_PROMPT : SUMMARIZATION_PROMPT;
|
|
821
|
+
if (customInstructions) {
|
|
822
|
+
// W:C6 — CC 198 verbatim injection shape (`\n\nAdditional Instructions:\n${e}`, three prompt家族一致).
|
|
823
|
+
basePrompt = `${basePrompt}\n\nAdditional Instructions:\n${customInstructions}`;
|
|
824
|
+
}
|
|
825
|
+
const llmMessages = convertToLlm(currentMessages);
|
|
826
|
+
// MF-18 修② + W:C16: the serialized conversation is bounded by the SUMMARY model's window BEFORE the
|
|
827
|
+
// call (clampSummarizationConversation, sema proactive superset) and, when the gateway's real
|
|
828
|
+
// tokenizer still rejects it, by the reactive PTL retry loop (CC 198 KNl family — see
|
|
829
|
+
// summarizeWithPtlRetry). Fixed parts = system prompt + instructions + previous summary
|
|
830
|
+
// + tag/format overhead — all sent verbatim, so they charge the budget at full length.
|
|
831
|
+
return summarizeWithPtlRetry({
|
|
832
|
+
label: "Summarization",
|
|
833
|
+
truncationLabel: "history",
|
|
834
|
+
llmMessages,
|
|
835
|
+
buildPromptText: (conversationText) => {
|
|
836
|
+
let promptText = `<conversation>\n${conversationText}\n</conversation>\n\n`;
|
|
837
|
+
if (previousSummary) {
|
|
838
|
+
promptText += `<previous-summary>\n${previousSummary}\n</previous-summary>\n\n`;
|
|
839
|
+
}
|
|
840
|
+
promptText += basePrompt;
|
|
841
|
+
return promptText;
|
|
842
|
+
},
|
|
843
|
+
model,
|
|
844
|
+
cpt: charsPerToken ?? model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN,
|
|
845
|
+
fixedPromptChars: SUMMARIZATION_SYSTEM_PROMPT.length + basePrompt.length + (previousSummary?.length ?? 0) + 128,
|
|
846
|
+
baseMaxTokens: Math.floor(0.8 * reserveTokens),
|
|
847
|
+
apiKey,
|
|
848
|
+
headers,
|
|
849
|
+
signal,
|
|
850
|
+
thinkingLevel,
|
|
851
|
+
streamFn,
|
|
852
|
+
runtime,
|
|
853
|
+
charsPerToken,
|
|
854
|
+
onInputTruncated,
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
/** Prepare session entries for compaction, or return undefined when compaction is not applicable.
|
|
858
|
+
* `charsPerToken` (design/123 D2, signature threading): keeps `tokensBefore` and the cut-point
|
|
859
|
+
* accounting in the same per-model structural coordinate as the caller's trigger estimate. */
|
|
860
|
+
export function prepareCompaction(pathEntries, settings, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
|
|
861
|
+
if (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === "compaction") {
|
|
862
|
+
return ok(undefined);
|
|
863
|
+
}
|
|
864
|
+
let prevCompactionIndex = -1;
|
|
865
|
+
for (let i = pathEntries.length - 1; i >= 0; i--) {
|
|
866
|
+
if (pathEntries[i].type === "compaction") {
|
|
867
|
+
prevCompactionIndex = i;
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
let previousSummary;
|
|
872
|
+
let boundaryStart = 0;
|
|
873
|
+
if (prevCompactionIndex >= 0) {
|
|
874
|
+
const prevCompaction = pathEntries[prevCompactionIndex];
|
|
875
|
+
previousSummary = prevCompaction.summary;
|
|
876
|
+
const firstKeptEntryIndex = pathEntries.findIndex((entry) => entry.id === prevCompaction.firstKeptEntryId);
|
|
877
|
+
boundaryStart = firstKeptEntryIndex >= 0 ? firstKeptEntryIndex : prevCompactionIndex + 1;
|
|
878
|
+
}
|
|
879
|
+
const boundaryEnd = pathEntries.length;
|
|
880
|
+
const tokensBefore = estimateContextTokens(buildSessionContext(pathEntries).messages, charsPerToken).tokens;
|
|
881
|
+
const cutPoint = findCutPoint(pathEntries, boundaryStart, boundaryEnd, settings.keepRecentTokens, charsPerToken);
|
|
882
|
+
const firstKeptEntry = pathEntries[cutPoint.firstKeptEntryIndex];
|
|
883
|
+
if (!firstKeptEntry?.id) {
|
|
884
|
+
return err(new CompactionError("invalid_session", "First kept entry has no UUID - session may need migration"));
|
|
885
|
+
}
|
|
886
|
+
const firstKeptEntryId = firstKeptEntry.id;
|
|
887
|
+
const historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;
|
|
888
|
+
const messagesToSummarize = [];
|
|
889
|
+
for (let i = boundaryStart; i < historyEnd; i++) {
|
|
890
|
+
const msg = getMessageFromEntryForCompaction(pathEntries[i]);
|
|
891
|
+
if (msg) {
|
|
892
|
+
messagesToSummarize.push(msg);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
const turnPrefixMessages = [];
|
|
896
|
+
if (cutPoint.isSplitTurn) {
|
|
897
|
+
for (let i = cutPoint.turnStartIndex; i < cutPoint.firstKeptEntryIndex; i++) {
|
|
898
|
+
const msg = getMessageFromEntryForCompaction(pathEntries[i]);
|
|
899
|
+
if (msg) {
|
|
900
|
+
turnPrefixMessages.push(msg);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
// VENDORED EDIT (audit A-2 + R-2 round-3 council): compaction is NOT APPLICABLE when there is nothing
|
|
905
|
+
// to summarize at all — no prior history AND (not a split turn, OR a split turn whose prefix is ALSO
|
|
906
|
+
// empty). The original A-2 guard tested only `!isSplitTurn`, missing the split-turn-with-empty-prefix
|
|
907
|
+
// corner: there `compact()` falls through both branches to `generateSummary([])` and the model
|
|
908
|
+
// hallucinates a "summary" from nothing that ADDS tokens while freeing none. A split turn WITH a
|
|
909
|
+
// non-empty prefix is legitimately compactable (the prefix gets summarized), so it is NOT caught here.
|
|
910
|
+
// Return undefined so the caller treats it as a quiet no-op.
|
|
911
|
+
if (messagesToSummarize.length === 0 && (!cutPoint.isSplitTurn || turnPrefixMessages.length === 0)) {
|
|
912
|
+
return ok(undefined);
|
|
913
|
+
}
|
|
914
|
+
const fileOps = extractFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);
|
|
915
|
+
if (cutPoint.isSplitTurn) {
|
|
916
|
+
for (const msg of turnPrefixMessages) {
|
|
917
|
+
extractFileOpsFromMessage(msg, fileOps);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
return ok({
|
|
921
|
+
firstKeptEntryId,
|
|
922
|
+
messagesToSummarize,
|
|
923
|
+
turnPrefixMessages,
|
|
924
|
+
isSplitTurn: cutPoint.isSplitTurn,
|
|
925
|
+
tokensBefore,
|
|
926
|
+
previousSummary,
|
|
927
|
+
fileOps,
|
|
928
|
+
settings,
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
const TURN_PREFIX_SUMMARIZATION_PROMPT = `This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.
|
|
932
|
+
|
|
933
|
+
Summarize the prefix to provide context for the retained suffix:
|
|
934
|
+
|
|
935
|
+
## Original Request
|
|
936
|
+
[What did the user ask for in this turn?]
|
|
937
|
+
|
|
938
|
+
## Early Progress
|
|
939
|
+
- [Key decisions and work done in the prefix]
|
|
940
|
+
|
|
941
|
+
## Context for Suffix
|
|
942
|
+
- [Information needed to understand the retained recent work]
|
|
943
|
+
|
|
944
|
+
Be concise. Focus on what's needed to understand the kept suffix.`;
|
|
945
|
+
export { computeFileLists, serializeConversation } from "./utils.js";
|
|
946
|
+
/** Generate compaction summary data from prepared session history.
|
|
947
|
+
* `charsPerToken` (design/123 D2, signature threading): coefficient for the summarization-input
|
|
948
|
+
* window guard. Defaults to the SUMMARY model's own `charsPerToken` (the estimated input is sent to
|
|
949
|
+
* THAT model), then 4. */
|
|
950
|
+
export async function compact(preparation, model, apiKey, headers, customInstructions, signal, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated) {
|
|
951
|
+
const { firstKeptEntryId, messagesToSummarize, turnPrefixMessages, isSplitTurn, tokensBefore, previousSummary, fileOps, settings, } = preparation;
|
|
952
|
+
if (!firstKeptEntryId) {
|
|
953
|
+
return err(new CompactionError("invalid_session", "First kept entry has no UUID - session may need migration"));
|
|
954
|
+
}
|
|
955
|
+
// VENDORED EDIT (audit A-2 + R-2 round-3 council, defense-in-depth): an empty conversation must never
|
|
956
|
+
// reach generateSummary (the model hallucinates a "summary" from nothing that ADDS tokens, frees none).
|
|
957
|
+
// `prepareCompaction` returns undefined for this shape, so reaching here means a hand-constructed
|
|
958
|
+
// preparation — fail loudly. The condition mirrors the prepare guard: nothing to summarize AND no
|
|
959
|
+
// usable split-turn prefix (the split branch below needs `turnPrefixMessages.length > 0`; without it,
|
|
960
|
+
// an empty `messagesToSummarize` falls through to the else branch's `generateSummary([])`).
|
|
961
|
+
if (messagesToSummarize.length === 0 && (!isSplitTurn || turnPrefixMessages.length === 0)) {
|
|
962
|
+
return err(new CompactionError("summarization_failed", "Nothing to summarize (empty preparation)"));
|
|
963
|
+
}
|
|
964
|
+
let summary;
|
|
965
|
+
if (isSplitTurn && turnPrefixMessages.length > 0) {
|
|
966
|
+
const [historyResult, turnPrefixResult] = await Promise.all([
|
|
967
|
+
messagesToSummarize.length > 0
|
|
968
|
+
? generateSummary(messagesToSummarize, model, settings.reserveTokens, apiKey, headers, signal, customInstructions, previousSummary, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated)
|
|
969
|
+
: // bug-hunt #1: a split-turn 2nd+ compaction where the cut splits the FIRST turn after the prior
|
|
970
|
+
// boundary leaves `messagesToSummarize` empty (historyEnd === boundaryStart) while `previousSummary`
|
|
971
|
+
// IS set. The old literal `"No prior history."` then fully SUPERSEDED the accumulated S1..Sn chain
|
|
972
|
+
// (buildSessionContext represents all pre-firstKept history with only the latest summary) — a silent,
|
|
973
|
+
// irreversible history erasure AND active contradiction on ordinary long tasks. With nothing new to
|
|
974
|
+
// fold in, the previous summary IS the complete history → thread it through verbatim (no model call,
|
|
975
|
+
// zero hallucination, faithful). Only truly-first compaction (no previousSummary) keeps the literal.
|
|
976
|
+
// Strip the prior summary's embedded file-ops footer (dual-review NIT): the canonical SUPERSET footer
|
|
977
|
+
// is re-appended below from `fileOps` (seeded with `prevCompaction.details`) — keeping the stale
|
|
978
|
+
// embedded one would duplicate it.
|
|
979
|
+
Promise.resolve(ok(previousSummary ? stripFileOperationsFooter(previousSummary) : "No prior history.")),
|
|
980
|
+
generateTurnPrefixSummary(turnPrefixMessages, model, settings.reserveTokens, apiKey, headers, signal, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated),
|
|
981
|
+
]);
|
|
982
|
+
if (!historyResult.ok) {
|
|
983
|
+
return err(historyResult.error);
|
|
984
|
+
}
|
|
985
|
+
if (!turnPrefixResult.ok) {
|
|
986
|
+
return err(turnPrefixResult.error);
|
|
987
|
+
}
|
|
988
|
+
summary = `${historyResult.value}\n\n---\n\n**Turn Context (split turn):**\n\n${turnPrefixResult.value}`;
|
|
989
|
+
}
|
|
990
|
+
else {
|
|
991
|
+
const summaryResult = await generateSummary(messagesToSummarize, model, settings.reserveTokens, apiKey, headers, signal, customInstructions, previousSummary, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated);
|
|
992
|
+
if (!summaryResult.ok) {
|
|
993
|
+
return err(summaryResult.error);
|
|
994
|
+
}
|
|
995
|
+
summary = summaryResult.value;
|
|
996
|
+
}
|
|
997
|
+
const { readFiles, modifiedFiles, modifiedFilesByRecency } = computeFileLists(fileOps);
|
|
998
|
+
summary += formatFileOperations(readFiles, modifiedFiles);
|
|
999
|
+
return ok({
|
|
1000
|
+
summary,
|
|
1001
|
+
firstKeptEntryId,
|
|
1002
|
+
tokensBefore,
|
|
1003
|
+
details: { readFiles, modifiedFiles, modifiedFilesByRecency },
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
async function generateTurnPrefixSummary(messages, model, reserveTokens, apiKey, headers, signal, thinkingLevel, streamFn, runtime, charsPerToken, onInputTruncated) {
|
|
1007
|
+
const llmMessages = convertToLlm(messages);
|
|
1008
|
+
// MF-18 修② + W:C16: same window bound + reactive PTL retry as generateSummary — the live-caught
|
|
1009
|
+
// failure mode hit BOTH summary paths (an oversized split-turn prefix is rarer but identical in
|
|
1010
|
+
// effect: gateway prompt-too-long).
|
|
1011
|
+
return summarizeWithPtlRetry({
|
|
1012
|
+
label: "Turn prefix summarization",
|
|
1013
|
+
truncationLabel: "turn_prefix",
|
|
1014
|
+
llmMessages,
|
|
1015
|
+
buildPromptText: (conversationText) => `<conversation>\n${conversationText}\n</conversation>\n\n${TURN_PREFIX_SUMMARIZATION_PROMPT}`,
|
|
1016
|
+
model,
|
|
1017
|
+
cpt: charsPerToken ?? model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN,
|
|
1018
|
+
fixedPromptChars: SUMMARIZATION_SYSTEM_PROMPT.length + TURN_PREFIX_SUMMARIZATION_PROMPT.length + 128,
|
|
1019
|
+
baseMaxTokens: Math.floor(0.5 * reserveTokens),
|
|
1020
|
+
apiKey,
|
|
1021
|
+
headers,
|
|
1022
|
+
signal,
|
|
1023
|
+
thinkingLevel,
|
|
1024
|
+
streamFn,
|
|
1025
|
+
runtime,
|
|
1026
|
+
charsPerToken,
|
|
1027
|
+
onInputTruncated,
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
//# sourceMappingURL=compaction.js.map
|