@orion-agents/orion-code 0.1.7 → 0.1.9
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 +445 -0
- package/README.md +60 -41
- package/README.zh-CN.md +34 -8
- package/dist/agents/coordinator.d.ts.map +1 -1
- package/dist/agents/coordinator.js +49 -9
- package/dist/agents/coordinator.js.map +1 -1
- package/dist/agents/fork.d.ts +5 -1
- package/dist/agents/fork.d.ts.map +1 -1
- package/dist/agents/fork.js +9 -10
- package/dist/agents/fork.js.map +1 -1
- package/dist/agents/worker-pool.d.ts.map +1 -1
- package/dist/agents/worker-pool.js +8 -3
- package/dist/agents/worker-pool.js.map +1 -1
- package/dist/cli.js +6 -6
- package/dist/cli.js.map +1 -1
- package/dist/commands/context-tool-command-handlers.d.ts.map +1 -1
- package/dist/commands/context-tool-command-handlers.js +42 -0
- package/dist/commands/context-tool-command-handlers.js.map +1 -1
- package/dist/commands/core-command-handlers.d.ts.map +1 -1
- package/dist/commands/core-command-handlers.js +3 -4
- package/dist/commands/core-command-handlers.js.map +1 -1
- package/dist/commands/diagnostic-command-handlers.d.ts.map +1 -1
- package/dist/commands/diagnostic-command-handlers.js +3 -0
- package/dist/commands/diagnostic-command-handlers.js.map +1 -1
- package/dist/commands/model-command-handlers.d.ts +1 -1
- package/dist/commands/model-command-handlers.d.ts.map +1 -1
- package/dist/commands/model-command-handlers.js +166 -1
- package/dist/commands/model-command-handlers.js.map +1 -1
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +7 -3
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/session-command-handlers.d.ts.map +1 -1
- package/dist/commands/session-command-handlers.js +97 -5
- package/dist/commands/session-command-handlers.js.map +1 -1
- package/dist/commands/session-commands.js +2 -2
- package/dist/commands/session-commands.js.map +1 -1
- package/dist/commands/types.d.ts +6 -0
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/workflow-command-handlers.d.ts.map +1 -1
- package/dist/commands/workflow-command-handlers.js +2 -2
- package/dist/commands/workflow-command-handlers.js.map +1 -1
- package/dist/commands/workflow-commands.d.ts.map +1 -1
- package/dist/commands/workflow-commands.js +1 -1
- package/dist/commands/workflow-commands.js.map +1 -1
- package/dist/core/checkpoint.d.ts.map +1 -1
- package/dist/core/checkpoint.js +9 -8
- package/dist/core/checkpoint.js.map +1 -1
- package/dist/framework/index.d.ts +5 -3
- package/dist/framework/index.d.ts.map +1 -1
- package/dist/framework/index.js +9 -1
- package/dist/framework/index.js.map +1 -1
- package/dist/framework/prompt.d.ts +1 -1
- package/dist/framework/prompt.d.ts.map +1 -1
- package/dist/framework/prompt.js +5 -4
- package/dist/framework/prompt.js.map +1 -1
- package/dist/framework/query.d.ts +30 -4
- package/dist/framework/query.d.ts.map +1 -1
- package/dist/framework/query.js +329 -62
- package/dist/framework/query.js.map +1 -1
- package/dist/framework/stop-decision.d.ts +56 -0
- package/dist/framework/stop-decision.d.ts.map +1 -0
- package/dist/framework/stop-decision.js +36 -0
- package/dist/framework/stop-decision.js.map +1 -0
- package/dist/framework/store.d.ts.map +1 -1
- package/dist/framework/store.js +4 -4
- package/dist/framework/store.js.map +1 -1
- package/dist/framework/tool-scheduler.d.ts +23 -13
- package/dist/framework/tool-scheduler.d.ts.map +1 -1
- package/dist/framework/tool-scheduler.js +93 -77
- package/dist/framework/tool-scheduler.js.map +1 -1
- package/dist/framework/tool.d.ts +7 -0
- package/dist/framework/tool.d.ts.map +1 -1
- package/dist/framework/tool.js +9 -0
- package/dist/framework/tool.js.map +1 -1
- package/dist/harness/assembler.d.ts.map +1 -1
- package/dist/harness/assembler.js +77 -19
- package/dist/harness/assembler.js.map +1 -1
- package/dist/harness/capability-profile.d.ts +3 -0
- package/dist/harness/capability-profile.d.ts.map +1 -0
- package/dist/harness/capability-profile.js +44 -0
- package/dist/harness/capability-profile.js.map +1 -0
- package/dist/harness/capsule.d.ts.map +1 -1
- package/dist/harness/capsule.js +22 -3
- package/dist/harness/capsule.js.map +1 -1
- package/dist/harness/compact-benchmark-corpus.d.ts +10 -0
- package/dist/harness/compact-benchmark-corpus.d.ts.map +1 -0
- package/dist/harness/compact-benchmark-corpus.js +56 -0
- package/dist/harness/compact-benchmark-corpus.js.map +1 -0
- package/dist/harness/context-harness.d.ts +23 -3
- package/dist/harness/context-harness.d.ts.map +1 -1
- package/dist/harness/context-harness.js +183 -11
- package/dist/harness/context-harness.js.map +1 -1
- package/dist/harness/contract.d.ts.map +1 -1
- package/dist/harness/contract.js +106 -11
- package/dist/harness/contract.js.map +1 -1
- package/dist/harness/drift-guard.d.ts +2 -1
- package/dist/harness/drift-guard.d.ts.map +1 -1
- package/dist/harness/drift-guard.js +315 -20
- package/dist/harness/drift-guard.js.map +1 -1
- package/dist/harness/evidence.d.ts.map +1 -1
- package/dist/harness/evidence.js +25 -12
- package/dist/harness/evidence.js.map +1 -1
- package/dist/harness/index.d.ts +7 -2
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +19 -1
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/ledger.d.ts.map +1 -1
- package/dist/harness/ledger.js +44 -14
- package/dist/harness/ledger.js.map +1 -1
- package/dist/harness/progress-controller.d.ts +14 -0
- package/dist/harness/progress-controller.d.ts.map +1 -0
- package/dist/harness/progress-controller.js +110 -0
- package/dist/harness/progress-controller.js.map +1 -0
- package/dist/harness/state.d.ts.map +1 -1
- package/dist/harness/state.js +5 -2
- package/dist/harness/state.js.map +1 -1
- package/dist/harness/stop-controller.d.ts +15 -0
- package/dist/harness/stop-controller.d.ts.map +1 -0
- package/dist/harness/stop-controller.js +87 -0
- package/dist/harness/stop-controller.js.map +1 -0
- package/dist/harness/types.d.ts +137 -0
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/verification.d.ts +7 -0
- package/dist/harness/verification.d.ts.map +1 -0
- package/dist/harness/verification.js +122 -0
- package/dist/harness/verification.js.map +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/ink-ui/screens/ReplScreen.d.ts +3 -0
- package/dist/ink-ui/screens/ReplScreen.d.ts.map +1 -1
- package/dist/ink-ui/screens/ReplScreen.js +30 -5
- package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +1 -0
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/prompt-context.d.ts +42 -0
- package/dist/memory/prompt-context.d.ts.map +1 -0
- package/dist/memory/prompt-context.js +129 -0
- package/dist/memory/prompt-context.js.map +1 -0
- package/dist/print-ui/launch.d.ts +1 -0
- package/dist/print-ui/launch.d.ts.map +1 -1
- package/dist/print-ui/launch.js +5 -2
- package/dist/print-ui/launch.js.map +1 -1
- package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
- package/dist/runtime/agent-runtime-controller.js +60 -22
- package/dist/runtime/agent-runtime-controller.js.map +1 -1
- package/dist/runtime/chat-checkpoint.d.ts.map +1 -1
- package/dist/runtime/chat-checkpoint.js +2 -5
- package/dist/runtime/chat-checkpoint.js.map +1 -1
- package/dist/runtime/chat-command-scope.d.ts +5 -0
- package/dist/runtime/chat-command-scope.d.ts.map +1 -0
- package/dist/runtime/chat-command-scope.js +22 -0
- package/dist/runtime/chat-command-scope.js.map +1 -0
- package/dist/runtime/chat-compact.d.ts +26 -0
- package/dist/runtime/chat-compact.d.ts.map +1 -0
- package/dist/runtime/chat-compact.js +132 -0
- package/dist/runtime/chat-compact.js.map +1 -0
- package/dist/runtime/chat-controller.d.ts.map +1 -1
- package/dist/runtime/chat-controller.js +102 -130
- package/dist/runtime/chat-controller.js.map +1 -1
- package/dist/runtime/chat-presentation.d.ts +6 -3
- package/dist/runtime/chat-presentation.d.ts.map +1 -1
- package/dist/runtime/chat-presentation.js +30 -6
- package/dist/runtime/chat-presentation.js.map +1 -1
- package/dist/runtime/goals/coordinator.d.ts +8 -0
- package/dist/runtime/goals/coordinator.d.ts.map +1 -1
- package/dist/runtime/goals/coordinator.js +103 -30
- package/dist/runtime/goals/coordinator.js.map +1 -1
- package/dist/runtime/goals/evidence.d.ts +10 -0
- package/dist/runtime/goals/evidence.d.ts.map +1 -1
- package/dist/runtime/goals/evidence.js +18 -0
- package/dist/runtime/goals/evidence.js.map +1 -1
- package/dist/runtime/goals/lifecycle.d.ts +13 -0
- package/dist/runtime/goals/lifecycle.d.ts.map +1 -0
- package/dist/runtime/goals/lifecycle.js +46 -0
- package/dist/runtime/goals/lifecycle.js.map +1 -0
- package/dist/runtime/goals/objective.d.ts +18 -0
- package/dist/runtime/goals/objective.d.ts.map +1 -0
- package/dist/runtime/goals/objective.js +60 -0
- package/dist/runtime/goals/objective.js.map +1 -0
- package/dist/runtime/goals/prompt.d.ts.map +1 -1
- package/dist/runtime/goals/prompt.js +7 -1
- package/dist/runtime/goals/prompt.js.map +1 -1
- package/dist/runtime/goals/stop-policy.d.ts +9 -0
- package/dist/runtime/goals/stop-policy.d.ts.map +1 -0
- package/dist/runtime/goals/stop-policy.js +83 -0
- package/dist/runtime/goals/stop-policy.js.map +1 -0
- package/dist/runtime/goals/tools.d.ts.map +1 -1
- package/dist/runtime/goals/tools.js +2 -2
- package/dist/runtime/goals/tools.js.map +1 -1
- package/dist/runtime/goals/types.d.ts +4 -1
- package/dist/runtime/goals/types.d.ts.map +1 -1
- package/dist/runtime/goals/types.js +2 -1
- package/dist/runtime/goals/types.js.map +1 -1
- package/dist/runtime/loop-budget.d.ts +2 -0
- package/dist/runtime/loop-budget.d.ts.map +1 -1
- package/dist/runtime/loop-budget.js +6 -2
- package/dist/runtime/loop-budget.js.map +1 -1
- package/dist/runtime/model-coordinator.d.ts +44 -1
- package/dist/runtime/model-coordinator.d.ts.map +1 -1
- package/dist/runtime/model-coordinator.js +161 -19
- package/dist/runtime/model-coordinator.js.map +1 -1
- package/dist/runtime/subagents/index.d.ts +1 -1
- package/dist/runtime/subagents/index.d.ts.map +1 -1
- package/dist/runtime/subagents/index.js.map +1 -1
- package/dist/runtime/subagents/production.d.ts +6 -2
- package/dist/runtime/subagents/production.d.ts.map +1 -1
- package/dist/runtime/subagents/production.js +25 -6
- package/dist/runtime/subagents/production.js.map +1 -1
- package/dist/runtime/subagents/runner.d.ts +12 -1
- package/dist/runtime/subagents/runner.d.ts.map +1 -1
- package/dist/runtime/subagents/runner.js +62 -1
- package/dist/runtime/subagents/runner.js.map +1 -1
- package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -1
- package/dist/runtime/subagents/runtime-integration.js +2 -1
- package/dist/runtime/subagents/runtime-integration.js.map +1 -1
- package/dist/runtime/subagents/supervisor.d.ts.map +1 -1
- package/dist/runtime/subagents/supervisor.js +6 -0
- package/dist/runtime/subagents/supervisor.js.map +1 -1
- package/dist/runtime/subagents/types.d.ts +4 -1
- package/dist/runtime/subagents/types.d.ts.map +1 -1
- package/dist/runtime/subagents/types.js.map +1 -1
- package/dist/runtime/ui-events.d.ts +37 -1
- package/dist/runtime/ui-events.d.ts.map +1 -1
- package/dist/runtime/ui-events.js.map +1 -1
- package/dist/runtime/ui-view-model.d.ts +10 -1
- package/dist/runtime/ui-view-model.d.ts.map +1 -1
- package/dist/runtime/ui-view-model.js +93 -4
- package/dist/runtime/ui-view-model.js.map +1 -1
- package/dist/services/bounded-response.d.ts +12 -0
- package/dist/services/bounded-response.d.ts.map +1 -0
- package/dist/services/bounded-response.js +67 -0
- package/dist/services/bounded-response.js.map +1 -0
- package/dist/services/compact/auto-compact.d.ts +82 -2
- package/dist/services/compact/auto-compact.d.ts.map +1 -1
- package/dist/services/compact/auto-compact.js +226 -44
- package/dist/services/compact/auto-compact.js.map +1 -1
- package/dist/services/compact/compact.d.ts +54 -37
- package/dist/services/compact/compact.d.ts.map +1 -1
- package/dist/services/compact/compact.js +512 -127
- package/dist/services/compact/compact.js.map +1 -1
- package/dist/services/compact/coordinator.d.ts +5 -1
- package/dist/services/compact/coordinator.d.ts.map +1 -1
- package/dist/services/compact/coordinator.js +10 -1
- package/dist/services/compact/coordinator.js.map +1 -1
- package/dist/services/compact/fingerprint.d.ts +27 -0
- package/dist/services/compact/fingerprint.d.ts.map +1 -0
- package/dist/services/compact/fingerprint.js +69 -0
- package/dist/services/compact/fingerprint.js.map +1 -0
- package/dist/services/compact/index.d.ts +7 -5
- package/dist/services/compact/index.d.ts.map +1 -1
- package/dist/services/compact/index.js +19 -6
- package/dist/services/compact/index.js.map +1 -1
- package/dist/services/compact/planner.d.ts +41 -0
- package/dist/services/compact/planner.d.ts.map +1 -0
- package/dist/services/compact/planner.js +102 -0
- package/dist/services/compact/planner.js.map +1 -0
- package/dist/services/compact/semantic-summary.d.ts +93 -0
- package/dist/services/compact/semantic-summary.d.ts.map +1 -0
- package/dist/services/compact/semantic-summary.js +158 -0
- package/dist/services/compact/semantic-summary.js.map +1 -0
- package/dist/services/compact/summary-generator.d.ts +23 -0
- package/dist/services/compact/summary-generator.d.ts.map +1 -1
- package/dist/services/compact/summary-generator.js +173 -39
- package/dist/services/compact/summary-generator.js.map +1 -1
- package/dist/services/concurrent-sessions.d.ts +1 -0
- package/dist/services/concurrent-sessions.d.ts.map +1 -1
- package/dist/services/concurrent-sessions.js +35 -22
- package/dist/services/concurrent-sessions.js.map +1 -1
- package/dist/services/file-context.d.ts.map +1 -1
- package/dist/services/file-context.js +29 -33
- package/dist/services/file-context.js.map +1 -1
- package/dist/services/file-lock.d.ts.map +1 -1
- package/dist/services/file-lock.js +60 -27
- package/dist/services/file-lock.js.map +1 -1
- package/dist/services/global-config.d.ts +6 -0
- package/dist/services/global-config.d.ts.map +1 -1
- package/dist/services/global-config.js +23 -13
- package/dist/services/global-config.js.map +1 -1
- package/dist/services/goal-storage.d.ts +1 -1
- package/dist/services/goal-storage.d.ts.map +1 -1
- package/dist/services/goal-storage.js +14 -4
- package/dist/services/goal-storage.js.map +1 -1
- package/dist/services/llm.d.ts +3 -0
- package/dist/services/llm.d.ts.map +1 -1
- package/dist/services/llm.js +7 -0
- package/dist/services/llm.js.map +1 -1
- package/dist/services/project-instructions.d.ts +8 -0
- package/dist/services/project-instructions.d.ts.map +1 -1
- package/dist/services/project-instructions.js +101 -51
- package/dist/services/project-instructions.js.map +1 -1
- package/dist/services/provider-resilience/request-gate.d.ts +9 -5
- package/dist/services/provider-resilience/request-gate.d.ts.map +1 -1
- package/dist/services/provider-resilience/request-gate.js +71 -23
- package/dist/services/provider-resilience/request-gate.js.map +1 -1
- package/dist/services/safe-project-reader.d.ts +30 -0
- package/dist/services/safe-project-reader.d.ts.map +1 -0
- package/dist/services/safe-project-reader.js +141 -0
- package/dist/services/safe-project-reader.js.map +1 -0
- package/dist/services/session-storage.d.ts +146 -10
- package/dist/services/session-storage.d.ts.map +1 -1
- package/dist/services/session-storage.js +851 -120
- package/dist/services/session-storage.js.map +1 -1
- package/dist/services/tool-allowlist.d.ts +4 -4
- package/dist/services/tool-allowlist.js +4 -4
- package/dist/services/usage-state.d.ts +7 -0
- package/dist/services/usage-state.d.ts.map +1 -1
- package/dist/services/usage-state.js +117 -16
- package/dist/services/usage-state.js.map +1 -1
- package/dist/services/web-search-adapters.d.ts.map +1 -1
- package/dist/services/web-search-adapters.js +24 -10
- package/dist/services/web-search-adapters.js.map +1 -1
- package/dist/services/web-search-mcp.d.ts.map +1 -1
- package/dist/services/web-search-mcp.js +13 -3
- package/dist/services/web-search-mcp.js.map +1 -1
- package/dist/services/workspace-containment.d.ts +8 -0
- package/dist/services/workspace-containment.d.ts.map +1 -0
- package/dist/services/workspace-containment.js +44 -0
- package/dist/services/workspace-containment.js.map +1 -0
- package/dist/skills/runtime.d.ts.map +1 -1
- package/dist/skills/runtime.js +34 -35
- package/dist/skills/runtime.js.map +1 -1
- package/dist/terminal-ui/completion.d.ts.map +1 -1
- package/dist/terminal-ui/completion.js +5 -1
- package/dist/terminal-ui/completion.js.map +1 -1
- package/dist/terminal-ui/launch.d.ts +5 -0
- package/dist/terminal-ui/launch.d.ts.map +1 -1
- package/dist/terminal-ui/launch.js +53 -17
- package/dist/terminal-ui/launch.js.map +1 -1
- package/dist/tools/git.d.ts.map +1 -1
- package/dist/tools/git.js +47 -12
- package/dist/tools/git.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +73 -64
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan.d.ts.map +1 -1
- package/dist/tools/plan.js +7 -6
- package/dist/tools/plan.js.map +1 -1
- package/dist/tools/web.d.ts.map +1 -1
- package/dist/tools/web.js +11 -2
- package/dist/tools/web.js.map +1 -1
- package/dist/tui-ui/chrome-view-model.js +1 -1
- package/dist/tui-ui/chrome-view-model.js.map +1 -1
- package/dist/tui-ui/inline-surface.d.ts +1 -1
- package/dist/tui-ui/inline-surface.d.ts.map +1 -1
- package/dist/tui-ui/inline-surface.js +24 -16
- package/dist/tui-ui/inline-surface.js.map +1 -1
- package/dist/tui-ui/state.d.ts.map +1 -1
- package/dist/tui-ui/state.js +93 -13
- package/dist/tui-ui/state.js.map +1 -1
- package/dist/tui-ui/transcript-layout.d.ts.map +1 -1
- package/dist/tui-ui/transcript-layout.js +38 -29
- package/dist/tui-ui/transcript-layout.js.map +1 -1
- package/dist/ui/command-panel.d.ts +2 -0
- package/dist/ui/command-panel.d.ts.map +1 -1
- package/dist/ui/command-panel.js +46 -20
- package/dist/ui/command-panel.js.map +1 -1
- package/dist/ui/file-completion.d.ts.map +1 -1
- package/dist/ui/file-completion.js +12 -6
- package/dist/ui/file-completion.js.map +1 -1
- package/dist/ui/shared/command-palette.d.ts.map +1 -1
- package/dist/ui/shared/command-palette.js +13 -9
- package/dist/ui/shared/command-palette.js.map +1 -1
- package/dist/ui/shared/text.d.ts +2 -0
- package/dist/ui/shared/text.d.ts.map +1 -1
- package/dist/ui/shared/text.js +20 -12
- package/dist/ui/shared/text.js.map +1 -1
- package/dist/ui/suggestions.d.ts.map +1 -1
- package/dist/ui/suggestions.js +7 -6
- package/dist/ui/suggestions.js.map +1 -1
- package/docs/migration/v0.1.8-to-v0.1.9.md +60 -0
- package/docs/plan/v0.1.9-release-checklist.md +64 -0
- package/docs/readme.md +27 -0
- package/npm-shrinkwrap.json +7124 -0
- package/package.json +17 -7
- package/dist/ink/index.d.ts +0 -54
- package/dist/ink/index.d.ts.map +0 -1
- package/dist/ink/index.js +0 -111
- package/dist/ink/index.js.map +0 -1
- package/dist/services/compact/micro-compact.d.ts +0 -21
- package/dist/services/compact/micro-compact.d.ts.map +0 -1
- package/dist/services/compact/micro-compact.js +0 -99
- package/dist/services/compact/micro-compact.js.map +0 -1
- package/dist/ui-v2/components/command-palette.d.ts +0 -2
- package/dist/ui-v2/components/command-palette.d.ts.map +0 -1
- package/dist/ui-v2/components/command-palette.js +0 -18
- package/dist/ui-v2/components/command-palette.js.map +0 -1
- package/dist/ui-v2/components/edit-preview-picker.d.ts +0 -26
- package/dist/ui-v2/components/edit-preview-picker.d.ts.map +0 -1
- package/dist/ui-v2/components/edit-preview-picker.js +0 -79
- package/dist/ui-v2/components/edit-preview-picker.js.map +0 -1
- package/dist/ui-v2/components/session-picker.d.ts +0 -19
- package/dist/ui-v2/components/session-picker.d.ts.map +0 -1
- package/dist/ui-v2/components/session-picker.js +0 -52
- package/dist/ui-v2/components/session-picker.js.map +0 -1
- package/dist/ui-v2/components/shell.d.ts +0 -36
- package/dist/ui-v2/components/shell.d.ts.map +0 -1
- package/dist/ui-v2/components/shell.js +0 -131
- package/dist/ui-v2/components/shell.js.map +0 -1
- package/dist/ui-v2/index.d.ts +0 -11
- package/dist/ui-v2/index.d.ts.map +0 -1
- package/dist/ui-v2/index.js +0 -27
- package/dist/ui-v2/index.js.map +0 -1
- package/dist/ui-v2/runtime/text.d.ts +0 -2
- package/dist/ui-v2/runtime/text.d.ts.map +0 -1
- package/dist/ui-v2/runtime/text.js +0 -18
- package/dist/ui-v2/runtime/text.js.map +0 -1
- package/dist/ui-v2/state/input-reducer.d.ts +0 -39
- package/dist/ui-v2/state/input-reducer.d.ts.map +0 -1
- package/dist/ui-v2/state/input-reducer.js +0 -82
- package/dist/ui-v2/state/input-reducer.js.map +0 -1
- package/dist/ui-v2/state/picker.d.ts +0 -16
- package/dist/ui-v2/state/picker.d.ts.map +0 -1
- package/dist/ui-v2/state/picker.js +0 -52
- package/dist/ui-v2/state/picker.js.map +0 -1
- package/dist/ui-v2/state/sessions.d.ts +0 -15
- package/dist/ui-v2/state/sessions.d.ts.map +0 -1
- package/dist/ui-v2/state/sessions.js +0 -70
- package/dist/ui-v2/state/sessions.js.map +0 -1
- package/dist/ui-v2/state/suggestions.d.ts +0 -2
- package/dist/ui-v2/state/suggestions.d.ts.map +0 -1
- package/dist/ui-v2/state/suggestions.js +0 -18
- package/dist/ui-v2/state/suggestions.js.map +0 -1
- package/dist/ui-v2/types.d.ts +0 -2
- package/dist/ui-v2/types.d.ts.map +0 -1
- package/dist/ui-v2/types.js +0 -18
- package/dist/ui-v2/types.js.map +0 -1
|
@@ -10,6 +10,8 @@ exports.SESSION_SIDECAR_SUFFIXES = exports.redactTraceText = void 0;
|
|
|
10
10
|
exports.resolveProjectPath = resolveProjectPath;
|
|
11
11
|
exports.getProjectKey = getProjectKey;
|
|
12
12
|
exports.isSessionMetaFile = isSessionMetaFile;
|
|
13
|
+
exports.prepareSessionCompactSourceReceipt = prepareSessionCompactSourceReceipt;
|
|
14
|
+
exports.advanceSessionCompactSourceReceipt = advanceSessionCompactSourceReceipt;
|
|
13
15
|
exports.createSession = createSession;
|
|
14
16
|
exports.saveSessionMeta = saveSessionMeta;
|
|
15
17
|
exports.updateSessionEffort = updateSessionEffort;
|
|
@@ -18,6 +20,7 @@ exports.updateSessionStats = updateSessionStats;
|
|
|
18
20
|
exports.resumeSession = resumeSession;
|
|
19
21
|
exports.updateSessionGoalBinding = updateSessionGoalBinding;
|
|
20
22
|
exports.clearSessionGoalBinding = clearSessionGoalBinding;
|
|
23
|
+
exports.restoreSessionGoalBinding = restoreSessionGoalBinding;
|
|
21
24
|
exports.updateSessionHarnessState = updateSessionHarnessState;
|
|
22
25
|
exports.loadSessionHarnessState = loadSessionHarnessState;
|
|
23
26
|
exports.updateSessionSkills = updateSessionSkills;
|
|
@@ -59,11 +62,55 @@ const tool_call_groups_1 = require("./compact/tool-call-groups");
|
|
|
59
62
|
const redaction_1 = require("./redaction");
|
|
60
63
|
const debug_log_1 = require("../utils/debug-log");
|
|
61
64
|
const goal_storage_1 = require("./goal-storage");
|
|
65
|
+
const fingerprint_1 = require("./compact/fingerprint");
|
|
66
|
+
const token_estimate_1 = require("../utils/token-estimate");
|
|
62
67
|
const harness_1 = require("../harness");
|
|
63
68
|
var redaction_2 = require("./redaction");
|
|
64
69
|
Object.defineProperty(exports, "redactTraceText", { enumerable: true, get: function () { return redaction_2.redactTraceText; } });
|
|
65
70
|
function sanitizeTraceEvent(event) {
|
|
66
71
|
const sanitized = { ...event };
|
|
72
|
+
if (sanitized.stopDecision) {
|
|
73
|
+
sanitized.stopDecision = {
|
|
74
|
+
...sanitized.stopDecision,
|
|
75
|
+
reason: {
|
|
76
|
+
...sanitized.stopDecision.reason,
|
|
77
|
+
message: (0, redaction_1.redactTraceText)(sanitized.stopDecision.reason.message),
|
|
78
|
+
},
|
|
79
|
+
evidence: sanitized.stopDecision.evidence.map(item => ({
|
|
80
|
+
...item,
|
|
81
|
+
source: (0, redaction_1.redactTraceText)(item.source),
|
|
82
|
+
detail: (0, redaction_1.redactTraceText)(item.detail),
|
|
83
|
+
})),
|
|
84
|
+
nextActions: sanitized.stopDecision.nextActions.map(item => ({
|
|
85
|
+
...item,
|
|
86
|
+
label: (0, redaction_1.redactTraceText)(item.label),
|
|
87
|
+
command: item.command ? (0, redaction_1.redactTraceText)(item.command) : undefined,
|
|
88
|
+
})),
|
|
89
|
+
resources: Object.fromEntries(Object.entries(sanitized.stopDecision.resources).map(([key, value]) => [
|
|
90
|
+
key,
|
|
91
|
+
value ? { ...value } : value,
|
|
92
|
+
])),
|
|
93
|
+
criterionStates: sanitized.stopDecision.criterionStates?.map(item => ({
|
|
94
|
+
...item,
|
|
95
|
+
id: (0, redaction_1.redactTraceText)(item.id),
|
|
96
|
+
})),
|
|
97
|
+
evidenceRefs: sanitized.stopDecision.evidenceRefs?.map(redaction_1.redactTraceText),
|
|
98
|
+
progressDelta: sanitized.stopDecision.progressDelta
|
|
99
|
+
? {
|
|
100
|
+
...sanitized.stopDecision.progressDelta,
|
|
101
|
+
criterionChanges: sanitized.stopDecision.progressDelta.criterionChanges.map(item => ({
|
|
102
|
+
...item,
|
|
103
|
+
id: (0, redaction_1.redactTraceText)(item.id),
|
|
104
|
+
})),
|
|
105
|
+
newEvidenceRefs: sanitized.stopDecision.progressDelta.newEvidenceRefs.map(redaction_1.redactTraceText),
|
|
106
|
+
newChangedFiles: sanitized.stopDecision.progressDelta.newChangedFiles.map(redaction_1.redactTraceText),
|
|
107
|
+
newDecisions: sanitized.stopDecision.progressDelta.newDecisions.map(redaction_1.redactTraceText),
|
|
108
|
+
newBlockers: sanitized.stopDecision.progressDelta.newBlockers.map(redaction_1.redactTraceText),
|
|
109
|
+
newDiagnostics: sanitized.stopDecision.progressDelta.newDiagnostics.map(redaction_1.redactTraceText),
|
|
110
|
+
}
|
|
111
|
+
: undefined,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
67
114
|
for (const key of [
|
|
68
115
|
'argsSummary',
|
|
69
116
|
'error',
|
|
@@ -71,6 +118,8 @@ function sanitizeTraceEvent(event) {
|
|
|
71
118
|
'permissionReason',
|
|
72
119
|
'continuationHint',
|
|
73
120
|
'goalStopReason',
|
|
121
|
+
'budgetExceededReason',
|
|
122
|
+
'lastToolSummary',
|
|
74
123
|
]) {
|
|
75
124
|
if (typeof sanitized[key] === 'string') {
|
|
76
125
|
sanitized[key] = (0, redaction_1.redactTraceText)(sanitized[key]);
|
|
@@ -91,6 +140,14 @@ function sanitizeTraceEvent(event) {
|
|
|
91
140
|
if (sanitized.promptOmittedEvidence) {
|
|
92
141
|
sanitized.promptOmittedEvidence = sanitized.promptOmittedEvidence.map(redaction_1.redactTraceText);
|
|
93
142
|
}
|
|
143
|
+
if (sanitized.promptSectionManifest) {
|
|
144
|
+
sanitized.promptSectionManifest = sanitized.promptSectionManifest.map(item => ({
|
|
145
|
+
...item,
|
|
146
|
+
name: (0, redaction_1.redactTraceText)(item.name),
|
|
147
|
+
source: (0, redaction_1.redactTraceText)(item.source),
|
|
148
|
+
reason: item.reason ? (0, redaction_1.redactTraceText)(item.reason) : undefined,
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
94
151
|
if (sanitized.workspaceChangedByTurn) {
|
|
95
152
|
sanitized.workspaceChangedByTurn = sanitized.workspaceChangedByTurn.map(redaction_1.redactTraceText);
|
|
96
153
|
}
|
|
@@ -416,10 +473,277 @@ function parseHarnessSidecarFile(path) {
|
|
|
416
473
|
return null;
|
|
417
474
|
}
|
|
418
475
|
}
|
|
476
|
+
function canonicalizeForHash(value) {
|
|
477
|
+
if (Array.isArray(value))
|
|
478
|
+
return value.map(canonicalizeForHash);
|
|
479
|
+
if (!value || typeof value !== 'object')
|
|
480
|
+
return value;
|
|
481
|
+
return Object.fromEntries(Object.entries(value)
|
|
482
|
+
.filter(([, entry]) => entry !== undefined)
|
|
483
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
484
|
+
.map(([key, entry]) => [key, canonicalizeForHash(entry)]));
|
|
485
|
+
}
|
|
486
|
+
function canonicalContentHash(value) {
|
|
487
|
+
return (0, crypto_1.createHash)('sha256')
|
|
488
|
+
.update(JSON.stringify(canonicalizeForHash(value)), 'utf-8')
|
|
489
|
+
.digest('hex');
|
|
490
|
+
}
|
|
491
|
+
function compactBindingHash(parts) {
|
|
492
|
+
return canonicalContentHash(parts);
|
|
493
|
+
}
|
|
494
|
+
function isSha256(value) {
|
|
495
|
+
return typeof value === 'string' && /^[a-f0-9]{64}$/.test(value);
|
|
496
|
+
}
|
|
497
|
+
function isRecord(value) {
|
|
498
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
499
|
+
}
|
|
500
|
+
function isStringArray(value) {
|
|
501
|
+
return Array.isArray(value) && value.every(item => typeof item === 'string' && item.length > 0);
|
|
502
|
+
}
|
|
503
|
+
function sameStrings(left, right) {
|
|
504
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
505
|
+
}
|
|
506
|
+
function validatePrepareSourceReceipt(receipt, sessionId) {
|
|
507
|
+
if (receipt.schemaVersion !== 1 ||
|
|
508
|
+
receipt.sessionId !== sessionId ||
|
|
509
|
+
!Number.isInteger(receipt.sourceMessageCount) ||
|
|
510
|
+
receipt.sourceMessageCount < 0 ||
|
|
511
|
+
!isSha256(receipt.sourcePrefixHash) ||
|
|
512
|
+
(receipt.activeCheckpointId !== null &&
|
|
513
|
+
(typeof receipt.activeCheckpointId !== 'string' || !receipt.activeCheckpointId))) {
|
|
514
|
+
throw new Error('Invalid compact prepare-source receipt');
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
function assertPrepareSourceMatches(receipt, session, rawMessages) {
|
|
518
|
+
validatePrepareSourceReceipt(receipt, session.id);
|
|
519
|
+
const activeCheckpointId = session.activeCompactCheckpointId ?? null;
|
|
520
|
+
if (activeCheckpointId !== receipt.activeCheckpointId) {
|
|
521
|
+
throw new Error(`Stale compact candidate: active checkpoint changed from ${receipt.activeCheckpointId ?? 'none'} to ${activeCheckpointId ?? 'none'}`);
|
|
522
|
+
}
|
|
523
|
+
if (rawMessages.length !== receipt.sourceMessageCount) {
|
|
524
|
+
throw new Error(`Stale compact candidate: source message count changed from ${receipt.sourceMessageCount} to ${rawMessages.length}`);
|
|
525
|
+
}
|
|
526
|
+
const prefixHash = canonicalContentHash(rawMessages);
|
|
527
|
+
if (prefixHash !== receipt.sourcePrefixHash) {
|
|
528
|
+
throw new Error('Stale compact candidate: source transcript hash changed during preparation');
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
/** Capture the append-only transcript identity before preparing a compact candidate. */
|
|
532
|
+
function prepareSessionCompactSourceReceipt(sessionId) {
|
|
533
|
+
const receipt = withLockedSession(sessionId, session => {
|
|
534
|
+
const rawMessages = readSessionMessagesForSession(session);
|
|
535
|
+
return {
|
|
536
|
+
schemaVersion: 1,
|
|
537
|
+
sessionId,
|
|
538
|
+
sourceMessageCount: rawMessages.length,
|
|
539
|
+
sourcePrefixHash: canonicalContentHash(rawMessages),
|
|
540
|
+
activeCheckpointId: session.activeCompactCheckpointId ?? null,
|
|
541
|
+
};
|
|
542
|
+
});
|
|
543
|
+
if (!receipt)
|
|
544
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
545
|
+
return receipt;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Advance a prepare receipt only across the exact messages written by the
|
|
549
|
+
* preparing turn. Any interleaved writer fails closed instead of being claimed
|
|
550
|
+
* by a candidate that never observed its messages.
|
|
551
|
+
*/
|
|
552
|
+
function advanceSessionCompactSourceReceipt(receipt, appendedMessages) {
|
|
553
|
+
const advanced = withLockedSession(receipt.sessionId, session => {
|
|
554
|
+
validatePrepareSourceReceipt(receipt, session.id);
|
|
555
|
+
if ((session.activeCompactCheckpointId ?? null) !== receipt.activeCheckpointId) {
|
|
556
|
+
throw new Error('Stale compact candidate: active checkpoint changed during preparation');
|
|
557
|
+
}
|
|
558
|
+
const rawMessages = readSessionMessagesForSession(session);
|
|
559
|
+
if (rawMessages.length !== receipt.sourceMessageCount + appendedMessages.length ||
|
|
560
|
+
canonicalContentHash(rawMessages.slice(0, receipt.sourceMessageCount)) !==
|
|
561
|
+
receipt.sourcePrefixHash ||
|
|
562
|
+
canonicalContentHash(rawMessages.slice(receipt.sourceMessageCount)) !==
|
|
563
|
+
canonicalContentHash(appendedMessages)) {
|
|
564
|
+
throw new Error('Stale compact candidate: transcript tail contains concurrent or unexpected messages');
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
...receipt,
|
|
568
|
+
sourceMessageCount: rawMessages.length,
|
|
569
|
+
sourcePrefixHash: canonicalContentHash(rawMessages),
|
|
570
|
+
};
|
|
571
|
+
});
|
|
572
|
+
if (!advanced)
|
|
573
|
+
throw new Error(`Session not found: ${receipt.sessionId}`);
|
|
574
|
+
return advanced;
|
|
575
|
+
}
|
|
576
|
+
function inspectSemanticSummary(value) {
|
|
577
|
+
if (!isRecord(value) || value.version !== 1) {
|
|
578
|
+
throw new Error('Compact semantic summary schema is invalid');
|
|
579
|
+
}
|
|
580
|
+
if (!Number.isInteger(value.taskEpoch) || value.taskEpoch < 1) {
|
|
581
|
+
throw new Error('Compact semantic summary taskEpoch is invalid');
|
|
582
|
+
}
|
|
583
|
+
for (const field of [
|
|
584
|
+
'constraints',
|
|
585
|
+
'decisions',
|
|
586
|
+
'completed',
|
|
587
|
+
'pending',
|
|
588
|
+
'blockers',
|
|
589
|
+
'files',
|
|
590
|
+
'evidenceRefs',
|
|
591
|
+
]) {
|
|
592
|
+
if (!isStringArray(value[field])) {
|
|
593
|
+
throw new Error(`Compact semantic summary ${field} must be a string array`);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (!isRecord(value.coverage) || !isStringArray(value.coverage.groupIds)) {
|
|
597
|
+
throw new Error('Compact semantic summary coverage is invalid');
|
|
598
|
+
}
|
|
599
|
+
const coverageGroupIds = value.coverage.groupIds;
|
|
600
|
+
if (value.coverage.groupCount !== coverageGroupIds.length ||
|
|
601
|
+
!Number.isInteger(value.coverage.messageCount) ||
|
|
602
|
+
value.coverage.messageCount < 0) {
|
|
603
|
+
throw new Error('Compact semantic summary coverage counts are inconsistent');
|
|
604
|
+
}
|
|
605
|
+
if (!Array.isArray(value.items)) {
|
|
606
|
+
throw new Error('Compact semantic summary items must be an array');
|
|
607
|
+
}
|
|
608
|
+
const taskEpochs = [];
|
|
609
|
+
for (const item of value.items) {
|
|
610
|
+
if (!isRecord(item) ||
|
|
611
|
+
typeof item.id !== 'string' ||
|
|
612
|
+
!item.id ||
|
|
613
|
+
typeof item.groupId !== 'string' ||
|
|
614
|
+
!item.groupId ||
|
|
615
|
+
!isStringArray(item.sourceRefs) ||
|
|
616
|
+
!Number.isInteger(item.tokenEstimate) ||
|
|
617
|
+
item.tokenEstimate < 0 ||
|
|
618
|
+
!Number.isInteger(item.taskEpoch) ||
|
|
619
|
+
item.taskEpoch < 1 ||
|
|
620
|
+
typeof item.text !== 'string') {
|
|
621
|
+
throw new Error('Compact semantic summary contains an invalid ContextItem');
|
|
622
|
+
}
|
|
623
|
+
taskEpochs.push(item.taskEpoch);
|
|
624
|
+
}
|
|
625
|
+
const criterionStatesValue = value.criterionStates;
|
|
626
|
+
if (criterionStatesValue !== undefined && !Array.isArray(criterionStatesValue)) {
|
|
627
|
+
throw new Error('Compact semantic criterionStates must be an array');
|
|
628
|
+
}
|
|
629
|
+
const criterionStates = (criterionStatesValue ?? []).map(item => {
|
|
630
|
+
if (!isRecord(item) ||
|
|
631
|
+
typeof item.id !== 'string' ||
|
|
632
|
+
!item.id ||
|
|
633
|
+
typeof item.statement !== 'string' ||
|
|
634
|
+
!['pending', 'passed', 'failed', 'waived'].includes(String(item.status)) ||
|
|
635
|
+
!isStringArray(item.evidenceRefs)) {
|
|
636
|
+
throw new Error('Compact semantic summary contains an invalid criterion state');
|
|
637
|
+
}
|
|
638
|
+
return {
|
|
639
|
+
id: item.id,
|
|
640
|
+
status: String(item.status),
|
|
641
|
+
evidenceRefs: item.evidenceRefs,
|
|
642
|
+
};
|
|
643
|
+
});
|
|
644
|
+
if (new Set(criterionStates.map(item => item.id)).size !== criterionStates.length) {
|
|
645
|
+
throw new Error('Compact semantic summary contains duplicate criterion IDs');
|
|
646
|
+
}
|
|
647
|
+
return {
|
|
648
|
+
coverageGroupIds,
|
|
649
|
+
criterionStates,
|
|
650
|
+
taskEpoch: value.taskEpoch,
|
|
651
|
+
taskEpochs,
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
function semanticValidationReceipt(semanticSummary, candidate, harnessState) {
|
|
655
|
+
const view = inspectSemanticSummary(semanticSummary);
|
|
656
|
+
const expectedCoverage = candidate.plan.evictedGroups.map(group => group.id);
|
|
657
|
+
if (!sameStrings(view.coverageGroupIds, expectedCoverage)) {
|
|
658
|
+
throw new Error('Compact semantic summary does not cover the prepared evicted groups');
|
|
659
|
+
}
|
|
660
|
+
const expectedTaskEpoch = Math.max(1, Math.floor(harnessState?.taskEpoch ?? harnessState?.contract?.taskEpoch ?? view.taskEpochs[0] ?? 1));
|
|
661
|
+
if (view.taskEpoch !== expectedTaskEpoch ||
|
|
662
|
+
view.taskEpochs.some(taskEpoch => taskEpoch !== expectedTaskEpoch)) {
|
|
663
|
+
throw new Error('Compact semantic summary taskEpoch does not match the active Harness epoch');
|
|
664
|
+
}
|
|
665
|
+
const contractCriteria = harnessState?.contract?.criteria ?? [];
|
|
666
|
+
const expectedCriteria = contractCriteria.map(criterion => ({
|
|
667
|
+
id: criterion.id,
|
|
668
|
+
status: criterion.status ?? 'pending',
|
|
669
|
+
evidenceRefs: [...criterion.evidenceRefs],
|
|
670
|
+
}));
|
|
671
|
+
if (expectedCriteria.length > 0) {
|
|
672
|
+
if (view.criterionStates.length !== expectedCriteria.length) {
|
|
673
|
+
throw new Error('Compact semantic summary omitted active task criteria');
|
|
674
|
+
}
|
|
675
|
+
for (const [index, expected] of expectedCriteria.entries()) {
|
|
676
|
+
const actual = view.criterionStates[index];
|
|
677
|
+
if (actual.id !== expected.id ||
|
|
678
|
+
actual.status !== expected.status ||
|
|
679
|
+
!sameStrings(actual.evidenceRefs, expected.evidenceRefs)) {
|
|
680
|
+
throw new Error(`Compact semantic criterion mismatch: ${expected.id}`);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
const knownEvidenceRefs = new Set([
|
|
685
|
+
...(harnessState?.ledger.flatMap(item => [item.id, `ledger:${item.id}`]) ?? []),
|
|
686
|
+
...(harnessState?.evidenceIndex?.flatMap(item => [item.id, `evidence:${item.id}`]) ?? []),
|
|
687
|
+
...(harnessState?.capsule?.keyFacts.flatMap(item => [item.id, `fact:${item.id}`]) ?? []),
|
|
688
|
+
]);
|
|
689
|
+
const validatedEvidenceRefs = [
|
|
690
|
+
...new Set(view.criterionStates.flatMap(item => item.evidenceRefs)),
|
|
691
|
+
];
|
|
692
|
+
if (validatedEvidenceRefs.length > 0 && !harnessState) {
|
|
693
|
+
throw new Error('Compact semantic evidence references require an authoritative Harness state');
|
|
694
|
+
}
|
|
695
|
+
for (const criterion of view.criterionStates) {
|
|
696
|
+
if (criterion.status === 'passed' && criterion.evidenceRefs.length === 0) {
|
|
697
|
+
throw new Error(`Passed compact criterion lacks evidence: ${criterion.id}`);
|
|
698
|
+
}
|
|
699
|
+
for (const evidenceRef of criterion.evidenceRefs) {
|
|
700
|
+
if (!knownEvidenceRefs.has(evidenceRef)) {
|
|
701
|
+
throw new Error(`Dangling compact criterion evidence reference: ${evidenceRef}`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return {
|
|
706
|
+
schemaValid: true,
|
|
707
|
+
coverageValid: true,
|
|
708
|
+
taskEpoch: expectedTaskEpoch,
|
|
709
|
+
taskEpochVerified: true,
|
|
710
|
+
criterionEvidenceRefsValid: true,
|
|
711
|
+
preservedCriterionIds: view.criterionStates.map(item => item.id),
|
|
712
|
+
validatedEvidenceRefs,
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
function validatePersistedSemanticReceipt(semanticSummary, receipt) {
|
|
716
|
+
const view = inspectSemanticSummary(semanticSummary);
|
|
717
|
+
if (receipt.schemaValid !== true ||
|
|
718
|
+
receipt.coverageValid !== true ||
|
|
719
|
+
receipt.taskEpochVerified !== true ||
|
|
720
|
+
receipt.criterionEvidenceRefsValid !== true ||
|
|
721
|
+
!Number.isInteger(receipt.taskEpoch) ||
|
|
722
|
+
receipt.taskEpoch < 1 ||
|
|
723
|
+
!isStringArray(receipt.preservedCriterionIds) ||
|
|
724
|
+
!Array.isArray(receipt.validatedEvidenceRefs) ||
|
|
725
|
+
!receipt.validatedEvidenceRefs.every(ref => typeof ref === 'string' && ref.length > 0) ||
|
|
726
|
+
view.taskEpoch !== receipt.taskEpoch ||
|
|
727
|
+
view.taskEpochs.some(taskEpoch => taskEpoch !== receipt.taskEpoch) ||
|
|
728
|
+
!sameStrings(view.criterionStates.map(item => item.id), receipt.preservedCriterionIds) ||
|
|
729
|
+
!sameStrings([...new Set(view.criterionStates.flatMap(item => item.evidenceRefs))], receipt.validatedEvidenceRefs)) {
|
|
730
|
+
throw new Error('Compact semantic validation receipt does not match its summary');
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
function reportInvalidCompactCheckpoint(path, reason) {
|
|
734
|
+
(0, debug_log_1.debugError)('session-storage.validateCompactCheckpoint', new Error(`Invalid compact checkpoint: ${reason}`), path);
|
|
735
|
+
return null;
|
|
736
|
+
}
|
|
737
|
+
function compactCandidatePath(path) {
|
|
738
|
+
return `${path}.candidate`;
|
|
739
|
+
}
|
|
740
|
+
function compactPreviousPath(path) {
|
|
741
|
+
return `${path}.previous`;
|
|
742
|
+
}
|
|
419
743
|
function parseCompactCheckpointFile(path) {
|
|
420
744
|
try {
|
|
421
745
|
const parsed = JSON.parse((0, fs_1.readFileSync)(path, 'utf-8'));
|
|
422
|
-
if (parsed?.version !== 1 ||
|
|
746
|
+
if ((parsed?.version !== 1 && parsed?.version !== 2) ||
|
|
423
747
|
!parsed.checkpointId ||
|
|
424
748
|
!parsed.sessionId ||
|
|
425
749
|
!Array.isArray(parsed.modelHistory) ||
|
|
@@ -427,6 +751,117 @@ function parseCompactCheckpointFile(path) {
|
|
|
427
751
|
parsed.sourceMessageCount < 0 ||
|
|
428
752
|
!parsed.summary ||
|
|
429
753
|
typeof parsed.summary.text !== 'string') {
|
|
754
|
+
return reportInvalidCompactCheckpoint(path, 'base schema mismatch');
|
|
755
|
+
}
|
|
756
|
+
if (parsed.version === 1)
|
|
757
|
+
return parsed;
|
|
758
|
+
if (parsed.sourceBoundary?.startMessageIndex !== 0 ||
|
|
759
|
+
parsed.sourceBoundary.endMessageIndexExclusive !== parsed.sourceMessageCount ||
|
|
760
|
+
!isSha256(parsed.sourcePrefixHash) ||
|
|
761
|
+
!isSha256(parsed.modelHistoryHash) ||
|
|
762
|
+
parsed.summary.schemaVersion !== 2 ||
|
|
763
|
+
typeof parsed.summary.strategy !== 'string' ||
|
|
764
|
+
!parsed.summary.strategy ||
|
|
765
|
+
!Number.isInteger(parsed.contractVersion) ||
|
|
766
|
+
parsed.contractVersion < 1 ||
|
|
767
|
+
!Number.isInteger(parsed.harnessStateVersion) ||
|
|
768
|
+
parsed.harnessStateVersion < 1 ||
|
|
769
|
+
parsed.validation?.schemaValid !== true ||
|
|
770
|
+
parsed.validation.toolCallGroupsValid !== true ||
|
|
771
|
+
parsed.validation.sourcePrefixVerified !== true ||
|
|
772
|
+
parsed.validation.targetMet !== true ||
|
|
773
|
+
!isSha256(parsed.validation.bindingHash) ||
|
|
774
|
+
!Number.isFinite(parsed.validation.targetHeadroomRatio) ||
|
|
775
|
+
!Number.isFinite(parsed.validation.achievedUsageRatio) ||
|
|
776
|
+
!parsed.candidateReceipt ||
|
|
777
|
+
!['semantic_candidate', 'compatibility_adapter'].includes(parsed.candidateReceipt.source) ||
|
|
778
|
+
!isSha256(parsed.candidateReceipt.candidateFingerprint) ||
|
|
779
|
+
!isSha256(parsed.candidateReceipt.persistedProjectionFingerprint) ||
|
|
780
|
+
!Number.isInteger(parsed.candidateReceipt.beforeTokens) ||
|
|
781
|
+
parsed.candidateReceipt.beforeTokens < 0 ||
|
|
782
|
+
!Number.isInteger(parsed.candidateReceipt.afterTokens) ||
|
|
783
|
+
parsed.candidateReceipt.afterTokens < 0 ||
|
|
784
|
+
(parsed.candidateReceipt.targetTokens !== undefined &&
|
|
785
|
+
(!Number.isInteger(parsed.candidateReceipt.targetTokens) ||
|
|
786
|
+
parsed.candidateReceipt.targetTokens < 0)) ||
|
|
787
|
+
!Number.isFinite(parsed.candidateReceipt.targetRatio) ||
|
|
788
|
+
!Array.isArray(parsed.candidateReceipt.diagnostics) ||
|
|
789
|
+
(parsed.harnessBinding !== undefined &&
|
|
790
|
+
(!Number.isInteger(parsed.harnessBinding.schemaVersion) ||
|
|
791
|
+
parsed.harnessBinding.schemaVersion < 1 ||
|
|
792
|
+
!isSha256(parsed.harnessBinding.stateHash))) ||
|
|
793
|
+
(parsed.goalBinding !== undefined &&
|
|
794
|
+
(!parsed.goalBinding.goalId ||
|
|
795
|
+
!Number.isInteger(parsed.goalBinding.revision) ||
|
|
796
|
+
parsed.goalBinding.revision < 0 ||
|
|
797
|
+
!isSha256(parsed.goalBinding.stateHash)))) {
|
|
798
|
+
return reportInvalidCompactCheckpoint(path, 'V2 receipt mismatch');
|
|
799
|
+
}
|
|
800
|
+
if (canonicalContentHash(parsed.modelHistory) !== parsed.modelHistoryHash) {
|
|
801
|
+
return reportInvalidCompactCheckpoint(path, 'replacement history hash mismatch');
|
|
802
|
+
}
|
|
803
|
+
if ((0, fingerprint_1.canonicalMessagesFingerprint)(parsed.modelHistory) !==
|
|
804
|
+
parsed.candidateReceipt.persistedProjectionFingerprint) {
|
|
805
|
+
return reportInvalidCompactCheckpoint(path, 'persisted projection fingerprint mismatch');
|
|
806
|
+
}
|
|
807
|
+
const semanticSummaryHash = parsed.candidateReceipt.semanticSummary
|
|
808
|
+
? canonicalContentHash(parsed.candidateReceipt.semanticSummary)
|
|
809
|
+
: undefined;
|
|
810
|
+
if (semanticSummaryHash !== parsed.candidateReceipt.semanticSummaryHash) {
|
|
811
|
+
return reportInvalidCompactCheckpoint(path, 'semantic summary hash mismatch');
|
|
812
|
+
}
|
|
813
|
+
const coverageHash = parsed.candidateReceipt.semanticSummary
|
|
814
|
+
? canonicalContentHash(parsed.candidateReceipt.semanticSummary.coverage)
|
|
815
|
+
: undefined;
|
|
816
|
+
if (coverageHash !== parsed.candidateReceipt.coverageHash) {
|
|
817
|
+
return reportInvalidCompactCheckpoint(path, 'semantic coverage hash mismatch');
|
|
818
|
+
}
|
|
819
|
+
if (parsed.candidateReceipt.source === 'semantic_candidate') {
|
|
820
|
+
if (!parsed.candidateReceipt.prepareSource ||
|
|
821
|
+
!parsed.candidateReceipt.semanticSummary ||
|
|
822
|
+
!parsed.candidateReceipt.semanticValidation ||
|
|
823
|
+
parsed.validation.prepareSourceVerified !== true ||
|
|
824
|
+
parsed.validation.candidateTokensVerified !== true ||
|
|
825
|
+
parsed.validation.semanticReceiptVerified !== true) {
|
|
826
|
+
return reportInvalidCompactCheckpoint(path, 'semantic candidate validation is incomplete');
|
|
827
|
+
}
|
|
828
|
+
try {
|
|
829
|
+
validatePrepareSourceReceipt(parsed.candidateReceipt.prepareSource, parsed.sessionId);
|
|
830
|
+
if (parsed.candidateReceipt.prepareSource.sourceMessageCount !== parsed.sourceMessageCount ||
|
|
831
|
+
parsed.candidateReceipt.prepareSource.sourcePrefixHash !== parsed.sourcePrefixHash) {
|
|
832
|
+
return reportInvalidCompactCheckpoint(path, 'prepare-source boundary mismatch');
|
|
833
|
+
}
|
|
834
|
+
validatePersistedSemanticReceipt(parsed.candidateReceipt.semanticSummary, parsed.candidateReceipt.semanticValidation);
|
|
835
|
+
}
|
|
836
|
+
catch (error) {
|
|
837
|
+
return reportInvalidCompactCheckpoint(path, error instanceof Error ? error.message : String(error));
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
const prepareSourceHash = parsed.candidateReceipt.prepareSource
|
|
841
|
+
? canonicalContentHash(parsed.candidateReceipt.prepareSource)
|
|
842
|
+
: undefined;
|
|
843
|
+
const semanticValidationHash = parsed.candidateReceipt.semanticValidation
|
|
844
|
+
? canonicalContentHash(parsed.candidateReceipt.semanticValidation)
|
|
845
|
+
: undefined;
|
|
846
|
+
const expectedBindingHash = compactBindingHash({
|
|
847
|
+
sourcePrefixHash: parsed.sourcePrefixHash,
|
|
848
|
+
modelHistoryHash: parsed.modelHistoryHash,
|
|
849
|
+
candidateFingerprint: parsed.candidateReceipt.candidateFingerprint,
|
|
850
|
+
persistedProjectionFingerprint: parsed.candidateReceipt.persistedProjectionFingerprint,
|
|
851
|
+
semanticSummaryHash,
|
|
852
|
+
prepareSourceHash,
|
|
853
|
+
semanticValidationHash,
|
|
854
|
+
harnessStateHash: parsed.harnessBinding?.stateHash,
|
|
855
|
+
goalStateHash: parsed.goalBinding?.stateHash,
|
|
856
|
+
});
|
|
857
|
+
if (expectedBindingHash !== parsed.validation.bindingHash) {
|
|
858
|
+
return reportInvalidCompactCheckpoint(path, 'cross-state binding hash mismatch');
|
|
859
|
+
}
|
|
860
|
+
try {
|
|
861
|
+
(0, tool_call_groups_1.assertToolCallGroups)(parsed.modelHistory);
|
|
862
|
+
}
|
|
863
|
+
catch (error) {
|
|
864
|
+
(0, debug_log_1.debugError)('session-storage.validateCompactCheckpoint.toolGroups', error, path);
|
|
430
865
|
return null;
|
|
431
866
|
}
|
|
432
867
|
return parsed;
|
|
@@ -627,6 +1062,24 @@ function clearSessionGoalBinding(sessionId, expectedGoalId) {
|
|
|
627
1062
|
session.updatedAtIso = new Date(session.updatedAt).toISOString();
|
|
628
1063
|
});
|
|
629
1064
|
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Restore a Goal binding after a later sidecar mutation failed. A different
|
|
1067
|
+
* active binding belongs to a newer lifecycle and must never be overwritten.
|
|
1068
|
+
*/
|
|
1069
|
+
function restoreSessionGoalBinding(sessionId, goal, expectedClearedAt) {
|
|
1070
|
+
return mutateSessionMeta(sessionId, session => {
|
|
1071
|
+
if (session.activeGoalId && session.activeGoalId !== goal.goalId) {
|
|
1072
|
+
throw new Error(`Session Goal binding changed from ${goal.goalId} to ${session.activeGoalId}; refusing to overwrite the newer Goal during rollback.`);
|
|
1073
|
+
}
|
|
1074
|
+
if (!session.activeGoalId && session.updatedAt !== expectedClearedAt) {
|
|
1075
|
+
throw new Error(`Session metadata changed after Goal ${goal.goalId} was cleared; refusing to overwrite newer session state during rollback.`);
|
|
1076
|
+
}
|
|
1077
|
+
session.activeGoalId = goal.goalId;
|
|
1078
|
+
session.activeGoalObjective = goal.objective;
|
|
1079
|
+
session.updatedAt = Date.now();
|
|
1080
|
+
session.updatedAtIso = new Date(session.updatedAt).toISOString();
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
630
1083
|
/**
|
|
631
1084
|
* 更新会话 Harness 状态。
|
|
632
1085
|
*/
|
|
@@ -712,30 +1165,158 @@ function persistSessionCompactHistory(sessionId, messages, timestamp = Date.now(
|
|
|
712
1165
|
appendSessionMessages(sessionId, compactMessages);
|
|
713
1166
|
return markSessionTranscriptDisplayStart(sessionId, timestamp);
|
|
714
1167
|
}
|
|
715
|
-
function
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
1168
|
+
function loadCompactCheckpointForSession(session, messages) {
|
|
1169
|
+
const compactPath = (0, config_dir_1.getProjectSessionCompactPath)(session.projectPath, session.id);
|
|
1170
|
+
const candidatePaths = [compactPath, compactPreviousPath(compactPath)];
|
|
1171
|
+
for (const path of candidatePaths) {
|
|
1172
|
+
if (!(0, fs_1.existsSync)(path))
|
|
1173
|
+
continue;
|
|
1174
|
+
const checkpoint = parseCompactCheckpointFile(path);
|
|
1175
|
+
if (!checkpoint || checkpoint.sessionId !== session.id)
|
|
1176
|
+
continue;
|
|
1177
|
+
if (session.activeCompactCheckpointId !== checkpoint.checkpointId)
|
|
1178
|
+
continue;
|
|
1179
|
+
if (checkpoint.sourceMessageCount > messages.length)
|
|
1180
|
+
continue;
|
|
1181
|
+
if (checkpoint.version === 2 &&
|
|
1182
|
+
canonicalContentHash(messages.slice(0, checkpoint.sourceMessageCount)) !==
|
|
1183
|
+
checkpoint.sourcePrefixHash) {
|
|
1184
|
+
reportInvalidCompactCheckpoint(path, 'covered transcript prefix hash mismatch');
|
|
1185
|
+
continue;
|
|
1186
|
+
}
|
|
1187
|
+
return checkpoint;
|
|
724
1188
|
}
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
return
|
|
1189
|
+
return null;
|
|
1190
|
+
}
|
|
1191
|
+
function loadSessionCompactCheckpoint(sessionId) {
|
|
1192
|
+
return (withLockedSession(sessionId, session => loadCompactCheckpointForSession(session, readSessionMessagesForSession(session))) ?? null);
|
|
729
1193
|
}
|
|
730
1194
|
function commitSessionCompactCheckpoint(input) {
|
|
731
1195
|
const checkpoint = withLockedSession(input.sessionId, session => {
|
|
732
|
-
const
|
|
1196
|
+
const rawMessages = readSessionMessagesForSession(session);
|
|
1197
|
+
const rawCount = rawMessages.length;
|
|
1198
|
+
if (input.candidate && !input.prepareSource) {
|
|
1199
|
+
throw new Error('Semantic compact candidate requires a prepare-source receipt');
|
|
1200
|
+
}
|
|
1201
|
+
if (input.prepareSource) {
|
|
1202
|
+
if (input.prepareSource.sourceMessageCount !== input.sourceMessageCount) {
|
|
1203
|
+
throw new Error('Compact source boundary differs from its prepare-source receipt');
|
|
1204
|
+
}
|
|
1205
|
+
assertPrepareSourceMatches(input.prepareSource, session, rawMessages);
|
|
1206
|
+
}
|
|
733
1207
|
if (input.sourceMessageCount < 0 || input.sourceMessageCount > rawCount) {
|
|
734
1208
|
throw new Error(`Invalid compact source boundary ${input.sourceMessageCount}; transcript has ${rawCount} messages`);
|
|
735
1209
|
}
|
|
736
1210
|
const createdAt = input.createdAt ?? Date.now();
|
|
1211
|
+
const candidateModelHistory = input.modelHistory.map(message => JSON.parse(JSON.stringify(message)));
|
|
1212
|
+
(0, tool_call_groups_1.assertToolCallGroups)(candidateModelHistory);
|
|
1213
|
+
const modelHistory = input.modelHistory
|
|
1214
|
+
.filter(message => message.role !== 'system')
|
|
1215
|
+
.map(message => JSON.parse(JSON.stringify(message)));
|
|
1216
|
+
(0, tool_call_groups_1.assertToolCallGroups)(modelHistory);
|
|
1217
|
+
const targetHeadroomRatio = 0.65;
|
|
1218
|
+
const safeInputBudget = Math.max(1, input.afterUsage.safeInputBudget ?? input.afterUsage.contextWindow);
|
|
1219
|
+
const achievedUsageRatio = input.afterUsage.usedTokens / safeInputBudget;
|
|
1220
|
+
if (!Number.isFinite(achievedUsageRatio) || achievedUsageRatio > targetHeadroomRatio) {
|
|
1221
|
+
throw new Error(`Compact candidate did not reach the required ${Math.round(targetHeadroomRatio * 100)}% safe-input headroom target (${Math.round(achievedUsageRatio * 100)}% used)`);
|
|
1222
|
+
}
|
|
1223
|
+
const sourcePrefixHash = canonicalContentHash(rawMessages.slice(0, input.sourceMessageCount));
|
|
1224
|
+
const modelHistoryHash = canonicalContentHash(modelHistory);
|
|
1225
|
+
const persistedProjectionFingerprint = (0, fingerprint_1.canonicalMessagesFingerprint)(modelHistory);
|
|
1226
|
+
const candidateBeforeTokens = input.candidate?.beforeTokens ?? input.beforeUsage.usedTokens;
|
|
1227
|
+
const candidateAfterTokens = input.candidate?.afterTokens ?? input.afterUsage.usedTokens;
|
|
1228
|
+
const candidateTargetRatio = input.candidate?.plan.targetRatio ?? targetHeadroomRatio;
|
|
1229
|
+
const candidateFingerprint = input.candidate?.fingerprint ?? persistedProjectionFingerprint;
|
|
1230
|
+
for (const [name, value] of [
|
|
1231
|
+
['beforeTokens', candidateBeforeTokens],
|
|
1232
|
+
['afterTokens', candidateAfterTokens],
|
|
1233
|
+
]) {
|
|
1234
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
1235
|
+
throw new Error(`Compact candidate ${name} must be a non-negative integer`);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
if (!isSha256(candidateFingerprint)) {
|
|
1239
|
+
throw new Error('Compact candidate fingerprint must be a SHA-256 digest');
|
|
1240
|
+
}
|
|
1241
|
+
if (input.candidate) {
|
|
1242
|
+
const actualCandidateTokens = (0, token_estimate_1.estimateMessagesTokens)(candidateModelHistory);
|
|
1243
|
+
if (candidateAfterTokens !== actualCandidateTokens) {
|
|
1244
|
+
throw new Error(`Compact candidate afterTokens ${candidateAfterTokens} does not match actual history ${actualCandidateTokens}`);
|
|
1245
|
+
}
|
|
1246
|
+
if (input.candidate.plan.targetTokens !== undefined &&
|
|
1247
|
+
candidateAfterTokens > input.candidate.plan.targetTokens) {
|
|
1248
|
+
throw new Error('Compact candidate exceeds its prepared target token budget');
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
if (!Number.isFinite(candidateTargetRatio) ||
|
|
1252
|
+
candidateTargetRatio <= 0 ||
|
|
1253
|
+
candidateTargetRatio > targetHeadroomRatio) {
|
|
1254
|
+
throw new Error(`Compact candidate target ratio must be within (0, ${targetHeadroomRatio}]`);
|
|
1255
|
+
}
|
|
1256
|
+
const semanticSummary = input.candidate
|
|
1257
|
+
? JSON.parse(JSON.stringify(input.candidate.semanticSummary))
|
|
1258
|
+
: undefined;
|
|
1259
|
+
const semanticSummaryHash = semanticSummary ? canonicalContentHash(semanticSummary) : undefined;
|
|
1260
|
+
const coverageHash = semanticSummary
|
|
1261
|
+
? canonicalContentHash(semanticSummary.coverage)
|
|
1262
|
+
: undefined;
|
|
1263
|
+
const semanticValidation = input.candidate && semanticSummary
|
|
1264
|
+
? semanticValidationReceipt(semanticSummary, input.candidate, input.semanticHarnessState ?? input.harnessState)
|
|
1265
|
+
: undefined;
|
|
1266
|
+
const prepareSource = input.prepareSource
|
|
1267
|
+
? { ...input.prepareSource }
|
|
1268
|
+
: undefined;
|
|
1269
|
+
const harnessBinding = input.harnessState
|
|
1270
|
+
? {
|
|
1271
|
+
schemaVersion: input.harnessState.version ?? input.harnessStateVersion ?? 2,
|
|
1272
|
+
stateHash: canonicalContentHash(input.harnessState),
|
|
1273
|
+
}
|
|
1274
|
+
: undefined;
|
|
1275
|
+
const goalBinding = input.goalBinding
|
|
1276
|
+
? {
|
|
1277
|
+
goalId: input.goalBinding.goalId,
|
|
1278
|
+
revision: input.goalBinding.revision,
|
|
1279
|
+
stateHash: canonicalContentHash(input.goalBinding.state ?? {
|
|
1280
|
+
goalId: input.goalBinding.goalId,
|
|
1281
|
+
revision: input.goalBinding.revision,
|
|
1282
|
+
}),
|
|
1283
|
+
}
|
|
1284
|
+
: undefined;
|
|
1285
|
+
const candidateReceipt = {
|
|
1286
|
+
source: input.candidate ? 'semantic_candidate' : 'compatibility_adapter',
|
|
1287
|
+
candidateFingerprint,
|
|
1288
|
+
persistedProjectionFingerprint,
|
|
1289
|
+
beforeTokens: candidateBeforeTokens,
|
|
1290
|
+
afterTokens: candidateAfterTokens,
|
|
1291
|
+
targetTokens: input.candidate?.plan.targetTokens,
|
|
1292
|
+
targetRatio: candidateTargetRatio,
|
|
1293
|
+
semanticSummary,
|
|
1294
|
+
semanticSummaryHash,
|
|
1295
|
+
diagnostics: input.candidate?.diagnostics.map(diagnostic => ({
|
|
1296
|
+
...diagnostic,
|
|
1297
|
+
message: (0, redaction_1.redactTraceText)(diagnostic.message),
|
|
1298
|
+
})) ?? [],
|
|
1299
|
+
coverageHash,
|
|
1300
|
+
prepareSource,
|
|
1301
|
+
semanticValidation,
|
|
1302
|
+
};
|
|
1303
|
+
const prepareSourceHash = prepareSource ? canonicalContentHash(prepareSource) : undefined;
|
|
1304
|
+
const semanticValidationHash = semanticValidation
|
|
1305
|
+
? canonicalContentHash(semanticValidation)
|
|
1306
|
+
: undefined;
|
|
1307
|
+
const bindingHash = compactBindingHash({
|
|
1308
|
+
sourcePrefixHash,
|
|
1309
|
+
modelHistoryHash,
|
|
1310
|
+
candidateFingerprint,
|
|
1311
|
+
persistedProjectionFingerprint,
|
|
1312
|
+
semanticSummaryHash,
|
|
1313
|
+
prepareSourceHash,
|
|
1314
|
+
semanticValidationHash,
|
|
1315
|
+
harnessStateHash: harnessBinding?.stateHash,
|
|
1316
|
+
goalStateHash: goalBinding?.stateHash,
|
|
1317
|
+
});
|
|
737
1318
|
const nextCheckpoint = {
|
|
738
|
-
version:
|
|
1319
|
+
version: 2,
|
|
739
1320
|
checkpointId: (0, crypto_1.randomUUID)(),
|
|
740
1321
|
sessionId: input.sessionId,
|
|
741
1322
|
createdAt,
|
|
@@ -743,34 +1324,128 @@ function commitSessionCompactCheckpoint(input) {
|
|
|
743
1324
|
modelId: input.modelId,
|
|
744
1325
|
sourceMessageCount: input.sourceMessageCount,
|
|
745
1326
|
transcriptStartMessageIndex: Math.max(0, Math.min(input.sourceMessageCount, input.transcriptStartMessageIndex)),
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
.
|
|
1327
|
+
sourceBoundary: {
|
|
1328
|
+
startMessageIndex: 0,
|
|
1329
|
+
endMessageIndexExclusive: input.sourceMessageCount,
|
|
1330
|
+
},
|
|
1331
|
+
sourcePrefixHash,
|
|
1332
|
+
modelHistory,
|
|
1333
|
+
modelHistoryHash,
|
|
749
1334
|
summary: {
|
|
750
1335
|
...input.summary,
|
|
751
1336
|
sourceMessageCount: input.sourceMessageCount,
|
|
1337
|
+
schemaVersion: 2,
|
|
1338
|
+
strategy: input.strategy ??
|
|
1339
|
+
(input.summary.source === 'llm' ? 'semantic-llm-v2' : 'deterministic-fallback-v2'),
|
|
752
1340
|
},
|
|
753
1341
|
beforeUsage: { ...input.beforeUsage },
|
|
754
1342
|
afterUsage: { ...input.afterUsage },
|
|
1343
|
+
contractVersion: (() => {
|
|
1344
|
+
const derivedContractVersion = input.harnessState?.contract?.version ?? 1;
|
|
1345
|
+
if (input.contractVersion !== undefined &&
|
|
1346
|
+
input.harnessState?.contract?.version !== undefined &&
|
|
1347
|
+
input.contractVersion !== derivedContractVersion) {
|
|
1348
|
+
throw new Error(`Compact contractVersion ${input.contractVersion} does not match Harness contract ${derivedContractVersion}`);
|
|
1349
|
+
}
|
|
1350
|
+
return input.contractVersion ?? derivedContractVersion;
|
|
1351
|
+
})(),
|
|
1352
|
+
harnessStateVersion: harnessBinding?.schemaVersion ?? input.harnessStateVersion ?? 2,
|
|
1353
|
+
harnessBinding,
|
|
1354
|
+
goalBinding,
|
|
1355
|
+
candidateReceipt,
|
|
1356
|
+
validation: {
|
|
1357
|
+
schemaValid: true,
|
|
1358
|
+
toolCallGroupsValid: true,
|
|
1359
|
+
sourcePrefixVerified: true,
|
|
1360
|
+
targetHeadroomRatio,
|
|
1361
|
+
achievedUsageRatio,
|
|
1362
|
+
targetMet: true,
|
|
1363
|
+
prepareSourceVerified: prepareSource ? true : undefined,
|
|
1364
|
+
candidateTokensVerified: input.candidate ? true : undefined,
|
|
1365
|
+
semanticReceiptVerified: semanticValidation ? true : undefined,
|
|
1366
|
+
bindingHash,
|
|
1367
|
+
validatedAt: createdAt,
|
|
1368
|
+
},
|
|
755
1369
|
};
|
|
756
1370
|
const previousId = session.activeCompactCheckpointId;
|
|
757
1371
|
const previousTime = session.lastCompactAt;
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
session.
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
//
|
|
764
|
-
|
|
1372
|
+
const previousUpdatedAt = session.updatedAt;
|
|
1373
|
+
const previousUpdatedAtIso = session.updatedAtIso;
|
|
1374
|
+
const compactPath = (0, config_dir_1.getProjectSessionCompactPath)(session.projectPath, input.sessionId);
|
|
1375
|
+
const candidatePath = compactCandidatePath(compactPath);
|
|
1376
|
+
const previousPath = compactPreviousPath(compactPath);
|
|
1377
|
+
// Recover a process that crashed after installing a new sidecar but before
|
|
1378
|
+
// committing its pointer. The previous file is keyed by the durable pointer.
|
|
1379
|
+
if ((0, fs_1.existsSync)(previousPath)) {
|
|
1380
|
+
const installed = (0, fs_1.existsSync)(compactPath) ? parseCompactCheckpointFile(compactPath) : null;
|
|
1381
|
+
const previous = parseCompactCheckpointFile(previousPath);
|
|
1382
|
+
if (previousId &&
|
|
1383
|
+
installed?.checkpointId !== previousId &&
|
|
1384
|
+
previous?.checkpointId === previousId) {
|
|
1385
|
+
if ((0, fs_1.existsSync)(compactPath))
|
|
1386
|
+
(0, fs_1.unlinkSync)(compactPath);
|
|
1387
|
+
(0, fs_1.renameSync)(previousPath, compactPath);
|
|
1388
|
+
}
|
|
1389
|
+
else if (installed?.checkpointId === previousId) {
|
|
1390
|
+
(0, fs_1.unlinkSync)(previousPath);
|
|
1391
|
+
}
|
|
1392
|
+
else {
|
|
1393
|
+
throw new Error('Cannot reconcile interrupted compact checkpoint transaction');
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
(0, atomic_write_1.atomicWriteFileSync)(candidatePath, JSON.stringify(nextCheckpoint, null, 2), { mode: 0o600 });
|
|
1397
|
+
const prepared = parseCompactCheckpointFile(candidatePath);
|
|
1398
|
+
if (prepared?.version !== 2 || prepared.checkpointId !== nextCheckpoint.checkpointId) {
|
|
1399
|
+
if ((0, fs_1.existsSync)(candidatePath))
|
|
1400
|
+
(0, fs_1.unlinkSync)(candidatePath);
|
|
1401
|
+
throw new Error('Compact candidate failed durable reload validation');
|
|
1402
|
+
}
|
|
1403
|
+
let previousInstalled = false;
|
|
1404
|
+
let candidateInstalled = false;
|
|
765
1405
|
try {
|
|
766
|
-
|
|
1406
|
+
if ((0, fs_1.existsSync)(compactPath)) {
|
|
1407
|
+
(0, fs_1.renameSync)(compactPath, previousPath);
|
|
1408
|
+
previousInstalled = true;
|
|
1409
|
+
}
|
|
1410
|
+
(0, fs_1.renameSync)(candidatePath, compactPath);
|
|
1411
|
+
candidateInstalled = true;
|
|
1412
|
+
session.activeCompactCheckpointId = nextCheckpoint.checkpointId;
|
|
1413
|
+
session.lastCompactAt = createdAt;
|
|
1414
|
+
session.updatedAt = createdAt;
|
|
1415
|
+
session.updatedAtIso = new Date(createdAt).toISOString();
|
|
1416
|
+
writeSessionMetaUnlocked(session);
|
|
1417
|
+
const persistedSession = readSessionMetaAtPath((0, config_dir_1.getProjectSessionMetaPath)(session.projectPath, session.id));
|
|
1418
|
+
const persistedCheckpoint = parseCompactCheckpointFile(compactPath);
|
|
1419
|
+
if (persistedSession?.activeCompactCheckpointId !== nextCheckpoint.checkpointId ||
|
|
1420
|
+
persistedCheckpoint?.checkpointId !== nextCheckpoint.checkpointId) {
|
|
1421
|
+
throw new Error('Compact checkpoint commit could not be read back atomically');
|
|
1422
|
+
}
|
|
767
1423
|
}
|
|
768
1424
|
catch (error) {
|
|
769
1425
|
session.activeCompactCheckpointId = previousId;
|
|
770
1426
|
session.lastCompactAt = previousTime;
|
|
771
|
-
|
|
1427
|
+
session.updatedAt = previousUpdatedAt;
|
|
1428
|
+
session.updatedAtIso = previousUpdatedAtIso;
|
|
1429
|
+
if (candidateInstalled && (0, fs_1.existsSync)(compactPath))
|
|
1430
|
+
(0, fs_1.unlinkSync)(compactPath);
|
|
1431
|
+
if (previousInstalled && (0, fs_1.existsSync)(previousPath))
|
|
1432
|
+
(0, fs_1.renameSync)(previousPath, compactPath);
|
|
1433
|
+
if ((0, fs_1.existsSync)(candidatePath))
|
|
1434
|
+
(0, fs_1.unlinkSync)(candidatePath);
|
|
1435
|
+
const persistedSession = readSessionMetaAtPath((0, config_dir_1.getProjectSessionMetaPath)(session.projectPath, session.id));
|
|
1436
|
+
if (persistedSession?.activeCompactCheckpointId === nextCheckpoint.checkpointId) {
|
|
1437
|
+
writeSessionMetaUnlocked(session);
|
|
1438
|
+
}
|
|
772
1439
|
throw error;
|
|
773
1440
|
}
|
|
1441
|
+
if ((0, fs_1.existsSync)(previousPath)) {
|
|
1442
|
+
try {
|
|
1443
|
+
(0, fs_1.unlinkSync)(previousPath);
|
|
1444
|
+
}
|
|
1445
|
+
catch (error) {
|
|
1446
|
+
(0, debug_log_1.debugError)('session-storage.compactPreviousCleanup', error, previousPath);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
774
1449
|
return nextCheckpoint;
|
|
775
1450
|
});
|
|
776
1451
|
if (!checkpoint)
|
|
@@ -778,16 +1453,16 @@ function commitSessionCompactCheckpoint(input) {
|
|
|
778
1453
|
return checkpoint;
|
|
779
1454
|
}
|
|
780
1455
|
function loadSessionTranscriptMessages(sessionId) {
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
1456
|
+
return (withLockedSession(sessionId, session => {
|
|
1457
|
+
const messages = readSessionMessagesForSession(session);
|
|
1458
|
+
const checkpoint = loadCompactCheckpointForSession(session, messages);
|
|
1459
|
+
if (checkpoint) {
|
|
1460
|
+
return messages.slice(checkpoint.transcriptStartMessageIndex);
|
|
1461
|
+
}
|
|
1462
|
+
return typeof session.transcriptDisplayStartTime === 'number'
|
|
1463
|
+
? messages.filter(message => (message.timestamp ?? 0) >= (session.transcriptDisplayStartTime ?? 0))
|
|
1464
|
+
: messages;
|
|
1465
|
+
}) ?? []);
|
|
791
1466
|
}
|
|
792
1467
|
function hasPersistedCompactContext(messages) {
|
|
793
1468
|
return messages.some(message => message.content.includes('[Orion Code Context State v2]') ||
|
|
@@ -808,8 +1483,7 @@ function endSession(sessionId) {
|
|
|
808
1483
|
* 更新会话任务摘要
|
|
809
1484
|
* 从会话消息中提取关键信息并更新元数据
|
|
810
1485
|
*/
|
|
811
|
-
function
|
|
812
|
-
// 提取工具使用列表
|
|
1486
|
+
function summarizeSessionMessages(messages) {
|
|
813
1487
|
const toolsUsed = [];
|
|
814
1488
|
const filesModified = [];
|
|
815
1489
|
for (const msg of messages) {
|
|
@@ -835,15 +1509,52 @@ function updateSessionSummary(sessionId, messages) {
|
|
|
835
1509
|
}
|
|
836
1510
|
// 提取任务摘要(从第一个用户消息)
|
|
837
1511
|
const firstUserMsg = messages.find(m => m.role === 'user' && m.content);
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
1512
|
+
const taskText = (0, redaction_1.redactTraceText)(firstUserMsg?.content ?? '');
|
|
1513
|
+
const taskSummary = taskText.length > 100 ? `${taskText.slice(0, 100)}...` : taskText;
|
|
1514
|
+
return {
|
|
1515
|
+
toolsUsed: [...new Set(toolsUsed)],
|
|
1516
|
+
filesModified: [...new Set(filesModified)],
|
|
1517
|
+
taskSummary,
|
|
1518
|
+
messageCount: messages.length,
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
function mergeMessageSummary(session, message) {
|
|
1522
|
+
if (!session.taskSummary && message.role === 'user' && message.content) {
|
|
1523
|
+
const taskText = (0, redaction_1.redactTraceText)(message.content);
|
|
1524
|
+
session.taskSummary = taskText.length > 100 ? `${taskText.slice(0, 100)}...` : taskText;
|
|
1525
|
+
}
|
|
1526
|
+
if (message.role !== 'assistant' || !message.tool_calls)
|
|
1527
|
+
return;
|
|
1528
|
+
const tools = new Set(session.toolsUsed ?? []);
|
|
1529
|
+
const files = new Set(session.filesModified ?? []);
|
|
1530
|
+
for (const toolCall of message.tool_calls) {
|
|
1531
|
+
tools.add(toolCall.function.name);
|
|
1532
|
+
if (toolCall.function.name !== 'write_file' && toolCall.function.name !== 'edit_file')
|
|
1533
|
+
continue;
|
|
1534
|
+
try {
|
|
1535
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
1536
|
+
if (typeof args.path === 'string')
|
|
1537
|
+
files.add(args.path);
|
|
1538
|
+
}
|
|
1539
|
+
catch (error) {
|
|
1540
|
+
(0, debug_log_1.debugError)('session-storage.parseToolArgs', error, toolCall.function.name);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
session.toolsUsed = [...tools];
|
|
1544
|
+
session.filesModified = [...files];
|
|
1545
|
+
}
|
|
1546
|
+
function updateSessionSummary(sessionId, _messages) {
|
|
1547
|
+
// Callers may hold a stale transcript snapshot. Re-read under the same lock
|
|
1548
|
+
// used by append/delete so reconciliation can never roll metadata backwards.
|
|
1549
|
+
withLockedSession(sessionId, session => {
|
|
1550
|
+
const summary = summarizeSessionMessages(readSessionMessagesForSession(session));
|
|
1551
|
+
session.toolsUsed = summary.toolsUsed;
|
|
1552
|
+
session.filesModified = summary.filesModified;
|
|
1553
|
+
session.taskSummary = summary.taskSummary;
|
|
1554
|
+
session.messageCount = summary.messageCount;
|
|
845
1555
|
session.updatedAt = Date.now();
|
|
846
1556
|
session.updatedAtIso = new Date(session.updatedAt).toISOString();
|
|
1557
|
+
writeSessionMetaUnlocked(session);
|
|
847
1558
|
});
|
|
848
1559
|
}
|
|
849
1560
|
/**
|
|
@@ -924,6 +1635,7 @@ function appendSessionMessage(sessionId, message) {
|
|
|
924
1635
|
// Keep transcript, metadata, and search index inside the same session
|
|
925
1636
|
// critical section so concurrent processes cannot lose counters.
|
|
926
1637
|
(0, session_index_1.updateSessionIndex)(sessionId, session.projectPath, message);
|
|
1638
|
+
mergeMessageSummary(session, message);
|
|
927
1639
|
session.updatedAt = Date.now();
|
|
928
1640
|
session.updatedAtIso = new Date(session.updatedAt).toISOString();
|
|
929
1641
|
session.messageCount = (session.messageCount ?? 0) + 1;
|
|
@@ -945,6 +1657,7 @@ function appendSessionMessages(sessionId, messages) {
|
|
|
945
1657
|
});
|
|
946
1658
|
for (const message of messages) {
|
|
947
1659
|
(0, session_index_1.updateSessionIndex)(sessionId, session.projectPath, message);
|
|
1660
|
+
mergeMessageSummary(session, message);
|
|
948
1661
|
}
|
|
949
1662
|
session.updatedAt = Date.now();
|
|
950
1663
|
session.updatedAtIso = new Date(session.updatedAt).toISOString();
|
|
@@ -982,6 +1695,10 @@ function overwriteSessionMessagesUnlocked(session, messages) {
|
|
|
982
1695
|
(0, session_index_1.updateSessionIndex)(session.id, session.projectPath, message);
|
|
983
1696
|
}
|
|
984
1697
|
session.messageCount = messages.length;
|
|
1698
|
+
const summary = summarizeSessionMessages(messages);
|
|
1699
|
+
session.toolsUsed = summary.toolsUsed;
|
|
1700
|
+
session.filesModified = summary.filesModified;
|
|
1701
|
+
session.taskSummary = summary.taskSummary;
|
|
985
1702
|
session.updatedAt = Date.now();
|
|
986
1703
|
session.updatedAtIso = new Date(session.updatedAt).toISOString();
|
|
987
1704
|
writeSessionMetaUnlocked(session);
|
|
@@ -1068,87 +1785,98 @@ function readSessionMessagesForSession(session) {
|
|
|
1068
1785
|
}
|
|
1069
1786
|
}
|
|
1070
1787
|
function appendSessionTraceEvent(sessionId, event) {
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
return traceEvent;
|
|
1788
|
+
return withLockedSession(sessionId, session => {
|
|
1789
|
+
(0, config_dir_1.ensureConfigDir)();
|
|
1790
|
+
const safeEvent = sanitizeTraceEvent(event);
|
|
1791
|
+
const traceEvent = {
|
|
1792
|
+
...safeEvent,
|
|
1793
|
+
sessionId,
|
|
1794
|
+
turnId: String(safeEvent.turnId),
|
|
1795
|
+
timestamp: safeEvent.timestamp ?? Date.now(),
|
|
1796
|
+
};
|
|
1797
|
+
(0, fs_1.appendFileSync)((0, config_dir_1.getProjectSessionTracePath)(session.projectPath, sessionId), `${JSON.stringify(traceEvent)}\n`, { mode: 0o600 });
|
|
1798
|
+
return traceEvent;
|
|
1799
|
+
});
|
|
1084
1800
|
}
|
|
1085
1801
|
function readSessionTraceEvents(sessionId) {
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1802
|
+
return (withLockedSession(sessionId, session => {
|
|
1803
|
+
const path = (0, config_dir_1.getProjectSessionTracePath)(session.projectPath, sessionId);
|
|
1804
|
+
if (!(0, fs_1.existsSync)(path))
|
|
1805
|
+
return [];
|
|
1806
|
+
try {
|
|
1807
|
+
const content = (0, fs_1.readFileSync)(path, 'utf-8');
|
|
1808
|
+
return content
|
|
1809
|
+
.trim()
|
|
1810
|
+
.split('\n')
|
|
1811
|
+
.filter(Boolean)
|
|
1812
|
+
.flatMap(line => {
|
|
1813
|
+
try {
|
|
1814
|
+
const parsed = JSON.parse(line);
|
|
1815
|
+
if (!parsed.type || !parsed.turnId || !parsed.timestamp)
|
|
1816
|
+
return [];
|
|
1817
|
+
const sanitized = sanitizeTraceEvent({
|
|
1818
|
+
...parsed,
|
|
1819
|
+
turnId: String(parsed.turnId),
|
|
1820
|
+
});
|
|
1821
|
+
return [
|
|
1822
|
+
{
|
|
1823
|
+
...sanitized,
|
|
1824
|
+
sessionId,
|
|
1825
|
+
turnId: String(sanitized.turnId),
|
|
1826
|
+
},
|
|
1827
|
+
];
|
|
1828
|
+
}
|
|
1829
|
+
catch (error) {
|
|
1830
|
+
// Drop only the malformed trace line, keep the rest of the trace.
|
|
1831
|
+
(0, debug_log_1.debugError)('session-storage.parseTraceLine', error);
|
|
1102
1832
|
return [];
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
];
|
|
1114
|
-
}
|
|
1115
|
-
catch (error) {
|
|
1116
|
-
// Drop only the malformed trace line, keep the rest of the trace.
|
|
1117
|
-
(0, debug_log_1.debugError)('session-storage.parseTraceLine', error);
|
|
1118
|
-
return [];
|
|
1119
|
-
}
|
|
1120
|
-
});
|
|
1121
|
-
}
|
|
1122
|
-
catch (error) {
|
|
1123
|
-
// An empty trace looks like "nothing happened" instead of "trace
|
|
1124
|
-
// unreadable", which misleads anyone debugging a past run.
|
|
1125
|
-
(0, debug_log_1.debugError)('session-storage.readTraceEvents', error, path);
|
|
1126
|
-
return [];
|
|
1127
|
-
}
|
|
1833
|
+
}
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1836
|
+
catch (error) {
|
|
1837
|
+
// An empty trace looks like "nothing happened" instead of "trace
|
|
1838
|
+
// unreadable", which misleads anyone debugging a past run.
|
|
1839
|
+
(0, debug_log_1.debugError)('session-storage.readTraceEvents', error, path);
|
|
1840
|
+
return [];
|
|
1841
|
+
}
|
|
1842
|
+
}) ?? []);
|
|
1128
1843
|
}
|
|
1129
1844
|
/**
|
|
1130
1845
|
* 读取会话消息并转换为 Message 格式(用于恢复对话历史)
|
|
1131
1846
|
* 包含完整的 tool_calls 信息,确保 LLM 能理解之前的工具调用
|
|
1132
1847
|
*/
|
|
1133
1848
|
function loadSessionHistory(sessionId) {
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1849
|
+
return (withLockedSession(sessionId, session => {
|
|
1850
|
+
const messages = readSessionMessagesForSession(session);
|
|
1851
|
+
const checkpoint = loadCompactCheckpointForSession(session, messages);
|
|
1852
|
+
if (checkpoint) {
|
|
1853
|
+
const restored = [
|
|
1854
|
+
...checkpoint.modelHistory.map(message => ({ ...message })),
|
|
1855
|
+
...messages.slice(checkpoint.sourceMessageCount).map(sessionMessageToModelMessage),
|
|
1856
|
+
];
|
|
1857
|
+
if (checkpoint.version === 2) {
|
|
1858
|
+
try {
|
|
1859
|
+
(0, tool_call_groups_1.assertToolCallGroups)(restored);
|
|
1860
|
+
return restored;
|
|
1861
|
+
}
|
|
1862
|
+
catch (error) {
|
|
1863
|
+
// Never mutate or synthesize data inside a validated V2
|
|
1864
|
+
// replacement. Fall back to the append-only transcript instead.
|
|
1865
|
+
(0, debug_log_1.debugError)('session-storage.restoreCompactCheckpoint.toolGroups', error, sessionId);
|
|
1866
|
+
return (0, tool_call_groups_1.sealToolCallGroups)(messages.map(sessionMessageToModelMessage));
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
return (0, tool_call_groups_1.sealToolCallGroups)(restored);
|
|
1870
|
+
}
|
|
1871
|
+
let modelVisibleMessages = messages;
|
|
1872
|
+
if (typeof session.transcriptDisplayStartTime === 'number') {
|
|
1873
|
+
const afterDisplayStart = messages.filter(message => (message.timestamp ?? 0) >= (session.transcriptDisplayStartTime ?? 0));
|
|
1874
|
+
modelVisibleMessages = hasPersistedCompactContext(afterDisplayStart)
|
|
1875
|
+
? afterDisplayStart
|
|
1876
|
+
: messages;
|
|
1877
|
+
}
|
|
1878
|
+
return (0, tool_call_groups_1.sealToolCallGroups)(modelVisibleMessages.map(sessionMessageToModelMessage));
|
|
1879
|
+
}) ?? []);
|
|
1152
1880
|
}
|
|
1153
1881
|
function sessionMessageToModelMessage(message) {
|
|
1154
1882
|
const result = {
|
|
@@ -1231,11 +1959,14 @@ function renameSession(sessionId, name) {
|
|
|
1231
1959
|
function deleteSession(sessionId) {
|
|
1232
1960
|
return (withLockedSession(sessionId, session => {
|
|
1233
1961
|
let deleted = false;
|
|
1962
|
+
const compactPath = (0, config_dir_1.getProjectSessionCompactPath)(session.projectPath, sessionId);
|
|
1234
1963
|
const paths = [
|
|
1235
1964
|
(0, config_dir_1.getProjectSessionMetaPath)(session.projectPath, sessionId),
|
|
1236
1965
|
(0, config_dir_1.getProjectSessionMessagesPath)(session.projectPath, sessionId),
|
|
1237
1966
|
(0, config_dir_1.getProjectSessionHarnessPath)(session.projectPath, sessionId),
|
|
1238
|
-
|
|
1967
|
+
compactPath,
|
|
1968
|
+
compactCandidatePath(compactPath),
|
|
1969
|
+
compactPreviousPath(compactPath),
|
|
1239
1970
|
(0, config_dir_1.getProjectSessionTracePath)(session.projectPath, sessionId),
|
|
1240
1971
|
];
|
|
1241
1972
|
// Preserve a durable deletion fence so a stale writer in another process
|