pulseed 0.5.1 → 0.5.3
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/adapters/types/a2a.d.ts +6 -6
- package/dist/base/config/identity-loader.d.ts +6 -0
- package/dist/base/config/identity-loader.d.ts.map +1 -1
- package/dist/base/config/identity-loader.js +34 -8
- package/dist/base/config/identity-loader.js.map +1 -1
- package/dist/grounding/gateway.d.ts.map +1 -1
- package/dist/grounding/gateway.js +2 -1
- package/dist/grounding/gateway.js.map +1 -1
- package/dist/grounding/providers/static-policy-provider.d.ts +1 -1
- package/dist/grounding/providers/static-policy-provider.d.ts.map +1 -1
- package/dist/grounding/providers/static-policy-provider.js +12 -8
- package/dist/grounding/providers/static-policy-provider.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/interface/chat/chat-event-state.d.ts +10 -0
- package/dist/interface/chat/chat-event-state.d.ts.map +1 -1
- package/dist/interface/chat/chat-event-state.js +184 -9
- package/dist/interface/chat/chat-event-state.js.map +1 -1
- package/dist/interface/chat/chat-events.d.ts +3 -1
- package/dist/interface/chat/chat-events.d.ts.map +1 -1
- package/dist/interface/chat/chat-runner.d.ts +25 -1
- package/dist/interface/chat/chat-runner.d.ts.map +1 -1
- package/dist/interface/chat/chat-runner.js +751 -83
- package/dist/interface/chat/chat-runner.js.map +1 -1
- package/dist/interface/chat/chat-verifier.d.ts +3 -1
- package/dist/interface/chat/chat-verifier.d.ts.map +1 -1
- package/dist/interface/chat/chat-verifier.js +2 -2
- package/dist/interface/chat/chat-verifier.js.map +1 -1
- package/dist/interface/chat/cross-platform-session.d.ts +4 -0
- package/dist/interface/chat/cross-platform-session.d.ts.map +1 -1
- package/dist/interface/chat/cross-platform-session.js +33 -0
- package/dist/interface/chat/cross-platform-session.js.map +1 -1
- package/dist/interface/chat/failure-recovery.d.ts +11 -0
- package/dist/interface/chat/failure-recovery.d.ts.map +1 -0
- package/dist/interface/chat/failure-recovery.js +115 -0
- package/dist/interface/chat/failure-recovery.js.map +1 -0
- package/dist/interface/chat/grounding.d.ts +1 -1
- package/dist/interface/chat/grounding.d.ts.map +1 -1
- package/dist/interface/chat/grounding.js +2 -2
- package/dist/interface/chat/grounding.js.map +1 -1
- package/dist/interface/chat/ingress-router.d.ts +11 -0
- package/dist/interface/chat/ingress-router.d.ts.map +1 -1
- package/dist/interface/chat/ingress-router.js +46 -2
- package/dist/interface/chat/ingress-router.js.map +1 -1
- package/dist/interface/chat/tend-command.d.ts +8 -0
- package/dist/interface/chat/tend-command.d.ts.map +1 -1
- package/dist/interface/chat/tend-command.js +80 -4
- package/dist/interface/chat/tend-command.js.map +1 -1
- package/dist/interface/cli/cli-command-registry.d.ts.map +1 -1
- package/dist/interface/cli/cli-command-registry.js +4 -0
- package/dist/interface/cli/cli-command-registry.js.map +1 -1
- package/dist/interface/cli/commands/daemon.d.ts.map +1 -1
- package/dist/interface/cli/commands/daemon.js +41 -7
- package/dist/interface/cli/commands/daemon.js.map +1 -1
- package/dist/interface/cli/commands/runtime.d.ts +3 -0
- package/dist/interface/cli/commands/runtime.d.ts.map +1 -0
- package/dist/interface/cli/commands/runtime.js +231 -0
- package/dist/interface/cli/commands/runtime.js.map +1 -0
- package/dist/interface/cli/commands/setup/steps-identity.d.ts.map +1 -1
- package/dist/interface/cli/commands/setup/steps-identity.js +5 -0
- package/dist/interface/cli/commands/setup/steps-identity.js.map +1 -1
- package/dist/interface/cli/commands/setup/steps-runtime.d.ts +2 -0
- package/dist/interface/cli/commands/setup/steps-runtime.d.ts.map +1 -1
- package/dist/interface/cli/commands/setup/steps-runtime.js +11 -2
- package/dist/interface/cli/commands/setup/steps-runtime.js.map +1 -1
- package/dist/interface/cli/setup.d.ts.map +1 -1
- package/dist/interface/cli/setup.js +14 -1
- package/dist/interface/cli/setup.js.map +1 -1
- package/dist/interface/cli/utils.d.ts.map +1 -1
- package/dist/interface/cli/utils.js +4 -0
- package/dist/interface/cli/utils.js.map +1 -1
- package/dist/interface/tui/app.d.ts +2 -0
- package/dist/interface/tui/app.d.ts.map +1 -1
- package/dist/interface/tui/app.js +73 -16
- package/dist/interface/tui/app.js.map +1 -1
- package/dist/interface/tui/chat/scroll.d.ts +3 -0
- package/dist/interface/tui/chat/scroll.d.ts.map +1 -1
- package/dist/interface/tui/chat/scroll.js +15 -0
- package/dist/interface/tui/chat/scroll.js.map +1 -1
- package/dist/interface/tui/chat/types.d.ts +1 -1
- package/dist/interface/tui/chat/types.d.ts.map +1 -1
- package/dist/interface/tui/chat/viewport.d.ts.map +1 -1
- package/dist/interface/tui/chat/viewport.js +8 -2
- package/dist/interface/tui/chat/viewport.js.map +1 -1
- package/dist/interface/tui/chat-surface.d.ts +2 -0
- package/dist/interface/tui/chat-surface.d.ts.map +1 -1
- package/dist/interface/tui/chat-surface.js +11 -0
- package/dist/interface/tui/chat-surface.js.map +1 -1
- package/dist/interface/tui/chat.d.ts.map +1 -1
- package/dist/interface/tui/chat.js +15 -7
- package/dist/interface/tui/chat.js.map +1 -1
- package/dist/interface/tui/clipboard.d.ts +6 -1
- package/dist/interface/tui/clipboard.d.ts.map +1 -1
- package/dist/interface/tui/clipboard.js +24 -5
- package/dist/interface/tui/clipboard.js.map +1 -1
- package/dist/interface/tui/entry.d.ts.map +1 -1
- package/dist/interface/tui/entry.js +28 -3
- package/dist/interface/tui/entry.js.map +1 -1
- package/dist/interface/tui/flicker/MouseTracking.d.ts +1 -1
- package/dist/interface/tui/flicker/MouseTracking.d.ts.map +1 -1
- package/dist/interface/tui/flicker/MouseTracking.js +8 -4
- package/dist/interface/tui/flicker/MouseTracking.js.map +1 -1
- package/dist/interface/tui/fullscreen-chat.d.ts +86 -5
- package/dist/interface/tui/fullscreen-chat.d.ts.map +1 -1
- package/dist/interface/tui/fullscreen-chat.js +586 -32
- package/dist/interface/tui/fullscreen-chat.js.map +1 -1
- package/dist/interface/tui/help-overlay.d.ts.map +1 -1
- package/dist/interface/tui/help-overlay.js +1 -1
- package/dist/interface/tui/help-overlay.js.map +1 -1
- package/dist/interface/tui/markdown-renderer.d.ts.map +1 -1
- package/dist/interface/tui/markdown-renderer.js +40 -12
- package/dist/interface/tui/markdown-renderer.js.map +1 -1
- package/dist/interface/tui/test-entry.js +1 -1
- package/dist/interface/tui/test-entry.js.map +1 -1
- package/dist/orchestrator/execution/adapter-layer.d.ts +2 -0
- package/dist/orchestrator/execution/adapter-layer.d.ts.map +1 -1
- package/dist/orchestrator/execution/adapter-layer.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.js +1 -0
- package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js +53 -12
- package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.js +7 -4
- package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-prompts.d.ts +1 -0
- package/dist/orchestrator/execution/agent-loop/agent-loop-prompts.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-prompts.js +10 -3
- package/dist/orchestrator/execution/agent-loop/agent-loop-prompts.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-session-factory.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-session-factory.js +2 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-session-factory.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.d.ts +2 -0
- package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js +51 -0
- package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts +13 -4
- package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js +44 -126
- package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/chat-display-output.d.ts +27 -0
- package/dist/orchestrator/execution/agent-loop/chat-display-output.d.ts.map +1 -0
- package/dist/orchestrator/execution/agent-loop/chat-display-output.js +157 -0
- package/dist/orchestrator/execution/agent-loop/chat-display-output.js.map +1 -0
- package/dist/orchestrator/execution/agent-loop/core-phase-runner.d.ts +1 -1
- package/dist/orchestrator/execution/agent-loop/core-phase-runner.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/core-phase-runner.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/index.d.ts +1 -0
- package/dist/orchestrator/execution/agent-loop/index.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/index.js +1 -0
- package/dist/orchestrator/execution/agent-loop/index.js.map +1 -1
- package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.d.ts +34 -0
- package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.d.ts.map +1 -0
- package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.js +54 -0
- package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.js.map +1 -0
- package/dist/orchestrator/execution/agent-loop/task-agent-loop-factory.d.ts +2 -0
- package/dist/orchestrator/execution/agent-loop/task-agent-loop-factory.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/task-agent-loop-factory.js +10 -0
- package/dist/orchestrator/execution/agent-loop/task-agent-loop-factory.js.map +1 -1
- package/dist/orchestrator/goal/goal-suggest.d.ts +4 -4
- package/dist/orchestrator/goal/types/goal-tree.d.ts +2 -2
- package/dist/orchestrator/loop/core-loop/contracts.d.ts +19 -0
- package/dist/orchestrator/loop/core-loop/contracts.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop/contracts.js.map +1 -1
- package/dist/orchestrator/loop/core-loop/iteration-kernel.d.ts +1 -0
- package/dist/orchestrator/loop/core-loop/iteration-kernel.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop/iteration-kernel.js +61 -2
- package/dist/orchestrator/loop/core-loop/iteration-kernel.js.map +1 -1
- package/dist/orchestrator/loop/core-loop/phase-policy.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop/phase-policy.js +27 -0
- package/dist/orchestrator/loop/core-loop/phase-policy.js.map +1 -1
- package/dist/orchestrator/loop/core-loop/phase-specs.d.ts +37 -0
- package/dist/orchestrator/loop/core-loop/phase-specs.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop/phase-specs.js +28 -0
- package/dist/orchestrator/loop/core-loop/phase-specs.js.map +1 -1
- package/dist/orchestrator/loop/core-loop/task-cycle.d.ts +12 -0
- package/dist/orchestrator/loop/core-loop/task-cycle.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop/task-cycle.js +170 -23
- package/dist/orchestrator/loop/core-loop/task-cycle.js.map +1 -1
- package/dist/orchestrator/loop/core-loop.d.ts +2 -1
- package/dist/orchestrator/loop/core-loop.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop.js +3 -0
- package/dist/orchestrator/loop/core-loop.js.map +1 -1
- package/dist/orchestrator/loop/loop-report-helper.d.ts.map +1 -1
- package/dist/orchestrator/loop/loop-report-helper.js +24 -0
- package/dist/orchestrator/loop/loop-report-helper.js.map +1 -1
- package/dist/orchestrator/loop/loop-result-types.d.ts +7 -0
- package/dist/orchestrator/loop/loop-result-types.d.ts.map +1 -1
- package/dist/orchestrator/loop/loop-result-types.js.map +1 -1
- package/dist/orchestrator/strategy/portfolio-manager.d.ts +2 -2
- package/dist/orchestrator/strategy/portfolio-manager.d.ts.map +1 -1
- package/dist/orchestrator/strategy/portfolio-manager.js +11 -1
- package/dist/orchestrator/strategy/portfolio-manager.js.map +1 -1
- package/dist/orchestrator/strategy/portfolio-rebalance.d.ts +4 -2
- package/dist/orchestrator/strategy/portfolio-rebalance.d.ts.map +1 -1
- package/dist/orchestrator/strategy/portfolio-rebalance.js +490 -12
- package/dist/orchestrator/strategy/portfolio-rebalance.js.map +1 -1
- package/dist/orchestrator/strategy/strategy-manager.js +3 -3
- package/dist/orchestrator/strategy/strategy-manager.js.map +1 -1
- package/dist/orchestrator/strategy/types/cross-portfolio.d.ts +2 -2
- package/dist/orchestrator/strategy/types/portfolio.d.ts +12 -12
- package/dist/orchestrator/strategy/types/strategy.d.ts +639 -8
- package/dist/orchestrator/strategy/types/strategy.d.ts.map +1 -1
- package/dist/orchestrator/strategy/types/strategy.js +122 -0
- package/dist/orchestrator/strategy/types/strategy.js.map +1 -1
- package/dist/platform/code-search/candidate-normalizer.d.ts +3 -0
- package/dist/platform/code-search/candidate-normalizer.d.ts.map +1 -0
- package/dist/platform/code-search/candidate-normalizer.js +61 -0
- package/dist/platform/code-search/candidate-normalizer.js.map +1 -0
- package/dist/platform/code-search/candidate.d.ts +25 -0
- package/dist/platform/code-search/candidate.d.ts.map +1 -0
- package/dist/platform/code-search/candidate.js +61 -0
- package/dist/platform/code-search/candidate.js.map +1 -0
- package/dist/platform/code-search/contracts.d.ts +275 -0
- package/dist/platform/code-search/contracts.d.ts.map +1 -0
- package/dist/platform/code-search/contracts.js +22 -0
- package/dist/platform/code-search/contracts.js.map +1 -0
- package/dist/platform/code-search/eval/fixtures.d.ts +14 -0
- package/dist/platform/code-search/eval/fixtures.d.ts.map +1 -0
- package/dist/platform/code-search/eval/fixtures.js +24 -0
- package/dist/platform/code-search/eval/fixtures.js.map +1 -0
- package/dist/platform/code-search/eval/metrics.d.ts +10 -0
- package/dist/platform/code-search/eval/metrics.d.ts.map +1 -0
- package/dist/platform/code-search/eval/metrics.js +20 -0
- package/dist/platform/code-search/eval/metrics.js.map +1 -0
- package/dist/platform/code-search/eval/runner.d.ts +3 -0
- package/dist/platform/code-search/eval/runner.d.ts.map +1 -0
- package/dist/platform/code-search/eval/runner.js +13 -0
- package/dist/platform/code-search/eval/runner.js.map +1 -0
- package/dist/platform/code-search/fusion.d.ts +6 -0
- package/dist/platform/code-search/fusion.d.ts.map +1 -0
- package/dist/platform/code-search/fusion.js +12 -0
- package/dist/platform/code-search/fusion.js.map +1 -0
- package/dist/platform/code-search/generated-detector.d.ts +15 -0
- package/dist/platform/code-search/generated-detector.d.ts.map +1 -0
- package/dist/platform/code-search/generated-detector.js +42 -0
- package/dist/platform/code-search/generated-detector.js.map +1 -0
- package/dist/platform/code-search/indexes/call-graph.d.ts +3 -0
- package/dist/platform/code-search/indexes/call-graph.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/call-graph.js +13 -0
- package/dist/platform/code-search/indexes/call-graph.js.map +1 -0
- package/dist/platform/code-search/indexes/config-index.d.ts +3 -0
- package/dist/platform/code-search/indexes/config-index.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/config-index.js +7 -0
- package/dist/platform/code-search/indexes/config-index.js.map +1 -0
- package/dist/platform/code-search/indexes/file-index.d.ts +5 -0
- package/dist/platform/code-search/indexes/file-index.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/file-index.js +106 -0
- package/dist/platform/code-search/indexes/file-index.js.map +1 -0
- package/dist/platform/code-search/indexes/index-store.d.ts +6 -0
- package/dist/platform/code-search/indexes/index-store.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/index-store.js +14 -0
- package/dist/platform/code-search/indexes/index-store.js.map +1 -0
- package/dist/platform/code-search/indexes/indexer.d.ts +3 -0
- package/dist/platform/code-search/indexes/indexer.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/indexer.js +27 -0
- package/dist/platform/code-search/indexes/indexer.js.map +1 -0
- package/dist/platform/code-search/indexes/package-graph.d.ts +3 -0
- package/dist/platform/code-search/indexes/package-graph.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/package-graph.js +26 -0
- package/dist/platform/code-search/indexes/package-graph.js.map +1 -0
- package/dist/platform/code-search/indexes/repo-map-index.d.ts +3 -0
- package/dist/platform/code-search/indexes/repo-map-index.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/repo-map-index.js +26 -0
- package/dist/platform/code-search/indexes/repo-map-index.js.map +1 -0
- package/dist/platform/code-search/indexes/semantic-index.d.ts +3 -0
- package/dist/platform/code-search/indexes/semantic-index.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/semantic-index.js +4 -0
- package/dist/platform/code-search/indexes/semantic-index.js.map +1 -0
- package/dist/platform/code-search/indexes/symbol-index.d.ts +3 -0
- package/dist/platform/code-search/indexes/symbol-index.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/symbol-index.js +84 -0
- package/dist/platform/code-search/indexes/symbol-index.js.map +1 -0
- package/dist/platform/code-search/indexes/test-index.d.ts +3 -0
- package/dist/platform/code-search/indexes/test-index.d.ts.map +1 -0
- package/dist/platform/code-search/indexes/test-index.js +22 -0
- package/dist/platform/code-search/indexes/test-index.js.map +1 -0
- package/dist/platform/code-search/orchestrator.d.ts +9 -0
- package/dist/platform/code-search/orchestrator.d.ts.map +1 -0
- package/dist/platform/code-search/orchestrator.js +81 -0
- package/dist/platform/code-search/orchestrator.js.map +1 -0
- package/dist/platform/code-search/path-policy.d.ts +6 -0
- package/dist/platform/code-search/path-policy.d.ts.map +1 -0
- package/dist/platform/code-search/path-policy.js +60 -0
- package/dist/platform/code-search/path-policy.js.map +1 -0
- package/dist/platform/code-search/progressive-reader.d.ts +8 -0
- package/dist/platform/code-search/progressive-reader.d.ts.map +1 -0
- package/dist/platform/code-search/progressive-reader.js +173 -0
- package/dist/platform/code-search/progressive-reader.js.map +1 -0
- package/dist/platform/code-search/query-planner.d.ts +4 -0
- package/dist/platform/code-search/query-planner.d.ts.map +1 -0
- package/dist/platform/code-search/query-planner.js +107 -0
- package/dist/platform/code-search/query-planner.js.map +1 -0
- package/dist/platform/code-search/reranker.d.ts +4 -0
- package/dist/platform/code-search/reranker.d.ts.map +1 -0
- package/dist/platform/code-search/reranker.js +57 -0
- package/dist/platform/code-search/reranker.js.map +1 -0
- package/dist/platform/code-search/retrievers/callgraph-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/callgraph-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/callgraph-retriever.js +31 -0
- package/dist/platform/code-search/retrievers/callgraph-retriever.js.map +1 -0
- package/dist/platform/code-search/retrievers/config-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/config-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/config-retriever.js +23 -0
- package/dist/platform/code-search/retrievers/config-retriever.js.map +1 -0
- package/dist/platform/code-search/retrievers/lexical-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/lexical-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/lexical-retriever.js +49 -0
- package/dist/platform/code-search/retrievers/lexical-retriever.js.map +1 -0
- package/dist/platform/code-search/retrievers/package-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/package-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/package-retriever.js +29 -0
- package/dist/platform/code-search/retrievers/package-retriever.js.map +1 -0
- package/dist/platform/code-search/retrievers/repo-map-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/repo-map-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/repo-map-retriever.js +30 -0
- package/dist/platform/code-search/retrievers/repo-map-retriever.js.map +1 -0
- package/dist/platform/code-search/retrievers/semantic-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/semantic-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/semantic-retriever.js +18 -0
- package/dist/platform/code-search/retrievers/semantic-retriever.js.map +1 -0
- package/dist/platform/code-search/retrievers/stacktrace-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/stacktrace-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/stacktrace-retriever.js +30 -0
- package/dist/platform/code-search/retrievers/stacktrace-retriever.js.map +1 -0
- package/dist/platform/code-search/retrievers/symbol-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/symbol-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/symbol-retriever.js +32 -0
- package/dist/platform/code-search/retrievers/symbol-retriever.js.map +1 -0
- package/dist/platform/code-search/retrievers/test-retriever.d.ts +6 -0
- package/dist/platform/code-search/retrievers/test-retriever.d.ts.map +1 -0
- package/dist/platform/code-search/retrievers/test-retriever.js +30 -0
- package/dist/platform/code-search/retrievers/test-retriever.js.map +1 -0
- package/dist/platform/code-search/session-store.d.ts +11 -0
- package/dist/platform/code-search/session-store.d.ts.map +1 -0
- package/dist/platform/code-search/session-store.js +41 -0
- package/dist/platform/code-search/session-store.js.map +1 -0
- package/dist/platform/code-search/trace.d.ts +9 -0
- package/dist/platform/code-search/trace.d.ts.map +1 -0
- package/dist/platform/code-search/trace.js +25 -0
- package/dist/platform/code-search/trace.js.map +1 -0
- package/dist/platform/code-search/verification-retrieval.d.ts +3 -0
- package/dist/platform/code-search/verification-retrieval.d.ts.map +1 -0
- package/dist/platform/code-search/verification-retrieval.js +33 -0
- package/dist/platform/code-search/verification-retrieval.js.map +1 -0
- package/dist/platform/dream/dream-types.d.ts +52 -52
- package/dist/platform/drive/types/satisficing.d.ts +2 -2
- package/dist/platform/knowledge/types/memory-lifecycle.d.ts +2 -2
- package/dist/platform/observation/context-provider.d.ts.map +1 -1
- package/dist/platform/observation/context-provider.js +37 -0
- package/dist/platform/observation/context-provider.js.map +1 -1
- package/dist/platform/observation/observation-helpers.d.ts +2 -2
- package/dist/platform/observation/workspace-context.d.ts.map +1 -1
- package/dist/platform/observation/workspace-context.js +27 -0
- package/dist/platform/observation/workspace-context.js.map +1 -1
- package/dist/platform/soil/contracts.d.ts +47 -47
- package/dist/platform/traits/types/curiosity.d.ts +24 -24
- package/dist/prompt/purposes/learning.d.ts +4 -4
- package/dist/reporting/report-formatters.d.ts.map +1 -1
- package/dist/reporting/report-formatters.js +33 -2
- package/dist/reporting/report-formatters.js.map +1 -1
- package/dist/reporting/reporting-engine.d.ts.map +1 -1
- package/dist/reporting/reporting-engine.js +2 -1
- package/dist/reporting/reporting-engine.js.map +1 -1
- package/dist/reporting/reporting-types.d.ts +11 -0
- package/dist/reporting/reporting-types.d.ts.map +1 -1
- package/dist/reporting/types/report.d.ts +72 -4
- package/dist/reporting/types/report.d.ts.map +1 -1
- package/dist/reporting/types/report.js +10 -0
- package/dist/reporting/types/report.js.map +1 -1
- package/dist/runtime/approval-broker.d.ts +1 -1
- package/dist/runtime/approval-broker.d.ts.map +1 -1
- package/dist/runtime/approval-broker.js +1 -2
- package/dist/runtime/approval-broker.js.map +1 -1
- package/dist/runtime/control/index.d.ts +1 -0
- package/dist/runtime/control/index.d.ts.map +1 -1
- package/dist/runtime/control/index.js +1 -0
- package/dist/runtime/control/index.js.map +1 -1
- package/dist/runtime/control/runtime-control-intent.d.ts.map +1 -1
- package/dist/runtime/control/runtime-control-intent.js +0 -8
- package/dist/runtime/control/runtime-control-intent.js.map +1 -1
- package/dist/runtime/control/runtime-control-result-routing.d.ts +28 -0
- package/dist/runtime/control/runtime-control-result-routing.d.ts.map +1 -0
- package/dist/runtime/control/runtime-control-result-routing.js +47 -0
- package/dist/runtime/control/runtime-control-result-routing.js.map +1 -0
- package/dist/runtime/control/runtime-control-service.d.ts +2 -1
- package/dist/runtime/control/runtime-control-service.d.ts.map +1 -1
- package/dist/runtime/control/runtime-control-service.js +32 -4
- package/dist/runtime/control/runtime-control-service.js.map +1 -1
- package/dist/runtime/daemon/client.d.ts +13 -1
- package/dist/runtime/daemon/client.d.ts.map +1 -1
- package/dist/runtime/daemon/client.js +2 -2
- package/dist/runtime/daemon/client.js.map +1 -1
- package/dist/runtime/daemon/index.d.ts +1 -0
- package/dist/runtime/daemon/index.d.ts.map +1 -1
- package/dist/runtime/daemon/index.js +1 -0
- package/dist/runtime/daemon/index.js.map +1 -1
- package/dist/runtime/daemon/runner-commands.d.ts +9 -1
- package/dist/runtime/daemon/runner-commands.d.ts.map +1 -1
- package/dist/runtime/daemon/runner-commands.js +33 -2
- package/dist/runtime/daemon/runner-commands.js.map +1 -1
- package/dist/runtime/daemon/runner-goal-cycle.d.ts.map +1 -1
- package/dist/runtime/daemon/runner-goal-cycle.js +55 -8
- package/dist/runtime/daemon/runner-goal-cycle.js.map +1 -1
- package/dist/runtime/daemon/runner-startup.d.ts +2 -1
- package/dist/runtime/daemon/runner-startup.d.ts.map +1 -1
- package/dist/runtime/daemon/runner-startup.js +32 -5
- package/dist/runtime/daemon/runner-startup.js.map +1 -1
- package/dist/runtime/daemon/runner.d.ts +2 -0
- package/dist/runtime/daemon/runner.d.ts.map +1 -1
- package/dist/runtime/daemon/runner.js +18 -3
- package/dist/runtime/daemon/runner.js.map +1 -1
- package/dist/runtime/daemon/runtime-root.d.ts +5 -0
- package/dist/runtime/daemon/runtime-root.d.ts.map +1 -0
- package/dist/runtime/daemon/runtime-root.js +60 -0
- package/dist/runtime/daemon/runtime-root.js.map +1 -0
- package/dist/runtime/daemon/wait-deadline-resolver.d.ts +25 -0
- package/dist/runtime/daemon/wait-deadline-resolver.d.ts.map +1 -0
- package/dist/runtime/daemon/wait-deadline-resolver.js +88 -0
- package/dist/runtime/daemon/wait-deadline-resolver.js.map +1 -0
- package/dist/runtime/event/server-command-handler.d.ts.map +1 -1
- package/dist/runtime/event/server-command-handler.js +47 -3
- package/dist/runtime/event/server-command-handler.js.map +1 -1
- package/dist/runtime/executor/goal-worker.d.ts +1 -0
- package/dist/runtime/executor/goal-worker.d.ts.map +1 -1
- package/dist/runtime/executor/goal-worker.js +1 -0
- package/dist/runtime/executor/goal-worker.js.map +1 -1
- package/dist/runtime/executor/loop-supervisor.d.ts +24 -1
- package/dist/runtime/executor/loop-supervisor.d.ts.map +1 -1
- package/dist/runtime/executor/loop-supervisor.js +191 -12
- package/dist/runtime/executor/loop-supervisor.js.map +1 -1
- package/dist/runtime/gateway/chat-session-dispatch.d.ts +1 -0
- package/dist/runtime/gateway/chat-session-dispatch.d.ts.map +1 -1
- package/dist/runtime/gateway/chat-session-dispatch.js +1 -0
- package/dist/runtime/gateway/chat-session-dispatch.js.map +1 -1
- package/dist/runtime/gateway/discord-gateway-adapter.d.ts.map +1 -1
- package/dist/runtime/gateway/discord-gateway-adapter.js +1 -0
- package/dist/runtime/gateway/discord-gateway-adapter.js.map +1 -1
- package/dist/runtime/gateway/signal-gateway-adapter.d.ts.map +1 -1
- package/dist/runtime/gateway/signal-gateway-adapter.js +1 -0
- package/dist/runtime/gateway/signal-gateway-adapter.js.map +1 -1
- package/dist/runtime/gateway/slack-channel-adapter.d.ts +4 -0
- package/dist/runtime/gateway/slack-channel-adapter.d.ts.map +1 -1
- package/dist/runtime/gateway/slack-channel-adapter.js +105 -10
- package/dist/runtime/gateway/slack-channel-adapter.js.map +1 -1
- package/dist/runtime/gateway/telegram-gateway-adapter.d.ts.map +1 -1
- package/dist/runtime/gateway/telegram-gateway-adapter.js +3 -1
- package/dist/runtime/gateway/telegram-gateway-adapter.js.map +1 -1
- package/dist/runtime/gateway/whatsapp-gateway-adapter.d.ts.map +1 -1
- package/dist/runtime/gateway/whatsapp-gateway-adapter.js +1 -0
- package/dist/runtime/gateway/whatsapp-gateway-adapter.js.map +1 -1
- package/dist/runtime/session-registry/index.d.ts +3 -0
- package/dist/runtime/session-registry/index.d.ts.map +1 -0
- package/dist/runtime/session-registry/index.js +3 -0
- package/dist/runtime/session-registry/index.js.map +1 -0
- package/dist/runtime/session-registry/registry.d.ts +39 -0
- package/dist/runtime/session-registry/registry.d.ts.map +1 -0
- package/dist/runtime/session-registry/registry.js +761 -0
- package/dist/runtime/session-registry/registry.js.map +1 -0
- package/dist/runtime/session-registry/types.d.ts +985 -0
- package/dist/runtime/session-registry/types.d.ts.map +1 -0
- package/dist/runtime/session-registry/types.js +108 -0
- package/dist/runtime/session-registry/types.js.map +1 -0
- package/dist/runtime/store/background-run-store.d.ts +75 -0
- package/dist/runtime/store/background-run-store.d.ts.map +1 -0
- package/dist/runtime/store/background-run-store.js +157 -0
- package/dist/runtime/store/background-run-store.js.map +1 -0
- package/dist/runtime/store/index.d.ts +2 -0
- package/dist/runtime/store/index.d.ts.map +1 -1
- package/dist/runtime/store/index.js +1 -0
- package/dist/runtime/store/index.js.map +1 -1
- package/dist/runtime/store/runtime-operation-schemas.d.ts +62 -22
- package/dist/runtime/store/runtime-operation-schemas.d.ts.map +1 -1
- package/dist/runtime/store/runtime-operation-schemas.js +5 -0
- package/dist/runtime/store/runtime-operation-schemas.js.map +1 -1
- package/dist/runtime/store/runtime-paths.d.ts +2 -0
- package/dist/runtime/store/runtime-paths.d.ts.map +1 -1
- package/dist/runtime/store/runtime-paths.js +6 -0
- package/dist/runtime/store/runtime-paths.js.map +1 -1
- package/dist/runtime/store/runtime-schemas.d.ts +6 -6
- package/dist/runtime/types/cron.d.ts +4 -4
- package/dist/runtime/types/daemon.d.ts +60 -0
- package/dist/runtime/types/daemon.d.ts.map +1 -1
- package/dist/runtime/types/daemon.js +14 -0
- package/dist/runtime/types/daemon.js.map +1 -1
- package/dist/runtime/types/envelope.d.ts +2 -2
- package/dist/runtime/types/notification.d.ts +1 -1
- package/dist/tools/builtin/exports.d.ts +4 -0
- package/dist/tools/builtin/exports.d.ts.map +1 -1
- package/dist/tools/builtin/exports.js +4 -0
- package/dist/tools/builtin/exports.js.map +1 -1
- package/dist/tools/builtin/factory.d.ts.map +1 -1
- package/dist/tools/builtin/factory.js +18 -0
- package/dist/tools/builtin/factory.js.map +1 -1
- package/dist/tools/fs/GlobTool/GlobTool.js +2 -2
- package/dist/tools/fs/GlobTool/GlobTool.js.map +1 -1
- package/dist/tools/fs/GrepTool/GrepTool.js +2 -2
- package/dist/tools/fs/GrepTool/GrepTool.js.map +1 -1
- package/dist/tools/fs/ReadTool/ReadTool.js +2 -2
- package/dist/tools/fs/ReadTool/ReadTool.js.map +1 -1
- package/dist/tools/kaggle/KaggleExperimentTools.d.ts +395 -0
- package/dist/tools/kaggle/KaggleExperimentTools.d.ts.map +1 -0
- package/dist/tools/kaggle/KaggleExperimentTools.js +923 -0
- package/dist/tools/kaggle/KaggleExperimentTools.js.map +1 -0
- package/dist/tools/kaggle/KaggleSubmissionTools.d.ts +241 -0
- package/dist/tools/kaggle/KaggleSubmissionTools.d.ts.map +1 -0
- package/dist/tools/kaggle/KaggleSubmissionTools.js +558 -0
- package/dist/tools/kaggle/KaggleSubmissionTools.js.map +1 -0
- package/dist/tools/kaggle/KaggleWorkspacePrepareTool.d.ts +105 -0
- package/dist/tools/kaggle/KaggleWorkspacePrepareTool.d.ts.map +1 -0
- package/dist/tools/kaggle/KaggleWorkspacePrepareTool.js +135 -0
- package/dist/tools/kaggle/KaggleWorkspacePrepareTool.js.map +1 -0
- package/dist/tools/kaggle/index.d.ts +6 -0
- package/dist/tools/kaggle/index.d.ts.map +1 -0
- package/dist/tools/kaggle/index.js +6 -0
- package/dist/tools/kaggle/index.js.map +1 -0
- package/dist/tools/kaggle/metrics.d.ts +89 -0
- package/dist/tools/kaggle/metrics.d.ts.map +1 -0
- package/dist/tools/kaggle/metrics.js +51 -0
- package/dist/tools/kaggle/metrics.js.map +1 -0
- package/dist/tools/kaggle/paths.d.ts +15 -0
- package/dist/tools/kaggle/paths.d.ts.map +1 -0
- package/dist/tools/kaggle/paths.js +136 -0
- package/dist/tools/kaggle/paths.js.map +1 -0
- package/dist/tools/network/GitHubCliTool/GitHubCliTool.d.ts +2 -2
- package/dist/tools/query/ArchitectureTool/ArchitectureTool.js +1 -1
- package/dist/tools/query/ArchitectureTool/ArchitectureTool.js.map +1 -1
- package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts +801 -0
- package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts.map +1 -0
- package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.js +147 -0
- package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.js.map +1 -0
- package/dist/tools/query/CodeReadContextTool/constants.d.ts +5 -0
- package/dist/tools/query/CodeReadContextTool/constants.d.ts.map +1 -0
- package/dist/tools/query/CodeReadContextTool/constants.js +5 -0
- package/dist/tools/query/CodeReadContextTool/constants.js.map +1 -0
- package/dist/tools/query/CodeReadContextTool/prompt.d.ts +2 -0
- package/dist/tools/query/CodeReadContextTool/prompt.d.ts.map +1 -0
- package/dist/tools/query/CodeReadContextTool/prompt.js +6 -0
- package/dist/tools/query/CodeReadContextTool/prompt.js.map +1 -0
- package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts +125 -0
- package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts.map +1 -0
- package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.js +97 -0
- package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.js.map +1 -0
- package/dist/tools/query/CodeSearchRepairTool/constants.d.ts +5 -0
- package/dist/tools/query/CodeSearchRepairTool/constants.d.ts.map +1 -0
- package/dist/tools/query/CodeSearchRepairTool/constants.js +5 -0
- package/dist/tools/query/CodeSearchRepairTool/constants.js.map +1 -0
- package/dist/tools/query/CodeSearchRepairTool/prompt.d.ts +2 -0
- package/dist/tools/query/CodeSearchRepairTool/prompt.d.ts.map +1 -0
- package/dist/tools/query/CodeSearchRepairTool/prompt.js +5 -0
- package/dist/tools/query/CodeSearchRepairTool/prompt.js.map +1 -0
- package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts +123 -0
- package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts.map +1 -0
- package/dist/tools/query/CodeSearchTool/CodeSearchTool.js +95 -0
- package/dist/tools/query/CodeSearchTool/CodeSearchTool.js.map +1 -0
- package/dist/tools/query/CodeSearchTool/constants.d.ts +5 -0
- package/dist/tools/query/CodeSearchTool/constants.d.ts.map +1 -0
- package/dist/tools/query/CodeSearchTool/constants.js +5 -0
- package/dist/tools/query/CodeSearchTool/constants.js.map +1 -0
- package/dist/tools/query/CodeSearchTool/prompt.d.ts +2 -0
- package/dist/tools/query/CodeSearchTool/prompt.d.ts.map +1 -0
- package/dist/tools/query/CodeSearchTool/prompt.js +6 -0
- package/dist/tools/query/CodeSearchTool/prompt.js.map +1 -0
- package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.d.ts +35 -7
- package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.d.ts.map +1 -1
- package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.js +128 -3
- package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.js.map +1 -1
- package/package.json +2 -1
|
@@ -6,6 +6,7 @@ import { execFile } from "node:child_process";
|
|
|
6
6
|
import * as fsp from "node:fs/promises";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import { getPulseedDirPath } from "../../base/utils/paths.js";
|
|
9
|
+
import { getSelfIdentityResponseForBaseDir } from "../../base/config/identity-loader.js";
|
|
9
10
|
import { loadProviderConfig } from "../../base/llm/provider-config.js";
|
|
10
11
|
import { TaskSchema } from "../../base/types/task.js";
|
|
11
12
|
import { ChatHistory } from "./chat-history.js";
|
|
@@ -17,12 +18,15 @@ import { toToolDefinitionsFiltered } from "../../tools/tool-definition-adapter.j
|
|
|
17
18
|
import { TendCommand } from "./tend-command.js";
|
|
18
19
|
import { EventSubscriber } from "./event-subscriber.js";
|
|
19
20
|
import { buildPromptedToolProtocolSystemPrompt, extractPromptedToolCalls, } from "../../orchestrator/execution/agent-loop/prompted-tool-protocol.js";
|
|
21
|
+
import { classifyFailureRecovery, formatFailureRecovery, formatLifecycleFailureMessage } from "./failure-recovery.js";
|
|
20
22
|
import { resolveExecutionPolicy, summarizeExecutionPolicy, withExecutionPolicyOverrides, } from "../../orchestrator/execution/agent-loop/execution-policy.js";
|
|
21
23
|
import { buildStandaloneIngressMessage, createIngressRouter, } from "./ingress-router.js";
|
|
24
|
+
import { createRuntimeSessionRegistry } from "../../runtime/session-registry/index.js";
|
|
22
25
|
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
23
26
|
const MAX_VERIFY_RETRIES = 2;
|
|
24
27
|
const MAX_TOOL_LOOPS = 5;
|
|
25
28
|
const ACTIVITY_PREVIEW_CHARS = 40;
|
|
29
|
+
const DIFF_ARTIFACT_MAX_LINES = 80;
|
|
26
30
|
const standaloneIngressRouter = createIngressRouter();
|
|
27
31
|
// ─── Command help text ───
|
|
28
32
|
const COMMAND_HELP = `Available commands:
|
|
@@ -35,6 +39,7 @@ Session
|
|
|
35
39
|
/resume [id|title] Resume native agentloop state for the current or selected session
|
|
36
40
|
/cleanup [--dry-run] Clean up stale chat sessions
|
|
37
41
|
/compact Summarize older chat turns and keep the latest turns
|
|
42
|
+
/context Show active working context and session assumptions
|
|
38
43
|
/exit Exit chat mode
|
|
39
44
|
|
|
40
45
|
Goals and tasks
|
|
@@ -68,14 +73,123 @@ function checkGitChanges(cwd) {
|
|
|
68
73
|
});
|
|
69
74
|
});
|
|
70
75
|
}
|
|
76
|
+
function runGit(cwd, args, timeout = 5_000) {
|
|
77
|
+
return new Promise((resolve) => {
|
|
78
|
+
execFile("git", args, { cwd, timeout }, (err, stdout, stderr) => {
|
|
79
|
+
if (err) {
|
|
80
|
+
resolve(null);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
resolve((stdout + stderr).trim());
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function parseGitLines(output) {
|
|
88
|
+
return output ? output.split("\n").map((line) => line.trim()).filter(Boolean) : [];
|
|
89
|
+
}
|
|
90
|
+
async function buildUntrackedFilePatch(cwd, relativePath) {
|
|
91
|
+
const absolutePath = path.resolve(cwd, relativePath);
|
|
92
|
+
const relativeFromCwd = path.relative(cwd, absolutePath);
|
|
93
|
+
if (relativeFromCwd.startsWith("..") || path.isAbsolute(relativeFromCwd)) {
|
|
94
|
+
return `diff --git a/${relativePath} b/${relativePath}\nnew file skipped: path outside workspace`;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const stat = await fsp.stat(absolutePath);
|
|
98
|
+
if (!stat.isFile()) {
|
|
99
|
+
return `diff --git a/${relativePath} b/${relativePath}\nnew file skipped: not a regular file`;
|
|
100
|
+
}
|
|
101
|
+
if (stat.size > 100_000) {
|
|
102
|
+
return `diff --git a/${relativePath} b/${relativePath}\nnew file skipped: ${stat.size} bytes`;
|
|
103
|
+
}
|
|
104
|
+
const content = await fsp.readFile(absolutePath, "utf-8");
|
|
105
|
+
const lines = content.split("\n");
|
|
106
|
+
const body = lines.map((line) => `+${line}`).join("\n");
|
|
107
|
+
return [
|
|
108
|
+
`diff --git a/${relativePath} b/${relativePath}`,
|
|
109
|
+
"new file mode 100644",
|
|
110
|
+
"--- /dev/null",
|
|
111
|
+
`+++ b/${relativePath}`,
|
|
112
|
+
`@@ -0,0 +1,${lines.length} @@`,
|
|
113
|
+
body,
|
|
114
|
+
].join("\n");
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return `diff --git a/${relativePath} b/${relativePath}\nnew file skipped: unreadable`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function collectGitDiffArtifact(cwd) {
|
|
121
|
+
const trackedStat = await runGit(cwd, ["diff", "HEAD", "--stat"]);
|
|
122
|
+
const untrackedFiles = parseGitLines(await runGit(cwd, ["ls-files", "--others", "--exclude-standard"]));
|
|
123
|
+
if (!trackedStat && untrackedFiles.length === 0)
|
|
124
|
+
return null;
|
|
125
|
+
const trackedNameStatus = await runGit(cwd, ["diff", "HEAD", "--name-status"]) ?? "";
|
|
126
|
+
const trackedPatch = await runGit(cwd, ["diff", "HEAD", "--patch", "--unified=3"], 10_000) ?? "";
|
|
127
|
+
const untrackedPatchParts = await Promise.all(untrackedFiles.slice(0, 10).map((file) => buildUntrackedFilePatch(cwd, file)));
|
|
128
|
+
if (untrackedFiles.length > 10) {
|
|
129
|
+
untrackedPatchParts.push(`... ${untrackedFiles.length - 10} additional untracked file(s) omitted`);
|
|
130
|
+
}
|
|
131
|
+
const stat = [
|
|
132
|
+
trackedStat,
|
|
133
|
+
untrackedFiles.length > 0
|
|
134
|
+
? ["Untracked files:", ...untrackedFiles.map((file) => ` ${file}`)].join("\n")
|
|
135
|
+
: "",
|
|
136
|
+
].filter(Boolean).join("\n");
|
|
137
|
+
const nameStatus = [
|
|
138
|
+
trackedNameStatus,
|
|
139
|
+
...untrackedFiles.map((file) => `A\t${file}`),
|
|
140
|
+
].filter(Boolean).join("\n");
|
|
141
|
+
const patch = [trackedPatch, ...untrackedPatchParts].filter(Boolean).join("\n");
|
|
142
|
+
const patchLines = patch.split("\n");
|
|
143
|
+
const truncated = patchLines.length > DIFF_ARTIFACT_MAX_LINES;
|
|
144
|
+
return {
|
|
145
|
+
stat,
|
|
146
|
+
nameStatus,
|
|
147
|
+
patch: patchLines.slice(0, DIFF_ARTIFACT_MAX_LINES).join("\n"),
|
|
148
|
+
truncated,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
71
151
|
function previewActivityText(value, maxChars = ACTIVITY_PREVIEW_CHARS) {
|
|
72
152
|
const normalized = value.replace(/\s+/g, " ").trim();
|
|
73
153
|
return normalized.length > maxChars ? `${normalized.slice(0, maxChars)}...` : normalized;
|
|
74
154
|
}
|
|
155
|
+
function classifyInterruptRedirect(input) {
|
|
156
|
+
const normalized = input.trim().toLowerCase();
|
|
157
|
+
if (/\b(background|bg)\b|バックグラウンド|裏で|裏側|continue.*background/.test(normalized)) {
|
|
158
|
+
return "background";
|
|
159
|
+
}
|
|
160
|
+
if (/\b(review|read.?only|readonly)\b|レビュー|確認だけ|読むだけ/.test(normalized)) {
|
|
161
|
+
return "review";
|
|
162
|
+
}
|
|
163
|
+
if (/\b(diff|changes?|patch)\b|差分|変更.*見|変更内容/.test(normalized)) {
|
|
164
|
+
return "diff";
|
|
165
|
+
}
|
|
166
|
+
if (/\b(stop|pause|summary|summarize|interrupt)\b|止め|停止|中断|一旦|要約/.test(normalized)) {
|
|
167
|
+
return "summary";
|
|
168
|
+
}
|
|
169
|
+
return "redirect";
|
|
170
|
+
}
|
|
75
171
|
function formatToolActivity(action, toolName, detail) {
|
|
76
172
|
const preview = detail ? previewActivityText(detail) : "";
|
|
77
173
|
return preview ? `${action} tool: ${toolName} - ${preview}` : `${action} tool: ${toolName}`;
|
|
78
174
|
}
|
|
175
|
+
function formatIntentInput(input, maxChars = 96) {
|
|
176
|
+
const normalized = input.replace(/\s+/g, " ").trim();
|
|
177
|
+
return normalized.length > maxChars ? `${normalized.slice(0, maxChars - 3)}...` : normalized;
|
|
178
|
+
}
|
|
179
|
+
function resolveSelfIdentityResponse(input, baseDir) {
|
|
180
|
+
const normalized = input.trim().toLowerCase().replace(/\s+/g, "");
|
|
181
|
+
if (!normalized)
|
|
182
|
+
return null;
|
|
183
|
+
const isEnglishIdentityQuestion = /^(whoareyou|whatisyourname|what'syourname)[?]?$/.test(normalized);
|
|
184
|
+
const isIdentityQuestion = [
|
|
185
|
+
/^(あなた|君|きみ|お前|おまえ)(は|って)?(誰|だれ|何者|なにもの)(ですか|なの|です)?[??]?$/,
|
|
186
|
+
/^(あなた|君|きみ|お前|おまえ)の名前(は|って)?(何|なに)(ですか|なの|です)?[??]?$/,
|
|
187
|
+
/^名前(は|って)?(何|なに)(ですか|なの|です)?[??]?$/,
|
|
188
|
+
].some((pattern) => pattern.test(normalized));
|
|
189
|
+
if (!isIdentityQuestion && !isEnglishIdentityQuestion)
|
|
190
|
+
return null;
|
|
191
|
+
return getSelfIdentityResponseForBaseDir(baseDir, isEnglishIdentityQuestion ? "en" : "ja");
|
|
192
|
+
}
|
|
79
193
|
// ─── ChatRunner ───
|
|
80
194
|
export class ChatRunner {
|
|
81
195
|
deps;
|
|
@@ -101,6 +215,8 @@ export class ChatRunner {
|
|
|
101
215
|
nativeAgentLoopStatePath = null;
|
|
102
216
|
runtimeControlContext = null;
|
|
103
217
|
sessionExecutionPolicy = null;
|
|
218
|
+
lastSelectedRoute = null;
|
|
219
|
+
activeTurn = null;
|
|
104
220
|
constructor(deps) {
|
|
105
221
|
this.deps = deps;
|
|
106
222
|
this.groundingGateway = createChatGroundingGateway({
|
|
@@ -138,6 +254,68 @@ export class ChatRunner {
|
|
|
138
254
|
getCurrentSessionMessages() {
|
|
139
255
|
return this.history?.getMessages() ?? [];
|
|
140
256
|
}
|
|
257
|
+
hasActiveTurn() {
|
|
258
|
+
return this.activeTurn !== null;
|
|
259
|
+
}
|
|
260
|
+
async interruptAndRedirect(input, cwd, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
261
|
+
const activeTurn = this.activeTurn;
|
|
262
|
+
if (!activeTurn) {
|
|
263
|
+
return this.execute(input, cwd, timeoutMs);
|
|
264
|
+
}
|
|
265
|
+
const start = Date.now();
|
|
266
|
+
const redirect = classifyInterruptRedirect(input);
|
|
267
|
+
if (redirect === "background") {
|
|
268
|
+
return this.emitEphemeralAssistantResult(input, [
|
|
269
|
+
"Continuing this same turn in the background is not available yet.",
|
|
270
|
+
"",
|
|
271
|
+
"The active turn is still running in the foreground.",
|
|
272
|
+
"Use /tend for daemon-backed work, or send a narrower follow-up request.",
|
|
273
|
+
].join("\n"), true, start);
|
|
274
|
+
}
|
|
275
|
+
activeTurn.interruptRequested = true;
|
|
276
|
+
if (!activeTurn.abortController.signal.aborted) {
|
|
277
|
+
activeTurn.abortController.abort();
|
|
278
|
+
}
|
|
279
|
+
this.emitCheckpoint("Interrupt requested", `Redirect: ${previewActivityText(input, 120)}`, activeTurn.context, "interrupt");
|
|
280
|
+
const stopped = await this.waitForActiveTurn(activeTurn, 2_000);
|
|
281
|
+
if (!stopped) {
|
|
282
|
+
return this.emitEphemeralAssistantResult(input, "Interrupt requested. The active turn will stop at the next safe point.", false, start);
|
|
283
|
+
}
|
|
284
|
+
if (redirect === "redirect") {
|
|
285
|
+
return this.execute(input, cwd, timeoutMs);
|
|
286
|
+
}
|
|
287
|
+
let output;
|
|
288
|
+
if (redirect === "diff") {
|
|
289
|
+
const diff = await collectGitDiffArtifact(activeTurn.cwd);
|
|
290
|
+
if (diff) {
|
|
291
|
+
const context = this.createEventContext();
|
|
292
|
+
this.emitDiffArtifact(diff, context);
|
|
293
|
+
output = "Interrupted the active turn. Current diff is shown above.";
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
output = "Interrupted the active turn. No working-tree changes were detected.";
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else if (redirect === "review") {
|
|
300
|
+
const review = await this.handleReview(start);
|
|
301
|
+
output = `Interrupted the active turn and switched to review-only mode.\n\n${review.output}`;
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
output = [
|
|
305
|
+
"Interrupted the active turn.",
|
|
306
|
+
"",
|
|
307
|
+
"Recent activity",
|
|
308
|
+
...(activeTurn.recentEvents.length > 0
|
|
309
|
+
? activeTurn.recentEvents.slice(-6).map((event) => `- ${event}`)
|
|
310
|
+
: ["- No activity was captured before the interrupt."]),
|
|
311
|
+
"",
|
|
312
|
+
"Next actions",
|
|
313
|
+
"- Ask for the exact continuation you want.",
|
|
314
|
+
"- Ask to show diff or switch to review if files may have changed.",
|
|
315
|
+
].join("\n");
|
|
316
|
+
}
|
|
317
|
+
return this.emitEphemeralAssistantResult(input, output, true, start);
|
|
318
|
+
}
|
|
141
319
|
setRuntimeControlContext(context) {
|
|
142
320
|
this.runtimeControlContext = context;
|
|
143
321
|
}
|
|
@@ -146,7 +324,11 @@ export class ChatRunner {
|
|
|
146
324
|
throw new Error("executeIngressMessage requires selectedRoute; use CrossPlatformChatSessionManager for ingress route selection.");
|
|
147
325
|
}
|
|
148
326
|
const runtimeControlContext = this.buildRuntimeControlContextFromIngress(ingress);
|
|
149
|
-
return this.execute(ingress.text, cwd, timeoutMs, {
|
|
327
|
+
return this.execute(ingress.text, cwd, timeoutMs, {
|
|
328
|
+
selectedRoute,
|
|
329
|
+
runtimeControlContext,
|
|
330
|
+
goalId: ingress.goal_id,
|
|
331
|
+
});
|
|
150
332
|
}
|
|
151
333
|
resolveRouteFromIngress(ingress) {
|
|
152
334
|
return standaloneIngressRouter.selectRoute(ingress, this.getRouteCapabilities());
|
|
@@ -160,6 +342,9 @@ export class ChatRunner {
|
|
|
160
342
|
hasAgentLoop: this.deps.chatAgentLoopRunner !== undefined,
|
|
161
343
|
hasToolLoop: this.deps.llmClient !== undefined,
|
|
162
344
|
hasRuntimeControlService: this.deps.runtimeControlService !== undefined,
|
|
345
|
+
hasDaemonTend: this.deps.llmClient !== undefined
|
|
346
|
+
&& this.deps.goalNegotiator !== undefined
|
|
347
|
+
&& this.deps.daemonClient !== undefined,
|
|
163
348
|
};
|
|
164
349
|
}
|
|
165
350
|
buildStandaloneIngressMessage(input, runtimeControlContext) {
|
|
@@ -173,6 +358,24 @@ export class ChatRunner {
|
|
|
173
358
|
const runtimeApprovalFn = runtimeControlContext?.approvalFn
|
|
174
359
|
?? this.deps.runtimeControlApprovalFn
|
|
175
360
|
?? this.deps.approvalFn;
|
|
361
|
+
const replyTarget = runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget;
|
|
362
|
+
const replyTargetInput = replyTarget
|
|
363
|
+
? {
|
|
364
|
+
...(replyTarget.surface ? { surface: replyTarget.surface } : {}),
|
|
365
|
+
channel,
|
|
366
|
+
...(replyTarget.platform ? { platform: replyTarget.platform } : {}),
|
|
367
|
+
...(replyTarget.conversation_id ? { conversation_id: replyTarget.conversation_id } : {}),
|
|
368
|
+
...(replyTarget.message_id ? { message_id: replyTarget.message_id } : {}),
|
|
369
|
+
...(replyTarget.response_channel ? { response_channel: replyTarget.response_channel } : {}),
|
|
370
|
+
...(replyTarget.outbox_topic ? { outbox_topic: replyTarget.outbox_topic } : {}),
|
|
371
|
+
...(replyTarget.identity_key ? { identity_key: replyTarget.identity_key } : {}),
|
|
372
|
+
...(replyTarget.user_id ? { user_id: replyTarget.user_id } : {}),
|
|
373
|
+
...(replyTarget.deliveryMode === "reply" || replyTarget.deliveryMode === "notify" || replyTarget.deliveryMode === "thread_reply"
|
|
374
|
+
? { deliveryMode: replyTarget.deliveryMode }
|
|
375
|
+
: {}),
|
|
376
|
+
...(replyTarget.metadata ? { metadata: replyTarget.metadata } : {}),
|
|
377
|
+
}
|
|
378
|
+
: undefined;
|
|
176
379
|
return buildStandaloneIngressMessage({
|
|
177
380
|
text: input,
|
|
178
381
|
channel,
|
|
@@ -181,7 +384,7 @@ export class ChatRunner {
|
|
|
181
384
|
conversation_id: runtimeControlContext?.replyTarget?.conversation_id ?? this.deps.runtimeReplyTarget?.conversation_id,
|
|
182
385
|
user_id: runtimeControlContext?.replyTarget?.user_id ?? this.deps.runtimeReplyTarget?.user_id,
|
|
183
386
|
actor: runtimeControlContext?.actor ?? this.deps.runtimeControlActor,
|
|
184
|
-
replyTarget:
|
|
387
|
+
replyTarget: replyTargetInput,
|
|
185
388
|
runtimeControl: {
|
|
186
389
|
allowed: true,
|
|
187
390
|
approvalMode: "interactive",
|
|
@@ -222,15 +425,94 @@ export class ChatRunner {
|
|
|
222
425
|
...(session.agentLoop ? { agentLoop: session.agentLoop } : {}),
|
|
223
426
|
};
|
|
224
427
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
428
|
+
formatRuntimeTimestamp(value) {
|
|
429
|
+
return value ?? "unknown";
|
|
430
|
+
}
|
|
431
|
+
formatRuntimeTitle(value) {
|
|
432
|
+
return value ? ` "${value}"` : "";
|
|
433
|
+
}
|
|
434
|
+
runtimeWarningLine(warnings) {
|
|
435
|
+
return warnings.length > 0 ? `Warnings: ${warnings.length}` : null;
|
|
436
|
+
}
|
|
437
|
+
activeRuntimeSession(session) {
|
|
438
|
+
return session.status === "active";
|
|
439
|
+
}
|
|
440
|
+
statusRuntimeRun(run) {
|
|
441
|
+
return run.status === "queued"
|
|
442
|
+
|| run.status === "running"
|
|
443
|
+
|| run.status === "failed"
|
|
444
|
+
|| run.status === "timed_out"
|
|
445
|
+
|| run.status === "lost";
|
|
446
|
+
}
|
|
447
|
+
compactRunLine(run) {
|
|
448
|
+
const title = this.formatRuntimeTitle(run.title);
|
|
449
|
+
const updated = this.formatRuntimeTimestamp(run.updated_at ?? run.started_at ?? run.created_at);
|
|
450
|
+
const summary = run.summary ? ` - ${run.summary.replace(/\s+/g, " ").trim()}` : "";
|
|
451
|
+
const error = run.error ? ` - error: ${run.error.replace(/\s+/g, " ").trim()}` : "";
|
|
452
|
+
return `- ${run.id}${title} [${run.kind}, ${run.status}], updated ${updated}${summary}${error}`;
|
|
453
|
+
}
|
|
454
|
+
compactSessionLine(session) {
|
|
455
|
+
const displayId = session.kind === "conversation"
|
|
456
|
+
? session.transcript_ref?.id ?? session.id.replace(/^session:conversation:/, "")
|
|
457
|
+
: session.id;
|
|
458
|
+
const title = this.formatRuntimeTitle(session.title);
|
|
459
|
+
const updated = this.formatRuntimeTimestamp(session.updated_at ?? session.last_event_at ?? session.created_at);
|
|
460
|
+
const workspace = session.workspace ? `, cwd ${session.workspace}` : "";
|
|
461
|
+
const resumable = session.resumable ? ", resumable" : "";
|
|
462
|
+
const attachable = session.attachable ? ", attachable" : "";
|
|
463
|
+
const runtimeId = displayId === session.id ? "" : `, runtime ${session.id}`;
|
|
464
|
+
return `- ${displayId}${title} [${session.kind}, ${session.status}], updated ${updated}${workspace}${resumable}${attachable}${runtimeId}`;
|
|
465
|
+
}
|
|
466
|
+
formatRuntimeSessionsList(snapshot) {
|
|
467
|
+
const chatSessions = snapshot.sessions.filter((session) => session.kind === "conversation");
|
|
468
|
+
const nonChatSessions = snapshot.sessions.filter((session) => session.kind !== "conversation");
|
|
469
|
+
const lines = ["Chat sessions:"];
|
|
470
|
+
if (chatSessions.length === 0) {
|
|
471
|
+
lines.push("No chat sessions found.");
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
for (const session of chatSessions) {
|
|
475
|
+
lines.push(this.compactSessionLine(session));
|
|
476
|
+
const runs = snapshot.background_runs.filter((run) => run.parent_session_id === session.id);
|
|
477
|
+
for (const run of runs) {
|
|
478
|
+
lines.push(` ${this.compactRunLine(run)}`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
if (nonChatSessions.length > 0) {
|
|
483
|
+
lines.push("", "Other runtime sessions:");
|
|
484
|
+
lines.push(...nonChatSessions.map((session) => this.compactSessionLine(session)));
|
|
485
|
+
}
|
|
486
|
+
if (snapshot.background_runs.length > 0) {
|
|
487
|
+
lines.push("", "Background runs:");
|
|
488
|
+
lines.push(...snapshot.background_runs.map((run) => this.compactRunLine(run)));
|
|
489
|
+
}
|
|
490
|
+
const warningLine = this.runtimeWarningLine(snapshot.warnings);
|
|
491
|
+
if (warningLine)
|
|
492
|
+
lines.push("", warningLine);
|
|
493
|
+
return lines.join("\n");
|
|
494
|
+
}
|
|
495
|
+
formatRuntimeStatus(snapshot) {
|
|
496
|
+
const activeSessions = snapshot.sessions.filter((session) => this.activeRuntimeSession(session));
|
|
497
|
+
const statusRuns = snapshot.background_runs.filter((run) => this.statusRuntimeRun(run));
|
|
498
|
+
const lines = [];
|
|
499
|
+
if (activeSessions.length > 0) {
|
|
500
|
+
lines.push("Active runtime sessions:");
|
|
501
|
+
lines.push(...activeSessions.map((session) => this.compactSessionLine(session)));
|
|
502
|
+
}
|
|
503
|
+
if (statusRuns.length > 0) {
|
|
504
|
+
if (lines.length > 0)
|
|
505
|
+
lines.push("");
|
|
506
|
+
lines.push("Background runs (queued/running/attention-needed):");
|
|
507
|
+
lines.push(...statusRuns.map((run) => this.compactRunLine(run)));
|
|
508
|
+
}
|
|
509
|
+
const warningLine = this.runtimeWarningLine(snapshot.warnings);
|
|
510
|
+
if (warningLine) {
|
|
511
|
+
if (lines.length > 0)
|
|
512
|
+
lines.push("");
|
|
513
|
+
lines.push(warningLine);
|
|
514
|
+
}
|
|
515
|
+
return lines.length > 0 ? lines.join("\n") : "No active runtime sessions or running/failed/lost background runs found.";
|
|
234
516
|
}
|
|
235
517
|
formatHistory(session) {
|
|
236
518
|
const title = session.title ? ` "${session.title}"` : "";
|
|
@@ -319,14 +601,19 @@ export class ChatRunner {
|
|
|
319
601
|
];
|
|
320
602
|
return { success: true, output: lines.join("\n"), elapsed_ms: Date.now() - start };
|
|
321
603
|
}
|
|
322
|
-
const
|
|
604
|
+
const registry = createRuntimeSessionRegistry({ stateManager: this.deps.stateManager });
|
|
605
|
+
const [goals, runtimeSnapshot] = await Promise.all([
|
|
606
|
+
this.loadGoals(),
|
|
607
|
+
registry.snapshot(),
|
|
608
|
+
]);
|
|
323
609
|
const active = this.activeGoals(goals);
|
|
610
|
+
const runtimeStatus = this.formatRuntimeStatus(runtimeSnapshot);
|
|
324
611
|
if (active.length === 0) {
|
|
325
|
-
return { success: true, output:
|
|
612
|
+
return { success: true, output: `No active goals found.\n\n${runtimeStatus}`, elapsed_ms: Date.now() - start };
|
|
326
613
|
}
|
|
327
614
|
return {
|
|
328
615
|
success: true,
|
|
329
|
-
output: `Active goals:\n${active.map((goal) => this.formatGoalLine(goal)).join("\n")}`,
|
|
616
|
+
output: `Active goals:\n${active.map((goal) => this.formatGoalLine(goal)).join("\n")}\n\n${runtimeStatus}`,
|
|
330
617
|
elapsed_ms: Date.now() - start,
|
|
331
618
|
};
|
|
332
619
|
}
|
|
@@ -775,7 +1062,79 @@ export class ChatRunner {
|
|
|
775
1062
|
elapsed_ms: Date.now() - start,
|
|
776
1063
|
};
|
|
777
1064
|
}
|
|
778
|
-
|
|
1065
|
+
formatRoute(route) {
|
|
1066
|
+
if (!route)
|
|
1067
|
+
return "none selected yet";
|
|
1068
|
+
const details = [
|
|
1069
|
+
`lane=${route.lane}`,
|
|
1070
|
+
`kind=${route.kind}`,
|
|
1071
|
+
`reason=${route.reason}`,
|
|
1072
|
+
];
|
|
1073
|
+
if (route.kind === "direct_answer") {
|
|
1074
|
+
details.push(`model_tier=${route.modelTier}`, `max_tokens=${route.maxTokens}`);
|
|
1075
|
+
}
|
|
1076
|
+
if (route.kind === "runtime_control") {
|
|
1077
|
+
details.push(`intent=${route.intent.kind}`);
|
|
1078
|
+
}
|
|
1079
|
+
return details.join(", ");
|
|
1080
|
+
}
|
|
1081
|
+
async handleContext(start, cwdOverride) {
|
|
1082
|
+
const cwd = this.sessionCwd ?? (cwdOverride ? resolveGitRoot(cwdOverride) : process.cwd());
|
|
1083
|
+
const session = this.history?.getSessionData() ?? null;
|
|
1084
|
+
const messages = session?.messages ?? [];
|
|
1085
|
+
const policy = await this.getSessionExecutionPolicy();
|
|
1086
|
+
const recentMessages = messages.slice(-6);
|
|
1087
|
+
const userTurns = messages.filter((message) => message.role === "user").length;
|
|
1088
|
+
const assistantTurns = messages.filter((message) => message.role === "assistant").length;
|
|
1089
|
+
const compactionSummary = session?.compactionSummary?.trim() ?? "";
|
|
1090
|
+
const agentLoopPath = this.nativeAgentLoopStatePath ?? session?.agentLoopStatePath ?? null;
|
|
1091
|
+
const replyTarget = this.runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null;
|
|
1092
|
+
const routeCapabilities = this.getRouteCapabilities();
|
|
1093
|
+
const replyTargetParts = replyTarget
|
|
1094
|
+
? [replyTarget.surface, replyTarget.platform, replyTarget.conversation_id].filter(Boolean)
|
|
1095
|
+
: [];
|
|
1096
|
+
const contextLines = [
|
|
1097
|
+
"Working context",
|
|
1098
|
+
"",
|
|
1099
|
+
"Session",
|
|
1100
|
+
`- session_id: ${this.history?.getSessionId() ?? "none"}`,
|
|
1101
|
+
`- cwd: ${cwd}`,
|
|
1102
|
+
`- messages: ${messages.length} (${userTurns} user, ${assistantTurns} assistant)`,
|
|
1103
|
+
`- recent_turns_retained: ${recentMessages.length}`,
|
|
1104
|
+
`- compaction_summary: ${compactionSummary ? "present" : "none"}`,
|
|
1105
|
+
`- agentloop_state_path: ${agentLoopPath ?? "none"}`,
|
|
1106
|
+
"",
|
|
1107
|
+
"Turn context",
|
|
1108
|
+
`- last_selected_route: ${this.formatRoute(this.lastSelectedRoute)}`,
|
|
1109
|
+
`- reply_target: ${replyTargetParts.length > 0 ? replyTargetParts.join(":") : "none"}`,
|
|
1110
|
+
`- route_capabilities: light_llm=${routeCapabilities.hasLightweightLlm}, agent_loop=${routeCapabilities.hasAgentLoop}, tool_loop=${routeCapabilities.hasToolLoop}, runtime_control=${routeCapabilities.hasRuntimeControlService}, daemon_tend=${routeCapabilities.hasDaemonTend}`,
|
|
1111
|
+
"",
|
|
1112
|
+
"Working assumptions",
|
|
1113
|
+
"- this view exposes operational context, not hidden reasoning",
|
|
1114
|
+
"- last_selected_route describes the most recent non-command turn in this ChatRunner",
|
|
1115
|
+
"- future turns may select a different route based on the next input",
|
|
1116
|
+
"",
|
|
1117
|
+
"Active constraints",
|
|
1118
|
+
...summarizeExecutionPolicy(policy).split("\n").map((line) => `- ${line}`),
|
|
1119
|
+
"",
|
|
1120
|
+
"Included context",
|
|
1121
|
+
"- current session cwd and execution policy because they constrain tool and route behavior",
|
|
1122
|
+
`- ${recentMessages.length} latest persisted message(s)`,
|
|
1123
|
+
`- ${compactionSummary ? "compacted older chat summary because older turns were summarized" : "no compacted older chat summary because none is stored"}`,
|
|
1124
|
+
`- ${agentLoopPath ? "native agent-loop resume path because this session can persist agent-loop state" : "no native agent-loop resume path because none is active"}`,
|
|
1125
|
+
"",
|
|
1126
|
+
"Not included",
|
|
1127
|
+
"- hidden reasoning or private model chain-of-thought",
|
|
1128
|
+
"- raw state files unless a command explicitly reads them",
|
|
1129
|
+
"- older chat turns beyond the retained window unless compacted into the session summary",
|
|
1130
|
+
];
|
|
1131
|
+
return {
|
|
1132
|
+
success: true,
|
|
1133
|
+
output: contextLines.join("\n"),
|
|
1134
|
+
elapsed_ms: Date.now() - start,
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
async handleCommand(input, cwd) {
|
|
779
1138
|
const trimmed = input.trim();
|
|
780
1139
|
if (!trimmed.startsWith("/"))
|
|
781
1140
|
return null;
|
|
@@ -789,9 +1148,9 @@ export class ChatRunner {
|
|
|
789
1148
|
return { success: true, output: "Conversation history cleared.", elapsed_ms: Date.now() - start };
|
|
790
1149
|
}
|
|
791
1150
|
if (cmd === "/sessions") {
|
|
792
|
-
const
|
|
793
|
-
const
|
|
794
|
-
return { success: true, output: this.
|
|
1151
|
+
const registry = createRuntimeSessionRegistry({ stateManager: this.deps.stateManager });
|
|
1152
|
+
const snapshot = await registry.snapshot();
|
|
1153
|
+
return { success: true, output: this.formatRuntimeSessionsList(snapshot), elapsed_ms: Date.now() - start };
|
|
795
1154
|
}
|
|
796
1155
|
if (cmd === "/history") {
|
|
797
1156
|
const catalog = new ChatSessionCatalog(this.deps.stateManager);
|
|
@@ -864,6 +1223,9 @@ export class ChatRunner {
|
|
|
864
1223
|
if (cmd === "/usage") {
|
|
865
1224
|
return this.handleUsage(trimmed.slice("/usage".length).trim(), start);
|
|
866
1225
|
}
|
|
1226
|
+
if (cmd === "/context" || cmd === "/working-memory") {
|
|
1227
|
+
return this.handleContext(start, cwd);
|
|
1228
|
+
}
|
|
867
1229
|
if (cmd === "/review") {
|
|
868
1230
|
return this.handleReview(start);
|
|
869
1231
|
}
|
|
@@ -873,6 +1235,26 @@ export class ChatRunner {
|
|
|
873
1235
|
if (cmd === "/undo") {
|
|
874
1236
|
return this.handleUndo(start);
|
|
875
1237
|
}
|
|
1238
|
+
if (cmd === "/retry") {
|
|
1239
|
+
return {
|
|
1240
|
+
success: false,
|
|
1241
|
+
output: [
|
|
1242
|
+
"/retry is not supported yet.",
|
|
1243
|
+
"",
|
|
1244
|
+
formatFailureRecovery({
|
|
1245
|
+
kind: "runtime_interruption",
|
|
1246
|
+
label: "Retry unavailable",
|
|
1247
|
+
summary: "PulSeed does not yet have a safe replay contract for the previous turn.",
|
|
1248
|
+
nextActions: [
|
|
1249
|
+
"Use /review to inspect any current diff before continuing.",
|
|
1250
|
+
"Use /resume when PulSeed reports resumable agent-loop state.",
|
|
1251
|
+
"Ask for the exact next step to rerun instead of replaying the full turn.",
|
|
1252
|
+
],
|
|
1253
|
+
}),
|
|
1254
|
+
].join("\n"),
|
|
1255
|
+
elapsed_ms: Date.now() - start,
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
876
1258
|
if (cmd === "/exit") {
|
|
877
1259
|
return { success: true, output: "Exiting chat mode.", elapsed_ms: Date.now() - start };
|
|
878
1260
|
}
|
|
@@ -1073,6 +1455,9 @@ export class ChatRunner {
|
|
|
1073
1455
|
daemonClient: this.deps.daemonClient,
|
|
1074
1456
|
stateManager: this.deps.stateManager,
|
|
1075
1457
|
chatHistory: history,
|
|
1458
|
+
sessionId: this.history?.getSessionId() ?? null,
|
|
1459
|
+
workspace: this.sessionCwd ?? process.cwd(),
|
|
1460
|
+
replyTarget: this.runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null,
|
|
1076
1461
|
};
|
|
1077
1462
|
const tendCommand = new TendCommand();
|
|
1078
1463
|
const result = await tendCommand.execute(args, tendDeps);
|
|
@@ -1138,7 +1523,34 @@ export class ChatRunner {
|
|
|
1138
1523
|
}
|
|
1139
1524
|
}
|
|
1140
1525
|
try {
|
|
1141
|
-
|
|
1526
|
+
const tendDeps = {
|
|
1527
|
+
llmClient: this.deps.llmClient,
|
|
1528
|
+
goalNegotiator: this.deps.goalNegotiator,
|
|
1529
|
+
daemonClient: this.deps.daemonClient,
|
|
1530
|
+
stateManager: this.deps.stateManager,
|
|
1531
|
+
chatHistory: this.history?.getMessages() ?? [],
|
|
1532
|
+
sessionId: this.history?.getSessionId() ?? null,
|
|
1533
|
+
workspace: this.sessionCwd ?? process.cwd(),
|
|
1534
|
+
replyTarget: this.runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null,
|
|
1535
|
+
};
|
|
1536
|
+
const result = await new TendCommand().startAcceptedGoal(goalId, maxIterations, tendDeps);
|
|
1537
|
+
if (!result.success) {
|
|
1538
|
+
if (subscriber) {
|
|
1539
|
+
subscriber.unsubscribe();
|
|
1540
|
+
this.activeSubscribers.delete(goalId);
|
|
1541
|
+
}
|
|
1542
|
+
return {
|
|
1543
|
+
success: false,
|
|
1544
|
+
output: result.message,
|
|
1545
|
+
elapsed_ms: Date.now() - start,
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
const shortId = goalId.length > 12 ? goalId.slice(0, 12) : goalId;
|
|
1549
|
+
return {
|
|
1550
|
+
success: true,
|
|
1551
|
+
output: `[tend] ${shortId}: Started — daemon is now tending your goal${maxIterations !== undefined ? ` (max ${maxIterations} iterations)` : ""}.\nBackground run: ${result.backgroundRunId}\nRun 'pulseed status' to check progress.`,
|
|
1552
|
+
elapsed_ms: Date.now() - start,
|
|
1553
|
+
};
|
|
1142
1554
|
}
|
|
1143
1555
|
catch (err) {
|
|
1144
1556
|
if (subscriber) {
|
|
@@ -1152,13 +1564,6 @@ export class ChatRunner {
|
|
|
1152
1564
|
elapsed_ms: Date.now() - start,
|
|
1153
1565
|
};
|
|
1154
1566
|
}
|
|
1155
|
-
const iterNote = maxIterations !== undefined ? ` (max ${maxIterations} iterations)` : "";
|
|
1156
|
-
const shortId = goalId.length > 12 ? goalId.slice(0, 12) : goalId;
|
|
1157
|
-
return {
|
|
1158
|
-
success: true,
|
|
1159
|
-
output: `[tend] ${shortId}: Started — daemon is now tending your goal${iterNote}.\nRun 'pulseed status' to check progress.`,
|
|
1160
|
-
elapsed_ms: Date.now() - start,
|
|
1161
|
-
};
|
|
1162
1567
|
}
|
|
1163
1568
|
/**
|
|
1164
1569
|
* Execute a single chat turn.
|
|
@@ -1174,11 +1579,13 @@ export class ChatRunner {
|
|
|
1174
1579
|
*/
|
|
1175
1580
|
async execute(input, cwd, timeoutMs = DEFAULT_TIMEOUT_MS, options = {}) {
|
|
1176
1581
|
const eventContext = this.createEventContext();
|
|
1582
|
+
const activeTurn = this.beginActiveTurn(eventContext, resolveGitRoot(cwd));
|
|
1177
1583
|
const resumeCommand = this.parseResumeCommand(input);
|
|
1178
1584
|
const resumeOnly = resumeCommand !== null;
|
|
1179
1585
|
const runtimeControlContext = options.runtimeControlContext ?? this.runtimeControlContext;
|
|
1586
|
+
const executionGoalId = options.goalId ?? this.deps.goalId;
|
|
1180
1587
|
// Intercept commands before any adapter call
|
|
1181
|
-
const commandResult = resumeOnly ? null : await this.handleCommand(input);
|
|
1588
|
+
const commandResult = resumeOnly ? null : await this.handleCommand(input, cwd);
|
|
1182
1589
|
if (commandResult !== null) {
|
|
1183
1590
|
if (commandResult.output) {
|
|
1184
1591
|
this.emitEvent({
|
|
@@ -1207,11 +1614,24 @@ export class ChatRunner {
|
|
|
1207
1614
|
}
|
|
1208
1615
|
if (resumeOnly && resumeCommand.selector) {
|
|
1209
1616
|
try {
|
|
1617
|
+
const selectorResolution = await this.resolveChatResumeSelector(resumeCommand.selector);
|
|
1618
|
+
if (selectorResolution.nonResumableMessage) {
|
|
1619
|
+
const elapsed_ms = 0;
|
|
1620
|
+
const output = selectorResolution.nonResumableMessage;
|
|
1621
|
+
this.emitEvent({
|
|
1622
|
+
type: "assistant_final",
|
|
1623
|
+
text: output,
|
|
1624
|
+
persisted: false,
|
|
1625
|
+
...this.eventBase(eventContext),
|
|
1626
|
+
});
|
|
1627
|
+
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1628
|
+
return { success: false, output, elapsed_ms };
|
|
1629
|
+
}
|
|
1210
1630
|
const catalog = new ChatSessionCatalog(this.deps.stateManager);
|
|
1211
|
-
const session = await catalog.loadSessionBySelector(
|
|
1631
|
+
const session = await catalog.loadSessionBySelector(selectorResolution.chatSelector);
|
|
1212
1632
|
if (!session) {
|
|
1213
1633
|
const elapsed_ms = 0;
|
|
1214
|
-
const output = `No chat session matched selector "${
|
|
1634
|
+
const output = `No chat session matched selector "${selectorResolution.chatSelector}".`;
|
|
1215
1635
|
this.emitEvent({
|
|
1216
1636
|
type: "assistant_final",
|
|
1217
1637
|
text: output,
|
|
@@ -1244,7 +1664,9 @@ export class ChatRunner {
|
|
|
1244
1664
|
this.nativeAgentLoopStatePath = `chat/agentloop/${sessionId}.state.json`;
|
|
1245
1665
|
this.history.setAgentLoopStatePath(this.nativeAgentLoopStatePath);
|
|
1246
1666
|
}
|
|
1667
|
+
const executionCwd = this.sessionCwd ?? cwd;
|
|
1247
1668
|
const gitRoot = this.sessionCwd ?? resolveGitRoot(cwd);
|
|
1669
|
+
activeTurn.cwd = gitRoot;
|
|
1248
1670
|
// history is always assigned by this point (either by startSession or the block above)
|
|
1249
1671
|
const history = this.history;
|
|
1250
1672
|
this.emitEvent({
|
|
@@ -1259,7 +1681,7 @@ export class ChatRunner {
|
|
|
1259
1681
|
// Build static grounding once per session; dynamic context is rebuilt each turn.
|
|
1260
1682
|
if (this.cachedStaticSystemPrompt === null) {
|
|
1261
1683
|
try {
|
|
1262
|
-
this.cachedStaticSystemPrompt = buildStaticSystemPrompt();
|
|
1684
|
+
this.cachedStaticSystemPrompt = buildStaticSystemPrompt(this.providerConfigBaseDir());
|
|
1263
1685
|
}
|
|
1264
1686
|
catch {
|
|
1265
1687
|
this.cachedStaticSystemPrompt = "";
|
|
@@ -1284,14 +1706,41 @@ export class ChatRunner {
|
|
|
1284
1706
|
const selectedRoute = resumeOnly
|
|
1285
1707
|
? null
|
|
1286
1708
|
: (options.selectedRoute ?? this.resolveRouteFromInput(input, runtimeControlContext));
|
|
1709
|
+
this.lastSelectedRoute = selectedRoute;
|
|
1287
1710
|
const directPrompt = historyBlock ? `${historyBlock}${input}` : input;
|
|
1711
|
+
if (!resumeOnly) {
|
|
1712
|
+
this.emitIntent(input, selectedRoute, eventContext);
|
|
1713
|
+
}
|
|
1714
|
+
else if (resumeOnly) {
|
|
1715
|
+
this.emitIntent(input, null, eventContext);
|
|
1716
|
+
}
|
|
1288
1717
|
const start = Date.now();
|
|
1289
1718
|
const assistantBuffer = { text: "" };
|
|
1290
1719
|
const turnUsage = this.zeroUsageCounter();
|
|
1720
|
+
const identityResponse = resumeOnly ? null : resolveSelfIdentityResponse(input, this.providerConfigBaseDir());
|
|
1721
|
+
if (identityResponse !== null) {
|
|
1722
|
+
const elapsed_ms = Date.now() - start;
|
|
1723
|
+
await history.appendAssistantMessage(identityResponse);
|
|
1724
|
+
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1725
|
+
this.emitEvent({
|
|
1726
|
+
type: "assistant_final",
|
|
1727
|
+
text: identityResponse,
|
|
1728
|
+
persisted: true,
|
|
1729
|
+
...this.eventBase(eventContext),
|
|
1730
|
+
});
|
|
1731
|
+
this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
|
|
1732
|
+
return {
|
|
1733
|
+
success: true,
|
|
1734
|
+
output: identityResponse,
|
|
1735
|
+
elapsed_ms,
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1291
1738
|
if (selectedRoute?.kind === "runtime_control") {
|
|
1292
|
-
|
|
1739
|
+
this.emitCheckpoint("Runtime control selected", `${selectedRoute.intent.kind} request recognized.`, eventContext, "route");
|
|
1740
|
+
const runtimeControlResult = await this.executeRuntimeControlRoute(selectedRoute, runtimeControlContext, executionCwd, start);
|
|
1293
1741
|
if (runtimeControlResult.success) {
|
|
1294
1742
|
await history.appendAssistantMessage(runtimeControlResult.output);
|
|
1743
|
+
this.emitCheckpoint("Runtime control completed", "The runtime-control operation produced a result.", eventContext, "complete");
|
|
1295
1744
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1296
1745
|
this.emitEvent({
|
|
1297
1746
|
type: "assistant_final",
|
|
@@ -1302,11 +1751,32 @@ export class ChatRunner {
|
|
|
1302
1751
|
this.emitLifecycleEndEvent("completed", runtimeControlResult.elapsed_ms, eventContext, true);
|
|
1303
1752
|
}
|
|
1304
1753
|
else {
|
|
1305
|
-
this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
|
|
1754
|
+
runtimeControlResult.output = this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
|
|
1306
1755
|
this.emitLifecycleEndEvent("error", runtimeControlResult.elapsed_ms, eventContext, false);
|
|
1307
1756
|
}
|
|
1308
1757
|
return runtimeControlResult;
|
|
1309
1758
|
}
|
|
1759
|
+
if (selectedRoute?.kind === "daemon_tend") {
|
|
1760
|
+
this.emitCheckpoint("Durable goal selected", "This long-running request is being prepared for daemon-backed CoreLoop execution.", eventContext, "route");
|
|
1761
|
+
const tendResult = await this.handleTend("", start);
|
|
1762
|
+
if (tendResult.success) {
|
|
1763
|
+
await history.appendAssistantMessage(tendResult.output);
|
|
1764
|
+
this.emitCheckpoint("Durable goal prepared", "The daemon-backed goal confirmation is ready.", eventContext, "complete");
|
|
1765
|
+
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1766
|
+
this.emitEvent({
|
|
1767
|
+
type: "assistant_final",
|
|
1768
|
+
text: tendResult.output,
|
|
1769
|
+
persisted: true,
|
|
1770
|
+
...this.eventBase(eventContext),
|
|
1771
|
+
});
|
|
1772
|
+
this.emitLifecycleEndEvent("completed", tendResult.elapsed_ms, eventContext, true);
|
|
1773
|
+
}
|
|
1774
|
+
else {
|
|
1775
|
+
tendResult.output = this.emitLifecycleErrorEvent(tendResult.output, assistantBuffer.text, eventContext);
|
|
1776
|
+
this.emitLifecycleEndEvent("error", tendResult.elapsed_ms, eventContext, false);
|
|
1777
|
+
}
|
|
1778
|
+
return tendResult;
|
|
1779
|
+
}
|
|
1310
1780
|
if (selectedRoute?.kind === "direct_answer") {
|
|
1311
1781
|
try {
|
|
1312
1782
|
this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
|
|
@@ -1321,7 +1791,12 @@ export class ChatRunner {
|
|
|
1321
1791
|
if (this.hasUsage(turnUsage)) {
|
|
1322
1792
|
history.recordUsage("execution", turnUsage);
|
|
1323
1793
|
}
|
|
1794
|
+
const diffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
1795
|
+
if (diffArtifact) {
|
|
1796
|
+
this.emitDiffArtifact(diffArtifact, eventContext);
|
|
1797
|
+
}
|
|
1324
1798
|
await history.appendAssistantMessage(output);
|
|
1799
|
+
this.emitCheckpoint("Response ready", "The direct answer has been persisted for this turn.", eventContext, "complete");
|
|
1325
1800
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1326
1801
|
this.emitEvent({
|
|
1327
1802
|
type: "assistant_final",
|
|
@@ -1344,13 +1819,11 @@ export class ChatRunner {
|
|
|
1344
1819
|
}
|
|
1345
1820
|
catch (err) {
|
|
1346
1821
|
const message = err instanceof Error ? err.message : String(err);
|
|
1347
|
-
this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1822
|
+
const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1348
1823
|
this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
|
|
1349
1824
|
return {
|
|
1350
1825
|
success: false,
|
|
1351
|
-
output
|
|
1352
|
-
? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
|
|
1353
|
-
: `Error: ${message}`,
|
|
1826
|
+
output,
|
|
1354
1827
|
elapsed_ms: Date.now() - start,
|
|
1355
1828
|
diagnostics: {
|
|
1356
1829
|
route: "direct",
|
|
@@ -1363,7 +1836,7 @@ export class ChatRunner {
|
|
|
1363
1836
|
}
|
|
1364
1837
|
const usesNativeAgentLoop = resumeOnly || selectedRoute?.kind === "agent_loop";
|
|
1365
1838
|
const groundingWorkspaceContext = !resumeOnly && usesNativeAgentLoop
|
|
1366
|
-
? await buildChatContext(input,
|
|
1839
|
+
? await buildChatContext(input, executionCwd)
|
|
1367
1840
|
: undefined;
|
|
1368
1841
|
let systemPrompt = this.cachedStaticSystemPrompt ?? "";
|
|
1369
1842
|
if (!resumeOnly) {
|
|
@@ -1373,8 +1846,8 @@ export class ChatRunner {
|
|
|
1373
1846
|
systemPrompt = await buildChatAgentLoopSystemPrompt({
|
|
1374
1847
|
stateManager: this.deps.stateManager,
|
|
1375
1848
|
pluginLoader: this.deps.pluginLoader,
|
|
1376
|
-
workspaceRoot:
|
|
1377
|
-
goalId:
|
|
1849
|
+
workspaceRoot: executionCwd,
|
|
1850
|
+
goalId: executionGoalId,
|
|
1378
1851
|
userMessage: input,
|
|
1379
1852
|
trustProjectInstructions: this.sessionExecutionPolicy?.trustProjectInstructions ?? true,
|
|
1380
1853
|
workspaceContext: groundingWorkspaceContext,
|
|
@@ -1384,8 +1857,8 @@ export class ChatRunner {
|
|
|
1384
1857
|
const groundingBundle = await this.groundingGateway.build({
|
|
1385
1858
|
surface: "chat",
|
|
1386
1859
|
purpose: "general_turn",
|
|
1387
|
-
workspaceRoot:
|
|
1388
|
-
goalId:
|
|
1860
|
+
workspaceRoot: executionCwd,
|
|
1861
|
+
goalId: executionGoalId,
|
|
1389
1862
|
userMessage: input,
|
|
1390
1863
|
query: input,
|
|
1391
1864
|
trustProjectInstructions: this.sessionExecutionPolicy?.trustProjectInstructions ?? true,
|
|
@@ -1396,6 +1869,9 @@ export class ChatRunner {
|
|
|
1396
1869
|
catch {
|
|
1397
1870
|
systemPrompt = this.cachedStaticSystemPrompt ?? "";
|
|
1398
1871
|
}
|
|
1872
|
+
this.emitCheckpoint("Context gathered", usesNativeAgentLoop
|
|
1873
|
+
? "Workspace and agent-loop grounding are ready."
|
|
1874
|
+
: "Workspace grounding is ready.", eventContext, "context");
|
|
1399
1875
|
}
|
|
1400
1876
|
const agentLoopSystemPrompt = [
|
|
1401
1877
|
systemPrompt,
|
|
@@ -1409,13 +1885,7 @@ export class ChatRunner {
|
|
|
1409
1885
|
const prompt = historyBlock ? `${historyBlock}${basePrompt}` : basePrompt;
|
|
1410
1886
|
if (resumeOnly && !this.deps.chatAgentLoopRunner) {
|
|
1411
1887
|
const elapsed_ms = Date.now() - start;
|
|
1412
|
-
const output = "Resume requires the native chat agentloop runtime.";
|
|
1413
|
-
this.emitEvent({
|
|
1414
|
-
type: "assistant_final",
|
|
1415
|
-
text: output,
|
|
1416
|
-
persisted: false,
|
|
1417
|
-
...this.eventBase(eventContext),
|
|
1418
|
-
});
|
|
1888
|
+
const output = this.emitLifecycleErrorEvent("Resume requires the native chat agentloop runtime.", assistantBuffer.text, eventContext);
|
|
1419
1889
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1420
1890
|
return {
|
|
1421
1891
|
success: false,
|
|
@@ -1429,13 +1899,7 @@ export class ChatRunner {
|
|
|
1429
1899
|
const resumeState = resumeOnly ? await this.loadResumableAgentLoopState() : null;
|
|
1430
1900
|
if (resumeOnly && !resumeState) {
|
|
1431
1901
|
const elapsed_ms = Date.now() - start;
|
|
1432
|
-
const output = "No resumable native agentloop state found.";
|
|
1433
|
-
this.emitEvent({
|
|
1434
|
-
type: "assistant_final",
|
|
1435
|
-
text: output,
|
|
1436
|
-
persisted: false,
|
|
1437
|
-
...this.eventBase(eventContext),
|
|
1438
|
-
});
|
|
1902
|
+
const output = this.emitLifecycleErrorEvent("No resumable native agentloop state found.", assistantBuffer.text, eventContext);
|
|
1439
1903
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1440
1904
|
return {
|
|
1441
1905
|
success: false,
|
|
@@ -1443,11 +1907,14 @@ export class ChatRunner {
|
|
|
1443
1907
|
elapsed_ms,
|
|
1444
1908
|
};
|
|
1445
1909
|
}
|
|
1910
|
+
this.emitCheckpoint(resumeOnly ? "Session resumed" : "Agent loop started", resumeOnly
|
|
1911
|
+
? "Resumable agent-loop state is loaded."
|
|
1912
|
+
: "The agent loop can now inspect, plan, edit, or verify with visible tool activity.", eventContext, "execution");
|
|
1446
1913
|
this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
|
|
1447
1914
|
const result = await chatAgentLoopRunner.execute({
|
|
1448
1915
|
message: basePrompt,
|
|
1449
|
-
cwd,
|
|
1450
|
-
goalId:
|
|
1916
|
+
cwd: executionCwd,
|
|
1917
|
+
goalId: executionGoalId,
|
|
1451
1918
|
history: priorTurns.map((m) => ({
|
|
1452
1919
|
role: m.role === "assistant" ? "assistant" : "user",
|
|
1453
1920
|
content: m.content,
|
|
@@ -1466,6 +1933,7 @@ export class ChatRunner {
|
|
|
1466
1933
|
...(resumeState ? { resumeState } : {}),
|
|
1467
1934
|
...(resumeOnly ? { resumeOnly: true } : {}),
|
|
1468
1935
|
...(agentLoopSystemPrompt ? { systemPrompt: agentLoopSystemPrompt } : {}),
|
|
1936
|
+
abortSignal: activeTurn.abortController.signal,
|
|
1469
1937
|
});
|
|
1470
1938
|
const elapsed_ms = Date.now() - start;
|
|
1471
1939
|
const agentLoopUsage = result.agentLoop?.usage
|
|
@@ -1478,7 +1946,12 @@ export class ChatRunner {
|
|
|
1478
1946
|
this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
|
|
1479
1947
|
}
|
|
1480
1948
|
if (result.success) {
|
|
1949
|
+
const diffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
1950
|
+
if (diffArtifact) {
|
|
1951
|
+
this.emitDiffArtifact(diffArtifact, eventContext);
|
|
1952
|
+
}
|
|
1481
1953
|
await history.appendAssistantMessage(result.output);
|
|
1954
|
+
this.emitCheckpoint("Response ready", "The agent-loop response has been persisted for this turn.", eventContext, "complete");
|
|
1482
1955
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1483
1956
|
this.emitEvent({
|
|
1484
1957
|
type: "assistant_final",
|
|
@@ -1489,7 +1962,7 @@ export class ChatRunner {
|
|
|
1489
1962
|
this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
|
|
1490
1963
|
}
|
|
1491
1964
|
else {
|
|
1492
|
-
this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", assistantBuffer.text, eventContext);
|
|
1965
|
+
result.output = this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", assistantBuffer.text, eventContext);
|
|
1493
1966
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1494
1967
|
}
|
|
1495
1968
|
return {
|
|
@@ -1500,13 +1973,11 @@ export class ChatRunner {
|
|
|
1500
1973
|
}
|
|
1501
1974
|
catch (err) {
|
|
1502
1975
|
const message = err instanceof Error ? err.message : String(err);
|
|
1503
|
-
this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1976
|
+
const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1504
1977
|
this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
|
|
1505
1978
|
return {
|
|
1506
1979
|
success: false,
|
|
1507
|
-
output
|
|
1508
|
-
? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
|
|
1509
|
-
: `Error: ${message}`,
|
|
1980
|
+
output,
|
|
1510
1981
|
elapsed_ms: Date.now() - start,
|
|
1511
1982
|
};
|
|
1512
1983
|
}
|
|
@@ -1514,12 +1985,18 @@ export class ChatRunner {
|
|
|
1514
1985
|
// Prefer the local LLM/tool loop over the external adapter fallback whenever a client is available.
|
|
1515
1986
|
if (selectedRoute?.kind === "tool_loop") {
|
|
1516
1987
|
try {
|
|
1517
|
-
|
|
1988
|
+
this.emitCheckpoint("Tool loop started", "The model will choose tools from the active catalog.", eventContext, "execution");
|
|
1989
|
+
const toolResult = await this.executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt || undefined, executionGoalId);
|
|
1518
1990
|
const elapsed_ms = Date.now() - start;
|
|
1519
1991
|
if (this.hasUsage(toolResult.usage)) {
|
|
1520
1992
|
history.recordUsage("execution", toolResult.usage);
|
|
1521
1993
|
}
|
|
1994
|
+
const diffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
1995
|
+
if (diffArtifact) {
|
|
1996
|
+
this.emitDiffArtifact(diffArtifact, eventContext);
|
|
1997
|
+
}
|
|
1522
1998
|
await history.appendAssistantMessage(toolResult.output);
|
|
1999
|
+
this.emitCheckpoint("Response ready", "The tool-loop response has been persisted for this turn.", eventContext, "complete");
|
|
1523
2000
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1524
2001
|
this.emitEvent({
|
|
1525
2002
|
type: "assistant_final",
|
|
@@ -1532,21 +2009,18 @@ export class ChatRunner {
|
|
|
1532
2009
|
}
|
|
1533
2010
|
catch (err) {
|
|
1534
2011
|
const message = err instanceof Error ? err.message : String(err);
|
|
1535
|
-
this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
2012
|
+
const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1536
2013
|
this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
|
|
1537
2014
|
return {
|
|
1538
2015
|
success: false,
|
|
1539
|
-
output
|
|
1540
|
-
? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
|
|
1541
|
-
: `Error: ${message}`,
|
|
2016
|
+
output,
|
|
1542
2017
|
elapsed_ms: Date.now() - start,
|
|
1543
2018
|
};
|
|
1544
2019
|
}
|
|
1545
2020
|
}
|
|
1546
2021
|
if (!resumeOnly && selectedRoute && selectedRoute.kind !== "adapter") {
|
|
1547
2022
|
const elapsed_ms = Date.now() - start;
|
|
1548
|
-
const output = `Unsupported chat route: ${selectedRoute.kind}
|
|
1549
|
-
this.emitLifecycleErrorEvent(output, assistantBuffer.text, eventContext);
|
|
2023
|
+
const output = this.emitLifecycleErrorEvent(`Unsupported chat route: ${selectedRoute.kind}`, assistantBuffer.text, eventContext);
|
|
1550
2024
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1551
2025
|
return {
|
|
1552
2026
|
success: false,
|
|
@@ -1562,10 +2036,25 @@ export class ChatRunner {
|
|
|
1562
2036
|
...(systemPrompt ? { system_prompt: systemPrompt } : {}),
|
|
1563
2037
|
};
|
|
1564
2038
|
const resolvedTimeoutMs = task.timeout_ms ?? DEFAULT_TIMEOUT_MS;
|
|
2039
|
+
this.emitCheckpoint("Adapter started", "The configured adapter has the current prompt and project context.", eventContext, "execution");
|
|
1565
2040
|
this.emitActivity("lifecycle", "Calling adapter...", eventContext, "lifecycle:adapter");
|
|
1566
2041
|
const adapterPromise = this.deps.adapter.execute(task);
|
|
1567
2042
|
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Chat adapter timed out after ${resolvedTimeoutMs}ms`)), resolvedTimeoutMs));
|
|
1568
|
-
let result
|
|
2043
|
+
let result;
|
|
2044
|
+
try {
|
|
2045
|
+
result = await Promise.race([adapterPromise, timeoutPromise]);
|
|
2046
|
+
}
|
|
2047
|
+
catch (err) {
|
|
2048
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2049
|
+
const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
2050
|
+
const timeoutElapsedMs = Date.now() - start;
|
|
2051
|
+
this.emitLifecycleEndEvent("error", timeoutElapsedMs, eventContext, false);
|
|
2052
|
+
return {
|
|
2053
|
+
success: false,
|
|
2054
|
+
output,
|
|
2055
|
+
elapsed_ms: timeoutElapsedMs,
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
1569
2058
|
// Surface adapter errors into output when output is empty
|
|
1570
2059
|
if (!result.output && result.error) {
|
|
1571
2060
|
result = { ...result, output: `Error: ${result.error}` };
|
|
@@ -1575,34 +2064,47 @@ export class ChatRunner {
|
|
|
1575
2064
|
this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
|
|
1576
2065
|
}
|
|
1577
2066
|
// Verification loop: check if git has uncommitted changes; if so, run tests
|
|
1578
|
-
const
|
|
1579
|
-
if (
|
|
2067
|
+
const diffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
2068
|
+
if (diffArtifact) {
|
|
1580
2069
|
let retries = 0;
|
|
1581
2070
|
const VERIFY_TIMEOUT_MS = 30_000;
|
|
2071
|
+
this.emitCheckpoint("Changes detected", "Verification is starting because the turn changed the working tree.", eventContext, "changes");
|
|
1582
2072
|
this.emitActivity("lifecycle", "Checking result...", eventContext, "lifecycle:checking");
|
|
1583
2073
|
let verification = await Promise.race([
|
|
1584
|
-
verifyChatAction(gitRoot, this.deps.toolExecutor),
|
|
2074
|
+
verifyChatAction(gitRoot, this.deps.toolExecutor, { force: true }),
|
|
1585
2075
|
new Promise((resolve) => setTimeout(() => resolve({ passed: true }), VERIFY_TIMEOUT_MS)),
|
|
1586
2076
|
]);
|
|
1587
2077
|
while (!verification.passed && retries < MAX_VERIFY_RETRIES) {
|
|
1588
2078
|
retries++;
|
|
2079
|
+
this.emitCheckpoint("Verification retry", `Attempt ${retries} of ${MAX_VERIFY_RETRIES} is repairing failed checks.`, eventContext, `verification-retry-${retries}`);
|
|
1589
2080
|
const retryPrompt = `The previous changes caused test failures. Please fix them.\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`;
|
|
1590
2081
|
const retryTask = { ...task, prompt: retryPrompt };
|
|
1591
2082
|
result = await this.deps.adapter.execute(retryTask);
|
|
1592
|
-
verification = await verifyChatAction(gitRoot, this.deps.toolExecutor);
|
|
2083
|
+
verification = await verifyChatAction(gitRoot, this.deps.toolExecutor, { force: true });
|
|
1593
2084
|
}
|
|
1594
2085
|
if (!verification.passed) {
|
|
1595
|
-
|
|
2086
|
+
const finalDiffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
2087
|
+
if (finalDiffArtifact) {
|
|
2088
|
+
this.emitDiffArtifact(finalDiffArtifact, eventContext);
|
|
2089
|
+
}
|
|
2090
|
+
this.emitCheckpoint("Verification failed", `Checks are still failing after ${MAX_VERIFY_RETRIES} retries.`, eventContext, "verification");
|
|
2091
|
+
const failureOutput = this.emitLifecycleErrorEvent(`Changes applied but tests are still failing after ${MAX_VERIFY_RETRIES} retries.`, assistantBuffer.text, eventContext);
|
|
1596
2092
|
this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
|
|
1597
2093
|
return {
|
|
1598
2094
|
success: false,
|
|
1599
|
-
output: `${
|
|
2095
|
+
output: `${failureOutput}\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`.trim(),
|
|
1600
2096
|
elapsed_ms: Date.now() - start,
|
|
1601
2097
|
};
|
|
1602
2098
|
}
|
|
2099
|
+
const finalDiffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
2100
|
+
if (finalDiffArtifact) {
|
|
2101
|
+
this.emitDiffArtifact(finalDiffArtifact, eventContext);
|
|
2102
|
+
}
|
|
2103
|
+
this.emitCheckpoint("Verification passed", "Changed files passed the configured chat verification.", eventContext, "verification");
|
|
1603
2104
|
}
|
|
1604
2105
|
if (result.success) {
|
|
1605
2106
|
await history.appendAssistantMessage(result.output);
|
|
2107
|
+
this.emitCheckpoint("Response ready", "The assistant response has been persisted for this turn.", eventContext, "complete");
|
|
1606
2108
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1607
2109
|
this.emitEvent({
|
|
1608
2110
|
type: "assistant_final",
|
|
@@ -1614,7 +2116,7 @@ export class ChatRunner {
|
|
|
1614
2116
|
}
|
|
1615
2117
|
else {
|
|
1616
2118
|
const partialText = assistantBuffer.text !== result.output ? assistantBuffer.text : "";
|
|
1617
|
-
this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
|
|
2119
|
+
result.output = this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
|
|
1618
2120
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1619
2121
|
}
|
|
1620
2122
|
return {
|
|
@@ -1658,10 +2160,10 @@ export class ChatRunner {
|
|
|
1658
2160
|
* Execute a chat turn using llmClient with self-knowledge tools (function calling).
|
|
1659
2161
|
* Loops up to MAX_TOOL_LOOPS times to resolve tool calls, then returns final text.
|
|
1660
2162
|
*/
|
|
1661
|
-
async executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt) {
|
|
2163
|
+
async executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt, goalId) {
|
|
1662
2164
|
const llmClient = this.deps.llmClient;
|
|
1663
2165
|
const messages = [{ role: "user", content: prompt }];
|
|
1664
|
-
const toolCallContext = await this.buildToolCallContext();
|
|
2166
|
+
const toolCallContext = await this.buildToolCallContext(goalId);
|
|
1665
2167
|
const usage = this.zeroUsageCounter();
|
|
1666
2168
|
for (let loop = 0; loop < MAX_TOOL_LOOPS; loop++) {
|
|
1667
2169
|
// Recompute tools each iteration so newly activated deferred tools are included
|
|
@@ -1797,6 +2299,7 @@ export class ChatRunner {
|
|
|
1797
2299
|
}
|
|
1798
2300
|
if (event.type === "plan_update") {
|
|
1799
2301
|
this.emitActivity("tool", `Updated plan: ${previewActivityText(event.summary)}`, eventContext, `plan:${event.turnId}`);
|
|
2302
|
+
this.emitCheckpoint("Plan updated", previewActivityText(event.summary, 160), eventContext, `plan:${event.eventId}`);
|
|
1800
2303
|
this.emitEvent({
|
|
1801
2304
|
type: "tool_update",
|
|
1802
2305
|
toolCallId: `plan:${event.turnId}:${event.createdAt}`,
|
|
@@ -1809,6 +2312,7 @@ export class ChatRunner {
|
|
|
1809
2312
|
}
|
|
1810
2313
|
if (event.type === "approval_request") {
|
|
1811
2314
|
this.emitActivity("tool", formatToolActivity("Running", event.toolName, `awaiting approval: ${event.reason}`), eventContext, event.callId);
|
|
2315
|
+
this.emitCheckpoint("Approval requested", `${event.toolName}: ${event.reason}`, eventContext, `approval:${event.callId}`);
|
|
1812
2316
|
this.emitEvent({
|
|
1813
2317
|
type: "tool_update",
|
|
1814
2318
|
toolCallId: event.callId,
|
|
@@ -1867,6 +2371,34 @@ export class ChatRunner {
|
|
|
1867
2371
|
}
|
|
1868
2372
|
return preview ? { preview } : {};
|
|
1869
2373
|
}
|
|
2374
|
+
async resolveChatResumeSelector(selector) {
|
|
2375
|
+
if (selector.startsWith("session:conversation:")) {
|
|
2376
|
+
return { chatSelector: selector.slice("session:conversation:".length) };
|
|
2377
|
+
}
|
|
2378
|
+
if (selector.startsWith("session:") || selector.startsWith("run:")) {
|
|
2379
|
+
const registry = createRuntimeSessionRegistry({ stateManager: this.deps.stateManager });
|
|
2380
|
+
if (selector.startsWith("session:")) {
|
|
2381
|
+
const session = await registry.getSession(selector);
|
|
2382
|
+
if (session?.kind === "conversation") {
|
|
2383
|
+
return { chatSelector: selector.slice("session:conversation:".length) };
|
|
2384
|
+
}
|
|
2385
|
+
if (session?.kind === "agent"
|
|
2386
|
+
&& session.resumable
|
|
2387
|
+
&& session.parent_session_id?.startsWith("session:conversation:")) {
|
|
2388
|
+
return { chatSelector: session.parent_session_id.slice("session:conversation:".length) };
|
|
2389
|
+
}
|
|
2390
|
+
return {
|
|
2391
|
+
chatSelector: selector,
|
|
2392
|
+
nonResumableMessage: `Runtime session ${selector} is not chat-resumable. Inspect it with 'pulseed runtime session ${selector}'.`,
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
return {
|
|
2396
|
+
chatSelector: selector,
|
|
2397
|
+
nonResumableMessage: `Background run ${selector} is not chat-resumable. Inspect it with 'pulseed runtime run ${selector}'.`,
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
return { chatSelector: selector };
|
|
2401
|
+
}
|
|
1870
2402
|
parseResumeCommand(input) {
|
|
1871
2403
|
const trimmed = input.trim();
|
|
1872
2404
|
const match = /^\/resume(?:\s+(.+))?$/i.exec(trimmed);
|
|
@@ -2077,11 +2609,81 @@ export class ChatRunner {
|
|
|
2077
2609
|
eventBase(context) {
|
|
2078
2610
|
return { ...context, createdAt: new Date().toISOString() };
|
|
2079
2611
|
}
|
|
2612
|
+
beginActiveTurn(context, cwd) {
|
|
2613
|
+
let resolveFinished = () => { };
|
|
2614
|
+
const finished = new Promise((resolve) => {
|
|
2615
|
+
resolveFinished = resolve;
|
|
2616
|
+
});
|
|
2617
|
+
const turn = {
|
|
2618
|
+
context,
|
|
2619
|
+
cwd,
|
|
2620
|
+
startedAt: Date.now(),
|
|
2621
|
+
abortController: new AbortController(),
|
|
2622
|
+
finished,
|
|
2623
|
+
resolveFinished,
|
|
2624
|
+
recentEvents: [],
|
|
2625
|
+
interruptRequested: false,
|
|
2626
|
+
};
|
|
2627
|
+
this.activeTurn = turn;
|
|
2628
|
+
return turn;
|
|
2629
|
+
}
|
|
2630
|
+
finishActiveTurn(context) {
|
|
2631
|
+
const activeTurn = this.activeTurn;
|
|
2632
|
+
if (!activeTurn || activeTurn.context.runId !== context.runId)
|
|
2633
|
+
return;
|
|
2634
|
+
activeTurn.resolveFinished();
|
|
2635
|
+
this.activeTurn = null;
|
|
2636
|
+
}
|
|
2637
|
+
waitForActiveTurn(turn, timeoutMs) {
|
|
2638
|
+
return Promise.race([
|
|
2639
|
+
turn.finished.then(() => true),
|
|
2640
|
+
new Promise((resolve) => setTimeout(() => resolve(false), timeoutMs)),
|
|
2641
|
+
]);
|
|
2642
|
+
}
|
|
2643
|
+
emitEphemeralAssistantResult(input, output, success, start) {
|
|
2644
|
+
const context = this.createEventContext();
|
|
2645
|
+
this.emitEvent({
|
|
2646
|
+
type: "lifecycle_start",
|
|
2647
|
+
input,
|
|
2648
|
+
...this.eventBase(context),
|
|
2649
|
+
});
|
|
2650
|
+
this.emitEvent({
|
|
2651
|
+
type: "assistant_final",
|
|
2652
|
+
text: output,
|
|
2653
|
+
persisted: false,
|
|
2654
|
+
...this.eventBase(context),
|
|
2655
|
+
});
|
|
2656
|
+
const elapsed_ms = Date.now() - start;
|
|
2657
|
+
this.emitLifecycleEndEvent(success ? "completed" : "error", elapsed_ms, context, false);
|
|
2658
|
+
return { success, output, elapsed_ms };
|
|
2659
|
+
}
|
|
2660
|
+
rememberActiveTurnEvent(event) {
|
|
2661
|
+
const activeTurn = this.activeTurn;
|
|
2662
|
+
if (!activeTurn || activeTurn.context.turnId !== event.turnId)
|
|
2663
|
+
return;
|
|
2664
|
+
let summary = null;
|
|
2665
|
+
if (event.type === "activity") {
|
|
2666
|
+
summary = previewActivityText(event.message, 140);
|
|
2667
|
+
}
|
|
2668
|
+
else if (event.type === "tool_start") {
|
|
2669
|
+
summary = `Started ${event.toolName}`;
|
|
2670
|
+
}
|
|
2671
|
+
else if (event.type === "tool_update") {
|
|
2672
|
+
summary = `${event.toolName}: ${previewActivityText(event.message, 100)}`;
|
|
2673
|
+
}
|
|
2674
|
+
else if (event.type === "tool_end") {
|
|
2675
|
+
summary = `${event.success ? "Finished" : "Failed"} ${event.toolName}: ${previewActivityText(event.summary, 100)}`;
|
|
2676
|
+
}
|
|
2677
|
+
if (!summary)
|
|
2678
|
+
return;
|
|
2679
|
+
activeTurn.recentEvents = [...activeTurn.recentEvents, summary].slice(-12);
|
|
2680
|
+
}
|
|
2080
2681
|
emitEvent(event) {
|
|
2682
|
+
this.rememberActiveTurnEvent(event);
|
|
2081
2683
|
const handler = this.onEvent ?? this.deps.onEvent;
|
|
2082
2684
|
handler?.(event);
|
|
2083
2685
|
}
|
|
2084
|
-
emitActivity(kind, message, eventContext, sourceId) {
|
|
2686
|
+
emitActivity(kind, message, eventContext, sourceId, transient = true) {
|
|
2085
2687
|
if (!message.trim())
|
|
2086
2688
|
return;
|
|
2087
2689
|
this.emitEvent({
|
|
@@ -2089,10 +2691,72 @@ export class ChatRunner {
|
|
|
2089
2691
|
kind,
|
|
2090
2692
|
message,
|
|
2091
2693
|
...(sourceId ? { sourceId } : {}),
|
|
2092
|
-
transient
|
|
2694
|
+
transient,
|
|
2093
2695
|
...this.eventBase(eventContext),
|
|
2094
2696
|
});
|
|
2095
2697
|
}
|
|
2698
|
+
emitIntent(input, selectedRoute, eventContext) {
|
|
2699
|
+
const subject = formatIntentInput(input);
|
|
2700
|
+
let nextStep = "resume the saved agent loop state before continuing.";
|
|
2701
|
+
let reason = "resume needs the prior runtime context before any further action.";
|
|
2702
|
+
if (selectedRoute?.kind === "runtime_control") {
|
|
2703
|
+
nextStep = `prepare the ${selectedRoute.intent.kind} runtime-control request.`;
|
|
2704
|
+
reason = "runtime changes need an explicit operation plan and approval path.";
|
|
2705
|
+
}
|
|
2706
|
+
else if (selectedRoute?.kind === "daemon_tend") {
|
|
2707
|
+
nextStep = "convert the request into a daemon-backed CoreLoop goal confirmation.";
|
|
2708
|
+
reason = "long-running work should survive chat turn timeouts and run through durable runtime state.";
|
|
2709
|
+
}
|
|
2710
|
+
else if (selectedRoute?.kind === "direct_answer") {
|
|
2711
|
+
nextStep = "ask the lightweight model for a concise direct answer.";
|
|
2712
|
+
reason = "the router classified this as a simple question that does not need tools.";
|
|
2713
|
+
}
|
|
2714
|
+
else if (selectedRoute?.kind === "agent_loop") {
|
|
2715
|
+
nextStep = "gather workspace context, then let the agent loop inspect or change files with visible tool activity.";
|
|
2716
|
+
reason = "this request may require multiple tool-backed steps.";
|
|
2717
|
+
}
|
|
2718
|
+
else if (selectedRoute?.kind === "tool_loop") {
|
|
2719
|
+
nextStep = "call the model with the tool catalog, then execute selected tools with visible activity.";
|
|
2720
|
+
reason = "the available tools are needed to answer from current project state.";
|
|
2721
|
+
}
|
|
2722
|
+
else if (selectedRoute?.kind === "adapter") {
|
|
2723
|
+
nextStep = "prepare project context before handing the turn to the configured adapter.";
|
|
2724
|
+
reason = "the adapter needs the current workspace context to act correctly.";
|
|
2725
|
+
}
|
|
2726
|
+
const message = [
|
|
2727
|
+
"Intent",
|
|
2728
|
+
`- Confirm: ${subject || "the current request"}`,
|
|
2729
|
+
`- Next: ${nextStep}`,
|
|
2730
|
+
`- Why: ${reason}`,
|
|
2731
|
+
].join("\n");
|
|
2732
|
+
this.emitActivity("commentary", message, eventContext, "intent:first-step", false);
|
|
2733
|
+
}
|
|
2734
|
+
emitCheckpoint(title, detail, eventContext, sourceKey) {
|
|
2735
|
+
const message = detail
|
|
2736
|
+
? `Checkpoint\n- ${title}: ${detail}`
|
|
2737
|
+
: `Checkpoint\n- ${title}`;
|
|
2738
|
+
this.emitActivity("checkpoint", message, eventContext, `checkpoint:${sourceKey}`, false);
|
|
2739
|
+
}
|
|
2740
|
+
emitDiffArtifact(artifact, eventContext) {
|
|
2741
|
+
const sections = [
|
|
2742
|
+
"Changed files",
|
|
2743
|
+
"",
|
|
2744
|
+
"Modified files",
|
|
2745
|
+
artifact.nameStatus || artifact.stat,
|
|
2746
|
+
"",
|
|
2747
|
+
"Diff summary",
|
|
2748
|
+
artifact.stat,
|
|
2749
|
+
"",
|
|
2750
|
+
"Inline patch",
|
|
2751
|
+
"```diff",
|
|
2752
|
+
artifact.patch || "(patch unavailable)",
|
|
2753
|
+
artifact.truncated ? `... truncated after ${DIFF_ARTIFACT_MAX_LINES} lines; run /review for the full diff.` : "",
|
|
2754
|
+
"```",
|
|
2755
|
+
"",
|
|
2756
|
+
"Files inspected are shown separately in the activity log.",
|
|
2757
|
+
].filter((line) => line !== "").join("\n");
|
|
2758
|
+
this.emitActivity("diff", sections, eventContext, "diff:working-tree", false);
|
|
2759
|
+
}
|
|
2096
2760
|
pushAssistantDelta(delta, assistantBuffer, eventContext) {
|
|
2097
2761
|
if (!delta)
|
|
2098
2762
|
return;
|
|
@@ -2112,15 +2776,19 @@ export class ChatRunner {
|
|
|
2112
2776
|
persisted,
|
|
2113
2777
|
...this.eventBase(eventContext),
|
|
2114
2778
|
});
|
|
2779
|
+
this.finishActiveTurn(eventContext);
|
|
2115
2780
|
}
|
|
2116
2781
|
emitLifecycleErrorEvent(error, partialText, eventContext) {
|
|
2782
|
+
const recovery = classifyFailureRecovery(error);
|
|
2117
2783
|
this.emitEvent({
|
|
2118
2784
|
type: "lifecycle_error",
|
|
2119
2785
|
error,
|
|
2120
2786
|
partialText,
|
|
2121
2787
|
persisted: false,
|
|
2788
|
+
recovery,
|
|
2122
2789
|
...this.eventBase(eventContext),
|
|
2123
2790
|
});
|
|
2791
|
+
return formatLifecycleFailureMessage(error, partialText, recovery);
|
|
2124
2792
|
}
|
|
2125
2793
|
/** Build a ToolCallContext from ChatRunnerDeps for tool dispatch. */
|
|
2126
2794
|
async getSessionExecutionPolicy() {
|
|
@@ -2133,11 +2801,11 @@ export class ChatRunner {
|
|
|
2133
2801
|
});
|
|
2134
2802
|
return this.sessionExecutionPolicy;
|
|
2135
2803
|
}
|
|
2136
|
-
async buildToolCallContext() {
|
|
2804
|
+
async buildToolCallContext(goalId = this.deps.goalId) {
|
|
2137
2805
|
const executionPolicy = await this.getSessionExecutionPolicy();
|
|
2138
2806
|
return {
|
|
2139
2807
|
cwd: this.sessionCwd ?? process.cwd(),
|
|
2140
|
-
goalId:
|
|
2808
|
+
goalId: goalId ?? "",
|
|
2141
2809
|
trustBalance: 0,
|
|
2142
2810
|
preApproved: false,
|
|
2143
2811
|
approvalFn: async (req) => {
|