@wrongstack/core 0.284.1 → 0.286.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-status-tracker.d.ts +74 -0
- package/dist/agent-status-tracker.d.ts.map +1 -0
- package/dist/autophase/auto-phase-planner.d.ts +79 -0
- package/dist/autophase/auto-phase-planner.d.ts.map +1 -0
- package/dist/autophase/auto-phase-runner.d.ts +79 -0
- package/dist/autophase/auto-phase-runner.d.ts.map +1 -0
- package/dist/autophase/checkpoint.d.ts +49 -0
- package/dist/autophase/checkpoint.d.ts.map +1 -0
- package/dist/autophase/index.d.ts +9 -0
- package/dist/autophase/index.d.ts.map +1 -0
- package/dist/autophase/phase-graph-builder.d.ts +46 -0
- package/dist/autophase/phase-graph-builder.d.ts.map +1 -0
- package/dist/autophase/phase-orchestrator.d.ts +150 -0
- package/dist/autophase/phase-orchestrator.d.ts.map +1 -0
- package/dist/autophase/phase-store.d.ts +29 -0
- package/dist/autophase/phase-store.d.ts.map +1 -0
- package/dist/autophase/types.d.ts +329 -0
- package/dist/autophase/types.d.ts.map +1 -0
- package/dist/boot.d.ts +73 -0
- package/dist/boot.d.ts.map +1 -0
- package/dist/coordination/adaptive-concurrency.d.ts +63 -0
- package/dist/coordination/adaptive-concurrency.d.ts.map +1 -0
- package/dist/coordination/agent-bridge.d.ts +24 -0
- package/dist/coordination/agent-bridge.d.ts.map +1 -0
- package/dist/coordination/agent-monitor.d.ts +129 -0
- package/dist/coordination/agent-monitor.d.ts.map +1 -0
- package/dist/coordination/agent-subagent-runner.d.ts +74 -0
- package/dist/coordination/agent-subagent-runner.d.ts.map +1 -0
- package/dist/coordination/agents/agent-prompts.d.ts +2 -0
- package/dist/coordination/agents/agent-prompts.d.ts.map +1 -0
- package/dist/coordination/agents/index.d.ts +35 -0
- package/dist/coordination/agents/index.d.ts.map +1 -0
- package/dist/coordination/agents/phase1-discovery.d.ts +4 -0
- package/dist/coordination/agents/phase1-discovery.d.ts.map +1 -0
- package/dist/coordination/agents/phase2-planning.d.ts +4 -0
- package/dist/coordination/agents/phase2-planning.d.ts.map +1 -0
- package/dist/coordination/agents/phase3-build.d.ts +4 -0
- package/dist/coordination/agents/phase3-build.d.ts.map +1 -0
- package/dist/coordination/agents/phase3-techstack.d.ts +13 -0
- package/dist/coordination/agents/phase3-techstack.d.ts.map +1 -0
- package/dist/coordination/agents/phase4-verify.d.ts +4 -0
- package/dist/coordination/agents/phase4-verify.d.ts.map +1 -0
- package/dist/coordination/agents/phase5-review.d.ts +4 -0
- package/dist/coordination/agents/phase5-review.d.ts.map +1 -0
- package/dist/coordination/agents/phase6-domain.d.ts +4 -0
- package/dist/coordination/agents/phase6-domain.d.ts.map +1 -0
- package/dist/coordination/agents/phase7-knowledge.d.ts +4 -0
- package/dist/coordination/agents/phase7-knowledge.d.ts.map +1 -0
- package/dist/coordination/agents/phase8-delivery.d.ts +4 -0
- package/dist/coordination/agents/phase8-delivery.d.ts.map +1 -0
- package/dist/coordination/agents/phase9-meta.d.ts +4 -0
- package/dist/coordination/agents/phase9-meta.d.ts.map +1 -0
- package/dist/coordination/agents/types.d.ts +79 -0
- package/dist/coordination/agents/types.d.ts.map +1 -0
- package/dist/coordination/agents.d.ts +8 -0
- package/dist/coordination/agents.d.ts.map +1 -0
- package/dist/coordination/auto-extend.d.ts +46 -0
- package/dist/coordination/auto-extend.d.ts.map +1 -0
- package/dist/coordination/autonomous-brain.d.ts +152 -0
- package/dist/coordination/autonomous-brain.d.ts.map +1 -0
- package/dist/coordination/autonomous-coordinator.d.ts +243 -0
- package/dist/coordination/autonomous-coordinator.d.ts.map +1 -0
- package/dist/coordination/brain-ledger.d.ts +142 -0
- package/dist/coordination/brain-ledger.d.ts.map +1 -0
- package/dist/coordination/brain-monitor.d.ts +103 -0
- package/dist/coordination/brain-monitor.d.ts.map +1 -0
- package/dist/coordination/brain.d.ts +147 -0
- package/dist/coordination/brain.d.ts.map +1 -0
- package/dist/coordination/change-manager.d.ts +151 -0
- package/dist/coordination/change-manager.d.ts.map +1 -0
- package/dist/coordination/checkpoint-wiring.d.ts +61 -0
- package/dist/coordination/checkpoint-wiring.d.ts.map +1 -0
- package/dist/coordination/collab-bus.d.ts +132 -0
- package/dist/coordination/collab-bus.d.ts.map +1 -0
- package/dist/coordination/collab-debug.d.ts +302 -0
- package/dist/coordination/collab-debug.d.ts.map +1 -0
- package/dist/coordination/commit-safety.d.ts +72 -0
- package/dist/coordination/commit-safety.d.ts.map +1 -0
- package/dist/coordination/consensus-protocol.d.ts +106 -0
- package/dist/coordination/consensus-protocol.d.ts.map +1 -0
- package/dist/coordination/coordinator/error-classifier.d.ts +15 -0
- package/dist/coordination/coordinator/error-classifier.d.ts.map +1 -0
- package/dist/coordination/delegate-tool.d.ts +101 -0
- package/dist/coordination/delegate-tool.d.ts.map +1 -0
- package/dist/coordination/dep-watcher-bridge.d.ts +47 -0
- package/dist/coordination/dep-watcher-bridge.d.ts.map +1 -0
- package/dist/coordination/dep-watcher.d.ts +74 -0
- package/dist/coordination/dep-watcher.d.ts.map +1 -0
- package/dist/coordination/director/director-errors.d.ts +29 -0
- package/dist/coordination/director/director-errors.d.ts.map +1 -0
- package/dist/coordination/director-construction.d.ts +90 -0
- package/dist/coordination/director-construction.d.ts.map +1 -0
- package/dist/coordination/director-prompts.d.ts +119 -0
- package/dist/coordination/director-prompts.d.ts.map +1 -0
- package/dist/coordination/director-session.d.ts +68 -0
- package/dist/coordination/director-session.d.ts.map +1 -0
- package/dist/coordination/director-tools.d.ts +65 -0
- package/dist/coordination/director-tools.d.ts.map +1 -0
- package/dist/coordination/director.d.ts +802 -0
- package/dist/coordination/director.d.ts.map +1 -0
- package/dist/coordination/dispatcher.d.ts +82 -0
- package/dist/coordination/dispatcher.d.ts.map +1 -0
- package/dist/coordination/file-author-tracker.d.ts +76 -0
- package/dist/coordination/file-author-tracker.d.ts.map +1 -0
- package/dist/coordination/fleet-bus.d.ts +122 -0
- package/dist/coordination/fleet-bus.d.ts.map +1 -0
- package/dist/coordination/fleet-event-validation.d.ts +10 -0
- package/dist/coordination/fleet-event-validation.d.ts.map +1 -0
- package/dist/coordination/fleet-manager.d.ts +234 -0
- package/dist/coordination/fleet-manager.d.ts.map +1 -0
- package/dist/coordination/fleet-spawn.d.ts +102 -0
- package/dist/coordination/fleet-spawn.d.ts.map +1 -0
- package/dist/coordination/fleet-status-tool.d.ts +36 -0
- package/dist/coordination/fleet-status-tool.d.ts.map +1 -0
- package/dist/coordination/fleet-supervisor.d.ts +157 -0
- package/dist/coordination/fleet-supervisor.d.ts.map +1 -0
- package/dist/coordination/fleet.d.ts +96 -0
- package/dist/coordination/fleet.d.ts.map +1 -0
- package/dist/coordination/global-mailbox.d.ts +295 -0
- package/dist/coordination/global-mailbox.d.ts.map +1 -0
- package/dist/coordination/icoordinator.d.ts +97 -0
- package/dist/coordination/icoordinator.d.ts.map +1 -0
- package/dist/coordination/ifleet-manager.d.ts +177 -0
- package/dist/coordination/ifleet-manager.d.ts.map +1 -0
- package/dist/coordination/in-memory-transport.d.ts +12 -0
- package/dist/coordination/in-memory-transport.d.ts.map +1 -0
- package/dist/coordination/index.d.ts +79 -2587
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +2262 -673
- package/dist/coordination/index.js.map +7 -1
- package/dist/coordination/knowledge-graph.d.ts +229 -0
- package/dist/coordination/knowledge-graph.d.ts.map +1 -0
- package/dist/coordination/large-answer-store.d.ts +61 -0
- package/dist/coordination/large-answer-store.d.ts.map +1 -0
- package/dist/coordination/mail-tools.d.ts +34 -0
- package/dist/coordination/mail-tools.d.ts.map +1 -0
- package/dist/coordination/mailbox-actions.d.ts +67 -0
- package/dist/coordination/mailbox-actions.d.ts.map +1 -0
- package/dist/coordination/mailbox-constants.d.ts +64 -0
- package/dist/coordination/mailbox-constants.d.ts.map +1 -0
- package/dist/coordination/mailbox-events.d.ts +32 -0
- package/dist/coordination/mailbox-events.d.ts.map +1 -0
- package/dist/coordination/mailbox-health.d.ts +131 -0
- package/dist/coordination/mailbox-health.d.ts.map +1 -0
- package/dist/coordination/mailbox-hooks.d.ts +55 -0
- package/dist/coordination/mailbox-hooks.d.ts.map +1 -0
- package/dist/coordination/mailbox-message-codec.d.ts +8 -0
- package/dist/coordination/mailbox-message-codec.d.ts.map +1 -0
- package/dist/coordination/mailbox-tool.d.ts +75 -0
- package/dist/coordination/mailbox-tool.d.ts.map +1 -0
- package/dist/{mailbox-types-BGZWrYTJ.d.ts → coordination/mailbox-types.d.ts} +125 -26
- package/dist/coordination/mailbox-types.d.ts.map +1 -0
- package/dist/coordination/mailbox.d.ts +88 -0
- package/dist/coordination/mailbox.d.ts.map +1 -0
- package/dist/coordination/model-matrix.d.ts +98 -0
- package/dist/coordination/model-matrix.d.ts.map +1 -0
- package/dist/coordination/multi-agent-coordinator.d.ts +202 -0
- package/dist/coordination/multi-agent-coordinator.d.ts.map +1 -0
- package/dist/coordination/null-fleet-bus.d.ts +10 -0
- package/dist/coordination/null-fleet-bus.d.ts.map +1 -0
- package/dist/coordination/package-author-tracker.d.ts +87 -0
- package/dist/coordination/package-author-tracker.d.ts.map +1 -0
- package/dist/coordination/package-outdated-watcher.d.ts +83 -0
- package/dist/coordination/package-outdated-watcher.d.ts.map +1 -0
- package/dist/coordination/single-instance-mailbox.d.ts +154 -0
- package/dist/coordination/single-instance-mailbox.d.ts.map +1 -0
- package/dist/coordination/spawn-budget.d.ts +6 -0
- package/dist/coordination/spawn-budget.d.ts.map +1 -0
- package/dist/coordination/subagent-budget.d.ts +323 -0
- package/dist/coordination/subagent-budget.d.ts.map +1 -0
- package/dist/coordination/subagent-nicknames.d.ts +42 -0
- package/dist/coordination/subagent-nicknames.d.ts.map +1 -0
- package/dist/coordination/subagent-result-tool.d.ts +20 -0
- package/dist/coordination/subagent-result-tool.d.ts.map +1 -0
- package/dist/coordination/task-auctioneer.d.ts +143 -0
- package/dist/coordination/task-auctioneer.d.ts.map +1 -0
- package/dist/coordination/task-dag.d.ts +147 -0
- package/dist/coordination/task-dag.d.ts.map +1 -0
- package/dist/coordination/techstack-mailbox-consumer.d.ts +50 -0
- package/dist/coordination/techstack-mailbox-consumer.d.ts.map +1 -0
- package/dist/coordination/transport.d.ts +2 -0
- package/dist/coordination/transport.d.ts.map +1 -0
- package/dist/coordination/worktree-task-runner.d.ts +45 -0
- package/dist/coordination/worktree-task-runner.d.ts.map +1 -0
- package/dist/core/agent-internals.d.ts +41 -0
- package/dist/core/agent-internals.d.ts.map +1 -0
- package/dist/core/agent-loop.d.ts +18 -0
- package/dist/core/agent-loop.d.ts.map +1 -0
- package/dist/core/agent-response.d.ts +21 -0
- package/dist/core/agent-response.d.ts.map +1 -0
- package/dist/core/agent-tools.d.ts +21 -0
- package/dist/core/agent-tools.d.ts.map +1 -0
- package/dist/core/agent-types.d.ts +95 -0
- package/dist/core/agent-types.d.ts.map +1 -0
- package/dist/core/agent.d.ts +54 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/btw.d.ts +40 -0
- package/dist/core/btw.d.ts.map +1 -0
- package/dist/core/context.d.ts +269 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/continue-intent.d.ts +92 -0
- package/dist/core/continue-intent.d.ts.map +1 -0
- package/dist/core/continue-to-next-iteration.d.ts +96 -0
- package/dist/core/continue-to-next-iteration.d.ts.map +1 -0
- package/dist/core/conversation-state.d.ts +96 -0
- package/dist/core/conversation-state.d.ts.map +1 -0
- package/dist/core/fallback-model.d.ts +94 -0
- package/dist/core/fallback-model.d.ts.map +1 -0
- package/dist/core/fleet-pulse.d.ts +42 -0
- package/dist/core/fleet-pulse.d.ts.map +1 -0
- package/dist/core/input-builder.d.ts +95 -0
- package/dist/core/input-builder.d.ts.map +1 -0
- package/dist/core/instruction-bundle.d.ts +22 -0
- package/dist/core/instruction-bundle.d.ts.map +1 -0
- package/dist/core/iteration-limit.d.ts +35 -0
- package/dist/core/iteration-limit.d.ts.map +1 -0
- package/dist/core/mailbox-loop.d.ts +63 -0
- package/dist/core/mailbox-loop.d.ts.map +1 -0
- package/dist/core/modes/brief.d.ts +2 -0
- package/dist/core/modes/brief.d.ts.map +1 -0
- package/dist/core/modes/default.d.ts +8 -0
- package/dist/core/modes/default.d.ts.map +1 -0
- package/dist/core/modes/teach.d.ts +2 -0
- package/dist/core/modes/teach.d.ts.map +1 -0
- package/dist/core/provider-runner.d.ts +24 -0
- package/dist/core/provider-runner.d.ts.map +1 -0
- package/dist/core/queued-messages.d.ts +55 -0
- package/dist/core/queued-messages.d.ts.map +1 -0
- package/dist/core/run-env.d.ts +49 -0
- package/dist/core/run-env.d.ts.map +1 -0
- package/dist/core/streaming-response-builder.d.ts +78 -0
- package/dist/core/streaming-response-builder.d.ts.map +1 -0
- package/dist/core/system-prompt-builder.d.ts +213 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -0
- package/dist/defaults/index.d.ts +68 -158
- package/dist/defaults/index.d.ts.map +1 -0
- package/dist/defaults/index.js +2061 -1300
- package/dist/defaults/index.js.map +7 -1
- package/dist/execution/auto-compaction-middleware.d.ts +123 -0
- package/dist/execution/auto-compaction-middleware.d.ts.map +1 -0
- package/dist/execution/autonomous-runner.d.ts +61 -0
- package/dist/execution/autonomous-runner.d.ts.map +1 -0
- package/dist/execution/autonomy-brain.d.ts +151 -0
- package/dist/execution/autonomy-brain.d.ts.map +1 -0
- package/dist/execution/autonomy-prompt-contributor.d.ts +39 -0
- package/dist/execution/autonomy-prompt-contributor.d.ts.map +1 -0
- package/dist/execution/brain-chain.d.ts +53 -0
- package/dist/execution/brain-chain.d.ts.map +1 -0
- package/dist/execution/brain-evaluation.d.ts +66 -0
- package/dist/execution/brain-evaluation.d.ts.map +1 -0
- package/dist/execution/brain-runtime.d.ts +171 -0
- package/dist/execution/brain-runtime.d.ts.map +1 -0
- package/dist/execution/compaction-core.d.ts +103 -0
- package/dist/execution/compaction-core.d.ts.map +1 -0
- package/dist/execution/compactor.d.ts +56 -0
- package/dist/execution/compactor.d.ts.map +1 -0
- package/dist/execution/council-brain.d.ts +79 -0
- package/dist/execution/council-brain.d.ts.map +1 -0
- package/dist/execution/design-color.d.ts +31 -0
- package/dist/execution/design-color.d.ts.map +1 -0
- package/dist/execution/design-detect.d.ts +96 -0
- package/dist/execution/design-detect.d.ts.map +1 -0
- package/dist/execution/design-kit-loader.d.ts +53 -0
- package/dist/execution/design-kit-loader.d.ts.map +1 -0
- package/dist/execution/design-materialize.d.ts +32 -0
- package/dist/execution/design-materialize.d.ts.map +1 -0
- package/dist/execution/design-project-store.d.ts +57 -0
- package/dist/execution/design-project-store.d.ts.map +1 -0
- package/dist/execution/design-verify.d.ts +44 -0
- package/dist/execution/design-verify.d.ts.map +1 -0
- package/dist/execution/error-handler.d.ts +34 -0
- package/dist/execution/error-handler.d.ts.map +1 -0
- package/dist/{parallel-eternal-engine-HUrtePLd.d.ts → execution/eternal-autonomy.d.ts} +22 -225
- package/dist/execution/eternal-autonomy.d.ts.map +1 -0
- package/dist/execution/goal-preamble.d.ts +2 -0
- package/dist/execution/goal-preamble.d.ts.map +1 -0
- package/dist/execution/index.d.ts +25 -180
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/execution/index.js +1748 -490
- package/dist/execution/index.js.map +7 -1
- package/dist/execution/intelligent-compactor.d.ts +85 -0
- package/dist/execution/intelligent-compactor.d.ts.map +1 -0
- package/dist/execution/model-runtime.d.ts +75 -0
- package/dist/execution/model-runtime.d.ts.map +1 -0
- package/dist/execution/parallel-eternal-engine.d.ts +142 -0
- package/dist/execution/parallel-eternal-engine.d.ts.map +1 -0
- package/dist/execution/prompt-enhancer.d.ts +12 -13
- package/dist/execution/prompt-enhancer.d.ts.map +1 -0
- package/dist/execution/prompt-enhancer.js +13 -7
- package/dist/execution/prompt-enhancer.js.map +7 -1
- package/dist/execution/prompt-loader.d.ts +52 -0
- package/dist/execution/prompt-loader.d.ts.map +1 -0
- package/dist/execution/provider-runner-impl.d.ts +14 -0
- package/dist/execution/provider-runner-impl.d.ts.map +1 -0
- package/dist/execution/regex-patterns.d.ts +7 -0
- package/dist/execution/regex-patterns.d.ts.map +1 -0
- package/dist/execution/retry-policy.d.ts +35 -0
- package/dist/execution/retry-policy.d.ts.map +1 -0
- package/dist/execution/selective-compactor.d.ts +94 -0
- package/dist/execution/selective-compactor.d.ts.map +1 -0
- package/dist/execution/skill-loader.d.ts +43 -0
- package/dist/execution/skill-loader.d.ts.map +1 -0
- package/dist/execution/strategy-compactor.d.ts +43 -0
- package/dist/execution/strategy-compactor.d.ts.map +1 -0
- package/dist/execution/tool-executor.d.ts +112 -0
- package/dist/execution/tool-executor.d.ts.map +1 -0
- package/dist/extension/extension-points.d.ts +121 -0
- package/dist/extension/extension-points.d.ts.map +1 -0
- package/dist/extension/index.d.ts +3 -10
- package/dist/extension/index.d.ts.map +1 -0
- package/dist/extension/index.js +59 -5
- package/dist/extension/index.js.map +7 -1
- package/dist/extension/registry.d.ts +86 -0
- package/dist/extension/registry.d.ts.map +1 -0
- package/dist/fleet-notifier.d.ts +28 -0
- package/dist/fleet-notifier.d.ts.map +1 -0
- package/dist/hooks/http-executor.d.ts +11 -0
- package/dist/hooks/http-executor.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/registry.d.ts +71 -0
- package/dist/hooks/registry.d.ts.map +1 -0
- package/dist/hooks/runner.d.ts +65 -0
- package/dist/hooks/runner.d.ts.map +1 -0
- package/dist/hooks/shell-executor.d.ts +33 -0
- package/dist/hooks/shell-executor.d.ts.map +1 -0
- package/dist/hooks/shell-hooks-equal.d.ts +15 -0
- package/dist/hooks/shell-hooks-equal.d.ts.map +1 -0
- package/dist/hq/agent-bridge.d.ts +27 -0
- package/dist/hq/agent-bridge.d.ts.map +1 -0
- package/dist/hq/alerts.d.ts +67 -0
- package/dist/hq/alerts.d.ts.map +1 -0
- package/dist/hq/auth-store.d.ts +179 -0
- package/dist/hq/auth-store.d.ts.map +1 -0
- package/dist/hq/brain-bridge.d.ts +37 -0
- package/dist/hq/brain-bridge.d.ts.map +1 -0
- package/dist/hq/commands.d.ts +122 -0
- package/dist/hq/commands.d.ts.map +1 -0
- package/dist/hq/cost-bridge.d.ts +36 -0
- package/dist/hq/cost-bridge.d.ts.map +1 -0
- package/dist/hq/factory.d.ts +69 -0
- package/dist/hq/factory.d.ts.map +1 -0
- package/dist/hq/fleet-bridge.d.ts +39 -0
- package/dist/hq/fleet-bridge.d.ts.map +1 -0
- package/dist/hq/index.d.ts +18 -816
- package/dist/hq/index.d.ts.map +1 -0
- package/dist/hq/index.js +1043 -192
- package/dist/hq/index.js.map +7 -1
- package/dist/hq/mailbox-mapper.d.ts +27 -0
- package/dist/hq/mailbox-mapper.d.ts.map +1 -0
- package/dist/hq/persistence.d.ts +121 -0
- package/dist/hq/persistence.d.ts.map +1 -0
- package/dist/hq/protocol.d.ts +612 -0
- package/dist/hq/protocol.d.ts.map +1 -0
- package/dist/hq/publisher.d.ts +181 -0
- package/dist/hq/publisher.d.ts.map +1 -0
- package/dist/hq/redaction.d.ts +30 -0
- package/dist/hq/redaction.d.ts.map +1 -0
- package/dist/hq/session-bridge.d.ts +29 -0
- package/dist/hq/session-bridge.d.ts.map +1 -0
- package/dist/hq/tool-bridge.d.ts +41 -0
- package/dist/hq/tool-bridge.d.ts.map +1 -0
- package/dist/hq/transcript-mapper.d.ts +36 -0
- package/dist/hq/transcript-mapper.d.ts.map +1 -0
- package/dist/hq/worktree-bridge.d.ts +34 -0
- package/dist/hq/worktree-bridge.d.ts.map +1 -0
- package/dist/index.d.ts +114 -2872
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6104 -2737
- package/dist/index.js.map +7 -1
- package/dist/infrastructure/context-manager.d.ts +92 -0
- package/dist/infrastructure/context-manager.d.ts.map +1 -0
- package/dist/infrastructure/index.d.ts +6 -64
- package/dist/infrastructure/index.d.ts.map +1 -0
- package/dist/infrastructure/index.js +39 -12
- package/dist/infrastructure/index.js.map +7 -1
- package/dist/infrastructure/logger.d.ts +99 -0
- package/dist/infrastructure/logger.d.ts.map +1 -0
- package/dist/infrastructure/mcp-servers.d.ts +83 -0
- package/dist/infrastructure/mcp-servers.d.ts.map +1 -0
- package/dist/{path-resolver-CMS5307d.d.ts → infrastructure/path-resolver.d.ts} +3 -5
- package/dist/infrastructure/path-resolver.d.ts.map +1 -0
- package/dist/infrastructure/token-counter.d.ts +57 -0
- package/dist/infrastructure/token-counter.d.ts.map +1 -0
- package/dist/kernel/container.d.ts +84 -0
- package/dist/kernel/container.d.ts.map +1 -0
- package/dist/{events-Bgnh43r9.d.ts → kernel/events.d.ts} +134 -210
- package/dist/kernel/events.d.ts.map +1 -0
- package/dist/kernel/index.d.ts +6 -107
- package/dist/kernel/index.d.ts.map +1 -0
- package/dist/kernel/index.js +56 -4
- package/dist/kernel/index.js.map +7 -1
- package/dist/kernel/pipeline.d.ts +105 -0
- package/dist/kernel/pipeline.d.ts.map +1 -0
- package/dist/kernel/run-controller.d.ts +55 -0
- package/dist/kernel/run-controller.d.ts.map +1 -0
- package/dist/kernel/tokens.d.ts +53 -0
- package/dist/kernel/tokens.d.ts.map +1 -0
- package/dist/mailbox-attach.d.ts +27 -0
- package/dist/mailbox-attach.d.ts.map +1 -0
- package/dist/middleware/collab-pause.d.ts +73 -0
- package/dist/middleware/collab-pause.d.ts.map +1 -0
- package/dist/models/codex-catalog.d.ts +41 -0
- package/dist/models/codex-catalog.d.ts.map +1 -0
- package/dist/models/index.d.ts +8 -163
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +150 -51
- package/dist/models/index.js.map +7 -1
- package/dist/models/llm-selector.d.ts +47 -0
- package/dist/models/llm-selector.d.ts.map +1 -0
- package/dist/models/mode-store.d.ts +22 -0
- package/dist/models/mode-store.d.ts.map +1 -0
- package/dist/models/model-intelligence.d.ts +56 -0
- package/dist/models/model-intelligence.d.ts.map +1 -0
- package/dist/models/model-router.d.ts +100 -0
- package/dist/models/model-router.d.ts.map +1 -0
- package/dist/models/models-registry.d.ts +106 -0
- package/dist/models/models-registry.d.ts.map +1 -0
- package/dist/models/provider-model-resolve.d.ts +69 -0
- package/dist/models/provider-model-resolve.d.ts.map +1 -0
- package/dist/observability/event-bridge.d.ts +10 -0
- package/dist/observability/event-bridge.d.ts.map +1 -0
- package/dist/observability/health.d.ts +18 -0
- package/dist/observability/health.d.ts.map +1 -0
- package/dist/observability/index.d.ts +9 -354
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +37 -23
- package/dist/observability/index.js.map +7 -1
- package/dist/observability/metrics.d.ts +26 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/otel-tracer.d.ts +41 -0
- package/dist/observability/otel-tracer.d.ts.map +1 -0
- package/dist/observability/otlp-metrics.d.ts +111 -0
- package/dist/observability/otlp-metrics.d.ts.map +1 -0
- package/dist/observability/otlp-traces.d.ts +95 -0
- package/dist/observability/otlp-traces.d.ts.map +1 -0
- package/dist/observability/prometheus.d.ts +49 -0
- package/dist/observability/prometheus.d.ts.map +1 -0
- package/dist/observability/tracer.d.ts +9 -0
- package/dist/observability/tracer.d.ts.map +1 -0
- package/dist/plugin/api.d.ts +226 -0
- package/dist/plugin/api.d.ts.map +1 -0
- package/dist/plugin/loader.d.ts +73 -0
- package/dist/plugin/loader.d.ts.map +1 -0
- package/dist/plugins/chimera-plugin.d.ts +37 -0
- package/dist/plugins/chimera-plugin.d.ts.map +1 -0
- package/dist/plugins/prompts-plugin.d.ts +26 -0
- package/dist/plugins/prompts-plugin.d.ts.map +1 -0
- package/dist/plugins/security-plugin.d.ts +19 -0
- package/dist/plugins/security-plugin.d.ts.map +1 -0
- package/dist/plugins/skills-plugin.d.ts +42 -0
- package/dist/plugins/skills-plugin.d.ts.map +1 -0
- package/dist/plugins/sync-plugin.d.ts +22 -0
- package/dist/plugins/sync-plugin.d.ts.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/prompt-installer.d.ts +50 -0
- package/dist/prompts/prompt-installer.d.ts.map +1 -0
- package/dist/prompts/prompt-manifest-store.d.ts +18 -0
- package/dist/prompts/prompt-manifest-store.d.ts.map +1 -0
- package/dist/registry/provider-registry.d.ts +51 -0
- package/dist/registry/provider-registry.d.ts.map +1 -0
- package/dist/registry/slash-command-registry.d.ts +61 -0
- package/dist/registry/slash-command-registry.d.ts.map +1 -0
- package/dist/registry/tool-registry.d.ts +154 -0
- package/dist/registry/tool-registry.d.ts.map +1 -0
- package/dist/replay/hash.d.ts +31 -0
- package/dist/replay/hash.d.ts.map +1 -0
- package/dist/replay/replay-provider-runner.d.ts +53 -0
- package/dist/replay/replay-provider-runner.d.ts.map +1 -0
- package/dist/{index-CbyuOE5y.d.ts → security/capabilities.d.ts} +31 -34
- package/dist/security/capabilities.d.ts.map +1 -0
- package/dist/security/config-secrets.d.ts +25 -0
- package/dist/security/config-secrets.d.ts.map +1 -0
- package/dist/security/index.d.ts +7 -8
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +354 -401
- package/dist/security/index.js.map +7 -1
- package/dist/security/permission-policy-schema.d.ts +77 -0
- package/dist/security/permission-policy-schema.d.ts.map +1 -0
- package/dist/security/permission-policy.d.ts +158 -0
- package/dist/security/permission-policy.d.ts.map +1 -0
- package/dist/security/secret-scrubber.d.ts +14 -0
- package/dist/security/secret-scrubber.d.ts.map +1 -0
- package/dist/security/secret-vault.d.ts +96 -0
- package/dist/security/secret-vault.d.ts.map +1 -0
- package/dist/security/yolo-risk.d.ts +11 -0
- package/dist/security/yolo-risk.d.ts.map +1 -0
- package/dist/{session-registry-Dvg7i_IA.d.ts → session-registry.d.ts} +8 -9
- package/dist/session-registry.d.ts.map +1 -0
- package/dist/skills/foreign-sources.d.ts +59 -0
- package/dist/skills/foreign-sources.d.ts.map +1 -0
- package/dist/skills/frontmatter.d.ts +44 -0
- package/dist/skills/frontmatter.d.ts.map +1 -0
- package/dist/skills/github-fetcher.d.ts +38 -0
- package/dist/skills/github-fetcher.d.ts.map +1 -0
- package/dist/skills/index.d.ts +11 -582
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +81 -43
- package/dist/skills/index.js.map +7 -1
- package/dist/skills/limits.d.ts +92 -0
- package/dist/skills/limits.d.ts.map +1 -0
- package/dist/skills/manifest-store.d.ts +42 -0
- package/dist/skills/manifest-store.d.ts.map +1 -0
- package/dist/skills/registry/github-direct-adapter.d.ts +17 -0
- package/dist/skills/registry/github-direct-adapter.d.ts.map +1 -0
- package/dist/skills/registry/registry-adapter.d.ts +84 -0
- package/dist/skills/registry/registry-adapter.d.ts.map +1 -0
- package/dist/skills/registry/skills-sh-adapter.d.ts +13 -0
- package/dist/skills/registry/skills-sh-adapter.d.ts.map +1 -0
- package/dist/skills/skill-generator.d.ts +82 -0
- package/dist/skills/skill-generator.d.ts.map +1 -0
- package/dist/skills/skill-installer.d.ts +124 -0
- package/dist/skills/skill-installer.d.ts.map +1 -0
- package/dist/storage/annotations-store.d.ts +118 -0
- package/dist/storage/annotations-store.d.ts.map +1 -0
- package/dist/storage/attachment-store.d.ts +31 -0
- package/dist/storage/attachment-store.d.ts.map +1 -0
- package/dist/storage/cloud-sync.d.ts +44 -0
- package/dist/storage/cloud-sync.d.ts.map +1 -0
- package/dist/storage/completed-work-checkpoint.d.ts +11 -0
- package/dist/storage/completed-work-checkpoint.d.ts.map +1 -0
- package/dist/storage/config-loader.d.ts +114 -0
- package/dist/storage/config-loader.d.ts.map +1 -0
- package/dist/storage/config-migration.d.ts +87 -0
- package/dist/storage/config-migration.d.ts.map +1 -0
- package/dist/storage/config-store.d.ts +22 -0
- package/dist/storage/config-store.d.ts.map +1 -0
- package/dist/{director-state-CMS_bMs4.d.ts → storage/director-state.d.ts} +28 -8
- package/dist/storage/director-state.d.ts.map +1 -0
- package/dist/storage/file-session-writer.d.ts +169 -0
- package/dist/storage/file-session-writer.d.ts.map +1 -0
- package/dist/{goal-store-Datpp-ar.d.ts → storage/goal-store.d.ts} +26 -19
- package/dist/storage/goal-store.d.ts.map +1 -0
- package/dist/storage/index.d.ts +39 -1031
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +783 -443
- package/dist/storage/index.js.map +7 -1
- package/dist/storage/input-history-store.d.ts +56 -0
- package/dist/storage/input-history-store.d.ts.map +1 -0
- package/dist/storage/memory-backend.d.ts +66 -0
- package/dist/storage/memory-backend.d.ts.map +1 -0
- package/dist/storage/memory-consolidator.d.ts +50 -0
- package/dist/storage/memory-consolidator.d.ts.map +1 -0
- package/dist/storage/memory-graph-backend.d.ts +117 -0
- package/dist/storage/memory-graph-backend.d.ts.map +1 -0
- package/dist/storage/memory-store.d.ts +119 -0
- package/dist/storage/memory-store.d.ts.map +1 -0
- package/dist/storage/plan-store.d.ts +78 -0
- package/dist/storage/plan-store.d.ts.map +1 -0
- package/dist/storage/plan-templates.d.ts +21 -0
- package/dist/storage/plan-templates.d.ts.map +1 -0
- package/dist/storage/prompt-store.d.ts +37 -0
- package/dist/storage/prompt-store.d.ts.map +1 -0
- package/dist/storage/prompt-usage-store.d.ts +29 -0
- package/dist/storage/prompt-usage-store.d.ts.map +1 -0
- package/dist/storage/provider-config-watcher.d.ts +34 -0
- package/dist/storage/provider-config-watcher.d.ts.map +1 -0
- package/dist/storage/queue-store.d.ts +41 -0
- package/dist/storage/queue-store.d.ts.map +1 -0
- package/dist/storage/recovery-lock.d.ts +79 -0
- package/dist/storage/recovery-lock.d.ts.map +1 -0
- package/dist/storage/replay-log-store.d.ts +97 -0
- package/dist/storage/replay-log-store.d.ts.map +1 -0
- package/dist/storage/session-analyzer.d.ts +48 -0
- package/dist/storage/session-analyzer.d.ts.map +1 -0
- package/dist/storage/session-checkpoint-cas.d.ts +37 -0
- package/dist/storage/session-checkpoint-cas.d.ts.map +1 -0
- package/dist/{session-event-bridge-D_z_mBwk.d.ts → storage/session-event-bridge.d.ts} +14 -15
- package/dist/storage/session-event-bridge.d.ts.map +1 -0
- package/dist/storage/session-helpers.d.ts +9 -0
- package/dist/storage/session-helpers.d.ts.map +1 -0
- package/dist/storage/session-id.d.ts +18 -0
- package/dist/storage/session-id.d.ts.map +1 -0
- package/dist/storage/session-reader.d.ts +21 -0
- package/dist/storage/session-reader.d.ts.map +1 -0
- package/dist/storage/session-recovery.d.ts +93 -0
- package/dist/storage/session-recovery.d.ts.map +1 -0
- package/dist/storage/session-resume-validation.d.ts +6 -0
- package/dist/storage/session-resume-validation.d.ts.map +1 -0
- package/dist/storage/session-rewinder.d.ts +21 -0
- package/dist/storage/session-rewinder.d.ts.map +1 -0
- package/dist/storage/session-store.d.ts +219 -0
- package/dist/storage/session-store.d.ts.map +1 -0
- package/dist/storage/session-summary.d.ts +12 -0
- package/dist/storage/session-summary.d.ts.map +1 -0
- package/dist/storage/session-tool-call-ends.d.ts +5 -0
- package/dist/storage/session-tool-call-ends.d.ts.map +1 -0
- package/dist/storage/storage-concurrency.d.ts +2 -0
- package/dist/storage/storage-concurrency.d.ts.map +1 -0
- package/dist/storage/task-store.d.ts +33 -0
- package/dist/storage/task-store.d.ts.map +1 -0
- package/dist/storage/todos-checkpoint.d.ts +39 -0
- package/dist/storage/todos-checkpoint.d.ts.map +1 -0
- package/dist/storage/tool-audit-log.d.ts +141 -0
- package/dist/storage/tool-audit-log.d.ts.map +1 -0
- package/dist/tasking/index.d.ts +3 -124
- package/dist/tasking/index.d.ts.map +1 -0
- package/dist/tasking/index.js +57 -4
- package/dist/tasking/index.js.map +7 -1
- package/dist/tasking/task-store.d.ts +22 -0
- package/dist/tasking/task-store.d.ts.map +1 -0
- package/dist/tasking/task-tracker.d.ts +102 -0
- package/dist/tasking/task-tracker.d.ts.map +1 -0
- package/dist/tools/index.d.ts +2 -59
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +93 -14
- package/dist/tools/index.js.map +7 -1
- package/dist/tools/mcp-control.d.ts +53 -0
- package/dist/tools/mcp-control.d.ts.map +1 -0
- package/dist/tools/mcp-use.d.ts +24 -0
- package/dist/tools/mcp-use.d.ts.map +1 -0
- package/dist/types/agent-bridge.d.ts +42 -0
- package/dist/types/agent-bridge.d.ts.map +1 -0
- package/dist/types/attachment.d.ts +54 -0
- package/dist/types/attachment.d.ts.map +1 -0
- package/dist/types/autonomy.d.ts +5 -0
- package/dist/types/autonomy.d.ts.map +1 -0
- package/dist/types/blocks.d.ts +76 -0
- package/dist/types/blocks.d.ts.map +1 -0
- package/dist/{compactor-DQLL4HTo.d.ts → types/compactor.d.ts} +5 -7
- package/dist/types/compactor.d.ts.map +1 -0
- package/dist/{config-MRqn1V-u.d.ts → types/config.d.ts} +344 -355
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/context-evidence.d.ts +68 -0
- package/dist/types/context-evidence.d.ts.map +1 -0
- package/dist/types/context-window.d.ts +35 -0
- package/dist/types/context-window.d.ts.map +1 -0
- package/dist/{default-config-B79_gJYv.d.ts → types/default-config.d.ts} +10 -11
- package/dist/types/default-config.d.ts.map +1 -0
- package/dist/types/design-kit.d.ts +91 -0
- package/dist/types/design-kit.d.ts.map +1 -0
- package/dist/{retry-policy-CQ7KwXJa.d.ts → types/error-handler.d.ts} +5 -12
- package/dist/types/error-handler.d.ts.map +1 -0
- package/dist/types/errors.d.ts +277 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/hooks.d.ts +167 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/index.d.ts +40 -244
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +101 -12
- package/dist/types/index.js.map +7 -1
- package/dist/{input-reader-E-ffP2ee.d.ts → types/input-reader.d.ts} +3 -4
- package/dist/types/input-reader.d.ts.map +1 -0
- package/dist/{logger-B63L5bTg.d.ts → types/logger.d.ts} +3 -4
- package/dist/types/logger.d.ts.map +1 -0
- package/dist/types/memory.d.ts +89 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/messages.d.ts +24 -0
- package/dist/types/messages.d.ts.map +1 -0
- package/dist/types/mode-prompts.d.ts +2 -0
- package/dist/types/mode-prompts.d.ts.map +1 -0
- package/dist/{mode-CZlO9iU1.d.ts → types/mode.d.ts} +6 -7
- package/dist/types/mode.d.ts.map +1 -0
- package/dist/types/models-registry.d.ts +105 -0
- package/dist/types/models-registry.d.ts.map +1 -0
- package/dist/types/multi-agent.d.ts +443 -0
- package/dist/types/multi-agent.d.ts.map +1 -0
- package/dist/{observability-D-HZN_mF.d.ts → types/observability.d.ts} +17 -13
- package/dist/types/observability.d.ts.map +1 -0
- package/dist/{path-resolver-CPRj4bFY.d.ts → types/path-resolver.d.ts} +2 -3
- package/dist/types/path-resolver.d.ts.map +1 -0
- package/dist/{permission-ByDKXEcG.d.ts → types/permission.d.ts} +8 -9
- package/dist/types/permission.d.ts.map +1 -0
- package/dist/types/plugin.d.ts +385 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/prompt-registry.d.ts +81 -0
- package/dist/types/prompt-registry.d.ts.map +1 -0
- package/dist/{prompt-DLd35n4Q.d.ts → types/prompt.d.ts} +14 -15
- package/dist/types/prompt.d.ts.map +1 -0
- package/dist/{provider-runner-ChL-kVg6.d.ts → types/provider-runner.d.ts} +9 -10
- package/dist/types/provider-runner.d.ts.map +1 -0
- package/dist/types/provider.d.ts +387 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/renderer.d.ts +23 -0
- package/dist/types/renderer.d.ts.map +1 -0
- package/dist/types/retry-policy.d.ts +7 -0
- package/dist/types/retry-policy.d.ts.map +1 -0
- package/dist/types/secret-scrubber.d.ts +5 -0
- package/dist/types/secret-scrubber.d.ts.map +1 -0
- package/dist/{secret-vault-BAKpgFw_.d.ts → types/secret-vault.d.ts} +13 -7
- package/dist/types/secret-vault.d.ts.map +1 -0
- package/dist/{selector-D8O6B_Rm.d.ts → types/selector.d.ts} +4 -6
- package/dist/types/selector.d.ts.map +1 -0
- package/dist/types/session-reader.d.ts +81 -0
- package/dist/types/session-reader.d.ts.map +1 -0
- package/dist/{session-rewinder-C9HnMkhP.d.ts → types/session-rewinder.d.ts} +5 -6
- package/dist/types/session-rewinder.d.ts.map +1 -0
- package/dist/types/session.d.ts +650 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/side-effect.d.ts +34 -0
- package/dist/types/side-effect.d.ts.map +1 -0
- package/dist/{skill-DHniprNl.d.ts → types/skill.d.ts} +4 -5
- package/dist/types/skill.d.ts.map +1 -0
- package/dist/types/slash-command.d.ts +59 -0
- package/dist/types/slash-command.d.ts.map +1 -0
- package/dist/types/spec.d.ts +77 -0
- package/dist/types/spec.d.ts.map +1 -0
- package/dist/types/system-prompt-contributor.d.ts +20 -0
- package/dist/types/system-prompt-contributor.d.ts.map +1 -0
- package/dist/types/system-prompt.d.ts +51 -0
- package/dist/types/system-prompt.d.ts.map +1 -0
- package/dist/{task-graph-CH3acNQ7.d.ts → types/task-graph.d.ts} +21 -22
- package/dist/types/task-graph.d.ts.map +1 -0
- package/dist/types/token-counter.d.ts +42 -0
- package/dist/types/token-counter.d.ts.map +1 -0
- package/dist/types/tool-executor.d.ts +133 -0
- package/dist/types/tool-executor.d.ts.map +1 -0
- package/dist/types/tool-markers.d.ts +23 -0
- package/dist/types/tool-markers.d.ts.map +1 -0
- package/dist/types/tool.d.ts +252 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/utility-types.d.ts +31 -0
- package/dist/types/utility-types.d.ts.map +1 -0
- package/dist/utils/assert-never.d.ts +14 -0
- package/dist/utils/assert-never.d.ts.map +1 -0
- package/dist/utils/atomic-write.d.ts +12 -0
- package/dist/utils/atomic-write.d.ts.map +1 -0
- package/dist/utils/child-env.d.ts +67 -0
- package/dist/utils/child-env.d.ts.map +1 -0
- package/dist/utils/color.d.ts +20 -0
- package/dist/utils/color.d.ts.map +1 -0
- package/dist/utils/config-json.d.ts +14 -0
- package/dist/utils/config-json.d.ts.map +1 -0
- package/dist/utils/context-evidence.d.ts +47 -0
- package/dist/utils/context-evidence.d.ts.map +1 -0
- package/dist/utils/deep-merge.d.ts +64 -0
- package/dist/utils/deep-merge.d.ts.map +1 -0
- package/dist/utils/diff.d.ts +11 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/error.d.ts +2 -3
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +3 -3
- package/dist/utils/error.js.map +7 -1
- package/dist/utils/expect-defined.d.ts +2 -3
- package/dist/utils/expect-defined.d.ts.map +1 -0
- package/dist/utils/expect-defined.js +3 -3
- package/dist/utils/expect-defined.js.map +7 -1
- package/dist/utils/glob-expand.d.ts +10 -0
- package/dist/utils/glob-expand.d.ts.map +1 -0
- package/dist/utils/glob-match.d.ts +4 -0
- package/dist/utils/glob-match.d.ts.map +1 -0
- package/dist/utils/incoming-images.d.ts +39 -0
- package/dist/utils/incoming-images.d.ts.map +1 -0
- package/dist/utils/index.d.ts +38 -920
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +323 -36
- package/dist/utils/index.js.map +7 -1
- package/dist/utils/instruction-file.d.ts +3 -0
- package/dist/utils/instruction-file.d.ts.map +1 -0
- package/dist/utils/ip-guard.d.ts +34 -0
- package/dist/utils/ip-guard.d.ts.map +1 -0
- package/dist/utils/json-repair.d.ts +23 -0
- package/dist/utils/json-repair.d.ts.map +1 -0
- package/dist/utils/json-schema-validate.d.ts +42 -0
- package/dist/utils/json-schema-validate.d.ts.map +1 -0
- package/dist/utils/lru-cache.d.ts +29 -0
- package/dist/utils/lru-cache.d.ts.map +1 -0
- package/dist/utils/merge-custom-models.d.ts +12 -0
- package/dist/utils/merge-custom-models.d.ts.map +1 -0
- package/dist/utils/merge-models-payload.d.ts +20 -0
- package/dist/utils/merge-models-payload.d.ts.map +1 -0
- package/dist/utils/message-invariants.d.ts +22 -0
- package/dist/utils/message-invariants.d.ts.map +1 -0
- package/dist/utils/newline-normalize.d.ts +5 -0
- package/dist/utils/newline-normalize.d.ts.map +1 -0
- package/dist/utils/regex-guard.d.ts +21 -0
- package/dist/utils/regex-guard.d.ts.map +1 -0
- package/dist/utils/safe-json.d.ts +31 -0
- package/dist/utils/safe-json.d.ts.map +1 -0
- package/dist/utils/session-scoped-path.d.ts +13 -0
- package/dist/utils/session-scoped-path.d.ts.map +1 -0
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/slug.d.ts +13 -0
- package/dist/utils/slug.d.ts.map +1 -0
- package/dist/utils/string.d.ts +9 -0
- package/dist/utils/string.d.ts.map +1 -0
- package/dist/utils/task-format.d.ts +22 -0
- package/dist/utils/task-format.d.ts.map +1 -0
- package/dist/utils/term.d.ts +133 -0
- package/dist/utils/term.d.ts.map +1 -0
- package/dist/utils/todos-format.d.ts +30 -0
- package/dist/utils/todos-format.d.ts.map +1 -0
- package/dist/utils/token-estimate.d.ts +112 -0
- package/dist/utils/token-estimate.d.ts.map +1 -0
- package/dist/utils/tool-description-mode.d.ts +28 -0
- package/dist/utils/tool-description-mode.d.ts.map +1 -0
- package/dist/utils/tool-output-serializer.d.ts +40 -0
- package/dist/utils/tool-output-serializer.d.ts.map +1 -0
- package/dist/utils/tool-result-render-mode.d.ts +55 -0
- package/dist/utils/tool-result-render-mode.d.ts.map +1 -0
- package/dist/utils/tool-subject.d.ts +5 -0
- package/dist/utils/tool-subject.d.ts.map +1 -0
- package/dist/utils/tool-wire-compact.d.ts +28 -0
- package/dist/utils/tool-wire-compact.d.ts.map +1 -0
- package/dist/utils/ulid.d.ts +11 -0
- package/dist/utils/ulid.d.ts.map +1 -0
- package/dist/{wstack-paths-C3K40Qst.d.ts → utils/wstack-paths.d.ts} +7 -8
- package/dist/utils/wstack-paths.d.ts.map +1 -0
- package/dist/worktree/index.d.ts +2 -0
- package/dist/worktree/index.d.ts.map +1 -0
- package/dist/{worktree-manager-DzwxKE35.d.ts → worktree/worktree-manager.d.ts} +32 -17
- package/dist/worktree/worktree-manager.d.ts.map +1 -0
- package/instructions/agents/browser.md +25 -16
- package/instructions/autonomy/active-mission.md +2 -4
- package/instructions/coordination/subagent-baseline.md +16 -2
- package/instructions/leader-after-task.md +3 -1
- package/instructions/sections/tool/common-patterns.md +7 -1
- package/instructions/sections/tool/delegation-full.md +1 -1
- package/instructions/system.md +47 -0
- package/package.json +4 -5
- package/skills/docker-deploy/SKILL.md +1 -1
- package/skills/node-modern/SKILL.md +2 -2
- package/skills/plugin-author/SKILL.md +9 -16
- package/skills/wrongstack-mailbox/SKILL.md +51 -12
- package/dist/dispatcher-types.d-BBeXBQgS.d.ts +0 -66
- package/dist/global-mailbox-sZwyI6CS.d.ts +0 -959
- package/dist/index--Gm41aBJ.d.ts +0 -671
- package/dist/mcp-servers-DEV4s6Ks.d.ts +0 -259
- package/dist/multi-agent-coordinator-4RCRZKjN.d.ts +0 -1770
- package/dist/null-fleet-bus-CFoNVQEK.d.ts +0 -2127
- package/dist/pipeline-DGDyIohT.d.ts +0 -331
- package/dist/provider-model-resolve-o2hHLs79.d.ts +0 -263
- package/dist/secret-scrubber-3MHDDAtm.d.ts +0 -6
- package/dist/secret-vault-DxohkUBc.d.ts +0 -272
- package/dist/session-reader-7Esxrkpw.d.ts +0 -155
- package/dist/task-format-GX0B1mMC.d.ts +0 -23
- package/dist/todos-checkpoint-FY7PjmMx.d.ts +0 -850
- package/dist/tool-BNlnIJvo.d.ts +0 -2190
- package/dist/tool-executor-CckSCM5E.d.ts +0 -906
package/dist/storage/index.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { randomUUID, createHash, randomBytes } from 'crypto';
|
|
2
|
-
import * as syncFs from 'fs';
|
|
3
|
-
import { createReadStream, openSync, writeSync, fsyncSync, closeSync, readFileSync, statSync } from 'fs';
|
|
4
|
-
import * as fsp4 from 'fs/promises';
|
|
5
|
-
import * as path2 from 'path';
|
|
6
|
-
import { createInterface } from 'readline';
|
|
7
|
-
import * as os from 'os';
|
|
8
|
-
import { hostname } from 'os';
|
|
9
|
-
import { spawn } from 'child_process';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
|
-
|
|
12
1
|
// src/storage/session-store.ts
|
|
2
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
3
|
+
import { createReadStream } from "node:fs";
|
|
4
|
+
import * as fsp4 from "node:fs/promises";
|
|
5
|
+
import * as path7 from "node:path";
|
|
6
|
+
import { createInterface } from "node:readline";
|
|
7
|
+
|
|
8
|
+
// src/utils/atomic-write.ts
|
|
9
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
10
|
+
import * as fs from "node:fs/promises";
|
|
11
|
+
import * as path3 from "node:path";
|
|
13
12
|
|
|
14
13
|
// src/utils/child-env.ts
|
|
15
14
|
var ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -85,8 +84,9 @@ function sanitizeNodeOptions(value) {
|
|
|
85
84
|
}
|
|
86
85
|
return kept.join(" ");
|
|
87
86
|
}
|
|
87
|
+
var gitIdentity = null;
|
|
88
88
|
function buildChildEnv(optsOrSessionId) {
|
|
89
|
-
const opts = {};
|
|
89
|
+
const opts = typeof optsOrSessionId === "string" ? { sessionId: optsOrSessionId } : optsOrSessionId ?? {};
|
|
90
90
|
const hasOwn = Object.hasOwn(process.env, "WRONGSTACK_CHILD_ENV_PASSTHROUGH");
|
|
91
91
|
const legacyHasOwn = Object.hasOwn(process.env, "WRONGSTACK_BASH_ENV_PASSTHROUGH");
|
|
92
92
|
const passthrough = hasOwn && process.env["WRONGSTACK_CHILD_ENV_PASSTHROUGH"] === "1" || legacyHasOwn && process.env["WRONGSTACK_BASH_ENV_PASSTHROUGH"] === "1";
|
|
@@ -124,6 +124,16 @@ function buildChildEnv(optsOrSessionId) {
|
|
|
124
124
|
out[k] = v;
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
+
if (gitIdentity) {
|
|
128
|
+
if (gitIdentity.name) {
|
|
129
|
+
out["GIT_AUTHOR_NAME"] = gitIdentity.name;
|
|
130
|
+
out["GIT_COMMITTER_NAME"] = gitIdentity.name;
|
|
131
|
+
}
|
|
132
|
+
if (gitIdentity.email) {
|
|
133
|
+
out["GIT_AUTHOR_EMAIL"] = gitIdentity.email;
|
|
134
|
+
out["GIT_COMMITTER_EMAIL"] = gitIdentity.email;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
127
137
|
if (opts.extra) {
|
|
128
138
|
Object.assign(out, opts.extra);
|
|
129
139
|
}
|
|
@@ -236,7 +246,7 @@ function toErrorMessage(err) {
|
|
|
236
246
|
// src/utils/expect-defined.ts
|
|
237
247
|
function expectDefined(value, label) {
|
|
238
248
|
if (value === null || value === void 0) {
|
|
239
|
-
const err = new Error("Expected value to be defined");
|
|
249
|
+
const err = new Error(label ? `Expected ${label} to be defined` : "Expected value to be defined");
|
|
240
250
|
err.name = "ExpectDefinedError";
|
|
241
251
|
throw err;
|
|
242
252
|
}
|
|
@@ -385,13 +395,16 @@ function safeParse(input, maxBytes = 5e6) {
|
|
|
385
395
|
};
|
|
386
396
|
}
|
|
387
397
|
}
|
|
398
|
+
|
|
399
|
+
// src/utils/session-scoped-path.ts
|
|
400
|
+
import * as path from "node:path";
|
|
388
401
|
function sessionScopedPath(dir, sessionId, suffix) {
|
|
389
402
|
if (!sessionId || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
390
403
|
throw invalid(sessionId);
|
|
391
404
|
}
|
|
392
|
-
const resolved =
|
|
393
|
-
const rel =
|
|
394
|
-
if (rel.startsWith("..") ||
|
|
405
|
+
const resolved = path.resolve(dir, `${sessionId}${suffix}`);
|
|
406
|
+
const rel = path.relative(path.resolve(dir), resolved);
|
|
407
|
+
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
395
408
|
throw invalid(sessionId);
|
|
396
409
|
}
|
|
397
410
|
return resolved;
|
|
@@ -409,6 +422,9 @@ function invalid(sessionId) {
|
|
|
409
422
|
function slugify(name, fallback = "prompt", maxLen = 64) {
|
|
410
423
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, maxLen).replace(/-+$/g, "") || fallback;
|
|
411
424
|
}
|
|
425
|
+
|
|
426
|
+
// src/utils/ulid.ts
|
|
427
|
+
import { randomBytes } from "node:crypto";
|
|
412
428
|
var ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
413
429
|
var ENCODING_LEN = ENCODING.length;
|
|
414
430
|
var TIME_LEN = 10;
|
|
@@ -434,6 +450,11 @@ function encodeRandom(len) {
|
|
|
434
450
|
function ulid(seedTime = Date.now()) {
|
|
435
451
|
return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN);
|
|
436
452
|
}
|
|
453
|
+
|
|
454
|
+
// src/utils/wstack-paths.ts
|
|
455
|
+
import { createHash } from "node:crypto";
|
|
456
|
+
import * as os from "node:os";
|
|
457
|
+
import * as path2 from "node:path";
|
|
437
458
|
function projectHash(absRoot) {
|
|
438
459
|
return createHash("sha256").update(path2.resolve(absRoot)).digest("hex").slice(0, 12);
|
|
439
460
|
}
|
|
@@ -507,18 +528,59 @@ function resolveWstackPaths(opts) {
|
|
|
507
528
|
|
|
508
529
|
// src/types/errors.ts
|
|
509
530
|
var ERROR_CODES = {
|
|
531
|
+
// Provider
|
|
532
|
+
PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
|
|
533
|
+
PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
|
|
534
|
+
PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
|
|
535
|
+
PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
|
|
536
|
+
PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
|
|
537
|
+
PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR",
|
|
538
|
+
PROVIDER_CONTEXT_OVERFLOW: "PROVIDER_CONTEXT_OVERFLOW",
|
|
539
|
+
// Tool
|
|
540
|
+
TOOL_NOT_FOUND: "TOOL_NOT_FOUND",
|
|
541
|
+
TOOL_PERMISSION_DENIED: "TOOL_PERMISSION_DENIED",
|
|
542
|
+
TOOL_EXECUTION_FAILED: "TOOL_EXECUTION_FAILED",
|
|
543
|
+
TOOL_TIMEOUT: "TOOL_TIMEOUT",
|
|
544
|
+
TOOL_INPUT_INVALID: "TOOL_INPUT_INVALID",
|
|
510
545
|
// Config
|
|
511
546
|
CONFIG_INVALID: "CONFIG_INVALID",
|
|
547
|
+
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
548
|
+
CONFIG_PARSE_FAILED: "CONFIG_PARSE_FAILED",
|
|
549
|
+
CONFIG_MIGRATION_NEEDED: "CONFIG_MIGRATION_NEEDED",
|
|
550
|
+
// Plugin
|
|
551
|
+
PLUGIN_LOAD_FAILED: "PLUGIN_LOAD_FAILED",
|
|
552
|
+
PLUGIN_API_MISMATCH: "PLUGIN_API_MISMATCH",
|
|
553
|
+
PLUGIN_MISSING_DEPENDENCY: "PLUGIN_MISSING_DEPENDENCY",
|
|
554
|
+
// Agent
|
|
555
|
+
AGENT_ITERATION_LIMIT: "AGENT_ITERATION_LIMIT",
|
|
556
|
+
AGENT_CONTEXT_OVERFLOW: "AGENT_CONTEXT_OVERFLOW",
|
|
557
|
+
AGENT_ABORTED: "AGENT_ABORTED",
|
|
558
|
+
AGENT_RUN_FAILED: "AGENT_RUN_FAILED",
|
|
512
559
|
// Session
|
|
513
560
|
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
514
561
|
SESSION_CORRUPTED: "SESSION_CORRUPTED",
|
|
515
562
|
SESSION_WRITE_FAILED: "SESSION_WRITE_FAILED",
|
|
563
|
+
// Container / Registry
|
|
564
|
+
CONTAINER_TOKEN_ALREADY_BOUND: "CONTAINER_TOKEN_ALREADY_BOUND",
|
|
565
|
+
CONTAINER_TOKEN_NOT_BOUND: "CONTAINER_TOKEN_NOT_BOUND",
|
|
566
|
+
CONTAINER_CIRCULAR_DEPENDENCY: "CONTAINER_CIRCULAR_DEPENDENCY",
|
|
567
|
+
REGISTRY_DUPLICATE: "REGISTRY_DUPLICATE",
|
|
568
|
+
REGISTRY_NOT_FOUND: "REGISTRY_NOT_FOUND",
|
|
569
|
+
REGISTRY_INVALID: "REGISTRY_INVALID",
|
|
516
570
|
// File system
|
|
517
571
|
FS_READ_FAILED: "FS_READ_FAILED",
|
|
572
|
+
FS_WRITE_FAILED: "FS_WRITE_FAILED",
|
|
573
|
+
FS_MKDIR_FAILED: "FS_MKDIR_FAILED",
|
|
518
574
|
FS_DELETE_FAILED: "FS_DELETE_FAILED",
|
|
519
575
|
FS_ATOMIC_WRITE_FAILED: "FS_ATOMIC_WRITE_FAILED",
|
|
576
|
+
// SDD (Spec-Driven Development)
|
|
577
|
+
SDD_VALIDATION_FAILED: "SDD_VALIDATION_FAILED",
|
|
578
|
+
SDD_PARSE_FAILED: "SDD_PARSE_FAILED",
|
|
579
|
+
SDD_INVALID_STATE: "SDD_INVALID_STATE",
|
|
580
|
+
SDD_NOT_READY: "SDD_NOT_READY",
|
|
520
581
|
// General
|
|
521
582
|
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
583
|
+
PARSE_FAILED: "PARSE_FAILED",
|
|
522
584
|
UNKNOWN: "UNKNOWN"
|
|
523
585
|
};
|
|
524
586
|
var WrongStackError = class extends Error {
|
|
@@ -598,17 +660,17 @@ var FsError = class extends WrongStackError {
|
|
|
598
660
|
|
|
599
661
|
// src/utils/atomic-write.ts
|
|
600
662
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
601
|
-
const dir =
|
|
602
|
-
await
|
|
603
|
-
const tmp =
|
|
663
|
+
const dir = path3.dirname(targetPath);
|
|
664
|
+
await fs.mkdir(dir, { recursive: true });
|
|
665
|
+
const tmp = path3.join(dir, `.${path3.basename(targetPath)}.${randomBytes2(6).toString("hex")}.tmp`);
|
|
604
666
|
try {
|
|
605
667
|
if (typeof content === "string") {
|
|
606
|
-
await
|
|
668
|
+
await fs.writeFile(tmp, content, { flag: "wx", encoding: opts.encoding ?? "utf8" });
|
|
607
669
|
} else {
|
|
608
|
-
await
|
|
670
|
+
await fs.writeFile(tmp, content, { flag: "wx" });
|
|
609
671
|
}
|
|
610
672
|
try {
|
|
611
|
-
const fh = await
|
|
673
|
+
const fh = await fs.open(tmp, "r+");
|
|
612
674
|
try {
|
|
613
675
|
await fh.sync();
|
|
614
676
|
} finally {
|
|
@@ -618,56 +680,56 @@ async function atomicWrite(targetPath, content, opts = {}) {
|
|
|
618
680
|
}
|
|
619
681
|
let mode;
|
|
620
682
|
try {
|
|
621
|
-
const stat13 = await
|
|
683
|
+
const stat13 = await fs.stat(targetPath);
|
|
622
684
|
mode = stat13.mode & 511;
|
|
623
685
|
} catch {
|
|
624
686
|
mode = opts.mode;
|
|
625
687
|
}
|
|
626
688
|
if (mode !== void 0) {
|
|
627
|
-
await
|
|
689
|
+
await fs.chmod(tmp, mode);
|
|
628
690
|
}
|
|
629
691
|
await renameWithRetry(tmp, targetPath);
|
|
630
692
|
if (mode !== void 0 && process.platform === "win32") {
|
|
631
693
|
try {
|
|
632
|
-
await
|
|
694
|
+
await fs.chmod(targetPath, mode);
|
|
633
695
|
} catch {
|
|
634
696
|
}
|
|
635
697
|
}
|
|
636
698
|
} catch (err) {
|
|
637
699
|
try {
|
|
638
|
-
await
|
|
700
|
+
await fs.unlink(tmp);
|
|
639
701
|
} catch {
|
|
640
702
|
}
|
|
641
703
|
throw err;
|
|
642
704
|
}
|
|
643
705
|
}
|
|
644
706
|
async function ensureDir(dir) {
|
|
645
|
-
await
|
|
707
|
+
await fs.mkdir(dir, { recursive: true });
|
|
646
708
|
}
|
|
647
709
|
async function withFileLock(targetPath, fn, opts = {}) {
|
|
648
|
-
const dir =
|
|
649
|
-
await
|
|
650
|
-
const lockPath =
|
|
710
|
+
const dir = path3.dirname(targetPath);
|
|
711
|
+
await fs.mkdir(dir, { recursive: true });
|
|
712
|
+
const lockPath = path3.join(dir, `.${path3.basename(targetPath)}.lock`);
|
|
651
713
|
const timeoutMs = opts.timeoutMs ?? 5e3;
|
|
652
714
|
const staleMs = opts.staleMs ?? 3e4;
|
|
653
715
|
const started = Date.now();
|
|
654
716
|
let handle;
|
|
655
717
|
for (; ; ) {
|
|
656
718
|
try {
|
|
657
|
-
handle = await
|
|
719
|
+
handle = await fs.open(lockPath, "wx");
|
|
658
720
|
await handle.writeFile(`${process.pid}:${Date.now()}`);
|
|
659
721
|
break;
|
|
660
722
|
} catch (err) {
|
|
661
723
|
const code = err.code;
|
|
662
724
|
if (code === "ENOENT") {
|
|
663
|
-
await
|
|
725
|
+
await fs.mkdir(dir, { recursive: true });
|
|
664
726
|
continue;
|
|
665
727
|
}
|
|
666
728
|
if (code !== "EEXIST") throw err;
|
|
667
729
|
try {
|
|
668
|
-
const stat13 = await
|
|
730
|
+
const stat13 = await fs.stat(lockPath);
|
|
669
731
|
if (Date.now() - stat13.mtimeMs > staleMs) {
|
|
670
|
-
await
|
|
732
|
+
await fs.unlink(lockPath);
|
|
671
733
|
continue;
|
|
672
734
|
}
|
|
673
735
|
} catch {
|
|
@@ -692,7 +754,7 @@ async function withFileLock(targetPath, fn, opts = {}) {
|
|
|
692
754
|
} catch {
|
|
693
755
|
}
|
|
694
756
|
try {
|
|
695
|
-
await
|
|
757
|
+
await fs.unlink(lockPath);
|
|
696
758
|
} catch {
|
|
697
759
|
}
|
|
698
760
|
}
|
|
@@ -700,14 +762,14 @@ async function withFileLock(targetPath, fn, opts = {}) {
|
|
|
700
762
|
var TRANSIENT_RENAME_CODES = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES", "ENOTEMPTY"]);
|
|
701
763
|
async function renameWithRetry(from, to) {
|
|
702
764
|
if (process.platform !== "win32") {
|
|
703
|
-
await
|
|
765
|
+
await fs.rename(from, to);
|
|
704
766
|
return;
|
|
705
767
|
}
|
|
706
768
|
const delays = [10, 25, 60, 120, 250];
|
|
707
769
|
let lastErr;
|
|
708
770
|
for (let i = 0; i <= delays.length; i++) {
|
|
709
771
|
try {
|
|
710
|
-
await
|
|
772
|
+
await fs.rename(from, to);
|
|
711
773
|
return;
|
|
712
774
|
} catch (err) {
|
|
713
775
|
lastErr = err;
|
|
@@ -721,6 +783,11 @@ async function renameWithRetry(from, to) {
|
|
|
721
783
|
throw lastErr;
|
|
722
784
|
}
|
|
723
785
|
|
|
786
|
+
// src/storage/file-session-writer.ts
|
|
787
|
+
import { closeSync, fsyncSync, openSync, writeSync } from "node:fs";
|
|
788
|
+
import * as fsp from "node:fs/promises";
|
|
789
|
+
import * as path4 from "node:path";
|
|
790
|
+
|
|
724
791
|
// src/storage/session-helpers.ts
|
|
725
792
|
function userInputTitle(content) {
|
|
726
793
|
const text = typeof content === "string" ? content : content.filter((b) => b.type === "text").map((b) => b.text).join(" ");
|
|
@@ -736,7 +803,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
736
803
|
this.meta = meta;
|
|
737
804
|
this.events = events;
|
|
738
805
|
this.resumed = opts.resumed ?? false;
|
|
739
|
-
this.manifestFile = opts.dir ?
|
|
806
|
+
this.manifestFile = opts.dir ? path4.join(opts.dir, `${path4.basename(id)}.summary.json`) : "";
|
|
740
807
|
this.filePath = opts.filePath ?? "";
|
|
741
808
|
this.secretScrubber = opts.secretScrubber;
|
|
742
809
|
this.checkpointCas = opts.checkpointCas;
|
|
@@ -1276,7 +1343,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
1276
1343
|
let removedCount = 0;
|
|
1277
1344
|
let targetCheckpointSeen = false;
|
|
1278
1345
|
try {
|
|
1279
|
-
fd = await
|
|
1346
|
+
fd = await fsp.open(this.filePath, "r", 384);
|
|
1280
1347
|
while (true) {
|
|
1281
1348
|
const buf = Buffer.alloc(CHUNK_SIZE);
|
|
1282
1349
|
const { bytesRead } = await fd.read(buf, 0, CHUNK_SIZE, fileOffset);
|
|
@@ -1331,7 +1398,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
1331
1398
|
await this.writeChain;
|
|
1332
1399
|
await this.handle.close();
|
|
1333
1400
|
const tmpPath = `${this.filePath}.rewind.tmp`;
|
|
1334
|
-
const src = await
|
|
1401
|
+
const src = await fsp.open(this.filePath, "r", 384);
|
|
1335
1402
|
try {
|
|
1336
1403
|
const statResult = await src.stat();
|
|
1337
1404
|
const totalSize = statResult.size;
|
|
@@ -1347,7 +1414,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
1347
1414
|
} else {
|
|
1348
1415
|
newlineAfterCheckpoint = totalSize;
|
|
1349
1416
|
}
|
|
1350
|
-
const writeFd = await
|
|
1417
|
+
const writeFd = await fsp.open(tmpPath, "w", 384);
|
|
1351
1418
|
try {
|
|
1352
1419
|
let readOffset = 0;
|
|
1353
1420
|
while (readOffset < newlineAfterCheckpoint) {
|
|
@@ -1395,11 +1462,11 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
1395
1462
|
await writeFd.close();
|
|
1396
1463
|
}
|
|
1397
1464
|
await src.close();
|
|
1398
|
-
await
|
|
1399
|
-
this.handle = await
|
|
1465
|
+
await fsp.rename(tmpPath, this.filePath);
|
|
1466
|
+
this.handle = await fsp.open(this.filePath, "a", 384);
|
|
1400
1467
|
} catch (err) {
|
|
1401
|
-
await
|
|
1402
|
-
this.handle = await
|
|
1468
|
+
await fsp.unlink(tmpPath).catch(() => void 0);
|
|
1469
|
+
this.handle = await fsp.open(this.filePath, "a", 384).catch(() => this.handle);
|
|
1403
1470
|
throw err;
|
|
1404
1471
|
}
|
|
1405
1472
|
await this.append({
|
|
@@ -1434,7 +1501,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
1434
1501
|
provider: this.meta.provider ?? "unknown"
|
|
1435
1502
|
})}
|
|
1436
1503
|
`;
|
|
1437
|
-
await
|
|
1504
|
+
await fsp.writeFile(this.filePath, record, "utf8");
|
|
1438
1505
|
this.activePromptIndex = null;
|
|
1439
1506
|
this.pendingFileSnapshots = [];
|
|
1440
1507
|
}
|
|
@@ -1479,6 +1546,12 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
1479
1546
|
}
|
|
1480
1547
|
};
|
|
1481
1548
|
|
|
1549
|
+
// src/storage/session-checkpoint-cas.ts
|
|
1550
|
+
import { spawn } from "node:child_process";
|
|
1551
|
+
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
1552
|
+
import * as fsp2 from "node:fs/promises";
|
|
1553
|
+
import * as path5 from "node:path";
|
|
1554
|
+
|
|
1482
1555
|
// src/storage/storage-concurrency.ts
|
|
1483
1556
|
async function mapWithConcurrency(items, concurrency, mapper) {
|
|
1484
1557
|
if (items.length === 0) return [];
|
|
@@ -1505,16 +1578,16 @@ var MAX_GIT_OUTPUT = 16 * 1024 * 1024;
|
|
|
1505
1578
|
var MAX_BLOB_BYTES = 64 * 1024 * 1024;
|
|
1506
1579
|
var MAX_CHECKPOINT_BYTES = 512 * 1024 * 1024;
|
|
1507
1580
|
function sha256(content) {
|
|
1508
|
-
return
|
|
1581
|
+
return createHash2("sha256").update(content).digest("hex");
|
|
1509
1582
|
}
|
|
1510
1583
|
function isInside(root, target) {
|
|
1511
|
-
const relative6 =
|
|
1512
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
1584
|
+
const relative6 = path5.relative(root, target);
|
|
1585
|
+
return relative6 === "" || !relative6.startsWith("..") && !path5.isAbsolute(relative6);
|
|
1513
1586
|
}
|
|
1514
1587
|
function normalizeRelative(input) {
|
|
1515
|
-
if (!input ||
|
|
1588
|
+
if (!input || path5.isAbsolute(input)) return null;
|
|
1516
1589
|
const normalized = input.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
1517
|
-
const resolved =
|
|
1590
|
+
const resolved = path5.posix.normalize(normalized);
|
|
1518
1591
|
if (!resolved || resolved === "." || resolved === ".." || resolved.startsWith("../")) return null;
|
|
1519
1592
|
return resolved;
|
|
1520
1593
|
}
|
|
@@ -1529,8 +1602,8 @@ var SessionCheckpointCas = class {
|
|
|
1529
1602
|
projectRoot;
|
|
1530
1603
|
runGit;
|
|
1531
1604
|
constructor(opts) {
|
|
1532
|
-
this.rootDir =
|
|
1533
|
-
this.projectRoot =
|
|
1605
|
+
this.rootDir = path5.resolve(opts.rootDir);
|
|
1606
|
+
this.projectRoot = path5.resolve(opts.projectRoot);
|
|
1534
1607
|
this.runGit = opts.runGit ?? defaultRunGit;
|
|
1535
1608
|
}
|
|
1536
1609
|
async capture(_sessionId, _promptIndex) {
|
|
@@ -1555,17 +1628,17 @@ var SessionCheckpointCas = class {
|
|
|
1555
1628
|
relativePaths,
|
|
1556
1629
|
CAPTURE_CONCURRENCY,
|
|
1557
1630
|
async (relative6) => {
|
|
1558
|
-
const absolute =
|
|
1631
|
+
const absolute = path5.resolve(this.projectRoot, ...relative6.split("/"));
|
|
1559
1632
|
if (!isInside(this.projectRoot, absolute)) {
|
|
1560
1633
|
unresolved.push({ path: relative6, reason: "path escapes project root" });
|
|
1561
1634
|
return null;
|
|
1562
1635
|
}
|
|
1563
1636
|
try {
|
|
1564
|
-
const stat13 = await
|
|
1637
|
+
const stat13 = await fsp2.lstat(absolute);
|
|
1565
1638
|
if (stat13.isSymbolicLink()) {
|
|
1566
|
-
const linkTarget = await
|
|
1567
|
-
const resolvedLink =
|
|
1568
|
-
if (
|
|
1639
|
+
const linkTarget = await fsp2.readlink(absolute);
|
|
1640
|
+
const resolvedLink = path5.resolve(path5.dirname(absolute), linkTarget);
|
|
1641
|
+
if (path5.isAbsolute(linkTarget) || !isInside(this.projectRoot, resolvedLink)) {
|
|
1569
1642
|
unresolved.push({
|
|
1570
1643
|
path: relative6,
|
|
1571
1644
|
reason: "symlink target escapes project root"
|
|
@@ -1593,7 +1666,7 @@ var SessionCheckpointCas = class {
|
|
|
1593
1666
|
return null;
|
|
1594
1667
|
}
|
|
1595
1668
|
scheduledBytes += stat13.size;
|
|
1596
|
-
const content = await
|
|
1669
|
+
const content = await fsp2.readFile(absolute);
|
|
1597
1670
|
const blobHash = sha256(content);
|
|
1598
1671
|
await this.putBlob(blobHash, content);
|
|
1599
1672
|
return { path: relative6, state: "file", blobHash, mode: stat13.mode & 511 };
|
|
@@ -1627,11 +1700,11 @@ var SessionCheckpointCas = class {
|
|
|
1627
1700
|
};
|
|
1628
1701
|
}
|
|
1629
1702
|
async materialize(checkpoint, targetRoot) {
|
|
1630
|
-
const target =
|
|
1703
|
+
const target = path5.resolve(targetRoot);
|
|
1631
1704
|
if (target === this.projectRoot) {
|
|
1632
1705
|
throw new Error("Refusing to materialize a workspace checkpoint over the parent project root");
|
|
1633
1706
|
}
|
|
1634
|
-
const targetStat = await
|
|
1707
|
+
const targetStat = await fsp2.stat(target);
|
|
1635
1708
|
if (!targetStat.isDirectory()) throw new Error(`Checkpoint target is not a directory: ${target}`);
|
|
1636
1709
|
const manifest = await this.loadManifest(checkpoint.manifestHash);
|
|
1637
1710
|
if (manifest.baseHead !== checkpoint.baseHead.toLowerCase() || manifest.coverage !== checkpoint.coverage || manifest.entries.length !== checkpoint.entryCount || manifest.unresolved.length !== checkpoint.unresolvedCount) {
|
|
@@ -1658,7 +1731,7 @@ var SessionCheckpointCas = class {
|
|
|
1658
1731
|
if (targetStatus.stdout.length > 0) {
|
|
1659
1732
|
throw new Error("Checkpoint target must be a clean checkout before materialization");
|
|
1660
1733
|
}
|
|
1661
|
-
const realTarget = await
|
|
1734
|
+
const realTarget = await fsp2.realpath(target);
|
|
1662
1735
|
const writtenFiles = [];
|
|
1663
1736
|
const deletedFiles = [];
|
|
1664
1737
|
const errors = [];
|
|
@@ -1667,10 +1740,10 @@ var SessionCheckpointCas = class {
|
|
|
1667
1740
|
try {
|
|
1668
1741
|
const output = await this.safeOutputPath(target, realTarget, entry.path);
|
|
1669
1742
|
if (entry.state === "symlink") {
|
|
1670
|
-
if (
|
|
1743
|
+
if (path5.isAbsolute(entry.linkTarget)) {
|
|
1671
1744
|
throw new Error("absolute symlink target refused");
|
|
1672
1745
|
}
|
|
1673
|
-
const resolvedLink =
|
|
1746
|
+
const resolvedLink = path5.resolve(path5.dirname(output), entry.linkTarget);
|
|
1674
1747
|
if (!isInside(target, resolvedLink)) throw new Error("symlink target escapes checkpoint root");
|
|
1675
1748
|
}
|
|
1676
1749
|
prepared.push({
|
|
@@ -1688,24 +1761,24 @@ var SessionCheckpointCas = class {
|
|
|
1688
1761
|
for (const { entry, output, content } of prepared) {
|
|
1689
1762
|
try {
|
|
1690
1763
|
if (entry.state === "absent") {
|
|
1691
|
-
await
|
|
1764
|
+
await fsp2.unlink(output).catch((err) => {
|
|
1692
1765
|
if (err.code !== "ENOENT") throw err;
|
|
1693
1766
|
});
|
|
1694
1767
|
deletedFiles.push(entry.path);
|
|
1695
1768
|
continue;
|
|
1696
1769
|
}
|
|
1697
1770
|
if (entry.state === "symlink") {
|
|
1698
|
-
await
|
|
1771
|
+
await fsp2.unlink(output).catch((err) => {
|
|
1699
1772
|
if (err.code !== "ENOENT") throw err;
|
|
1700
1773
|
});
|
|
1701
|
-
await
|
|
1702
|
-
await
|
|
1774
|
+
await fsp2.mkdir(path5.dirname(output), { recursive: true });
|
|
1775
|
+
await fsp2.symlink(entry.linkTarget, output);
|
|
1703
1776
|
writtenFiles.push(entry.path);
|
|
1704
1777
|
continue;
|
|
1705
1778
|
}
|
|
1706
1779
|
if (!content) throw new Error("CAS blob was not prepared");
|
|
1707
1780
|
await atomicWrite(output, content, { mode: entry.mode });
|
|
1708
|
-
await
|
|
1781
|
+
await fsp2.chmod(output, entry.mode).catch(() => void 0);
|
|
1709
1782
|
writtenFiles.push(entry.path);
|
|
1710
1783
|
} catch (err) {
|
|
1711
1784
|
errors.push(`${entry.path}: ${toErrorMessage(err)}`);
|
|
@@ -1715,48 +1788,48 @@ var SessionCheckpointCas = class {
|
|
|
1715
1788
|
}
|
|
1716
1789
|
objectPath(hash) {
|
|
1717
1790
|
if (!HASH_RE.test(hash)) throw new Error(`Invalid CAS object hash: ${hash}`);
|
|
1718
|
-
return
|
|
1791
|
+
return path5.join(this.rootDir, "objects", hash.slice(0, 2), hash.slice(2));
|
|
1719
1792
|
}
|
|
1720
1793
|
manifestPath(hash) {
|
|
1721
1794
|
if (!HASH_RE.test(hash)) throw new Error(`Invalid checkpoint manifest hash: ${hash}`);
|
|
1722
|
-
return
|
|
1795
|
+
return path5.join(this.rootDir, "manifests", `${hash}.json`);
|
|
1723
1796
|
}
|
|
1724
1797
|
async putBlob(hash, content) {
|
|
1725
1798
|
const target = this.objectPath(hash);
|
|
1726
|
-
await
|
|
1799
|
+
await fsp2.mkdir(path5.dirname(target), { recursive: true });
|
|
1727
1800
|
try {
|
|
1728
|
-
const existing = await
|
|
1801
|
+
const existing = await fsp2.readFile(target);
|
|
1729
1802
|
if (sha256(existing) !== hash) throw new Error(`Corrupt CAS object collision: ${hash}`);
|
|
1730
1803
|
return;
|
|
1731
1804
|
} catch (err) {
|
|
1732
1805
|
if (err.code !== "ENOENT") throw err;
|
|
1733
1806
|
}
|
|
1734
|
-
const temp =
|
|
1735
|
-
|
|
1736
|
-
`.${
|
|
1807
|
+
const temp = path5.join(
|
|
1808
|
+
path5.dirname(target),
|
|
1809
|
+
`.${path5.basename(target)}.${process.pid}.${randomUUID()}.tmp`
|
|
1737
1810
|
);
|
|
1738
1811
|
let handle;
|
|
1739
1812
|
try {
|
|
1740
|
-
handle = await
|
|
1813
|
+
handle = await fsp2.open(temp, "wx", 384);
|
|
1741
1814
|
await handle.writeFile(content);
|
|
1742
1815
|
await handle.sync();
|
|
1743
1816
|
await handle.close();
|
|
1744
1817
|
handle = void 0;
|
|
1745
1818
|
try {
|
|
1746
|
-
await
|
|
1819
|
+
await fsp2.link(temp, target);
|
|
1747
1820
|
} catch (err) {
|
|
1748
1821
|
if (err.code !== "EEXIST") throw err;
|
|
1749
|
-
const existing = await
|
|
1822
|
+
const existing = await fsp2.readFile(target);
|
|
1750
1823
|
if (sha256(existing) !== hash) throw new Error(`Corrupt CAS object collision: ${hash}`);
|
|
1751
1824
|
}
|
|
1752
1825
|
} finally {
|
|
1753
1826
|
await handle?.close().catch(() => void 0);
|
|
1754
|
-
await
|
|
1827
|
+
await fsp2.unlink(temp).catch(() => void 0);
|
|
1755
1828
|
}
|
|
1756
1829
|
}
|
|
1757
1830
|
async putManifest(hash, encoded) {
|
|
1758
1831
|
const target = this.manifestPath(hash);
|
|
1759
|
-
const existing = await
|
|
1832
|
+
const existing = await fsp2.readFile(target).catch(() => null);
|
|
1760
1833
|
if (existing) {
|
|
1761
1834
|
if (sha256(existing) !== hash) throw new Error(`Corrupt checkpoint manifest collision: ${hash}`);
|
|
1762
1835
|
return;
|
|
@@ -1764,12 +1837,12 @@ var SessionCheckpointCas = class {
|
|
|
1764
1837
|
await atomicWrite(target, encoded, { mode: 384 });
|
|
1765
1838
|
}
|
|
1766
1839
|
async readBlob(hash) {
|
|
1767
|
-
const content = await
|
|
1840
|
+
const content = await fsp2.readFile(this.objectPath(hash));
|
|
1768
1841
|
if (sha256(content) !== hash) throw new Error(`CAS blob integrity check failed: ${hash}`);
|
|
1769
1842
|
return content;
|
|
1770
1843
|
}
|
|
1771
1844
|
async loadManifest(hash) {
|
|
1772
|
-
const raw = await
|
|
1845
|
+
const raw = await fsp2.readFile(this.manifestPath(hash));
|
|
1773
1846
|
if (sha256(raw) !== hash) throw new Error(`Checkpoint manifest integrity check failed: ${hash}`);
|
|
1774
1847
|
const parsed = JSON.parse(raw.toString("utf8"));
|
|
1775
1848
|
if (parsed.version !== 1 || typeof parsed.baseHead !== "string" || parsed.coverage !== "git-head-plus-dirty" || !Array.isArray(parsed.entries) || !Array.isArray(parsed.unresolved)) {
|
|
@@ -1794,17 +1867,17 @@ var SessionCheckpointCas = class {
|
|
|
1794
1867
|
async safeOutputPath(target, realTarget, relative6) {
|
|
1795
1868
|
const normalized = normalizeRelative(relative6);
|
|
1796
1869
|
if (!normalized) throw new Error("invalid relative path");
|
|
1797
|
-
const output =
|
|
1870
|
+
const output = path5.resolve(target, ...normalized.split("/"));
|
|
1798
1871
|
if (!isInside(target, output)) throw new Error("path escapes checkpoint target");
|
|
1799
1872
|
let probe = output;
|
|
1800
1873
|
for (; ; ) {
|
|
1801
1874
|
try {
|
|
1802
|
-
const real = await
|
|
1875
|
+
const real = await fsp2.realpath(probe);
|
|
1803
1876
|
if (!isInside(realTarget, real)) throw new Error("path resolves through a symlink outside checkpoint target");
|
|
1804
1877
|
return output;
|
|
1805
1878
|
} catch (err) {
|
|
1806
1879
|
if (err.code !== "ENOENT") throw err;
|
|
1807
|
-
const parent =
|
|
1880
|
+
const parent = path5.dirname(probe);
|
|
1808
1881
|
if (parent === probe) throw err;
|
|
1809
1882
|
probe = parent;
|
|
1810
1883
|
}
|
|
@@ -1859,12 +1932,17 @@ function defaultRunGit(args, cwd) {
|
|
|
1859
1932
|
child.on("close", (code) => resolve11(result(code ?? 1)));
|
|
1860
1933
|
});
|
|
1861
1934
|
}
|
|
1935
|
+
|
|
1936
|
+
// src/storage/session-resume-validation.ts
|
|
1937
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
1938
|
+
import * as fsp3 from "node:fs/promises";
|
|
1939
|
+
import * as path6 from "node:path";
|
|
1862
1940
|
var MAX_REVALIDATE_BYTES = 5 * 1024 * 1024;
|
|
1863
1941
|
var VALIDATION_CONCURRENCY = 8;
|
|
1864
1942
|
var NOTICE_PATH_LIMIT = 20;
|
|
1865
1943
|
function isInside2(root, target) {
|
|
1866
|
-
const relative6 =
|
|
1867
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
1944
|
+
const relative6 = path6.relative(root, target);
|
|
1945
|
+
return relative6 === "" || !relative6.startsWith("..") && !path6.isAbsolute(relative6);
|
|
1868
1946
|
}
|
|
1869
1947
|
function errno(err) {
|
|
1870
1948
|
return err && typeof err === "object" && "code" in err ? String(err.code) : void 0;
|
|
@@ -1875,7 +1953,7 @@ function latestObservations(events, projectRoot) {
|
|
|
1875
1953
|
if (event.type !== "file_observation" || typeof event.path !== "string" || event.path.length === 0 || typeof event.hash !== "string" || !/^[a-f\d]{64}$/i.test(event.hash)) {
|
|
1876
1954
|
continue;
|
|
1877
1955
|
}
|
|
1878
|
-
const normalized =
|
|
1956
|
+
const normalized = path6.resolve(projectRoot, event.path);
|
|
1879
1957
|
latest.set(normalized, {
|
|
1880
1958
|
path: normalized,
|
|
1881
1959
|
hash: event.hash.toLowerCase(),
|
|
@@ -1899,7 +1977,7 @@ async function validateOne(observation, lexicalRoot, realRoot) {
|
|
|
1899
1977
|
}
|
|
1900
1978
|
let realFile;
|
|
1901
1979
|
try {
|
|
1902
|
-
realFile = await
|
|
1980
|
+
realFile = await fsp3.realpath(observation.path);
|
|
1903
1981
|
} catch (err) {
|
|
1904
1982
|
if (errno(err) === "ENOENT") return { ...base, status: "deleted" };
|
|
1905
1983
|
return { ...base, status: "unreadable", detail: toErrorMessage(err) };
|
|
@@ -1912,7 +1990,7 @@ async function validateOne(observation, lexicalRoot, realRoot) {
|
|
|
1912
1990
|
};
|
|
1913
1991
|
}
|
|
1914
1992
|
try {
|
|
1915
|
-
const stat13 = await
|
|
1993
|
+
const stat13 = await fsp3.stat(realFile);
|
|
1916
1994
|
if (!stat13.isFile()) {
|
|
1917
1995
|
return { ...base, status: "unreadable", detail: "Path is no longer a regular file." };
|
|
1918
1996
|
}
|
|
@@ -1923,8 +2001,8 @@ async function validateOne(observation, lexicalRoot, realRoot) {
|
|
|
1923
2001
|
detail: `File now exceeds the ${MAX_REVALIDATE_BYTES}-byte validation limit.`
|
|
1924
2002
|
};
|
|
1925
2003
|
}
|
|
1926
|
-
const content = await
|
|
1927
|
-
const actualHash =
|
|
2004
|
+
const content = await fsp3.readFile(realFile, "utf8");
|
|
2005
|
+
const actualHash = createHash3("sha256").update(content, "utf8").digest("hex");
|
|
1928
2006
|
if (actualHash === observation.hash) return null;
|
|
1929
2007
|
return { ...base, status: "modified", actualHash };
|
|
1930
2008
|
} catch (err) {
|
|
@@ -1933,8 +2011,8 @@ async function validateOne(observation, lexicalRoot, realRoot) {
|
|
|
1933
2011
|
}
|
|
1934
2012
|
}
|
|
1935
2013
|
async function validateResumeFileObservations(events, projectRoot) {
|
|
1936
|
-
const lexicalRoot =
|
|
1937
|
-
const realRoot = await
|
|
2014
|
+
const lexicalRoot = path6.resolve(projectRoot);
|
|
2015
|
+
const realRoot = await fsp3.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
1938
2016
|
const observations = latestObservations(events, lexicalRoot);
|
|
1939
2017
|
const results = await mapWithConcurrency(
|
|
1940
2018
|
observations,
|
|
@@ -1949,9 +2027,9 @@ async function validateResumeFileObservations(events, projectRoot) {
|
|
|
1949
2027
|
}
|
|
1950
2028
|
function formatResumeValidationNotice(validation, projectRoot) {
|
|
1951
2029
|
if (validation.staleFiles.length === 0) return null;
|
|
1952
|
-
const root =
|
|
2030
|
+
const root = path6.resolve(projectRoot);
|
|
1953
2031
|
const shown = validation.staleFiles.slice(0, NOTICE_PATH_LIMIT).map((entry) => {
|
|
1954
|
-
const relative6 =
|
|
2032
|
+
const relative6 = path6.relative(root, entry.path);
|
|
1955
2033
|
const display = isInside2(root, entry.path) ? relative6 || "." : entry.path;
|
|
1956
2034
|
return `- ${JSON.stringify(display)} [${entry.status}]`;
|
|
1957
2035
|
});
|
|
@@ -2059,6 +2137,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2059
2137
|
projectRoot;
|
|
2060
2138
|
checkpointCas;
|
|
2061
2139
|
isSessionInUse;
|
|
2140
|
+
logger;
|
|
2062
2141
|
/**
|
|
2063
2142
|
* In-memory cache for load() results, keyed by session ID. The cache is
|
|
2064
2143
|
* invalidated when the file's mtimeMs or size changes (indicating the
|
|
@@ -2076,14 +2155,26 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2076
2155
|
static LIST_SCAN_CONCURRENCY = 32;
|
|
2077
2156
|
constructor(opts) {
|
|
2078
2157
|
this.dir = opts.dir;
|
|
2079
|
-
this.projectRoot = opts.projectRoot ?
|
|
2158
|
+
this.projectRoot = opts.projectRoot ? path7.resolve(opts.projectRoot) : void 0;
|
|
2080
2159
|
this.checkpointCas = this.projectRoot ? new SessionCheckpointCas({
|
|
2081
|
-
rootDir:
|
|
2160
|
+
rootDir: path7.join(this.dir, "_cas"),
|
|
2082
2161
|
projectRoot: this.projectRoot
|
|
2083
2162
|
}) : void 0;
|
|
2084
2163
|
this.events = opts.events;
|
|
2085
2164
|
this.secretScrubber = opts.secretScrubber;
|
|
2086
2165
|
this.isSessionInUse = opts.isSessionInUse;
|
|
2166
|
+
this.logger = opts.logger;
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* Emit a structured warning. Uses the configured Logger when available;
|
|
2170
|
+
* falls back to console.warn(JSON) so warnings are never silently dropped.
|
|
2171
|
+
*/
|
|
2172
|
+
logWarn(msg, ctx) {
|
|
2173
|
+
if (this.logger) {
|
|
2174
|
+
this.logger.warn(msg, ctx);
|
|
2175
|
+
} else {
|
|
2176
|
+
console.warn(JSON.stringify({ ...ctx, message: msg, timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
|
|
2177
|
+
}
|
|
2087
2178
|
}
|
|
2088
2179
|
/**
|
|
2089
2180
|
* Clear the load() cache. Useful for testing or when the caller knows
|
|
@@ -2132,17 +2223,17 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2132
2223
|
}
|
|
2133
2224
|
/** Absolute path to the session index file. */
|
|
2134
2225
|
get indexFile() {
|
|
2135
|
-
return
|
|
2226
|
+
return path7.join(this.dir, "_index.jsonl");
|
|
2136
2227
|
}
|
|
2137
2228
|
/** Join session ID to its absolute path within the store directory. */
|
|
2138
2229
|
sessionPath(id, ext) {
|
|
2139
2230
|
return sessionScopedPath(this.dir, id, ext);
|
|
2140
2231
|
}
|
|
2141
2232
|
shardManifestPath(shardKey) {
|
|
2142
|
-
return shardKey ?
|
|
2233
|
+
return shardKey ? path7.join(this.dir, shardKey, "_manifest.json") : path7.join(this.dir, "_manifest.json");
|
|
2143
2234
|
}
|
|
2144
2235
|
shardKeyForSessionId(id) {
|
|
2145
|
-
const dirName =
|
|
2236
|
+
const dirName = path7.dirname(id);
|
|
2146
2237
|
return dirName === "." ? "" : dirName;
|
|
2147
2238
|
}
|
|
2148
2239
|
invalidateShardManifestBySessionId(id) {
|
|
@@ -2154,7 +2245,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2154
2245
|
* subdirectory so sessions group naturally by day.
|
|
2155
2246
|
*/
|
|
2156
2247
|
async ensureShardDir(id) {
|
|
2157
|
-
const dirPath =
|
|
2248
|
+
const dirPath = path7.dirname(sessionScopedPath(this.dir, id, ""));
|
|
2158
2249
|
await ensureDir(dirPath);
|
|
2159
2250
|
return dirPath;
|
|
2160
2251
|
}
|
|
@@ -2185,12 +2276,10 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2185
2276
|
this.emitWrite(id, file, "create", "success", Date.now() - t0);
|
|
2186
2277
|
return writer;
|
|
2187
2278
|
} catch (err) {
|
|
2188
|
-
await handle.close().catch((e) =>
|
|
2189
|
-
|
|
2190
|
-
event: "session_store.handle_close_failed",
|
|
2191
|
-
|
|
2192
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2193
|
-
})));
|
|
2279
|
+
await handle.close().catch((e) => this.logWarn(
|
|
2280
|
+
"Session handle close failed",
|
|
2281
|
+
{ event: "session_store.handle_close_failed", message: e instanceof Error ? e.message : String(e) }
|
|
2282
|
+
));
|
|
2194
2283
|
this.emitError(id, file, "create", toErrorMessage(err), true);
|
|
2195
2284
|
throw err;
|
|
2196
2285
|
}
|
|
@@ -2216,7 +2305,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2216
2305
|
}
|
|
2217
2306
|
const parentPrefix = parent.events.slice(0, boundary + 1);
|
|
2218
2307
|
const workspaceCheckpoint = targetCheckpoint?.workspaceCheckpoint;
|
|
2219
|
-
const checkpointHash =
|
|
2308
|
+
const checkpointHash = createHash4("sha256").update(parentPrefix.map((event) => JSON.stringify(event)).join("\n") + "\n", "utf8").digest("hex");
|
|
2220
2309
|
const inherited = parentPrefix.filter(inheritsIntoFork);
|
|
2221
2310
|
const writer = await this.create({
|
|
2222
2311
|
id: "",
|
|
@@ -2311,7 +2400,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2311
2400
|
// Shard directory (sessions/<date>/) — must match create() so the
|
|
2312
2401
|
// .summary.json sidecar lands next to the JSONL instead of the
|
|
2313
2402
|
// sessions root (where summaryFor() would never find it).
|
|
2314
|
-
dir:
|
|
2403
|
+
dir: path7.dirname(file),
|
|
2315
2404
|
filePath: file,
|
|
2316
2405
|
secretScrubber: this.secretScrubber,
|
|
2317
2406
|
checkpointCas: this.checkpointCas,
|
|
@@ -2321,12 +2410,10 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2321
2410
|
this.emitWrite(id, file, "resume", "success", Date.now() - t0);
|
|
2322
2411
|
return { writer, data: resumedData };
|
|
2323
2412
|
} catch (err) {
|
|
2324
|
-
await handle.close().catch((e) =>
|
|
2325
|
-
|
|
2326
|
-
event: "session_store.handle_close_failed",
|
|
2327
|
-
|
|
2328
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2329
|
-
})));
|
|
2413
|
+
await handle.close().catch((e) => this.logWarn(
|
|
2414
|
+
"Session handle close failed",
|
|
2415
|
+
{ event: "session_store.handle_close_failed", message: e instanceof Error ? e.message : String(e) }
|
|
2416
|
+
));
|
|
2330
2417
|
this.emitError(id, file, "resume", toErrorMessage(err), true);
|
|
2331
2418
|
throw err;
|
|
2332
2419
|
}
|
|
@@ -2866,7 +2953,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2866
2953
|
return entry;
|
|
2867
2954
|
}
|
|
2868
2955
|
async collectSessionFilesInShard(shardKey) {
|
|
2869
|
-
const dir = shardKey ?
|
|
2956
|
+
const dir = shardKey ? path7.join(this.dir, shardKey) : this.dir;
|
|
2870
2957
|
const entries = await this.collectSessionFiles(dir, shardKey);
|
|
2871
2958
|
return shardKey ? entries.filter((entry) => entry.id.startsWith(`${shardKey}/`)) : entries.filter((entry) => !entry.id.includes("/"));
|
|
2872
2959
|
}
|
|
@@ -2889,13 +2976,13 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2889
2976
|
if (entry.name === "_index.jsonl") continue;
|
|
2890
2977
|
const base = entry.name.replace(/\.jsonl$/, "");
|
|
2891
2978
|
const id = prefix ? `${prefix}/${base}` : base;
|
|
2892
|
-
files.push({ id, filePath:
|
|
2979
|
+
files.push({ id, filePath: path7.join(dir, entry.name) });
|
|
2893
2980
|
}
|
|
2894
2981
|
}
|
|
2895
2982
|
const childFileArrays = await Promise.all(
|
|
2896
2983
|
dirEntries.map((entry) => {
|
|
2897
2984
|
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
2898
|
-
return this.collectSessionFiles(
|
|
2985
|
+
return this.collectSessionFiles(path7.join(dir, entry.name), childPrefix, depth + 1);
|
|
2899
2986
|
})
|
|
2900
2987
|
);
|
|
2901
2988
|
return [...childFileArrays.flat(), ...files];
|
|
@@ -2928,7 +3015,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2928
3015
|
const childIdArrays = await Promise.all(
|
|
2929
3016
|
dirEntries.map((entry) => {
|
|
2930
3017
|
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
2931
|
-
return this.collectSessionIds(
|
|
3018
|
+
return this.collectSessionIds(path7.join(dir, entry.name), childPrefix, depth + 1);
|
|
2932
3019
|
})
|
|
2933
3020
|
);
|
|
2934
3021
|
return [...childIdArrays.flat(), ...fileIds];
|
|
@@ -2947,13 +3034,10 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
2947
3034
|
await atomicWrite(manifest, JSON.stringify(summary), { mode: 384 }).catch((err) => {
|
|
2948
3035
|
const msg = toErrorMessage(err);
|
|
2949
3036
|
this.emitError(id, manifest, "summary_fallback", msg, true);
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
event: "session_store.manifest_write_failed",
|
|
2953
|
-
|
|
2954
|
-
message: msg,
|
|
2955
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2956
|
-
}));
|
|
3037
|
+
this.logWarn(
|
|
3038
|
+
"Session manifest write failed",
|
|
3039
|
+
{ event: "session_store.manifest_write_failed", sessionId: id, message: msg }
|
|
3040
|
+
);
|
|
2957
3041
|
});
|
|
2958
3042
|
outcome = "failure";
|
|
2959
3043
|
errorMsg = "summary fallback \xE2\u20AC\u201D manifest rebuilt";
|
|
@@ -3045,9 +3129,9 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
3045
3129
|
async deleteSession(id) {
|
|
3046
3130
|
const jsonlPath = this.sessionPath(id, ".jsonl");
|
|
3047
3131
|
const summaryPath = this.sessionPath(id, ".summary.json");
|
|
3048
|
-
const shardDir =
|
|
3049
|
-
const base =
|
|
3050
|
-
const sessDir =
|
|
3132
|
+
const shardDir = path7.dirname(jsonlPath);
|
|
3133
|
+
const base = path7.basename(id);
|
|
3134
|
+
const sessDir = path7.join(shardDir, base);
|
|
3051
3135
|
const deletions = [
|
|
3052
3136
|
fsp4.unlink(jsonlPath),
|
|
3053
3137
|
fsp4.unlink(summaryPath),
|
|
@@ -3088,7 +3172,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
3088
3172
|
*/
|
|
3089
3173
|
async readActiveSessionId() {
|
|
3090
3174
|
try {
|
|
3091
|
-
const raw = await fsp4.readFile(
|
|
3175
|
+
const raw = await fsp4.readFile(path7.join(this.dir, "active.json"), "utf8");
|
|
3092
3176
|
const active = JSON.parse(raw);
|
|
3093
3177
|
return active.sessionId ?? null;
|
|
3094
3178
|
} catch {
|
|
@@ -3151,7 +3235,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
3151
3235
|
const activeSessionId = await this.readActiveSessionId();
|
|
3152
3236
|
const isPrunableJsonl = (name) => name.endsWith(".jsonl") && name !== "_index.jsonl" && name !== "_mailbox.jsonl" && !name.endsWith(".replay.jsonl") && !name.endsWith(".audit.jsonl");
|
|
3153
3237
|
const pruneFile = async (dir, name, prefix) => {
|
|
3154
|
-
const jsonlPath =
|
|
3238
|
+
const jsonlPath = path7.join(dir, name);
|
|
3155
3239
|
try {
|
|
3156
3240
|
const stat13 = await fsp4.stat(jsonlPath);
|
|
3157
3241
|
if (stat13.mtimeMs >= cutoff) return;
|
|
@@ -3171,7 +3255,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
3171
3255
|
continue;
|
|
3172
3256
|
}
|
|
3173
3257
|
if (!entry.isDirectory()) continue;
|
|
3174
|
-
const dateDir =
|
|
3258
|
+
const dateDir = path7.join(this.dir, entry.name);
|
|
3175
3259
|
const files = await fsp4.readdir(dateDir, { withFileTypes: true }).catch(() => []);
|
|
3176
3260
|
for (const file of files) {
|
|
3177
3261
|
if (!file.isFile() || !isPrunableJsonl(file.name)) continue;
|
|
@@ -3183,7 +3267,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
3183
3267
|
}
|
|
3184
3268
|
for (const entry of entries) {
|
|
3185
3269
|
if (!entry.isDirectory()) continue;
|
|
3186
|
-
const dateDir =
|
|
3270
|
+
const dateDir = path7.join(this.dir, entry.name);
|
|
3187
3271
|
try {
|
|
3188
3272
|
const remaining = await fsp4.readdir(dateDir);
|
|
3189
3273
|
if (remaining.length === 0) {
|
|
@@ -3305,16 +3389,29 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
3305
3389
|
}
|
|
3306
3390
|
}
|
|
3307
3391
|
};
|
|
3392
|
+
|
|
3393
|
+
// src/storage/queue-store.ts
|
|
3394
|
+
import * as fsp5 from "node:fs/promises";
|
|
3395
|
+
import * as path8 from "node:path";
|
|
3308
3396
|
var QueueStore = class {
|
|
3309
3397
|
file;
|
|
3310
3398
|
// Use `| undefined` (not `?`) so exactOptionalPropertyTypes doesn't
|
|
3311
3399
|
// reject assigning an optional constructor parameter to these fields.
|
|
3312
3400
|
events;
|
|
3313
3401
|
traceId;
|
|
3402
|
+
logger;
|
|
3314
3403
|
constructor(opts) {
|
|
3315
|
-
this.file =
|
|
3404
|
+
this.file = path8.join(opts.dir, "queue.json");
|
|
3316
3405
|
this.events = opts.events;
|
|
3317
3406
|
this.traceId = opts.traceId;
|
|
3407
|
+
this.logger = opts.logger;
|
|
3408
|
+
}
|
|
3409
|
+
logWarn(msg, ctx) {
|
|
3410
|
+
if (this.logger) {
|
|
3411
|
+
this.logger.warn(msg, ctx);
|
|
3412
|
+
} else {
|
|
3413
|
+
console.warn(JSON.stringify({ ...ctx, message: msg, timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
|
|
3414
|
+
}
|
|
3318
3415
|
}
|
|
3319
3416
|
async write(items) {
|
|
3320
3417
|
const t0 = Date.now();
|
|
@@ -3344,20 +3441,14 @@ var QueueStore = class {
|
|
|
3344
3441
|
recoverable: false,
|
|
3345
3442
|
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
3346
3443
|
});
|
|
3347
|
-
|
|
3348
|
-
level: "warn",
|
|
3349
|
-
event: "queue_store.write_failed",
|
|
3350
|
-
path: this.file,
|
|
3351
|
-
message: toErrorMessage(err),
|
|
3352
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3353
|
-
}));
|
|
3444
|
+
this.logWarn("Queue store write failed", { event: "queue_store.write_failed", path: this.file, message: toErrorMessage(err) });
|
|
3354
3445
|
}
|
|
3355
3446
|
}
|
|
3356
3447
|
async read() {
|
|
3357
3448
|
const t0 = Date.now();
|
|
3358
3449
|
let raw;
|
|
3359
3450
|
try {
|
|
3360
|
-
raw = await
|
|
3451
|
+
raw = await fsp5.readFile(this.file, "utf8");
|
|
3361
3452
|
} catch (err) {
|
|
3362
3453
|
const code = err.code;
|
|
3363
3454
|
if (code === "ENOENT") {
|
|
@@ -3382,13 +3473,7 @@ var QueueStore = class {
|
|
|
3382
3473
|
recoverable: true,
|
|
3383
3474
|
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
3384
3475
|
});
|
|
3385
|
-
|
|
3386
|
-
level: "warn",
|
|
3387
|
-
event: "queue_store.read_failed",
|
|
3388
|
-
path: this.file,
|
|
3389
|
-
message: toErrorMessage(err),
|
|
3390
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3391
|
-
}));
|
|
3476
|
+
this.logWarn("Queue store read failed", { event: "queue_store.read_failed", path: this.file, message: toErrorMessage(err) });
|
|
3392
3477
|
return [];
|
|
3393
3478
|
}
|
|
3394
3479
|
let parsed;
|
|
@@ -3438,7 +3523,7 @@ var QueueStore = class {
|
|
|
3438
3523
|
async clear() {
|
|
3439
3524
|
const t0 = Date.now();
|
|
3440
3525
|
try {
|
|
3441
|
-
await
|
|
3526
|
+
await fsp5.unlink(this.file);
|
|
3442
3527
|
this.events?.emit("storage.write", {
|
|
3443
3528
|
sessionId: this.traceId ?? "~boot~",
|
|
3444
3529
|
store: "queue",
|
|
@@ -3461,13 +3546,7 @@ var QueueStore = class {
|
|
|
3461
3546
|
recoverable: true,
|
|
3462
3547
|
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
3463
3548
|
});
|
|
3464
|
-
|
|
3465
|
-
level: "warn",
|
|
3466
|
-
event: "queue_store.clear_failed",
|
|
3467
|
-
path: this.file,
|
|
3468
|
-
message: err.message,
|
|
3469
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3470
|
-
}));
|
|
3549
|
+
this.logWarn("Queue store clear failed", { event: "queue_store.clear_failed", path: this.file, message: err.message });
|
|
3471
3550
|
}
|
|
3472
3551
|
}
|
|
3473
3552
|
};
|
|
@@ -3476,6 +3555,11 @@ function isPersistedQueueItem(v) {
|
|
|
3476
3555
|
const o = v;
|
|
3477
3556
|
return typeof o["displayText"] === "string" && Array.isArray(o["blocks"]);
|
|
3478
3557
|
}
|
|
3558
|
+
|
|
3559
|
+
// src/storage/attachment-store.ts
|
|
3560
|
+
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
3561
|
+
import * as fsp6 from "node:fs/promises";
|
|
3562
|
+
import * as path9 from "node:path";
|
|
3479
3563
|
var DEFAULT_SPOOL_THRESHOLD = 256 * 1024;
|
|
3480
3564
|
var PLACEHOLDER_RE = /\[(pasted|image|file) #(\d+)[^\]]*\]|\[file:([^\]]+)\]/g;
|
|
3481
3565
|
var DefaultAttachmentStore = class {
|
|
@@ -3490,13 +3574,13 @@ var DefaultAttachmentStore = class {
|
|
|
3490
3574
|
}
|
|
3491
3575
|
async add(input) {
|
|
3492
3576
|
const seq = ++this.nextSeq[input.kind];
|
|
3493
|
-
const id = `${kindPrefix(input.kind)}-${seq}-${
|
|
3577
|
+
const id = `${kindPrefix(input.kind)}-${seq}-${randomBytes3(3).toString("hex")}`;
|
|
3494
3578
|
const bytes = Buffer.byteLength(input.data, input.kind === "image" ? "base64" : "utf8");
|
|
3495
3579
|
let spooledPath;
|
|
3496
3580
|
let data = input.data;
|
|
3497
3581
|
if (this.spoolDir && bytes >= this.spoolThreshold) {
|
|
3498
|
-
await
|
|
3499
|
-
spooledPath =
|
|
3582
|
+
await fsp6.mkdir(this.spoolDir, { recursive: true });
|
|
3583
|
+
spooledPath = path9.join(this.spoolDir, `${id}.bin`);
|
|
3500
3584
|
await atomicWrite(spooledPath, input.data, {
|
|
3501
3585
|
encoding: input.kind === "image" ? "base64" : "utf8"
|
|
3502
3586
|
});
|
|
@@ -3558,7 +3642,7 @@ var DefaultAttachmentStore = class {
|
|
|
3558
3642
|
for (const att of this.items.values()) {
|
|
3559
3643
|
if (att.path) toDelete.push(att.path);
|
|
3560
3644
|
}
|
|
3561
|
-
await Promise.all(toDelete.map((p) =>
|
|
3645
|
+
await Promise.all(toDelete.map((p) => fsp6.unlink(p).catch(() => void 0)));
|
|
3562
3646
|
}
|
|
3563
3647
|
this.items.clear();
|
|
3564
3648
|
this.refs.length = 0;
|
|
@@ -3566,7 +3650,7 @@ var DefaultAttachmentStore = class {
|
|
|
3566
3650
|
}
|
|
3567
3651
|
async toBlock(att) {
|
|
3568
3652
|
if (att.kind === "image") {
|
|
3569
|
-
const data = att.data ?? (att.path ? await
|
|
3653
|
+
const data = att.data ?? (att.path ? await fsp6.readFile(att.path, { encoding: "base64" }) : "");
|
|
3570
3654
|
return {
|
|
3571
3655
|
type: "image",
|
|
3572
3656
|
source: {
|
|
@@ -3576,7 +3660,7 @@ var DefaultAttachmentStore = class {
|
|
|
3576
3660
|
}
|
|
3577
3661
|
};
|
|
3578
3662
|
}
|
|
3579
|
-
const raw = att.data ?? (att.path ? await
|
|
3663
|
+
const raw = att.data ?? (att.path ? await fsp6.readFile(att.path, "utf8") : "");
|
|
3580
3664
|
const label = att.meta.filename ? `<file path="${att.meta.filename}">` : "<pasted>";
|
|
3581
3665
|
const close = att.meta.filename ? "</file>" : "</pasted>";
|
|
3582
3666
|
return { type: "text", text: `${label}
|
|
@@ -3614,6 +3698,11 @@ function mergeAdjacentText(blocks) {
|
|
|
3614
3698
|
return out;
|
|
3615
3699
|
}
|
|
3616
3700
|
|
|
3701
|
+
// src/storage/memory-backend.ts
|
|
3702
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
3703
|
+
import * as fs2 from "node:fs/promises";
|
|
3704
|
+
import * as path10 from "node:path";
|
|
3705
|
+
|
|
3617
3706
|
// src/types/memory.ts
|
|
3618
3707
|
var MEMORY_TYPE_LABELS = {
|
|
3619
3708
|
fact: "Fact",
|
|
@@ -3779,7 +3868,7 @@ var FileMemoryBackend = class {
|
|
|
3779
3868
|
}
|
|
3780
3869
|
async getMtime(file) {
|
|
3781
3870
|
try {
|
|
3782
|
-
const stat13 = await
|
|
3871
|
+
const stat13 = await fs2.stat(file);
|
|
3783
3872
|
return stat13.mtimeMs;
|
|
3784
3873
|
} catch {
|
|
3785
3874
|
return 0;
|
|
@@ -3826,13 +3915,13 @@ var FileMemoryBackend = class {
|
|
|
3826
3915
|
}
|
|
3827
3916
|
async remember(scope, entry, filePath) {
|
|
3828
3917
|
const file = this.resolveFile(filePath, scope);
|
|
3829
|
-
await ensureDir(
|
|
3918
|
+
await ensureDir(path10.dirname(file));
|
|
3830
3919
|
let existing = "";
|
|
3831
3920
|
try {
|
|
3832
|
-
existing = await
|
|
3921
|
+
existing = await fs2.readFile(file, "utf8");
|
|
3833
3922
|
} catch {
|
|
3834
3923
|
}
|
|
3835
|
-
const id = `mem_${Date.now()}_${
|
|
3924
|
+
const id = `mem_${Date.now()}_${randomUUID2().slice(0, 8)}`;
|
|
3836
3925
|
const meta = formatMetadata(entry);
|
|
3837
3926
|
const line = `
|
|
3838
3927
|
- [${entry.ts}] ${id}${meta} ${entry.text.replace(/\n/g, " ")}
|
|
@@ -3847,7 +3936,7 @@ ${line}`;
|
|
|
3847
3936
|
return withFileLock(file, async () => {
|
|
3848
3937
|
let existing;
|
|
3849
3938
|
try {
|
|
3850
|
-
existing = await
|
|
3939
|
+
existing = await fs2.readFile(file, "utf8");
|
|
3851
3940
|
} catch {
|
|
3852
3941
|
return 0;
|
|
3853
3942
|
}
|
|
@@ -3884,7 +3973,7 @@ ${line}`;
|
|
|
3884
3973
|
async readAll(scope, filePath) {
|
|
3885
3974
|
const file = this.resolveFile(filePath, scope);
|
|
3886
3975
|
try {
|
|
3887
|
-
return await
|
|
3976
|
+
return await fs2.readFile(file, "utf8");
|
|
3888
3977
|
} catch {
|
|
3889
3978
|
return "";
|
|
3890
3979
|
}
|
|
@@ -3908,7 +3997,7 @@ ${line}`;
|
|
|
3908
3997
|
const file = this.resolveFile(filePath, scope);
|
|
3909
3998
|
let existing;
|
|
3910
3999
|
try {
|
|
3911
|
-
existing = await
|
|
4000
|
+
existing = await fs2.readFile(file, "utf8");
|
|
3912
4001
|
} catch {
|
|
3913
4002
|
return 0;
|
|
3914
4003
|
}
|
|
@@ -3928,7 +4017,7 @@ ${line}`;
|
|
|
3928
4017
|
const next = lines.join("\n");
|
|
3929
4018
|
const backup = `${file}.bak.${Date.now()}`;
|
|
3930
4019
|
try {
|
|
3931
|
-
await
|
|
4020
|
+
await fs2.copyFile(file, backup);
|
|
3932
4021
|
await pruneConsolidateBackups(file);
|
|
3933
4022
|
} catch {
|
|
3934
4023
|
}
|
|
@@ -3942,14 +4031,14 @@ ${line}`;
|
|
|
3942
4031
|
}
|
|
3943
4032
|
};
|
|
3944
4033
|
async function pruneConsolidateBackups(file) {
|
|
3945
|
-
const dir =
|
|
3946
|
-
const base =
|
|
4034
|
+
const dir = path10.dirname(file);
|
|
4035
|
+
const base = path10.basename(file);
|
|
3947
4036
|
const prefix = `${base}.bak.`;
|
|
3948
|
-
const backups = (await
|
|
4037
|
+
const backups = (await fs2.readdir(dir)).filter((name) => name.startsWith(prefix)).sort().reverse();
|
|
3949
4038
|
await Promise.all(
|
|
3950
4039
|
backups.slice(MAX_MEMORY_CONSOLIDATE_BACKUPS).map(async (name) => {
|
|
3951
4040
|
try {
|
|
3952
|
-
await
|
|
4041
|
+
await fs2.unlink(path10.join(dir, name));
|
|
3953
4042
|
} catch {
|
|
3954
4043
|
}
|
|
3955
4044
|
})
|
|
@@ -4309,6 +4398,10 @@ ${body.trim()}`);
|
|
|
4309
4398
|
score += 1;
|
|
4310
4399
|
reasons.push("preference");
|
|
4311
4400
|
break;
|
|
4401
|
+
case "reference":
|
|
4402
|
+
break;
|
|
4403
|
+
case "fact":
|
|
4404
|
+
break;
|
|
4312
4405
|
}
|
|
4313
4406
|
const ageDays = (now - new Date(entry.ts).getTime()) / (1e3 * 60 * 60 * 24);
|
|
4314
4407
|
if (ageDays < 1) score += 1;
|
|
@@ -4516,9 +4609,9 @@ ${body.trim()}`);
|
|
|
4516
4609
|
if (!this.persistBackup || scope === "project-agents") return;
|
|
4517
4610
|
try {
|
|
4518
4611
|
const content = await this.backend.readAll(scope, this.files[scope]);
|
|
4519
|
-
const { writeFile:
|
|
4520
|
-
await
|
|
4521
|
-
await
|
|
4612
|
+
const { writeFile: writeFile7, mkdir: mkdir7 } = await import("node:fs/promises");
|
|
4613
|
+
await mkdir7(this.backupDir, { recursive: true });
|
|
4614
|
+
await writeFile7(`${this.backupDir}/${scope}.md`, content, "utf8");
|
|
4522
4615
|
} catch {
|
|
4523
4616
|
}
|
|
4524
4617
|
}
|
|
@@ -4533,6 +4626,9 @@ function labelOf(scope) {
|
|
|
4533
4626
|
return "User memory";
|
|
4534
4627
|
}
|
|
4535
4628
|
}
|
|
4629
|
+
|
|
4630
|
+
// src/storage/memory-graph-backend.ts
|
|
4631
|
+
import * as fs3 from "node:fs/promises";
|
|
4536
4632
|
var GraphMemoryBackend = class _GraphMemoryBackend {
|
|
4537
4633
|
kind = "graph";
|
|
4538
4634
|
file;
|
|
@@ -4584,7 +4680,8 @@ var GraphMemoryBackend = class _GraphMemoryBackend {
|
|
|
4584
4680
|
priority: entry.priority
|
|
4585
4681
|
});
|
|
4586
4682
|
this.indexNode(nodeId, entry);
|
|
4587
|
-
const
|
|
4683
|
+
const SIMILARITY_WINDOW = 100;
|
|
4684
|
+
const recentNodes = [...this.nodes.values()].slice(-SIMILARITY_WINDOW);
|
|
4588
4685
|
for (const other of recentNodes) {
|
|
4589
4686
|
if (other.id === nodeId) continue;
|
|
4590
4687
|
const sim = wordOverlap(entry.text, other.entry.text);
|
|
@@ -4699,7 +4796,7 @@ var GraphMemoryBackend = class _GraphMemoryBackend {
|
|
|
4699
4796
|
this.loadedScope = scope;
|
|
4700
4797
|
this.loaded = true;
|
|
4701
4798
|
try {
|
|
4702
|
-
await
|
|
4799
|
+
await fs3.unlink(this.graphFile);
|
|
4703
4800
|
} catch {
|
|
4704
4801
|
}
|
|
4705
4802
|
}
|
|
@@ -4739,7 +4836,7 @@ var GraphMemoryBackend = class _GraphMemoryBackend {
|
|
|
4739
4836
|
async loadGraph(scope) {
|
|
4740
4837
|
if (this.loaded && this.loadedScope === scope) return;
|
|
4741
4838
|
try {
|
|
4742
|
-
const raw = await
|
|
4839
|
+
const raw = await fs3.readFile(this.graphFile, "utf8");
|
|
4743
4840
|
const data = JSON.parse(raw);
|
|
4744
4841
|
this.nodes = new Map(data.nodes);
|
|
4745
4842
|
this.edges = data.edges;
|
|
@@ -4761,10 +4858,10 @@ var GraphMemoryBackend = class _GraphMemoryBackend {
|
|
|
4761
4858
|
edges: this.edges
|
|
4762
4859
|
};
|
|
4763
4860
|
const dir = this.graphFile.substring(0, this.graphFile.lastIndexOf("/"));
|
|
4764
|
-
await
|
|
4861
|
+
await fs3.mkdir(dir, { recursive: true });
|
|
4765
4862
|
const tmp = `${this.graphFile}.tmp`;
|
|
4766
|
-
await
|
|
4767
|
-
await
|
|
4863
|
+
await fs3.writeFile(tmp, JSON.stringify(data));
|
|
4864
|
+
await fs3.rename(tmp, this.graphFile);
|
|
4768
4865
|
} catch {
|
|
4769
4866
|
}
|
|
4770
4867
|
}
|
|
@@ -4880,6 +4977,11 @@ function simpleHash(s) {
|
|
|
4880
4977
|
}
|
|
4881
4978
|
return Math.abs(h).toString(36);
|
|
4882
4979
|
}
|
|
4980
|
+
|
|
4981
|
+
// src/utils/instruction-file.ts
|
|
4982
|
+
import { readFileSync, statSync } from "node:fs";
|
|
4983
|
+
import * as path11 from "node:path";
|
|
4984
|
+
import { fileURLToPath } from "node:url";
|
|
4883
4985
|
var textCache = /* @__PURE__ */ new Map();
|
|
4884
4986
|
var rootCandidates;
|
|
4885
4987
|
function readBundledInstructionText(relativePath) {
|
|
@@ -4888,7 +4990,7 @@ function readBundledInstructionText(relativePath) {
|
|
|
4888
4990
|
let resolved = "";
|
|
4889
4991
|
for (const root of instructionRootCandidates()) {
|
|
4890
4992
|
try {
|
|
4891
|
-
resolved = readFileSync(
|
|
4993
|
+
resolved = readFileSync(path11.join(root, relativePath), "utf8").trimEnd();
|
|
4892
4994
|
break;
|
|
4893
4995
|
} catch {
|
|
4894
4996
|
}
|
|
@@ -4904,11 +5006,11 @@ function renderInstructionTemplate(template, values) {
|
|
|
4904
5006
|
}
|
|
4905
5007
|
function instructionRootCandidates() {
|
|
4906
5008
|
if (rootCandidates !== void 0) return rootCandidates;
|
|
4907
|
-
const here =
|
|
5009
|
+
const here = path11.dirname(fileURLToPath(import.meta.url));
|
|
4908
5010
|
const candidates = [
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
5011
|
+
path11.resolve(here, "../../instructions"),
|
|
5012
|
+
path11.resolve(here, "../instructions"),
|
|
5013
|
+
path11.resolve(here, "instructions")
|
|
4912
5014
|
];
|
|
4913
5015
|
rootCandidates = candidates.sort((a, b) => Number(!isDirectory(a)) - Number(!isDirectory(b)));
|
|
4914
5016
|
return rootCandidates;
|
|
@@ -5104,14 +5206,13 @@ function deepFreeze(obj) {
|
|
|
5104
5206
|
}
|
|
5105
5207
|
return Object.freeze(obj);
|
|
5106
5208
|
}
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
KEK_MAGIC.length + 1 + KEK_SALT_BYTES + IV_BYTES + TAG_BYTES + KEY_BYTES;
|
|
5209
|
+
|
|
5210
|
+
// src/storage/provider-config-watcher.ts
|
|
5211
|
+
import * as syncFs from "node:fs";
|
|
5212
|
+
import * as fs4 from "node:fs/promises";
|
|
5213
|
+
import * as path12 from "node:path";
|
|
5214
|
+
|
|
5215
|
+
// src/security/config-secrets.ts
|
|
5115
5216
|
function decryptConfigSecrets(cfg, vault, opts) {
|
|
5116
5217
|
const warn = opts?.warn ?? ((msg) => console.warn(msg));
|
|
5117
5218
|
return walk(cfg, vault, (v, key) => {
|
|
@@ -5155,7 +5256,7 @@ function isSecretField(name) {
|
|
|
5155
5256
|
async function readProviderSnapshot(configPath, vault, warn) {
|
|
5156
5257
|
let raw;
|
|
5157
5258
|
try {
|
|
5158
|
-
raw = await
|
|
5259
|
+
raw = await fs4.readFile(configPath, "utf8");
|
|
5159
5260
|
} catch (err) {
|
|
5160
5261
|
if (err.code !== "ENOENT") {
|
|
5161
5262
|
warn?.(`Could not read ${configPath}: ${err.message}`);
|
|
@@ -5190,7 +5291,7 @@ function serializeSnapshot(s) {
|
|
|
5190
5291
|
function watchProviderConfig(configPath, vault, onChange, opts = {}) {
|
|
5191
5292
|
const debounceMs = opts.debounceMs ?? 200;
|
|
5192
5293
|
const warn = opts.warn;
|
|
5193
|
-
const base =
|
|
5294
|
+
const base = path12.basename(configPath);
|
|
5194
5295
|
let timer;
|
|
5195
5296
|
let closed = false;
|
|
5196
5297
|
let lastSerialized;
|
|
@@ -5201,7 +5302,7 @@ function watchProviderConfig(configPath, vault, onChange, opts = {}) {
|
|
|
5201
5302
|
});
|
|
5202
5303
|
let watcher;
|
|
5203
5304
|
try {
|
|
5204
|
-
watcher = syncFs.watch(
|
|
5305
|
+
watcher = syncFs.watch(path12.dirname(configPath), { recursive: false });
|
|
5205
5306
|
} catch (err) {
|
|
5206
5307
|
warn?.(`Provider config watcher could not start: ${err.message}`);
|
|
5207
5308
|
return { close: () => {
|
|
@@ -5243,6 +5344,10 @@ function watchProviderConfig(configPath, vault, onChange, opts = {}) {
|
|
|
5243
5344
|
};
|
|
5244
5345
|
}
|
|
5245
5346
|
|
|
5347
|
+
// src/storage/config-loader.ts
|
|
5348
|
+
import * as fs5 from "node:fs/promises";
|
|
5349
|
+
import * as path13 from "node:path";
|
|
5350
|
+
|
|
5246
5351
|
// src/types/config.ts
|
|
5247
5352
|
var DEFAULT_TUI_THINKING_WORD = "thinking";
|
|
5248
5353
|
|
|
@@ -5381,12 +5486,38 @@ var BEHAVIOR_DEFAULTS = {
|
|
|
5381
5486
|
tokenSavingMode: "off",
|
|
5382
5487
|
allowOutsideProjectRoot: true
|
|
5383
5488
|
},
|
|
5489
|
+
superMemory: {
|
|
5490
|
+
enabled: true,
|
|
5491
|
+
storage: {
|
|
5492
|
+
projectLocal: true,
|
|
5493
|
+
directory: ".wrongstack/memories"
|
|
5494
|
+
},
|
|
5495
|
+
inject: {
|
|
5496
|
+
turnContext: true,
|
|
5497
|
+
toolResults: true,
|
|
5498
|
+
maxHintsPerTool: 4,
|
|
5499
|
+
maxCharsPerTool: 1200,
|
|
5500
|
+
maxTurnMemories: 8,
|
|
5501
|
+
maxCharsPerTurn: 2400,
|
|
5502
|
+
minScore: 0.65,
|
|
5503
|
+
repeatCooldownMs: 30 * 6e4
|
|
5504
|
+
},
|
|
5505
|
+
hygiene: {
|
|
5506
|
+
autoAfterSession: true,
|
|
5507
|
+
autoOnFileChange: true,
|
|
5508
|
+
retentionDays: 90,
|
|
5509
|
+
archiveLowConfidenceAfterDays: 30
|
|
5510
|
+
},
|
|
5511
|
+
embeddings: {
|
|
5512
|
+
enabled: false
|
|
5513
|
+
}
|
|
5514
|
+
},
|
|
5384
5515
|
skills: { readClaudeSkills: true },
|
|
5385
5516
|
mcpServers: {},
|
|
5386
5517
|
fallbackAuto: true,
|
|
5387
5518
|
maxConcurrent: 4,
|
|
5388
|
-
// YOLO on by default: auto-approve
|
|
5389
|
-
// prompt.
|
|
5519
|
+
// YOLO on by default: auto-approve non-denied tool calls without a per-call
|
|
5520
|
+
// prompt. Users
|
|
5390
5521
|
// who want the per-call prompts set `yolo: false`. Existing installs whose
|
|
5391
5522
|
// config lacks this key pick it up via fillMissingDefaults; an explicit
|
|
5392
5523
|
// `false` is preserved by the deep-merge (opt-out respected).
|
|
@@ -5405,8 +5536,8 @@ var BEHAVIOR_DEFAULTS = {
|
|
|
5405
5536
|
autonomy: {
|
|
5406
5537
|
// 'auto' by default: the agent self-drives (picks the top next-step after
|
|
5407
5538
|
// each turn). This is a startup default, not a runtime flip — the
|
|
5408
|
-
// autoProceedMaxIterations cap + autoProceedDelayMs cooldown +
|
|
5409
|
-
//
|
|
5539
|
+
// autoProceedMaxIterations cap + autoProceedDelayMs cooldown + Ctrl+C /
|
|
5540
|
+
// [GOAL_COMPLETE] stops remain in force. Explicit 'off'
|
|
5410
5541
|
// in a config file is preserved (opt-out respected).
|
|
5411
5542
|
defaultMode: "auto",
|
|
5412
5543
|
autoProceedDelayMs: DEFAULT_AUTONOMY_CONFIG.autoProceedDelayMs,
|
|
@@ -5521,6 +5652,7 @@ var IN_PROJECT_ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
|
5521
5652
|
"context",
|
|
5522
5653
|
"tools",
|
|
5523
5654
|
"features",
|
|
5655
|
+
"superMemory",
|
|
5524
5656
|
"skills",
|
|
5525
5657
|
"autonomy",
|
|
5526
5658
|
"indexing",
|
|
@@ -5560,6 +5692,14 @@ var KNOWN_DENIED_IN_PROJECT = [
|
|
|
5560
5692
|
{
|
|
5561
5693
|
key: "fleet",
|
|
5562
5694
|
reason: "Fleet supervision knobs: a repo-committed config could enable autonomous subagent spawning/steering/termination and mailbox traffic on the victim machine."
|
|
5695
|
+
},
|
|
5696
|
+
{
|
|
5697
|
+
key: "brain",
|
|
5698
|
+
reason: "Brain decision-layer knobs: a repo-committed config could raise the autonomy risk ceiling, switch the Brain to headless (removing the human tier), or reroute Brain decisions to an attacker-chosen provider/model."
|
|
5699
|
+
},
|
|
5700
|
+
{
|
|
5701
|
+
key: "git",
|
|
5702
|
+
reason: "Carries git.identity (GIT_AUTHOR_*/GIT_COMMITTER_* injection): a repo-committed config could spoof the author identity written into the victim's commit history (impersonation)."
|
|
5563
5703
|
}
|
|
5564
5704
|
];
|
|
5565
5705
|
var KNOWN_CONFIG_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -5585,6 +5725,7 @@ var KNOWN_CONFIG_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
5585
5725
|
"plugins",
|
|
5586
5726
|
"log",
|
|
5587
5727
|
"features",
|
|
5728
|
+
"superMemory",
|
|
5588
5729
|
"skills",
|
|
5589
5730
|
"yolo",
|
|
5590
5731
|
"nextPrediction",
|
|
@@ -5603,7 +5744,9 @@ var KNOWN_CONFIG_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
5603
5744
|
"sync",
|
|
5604
5745
|
"extensions",
|
|
5605
5746
|
"acp",
|
|
5606
|
-
"fleet"
|
|
5747
|
+
"fleet",
|
|
5748
|
+
"brain",
|
|
5749
|
+
"git"
|
|
5607
5750
|
]);
|
|
5608
5751
|
function assertInProjectAllowListComplete() {
|
|
5609
5752
|
const missingFromBoth = [];
|
|
@@ -5696,6 +5839,19 @@ function stripUnsafeInProjectFields(inProject, sourcePath, warn = (msg) => conso
|
|
|
5696
5839
|
out["skills"] = clonedSkills;
|
|
5697
5840
|
}
|
|
5698
5841
|
}
|
|
5842
|
+
const outSuperMemory = out["superMemory"];
|
|
5843
|
+
if (outSuperMemory && typeof outSuperMemory === "object") {
|
|
5844
|
+
const storage = outSuperMemory["storage"];
|
|
5845
|
+
if (storage && typeof storage === "object" && "directory" in storage) {
|
|
5846
|
+
const clonedStorage = { ...storage };
|
|
5847
|
+
delete clonedStorage["directory"];
|
|
5848
|
+
out["superMemory"] = {
|
|
5849
|
+
...outSuperMemory,
|
|
5850
|
+
storage: clonedStorage
|
|
5851
|
+
};
|
|
5852
|
+
stripped.push("superMemory.storage.directory");
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5699
5855
|
if (stripped.length > 0) {
|
|
5700
5856
|
warn(
|
|
5701
5857
|
JSON.stringify({
|
|
@@ -5711,8 +5867,8 @@ function stripUnsafeInProjectFields(inProject, sourcePath, warn = (msg) => conso
|
|
|
5711
5867
|
return out;
|
|
5712
5868
|
}
|
|
5713
5869
|
function samePath(a, b) {
|
|
5714
|
-
let ra =
|
|
5715
|
-
let rb =
|
|
5870
|
+
let ra = path13.resolve(a);
|
|
5871
|
+
let rb = path13.resolve(b);
|
|
5716
5872
|
if (process.platform === "win32" || process.platform === "darwin") {
|
|
5717
5873
|
ra = ra.toLowerCase();
|
|
5718
5874
|
rb = rb.toLowerCase();
|
|
@@ -5741,6 +5897,7 @@ var DefaultConfigLoader = class {
|
|
|
5741
5897
|
extraSources;
|
|
5742
5898
|
events;
|
|
5743
5899
|
traceId;
|
|
5900
|
+
logger;
|
|
5744
5901
|
jsonCache = /* @__PURE__ */ new Map();
|
|
5745
5902
|
constructor(opts) {
|
|
5746
5903
|
this.paths = opts.paths;
|
|
@@ -5749,6 +5906,19 @@ var DefaultConfigLoader = class {
|
|
|
5749
5906
|
this.extraSources = opts.sources ?? [];
|
|
5750
5907
|
this.events = opts.events;
|
|
5751
5908
|
this.traceId = opts.traceId;
|
|
5909
|
+
this.logger = opts.logger;
|
|
5910
|
+
}
|
|
5911
|
+
/**
|
|
5912
|
+
* Emit a structured warning. Uses the configured Logger when available;
|
|
5913
|
+
* falls back to console.warn(JSON) so warnings are never silently dropped
|
|
5914
|
+
* during early boot (before a Logger is constructed).
|
|
5915
|
+
*/
|
|
5916
|
+
logWarn(msg, ctx) {
|
|
5917
|
+
if (this.logger) {
|
|
5918
|
+
this.logger.warn(msg, ctx);
|
|
5919
|
+
} else {
|
|
5920
|
+
console.warn(JSON.stringify({ ...ctx, message: msg, timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
|
|
5921
|
+
}
|
|
5752
5922
|
}
|
|
5753
5923
|
async load(opts = {}) {
|
|
5754
5924
|
let cfg = { ...BEHAVIOR_DEFAULTS };
|
|
@@ -5761,7 +5931,14 @@ var DefaultConfigLoader = class {
|
|
|
5761
5931
|
]);
|
|
5762
5932
|
cfg = deepMerge2(cfg, global);
|
|
5763
5933
|
cfg = deepMerge2(cfg, local);
|
|
5764
|
-
cfg = deepMerge2(
|
|
5934
|
+
cfg = deepMerge2(
|
|
5935
|
+
cfg,
|
|
5936
|
+
stripUnsafeInProjectFields(
|
|
5937
|
+
inProject,
|
|
5938
|
+
this.paths.inProjectConfig,
|
|
5939
|
+
this.logger ? (msg) => this.logger.warn(msg) : void 0
|
|
5940
|
+
)
|
|
5941
|
+
);
|
|
5765
5942
|
for (const [key, fn] of Object.entries(ENV_MAP)) {
|
|
5766
5943
|
const v = process.env[key];
|
|
5767
5944
|
if (v) fn(cfg, v);
|
|
@@ -5778,14 +5955,9 @@ var DefaultConfigLoader = class {
|
|
|
5778
5955
|
cfg = deepMerge2(cfg, patch);
|
|
5779
5956
|
}
|
|
5780
5957
|
} catch (err) {
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
event: "config.source_load_failed",
|
|
5785
|
-
source: src.name,
|
|
5786
|
-
message: toErrorMessage(err),
|
|
5787
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5788
|
-
})
|
|
5958
|
+
this.logWarn(
|
|
5959
|
+
"Config source load failed",
|
|
5960
|
+
{ event: "config.source_load_failed", source: src.name, message: toErrorMessage(err) }
|
|
5789
5961
|
);
|
|
5790
5962
|
}
|
|
5791
5963
|
}
|
|
@@ -5814,7 +5986,7 @@ var DefaultConfigLoader = class {
|
|
|
5814
5986
|
}
|
|
5815
5987
|
}
|
|
5816
5988
|
this.validateBehavior(cfg);
|
|
5817
|
-
if (this.strict) {
|
|
5989
|
+
if (this.strict && !opts.skipIdentityValidation) {
|
|
5818
5990
|
this.validateIdentity(cfg);
|
|
5819
5991
|
}
|
|
5820
5992
|
return Object.freeze(cfg);
|
|
@@ -5826,7 +5998,7 @@ var DefaultConfigLoader = class {
|
|
|
5826
5998
|
await withFileLock(fp, async () => {
|
|
5827
5999
|
let parsed;
|
|
5828
6000
|
try {
|
|
5829
|
-
const raw = await
|
|
6001
|
+
const raw = await fs5.readFile(fp, "utf8");
|
|
5830
6002
|
const result = safeParse(raw);
|
|
5831
6003
|
if (!result.ok || !isPlainRecord(result.value)) {
|
|
5832
6004
|
return;
|
|
@@ -5845,14 +6017,9 @@ var DefaultConfigLoader = class {
|
|
|
5845
6017
|
durationMs: Date.now() - t0,
|
|
5846
6018
|
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
5847
6019
|
});
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
event: "config.defaults_read_failed",
|
|
5852
|
-
path: fp,
|
|
5853
|
-
message: toErrorMessage(err),
|
|
5854
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5855
|
-
})
|
|
6020
|
+
this.logWarn(
|
|
6021
|
+
"Config defaults read failed",
|
|
6022
|
+
{ event: "config.defaults_read_failed", path: fp, message: toErrorMessage(err) }
|
|
5856
6023
|
);
|
|
5857
6024
|
return;
|
|
5858
6025
|
}
|
|
@@ -5886,14 +6053,9 @@ var DefaultConfigLoader = class {
|
|
|
5886
6053
|
durationMs: Date.now() - t0,
|
|
5887
6054
|
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
5888
6055
|
});
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
event: "config.defaults_write_failed",
|
|
5893
|
-
path: fp,
|
|
5894
|
-
message: toErrorMessage(err),
|
|
5895
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5896
|
-
})
|
|
6056
|
+
this.logWarn(
|
|
6057
|
+
"Config defaults write failed",
|
|
6058
|
+
{ event: "config.defaults_write_failed", path: fp, message: toErrorMessage(err) }
|
|
5897
6059
|
);
|
|
5898
6060
|
}
|
|
5899
6061
|
}
|
|
@@ -5945,7 +6107,7 @@ var DefaultConfigLoader = class {
|
|
|
5945
6107
|
const fp = this.paths.syncConfig;
|
|
5946
6108
|
const t0 = Date.now();
|
|
5947
6109
|
try {
|
|
5948
|
-
const raw = await
|
|
6110
|
+
const raw = await fs5.readFile(fp, "utf8");
|
|
5949
6111
|
const parsed = safeParse(raw);
|
|
5950
6112
|
if (!parsed.ok || !parsed.value) {
|
|
5951
6113
|
this.events?.emit("storage.read", {
|
|
@@ -5996,13 +6158,9 @@ var DefaultConfigLoader = class {
|
|
|
5996
6158
|
error: storageErrorString(err),
|
|
5997
6159
|
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
5998
6160
|
});
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
event: "config.sync_load_failed",
|
|
6003
|
-
message: toErrorMessage(err),
|
|
6004
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6005
|
-
})
|
|
6161
|
+
this.logWarn(
|
|
6162
|
+
"Config sync load failed",
|
|
6163
|
+
{ event: "config.sync_load_failed", message: toErrorMessage(err) }
|
|
6006
6164
|
);
|
|
6007
6165
|
return null;
|
|
6008
6166
|
}
|
|
@@ -6011,7 +6169,7 @@ var DefaultConfigLoader = class {
|
|
|
6011
6169
|
const t0 = Date.now();
|
|
6012
6170
|
let mtimeMs = null;
|
|
6013
6171
|
try {
|
|
6014
|
-
const stat13 = await
|
|
6172
|
+
const stat13 = await fs5.stat(file);
|
|
6015
6173
|
mtimeMs = stat13.mtimeMs;
|
|
6016
6174
|
const cached = this.jsonCache.get(file);
|
|
6017
6175
|
if (cached && cached.mtimeMs === mtimeMs) {
|
|
@@ -6032,20 +6190,15 @@ var DefaultConfigLoader = class {
|
|
|
6032
6190
|
error: storageErrorString(err),
|
|
6033
6191
|
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
6034
6192
|
});
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
event: "config.read_failed",
|
|
6039
|
-
path: file,
|
|
6040
|
-
message: toErrorMessage(err),
|
|
6041
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6042
|
-
})
|
|
6193
|
+
this.logWarn(
|
|
6194
|
+
"Config read failed (stat)",
|
|
6195
|
+
{ event: "config.read_failed", path: file, message: toErrorMessage(err) }
|
|
6043
6196
|
);
|
|
6044
6197
|
return {};
|
|
6045
6198
|
}
|
|
6046
6199
|
let raw;
|
|
6047
6200
|
try {
|
|
6048
|
-
raw = await
|
|
6201
|
+
raw = await fs5.readFile(file, "utf8");
|
|
6049
6202
|
} catch (err) {
|
|
6050
6203
|
if (err.code !== "ENOENT") {
|
|
6051
6204
|
this.events?.emit("storage.read", {
|
|
@@ -6058,14 +6211,9 @@ var DefaultConfigLoader = class {
|
|
|
6058
6211
|
error: storageErrorString(err),
|
|
6059
6212
|
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
6060
6213
|
});
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
event: "config.read_failed",
|
|
6065
|
-
path: file,
|
|
6066
|
-
message: toErrorMessage(err),
|
|
6067
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6068
|
-
})
|
|
6214
|
+
this.logWarn(
|
|
6215
|
+
"Config read failed (read)",
|
|
6216
|
+
{ event: "config.read_failed", path: file, message: toErrorMessage(err) }
|
|
6069
6217
|
);
|
|
6070
6218
|
}
|
|
6071
6219
|
this.jsonCache.set(file, { mtimeMs: null, value: {} });
|
|
@@ -6083,14 +6231,9 @@ var DefaultConfigLoader = class {
|
|
|
6083
6231
|
error: "parse error or empty file",
|
|
6084
6232
|
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
6085
6233
|
});
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
event: "config.parse_failed",
|
|
6090
|
-
path: file,
|
|
6091
|
-
message: "invalid JSON \u2014 falling back to defaults for this layer",
|
|
6092
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6093
|
-
})
|
|
6234
|
+
this.logWarn(
|
|
6235
|
+
"Config parse failed \u2014 falling back to defaults",
|
|
6236
|
+
{ event: "config.parse_failed", path: file }
|
|
6094
6237
|
);
|
|
6095
6238
|
return {};
|
|
6096
6239
|
}
|
|
@@ -6137,8 +6280,9 @@ var DefaultConfigLoader = class {
|
|
|
6137
6280
|
}
|
|
6138
6281
|
if (c.mode !== void 0 && !isContextWindowModeId(c.mode)) {
|
|
6139
6282
|
const known = listContextWindowModes().map((m) => m.id).join(", ");
|
|
6140
|
-
|
|
6141
|
-
`
|
|
6283
|
+
this.logWarn(
|
|
6284
|
+
`Ignoring unknown context.mode "${c.mode}" \u2014 falling back to "${DEFAULT_CONTEXT_WINDOW_MODE_ID}"`,
|
|
6285
|
+
{ event: "config.unknown_context_mode", mode: c.mode, known }
|
|
6142
6286
|
);
|
|
6143
6287
|
c.mode = DEFAULT_CONTEXT_WINDOW_MODE_ID;
|
|
6144
6288
|
}
|
|
@@ -6212,6 +6356,11 @@ function runConfigMigrations(input, targetVersion, migrations) {
|
|
|
6212
6356
|
return { config: current, applied, shouldPersist };
|
|
6213
6357
|
}
|
|
6214
6358
|
var DEFAULT_CONFIG_MIGRATIONS = [];
|
|
6359
|
+
|
|
6360
|
+
// src/storage/recovery-lock.ts
|
|
6361
|
+
import * as fsp7 from "node:fs/promises";
|
|
6362
|
+
import * as os2 from "node:os";
|
|
6363
|
+
import * as path14 from "node:path";
|
|
6215
6364
|
var LOCK_FILE = "active.json";
|
|
6216
6365
|
var DEFAULT_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
6217
6366
|
var RecoveryLock = class {
|
|
@@ -6222,9 +6371,9 @@ var RecoveryLock = class {
|
|
|
6222
6371
|
sessionStore;
|
|
6223
6372
|
probe;
|
|
6224
6373
|
constructor(opts) {
|
|
6225
|
-
this.file =
|
|
6374
|
+
this.file = path14.join(opts.dir, LOCK_FILE);
|
|
6226
6375
|
this.pid = opts.pid ?? process.pid;
|
|
6227
|
-
this.hostname = opts.hostname ??
|
|
6376
|
+
this.hostname = opts.hostname ?? os2.hostname();
|
|
6228
6377
|
this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
6229
6378
|
this.sessionStore = opts.sessionStore;
|
|
6230
6379
|
this.probe = opts.isPidAlive ?? defaultIsPidAlive;
|
|
@@ -6283,7 +6432,7 @@ var RecoveryLock = class {
|
|
|
6283
6432
|
* null return before calling this.
|
|
6284
6433
|
*/
|
|
6285
6434
|
async write(sessionId) {
|
|
6286
|
-
await ensureDir(
|
|
6435
|
+
await ensureDir(path14.dirname(this.file));
|
|
6287
6436
|
const lock = {
|
|
6288
6437
|
v: 1,
|
|
6289
6438
|
sessionId,
|
|
@@ -6292,7 +6441,7 @@ var RecoveryLock = class {
|
|
|
6292
6441
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6293
6442
|
};
|
|
6294
6443
|
try {
|
|
6295
|
-
await
|
|
6444
|
+
await fsp7.writeFile(this.file, JSON.stringify(lock), { flag: "wx", mode: 384 });
|
|
6296
6445
|
} catch (err) {
|
|
6297
6446
|
const code = err.code;
|
|
6298
6447
|
if (code === "EEXIST") {
|
|
@@ -6308,7 +6457,7 @@ var RecoveryLock = class {
|
|
|
6308
6457
|
*/
|
|
6309
6458
|
async clear() {
|
|
6310
6459
|
try {
|
|
6311
|
-
await
|
|
6460
|
+
await fsp7.unlink(this.file);
|
|
6312
6461
|
} catch (err) {
|
|
6313
6462
|
const code = err.code;
|
|
6314
6463
|
if (code === "ENOENT") return;
|
|
@@ -6318,7 +6467,7 @@ var RecoveryLock = class {
|
|
|
6318
6467
|
async readLock() {
|
|
6319
6468
|
let raw;
|
|
6320
6469
|
try {
|
|
6321
|
-
raw = await
|
|
6470
|
+
raw = await fsp7.readFile(this.file, "utf8");
|
|
6322
6471
|
} catch (err) {
|
|
6323
6472
|
const code = err.code;
|
|
6324
6473
|
if (code === "ENOENT") return null;
|
|
@@ -6349,6 +6498,9 @@ function defaultIsPidAlive(pid) {
|
|
|
6349
6498
|
return false;
|
|
6350
6499
|
}
|
|
6351
6500
|
}
|
|
6501
|
+
|
|
6502
|
+
// src/storage/session-reader.ts
|
|
6503
|
+
import * as fs6 from "node:fs/promises";
|
|
6352
6504
|
var DefaultSessionReader = class _DefaultSessionReader {
|
|
6353
6505
|
store;
|
|
6354
6506
|
eventCache = /* @__PURE__ */ new Map();
|
|
@@ -6366,7 +6518,7 @@ var DefaultSessionReader = class _DefaultSessionReader {
|
|
|
6366
6518
|
const sessionPath = sessionScopedPath(rootDir, sessionId, ".jsonl");
|
|
6367
6519
|
let mtimeMs = null;
|
|
6368
6520
|
try {
|
|
6369
|
-
const stat13 = await
|
|
6521
|
+
const stat13 = await fs6.stat(sessionPath);
|
|
6370
6522
|
mtimeMs = stat13.mtimeMs;
|
|
6371
6523
|
} catch {
|
|
6372
6524
|
this.eventCache.delete(sessionId);
|
|
@@ -6686,6 +6838,8 @@ function renderMarkdown(meta, events) {
|
|
|
6686
6838
|
lines.push("");
|
|
6687
6839
|
break;
|
|
6688
6840
|
}
|
|
6841
|
+
default:
|
|
6842
|
+
break;
|
|
6689
6843
|
}
|
|
6690
6844
|
}
|
|
6691
6845
|
return lines.join("\n");
|
|
@@ -6719,10 +6873,16 @@ function renderPlainText(meta, events) {
|
|
|
6719
6873
|
case "error":
|
|
6720
6874
|
lines.push(`[${e.ts}] ERROR (${e.phase}): ${e.message}`);
|
|
6721
6875
|
break;
|
|
6876
|
+
default:
|
|
6877
|
+
break;
|
|
6722
6878
|
}
|
|
6723
6879
|
}
|
|
6724
6880
|
return lines.join("\n");
|
|
6725
6881
|
}
|
|
6882
|
+
|
|
6883
|
+
// src/storage/annotations-store.ts
|
|
6884
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
6885
|
+
import * as fs7 from "node:fs/promises";
|
|
6726
6886
|
var FILE_VERSION = 1;
|
|
6727
6887
|
var MAX_TEXT_LENGTH = 2e3;
|
|
6728
6888
|
var MAX_ANNOTATIONS = 1e3;
|
|
@@ -6730,12 +6890,14 @@ var AnnotationsStore = class {
|
|
|
6730
6890
|
dir;
|
|
6731
6891
|
events;
|
|
6732
6892
|
traceId;
|
|
6893
|
+
maxAnnotations;
|
|
6733
6894
|
/** Per-session write queue. Created lazily on first add. */
|
|
6734
6895
|
writeChains = /* @__PURE__ */ new Map();
|
|
6735
6896
|
constructor(opts) {
|
|
6736
6897
|
this.dir = opts.dir;
|
|
6737
6898
|
this.events = opts.events;
|
|
6738
6899
|
this.traceId = opts.traceId;
|
|
6900
|
+
this.maxAnnotations = opts.maxAnnotations ?? MAX_ANNOTATIONS;
|
|
6739
6901
|
}
|
|
6740
6902
|
// ── Reads ──────────────────────────────────────────────────────────────
|
|
6741
6903
|
/**
|
|
@@ -6817,7 +6979,7 @@ var AnnotationsStore = class {
|
|
|
6817
6979
|
});
|
|
6818
6980
|
}
|
|
6819
6981
|
const annotation = {
|
|
6820
|
-
id:
|
|
6982
|
+
id: randomUUID3(),
|
|
6821
6983
|
sessionId: input.sessionId,
|
|
6822
6984
|
atEventIndex: input.atEventIndex,
|
|
6823
6985
|
authorId: input.authorId,
|
|
@@ -6833,12 +6995,12 @@ var AnnotationsStore = class {
|
|
|
6833
6995
|
await withFileLock(fp, async () => {
|
|
6834
6996
|
const all = await this.list(input.sessionId);
|
|
6835
6997
|
all.push(annotation);
|
|
6836
|
-
if (all.length >
|
|
6998
|
+
if (all.length > this.maxAnnotations) {
|
|
6837
6999
|
const sorted = all.map((a, i) => ({ a, i })).sort((x, y) => {
|
|
6838
7000
|
if (x.a.resolved !== y.a.resolved) return x.a.resolved ? 1 : -1;
|
|
6839
7001
|
return x.a.createdAt.localeCompare(y.a.createdAt);
|
|
6840
7002
|
});
|
|
6841
|
-
const evictCount = all.length -
|
|
7003
|
+
const evictCount = all.length - this.maxAnnotations;
|
|
6842
7004
|
const toEvict = new Set(sorted.slice(0, evictCount).map((s) => s.a.id));
|
|
6843
7005
|
const kept = all.filter((a) => !toEvict.has(a.id));
|
|
6844
7006
|
await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: kept });
|
|
@@ -6947,7 +7109,7 @@ var AnnotationsStore = class {
|
|
|
6947
7109
|
const fp = this.filePath(sessionId);
|
|
6948
7110
|
let raw;
|
|
6949
7111
|
try {
|
|
6950
|
-
raw = await
|
|
7112
|
+
raw = await fs7.readFile(fp, "utf8");
|
|
6951
7113
|
} catch (err) {
|
|
6952
7114
|
if (err.code === "ENOENT") return null;
|
|
6953
7115
|
throw err;
|
|
@@ -6982,6 +7144,13 @@ var AnnotationsStore = class {
|
|
|
6982
7144
|
return next;
|
|
6983
7145
|
}
|
|
6984
7146
|
};
|
|
7147
|
+
|
|
7148
|
+
// src/storage/replay-log-store.ts
|
|
7149
|
+
import * as fs8 from "node:fs/promises";
|
|
7150
|
+
import * as path15 from "node:path";
|
|
7151
|
+
|
|
7152
|
+
// src/replay/hash.ts
|
|
7153
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
6985
7154
|
function stableStringify(value) {
|
|
6986
7155
|
return JSON.stringify(sortKeys(value));
|
|
6987
7156
|
}
|
|
@@ -7010,7 +7179,7 @@ function hashRequest(request) {
|
|
|
7010
7179
|
toolChoice: request.toolChoice
|
|
7011
7180
|
};
|
|
7012
7181
|
const json = stableStringify(payload);
|
|
7013
|
-
const digest =
|
|
7182
|
+
const digest = createHash5("sha256").update(json, "utf8").digest("hex");
|
|
7014
7183
|
return `sha256:${digest}`;
|
|
7015
7184
|
}
|
|
7016
7185
|
|
|
@@ -7022,6 +7191,7 @@ function storageErrorString2(err) {
|
|
|
7022
7191
|
}
|
|
7023
7192
|
return String(err);
|
|
7024
7193
|
}
|
|
7194
|
+
var FILE_VERSION2 = 1;
|
|
7025
7195
|
var DEFAULT_MAX_ENTRIES = 1e3;
|
|
7026
7196
|
var ReplayLogStore = class {
|
|
7027
7197
|
dir;
|
|
@@ -7066,12 +7236,12 @@ var ReplayLogStore = class {
|
|
|
7066
7236
|
const line = JSON.stringify(entry) + "\n";
|
|
7067
7237
|
let offset2 = 0;
|
|
7068
7238
|
try {
|
|
7069
|
-
const stat13 = await
|
|
7239
|
+
const stat13 = await fs8.stat(fp);
|
|
7070
7240
|
offset2 = stat13.size;
|
|
7071
7241
|
} catch (err) {
|
|
7072
7242
|
if (err.code !== "ENOENT") throw err;
|
|
7073
7243
|
}
|
|
7074
|
-
await
|
|
7244
|
+
await fs8.appendFile(fp, line, "utf8");
|
|
7075
7245
|
cache.set(hash, { entry, offset: offset2, length: Buffer.byteLength(line, "utf8") });
|
|
7076
7246
|
this.diskCount.set(input.sessionId, currentCount + 1);
|
|
7077
7247
|
this.events?.emit("storage.write", {
|
|
@@ -7199,7 +7369,7 @@ var ReplayLogStore = class {
|
|
|
7199
7369
|
const scan = async (dir, prefix, depth) => {
|
|
7200
7370
|
let entries;
|
|
7201
7371
|
try {
|
|
7202
|
-
entries = await
|
|
7372
|
+
entries = await fs8.readdir(dir, { withFileTypes: true });
|
|
7203
7373
|
} catch (err) {
|
|
7204
7374
|
if (depth === 0 && err.code !== "ENOENT") {
|
|
7205
7375
|
console.warn(JSON.stringify({
|
|
@@ -7215,13 +7385,13 @@ var ReplayLogStore = class {
|
|
|
7215
7385
|
for (const entry of entries) {
|
|
7216
7386
|
if (entry.name.startsWith(".")) continue;
|
|
7217
7387
|
if (entry.isDirectory()) {
|
|
7218
|
-
if (depth === 0) await scan(
|
|
7388
|
+
if (depth === 0) await scan(path15.join(dir, entry.name), entry.name, depth + 1);
|
|
7219
7389
|
continue;
|
|
7220
7390
|
}
|
|
7221
7391
|
if (!entry.isFile() || !entry.name.endsWith(".replay.jsonl")) continue;
|
|
7222
7392
|
const base = entry.name.slice(0, -".replay.jsonl".length);
|
|
7223
7393
|
const sessionId = prefix ? `${prefix}/${base}` : base;
|
|
7224
|
-
const fp =
|
|
7394
|
+
const fp = path15.join(dir, entry.name);
|
|
7225
7395
|
out.push({
|
|
7226
7396
|
sessionId,
|
|
7227
7397
|
entryCount: await this.countEntries(fp),
|
|
@@ -7237,7 +7407,7 @@ var ReplayLogStore = class {
|
|
|
7237
7407
|
return sessionScopedPath(this.dir, sessionId, ".replay.jsonl");
|
|
7238
7408
|
}
|
|
7239
7409
|
async countEntries(filePath) {
|
|
7240
|
-
const handle = await
|
|
7410
|
+
const handle = await fs8.open(filePath, "r");
|
|
7241
7411
|
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
7242
7412
|
let count = 0;
|
|
7243
7413
|
let hasNonWhitespace2 = false;
|
|
@@ -7278,7 +7448,7 @@ var ReplayLogStore = class {
|
|
|
7278
7448
|
async readAll(sessionId) {
|
|
7279
7449
|
const fp = this.filePath(sessionId);
|
|
7280
7450
|
try {
|
|
7281
|
-
const raw = await
|
|
7451
|
+
const raw = await fs8.readFile(fp, "utf8");
|
|
7282
7452
|
const out = [];
|
|
7283
7453
|
for (const line of raw.split("\n")) {
|
|
7284
7454
|
if (!line.trim()) continue;
|
|
@@ -7306,6 +7476,7 @@ var ReplayLogStore = class {
|
|
|
7306
7476
|
durationMs,
|
|
7307
7477
|
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
7308
7478
|
});
|
|
7479
|
+
void FILE_VERSION2;
|
|
7309
7480
|
}
|
|
7310
7481
|
async ensureCache(sessionId) {
|
|
7311
7482
|
let cache = this.cache.get(sessionId);
|
|
@@ -7313,7 +7484,7 @@ var ReplayLogStore = class {
|
|
|
7313
7484
|
const fp = this.filePath(sessionId);
|
|
7314
7485
|
cache = /* @__PURE__ */ new Map();
|
|
7315
7486
|
try {
|
|
7316
|
-
const handle = await
|
|
7487
|
+
const handle = await fs8.open(fp, "r");
|
|
7317
7488
|
const CHUNK = 64 * 1024;
|
|
7318
7489
|
const buffer = Buffer.alloc(CHUNK);
|
|
7319
7490
|
let leftover = "";
|
|
@@ -7364,7 +7535,7 @@ var ReplayLogStore = class {
|
|
|
7364
7535
|
async hydrateEntry(sessionId, hash, location) {
|
|
7365
7536
|
if (location.entry) return location.entry;
|
|
7366
7537
|
const fp = this.filePath(sessionId);
|
|
7367
|
-
const handle = await
|
|
7538
|
+
const handle = await fs8.open(fp, "r");
|
|
7368
7539
|
try {
|
|
7369
7540
|
const buffer = Buffer.alloc(location.length);
|
|
7370
7541
|
const { bytesRead } = await handle.read(buffer, 0, location.length, location.offset);
|
|
@@ -7389,6 +7560,10 @@ var ReplayLogStore = class {
|
|
|
7389
7560
|
return next;
|
|
7390
7561
|
}
|
|
7391
7562
|
};
|
|
7563
|
+
|
|
7564
|
+
// src/storage/session-recovery.ts
|
|
7565
|
+
import * as fs9 from "node:fs/promises";
|
|
7566
|
+
import * as path16 from "node:path";
|
|
7392
7567
|
var SessionRecovery = class {
|
|
7393
7568
|
constructor(dir) {
|
|
7394
7569
|
this.dir = dir;
|
|
@@ -7414,7 +7589,7 @@ var SessionRecovery = class {
|
|
|
7414
7589
|
const fp = this.filePath(sessionId);
|
|
7415
7590
|
let stat13;
|
|
7416
7591
|
try {
|
|
7417
|
-
stat13 = await
|
|
7592
|
+
stat13 = await fs9.stat(fp);
|
|
7418
7593
|
} catch (err) {
|
|
7419
7594
|
if (err.code === "ENOENT") return null;
|
|
7420
7595
|
return null;
|
|
@@ -7448,7 +7623,7 @@ var SessionRecovery = class {
|
|
|
7448
7623
|
const fp = this.filePath(sessionId);
|
|
7449
7624
|
let raw;
|
|
7450
7625
|
try {
|
|
7451
|
-
raw = await
|
|
7626
|
+
raw = await fs9.readFile(fp, "utf8");
|
|
7452
7627
|
} catch (err) {
|
|
7453
7628
|
if (err.code === "ENOENT") return null;
|
|
7454
7629
|
return null;
|
|
@@ -7493,7 +7668,7 @@ var SessionRecovery = class {
|
|
|
7493
7668
|
const collect = async (dir, prefix, depth) => {
|
|
7494
7669
|
let entries;
|
|
7495
7670
|
try {
|
|
7496
|
-
entries = await
|
|
7671
|
+
entries = await fs9.readdir(dir, { withFileTypes: true });
|
|
7497
7672
|
} catch {
|
|
7498
7673
|
return;
|
|
7499
7674
|
}
|
|
@@ -7503,7 +7678,7 @@ var SessionRecovery = class {
|
|
|
7503
7678
|
continue;
|
|
7504
7679
|
if (entry.isDirectory()) {
|
|
7505
7680
|
if (depth === 0) {
|
|
7506
|
-
await collect(
|
|
7681
|
+
await collect(path16.join(dir, entry.name), entry.name, depth + 1);
|
|
7507
7682
|
}
|
|
7508
7683
|
continue;
|
|
7509
7684
|
}
|
|
@@ -7544,7 +7719,7 @@ function hasNonWhitespace(line) {
|
|
|
7544
7719
|
}
|
|
7545
7720
|
async function scanLatestLifecycleBoundary(filePath, size) {
|
|
7546
7721
|
const CHUNK_SIZE = 64 * 1024;
|
|
7547
|
-
const handle = await
|
|
7722
|
+
const handle = await fs9.open(filePath, "r");
|
|
7548
7723
|
let position = size;
|
|
7549
7724
|
let laterLineFragment = Buffer.alloc(0);
|
|
7550
7725
|
let latestBoundary = null;
|
|
@@ -7580,6 +7755,10 @@ async function scanLatestLifecycleBoundary(filePath, size) {
|
|
|
7580
7755
|
await handle.close();
|
|
7581
7756
|
}
|
|
7582
7757
|
}
|
|
7758
|
+
|
|
7759
|
+
// src/storage/tool-audit-log.ts
|
|
7760
|
+
import { createHash as createHash6, randomUUID as randomUUID4 } from "node:crypto";
|
|
7761
|
+
import * as fs10 from "node:fs/promises";
|
|
7583
7762
|
var GENESIS_PREV = "0".repeat(64);
|
|
7584
7763
|
var DEFAULT_FSYNC_EVERY = 100;
|
|
7585
7764
|
var ToolAuditLog = class {
|
|
@@ -7623,7 +7802,7 @@ var ToolAuditLog = class {
|
|
|
7623
7802
|
const tip = await this._resolveChainTip(input.sessionId, fp);
|
|
7624
7803
|
const prevHash = tip.prevHash;
|
|
7625
7804
|
const index = tip.nextIndex;
|
|
7626
|
-
const id =
|
|
7805
|
+
const id = randomUUID4();
|
|
7627
7806
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
7628
7807
|
const content = {
|
|
7629
7808
|
id,
|
|
@@ -7636,7 +7815,7 @@ var ToolAuditLog = class {
|
|
|
7636
7815
|
isError: input.isError,
|
|
7637
7816
|
index
|
|
7638
7817
|
};
|
|
7639
|
-
const hash =
|
|
7818
|
+
const hash = createHash6("sha256").update(stableStringify2(content), "utf8").digest("hex");
|
|
7640
7819
|
entry = {
|
|
7641
7820
|
id,
|
|
7642
7821
|
ts,
|
|
@@ -7649,9 +7828,9 @@ var ToolAuditLog = class {
|
|
|
7649
7828
|
isError: input.isError,
|
|
7650
7829
|
index
|
|
7651
7830
|
};
|
|
7652
|
-
await
|
|
7831
|
+
await fs10.appendFile(fp, JSON.stringify(entry) + "\n", "utf8");
|
|
7653
7832
|
try {
|
|
7654
|
-
const st = await
|
|
7833
|
+
const st = await fs10.stat(fp);
|
|
7655
7834
|
this.tailStat.set(input.sessionId, { mtimeMs: st.mtimeMs, size: st.size });
|
|
7656
7835
|
} catch {
|
|
7657
7836
|
}
|
|
@@ -7698,7 +7877,7 @@ var ToolAuditLog = class {
|
|
|
7698
7877
|
const cachedStat = this.tailStat.get(sessionId);
|
|
7699
7878
|
if (cachedHash !== void 0 && cachedIndex !== void 0 && cachedStat) {
|
|
7700
7879
|
try {
|
|
7701
|
-
const st = await
|
|
7880
|
+
const st = await fs10.stat(fp);
|
|
7702
7881
|
if (st.mtimeMs === cachedStat.mtimeMs && st.size === cachedStat.size) {
|
|
7703
7882
|
return { prevHash: cachedHash, nextIndex: cachedIndex };
|
|
7704
7883
|
}
|
|
@@ -7719,7 +7898,7 @@ var ToolAuditLog = class {
|
|
|
7719
7898
|
this.tailHash.set(sessionId, prevHash);
|
|
7720
7899
|
this.tailIndex.set(sessionId, nextIndex);
|
|
7721
7900
|
try {
|
|
7722
|
-
const st = await
|
|
7901
|
+
const st = await fs10.stat(fp);
|
|
7723
7902
|
this.tailStat.set(sessionId, { mtimeMs: st.mtimeMs, size: st.size });
|
|
7724
7903
|
} catch {
|
|
7725
7904
|
}
|
|
@@ -7778,7 +7957,7 @@ var ToolAuditLog = class {
|
|
|
7778
7957
|
isError: e.isError,
|
|
7779
7958
|
index: e.index
|
|
7780
7959
|
};
|
|
7781
|
-
const expectedHash =
|
|
7960
|
+
const expectedHash = createHash6("sha256").update(stableStringify2(content), "utf8").digest("hex");
|
|
7782
7961
|
if (expectedHash !== e.hash) {
|
|
7783
7962
|
return {
|
|
7784
7963
|
ok: false,
|
|
@@ -7840,7 +8019,7 @@ var ToolAuditLog = class {
|
|
|
7840
8019
|
async readAll(sessionId) {
|
|
7841
8020
|
const fp = this.filePath(sessionId);
|
|
7842
8021
|
try {
|
|
7843
|
-
const raw = await
|
|
8022
|
+
const raw = await fs10.readFile(fp, "utf8");
|
|
7844
8023
|
const out = [];
|
|
7845
8024
|
for (const line of raw.split("\n")) {
|
|
7846
8025
|
if (!line.trim()) continue;
|
|
@@ -7878,7 +8057,7 @@ var ToolAuditLog = class {
|
|
|
7878
8057
|
}
|
|
7879
8058
|
async sync(sessionId, fp) {
|
|
7880
8059
|
try {
|
|
7881
|
-
const fh = await
|
|
8060
|
+
const fh = await fs10.open(fp, "r+");
|
|
7882
8061
|
try {
|
|
7883
8062
|
await fh.sync();
|
|
7884
8063
|
} finally {
|
|
@@ -8014,10 +8193,17 @@ var SessionAnalyzer = class {
|
|
|
8014
8193
|
return last - first;
|
|
8015
8194
|
}
|
|
8016
8195
|
};
|
|
8196
|
+
|
|
8197
|
+
// src/session-registry.ts
|
|
8198
|
+
import * as fs11 from "node:fs/promises";
|
|
8199
|
+
import * as path17 from "node:path";
|
|
8200
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
8017
8201
|
var REGISTRY_FILE = "session-registry.json";
|
|
8018
8202
|
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
8019
8203
|
var STALE_TIMEOUT_MS = 3e4;
|
|
8020
8204
|
var CLOSING_GRACE_MS = 15e3;
|
|
8205
|
+
var LOST_GRACE_MS = 3e4;
|
|
8206
|
+
var AGENT_STALE_MS = 5 * 6e4;
|
|
8021
8207
|
var STALE_LOCK_MS = 1e4;
|
|
8022
8208
|
var STALE_TMP_MS = 6e4;
|
|
8023
8209
|
var MAX_STALE_TMP_FILES = 20;
|
|
@@ -8029,6 +8215,16 @@ function pidAlive(pid) {
|
|
|
8029
8215
|
return false;
|
|
8030
8216
|
}
|
|
8031
8217
|
}
|
|
8218
|
+
function parseRegistry(raw) {
|
|
8219
|
+
try {
|
|
8220
|
+
const parsed = JSON.parse(raw);
|
|
8221
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
8222
|
+
return parsed;
|
|
8223
|
+
}
|
|
8224
|
+
} catch {
|
|
8225
|
+
}
|
|
8226
|
+
return {};
|
|
8227
|
+
}
|
|
8032
8228
|
var SessionRegistry = class {
|
|
8033
8229
|
filePath;
|
|
8034
8230
|
heartbeatTimer = null;
|
|
@@ -8040,7 +8236,7 @@ var SessionRegistry = class {
|
|
|
8040
8236
|
*/
|
|
8041
8237
|
lastEntry = null;
|
|
8042
8238
|
constructor(globalRoot) {
|
|
8043
|
-
this.filePath =
|
|
8239
|
+
this.filePath = path17.join(globalRoot, REGISTRY_FILE);
|
|
8044
8240
|
}
|
|
8045
8241
|
// ── Public API ──────────────────────────────────────────────────────────
|
|
8046
8242
|
/**
|
|
@@ -8196,24 +8392,43 @@ var SessionRegistry = class {
|
|
|
8196
8392
|
}
|
|
8197
8393
|
async readAndPrune() {
|
|
8198
8394
|
try {
|
|
8199
|
-
const raw = await
|
|
8200
|
-
const registry =
|
|
8395
|
+
const raw = await fs11.readFile(this.filePath, "utf8");
|
|
8396
|
+
const registry = parseRegistry(raw);
|
|
8201
8397
|
const now = Date.now();
|
|
8202
8398
|
let pruned = false;
|
|
8203
8399
|
for (const [id, entry] of Object.entries(registry)) {
|
|
8204
|
-
const
|
|
8400
|
+
const heartbeatAt = Date.parse(entry.lastHeartbeatAt);
|
|
8401
|
+
if (!Number.isFinite(heartbeatAt)) {
|
|
8402
|
+
delete registry[id];
|
|
8403
|
+
pruned = true;
|
|
8404
|
+
continue;
|
|
8405
|
+
}
|
|
8406
|
+
const heartbeatAge = now - heartbeatAt;
|
|
8407
|
+
const agents = Array.isArray(entry.agents) ? entry.agents : [];
|
|
8408
|
+
const liveAgents = agents.filter((agent) => {
|
|
8409
|
+
if (agent.id === "leader") return true;
|
|
8410
|
+
const lastActivityAt = Date.parse(agent.lastActivityAt);
|
|
8411
|
+
return Number.isFinite(lastActivityAt) && now - lastActivityAt <= AGENT_STALE_MS;
|
|
8412
|
+
});
|
|
8413
|
+
if (liveAgents.length !== agents.length || entry.agentCount !== liveAgents.length) {
|
|
8414
|
+
entry.agents = liveAgents;
|
|
8415
|
+
entry.agentCount = liveAgents.length;
|
|
8416
|
+
pruned = true;
|
|
8417
|
+
}
|
|
8205
8418
|
if (entry.status === "closing" && heartbeatAge > CLOSING_GRACE_MS) {
|
|
8206
8419
|
delete registry[id];
|
|
8207
8420
|
pruned = true;
|
|
8208
8421
|
continue;
|
|
8209
8422
|
}
|
|
8210
|
-
if (heartbeatAge
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8423
|
+
if (heartbeatAge <= STALE_TIMEOUT_MS) continue;
|
|
8424
|
+
if (!pidAlive(entry.pid) || heartbeatAge > STALE_TIMEOUT_MS + LOST_GRACE_MS) {
|
|
8425
|
+
delete registry[id];
|
|
8426
|
+
pruned = true;
|
|
8427
|
+
continue;
|
|
8428
|
+
}
|
|
8429
|
+
if (entry.status !== "lost") {
|
|
8430
|
+
entry.status = "lost";
|
|
8431
|
+
pruned = true;
|
|
8217
8432
|
}
|
|
8218
8433
|
}
|
|
8219
8434
|
if (pruned) {
|
|
@@ -8230,11 +8445,11 @@ var SessionRegistry = class {
|
|
|
8230
8445
|
const retryDelayMs = 20;
|
|
8231
8446
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
8232
8447
|
try {
|
|
8233
|
-
await
|
|
8234
|
-
let lockHandle = await
|
|
8448
|
+
await fs11.mkdir(path17.dirname(this.filePath), { recursive: true });
|
|
8449
|
+
let lockHandle = await fs11.open(lockPath, "wx").catch(() => null);
|
|
8235
8450
|
if (!lockHandle) {
|
|
8236
8451
|
if (await this.breakStaleLock(lockPath)) {
|
|
8237
|
-
lockHandle = await
|
|
8452
|
+
lockHandle = await fs11.open(lockPath, "wx").catch(() => null);
|
|
8238
8453
|
}
|
|
8239
8454
|
if (!lockHandle) {
|
|
8240
8455
|
await new Promise((r) => setTimeout(r, retryDelayMs * (attempt + 1)));
|
|
@@ -8243,14 +8458,14 @@ var SessionRegistry = class {
|
|
|
8243
8458
|
}
|
|
8244
8459
|
try {
|
|
8245
8460
|
await lockHandle.writeFile(String(process.pid)).catch(() => void 0);
|
|
8246
|
-
const raw = await
|
|
8247
|
-
const registry =
|
|
8461
|
+
const raw = await fs11.readFile(this.filePath, "utf8").catch(() => "{}");
|
|
8462
|
+
const registry = parseRegistry(raw);
|
|
8248
8463
|
fn(registry);
|
|
8249
8464
|
await this.writeAtomicLocked(registry);
|
|
8250
8465
|
return;
|
|
8251
8466
|
} finally {
|
|
8252
8467
|
await lockHandle.close();
|
|
8253
|
-
await
|
|
8468
|
+
await fs11.unlink(lockPath).catch(() => void 0);
|
|
8254
8469
|
}
|
|
8255
8470
|
} catch {
|
|
8256
8471
|
return;
|
|
@@ -8267,16 +8482,16 @@ var SessionRegistry = class {
|
|
|
8267
8482
|
async breakStaleLock(lockPath) {
|
|
8268
8483
|
try {
|
|
8269
8484
|
const [stat13, content] = await Promise.all([
|
|
8270
|
-
|
|
8485
|
+
fs11.stat(lockPath),
|
|
8271
8486
|
/* v8 ignore start -- best-effort lock-content read; .catch only fires if the lock vanished */
|
|
8272
|
-
|
|
8487
|
+
fs11.readFile(lockPath, "utf8").catch(() => "")
|
|
8273
8488
|
/* v8 ignore stop */
|
|
8274
8489
|
]);
|
|
8275
8490
|
const ageMs = Date.now() - stat13.mtimeMs;
|
|
8276
8491
|
const ownerPid = Number.parseInt(content.trim(), 10);
|
|
8277
8492
|
const ownerDead = Number.isInteger(ownerPid) && ownerPid > 0 && ownerPid !== process.pid && !pidAlive(ownerPid);
|
|
8278
8493
|
if (ownerDead || ageMs > STALE_LOCK_MS) {
|
|
8279
|
-
await
|
|
8494
|
+
await fs11.unlink(lockPath).catch(() => void 0);
|
|
8280
8495
|
return true;
|
|
8281
8496
|
}
|
|
8282
8497
|
return false;
|
|
@@ -8294,35 +8509,41 @@ var SessionRegistry = class {
|
|
|
8294
8509
|
await this.writeAtomicFile(registry);
|
|
8295
8510
|
}
|
|
8296
8511
|
async writeAtomicFile(registry) {
|
|
8297
|
-
const tmp =
|
|
8298
|
-
|
|
8299
|
-
`.${
|
|
8512
|
+
const tmp = path17.join(
|
|
8513
|
+
path17.dirname(this.filePath),
|
|
8514
|
+
`.${path17.basename(this.filePath)}.${randomUUID5().slice(0, 8)}.tmp`
|
|
8300
8515
|
);
|
|
8301
8516
|
try {
|
|
8302
|
-
await
|
|
8303
|
-
|
|
8517
|
+
const handle = await fs11.open(tmp, "w");
|
|
8518
|
+
try {
|
|
8519
|
+
await handle.writeFile(JSON.stringify(registry, null, 2), "utf8");
|
|
8520
|
+
await handle.sync().catch(() => void 0);
|
|
8521
|
+
} finally {
|
|
8522
|
+
await handle.close();
|
|
8523
|
+
}
|
|
8524
|
+
await fs11.rename(tmp, this.filePath);
|
|
8304
8525
|
} catch (err) {
|
|
8305
|
-
await
|
|
8526
|
+
await fs11.unlink(tmp).catch(() => void 0);
|
|
8306
8527
|
throw err;
|
|
8307
8528
|
}
|
|
8308
8529
|
}
|
|
8309
8530
|
async pruneStaleTempFiles() {
|
|
8310
8531
|
try {
|
|
8311
|
-
const dir =
|
|
8312
|
-
const base =
|
|
8532
|
+
const dir = path17.dirname(this.filePath);
|
|
8533
|
+
const base = path17.basename(this.filePath);
|
|
8313
8534
|
const now = Date.now();
|
|
8314
8535
|
const stale = [];
|
|
8315
|
-
for (const name of await
|
|
8536
|
+
for (const name of await fs11.readdir(dir)) {
|
|
8316
8537
|
const isTemp = (name.startsWith(`${base}.`) || name.startsWith(`.${base}.`)) && name.endsWith(".tmp");
|
|
8317
8538
|
if (!isTemp) continue;
|
|
8318
|
-
const stat13 = await
|
|
8539
|
+
const stat13 = await fs11.stat(path17.join(dir, name)).catch(() => null);
|
|
8319
8540
|
if (!stat13) continue;
|
|
8320
8541
|
if (now - stat13.mtimeMs > STALE_TMP_MS) stale.push({ name, mtimeMs: stat13.mtimeMs });
|
|
8321
8542
|
}
|
|
8322
8543
|
stale.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
8323
8544
|
await Promise.all(
|
|
8324
8545
|
stale.slice(MAX_STALE_TMP_FILES).map(async ({ name }) => {
|
|
8325
|
-
await
|
|
8546
|
+
await fs11.unlink(path17.join(dir, name)).catch(() => void 0);
|
|
8326
8547
|
})
|
|
8327
8548
|
);
|
|
8328
8549
|
} catch {
|
|
@@ -8617,6 +8838,13 @@ var AgentStatusTracker = class {
|
|
|
8617
8838
|
if (this.agents.delete(p.subagentId)) this.flush();
|
|
8618
8839
|
})
|
|
8619
8840
|
);
|
|
8841
|
+
this.unsubscribers.push(
|
|
8842
|
+
on("subagent.removed", (_e, payload) => {
|
|
8843
|
+
const p = payload;
|
|
8844
|
+
if (!p?.subagentId) return;
|
|
8845
|
+
if (this.agents.delete(p.subagentId)) this.flush();
|
|
8846
|
+
})
|
|
8847
|
+
);
|
|
8620
8848
|
this.sweepTimer = setInterval(() => this.sweep(), AGENT_SWEEP_INTERVAL_MS);
|
|
8621
8849
|
if (typeof this.sweepTimer.unref === "function") this.sweepTimer.unref();
|
|
8622
8850
|
}
|
|
@@ -8729,6 +8957,10 @@ var AgentStatusTracker = class {
|
|
|
8729
8957
|
}
|
|
8730
8958
|
}
|
|
8731
8959
|
};
|
|
8960
|
+
|
|
8961
|
+
// src/fleet-notifier.ts
|
|
8962
|
+
import * as fs12 from "node:fs/promises";
|
|
8963
|
+
import * as path18 from "node:path";
|
|
8732
8964
|
var INSTANCES_FILE = "webui-instances.json";
|
|
8733
8965
|
var DISCOVERY_TTL_MS = 2500;
|
|
8734
8966
|
var COALESCE_MS = 50;
|
|
@@ -8743,7 +8975,7 @@ function pidAlive2(pid) {
|
|
|
8743
8975
|
}
|
|
8744
8976
|
}
|
|
8745
8977
|
function normRoot(root) {
|
|
8746
|
-
const resolved =
|
|
8978
|
+
const resolved = path18.resolve(root);
|
|
8747
8979
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
8748
8980
|
}
|
|
8749
8981
|
var FleetNotifier = class {
|
|
@@ -8790,7 +9022,7 @@ var FleetNotifier = class {
|
|
|
8790
9022
|
}
|
|
8791
9023
|
async discover() {
|
|
8792
9024
|
try {
|
|
8793
|
-
const raw = await
|
|
9025
|
+
const raw = await fs12.readFile(path18.join(this.baseDir, INSTANCES_FILE), "utf8");
|
|
8794
9026
|
const data = JSON.parse(raw);
|
|
8795
9027
|
const list = Array.isArray(data?.instances) ? data.instances : [];
|
|
8796
9028
|
return list.filter((i) => i && typeof i.httpPort === "number").filter((i) => i.pid !== this.selfPid).filter((i) => normRoot(i.projectRoot) === this.projectRoot).filter((i) => pidAlive2(i.pid)).map((i) => {
|
|
@@ -8808,6 +9040,10 @@ async function defaultPost(url) {
|
|
|
8808
9040
|
signal: AbortSignal.timeout(POST_TIMEOUT_MS)
|
|
8809
9041
|
});
|
|
8810
9042
|
}
|
|
9043
|
+
|
|
9044
|
+
// src/storage/session-rewinder.ts
|
|
9045
|
+
import * as fsp8 from "node:fs/promises";
|
|
9046
|
+
import * as path19 from "node:path";
|
|
8811
9047
|
var DefaultSessionRewinder = class {
|
|
8812
9048
|
constructor(sessionsDir, projectRoot) {
|
|
8813
9049
|
this.sessionsDir = sessionsDir;
|
|
@@ -8820,7 +9056,7 @@ var DefaultSessionRewinder = class {
|
|
|
8820
9056
|
}
|
|
8821
9057
|
async listCheckpoints(sessionId) {
|
|
8822
9058
|
const file = this.sessionFile(sessionId);
|
|
8823
|
-
const raw = await
|
|
9059
|
+
const raw = await fsp8.readFile(file, "utf8");
|
|
8824
9060
|
const events = parseEvents(raw);
|
|
8825
9061
|
const fileCountMap = /* @__PURE__ */ new Map();
|
|
8826
9062
|
for (const event of events) {
|
|
@@ -8845,7 +9081,7 @@ var DefaultSessionRewinder = class {
|
|
|
8845
9081
|
}
|
|
8846
9082
|
async rewindToCheckpoint(sessionId, checkpointIndex) {
|
|
8847
9083
|
const file = this.sessionFile(sessionId);
|
|
8848
|
-
const raw = await
|
|
9084
|
+
const raw = await fsp8.readFile(file, "utf8");
|
|
8849
9085
|
const events = parseEvents(raw);
|
|
8850
9086
|
let targetIdx = -1;
|
|
8851
9087
|
for (let i = 0; i < events.length; i++) {
|
|
@@ -8884,7 +9120,7 @@ var DefaultSessionRewinder = class {
|
|
|
8884
9120
|
}
|
|
8885
9121
|
async rewindLastN(sessionId, n) {
|
|
8886
9122
|
const file = this.sessionFile(sessionId);
|
|
8887
|
-
const raw = await
|
|
9123
|
+
const raw = await fsp8.readFile(file, "utf8");
|
|
8888
9124
|
const events = parseEvents(raw);
|
|
8889
9125
|
const checkpoints = [];
|
|
8890
9126
|
for (const event of events) {
|
|
@@ -8913,7 +9149,7 @@ var DefaultSessionRewinder = class {
|
|
|
8913
9149
|
}
|
|
8914
9150
|
async rewindToStart(sessionId) {
|
|
8915
9151
|
const file = this.sessionFile(sessionId);
|
|
8916
|
-
const raw = await
|
|
9152
|
+
const raw = await fsp8.readFile(file, "utf8");
|
|
8917
9153
|
const events = parseEvents(raw);
|
|
8918
9154
|
const allSnapshots = [];
|
|
8919
9155
|
for (const event of events) {
|
|
@@ -8948,10 +9184,10 @@ async function revertSnapshots(snapshots, projectRoot) {
|
|
|
8948
9184
|
for (const snapshot of [...snapshots].reverse()) {
|
|
8949
9185
|
for (const file of [...snapshot.files].reverse()) {
|
|
8950
9186
|
try {
|
|
8951
|
-
const absPath =
|
|
8952
|
-
const root =
|
|
8953
|
-
const rel =
|
|
8954
|
-
if (rel.startsWith("..") ||
|
|
9187
|
+
const absPath = path19.resolve(file.path);
|
|
9188
|
+
const root = path19.resolve(projectRoot);
|
|
9189
|
+
const rel = path19.relative(root, absPath);
|
|
9190
|
+
if (rel.startsWith("..") || path19.isAbsolute(rel)) {
|
|
8955
9191
|
errors.push(`${file.path}: path resolves outside project root \u2014 skipping`);
|
|
8956
9192
|
continue;
|
|
8957
9193
|
}
|
|
@@ -8961,7 +9197,7 @@ async function revertSnapshots(snapshots, projectRoot) {
|
|
|
8961
9197
|
revertedFiles.push(file.path);
|
|
8962
9198
|
}
|
|
8963
9199
|
} else if (file.action === "created") {
|
|
8964
|
-
await
|
|
9200
|
+
await fsp8.unlink(file.path);
|
|
8965
9201
|
revertedFiles.push(file.path);
|
|
8966
9202
|
} else if (file.action === "modified") {
|
|
8967
9203
|
if (file.before !== null) {
|
|
@@ -8976,11 +9212,14 @@ async function revertSnapshots(snapshots, projectRoot) {
|
|
|
8976
9212
|
}
|
|
8977
9213
|
return { revertedFiles, errors };
|
|
8978
9214
|
}
|
|
9215
|
+
|
|
9216
|
+
// src/storage/todos-checkpoint.ts
|
|
9217
|
+
import * as fsp9 from "node:fs/promises";
|
|
8979
9218
|
async function loadTodosCheckpoint(filePath, events, traceId) {
|
|
8980
9219
|
const t0 = Date.now();
|
|
8981
9220
|
let raw;
|
|
8982
9221
|
try {
|
|
8983
|
-
raw = await
|
|
9222
|
+
raw = await fsp9.readFile(filePath, "utf8");
|
|
8984
9223
|
} catch (err) {
|
|
8985
9224
|
events?.emit("storage.error", {
|
|
8986
9225
|
sessionId: traceId ?? "~boot~",
|
|
@@ -9034,7 +9273,7 @@ async function loadTodosCheckpoint(filePath, events, traceId) {
|
|
|
9034
9273
|
return null;
|
|
9035
9274
|
}
|
|
9036
9275
|
}
|
|
9037
|
-
async function saveTodosCheckpoint(filePath, sessionId, todos, events, traceId) {
|
|
9276
|
+
async function saveTodosCheckpoint(filePath, sessionId, todos, events, traceId, warn) {
|
|
9038
9277
|
const t0 = Date.now();
|
|
9039
9278
|
const payload = {
|
|
9040
9279
|
version: 1,
|
|
@@ -9063,28 +9302,17 @@ async function saveTodosCheckpoint(filePath, sessionId, todos, events, traceId)
|
|
|
9063
9302
|
error: toErrorMessage(err),
|
|
9064
9303
|
recoverable: false
|
|
9065
9304
|
});
|
|
9066
|
-
console.warn(JSON.stringify({
|
|
9067
|
-
level: "warn",
|
|
9068
|
-
event: "todos_checkpoint.save_failed",
|
|
9069
|
-
message: toErrorMessage(err),
|
|
9070
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9071
|
-
}));
|
|
9305
|
+
(warn ?? ((m) => console.warn(JSON.stringify({ level: "warn", event: "todos_checkpoint.save_failed", message: m, timestamp: (/* @__PURE__ */ new Date()).toISOString() }))))(toErrorMessage(err));
|
|
9072
9306
|
}
|
|
9073
9307
|
}
|
|
9074
|
-
function attachTodosCheckpoint(state, filePath, sessionId, events, traceId) {
|
|
9308
|
+
function attachTodosCheckpoint(state, filePath, sessionId, events, traceId, warn) {
|
|
9075
9309
|
let timer = null;
|
|
9076
9310
|
let pending = null;
|
|
9077
9311
|
let writeChain = Promise.resolve();
|
|
9078
9312
|
const enqueueWrite = (todos) => {
|
|
9079
9313
|
writeChain = writeChain.then(() => saveTodosCheckpoint(filePath, sessionId, todos, events, traceId)).catch((err) => {
|
|
9080
9314
|
const msg = toErrorMessage(err);
|
|
9081
|
-
console.error(JSON.stringify({
|
|
9082
|
-
level: "error",
|
|
9083
|
-
event: "todos_checkpoint.write_chain_failed",
|
|
9084
|
-
sessionId,
|
|
9085
|
-
message: msg,
|
|
9086
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9087
|
-
}));
|
|
9315
|
+
(warn ?? ((m) => console.error(JSON.stringify({ level: "error", event: "todos_checkpoint.write_chain_failed", sessionId, message: m, timestamp: (/* @__PURE__ */ new Date()).toISOString() }))))(msg);
|
|
9088
9316
|
});
|
|
9089
9317
|
return writeChain;
|
|
9090
9318
|
};
|
|
@@ -9115,11 +9343,14 @@ function attachTodosCheckpoint(state, filePath, sessionId, events, traceId) {
|
|
|
9115
9343
|
}
|
|
9116
9344
|
};
|
|
9117
9345
|
}
|
|
9346
|
+
|
|
9347
|
+
// src/storage/completed-work-checkpoint.ts
|
|
9348
|
+
import * as fsp10 from "node:fs/promises";
|
|
9118
9349
|
async function loadCompletedWorkCheckpoint(filePath, events, traceId) {
|
|
9119
9350
|
const t0 = Date.now();
|
|
9120
9351
|
let raw;
|
|
9121
9352
|
try {
|
|
9122
|
-
raw = await
|
|
9353
|
+
raw = await fsp10.readFile(filePath, "utf8");
|
|
9123
9354
|
} catch (err) {
|
|
9124
9355
|
events?.emit("storage.error", {
|
|
9125
9356
|
sessionId: traceId ?? "~boot~",
|
|
@@ -9213,11 +9444,15 @@ function isCompletedWorkEvidence(value) {
|
|
|
9213
9444
|
const item = value;
|
|
9214
9445
|
return typeof item.key === "string" && typeof item.source === "string" && ["todo", "plan", "task", "verification", "manual"].includes(item.source) && typeof item.summary === "string" && typeof item.completedAt === "number" && (item.evidence === void 0 || typeof item.evidence === "string");
|
|
9215
9446
|
}
|
|
9447
|
+
|
|
9448
|
+
// src/storage/plan-store.ts
|
|
9449
|
+
import * as fsp11 from "node:fs/promises";
|
|
9450
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
9216
9451
|
async function loadPlan(filePath, events) {
|
|
9217
9452
|
const t0 = Date.now();
|
|
9218
9453
|
let raw;
|
|
9219
9454
|
try {
|
|
9220
|
-
raw = await
|
|
9455
|
+
raw = await fsp11.readFile(filePath, "utf8");
|
|
9221
9456
|
} catch (err) {
|
|
9222
9457
|
events?.emit("storage.error", {
|
|
9223
9458
|
sessionId: "~boot~",
|
|
@@ -9265,7 +9500,7 @@ async function loadPlan(filePath, events) {
|
|
|
9265
9500
|
return null;
|
|
9266
9501
|
}
|
|
9267
9502
|
}
|
|
9268
|
-
async function savePlan(filePath, plan, events) {
|
|
9503
|
+
async function savePlan(filePath, plan, events, warn) {
|
|
9269
9504
|
const t0 = Date.now();
|
|
9270
9505
|
try {
|
|
9271
9506
|
await atomicWrite(filePath, JSON.stringify(plan, null, 2), { mode: 384 });
|
|
@@ -9287,10 +9522,14 @@ async function savePlan(filePath, plan, events) {
|
|
|
9287
9522
|
error: toErrorMessage(err),
|
|
9288
9523
|
recoverable: false
|
|
9289
9524
|
});
|
|
9290
|
-
console.warn(
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9525
|
+
(warn ?? ((m) => console.warn(
|
|
9526
|
+
JSON.stringify({
|
|
9527
|
+
level: "warn",
|
|
9528
|
+
event: "plan_store.save_failed",
|
|
9529
|
+
message: m,
|
|
9530
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9531
|
+
})
|
|
9532
|
+
)))(toErrorMessage(err));
|
|
9294
9533
|
return false;
|
|
9295
9534
|
}
|
|
9296
9535
|
}
|
|
@@ -9306,7 +9545,7 @@ function emptyPlan(sessionId, title) {
|
|
|
9306
9545
|
function addPlanItem(plan, title, details) {
|
|
9307
9546
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9308
9547
|
const item = {
|
|
9309
|
-
id: `plan_${Date.now()}_${
|
|
9548
|
+
id: `plan_${Date.now()}_${randomUUID6().slice(0, 6)}`,
|
|
9310
9549
|
title,
|
|
9311
9550
|
details,
|
|
9312
9551
|
status: "open",
|
|
@@ -9331,9 +9570,7 @@ function setPlanItemStatus(plan, idOrIndex, status) {
|
|
|
9331
9570
|
const idx = matchIndex(plan, idOrIndex);
|
|
9332
9571
|
if (idx === -1) return plan;
|
|
9333
9572
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9334
|
-
const items = plan.items.map(
|
|
9335
|
-
(it, i) => i === idx ? { ...it, status, updatedAt: now } : it
|
|
9336
|
-
);
|
|
9573
|
+
const items = plan.items.map((it, i) => i === idx ? { ...it, status, updatedAt: now } : it);
|
|
9337
9574
|
return { ...plan, items, updatedAt: now };
|
|
9338
9575
|
}
|
|
9339
9576
|
function clearPlan(plan) {
|
|
@@ -9380,7 +9617,7 @@ function deriveTodosFromPlanItem(plan, idOrIndex, subtasks) {
|
|
|
9380
9617
|
if (subtasks && subtasks.length > 0) {
|
|
9381
9618
|
for (const st of subtasks) {
|
|
9382
9619
|
todos.push({
|
|
9383
|
-
id: `todo_${Date.now()}_${
|
|
9620
|
+
id: `todo_${Date.now()}_${randomUUID6().slice(0, 6)}`,
|
|
9384
9621
|
content: st,
|
|
9385
9622
|
status: "pending",
|
|
9386
9623
|
promotedFromPlan: item.id
|
|
@@ -9521,6 +9758,9 @@ ${cat}:`);
|
|
|
9521
9758
|
}
|
|
9522
9759
|
return lines.join("\n");
|
|
9523
9760
|
}
|
|
9761
|
+
|
|
9762
|
+
// src/storage/task-store.ts
|
|
9763
|
+
import * as fsp12 from "node:fs/promises";
|
|
9524
9764
|
function emptyTaskFile(sessionId) {
|
|
9525
9765
|
return {
|
|
9526
9766
|
version: 1,
|
|
@@ -9533,7 +9773,7 @@ async function loadTasks(filePath, events, traceId) {
|
|
|
9533
9773
|
const t0 = Date.now();
|
|
9534
9774
|
let raw;
|
|
9535
9775
|
try {
|
|
9536
|
-
raw = await
|
|
9776
|
+
raw = await fsp12.readFile(filePath, "utf8");
|
|
9537
9777
|
} catch (err) {
|
|
9538
9778
|
events?.emit("storage.error", {
|
|
9539
9779
|
sessionId: traceId ?? "~boot~",
|
|
@@ -9585,7 +9825,7 @@ async function loadTasks(filePath, events, traceId) {
|
|
|
9585
9825
|
return null;
|
|
9586
9826
|
}
|
|
9587
9827
|
}
|
|
9588
|
-
async function saveTasks(filePath, tasks, events, traceId) {
|
|
9828
|
+
async function saveTasks(filePath, tasks, events, traceId, warn) {
|
|
9589
9829
|
const t0 = Date.now();
|
|
9590
9830
|
try {
|
|
9591
9831
|
tasks.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9611,10 +9851,14 @@ async function saveTasks(filePath, tasks, events, traceId) {
|
|
|
9611
9851
|
recoverable: false,
|
|
9612
9852
|
...traceId !== void 0 && { traceId }
|
|
9613
9853
|
});
|
|
9614
|
-
console.warn(
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9854
|
+
(warn ?? ((m) => console.warn(
|
|
9855
|
+
JSON.stringify({
|
|
9856
|
+
level: "warn",
|
|
9857
|
+
event: "task_store.save_failed",
|
|
9858
|
+
message: m,
|
|
9859
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9860
|
+
})
|
|
9861
|
+
)))(toErrorMessage(err));
|
|
9618
9862
|
return false;
|
|
9619
9863
|
}
|
|
9620
9864
|
}
|
|
@@ -9634,10 +9878,14 @@ async function mutateTasks(filePath, sessionId, fn, events, traceId) {
|
|
|
9634
9878
|
return updated;
|
|
9635
9879
|
});
|
|
9636
9880
|
}
|
|
9881
|
+
|
|
9882
|
+
// src/storage/director-state.ts
|
|
9883
|
+
import * as fsp13 from "node:fs/promises";
|
|
9884
|
+
import { hostname as hostname2 } from "node:os";
|
|
9637
9885
|
async function loadDirectorState(filePath) {
|
|
9638
9886
|
let raw;
|
|
9639
9887
|
try {
|
|
9640
|
-
raw = await
|
|
9888
|
+
raw = await fsp13.readFile(filePath, "utf8");
|
|
9641
9889
|
} catch {
|
|
9642
9890
|
return null;
|
|
9643
9891
|
}
|
|
@@ -9652,7 +9900,7 @@ async function loadDirectorState(filePath) {
|
|
|
9652
9900
|
async function acquireDirectorStateLock(lockPath, processId = process.pid) {
|
|
9653
9901
|
let existing;
|
|
9654
9902
|
try {
|
|
9655
|
-
existing = await
|
|
9903
|
+
existing = await fsp13.readFile(lockPath, "utf8");
|
|
9656
9904
|
} catch {
|
|
9657
9905
|
}
|
|
9658
9906
|
if (existing) {
|
|
@@ -9668,7 +9916,7 @@ async function acquireDirectorStateLock(lockPath, processId = process.pid) {
|
|
|
9668
9916
|
}
|
|
9669
9917
|
const lock = {
|
|
9670
9918
|
pid: processId,
|
|
9671
|
-
hostname:
|
|
9919
|
+
hostname: hostname2(),
|
|
9672
9920
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9673
9921
|
};
|
|
9674
9922
|
await atomicWrite(lockPath, JSON.stringify(lock), { mode: 384 });
|
|
@@ -9676,7 +9924,7 @@ async function acquireDirectorStateLock(lockPath, processId = process.pid) {
|
|
|
9676
9924
|
}
|
|
9677
9925
|
async function releaseDirectorStateLock(lockPath) {
|
|
9678
9926
|
try {
|
|
9679
|
-
await
|
|
9927
|
+
await fsp13.unlink(lockPath);
|
|
9680
9928
|
} catch {
|
|
9681
9929
|
}
|
|
9682
9930
|
}
|
|
@@ -9831,15 +10079,18 @@ var DirectorStateCheckpoint = class {
|
|
|
9831
10079
|
}
|
|
9832
10080
|
}
|
|
9833
10081
|
};
|
|
10082
|
+
|
|
10083
|
+
// src/storage/goal-store.ts
|
|
10084
|
+
import * as fsp14 from "node:fs/promises";
|
|
9834
10085
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
9835
10086
|
function goalFilePath(projectRoot) {
|
|
9836
10087
|
return resolveWstackPaths({ projectRoot }).projectGoal;
|
|
9837
10088
|
}
|
|
9838
|
-
async function loadGoal(filePath, events) {
|
|
10089
|
+
async function loadGoal(filePath, events, warn) {
|
|
9839
10090
|
const t0 = Date.now();
|
|
9840
10091
|
let raw;
|
|
9841
10092
|
try {
|
|
9842
|
-
raw = await
|
|
10093
|
+
raw = await fsp14.readFile(filePath, "utf8");
|
|
9843
10094
|
} catch (err) {
|
|
9844
10095
|
const code = err.code;
|
|
9845
10096
|
if (code === "ENOENT") {
|
|
@@ -9866,13 +10117,9 @@ async function loadGoal(filePath, events) {
|
|
|
9866
10117
|
try {
|
|
9867
10118
|
const parsed = JSON.parse(raw);
|
|
9868
10119
|
if (parsed?.version !== 1 || typeof parsed.goal !== "string" || !Array.isArray(parsed.journal)) {
|
|
9869
|
-
console.warn(JSON.stringify({
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
path: filePath,
|
|
9873
|
-
message: "invalid schema \u2014 consider deleting and re-creating",
|
|
9874
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9875
|
-
}));
|
|
10120
|
+
(warn ?? ((msg) => console.warn(JSON.stringify({ level: "warn", event: "goal_store.invalid_schema", path: filePath, message: msg, timestamp: (/* @__PURE__ */ new Date()).toISOString() }))))(
|
|
10121
|
+
"invalid schema \u2014 consider deleting and re-creating"
|
|
10122
|
+
);
|
|
9876
10123
|
events?.emit("storage.read", {
|
|
9877
10124
|
sessionId: "~boot~",
|
|
9878
10125
|
store: "goal",
|
|
@@ -9894,13 +10141,9 @@ async function loadGoal(filePath, events) {
|
|
|
9894
10141
|
});
|
|
9895
10142
|
return parsed;
|
|
9896
10143
|
} catch {
|
|
9897
|
-
console.warn(JSON.stringify({
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
path: filePath,
|
|
9901
|
-
message: "JSON parse failed \u2014 consider deleting and re-creating",
|
|
9902
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9903
|
-
}));
|
|
10144
|
+
(warn ?? ((msg) => console.warn(JSON.stringify({ level: "warn", event: "goal_store.parse_failed", path: filePath, message: msg, timestamp: (/* @__PURE__ */ new Date()).toISOString() }))))(
|
|
10145
|
+
"JSON parse failed \u2014 consider deleting and re-creating"
|
|
10146
|
+
);
|
|
9904
10147
|
events?.emit("storage.read", {
|
|
9905
10148
|
sessionId: "~boot~",
|
|
9906
10149
|
store: "goal",
|
|
@@ -10083,9 +10326,14 @@ function computeTrend(history) {
|
|
|
10083
10326
|
if (avgDelta < -1) return "stalling";
|
|
10084
10327
|
return "steady";
|
|
10085
10328
|
}
|
|
10329
|
+
|
|
10330
|
+
// src/storage/prompt-store.ts
|
|
10331
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
10332
|
+
import * as fs13 from "node:fs/promises";
|
|
10333
|
+
import * as path20 from "node:path";
|
|
10086
10334
|
var SCHEMA_VERSION = 2;
|
|
10087
10335
|
function promptChecksum(content) {
|
|
10088
|
-
return
|
|
10336
|
+
return createHash7("sha256").update(content, "utf8").digest("hex");
|
|
10089
10337
|
}
|
|
10090
10338
|
function migratePromptEntry(raw) {
|
|
10091
10339
|
if (!raw || typeof raw !== "object") return null;
|
|
@@ -10146,12 +10394,12 @@ var DefaultPromptStore = class {
|
|
|
10146
10394
|
await ensureDir(this.dir);
|
|
10147
10395
|
const entries = [];
|
|
10148
10396
|
try {
|
|
10149
|
-
const files = await
|
|
10397
|
+
const files = await fs13.readdir(this.dir);
|
|
10150
10398
|
for (const file of files) {
|
|
10151
10399
|
if (!file.endsWith(".json")) continue;
|
|
10152
10400
|
try {
|
|
10153
10401
|
const raw = JSON.parse(
|
|
10154
|
-
await
|
|
10402
|
+
await fs13.readFile(path20.join(this.dir, file), "utf8")
|
|
10155
10403
|
);
|
|
10156
10404
|
const migrated = migratePromptEntry(raw.entry);
|
|
10157
10405
|
if (migrated) entries.push(migrated);
|
|
@@ -10165,9 +10413,9 @@ var DefaultPromptStore = class {
|
|
|
10165
10413
|
);
|
|
10166
10414
|
}
|
|
10167
10415
|
async get(id) {
|
|
10168
|
-
const file =
|
|
10416
|
+
const file = path20.join(this.dir, `${id}.json`);
|
|
10169
10417
|
try {
|
|
10170
|
-
const raw = JSON.parse(await
|
|
10418
|
+
const raw = JSON.parse(await fs13.readFile(file, "utf8"));
|
|
10171
10419
|
return migratePromptEntry(raw.entry);
|
|
10172
10420
|
} catch {
|
|
10173
10421
|
return null;
|
|
@@ -10175,14 +10423,14 @@ var DefaultPromptStore = class {
|
|
|
10175
10423
|
}
|
|
10176
10424
|
async save(entry) {
|
|
10177
10425
|
await ensureDir(this.dir);
|
|
10178
|
-
const file =
|
|
10426
|
+
const file = path20.join(this.dir, `${entry.id}.json`);
|
|
10179
10427
|
const raw = { version: SCHEMA_VERSION, entry };
|
|
10180
10428
|
await atomicWrite(file, JSON.stringify(raw, null, 2));
|
|
10181
10429
|
}
|
|
10182
10430
|
async delete(id) {
|
|
10183
|
-
const file =
|
|
10431
|
+
const file = path20.join(this.dir, `${id}.json`);
|
|
10184
10432
|
try {
|
|
10185
|
-
await
|
|
10433
|
+
await fs13.unlink(file);
|
|
10186
10434
|
return true;
|
|
10187
10435
|
} catch {
|
|
10188
10436
|
return false;
|
|
@@ -10219,6 +10467,10 @@ var DefaultPromptStore = class {
|
|
|
10219
10467
|
};
|
|
10220
10468
|
}
|
|
10221
10469
|
};
|
|
10470
|
+
|
|
10471
|
+
// src/storage/prompt-usage-store.ts
|
|
10472
|
+
import * as fs14 from "node:fs/promises";
|
|
10473
|
+
import * as path21 from "node:path";
|
|
10222
10474
|
var PromptUsageStore = class {
|
|
10223
10475
|
constructor(file) {
|
|
10224
10476
|
this.file = file;
|
|
@@ -10226,7 +10478,7 @@ var PromptUsageStore = class {
|
|
|
10226
10478
|
file;
|
|
10227
10479
|
async load() {
|
|
10228
10480
|
try {
|
|
10229
|
-
const raw = JSON.parse(await
|
|
10481
|
+
const raw = JSON.parse(await fs14.readFile(this.file, "utf8"));
|
|
10230
10482
|
if (raw && typeof raw === "object" && raw.usage && typeof raw.usage === "object") {
|
|
10231
10483
|
return raw.usage;
|
|
10232
10484
|
}
|
|
@@ -10239,7 +10491,7 @@ var PromptUsageStore = class {
|
|
|
10239
10491
|
const prev = usage[slug];
|
|
10240
10492
|
const next = { count: (prev?.count ?? 0) + 1, lastUsedAt: at };
|
|
10241
10493
|
usage[slug] = next;
|
|
10242
|
-
await ensureDir(
|
|
10494
|
+
await ensureDir(path21.dirname(this.file));
|
|
10243
10495
|
await atomicWrite(this.file, JSON.stringify({ version: 1, usage }, null, 2));
|
|
10244
10496
|
return next;
|
|
10245
10497
|
}
|
|
@@ -10261,6 +10513,10 @@ var PromptUsageStore = class {
|
|
|
10261
10513
|
).slice(0, limit);
|
|
10262
10514
|
}
|
|
10263
10515
|
};
|
|
10516
|
+
|
|
10517
|
+
// src/storage/input-history-store.ts
|
|
10518
|
+
import * as fs15 from "node:fs/promises";
|
|
10519
|
+
import * as path22 from "node:path";
|
|
10264
10520
|
var INPUT_HISTORY_DEFAULT_MAX = 100;
|
|
10265
10521
|
var InputHistoryStore = class {
|
|
10266
10522
|
/**
|
|
@@ -10282,7 +10538,7 @@ var InputHistoryStore = class {
|
|
|
10282
10538
|
*/
|
|
10283
10539
|
async load() {
|
|
10284
10540
|
try {
|
|
10285
|
-
const raw = JSON.parse(await
|
|
10541
|
+
const raw = JSON.parse(await fs15.readFile(this.file, "utf8"));
|
|
10286
10542
|
if (raw && typeof raw === "object" && Array.isArray(raw.entries) && raw.entries.every((e) => typeof e === "string")) {
|
|
10287
10543
|
return raw.entries.slice(0, this.maxEntries);
|
|
10288
10544
|
}
|
|
@@ -10299,7 +10555,7 @@ var InputHistoryStore = class {
|
|
|
10299
10555
|
*/
|
|
10300
10556
|
async save(entries) {
|
|
10301
10557
|
const cleaned = this.scrubAndFilter(entries);
|
|
10302
|
-
await ensureDir(
|
|
10558
|
+
await ensureDir(path22.dirname(this.file));
|
|
10303
10559
|
const payload = {
|
|
10304
10560
|
version: 1,
|
|
10305
10561
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -10309,7 +10565,7 @@ var InputHistoryStore = class {
|
|
|
10309
10565
|
}
|
|
10310
10566
|
/** Truncate the file to an empty entry list (used by /clear). */
|
|
10311
10567
|
async clear() {
|
|
10312
|
-
await ensureDir(
|
|
10568
|
+
await ensureDir(path22.dirname(this.file));
|
|
10313
10569
|
const payload = { version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), entries: [] };
|
|
10314
10570
|
await atomicWrite(this.file, JSON.stringify(payload, null, 2));
|
|
10315
10571
|
}
|
|
@@ -10337,13 +10593,18 @@ var InputHistoryStore = class {
|
|
|
10337
10593
|
return text.includes("***REDACTED***");
|
|
10338
10594
|
}
|
|
10339
10595
|
};
|
|
10596
|
+
|
|
10597
|
+
// src/storage/cloud-sync.ts
|
|
10598
|
+
import * as fs16 from "node:fs/promises";
|
|
10599
|
+
import * as path23 from "node:path";
|
|
10600
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
10340
10601
|
var ALL_SYNC_CATEGORIES = ["settings", "skills", "prompts", "memory", "history"];
|
|
10341
10602
|
var CloudSync = class {
|
|
10342
10603
|
constructor(paths, getConfig, setConfig) {
|
|
10343
10604
|
this.paths = paths;
|
|
10344
10605
|
this.getConfig = getConfig;
|
|
10345
10606
|
this.setConfig = setConfig;
|
|
10346
|
-
this.statePath =
|
|
10607
|
+
this.statePath = path23.join(paths.globalRoot, "sync-state.json");
|
|
10347
10608
|
}
|
|
10348
10609
|
paths;
|
|
10349
10610
|
getConfig;
|
|
@@ -10418,7 +10679,7 @@ var CloudSync = class {
|
|
|
10418
10679
|
lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10419
10680
|
localRev: rev
|
|
10420
10681
|
};
|
|
10421
|
-
await
|
|
10682
|
+
await fs16.writeFile(this.statePath, JSON.stringify(syncState, null, 2), "utf8");
|
|
10422
10683
|
this.state = syncState;
|
|
10423
10684
|
return {
|
|
10424
10685
|
ok: true,
|
|
@@ -10450,8 +10711,8 @@ var CloudSync = class {
|
|
|
10450
10711
|
const rel = segments.slice(2).join("/");
|
|
10451
10712
|
const destPath = resolvePulledCategoryPath(cat, localPath, rel, entry.path);
|
|
10452
10713
|
const blobData = await this.getBlob(token, owner, repoName, entry.sha);
|
|
10453
|
-
await
|
|
10454
|
-
await
|
|
10714
|
+
await fs16.mkdir(path23.dirname(destPath), { recursive: true });
|
|
10715
|
+
await fs16.writeFile(destPath, Buffer.from(blobData, "base64"));
|
|
10455
10716
|
}
|
|
10456
10717
|
const localRev = await this.hashLocalCategories(cfg.categories);
|
|
10457
10718
|
const syncState = {
|
|
@@ -10460,7 +10721,7 @@ var CloudSync = class {
|
|
|
10460
10721
|
lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10461
10722
|
localRev
|
|
10462
10723
|
};
|
|
10463
|
-
await
|
|
10724
|
+
await fs16.writeFile(this.statePath, JSON.stringify(syncState, null, 2), "utf8");
|
|
10464
10725
|
this.state = syncState;
|
|
10465
10726
|
return {
|
|
10466
10727
|
ok: true,
|
|
@@ -10479,7 +10740,7 @@ var CloudSync = class {
|
|
|
10479
10740
|
}
|
|
10480
10741
|
async loadState() {
|
|
10481
10742
|
try {
|
|
10482
|
-
const raw = await
|
|
10743
|
+
const raw = await fs16.readFile(this.statePath, "utf8");
|
|
10483
10744
|
this.state = JSON.parse(raw);
|
|
10484
10745
|
} catch {
|
|
10485
10746
|
this.state = null;
|
|
@@ -10557,24 +10818,24 @@ var CloudSync = class {
|
|
|
10557
10818
|
const localPath = this.categoryToPath(cat);
|
|
10558
10819
|
if (!localPath) continue;
|
|
10559
10820
|
try {
|
|
10560
|
-
const stat13 = await
|
|
10821
|
+
const stat13 = await fs16.stat(localPath);
|
|
10561
10822
|
if (stat13.isDirectory()) {
|
|
10562
10823
|
const files = await this.walkDir(localPath, localPath);
|
|
10563
10824
|
for (const file of files) {
|
|
10564
|
-
const content = await
|
|
10565
|
-
const rel =
|
|
10825
|
+
const content = await fs16.readFile(file, "utf8");
|
|
10826
|
+
const rel = path23.relative(localPath, file).replace(/\\/g, "/");
|
|
10566
10827
|
entries.push({ path: `data/${cat}/${rel}`, content, mode: "100644" });
|
|
10567
10828
|
hashes.push(content);
|
|
10568
10829
|
}
|
|
10569
10830
|
} else {
|
|
10570
|
-
const content = await
|
|
10831
|
+
const content = await fs16.readFile(localPath, "utf8");
|
|
10571
10832
|
entries.push({ path: `data/${cat}`, content, mode: "100644" });
|
|
10572
10833
|
hashes.push(content);
|
|
10573
10834
|
}
|
|
10574
10835
|
} catch {
|
|
10575
10836
|
}
|
|
10576
10837
|
}
|
|
10577
|
-
const rev =
|
|
10838
|
+
const rev = createHash8("sha256").update(hashes.join("")).digest("hex").slice(0, 12);
|
|
10578
10839
|
return { treeEntries: entries, rev };
|
|
10579
10840
|
}
|
|
10580
10841
|
async hashLocalCategories(categories) {
|
|
@@ -10583,21 +10844,21 @@ var CloudSync = class {
|
|
|
10583
10844
|
const localPath = this.categoryToPath(cat);
|
|
10584
10845
|
if (!localPath) continue;
|
|
10585
10846
|
try {
|
|
10586
|
-
const stat13 = await
|
|
10847
|
+
const stat13 = await fs16.stat(localPath);
|
|
10587
10848
|
if (stat13.isDirectory()) {
|
|
10588
10849
|
const files = await this.walkDir(localPath, localPath);
|
|
10589
10850
|
for (const file of files) {
|
|
10590
|
-
const content = await
|
|
10851
|
+
const content = await fs16.readFile(file);
|
|
10591
10852
|
hashes.push(content.toString("base64") + file);
|
|
10592
10853
|
}
|
|
10593
10854
|
} else {
|
|
10594
|
-
const content = await
|
|
10855
|
+
const content = await fs16.readFile(localPath);
|
|
10595
10856
|
hashes.push(content.toString("base64") + localPath);
|
|
10596
10857
|
}
|
|
10597
10858
|
} catch {
|
|
10598
10859
|
}
|
|
10599
10860
|
}
|
|
10600
|
-
return
|
|
10861
|
+
return createHash8("sha256").update(hashes.join("")).digest("hex").slice(0, 12);
|
|
10601
10862
|
}
|
|
10602
10863
|
categoryToPath(cat) {
|
|
10603
10864
|
switch (cat) {
|
|
@@ -10618,9 +10879,9 @@ var CloudSync = class {
|
|
|
10618
10879
|
}
|
|
10619
10880
|
async walkDir(dir, base) {
|
|
10620
10881
|
const results = [];
|
|
10621
|
-
const entries = await
|
|
10882
|
+
const entries = await fs16.readdir(dir, { withFileTypes: true });
|
|
10622
10883
|
for (const entry of entries) {
|
|
10623
|
-
const full =
|
|
10884
|
+
const full = path23.join(dir, entry.name);
|
|
10624
10885
|
if (entry.isDirectory()) {
|
|
10625
10886
|
results.push(...await this.walkDir(full, base));
|
|
10626
10887
|
} else {
|
|
@@ -10642,9 +10903,9 @@ function resolvePulledCategoryPath(cat, localPath, rel, remotePath) {
|
|
|
10642
10903
|
return localPath;
|
|
10643
10904
|
}
|
|
10644
10905
|
if (!rel) return localPath;
|
|
10645
|
-
const normalizedRel =
|
|
10646
|
-
const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${
|
|
10647
|
-
if (
|
|
10906
|
+
const normalizedRel = path23.normalize(rel);
|
|
10907
|
+
const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${path23.sep}`);
|
|
10908
|
+
if (path23.isAbsolute(normalizedRel) || traversesUp) {
|
|
10648
10909
|
throw new FsError({
|
|
10649
10910
|
message: `Refusing CloudSync path traversal: ${remotePath}`,
|
|
10650
10911
|
code: ERROR_CODES.FS_DELETE_FAILED,
|
|
@@ -10652,10 +10913,10 @@ function resolvePulledCategoryPath(cat, localPath, rel, remotePath) {
|
|
|
10652
10913
|
context: { reason: "path_traversal", normalizedRel }
|
|
10653
10914
|
});
|
|
10654
10915
|
}
|
|
10655
|
-
const dest =
|
|
10656
|
-
const root =
|
|
10657
|
-
const relative6 =
|
|
10658
|
-
if (relative6.startsWith("..") ||
|
|
10916
|
+
const dest = path23.resolve(localPath, normalizedRel);
|
|
10917
|
+
const root = path23.resolve(localPath);
|
|
10918
|
+
const relative6 = path23.relative(root, dest);
|
|
10919
|
+
if (relative6.startsWith("..") || path23.isAbsolute(relative6)) {
|
|
10659
10920
|
throw new FsError({
|
|
10660
10921
|
message: `Refusing CloudSync path outside category root: ${remotePath}`,
|
|
10661
10922
|
code: ERROR_CODES.FS_DELETE_FAILED,
|
|
@@ -10794,7 +11055,86 @@ function resolveSessionLoggingConfig(cfg) {
|
|
|
10794
11055
|
}
|
|
10795
11056
|
};
|
|
10796
11057
|
}
|
|
10797
|
-
|
|
10798
|
-
|
|
11058
|
+
export {
|
|
11059
|
+
ALL_SYNC_CATEGORIES,
|
|
11060
|
+
AgentStatusTracker,
|
|
11061
|
+
AnnotationsStore,
|
|
11062
|
+
CORE_RECONSTRUCT_EVENTS,
|
|
11063
|
+
CloudSync,
|
|
11064
|
+
ConfigMigrationError,
|
|
11065
|
+
DEFAULT_CONFIG_MIGRATIONS,
|
|
11066
|
+
DefaultAttachmentStore,
|
|
11067
|
+
DefaultConfigLoader,
|
|
11068
|
+
DefaultConfigStore,
|
|
11069
|
+
DefaultMemoryStore,
|
|
11070
|
+
DefaultPromptStore,
|
|
11071
|
+
DefaultSessionReader,
|
|
11072
|
+
DefaultSessionRewinder,
|
|
11073
|
+
DefaultSessionStore,
|
|
11074
|
+
DirectorStateCheckpoint,
|
|
11075
|
+
FileMemoryBackend,
|
|
11076
|
+
FleetNotifier,
|
|
11077
|
+
GraphMemoryBackend,
|
|
11078
|
+
INPUT_HISTORY_DEFAULT_MAX,
|
|
11079
|
+
InputHistoryStore,
|
|
11080
|
+
MAX_JOURNAL_ENTRIES,
|
|
11081
|
+
MAX_PROGRESS_HISTORY,
|
|
11082
|
+
PromptUsageStore,
|
|
11083
|
+
QueueStore,
|
|
11084
|
+
RecoveryLock,
|
|
11085
|
+
ReplayLogStore,
|
|
11086
|
+
STANDARD_AUDIT_EVENTS,
|
|
11087
|
+
SessionAnalyzer,
|
|
11088
|
+
SessionCheckpointCas,
|
|
11089
|
+
SessionMemoryConsolidator,
|
|
11090
|
+
SessionRecovery,
|
|
11091
|
+
SessionRegistry,
|
|
11092
|
+
ToolAuditLog,
|
|
11093
|
+
addPlanItem,
|
|
11094
|
+
appendJournal,
|
|
11095
|
+
attachPlanCheckpoint,
|
|
11096
|
+
attachTodosCheckpoint,
|
|
11097
|
+
clearPlan,
|
|
11098
|
+
createSessionEventBridge,
|
|
11099
|
+
deriveTodosFromPlanItem,
|
|
11100
|
+
emptyGoal,
|
|
11101
|
+
emptyPlan,
|
|
11102
|
+
emptyTaskFile,
|
|
11103
|
+
formatGoal,
|
|
11104
|
+
formatPlan,
|
|
11105
|
+
formatPlanTemplates,
|
|
11106
|
+
generateSessionId,
|
|
11107
|
+
getPlanTemplate,
|
|
11108
|
+
getSessionRegistry,
|
|
11109
|
+
goalFilePath,
|
|
11110
|
+
hasSessionRegistry,
|
|
11111
|
+
listPlanTemplates,
|
|
11112
|
+
loadCompletedWorkCheckpoint,
|
|
11113
|
+
loadDirectorState,
|
|
11114
|
+
loadGoal,
|
|
11115
|
+
loadPlan,
|
|
11116
|
+
loadTasks,
|
|
11117
|
+
loadTodosCheckpoint,
|
|
11118
|
+
migratePromptEntry,
|
|
11119
|
+
mutatePlan,
|
|
11120
|
+
mutateTasks,
|
|
11121
|
+
parseEntries,
|
|
11122
|
+
parseProgressFromText,
|
|
11123
|
+
promptChecksum,
|
|
11124
|
+
recordProgress,
|
|
11125
|
+
removePlanItem,
|
|
11126
|
+
resolveAuditLevel,
|
|
11127
|
+
resolveSessionLoggingConfig,
|
|
11128
|
+
runConfigMigrations,
|
|
11129
|
+
sanitizeModel,
|
|
11130
|
+
saveCompletedWorkCheckpoint,
|
|
11131
|
+
saveGoal,
|
|
11132
|
+
savePlan,
|
|
11133
|
+
saveTasks,
|
|
11134
|
+
saveTodosCheckpoint,
|
|
11135
|
+
setPlanItemStatus,
|
|
11136
|
+
setProgress,
|
|
11137
|
+
summarizeUsage,
|
|
11138
|
+
watchProviderConfig
|
|
11139
|
+
};
|
|
10799
11140
|
//# sourceMappingURL=index.js.map
|
|
10800
|
-
//# sourceMappingURL=index.js.map
|