pulseed 0.5.2 → 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/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 +24 -1
- package/dist/interface/chat/chat-runner.d.ts.map +1 -1
- package/dist/interface/chat/chat-runner.js +678 -67
- 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 +1 -0
- package/dist/interface/chat/cross-platform-session.d.ts.map +1 -1
- package/dist/interface/chat/cross-platform-session.js +24 -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/ingress-router.d.ts +9 -0
- package/dist/interface/chat/ingress-router.d.ts.map +1 -1
- package/dist/interface/chat/ingress-router.js +35 -1
- 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/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/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.map +1 -1
- package/dist/interface/tui/app.js +22 -1
- 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 +14 -2
- 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/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 +27 -13
- 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/bounded-agent-loop-runner.d.ts.map +1 -1
- package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js +6 -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 +1 -0
- 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 +1 -0
- package/dist/orchestrator/execution/agent-loop/chat-agent-loop-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/loop/core-loop/phase-policy.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop/phase-policy.js +3 -0
- package/dist/orchestrator/loop/core-loop/phase-policy.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/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/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/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/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-startup.d.ts.map +1 -1
- package/dist/runtime/daemon/runner-startup.js +22 -1
- package/dist/runtime/daemon/runner-startup.js.map +1 -1
- package/dist/runtime/daemon/runner.d.ts.map +1 -1
- package/dist/runtime/daemon/runner.js +3 -2
- 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/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/telegram-gateway-adapter.d.ts.map +1 -1
- package/dist/runtime/gateway/telegram-gateway-adapter.js +2 -1
- package/dist/runtime/gateway/telegram-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 +24 -24
- 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/types/daemon.d.ts +3 -0
- package/dist/runtime/types/daemon.d.ts.map +1 -1
- package/dist/runtime/types/daemon.js +1 -0
- package/dist/runtime/types/daemon.js.map +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/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/package.json +2 -1
|
@@ -18,12 +18,15 @@ import { toToolDefinitionsFiltered } from "../../tools/tool-definition-adapter.j
|
|
|
18
18
|
import { TendCommand } from "./tend-command.js";
|
|
19
19
|
import { EventSubscriber } from "./event-subscriber.js";
|
|
20
20
|
import { buildPromptedToolProtocolSystemPrompt, extractPromptedToolCalls, } from "../../orchestrator/execution/agent-loop/prompted-tool-protocol.js";
|
|
21
|
+
import { classifyFailureRecovery, formatFailureRecovery, formatLifecycleFailureMessage } from "./failure-recovery.js";
|
|
21
22
|
import { resolveExecutionPolicy, summarizeExecutionPolicy, withExecutionPolicyOverrides, } from "../../orchestrator/execution/agent-loop/execution-policy.js";
|
|
22
23
|
import { buildStandaloneIngressMessage, createIngressRouter, } from "./ingress-router.js";
|
|
24
|
+
import { createRuntimeSessionRegistry } from "../../runtime/session-registry/index.js";
|
|
23
25
|
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
24
26
|
const MAX_VERIFY_RETRIES = 2;
|
|
25
27
|
const MAX_TOOL_LOOPS = 5;
|
|
26
28
|
const ACTIVITY_PREVIEW_CHARS = 40;
|
|
29
|
+
const DIFF_ARTIFACT_MAX_LINES = 80;
|
|
27
30
|
const standaloneIngressRouter = createIngressRouter();
|
|
28
31
|
// ─── Command help text ───
|
|
29
32
|
const COMMAND_HELP = `Available commands:
|
|
@@ -36,6 +39,7 @@ Session
|
|
|
36
39
|
/resume [id|title] Resume native agentloop state for the current or selected session
|
|
37
40
|
/cleanup [--dry-run] Clean up stale chat sessions
|
|
38
41
|
/compact Summarize older chat turns and keep the latest turns
|
|
42
|
+
/context Show active working context and session assumptions
|
|
39
43
|
/exit Exit chat mode
|
|
40
44
|
|
|
41
45
|
Goals and tasks
|
|
@@ -69,14 +73,109 @@ function checkGitChanges(cwd) {
|
|
|
69
73
|
});
|
|
70
74
|
});
|
|
71
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
|
+
}
|
|
72
151
|
function previewActivityText(value, maxChars = ACTIVITY_PREVIEW_CHARS) {
|
|
73
152
|
const normalized = value.replace(/\s+/g, " ").trim();
|
|
74
153
|
return normalized.length > maxChars ? `${normalized.slice(0, maxChars)}...` : normalized;
|
|
75
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
|
+
}
|
|
76
171
|
function formatToolActivity(action, toolName, detail) {
|
|
77
172
|
const preview = detail ? previewActivityText(detail) : "";
|
|
78
173
|
return preview ? `${action} tool: ${toolName} - ${preview}` : `${action} tool: ${toolName}`;
|
|
79
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
|
+
}
|
|
80
179
|
function resolveSelfIdentityResponse(input, baseDir) {
|
|
81
180
|
const normalized = input.trim().toLowerCase().replace(/\s+/g, "");
|
|
82
181
|
if (!normalized)
|
|
@@ -116,6 +215,8 @@ export class ChatRunner {
|
|
|
116
215
|
nativeAgentLoopStatePath = null;
|
|
117
216
|
runtimeControlContext = null;
|
|
118
217
|
sessionExecutionPolicy = null;
|
|
218
|
+
lastSelectedRoute = null;
|
|
219
|
+
activeTurn = null;
|
|
119
220
|
constructor(deps) {
|
|
120
221
|
this.deps = deps;
|
|
121
222
|
this.groundingGateway = createChatGroundingGateway({
|
|
@@ -153,6 +254,68 @@ export class ChatRunner {
|
|
|
153
254
|
getCurrentSessionMessages() {
|
|
154
255
|
return this.history?.getMessages() ?? [];
|
|
155
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
|
+
}
|
|
156
319
|
setRuntimeControlContext(context) {
|
|
157
320
|
this.runtimeControlContext = context;
|
|
158
321
|
}
|
|
@@ -179,6 +342,9 @@ export class ChatRunner {
|
|
|
179
342
|
hasAgentLoop: this.deps.chatAgentLoopRunner !== undefined,
|
|
180
343
|
hasToolLoop: this.deps.llmClient !== undefined,
|
|
181
344
|
hasRuntimeControlService: this.deps.runtimeControlService !== undefined,
|
|
345
|
+
hasDaemonTend: this.deps.llmClient !== undefined
|
|
346
|
+
&& this.deps.goalNegotiator !== undefined
|
|
347
|
+
&& this.deps.daemonClient !== undefined,
|
|
182
348
|
};
|
|
183
349
|
}
|
|
184
350
|
buildStandaloneIngressMessage(input, runtimeControlContext) {
|
|
@@ -259,15 +425,94 @@ export class ChatRunner {
|
|
|
259
425
|
...(session.agentLoop ? { agentLoop: session.agentLoop } : {}),
|
|
260
426
|
};
|
|
261
427
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
|
|
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.";
|
|
271
516
|
}
|
|
272
517
|
formatHistory(session) {
|
|
273
518
|
const title = session.title ? ` "${session.title}"` : "";
|
|
@@ -356,14 +601,19 @@ export class ChatRunner {
|
|
|
356
601
|
];
|
|
357
602
|
return { success: true, output: lines.join("\n"), elapsed_ms: Date.now() - start };
|
|
358
603
|
}
|
|
359
|
-
const
|
|
604
|
+
const registry = createRuntimeSessionRegistry({ stateManager: this.deps.stateManager });
|
|
605
|
+
const [goals, runtimeSnapshot] = await Promise.all([
|
|
606
|
+
this.loadGoals(),
|
|
607
|
+
registry.snapshot(),
|
|
608
|
+
]);
|
|
360
609
|
const active = this.activeGoals(goals);
|
|
610
|
+
const runtimeStatus = this.formatRuntimeStatus(runtimeSnapshot);
|
|
361
611
|
if (active.length === 0) {
|
|
362
|
-
return { success: true, output:
|
|
612
|
+
return { success: true, output: `No active goals found.\n\n${runtimeStatus}`, elapsed_ms: Date.now() - start };
|
|
363
613
|
}
|
|
364
614
|
return {
|
|
365
615
|
success: true,
|
|
366
|
-
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}`,
|
|
367
617
|
elapsed_ms: Date.now() - start,
|
|
368
618
|
};
|
|
369
619
|
}
|
|
@@ -812,7 +1062,79 @@ export class ChatRunner {
|
|
|
812
1062
|
elapsed_ms: Date.now() - start,
|
|
813
1063
|
};
|
|
814
1064
|
}
|
|
815
|
-
|
|
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) {
|
|
816
1138
|
const trimmed = input.trim();
|
|
817
1139
|
if (!trimmed.startsWith("/"))
|
|
818
1140
|
return null;
|
|
@@ -826,9 +1148,9 @@ export class ChatRunner {
|
|
|
826
1148
|
return { success: true, output: "Conversation history cleared.", elapsed_ms: Date.now() - start };
|
|
827
1149
|
}
|
|
828
1150
|
if (cmd === "/sessions") {
|
|
829
|
-
const
|
|
830
|
-
const
|
|
831
|
-
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 };
|
|
832
1154
|
}
|
|
833
1155
|
if (cmd === "/history") {
|
|
834
1156
|
const catalog = new ChatSessionCatalog(this.deps.stateManager);
|
|
@@ -901,6 +1223,9 @@ export class ChatRunner {
|
|
|
901
1223
|
if (cmd === "/usage") {
|
|
902
1224
|
return this.handleUsage(trimmed.slice("/usage".length).trim(), start);
|
|
903
1225
|
}
|
|
1226
|
+
if (cmd === "/context" || cmd === "/working-memory") {
|
|
1227
|
+
return this.handleContext(start, cwd);
|
|
1228
|
+
}
|
|
904
1229
|
if (cmd === "/review") {
|
|
905
1230
|
return this.handleReview(start);
|
|
906
1231
|
}
|
|
@@ -910,6 +1235,26 @@ export class ChatRunner {
|
|
|
910
1235
|
if (cmd === "/undo") {
|
|
911
1236
|
return this.handleUndo(start);
|
|
912
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
|
+
}
|
|
913
1258
|
if (cmd === "/exit") {
|
|
914
1259
|
return { success: true, output: "Exiting chat mode.", elapsed_ms: Date.now() - start };
|
|
915
1260
|
}
|
|
@@ -1110,6 +1455,9 @@ export class ChatRunner {
|
|
|
1110
1455
|
daemonClient: this.deps.daemonClient,
|
|
1111
1456
|
stateManager: this.deps.stateManager,
|
|
1112
1457
|
chatHistory: history,
|
|
1458
|
+
sessionId: this.history?.getSessionId() ?? null,
|
|
1459
|
+
workspace: this.sessionCwd ?? process.cwd(),
|
|
1460
|
+
replyTarget: this.runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null,
|
|
1113
1461
|
};
|
|
1114
1462
|
const tendCommand = new TendCommand();
|
|
1115
1463
|
const result = await tendCommand.execute(args, tendDeps);
|
|
@@ -1175,7 +1523,34 @@ export class ChatRunner {
|
|
|
1175
1523
|
}
|
|
1176
1524
|
}
|
|
1177
1525
|
try {
|
|
1178
|
-
|
|
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
|
+
};
|
|
1179
1554
|
}
|
|
1180
1555
|
catch (err) {
|
|
1181
1556
|
if (subscriber) {
|
|
@@ -1189,13 +1564,6 @@ export class ChatRunner {
|
|
|
1189
1564
|
elapsed_ms: Date.now() - start,
|
|
1190
1565
|
};
|
|
1191
1566
|
}
|
|
1192
|
-
const iterNote = maxIterations !== undefined ? ` (max ${maxIterations} iterations)` : "";
|
|
1193
|
-
const shortId = goalId.length > 12 ? goalId.slice(0, 12) : goalId;
|
|
1194
|
-
return {
|
|
1195
|
-
success: true,
|
|
1196
|
-
output: `[tend] ${shortId}: Started — daemon is now tending your goal${iterNote}.\nRun 'pulseed status' to check progress.`,
|
|
1197
|
-
elapsed_ms: Date.now() - start,
|
|
1198
|
-
};
|
|
1199
1567
|
}
|
|
1200
1568
|
/**
|
|
1201
1569
|
* Execute a single chat turn.
|
|
@@ -1211,12 +1579,13 @@ export class ChatRunner {
|
|
|
1211
1579
|
*/
|
|
1212
1580
|
async execute(input, cwd, timeoutMs = DEFAULT_TIMEOUT_MS, options = {}) {
|
|
1213
1581
|
const eventContext = this.createEventContext();
|
|
1582
|
+
const activeTurn = this.beginActiveTurn(eventContext, resolveGitRoot(cwd));
|
|
1214
1583
|
const resumeCommand = this.parseResumeCommand(input);
|
|
1215
1584
|
const resumeOnly = resumeCommand !== null;
|
|
1216
1585
|
const runtimeControlContext = options.runtimeControlContext ?? this.runtimeControlContext;
|
|
1217
1586
|
const executionGoalId = options.goalId ?? this.deps.goalId;
|
|
1218
1587
|
// Intercept commands before any adapter call
|
|
1219
|
-
const commandResult = resumeOnly ? null : await this.handleCommand(input);
|
|
1588
|
+
const commandResult = resumeOnly ? null : await this.handleCommand(input, cwd);
|
|
1220
1589
|
if (commandResult !== null) {
|
|
1221
1590
|
if (commandResult.output) {
|
|
1222
1591
|
this.emitEvent({
|
|
@@ -1245,11 +1614,24 @@ export class ChatRunner {
|
|
|
1245
1614
|
}
|
|
1246
1615
|
if (resumeOnly && resumeCommand.selector) {
|
|
1247
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
|
+
}
|
|
1248
1630
|
const catalog = new ChatSessionCatalog(this.deps.stateManager);
|
|
1249
|
-
const session = await catalog.loadSessionBySelector(
|
|
1631
|
+
const session = await catalog.loadSessionBySelector(selectorResolution.chatSelector);
|
|
1250
1632
|
if (!session) {
|
|
1251
1633
|
const elapsed_ms = 0;
|
|
1252
|
-
const output = `No chat session matched selector "${
|
|
1634
|
+
const output = `No chat session matched selector "${selectorResolution.chatSelector}".`;
|
|
1253
1635
|
this.emitEvent({
|
|
1254
1636
|
type: "assistant_final",
|
|
1255
1637
|
text: output,
|
|
@@ -1284,6 +1666,7 @@ export class ChatRunner {
|
|
|
1284
1666
|
}
|
|
1285
1667
|
const executionCwd = this.sessionCwd ?? cwd;
|
|
1286
1668
|
const gitRoot = this.sessionCwd ?? resolveGitRoot(cwd);
|
|
1669
|
+
activeTurn.cwd = gitRoot;
|
|
1287
1670
|
// history is always assigned by this point (either by startSession or the block above)
|
|
1288
1671
|
const history = this.history;
|
|
1289
1672
|
this.emitEvent({
|
|
@@ -1323,7 +1706,14 @@ export class ChatRunner {
|
|
|
1323
1706
|
const selectedRoute = resumeOnly
|
|
1324
1707
|
? null
|
|
1325
1708
|
: (options.selectedRoute ?? this.resolveRouteFromInput(input, runtimeControlContext));
|
|
1709
|
+
this.lastSelectedRoute = selectedRoute;
|
|
1326
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
|
+
}
|
|
1327
1717
|
const start = Date.now();
|
|
1328
1718
|
const assistantBuffer = { text: "" };
|
|
1329
1719
|
const turnUsage = this.zeroUsageCounter();
|
|
@@ -1346,9 +1736,11 @@ export class ChatRunner {
|
|
|
1346
1736
|
};
|
|
1347
1737
|
}
|
|
1348
1738
|
if (selectedRoute?.kind === "runtime_control") {
|
|
1739
|
+
this.emitCheckpoint("Runtime control selected", `${selectedRoute.intent.kind} request recognized.`, eventContext, "route");
|
|
1349
1740
|
const runtimeControlResult = await this.executeRuntimeControlRoute(selectedRoute, runtimeControlContext, executionCwd, start);
|
|
1350
1741
|
if (runtimeControlResult.success) {
|
|
1351
1742
|
await history.appendAssistantMessage(runtimeControlResult.output);
|
|
1743
|
+
this.emitCheckpoint("Runtime control completed", "The runtime-control operation produced a result.", eventContext, "complete");
|
|
1352
1744
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1353
1745
|
this.emitEvent({
|
|
1354
1746
|
type: "assistant_final",
|
|
@@ -1359,11 +1751,32 @@ export class ChatRunner {
|
|
|
1359
1751
|
this.emitLifecycleEndEvent("completed", runtimeControlResult.elapsed_ms, eventContext, true);
|
|
1360
1752
|
}
|
|
1361
1753
|
else {
|
|
1362
|
-
this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
|
|
1754
|
+
runtimeControlResult.output = this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
|
|
1363
1755
|
this.emitLifecycleEndEvent("error", runtimeControlResult.elapsed_ms, eventContext, false);
|
|
1364
1756
|
}
|
|
1365
1757
|
return runtimeControlResult;
|
|
1366
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
|
+
}
|
|
1367
1780
|
if (selectedRoute?.kind === "direct_answer") {
|
|
1368
1781
|
try {
|
|
1369
1782
|
this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
|
|
@@ -1378,7 +1791,12 @@ export class ChatRunner {
|
|
|
1378
1791
|
if (this.hasUsage(turnUsage)) {
|
|
1379
1792
|
history.recordUsage("execution", turnUsage);
|
|
1380
1793
|
}
|
|
1794
|
+
const diffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
1795
|
+
if (diffArtifact) {
|
|
1796
|
+
this.emitDiffArtifact(diffArtifact, eventContext);
|
|
1797
|
+
}
|
|
1381
1798
|
await history.appendAssistantMessage(output);
|
|
1799
|
+
this.emitCheckpoint("Response ready", "The direct answer has been persisted for this turn.", eventContext, "complete");
|
|
1382
1800
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1383
1801
|
this.emitEvent({
|
|
1384
1802
|
type: "assistant_final",
|
|
@@ -1401,13 +1819,11 @@ export class ChatRunner {
|
|
|
1401
1819
|
}
|
|
1402
1820
|
catch (err) {
|
|
1403
1821
|
const message = err instanceof Error ? err.message : String(err);
|
|
1404
|
-
this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1822
|
+
const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1405
1823
|
this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
|
|
1406
1824
|
return {
|
|
1407
1825
|
success: false,
|
|
1408
|
-
output
|
|
1409
|
-
? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
|
|
1410
|
-
: `Error: ${message}`,
|
|
1826
|
+
output,
|
|
1411
1827
|
elapsed_ms: Date.now() - start,
|
|
1412
1828
|
diagnostics: {
|
|
1413
1829
|
route: "direct",
|
|
@@ -1453,6 +1869,9 @@ export class ChatRunner {
|
|
|
1453
1869
|
catch {
|
|
1454
1870
|
systemPrompt = this.cachedStaticSystemPrompt ?? "";
|
|
1455
1871
|
}
|
|
1872
|
+
this.emitCheckpoint("Context gathered", usesNativeAgentLoop
|
|
1873
|
+
? "Workspace and agent-loop grounding are ready."
|
|
1874
|
+
: "Workspace grounding is ready.", eventContext, "context");
|
|
1456
1875
|
}
|
|
1457
1876
|
const agentLoopSystemPrompt = [
|
|
1458
1877
|
systemPrompt,
|
|
@@ -1466,13 +1885,7 @@ export class ChatRunner {
|
|
|
1466
1885
|
const prompt = historyBlock ? `${historyBlock}${basePrompt}` : basePrompt;
|
|
1467
1886
|
if (resumeOnly && !this.deps.chatAgentLoopRunner) {
|
|
1468
1887
|
const elapsed_ms = Date.now() - start;
|
|
1469
|
-
const output = "Resume requires the native chat agentloop runtime.";
|
|
1470
|
-
this.emitEvent({
|
|
1471
|
-
type: "assistant_final",
|
|
1472
|
-
text: output,
|
|
1473
|
-
persisted: false,
|
|
1474
|
-
...this.eventBase(eventContext),
|
|
1475
|
-
});
|
|
1888
|
+
const output = this.emitLifecycleErrorEvent("Resume requires the native chat agentloop runtime.", assistantBuffer.text, eventContext);
|
|
1476
1889
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1477
1890
|
return {
|
|
1478
1891
|
success: false,
|
|
@@ -1486,13 +1899,7 @@ export class ChatRunner {
|
|
|
1486
1899
|
const resumeState = resumeOnly ? await this.loadResumableAgentLoopState() : null;
|
|
1487
1900
|
if (resumeOnly && !resumeState) {
|
|
1488
1901
|
const elapsed_ms = Date.now() - start;
|
|
1489
|
-
const output = "No resumable native agentloop state found.";
|
|
1490
|
-
this.emitEvent({
|
|
1491
|
-
type: "assistant_final",
|
|
1492
|
-
text: output,
|
|
1493
|
-
persisted: false,
|
|
1494
|
-
...this.eventBase(eventContext),
|
|
1495
|
-
});
|
|
1902
|
+
const output = this.emitLifecycleErrorEvent("No resumable native agentloop state found.", assistantBuffer.text, eventContext);
|
|
1496
1903
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1497
1904
|
return {
|
|
1498
1905
|
success: false,
|
|
@@ -1500,6 +1907,9 @@ export class ChatRunner {
|
|
|
1500
1907
|
elapsed_ms,
|
|
1501
1908
|
};
|
|
1502
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");
|
|
1503
1913
|
this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
|
|
1504
1914
|
const result = await chatAgentLoopRunner.execute({
|
|
1505
1915
|
message: basePrompt,
|
|
@@ -1523,6 +1933,7 @@ export class ChatRunner {
|
|
|
1523
1933
|
...(resumeState ? { resumeState } : {}),
|
|
1524
1934
|
...(resumeOnly ? { resumeOnly: true } : {}),
|
|
1525
1935
|
...(agentLoopSystemPrompt ? { systemPrompt: agentLoopSystemPrompt } : {}),
|
|
1936
|
+
abortSignal: activeTurn.abortController.signal,
|
|
1526
1937
|
});
|
|
1527
1938
|
const elapsed_ms = Date.now() - start;
|
|
1528
1939
|
const agentLoopUsage = result.agentLoop?.usage
|
|
@@ -1535,7 +1946,12 @@ export class ChatRunner {
|
|
|
1535
1946
|
this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
|
|
1536
1947
|
}
|
|
1537
1948
|
if (result.success) {
|
|
1949
|
+
const diffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
1950
|
+
if (diffArtifact) {
|
|
1951
|
+
this.emitDiffArtifact(diffArtifact, eventContext);
|
|
1952
|
+
}
|
|
1538
1953
|
await history.appendAssistantMessage(result.output);
|
|
1954
|
+
this.emitCheckpoint("Response ready", "The agent-loop response has been persisted for this turn.", eventContext, "complete");
|
|
1539
1955
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1540
1956
|
this.emitEvent({
|
|
1541
1957
|
type: "assistant_final",
|
|
@@ -1546,7 +1962,7 @@ export class ChatRunner {
|
|
|
1546
1962
|
this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
|
|
1547
1963
|
}
|
|
1548
1964
|
else {
|
|
1549
|
-
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);
|
|
1550
1966
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1551
1967
|
}
|
|
1552
1968
|
return {
|
|
@@ -1557,13 +1973,11 @@ export class ChatRunner {
|
|
|
1557
1973
|
}
|
|
1558
1974
|
catch (err) {
|
|
1559
1975
|
const message = err instanceof Error ? err.message : String(err);
|
|
1560
|
-
this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1976
|
+
const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1561
1977
|
this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
|
|
1562
1978
|
return {
|
|
1563
1979
|
success: false,
|
|
1564
|
-
output
|
|
1565
|
-
? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
|
|
1566
|
-
: `Error: ${message}`,
|
|
1980
|
+
output,
|
|
1567
1981
|
elapsed_ms: Date.now() - start,
|
|
1568
1982
|
};
|
|
1569
1983
|
}
|
|
@@ -1571,12 +1985,18 @@ export class ChatRunner {
|
|
|
1571
1985
|
// Prefer the local LLM/tool loop over the external adapter fallback whenever a client is available.
|
|
1572
1986
|
if (selectedRoute?.kind === "tool_loop") {
|
|
1573
1987
|
try {
|
|
1988
|
+
this.emitCheckpoint("Tool loop started", "The model will choose tools from the active catalog.", eventContext, "execution");
|
|
1574
1989
|
const toolResult = await this.executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt || undefined, executionGoalId);
|
|
1575
1990
|
const elapsed_ms = Date.now() - start;
|
|
1576
1991
|
if (this.hasUsage(toolResult.usage)) {
|
|
1577
1992
|
history.recordUsage("execution", toolResult.usage);
|
|
1578
1993
|
}
|
|
1994
|
+
const diffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
1995
|
+
if (diffArtifact) {
|
|
1996
|
+
this.emitDiffArtifact(diffArtifact, eventContext);
|
|
1997
|
+
}
|
|
1579
1998
|
await history.appendAssistantMessage(toolResult.output);
|
|
1999
|
+
this.emitCheckpoint("Response ready", "The tool-loop response has been persisted for this turn.", eventContext, "complete");
|
|
1580
2000
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1581
2001
|
this.emitEvent({
|
|
1582
2002
|
type: "assistant_final",
|
|
@@ -1589,21 +2009,18 @@ export class ChatRunner {
|
|
|
1589
2009
|
}
|
|
1590
2010
|
catch (err) {
|
|
1591
2011
|
const message = err instanceof Error ? err.message : String(err);
|
|
1592
|
-
this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
2012
|
+
const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
|
|
1593
2013
|
this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
|
|
1594
2014
|
return {
|
|
1595
2015
|
success: false,
|
|
1596
|
-
output
|
|
1597
|
-
? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
|
|
1598
|
-
: `Error: ${message}`,
|
|
2016
|
+
output,
|
|
1599
2017
|
elapsed_ms: Date.now() - start,
|
|
1600
2018
|
};
|
|
1601
2019
|
}
|
|
1602
2020
|
}
|
|
1603
2021
|
if (!resumeOnly && selectedRoute && selectedRoute.kind !== "adapter") {
|
|
1604
2022
|
const elapsed_ms = Date.now() - start;
|
|
1605
|
-
const output = `Unsupported chat route: ${selectedRoute.kind}
|
|
1606
|
-
this.emitLifecycleErrorEvent(output, assistantBuffer.text, eventContext);
|
|
2023
|
+
const output = this.emitLifecycleErrorEvent(`Unsupported chat route: ${selectedRoute.kind}`, assistantBuffer.text, eventContext);
|
|
1607
2024
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1608
2025
|
return {
|
|
1609
2026
|
success: false,
|
|
@@ -1619,10 +2036,25 @@ export class ChatRunner {
|
|
|
1619
2036
|
...(systemPrompt ? { system_prompt: systemPrompt } : {}),
|
|
1620
2037
|
};
|
|
1621
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");
|
|
1622
2040
|
this.emitActivity("lifecycle", "Calling adapter...", eventContext, "lifecycle:adapter");
|
|
1623
2041
|
const adapterPromise = this.deps.adapter.execute(task);
|
|
1624
2042
|
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Chat adapter timed out after ${resolvedTimeoutMs}ms`)), resolvedTimeoutMs));
|
|
1625
|
-
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
|
+
}
|
|
1626
2058
|
// Surface adapter errors into output when output is empty
|
|
1627
2059
|
if (!result.output && result.error) {
|
|
1628
2060
|
result = { ...result, output: `Error: ${result.error}` };
|
|
@@ -1632,34 +2064,47 @@ export class ChatRunner {
|
|
|
1632
2064
|
this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
|
|
1633
2065
|
}
|
|
1634
2066
|
// Verification loop: check if git has uncommitted changes; if so, run tests
|
|
1635
|
-
const
|
|
1636
|
-
if (
|
|
2067
|
+
const diffArtifact = await collectGitDiffArtifact(gitRoot);
|
|
2068
|
+
if (diffArtifact) {
|
|
1637
2069
|
let retries = 0;
|
|
1638
2070
|
const VERIFY_TIMEOUT_MS = 30_000;
|
|
2071
|
+
this.emitCheckpoint("Changes detected", "Verification is starting because the turn changed the working tree.", eventContext, "changes");
|
|
1639
2072
|
this.emitActivity("lifecycle", "Checking result...", eventContext, "lifecycle:checking");
|
|
1640
2073
|
let verification = await Promise.race([
|
|
1641
|
-
verifyChatAction(gitRoot, this.deps.toolExecutor),
|
|
2074
|
+
verifyChatAction(gitRoot, this.deps.toolExecutor, { force: true }),
|
|
1642
2075
|
new Promise((resolve) => setTimeout(() => resolve({ passed: true }), VERIFY_TIMEOUT_MS)),
|
|
1643
2076
|
]);
|
|
1644
2077
|
while (!verification.passed && retries < MAX_VERIFY_RETRIES) {
|
|
1645
2078
|
retries++;
|
|
2079
|
+
this.emitCheckpoint("Verification retry", `Attempt ${retries} of ${MAX_VERIFY_RETRIES} is repairing failed checks.`, eventContext, `verification-retry-${retries}`);
|
|
1646
2080
|
const retryPrompt = `The previous changes caused test failures. Please fix them.\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`;
|
|
1647
2081
|
const retryTask = { ...task, prompt: retryPrompt };
|
|
1648
2082
|
result = await this.deps.adapter.execute(retryTask);
|
|
1649
|
-
verification = await verifyChatAction(gitRoot, this.deps.toolExecutor);
|
|
2083
|
+
verification = await verifyChatAction(gitRoot, this.deps.toolExecutor, { force: true });
|
|
1650
2084
|
}
|
|
1651
2085
|
if (!verification.passed) {
|
|
1652
|
-
|
|
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);
|
|
1653
2092
|
this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
|
|
1654
2093
|
return {
|
|
1655
2094
|
success: false,
|
|
1656
|
-
output: `${
|
|
2095
|
+
output: `${failureOutput}\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`.trim(),
|
|
1657
2096
|
elapsed_ms: Date.now() - start,
|
|
1658
2097
|
};
|
|
1659
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");
|
|
1660
2104
|
}
|
|
1661
2105
|
if (result.success) {
|
|
1662
2106
|
await history.appendAssistantMessage(result.output);
|
|
2107
|
+
this.emitCheckpoint("Response ready", "The assistant response has been persisted for this turn.", eventContext, "complete");
|
|
1663
2108
|
this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
|
|
1664
2109
|
this.emitEvent({
|
|
1665
2110
|
type: "assistant_final",
|
|
@@ -1671,7 +2116,7 @@ export class ChatRunner {
|
|
|
1671
2116
|
}
|
|
1672
2117
|
else {
|
|
1673
2118
|
const partialText = assistantBuffer.text !== result.output ? assistantBuffer.text : "";
|
|
1674
|
-
this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
|
|
2119
|
+
result.output = this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
|
|
1675
2120
|
this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
|
|
1676
2121
|
}
|
|
1677
2122
|
return {
|
|
@@ -1854,6 +2299,7 @@ export class ChatRunner {
|
|
|
1854
2299
|
}
|
|
1855
2300
|
if (event.type === "plan_update") {
|
|
1856
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}`);
|
|
1857
2303
|
this.emitEvent({
|
|
1858
2304
|
type: "tool_update",
|
|
1859
2305
|
toolCallId: `plan:${event.turnId}:${event.createdAt}`,
|
|
@@ -1866,6 +2312,7 @@ export class ChatRunner {
|
|
|
1866
2312
|
}
|
|
1867
2313
|
if (event.type === "approval_request") {
|
|
1868
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}`);
|
|
1869
2316
|
this.emitEvent({
|
|
1870
2317
|
type: "tool_update",
|
|
1871
2318
|
toolCallId: event.callId,
|
|
@@ -1924,6 +2371,34 @@ export class ChatRunner {
|
|
|
1924
2371
|
}
|
|
1925
2372
|
return preview ? { preview } : {};
|
|
1926
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
|
+
}
|
|
1927
2402
|
parseResumeCommand(input) {
|
|
1928
2403
|
const trimmed = input.trim();
|
|
1929
2404
|
const match = /^\/resume(?:\s+(.+))?$/i.exec(trimmed);
|
|
@@ -2134,11 +2609,81 @@ export class ChatRunner {
|
|
|
2134
2609
|
eventBase(context) {
|
|
2135
2610
|
return { ...context, createdAt: new Date().toISOString() };
|
|
2136
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
|
+
}
|
|
2137
2681
|
emitEvent(event) {
|
|
2682
|
+
this.rememberActiveTurnEvent(event);
|
|
2138
2683
|
const handler = this.onEvent ?? this.deps.onEvent;
|
|
2139
2684
|
handler?.(event);
|
|
2140
2685
|
}
|
|
2141
|
-
emitActivity(kind, message, eventContext, sourceId) {
|
|
2686
|
+
emitActivity(kind, message, eventContext, sourceId, transient = true) {
|
|
2142
2687
|
if (!message.trim())
|
|
2143
2688
|
return;
|
|
2144
2689
|
this.emitEvent({
|
|
@@ -2146,10 +2691,72 @@ export class ChatRunner {
|
|
|
2146
2691
|
kind,
|
|
2147
2692
|
message,
|
|
2148
2693
|
...(sourceId ? { sourceId } : {}),
|
|
2149
|
-
transient
|
|
2694
|
+
transient,
|
|
2150
2695
|
...this.eventBase(eventContext),
|
|
2151
2696
|
});
|
|
2152
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
|
+
}
|
|
2153
2760
|
pushAssistantDelta(delta, assistantBuffer, eventContext) {
|
|
2154
2761
|
if (!delta)
|
|
2155
2762
|
return;
|
|
@@ -2169,15 +2776,19 @@ export class ChatRunner {
|
|
|
2169
2776
|
persisted,
|
|
2170
2777
|
...this.eventBase(eventContext),
|
|
2171
2778
|
});
|
|
2779
|
+
this.finishActiveTurn(eventContext);
|
|
2172
2780
|
}
|
|
2173
2781
|
emitLifecycleErrorEvent(error, partialText, eventContext) {
|
|
2782
|
+
const recovery = classifyFailureRecovery(error);
|
|
2174
2783
|
this.emitEvent({
|
|
2175
2784
|
type: "lifecycle_error",
|
|
2176
2785
|
error,
|
|
2177
2786
|
partialText,
|
|
2178
2787
|
persisted: false,
|
|
2788
|
+
recovery,
|
|
2179
2789
|
...this.eventBase(eventContext),
|
|
2180
2790
|
});
|
|
2791
|
+
return formatLifecycleFailureMessage(error, partialText, recovery);
|
|
2181
2792
|
}
|
|
2182
2793
|
/** Build a ToolCallContext from ChatRunnerDeps for tool dispatch. */
|
|
2183
2794
|
async getSessionExecutionPolicy() {
|