@getpaseo/server 0.1.30 → 0.1.32
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/scripts/daemon-runner.js +1 -1
- package/dist/scripts/daemon-runner.js.map +1 -1
- package/dist/scripts/dev-runner.js +1 -1
- package/dist/scripts/dev-runner.js.map +1 -1
- package/dist/server/client/daemon-client-relay-e2ee-transport.d.ts.map +1 -1
- package/dist/server/client/daemon-client-relay-e2ee-transport.js.map +1 -1
- package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -1
- package/dist/server/client/daemon-client-websocket-transport.js.map +1 -1
- package/dist/server/client/daemon-client.d.ts +108 -103
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +417 -407
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/server/agent/activity-curator.d.ts.map +1 -1
- package/dist/server/server/agent/activity-curator.js +5 -4
- package/dist/server/server/agent/activity-curator.js.map +1 -1
- package/dist/server/server/agent/agent-management-mcp.d.ts.map +1 -1
- package/dist/server/server/agent/agent-management-mcp.js +13 -17
- package/dist/server/server/agent/agent-management-mcp.js.map +1 -1
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
- package/dist/server/server/agent/agent-manager.js +26 -26
- package/dist/server/server/agent/agent-manager.js.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.js +1 -3
- package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
- package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
- package/dist/server/server/agent/agent-projections.js +4 -12
- package/dist/server/server/agent/agent-projections.js.map +1 -1
- package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -1
- package/dist/server/server/agent/agent-response-loop.js +6 -6
- package/dist/server/server/agent/agent-response-loop.js.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts +23 -0
- package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
- package/dist/server/server/agent/agent-storage.d.ts.map +1 -1
- package/dist/server/server/agent/agent-storage.js +2 -4
- package/dist/server/server/agent/agent-storage.js.map +1 -1
- package/dist/server/server/agent/dictation-debug.d.ts.map +1 -1
- package/dist/server/server/agent/dictation-debug.js.map +1 -1
- package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
- package/dist/server/server/agent/mcp-server.js +19 -27
- package/dist/server/server/agent/mcp-server.js.map +1 -1
- package/dist/server/server/agent/pcm16-resampler.d.ts.map +1 -1
- package/dist/server/server/agent/pcm16-resampler.js.map +1 -1
- package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -1
- package/dist/server/server/agent/provider-launch-config.js +4 -2
- package/dist/server/server/agent/provider-launch-config.js.map +1 -1
- package/dist/server/server/agent/provider-manifest.d.ts +2 -2
- package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
- package/dist/server/server/agent/provider-manifest.js +63 -9
- package/dist/server/server/agent/provider-manifest.js.map +1 -1
- package/dist/server/server/agent/provider-registry.d.ts +2 -2
- package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
- package/dist/server/server/agent/provider-registry.js +1 -1
- package/dist/server/server/agent/provider-registry.js.map +1 -1
- package/dist/server/server/agent/providers/claude/model-catalog.js +10 -10
- package/dist/server/server/agent/providers/claude/model-catalog.js.map +1 -1
- package/dist/server/server/agent/providers/claude/partial-json.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/partial-json.js +4 -4
- package/dist/server/server/agent/providers/claude/partial-json.js.map +1 -1
- package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +20 -0
- package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts.map +1 -0
- package/dist/server/server/agent/providers/claude/sidechain-tracker.js +230 -0
- package/dist/server/server/agent/providers/claude/sidechain-tracker.js.map +1 -0
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +11 -0
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +37 -20
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.js.map +1 -1
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +21 -11
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -1
- package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js +23 -11
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude-agent.js +486 -1134
- package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js +2 -2
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js.map +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js +14 -11
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.js +347 -163
- package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
- package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex-rollout-timeline.js +21 -32
- package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +2 -2
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +2 -9
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.js +5 -5
- package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +277 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.js +149 -15
- package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -1
- package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js +1 -3
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -1
- package/dist/server/server/agent/stt-manager.d.ts.map +1 -1
- package/dist/server/server/agent/stt-manager.js +1 -2
- package/dist/server/server/agent/stt-manager.js.map +1 -1
- package/dist/server/server/agent/system-prompt.js +5 -5
- package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
- package/dist/server/server/agent/timeline-projection.js.map +1 -1
- package/dist/server/server/agent/tts-manager.d.ts.map +1 -1
- package/dist/server/server/agent/tts-manager.js +27 -9
- package/dist/server/server/agent/tts-manager.js.map +1 -1
- package/dist/server/server/agent/wait-for-agent-tracker.d.ts.map +1 -1
- package/dist/server/server/agent/wait-for-agent-tracker.js.map +1 -1
- package/dist/server/server/agent-attention-policy.d.ts.map +1 -1
- package/dist/server/server/agent-attention-policy.js.map +1 -1
- package/dist/server/server/allowed-hosts.d.ts.map +1 -1
- package/dist/server/server/allowed-hosts.js.map +1 -1
- package/dist/server/server/bootstrap.d.ts.map +1 -1
- package/dist/server/server/bootstrap.js +46 -5
- package/dist/server/server/bootstrap.js.map +1 -1
- package/dist/server/server/config.d.ts.map +1 -1
- package/dist/server/server/config.js +4 -11
- package/dist/server/server/config.js.map +1 -1
- package/dist/server/server/connection-offer.d.ts +1 -1
- package/dist/server/server/connection-offer.d.ts.map +1 -1
- package/dist/server/server/connection-offer.js +2 -3
- package/dist/server/server/connection-offer.js.map +1 -1
- package/dist/server/server/daemon-version.d.ts.map +1 -1
- package/dist/server/server/daemon-version.js +1 -1
- package/dist/server/server/daemon-version.js.map +1 -1
- package/dist/server/server/dictation/dictation-stream-manager.d.ts.map +1 -1
- package/dist/server/server/dictation/dictation-stream-manager.js +4 -1
- package/dist/server/server/dictation/dictation-stream-manager.js.map +1 -1
- package/dist/server/server/exports.d.ts +1 -1
- package/dist/server/server/exports.d.ts.map +1 -1
- package/dist/server/server/exports.js +1 -1
- package/dist/server/server/exports.js.map +1 -1
- package/dist/server/server/file-explorer/service.d.ts +1 -1
- package/dist/server/server/file-explorer/service.d.ts.map +1 -1
- package/dist/server/server/file-explorer/service.js +5 -8
- package/dist/server/server/file-explorer/service.js.map +1 -1
- package/dist/server/server/index.js +1 -1
- package/dist/server/server/index.js.map +1 -1
- package/dist/server/server/logger.d.ts.map +1 -1
- package/dist/server/server/logger.js.map +1 -1
- package/dist/server/server/messages.d.ts.map +1 -1
- package/dist/server/server/messages.js.map +1 -1
- package/dist/server/server/package-version.d.ts.map +1 -1
- package/dist/server/server/package-version.js +1 -2
- package/dist/server/server/package-version.js.map +1 -1
- package/dist/server/server/persisted-config.d.ts.map +1 -1
- package/dist/server/server/persisted-config.js.map +1 -1
- package/dist/server/server/persistence-hooks.d.ts.map +1 -1
- package/dist/server/server/persistence-hooks.js.map +1 -1
- package/dist/server/server/pid-lock.d.ts.map +1 -1
- package/dist/server/server/pid-lock.js.map +1 -1
- package/dist/server/server/push/push-service.d.ts.map +1 -1
- package/dist/server/server/push/push-service.js.map +1 -1
- package/dist/server/server/relay-transport.d.ts.map +1 -1
- package/dist/server/server/relay-transport.js +6 -2
- package/dist/server/server/relay-transport.js.map +1 -1
- package/dist/server/server/session.d.ts +49 -37
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +1234 -998
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/server/speech/audio.d.ts.map +1 -1
- package/dist/server/server/speech/audio.js.map +1 -1
- package/dist/server/server/speech/providers/local/config.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/config.js +5 -14
- package/dist/server/server/speech/providers/local/config.js.map +1 -1
- package/dist/server/server/speech/providers/local/models.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/models.js +1 -1
- package/dist/server/server/speech/providers/local/models.js.map +1 -1
- package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js +21 -7
- package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js.map +1 -1
- package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/runtime.js +1 -23
- package/dist/server/server/speech/providers/local/runtime.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/model-downloader.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +9 -4
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js +7 -2
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +5 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +2 -4
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js +1 -3
- package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js +2 -4
- package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +4 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js +1 -1
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js.map +1 -1
- package/dist/server/server/speech/providers/openai/config.d.ts.map +1 -1
- package/dist/server/server/speech/providers/openai/config.js +5 -24
- package/dist/server/server/speech/providers/openai/config.js.map +1 -1
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts.map +1 -1
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +6 -3
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.js.map +1 -1
- package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -1
- package/dist/server/server/speech/providers/openai/runtime.js +2 -6
- package/dist/server/server/speech/providers/openai/runtime.js.map +1 -1
- package/dist/server/server/speech/providers/openai/stt.d.ts.map +1 -1
- package/dist/server/server/speech/providers/openai/stt.js +1 -3
- package/dist/server/server/speech/providers/openai/stt.js.map +1 -1
- package/dist/server/server/speech/providers/openai/tts.d.ts.map +1 -1
- package/dist/server/server/speech/providers/openai/tts.js.map +1 -1
- package/dist/server/server/speech/speech-config-resolver.d.ts.map +1 -1
- package/dist/server/server/speech/speech-config-resolver.js +3 -7
- package/dist/server/server/speech/speech-config-resolver.js.map +1 -1
- package/dist/server/server/speech/speech-provider.d.ts.map +1 -1
- package/dist/server/server/speech/speech-runtime.d.ts.map +1 -1
- package/dist/server/server/speech/speech-runtime.js.map +1 -1
- package/dist/server/server/speech/turn-detection-provider.d.ts.map +1 -1
- package/dist/server/server/terminal-mcp/server.d.ts.map +1 -1
- package/dist/server/server/terminal-mcp/server.js +3 -11
- package/dist/server/server/terminal-mcp/server.js.map +1 -1
- package/dist/server/server/terminal-mcp/terminal-manager.d.ts.map +1 -1
- package/dist/server/server/terminal-mcp/terminal-manager.js +2 -14
- package/dist/server/server/terminal-mcp/terminal-manager.js.map +1 -1
- package/dist/server/server/terminal-mcp/tmux.d.ts +1 -1
- package/dist/server/server/terminal-mcp/tmux.d.ts.map +1 -1
- package/dist/server/server/terminal-mcp/tmux.js +20 -123
- package/dist/server/server/terminal-mcp/tmux.js.map +1 -1
- package/dist/server/server/utils/diff-highlighter.d.ts +11 -3
- package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -1
- package/dist/server/server/utils/diff-highlighter.js +49 -36
- package/dist/server/server/utils/diff-highlighter.js.map +1 -1
- package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.d.ts.map +1 -1
- package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.js.map +1 -1
- package/dist/server/server/voice/voice-turn-controller.d.ts.map +1 -1
- package/dist/server/server/voice/voice-turn-controller.js +1 -3
- package/dist/server/server/voice/voice-turn-controller.js.map +1 -1
- package/dist/server/server/voice-config.d.ts.map +1 -1
- package/dist/server/server/voice-config.js.map +1 -1
- package/dist/server/server/voice-mcp-bridge.d.ts.map +1 -1
- package/dist/server/server/voice-mcp-bridge.js.map +1 -1
- package/dist/server/server/websocket-server.d.ts +1 -0
- package/dist/server/server/websocket-server.d.ts.map +1 -1
- package/dist/server/server/websocket-server.js +20 -22
- package/dist/server/server/websocket-server.js.map +1 -1
- package/dist/server/server/workspace-registry-bootstrap.d.ts +3 -3
- package/dist/server/server/workspace-registry-bootstrap.d.ts.map +1 -1
- package/dist/server/server/workspace-registry-bootstrap.js +6 -6
- package/dist/server/server/workspace-registry-bootstrap.js.map +1 -1
- package/dist/server/server/workspace-registry-model.d.ts +14 -3
- package/dist/server/server/workspace-registry-model.d.ts.map +1 -1
- package/dist/server/server/workspace-registry-model.js +40 -15
- package/dist/server/server/workspace-registry-model.js.map +1 -1
- package/dist/server/server/workspace-registry.d.ts +5 -5
- package/dist/server/server/workspace-registry.d.ts.map +1 -1
- package/dist/server/server/workspace-registry.js +16 -13
- package/dist/server/server/workspace-registry.js.map +1 -1
- package/dist/server/server/worktree-bootstrap.d.ts.map +1 -1
- package/dist/server/server/worktree-bootstrap.js +17 -6
- package/dist/server/server/worktree-bootstrap.js.map +1 -1
- package/dist/server/shared/agent-attention-notification.d.ts.map +1 -1
- package/dist/server/shared/agent-attention-notification.js.map +1 -1
- package/dist/server/shared/agent-lifecycle.d.ts.map +1 -1
- package/dist/server/shared/daemon-endpoints.d.ts +1 -0
- package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
- package/dist/server/shared/daemon-endpoints.js +11 -2
- package/dist/server/shared/daemon-endpoints.js.map +1 -1
- package/dist/server/shared/messages.d.ts +1228 -2982
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +330 -302
- package/dist/server/shared/messages.js.map +1 -1
- package/dist/server/shared/terminal-stream-protocol.d.ts +36 -0
- package/dist/server/shared/terminal-stream-protocol.d.ts.map +1 -0
- package/dist/server/shared/terminal-stream-protocol.js +99 -0
- package/dist/server/shared/terminal-stream-protocol.js.map +1 -0
- package/dist/server/shared/tool-call-display.d.ts.map +1 -1
- package/dist/server/shared/tool-call-display.js +6 -3
- package/dist/server/shared/tool-call-display.js.map +1 -1
- package/dist/server/terminal/terminal.d.ts +5 -48
- package/dist/server/terminal/terminal.d.ts.map +1 -1
- package/dist/server/terminal/terminal.js +44 -98
- package/dist/server/terminal/terminal.js.map +1 -1
- package/dist/server/utils/checkout-git.d.ts +1 -0
- package/dist/server/utils/checkout-git.d.ts.map +1 -1
- package/dist/server/utils/checkout-git.js +111 -120
- package/dist/server/utils/checkout-git.js.map +1 -1
- package/dist/server/utils/directory-suggestions.d.ts +1 -1
- package/dist/server/utils/directory-suggestions.d.ts.map +1 -1
- package/dist/server/utils/directory-suggestions.js +40 -40
- package/dist/server/utils/directory-suggestions.js.map +1 -1
- package/dist/server/utils/project-icon.d.ts.map +1 -1
- package/dist/server/utils/project-icon.js +2 -11
- package/dist/server/utils/project-icon.js.map +1 -1
- package/dist/server/utils/worktree.d.ts +2 -0
- package/dist/server/utils/worktree.d.ts.map +1 -1
- package/dist/server/utils/worktree.js +22 -19
- package/dist/server/utils/worktree.js.map +1 -1
- package/dist/src/server/agent/activity-curator.js +5 -4
- package/dist/src/server/agent/activity-curator.js.map +1 -1
- package/dist/src/server/agent/agent-manager.js +26 -26
- package/dist/src/server/agent/agent-manager.js.map +1 -1
- package/dist/src/server/agent/agent-metadata-generator.js +1 -3
- package/dist/src/server/agent/agent-metadata-generator.js.map +1 -1
- package/dist/src/server/agent/agent-projections.js +4 -12
- package/dist/src/server/agent/agent-projections.js.map +1 -1
- package/dist/src/server/agent/agent-response-loop.js +6 -6
- package/dist/src/server/agent/agent-response-loop.js.map +1 -1
- package/dist/src/server/agent/agent-sdk-types.js.map +1 -1
- package/dist/src/server/agent/agent-storage.js +2 -4
- package/dist/src/server/agent/agent-storage.js.map +1 -1
- package/dist/src/server/agent/dictation-debug.js.map +1 -1
- package/dist/src/server/agent/mcp-server.js +19 -27
- package/dist/src/server/agent/mcp-server.js.map +1 -1
- package/dist/src/server/agent/pcm16-resampler.js.map +1 -1
- package/dist/src/server/agent/provider-launch-config.js +4 -2
- package/dist/src/server/agent/provider-launch-config.js.map +1 -1
- package/dist/src/server/agent/provider-manifest.js +63 -9
- package/dist/src/server/agent/provider-manifest.js.map +1 -1
- package/dist/src/server/agent/provider-registry.js +1 -1
- package/dist/src/server/agent/provider-registry.js.map +1 -1
- package/dist/src/server/agent/providers/claude/model-catalog.js +10 -10
- package/dist/src/server/agent/providers/claude/model-catalog.js.map +1 -1
- package/dist/src/server/agent/providers/claude/partial-json.js +4 -4
- package/dist/src/server/agent/providers/claude/partial-json.js.map +1 -1
- package/dist/src/server/agent/providers/claude/sidechain-tracker.js +230 -0
- package/dist/src/server/agent/providers/claude/sidechain-tracker.js.map +1 -0
- package/dist/src/server/agent/providers/claude/task-notification-tool-call.js +37 -20
- package/dist/src/server/agent/providers/claude/task-notification-tool-call.js.map +1 -1
- package/dist/src/server/agent/providers/claude/tool-call-detail-parser.js +21 -11
- package/dist/src/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -1
- package/dist/src/server/agent/providers/claude/tool-call-mapper.js +23 -11
- package/dist/src/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
- package/dist/src/server/agent/providers/claude-agent.js +486 -1134
- package/dist/src/server/agent/providers/claude-agent.js.map +1 -1
- package/dist/src/server/agent/providers/codex/tool-call-detail-parser.js +2 -2
- package/dist/src/server/agent/providers/codex/tool-call-detail-parser.js.map +1 -1
- package/dist/src/server/agent/providers/codex/tool-call-mapper.js +14 -11
- package/dist/src/server/agent/providers/codex/tool-call-mapper.js.map +1 -1
- package/dist/src/server/agent/providers/codex-app-server-agent.js +347 -163
- package/dist/src/server/agent/providers/codex-app-server-agent.js.map +1 -1
- package/dist/src/server/agent/providers/codex-rollout-timeline.js +21 -32
- package/dist/src/server/agent/providers/codex-rollout-timeline.js.map +1 -1
- package/dist/src/server/agent/providers/opencode/tool-call-detail-parser.js +2 -2
- package/dist/src/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -1
- package/dist/src/server/agent/providers/opencode/tool-call-mapper.js +2 -9
- package/dist/src/server/agent/providers/opencode/tool-call-mapper.js.map +1 -1
- package/dist/src/server/agent/providers/opencode-agent.js +5 -5
- package/dist/src/server/agent/providers/opencode-agent.js.map +1 -1
- package/dist/src/server/agent/providers/tool-call-detail-primitives.js +149 -15
- package/dist/src/server/agent/providers/tool-call-detail-primitives.js.map +1 -1
- package/dist/src/server/agent/providers/tool-call-mapper-utils.js +1 -3
- package/dist/src/server/agent/providers/tool-call-mapper-utils.js.map +1 -1
- package/dist/src/server/agent/stt-manager.js +1 -2
- package/dist/src/server/agent/stt-manager.js.map +1 -1
- package/dist/src/server/agent/timeline-projection.js.map +1 -1
- package/dist/src/server/agent/tts-manager.js +27 -9
- package/dist/src/server/agent/tts-manager.js.map +1 -1
- package/dist/src/server/agent/wait-for-agent-tracker.js.map +1 -1
- package/dist/src/server/agent-attention-policy.js.map +1 -1
- package/dist/src/server/allowed-hosts.js.map +1 -1
- package/dist/src/server/bootstrap.js +46 -5
- package/dist/src/server/bootstrap.js.map +1 -1
- package/dist/src/server/config.js +4 -11
- package/dist/src/server/config.js.map +1 -1
- package/dist/src/server/connection-offer.js +2 -3
- package/dist/src/server/connection-offer.js.map +1 -1
- package/dist/src/server/daemon-version.js +1 -1
- package/dist/src/server/daemon-version.js.map +1 -1
- package/dist/src/server/dictation/dictation-stream-manager.js +4 -1
- package/dist/src/server/dictation/dictation-stream-manager.js.map +1 -1
- package/dist/src/server/file-explorer/service.js +5 -8
- package/dist/src/server/file-explorer/service.js.map +1 -1
- package/dist/src/server/messages.js.map +1 -1
- package/dist/src/server/package-version.js +1 -2
- package/dist/src/server/package-version.js.map +1 -1
- package/dist/src/server/pairing-offer.js +45 -0
- package/dist/src/server/pairing-offer.js.map +1 -0
- package/dist/src/server/pairing-qr.js +45 -0
- package/dist/src/server/pairing-qr.js.map +1 -0
- package/dist/src/server/persisted-config.js.map +1 -1
- package/dist/src/server/persistence-hooks.js.map +1 -1
- package/dist/src/server/pid-lock.js.map +1 -1
- package/dist/src/server/push/push-service.js.map +1 -1
- package/dist/src/server/relay-transport.js +6 -2
- package/dist/src/server/relay-transport.js.map +1 -1
- package/dist/src/server/session.js +1234 -998
- package/dist/src/server/session.js.map +1 -1
- package/dist/src/server/speech/audio.js.map +1 -1
- package/dist/src/server/speech/providers/local/config.js +5 -14
- package/dist/src/server/speech/providers/local/config.js.map +1 -1
- package/dist/src/server/speech/providers/local/models.js +1 -1
- package/dist/src/server/speech/providers/local/models.js.map +1 -1
- package/dist/src/server/speech/providers/local/pocket/pocket-tts-onnx.js +21 -7
- package/dist/src/server/speech/providers/local/pocket/pocket-tts-onnx.js.map +1 -1
- package/dist/src/server/speech/providers/local/runtime.js +1 -23
- package/dist/src/server/speech/providers/local/runtime.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/model-catalog.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/model-downloader.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +9 -4
- package/dist/src/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-online-recognizer.js +7 -2
- package/dist/src/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +5 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +2 -4
- package/dist/src/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-realtime-session.js +1 -3
- package/dist/src/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-stt.js +2 -4
- package/dist/src/server/speech/providers/local/sherpa/sherpa-stt.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-tts.js +4 -1
- package/dist/src/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/silero-vad-provider.js +1 -1
- package/dist/src/server/speech/providers/local/sherpa/silero-vad-provider.js.map +1 -1
- package/dist/src/server/speech/providers/local/sherpa/silero-vad-session.js.map +1 -1
- package/dist/src/server/speech/providers/openai/config.js +5 -24
- package/dist/src/server/speech/providers/openai/config.js.map +1 -1
- package/dist/src/server/speech/providers/openai/realtime-transcription-session.js +6 -3
- package/dist/src/server/speech/providers/openai/realtime-transcription-session.js.map +1 -1
- package/dist/src/server/speech/providers/openai/runtime.js +2 -6
- package/dist/src/server/speech/providers/openai/runtime.js.map +1 -1
- package/dist/src/server/speech/providers/openai/stt.js +1 -3
- package/dist/src/server/speech/providers/openai/stt.js.map +1 -1
- package/dist/src/server/speech/providers/openai/tts.js.map +1 -1
- package/dist/src/server/speech/speech-config-resolver.js +3 -7
- package/dist/src/server/speech/speech-config-resolver.js.map +1 -1
- package/dist/src/server/speech/speech-runtime.js.map +1 -1
- package/dist/src/server/utils/diff-highlighter.js +49 -36
- package/dist/src/server/utils/diff-highlighter.js.map +1 -1
- package/dist/src/server/voice/fixed-duration-pcm-ring-buffer.js.map +1 -1
- package/dist/src/server/voice/voice-turn-controller.js +1 -3
- package/dist/src/server/voice/voice-turn-controller.js.map +1 -1
- package/dist/src/server/voice-config.js.map +1 -1
- package/dist/src/server/voice-mcp-bridge.js.map +1 -1
- package/dist/src/server/websocket-server.js +20 -22
- package/dist/src/server/websocket-server.js.map +1 -1
- package/dist/src/server/workspace-registry-bootstrap.js +6 -6
- package/dist/src/server/workspace-registry-bootstrap.js.map +1 -1
- package/dist/src/server/workspace-registry-model.js +40 -15
- package/dist/src/server/workspace-registry-model.js.map +1 -1
- package/dist/src/server/workspace-registry.js +16 -13
- package/dist/src/server/workspace-registry.js.map +1 -1
- package/dist/src/server/worktree-bootstrap.js +17 -6
- package/dist/src/server/worktree-bootstrap.js.map +1 -1
- package/dist/src/shared/agent-attention-notification.js.map +1 -1
- package/dist/src/shared/daemon-endpoints.js +11 -2
- package/dist/src/shared/daemon-endpoints.js.map +1 -1
- package/dist/src/shared/messages.js +330 -302
- package/dist/src/shared/messages.js.map +1 -1
- package/dist/src/shared/terminal-stream-protocol.js +99 -0
- package/dist/src/shared/terminal-stream-protocol.js.map +1 -0
- package/dist/src/shared/tool-call-display.js +6 -3
- package/dist/src/shared/tool-call-display.js.map +1 -1
- package/dist/src/terminal/terminal.js +44 -98
- package/dist/src/terminal/terminal.js.map +1 -1
- package/dist/src/utils/checkout-git.js +111 -120
- package/dist/src/utils/checkout-git.js.map +1 -1
- package/dist/src/utils/directory-suggestions.js +40 -40
- package/dist/src/utils/directory-suggestions.js.map +1 -1
- package/dist/src/utils/project-icon.js +2 -11
- package/dist/src/utils/project-icon.js.map +1 -1
- package/dist/src/utils/worktree.js +22 -19
- package/dist/src/utils/worktree.js.map +1 -1
- package/package.json +3 -11
- package/dist/server/client/daemon-client-terminal-stream-manager.d.ts +0 -43
- package/dist/server/client/daemon-client-terminal-stream-manager.d.ts.map +0 -1
- package/dist/server/client/daemon-client-terminal-stream-manager.js +0 -134
- package/dist/server/client/daemon-client-terminal-stream-manager.js.map +0 -1
- package/dist/server/server/utils/syntax-highlighter.d.ts +0 -10
- package/dist/server/server/utils/syntax-highlighter.d.ts.map +0 -1
- package/dist/server/server/utils/syntax-highlighter.js +0 -145
- package/dist/server/server/utils/syntax-highlighter.js.map +0 -1
- package/dist/server/shared/binary-mux.d.ts +0 -31
- package/dist/server/shared/binary-mux.d.ts.map +0 -1
- package/dist/server/shared/binary-mux.js +0 -114
- package/dist/server/shared/binary-mux.js.map +0 -1
- package/dist/server/shared/terminal-key-input.d.ts +0 -9
- package/dist/server/shared/terminal-key-input.d.ts.map +0 -1
- package/dist/server/shared/terminal-key-input.js +0 -132
- package/dist/server/shared/terminal-key-input.js.map +0 -1
- package/dist/src/server/utils/syntax-highlighter.js +0 -145
- package/dist/src/server/utils/syntax-highlighter.js.map +0 -1
- package/dist/src/shared/binary-mux.js +0 -114
- package/dist/src/shared/binary-mux.js.map +0 -1
|
@@ -6,35 +6,14 @@ import os from "node:os";
|
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { query, } from "@anthropic-ai/claude-agent-sdk";
|
|
8
8
|
import { mapClaudeCanceledToolCall, mapClaudeCompletedToolCall, mapClaudeFailedToolCall, mapClaudeRunningToolCall, } from "./claude/tool-call-mapper.js";
|
|
9
|
-
import {
|
|
9
|
+
import { coerceTaskNotificationHistoryRecordToSystemMessage, mapTaskNotificationSystemRecordToToolCall, mapTaskNotificationUserContentToToolCall, } from "./claude/task-notification-tool-call.js";
|
|
10
10
|
import { buildClaudeModelFamilyAliases, buildClaudeSelectableModelIds, listClaudeCatalogModels, } from "./claude/model-catalog.js";
|
|
11
11
|
import { parsePartialJsonObject } from "./claude/partial-json.js";
|
|
12
|
-
import {
|
|
13
|
-
import { applyProviderEnv
|
|
12
|
+
import { ClaudeSidechainTracker } from "./claude/sidechain-tracker.js";
|
|
13
|
+
import { applyProviderEnv } from "../provider-launch-config.js";
|
|
14
14
|
import { getOrchestratorModeInstructions } from "../orchestrator-instructions.js";
|
|
15
|
-
/*
|
|
16
|
-
* Routing invariant:
|
|
17
|
-
* While a foreground Claude turn is active, identifier-less assistant/stream/result
|
|
18
|
-
* events must stay attached to that foreground run unless we have explicit evidence
|
|
19
|
-
* that a distinct autonomous run has started.
|
|
20
|
-
*
|
|
21
|
-
* We previously allowed task_notification metadata to reserve autonomous ownership,
|
|
22
|
-
* then consumed that reservation on the next unbound chunk. In practice Claude often
|
|
23
|
-
* emits task_notification records and foreground tool-use stream chunks interleaved
|
|
24
|
-
* within the same turn. That let a foreground turn's terminal result get misrouted
|
|
25
|
-
* into an autonomous side run, which stranded the agent in "running" because the
|
|
26
|
-
* foreground stream never received turn_completed.
|
|
27
|
-
*
|
|
28
|
-
* The rule below is intentionally conservative: foreground turns get first claim on
|
|
29
|
-
* same-turn traffic, and autonomous wake reservations are only consumed once no
|
|
30
|
-
* foreground turn is active. This keeps task_notification advisory instead of letting
|
|
31
|
-
* it steal ownership from the active user turn.
|
|
32
|
-
*/
|
|
33
15
|
const fsPromises = promises;
|
|
34
|
-
const CLAUDE_SETTING_SOURCES = [
|
|
35
|
-
"user",
|
|
36
|
-
"project",
|
|
37
|
-
];
|
|
16
|
+
const CLAUDE_SETTING_SOURCES = ["user", "project"];
|
|
38
17
|
function normalizeModelIdCandidate(modelId) {
|
|
39
18
|
if (typeof modelId !== "string") {
|
|
40
19
|
return null;
|
|
@@ -175,6 +154,8 @@ const REWIND_COMMAND = {
|
|
|
175
154
|
argumentHint: "[user_message_uuid]",
|
|
176
155
|
};
|
|
177
156
|
const INTERRUPT_TOOL_USE_PLACEHOLDER = "[Request interrupted by user for tool use]";
|
|
157
|
+
const INTERRUPT_PLACEHOLDER_PATTERN = /^\[Request interrupted by user(?:[^\]]*)\]$/;
|
|
158
|
+
const NO_RESPONSE_REQUESTED_PLACEHOLDER = "No response requested.";
|
|
178
159
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
179
160
|
function resolveClaudeSpawnCommand(spawnOptions, runtimeSettings) {
|
|
180
161
|
const commandConfig = runtimeSettings?.command;
|
|
@@ -203,9 +184,7 @@ function applyRuntimeSettingsToClaudeOptions(options, runtimeSettings) {
|
|
|
203
184
|
// The SDK defaults to spawning "node" via PATH lookup, which fails when
|
|
204
185
|
// running from the managed runtime bundle where node isn't in PATH.
|
|
205
186
|
// Always use process.execPath — the actual node binary running the daemon.
|
|
206
|
-
const command = resolved.command === spawnOptions.command
|
|
207
|
-
? process.execPath
|
|
208
|
-
: resolved.command;
|
|
187
|
+
const command = resolved.command === spawnOptions.command ? process.execPath : resolved.command;
|
|
209
188
|
return spawn(command, resolved.args, {
|
|
210
189
|
cwd: spawnOptions.cwd,
|
|
211
190
|
env: applyProviderEnv(spawnOptions.env, runtimeSettings),
|
|
@@ -228,32 +207,20 @@ function summarizeClaudeOptionsForLog(options) {
|
|
|
228
207
|
const prompt = systemPromptRaw;
|
|
229
208
|
const promptType = typeof prompt.type === "string" ? prompt.type : "custom";
|
|
230
209
|
return {
|
|
231
|
-
mode: promptType === "preset"
|
|
232
|
-
|
|
233
|
-
: "custom",
|
|
234
|
-
preset: typeof prompt.preset === "string" && prompt.preset.length > 0
|
|
235
|
-
? prompt.preset
|
|
236
|
-
: null,
|
|
210
|
+
mode: promptType === "preset" ? "preset" : "custom",
|
|
211
|
+
preset: typeof prompt.preset === "string" && prompt.preset.length > 0 ? prompt.preset : null,
|
|
237
212
|
};
|
|
238
213
|
})();
|
|
239
|
-
const mcpServerNames = options.mcpServers
|
|
240
|
-
? Object.keys(options.mcpServers).sort()
|
|
241
|
-
: [];
|
|
214
|
+
const mcpServerNames = options.mcpServers ? Object.keys(options.mcpServers).sort() : [];
|
|
242
215
|
return {
|
|
243
216
|
cwd: typeof options.cwd === "string" ? options.cwd : null,
|
|
244
|
-
permissionMode: typeof options.permissionMode === "string"
|
|
245
|
-
? options.permissionMode
|
|
246
|
-
: null,
|
|
217
|
+
permissionMode: typeof options.permissionMode === "string" ? options.permissionMode : null,
|
|
247
218
|
model: typeof options.model === "string" ? options.model : null,
|
|
248
219
|
includePartialMessages: options.includePartialMessages === true,
|
|
249
|
-
settingSources: Array.isArray(options.settingSources)
|
|
250
|
-
? options.settingSources
|
|
251
|
-
: [],
|
|
220
|
+
settingSources: Array.isArray(options.settingSources) ? options.settingSources : [],
|
|
252
221
|
enableFileCheckpointing: options.enableFileCheckpointing === true,
|
|
253
222
|
hasResume: typeof options.resume === "string" && options.resume.length > 0,
|
|
254
|
-
maxThinkingTokens: typeof options.maxThinkingTokens === "number"
|
|
255
|
-
? options.maxThinkingTokens
|
|
256
|
-
: null,
|
|
223
|
+
maxThinkingTokens: typeof options.maxThinkingTokens === "number" ? options.maxThinkingTokens : null,
|
|
257
224
|
hasEnv: !!options.env,
|
|
258
225
|
envKeyCount: Object.keys(options.env ?? {}).length,
|
|
259
226
|
hasMcpServers: mcpServerNames.length > 0,
|
|
@@ -338,10 +305,59 @@ function coerceToolResultContentToString(content) {
|
|
|
338
305
|
}
|
|
339
306
|
return deterministicStringify(content);
|
|
340
307
|
}
|
|
308
|
+
function normalizeClaudeTranscriptText(value) {
|
|
309
|
+
if (typeof value !== "string") {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
const normalized = value.trim();
|
|
313
|
+
return normalized.length > 0 ? normalized : null;
|
|
314
|
+
}
|
|
315
|
+
function isClaudeInterruptPlaceholderText(value) {
|
|
316
|
+
const normalized = normalizeClaudeTranscriptText(value);
|
|
317
|
+
return normalized !== null && INTERRUPT_PLACEHOLDER_PATTERN.test(normalized);
|
|
318
|
+
}
|
|
319
|
+
function isClaudeNoResponsePlaceholderText(value) {
|
|
320
|
+
return normalizeClaudeTranscriptText(value) === NO_RESPONSE_REQUESTED_PLACEHOLDER;
|
|
321
|
+
}
|
|
322
|
+
function isClaudeTranscriptNoiseText(value) {
|
|
323
|
+
return isClaudeInterruptPlaceholderText(value) || isClaudeNoResponsePlaceholderText(value);
|
|
324
|
+
}
|
|
325
|
+
function collectClaudeTextContentParts(content) {
|
|
326
|
+
if (typeof content === "string") {
|
|
327
|
+
const normalized = normalizeClaudeTranscriptText(content);
|
|
328
|
+
return normalized ? [normalized] : [];
|
|
329
|
+
}
|
|
330
|
+
if (!Array.isArray(content)) {
|
|
331
|
+
return [];
|
|
332
|
+
}
|
|
333
|
+
const parts = [];
|
|
334
|
+
for (const block of content) {
|
|
335
|
+
if (!block || typeof block !== "object") {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
const text = normalizeClaudeTranscriptText(block.text);
|
|
339
|
+
if (text) {
|
|
340
|
+
parts.push(text);
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
const input = normalizeClaudeTranscriptText(block.input);
|
|
344
|
+
if (input) {
|
|
345
|
+
parts.push(input);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return parts;
|
|
349
|
+
}
|
|
350
|
+
function isClaudeTranscriptNoiseContent(content) {
|
|
351
|
+
const parts = collectClaudeTextContentParts(content);
|
|
352
|
+
return parts.length > 0 && parts.every((part) => isClaudeTranscriptNoiseText(part));
|
|
353
|
+
}
|
|
341
354
|
export function extractUserMessageText(content) {
|
|
342
355
|
if (typeof content === "string") {
|
|
343
356
|
const normalized = content.trim();
|
|
344
|
-
|
|
357
|
+
if (!normalized || isClaudeTranscriptNoiseText(normalized)) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
return normalized;
|
|
345
361
|
}
|
|
346
362
|
if (!Array.isArray(content)) {
|
|
347
363
|
return null;
|
|
@@ -353,12 +369,18 @@ export function extractUserMessageText(content) {
|
|
|
353
369
|
}
|
|
354
370
|
const text = typeof block.text === "string" ? block.text : undefined;
|
|
355
371
|
if (text && text.trim()) {
|
|
356
|
-
|
|
372
|
+
const trimmed = text.trim();
|
|
373
|
+
if (!isClaudeTranscriptNoiseText(trimmed)) {
|
|
374
|
+
parts.push(trimmed);
|
|
375
|
+
}
|
|
357
376
|
continue;
|
|
358
377
|
}
|
|
359
378
|
const input = typeof block.input === "string" ? block.input : undefined;
|
|
360
379
|
if (input && input.trim()) {
|
|
361
|
-
|
|
380
|
+
const trimmed = input.trim();
|
|
381
|
+
if (!isClaudeTranscriptNoiseText(trimmed)) {
|
|
382
|
+
parts.push(trimmed);
|
|
383
|
+
}
|
|
362
384
|
}
|
|
363
385
|
}
|
|
364
386
|
if (parts.length === 0) {
|
|
@@ -367,8 +389,6 @@ export function extractUserMessageText(content) {
|
|
|
367
389
|
const combined = parts.join("\n\n").trim();
|
|
368
390
|
return combined.length > 0 ? combined : null;
|
|
369
391
|
}
|
|
370
|
-
const MAX_SUB_AGENT_LOG_ENTRIES = 200;
|
|
371
|
-
const MAX_SUB_AGENT_SUMMARY_CHARS = 160;
|
|
372
392
|
function isMetadata(value) {
|
|
373
393
|
return typeof value === "object" && value !== null;
|
|
374
394
|
}
|
|
@@ -508,179 +528,10 @@ function resolvePermissionKind(toolName, input) {
|
|
|
508
528
|
}
|
|
509
529
|
return "tool";
|
|
510
530
|
}
|
|
511
|
-
const ACTIVE_RUN_STATES = new Set([
|
|
512
|
-
"queued",
|
|
513
|
-
"awaiting_response",
|
|
514
|
-
"streaming",
|
|
515
|
-
"finalizing",
|
|
516
|
-
]);
|
|
517
|
-
class RunTracker {
|
|
518
|
-
constructor() {
|
|
519
|
-
this.runs = new Map();
|
|
520
|
-
this.runByTaskId = new Map();
|
|
521
|
-
this.runByParentMessageId = new Map();
|
|
522
|
-
this.runByMessageId = new Map();
|
|
523
|
-
}
|
|
524
|
-
createRun(input) {
|
|
525
|
-
const run = {
|
|
526
|
-
id: input.id,
|
|
527
|
-
owner: input.owner,
|
|
528
|
-
queue: input.queue,
|
|
529
|
-
state: "queued",
|
|
530
|
-
promptReplaySeen: input.promptReplaySeen ?? true,
|
|
531
|
-
taskIds: new Set(),
|
|
532
|
-
parentMessageIds: new Set(),
|
|
533
|
-
messageIds: new Set(),
|
|
534
|
-
};
|
|
535
|
-
this.runs.set(run.id, run);
|
|
536
|
-
return run;
|
|
537
|
-
}
|
|
538
|
-
getRun(runId) {
|
|
539
|
-
return this.runs.get(runId) ?? null;
|
|
540
|
-
}
|
|
541
|
-
getForegroundRun() {
|
|
542
|
-
for (const run of this.runs.values()) {
|
|
543
|
-
if (run.owner === "foreground" && this.isActive(run.state)) {
|
|
544
|
-
return run;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
return null;
|
|
548
|
-
}
|
|
549
|
-
listActiveRuns(owner) {
|
|
550
|
-
const runs = [];
|
|
551
|
-
for (const run of this.runs.values()) {
|
|
552
|
-
if (!this.isActive(run.state)) {
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
if (owner && run.owner !== owner) {
|
|
556
|
-
continue;
|
|
557
|
-
}
|
|
558
|
-
runs.push(run);
|
|
559
|
-
}
|
|
560
|
-
return runs;
|
|
561
|
-
}
|
|
562
|
-
hasActiveRuns(owner) {
|
|
563
|
-
for (const run of this.runs.values()) {
|
|
564
|
-
if (!this.isActive(run.state)) {
|
|
565
|
-
continue;
|
|
566
|
-
}
|
|
567
|
-
if (owner && run.owner !== owner) {
|
|
568
|
-
continue;
|
|
569
|
-
}
|
|
570
|
-
return true;
|
|
571
|
-
}
|
|
572
|
-
return false;
|
|
573
|
-
}
|
|
574
|
-
getLatestActiveRun(owner) {
|
|
575
|
-
let latest = null;
|
|
576
|
-
for (const run of this.runs.values()) {
|
|
577
|
-
if (!this.isActive(run.state)) {
|
|
578
|
-
continue;
|
|
579
|
-
}
|
|
580
|
-
if (owner && run.owner !== owner) {
|
|
581
|
-
continue;
|
|
582
|
-
}
|
|
583
|
-
latest = run;
|
|
584
|
-
}
|
|
585
|
-
return latest;
|
|
586
|
-
}
|
|
587
|
-
isRunActive(run) {
|
|
588
|
-
if (!run) {
|
|
589
|
-
return false;
|
|
590
|
-
}
|
|
591
|
-
return this.isActive(run.state);
|
|
592
|
-
}
|
|
593
|
-
resolveByIdentifiers(identifiers) {
|
|
594
|
-
if (identifiers.taskId) {
|
|
595
|
-
const run = this.resolveMappedRun(this.runByTaskId, identifiers.taskId);
|
|
596
|
-
if (run) {
|
|
597
|
-
return { run, reason: "task_id" };
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
if (identifiers.parentMessageId) {
|
|
601
|
-
const run = this.resolveMappedRun(this.runByParentMessageId, identifiers.parentMessageId);
|
|
602
|
-
if (run) {
|
|
603
|
-
return { run, reason: "parent_message_id" };
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
if (identifiers.messageId) {
|
|
607
|
-
const run = this.resolveMappedRun(this.runByMessageId, identifiers.messageId);
|
|
608
|
-
if (run) {
|
|
609
|
-
return { run, reason: "message_id" };
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
return { run: null, reason: "metadata" };
|
|
613
|
-
}
|
|
614
|
-
bindIdentifiers(run, identifiers) {
|
|
615
|
-
if (identifiers.taskId) {
|
|
616
|
-
run.taskIds.add(identifiers.taskId);
|
|
617
|
-
this.runByTaskId.set(identifiers.taskId, run.id);
|
|
618
|
-
}
|
|
619
|
-
if (identifiers.parentMessageId) {
|
|
620
|
-
run.parentMessageIds.add(identifiers.parentMessageId);
|
|
621
|
-
this.runByParentMessageId.set(identifiers.parentMessageId, run.id);
|
|
622
|
-
}
|
|
623
|
-
if (identifiers.messageId) {
|
|
624
|
-
run.messageIds.add(identifiers.messageId);
|
|
625
|
-
this.runByMessageId.set(identifiers.messageId, run.id);
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
transition(run, nextState) {
|
|
629
|
-
run.state = nextState;
|
|
630
|
-
}
|
|
631
|
-
complete(run, terminalState) {
|
|
632
|
-
run.state = terminalState;
|
|
633
|
-
this.clearRunIndex(run);
|
|
634
|
-
}
|
|
635
|
-
deriveLifecycle(pendingPermissionCount) {
|
|
636
|
-
for (const run of this.runs.values()) {
|
|
637
|
-
if (this.isActive(run.state)) {
|
|
638
|
-
return "running";
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
if (pendingPermissionCount > 0) {
|
|
642
|
-
return "permission";
|
|
643
|
-
}
|
|
644
|
-
for (const run of this.runs.values()) {
|
|
645
|
-
if (run.state === "error") {
|
|
646
|
-
return "error";
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
return "idle";
|
|
650
|
-
}
|
|
651
|
-
resolveMappedRun(mapping, identifier) {
|
|
652
|
-
const runId = mapping.get(identifier);
|
|
653
|
-
if (!runId) {
|
|
654
|
-
return null;
|
|
655
|
-
}
|
|
656
|
-
const run = this.runs.get(runId);
|
|
657
|
-
if (!run || !this.isActive(run.state)) {
|
|
658
|
-
mapping.delete(identifier);
|
|
659
|
-
return null;
|
|
660
|
-
}
|
|
661
|
-
return run;
|
|
662
|
-
}
|
|
663
|
-
clearRunIndex(run) {
|
|
664
|
-
for (const taskId of run.taskIds) {
|
|
665
|
-
this.runByTaskId.delete(taskId);
|
|
666
|
-
}
|
|
667
|
-
for (const parentMessageId of run.parentMessageIds) {
|
|
668
|
-
this.runByParentMessageId.delete(parentMessageId);
|
|
669
|
-
}
|
|
670
|
-
for (const messageId of run.messageIds) {
|
|
671
|
-
this.runByMessageId.delete(messageId);
|
|
672
|
-
}
|
|
673
|
-
run.taskIds.clear();
|
|
674
|
-
run.parentMessageIds.clear();
|
|
675
|
-
run.messageIds.clear();
|
|
676
|
-
}
|
|
677
|
-
isActive(state) {
|
|
678
|
-
return ACTIVE_RUN_STATES.has(state);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
531
|
class TimelineAssembler {
|
|
682
532
|
constructor() {
|
|
683
533
|
this.messages = new Map();
|
|
534
|
+
this.finalizedMessageIds = new Set();
|
|
684
535
|
this.activeMessageByRun = new Map();
|
|
685
536
|
this.syntheticMessageCounter = 0;
|
|
686
537
|
}
|
|
@@ -700,6 +551,9 @@ class TimelineAssembler {
|
|
|
700
551
|
if (!messageId) {
|
|
701
552
|
return [];
|
|
702
553
|
}
|
|
554
|
+
if (this.finalizedMessageIds.has(messageId)) {
|
|
555
|
+
return [];
|
|
556
|
+
}
|
|
703
557
|
const state = this.ensureMessageState(messageId, runId);
|
|
704
558
|
const fragments = this.extractFragments(message.message?.content);
|
|
705
559
|
return this.applyAbsoluteFragments(state, fragments);
|
|
@@ -799,13 +653,16 @@ class TimelineAssembler {
|
|
|
799
653
|
if (runId && this.activeMessageByRun.get(runId) === messageId) {
|
|
800
654
|
this.activeMessageByRun.delete(runId);
|
|
801
655
|
}
|
|
656
|
+
this.finalizedMessageIds.add(messageId);
|
|
657
|
+
this.messages.delete(messageId);
|
|
802
658
|
return items;
|
|
803
659
|
}
|
|
804
660
|
emitNewContent(state) {
|
|
805
661
|
const items = [];
|
|
806
662
|
const nextAssistantText = state.assistantText.slice(state.emittedAssistantLength);
|
|
807
663
|
if (nextAssistantText.length > 0 &&
|
|
808
|
-
nextAssistantText !== INTERRUPT_TOOL_USE_PLACEHOLDER
|
|
664
|
+
nextAssistantText !== INTERRUPT_TOOL_USE_PLACEHOLDER &&
|
|
665
|
+
!isClaudeTranscriptNoiseText(nextAssistantText)) {
|
|
809
666
|
state.emittedAssistantLength = state.assistantText.length;
|
|
810
667
|
items.push({ type: "assistant_message", text: nextAssistantText });
|
|
811
668
|
}
|
|
@@ -886,28 +743,12 @@ class TimelineAssembler {
|
|
|
886
743
|
}
|
|
887
744
|
readMessageIdFromAssistantMessage(message) {
|
|
888
745
|
const candidate = message;
|
|
889
|
-
return readTrimmedString(candidate.message_id) ??
|
|
890
|
-
readTrimmedString(candidate.message?.id) ??
|
|
891
|
-
null;
|
|
746
|
+
return (readTrimmedString(candidate.message_id) ?? readTrimmedString(candidate.message?.id) ?? null);
|
|
892
747
|
}
|
|
893
748
|
readMessageIdFromStreamEvent(event) {
|
|
894
749
|
const message = event.message;
|
|
895
|
-
return
|
|
896
|
-
readTrimmedString(message?.id) ??
|
|
897
|
-
null);
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
function isMetadataOnlySdkMessage(message) {
|
|
901
|
-
if (message.type === "system") {
|
|
902
|
-
return true;
|
|
903
|
-
}
|
|
904
|
-
if (message.type !== "user") {
|
|
905
|
-
return false;
|
|
906
|
-
}
|
|
907
|
-
if (isSyntheticUserEntry(message)) {
|
|
908
|
-
return true;
|
|
750
|
+
return readTrimmedString(event.message_id) ?? readTrimmedString(message?.id) ?? null;
|
|
909
751
|
}
|
|
910
|
-
return isTaskNotificationUserContent(message.message?.content);
|
|
911
752
|
}
|
|
912
753
|
function isSyntheticUserEntry(entry) {
|
|
913
754
|
if (!entry || typeof entry !== "object") {
|
|
@@ -1025,29 +866,30 @@ class ClaudeAgentSession {
|
|
|
1025
866
|
this.toolUseInputBuffers = new Map();
|
|
1026
867
|
this.pendingPermissions = new Map();
|
|
1027
868
|
this.activeForegroundTurn = null;
|
|
869
|
+
this.autonomousTurn = null;
|
|
1028
870
|
this.liveEventQueue = new Pushable();
|
|
1029
|
-
this.runTracker = new RunTracker();
|
|
1030
871
|
this.timelineAssembler = new TimelineAssembler();
|
|
872
|
+
this.sidechainTracker = new ClaudeSidechainTracker({
|
|
873
|
+
getToolInput: (toolUseId) => this.toolUseCache.get(toolUseId)?.input ?? null,
|
|
874
|
+
});
|
|
1031
875
|
this.persistedHistory = [];
|
|
1032
876
|
this.historyPending = false;
|
|
877
|
+
this.historyOffsetSessionId = null;
|
|
878
|
+
this.historyReadOffsetBytes = 0;
|
|
879
|
+
this.historyLineFragment = "";
|
|
1033
880
|
this.turnState = "idle";
|
|
1034
|
-
this.
|
|
1035
|
-
this.pendingAutonomousWakeReservations = 0;
|
|
1036
|
-
this.nextRunOrdinal = 1;
|
|
881
|
+
this.nextTurnOrdinal = 1;
|
|
1037
882
|
this.cancelCurrentTurn = null;
|
|
1038
|
-
this.pendingInterruptPromise = null;
|
|
1039
883
|
this.activeTurnPromise = null;
|
|
1040
884
|
this.cachedRuntimeInfo = null;
|
|
1041
885
|
this.lastOptionsModel = null;
|
|
1042
886
|
this.selectableModelIds = buildClaudeSelectableModelIds();
|
|
1043
887
|
this.selectableModelFamilyAliases = buildClaudeModelFamilyAliases();
|
|
1044
|
-
this.activeSidechains = new Map();
|
|
1045
888
|
this.compacting = false;
|
|
1046
889
|
this.queryPumpPromise = null;
|
|
1047
890
|
this.queryRestartNeeded = false;
|
|
891
|
+
this.pendingInterruptAbort = false;
|
|
1048
892
|
this.userMessageIds = [];
|
|
1049
|
-
this.localUserMessageIds = new Set();
|
|
1050
|
-
this.suppressLocalReplayActivity = false;
|
|
1051
893
|
this.recentStderr = "";
|
|
1052
894
|
this.closed = false;
|
|
1053
895
|
this.handlePermissionRequest = async (toolName, input, options) => {
|
|
@@ -1202,34 +1044,25 @@ class ClaudeAgentSession {
|
|
|
1202
1044
|
if (this.cancelCurrentTurn) {
|
|
1203
1045
|
this.cancelCurrentTurn();
|
|
1204
1046
|
}
|
|
1205
|
-
this.suppressLocalReplayActivity = false;
|
|
1206
|
-
this.pendingAutonomousWakeReservations = 0;
|
|
1207
1047
|
const slashCommand = this.resolveSlashCommandInvocation(prompt);
|
|
1208
1048
|
if (slashCommand?.commandName === REWIND_COMMAND_NAME) {
|
|
1209
1049
|
yield* this.streamRewindCommand(slashCommand);
|
|
1210
1050
|
return;
|
|
1211
1051
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
this.runTracker.hasActiveRuns("autonomous")) {
|
|
1215
|
-
await this.transitionAutonomousToForeground();
|
|
1052
|
+
if (this.autonomousTurn) {
|
|
1053
|
+
this.completeAutonomousTurn();
|
|
1216
1054
|
}
|
|
1217
1055
|
const sdkMessage = this.toSdkUserMessage(prompt);
|
|
1218
1056
|
const queue = new Pushable();
|
|
1219
|
-
const run = this.createRun("foreground", queue);
|
|
1220
|
-
this.runTracker.bindIdentifiers(run, {
|
|
1221
|
-
taskId: null,
|
|
1222
|
-
parentMessageId: null,
|
|
1223
|
-
messageId: typeof sdkMessage.uuid === "string" ? sdkMessage.uuid : null,
|
|
1224
|
-
});
|
|
1225
1057
|
const foregroundTurn = {
|
|
1226
|
-
|
|
1058
|
+
id: this.createTurnId("foreground"),
|
|
1227
1059
|
queue,
|
|
1060
|
+
hasVisibleActivity: false,
|
|
1228
1061
|
};
|
|
1229
1062
|
this.activeForegroundTurn = foregroundTurn;
|
|
1230
|
-
this.preReplayMetadataSeen = false;
|
|
1231
1063
|
this.transitionTurnState("foreground", "foreground stream started");
|
|
1232
1064
|
this.clearRecentStderr();
|
|
1065
|
+
queue.push({ type: "turn_started", provider: "claude" });
|
|
1233
1066
|
let finishedNaturally = false;
|
|
1234
1067
|
let cancelIssued = false;
|
|
1235
1068
|
let queueDrainedWithoutTerminal = false;
|
|
@@ -1240,19 +1073,16 @@ class ClaudeAgentSession {
|
|
|
1240
1073
|
return;
|
|
1241
1074
|
}
|
|
1242
1075
|
cancelIssued = true;
|
|
1243
|
-
if (this.activeForegroundTurn?.runId === run.id) {
|
|
1244
|
-
this.activeForegroundTurn = null;
|
|
1245
|
-
}
|
|
1246
1076
|
if (this.cancelCurrentTurn === requestCancel) {
|
|
1247
1077
|
this.cancelCurrentTurn = null;
|
|
1248
1078
|
}
|
|
1249
1079
|
this.rejectAllPendingPermissions(new Error("Permission request aborted"));
|
|
1250
|
-
this.
|
|
1080
|
+
this.finishForegroundTurn({
|
|
1251
1081
|
type: "turn_canceled",
|
|
1252
1082
|
provider: "claude",
|
|
1253
1083
|
reason: "Interrupted",
|
|
1254
1084
|
});
|
|
1255
|
-
|
|
1085
|
+
void this.interruptActiveTurn().catch((error) => {
|
|
1256
1086
|
this.logger.warn({ err: error }, "Failed to interrupt during cancel");
|
|
1257
1087
|
});
|
|
1258
1088
|
};
|
|
@@ -1266,7 +1096,7 @@ class ClaudeAgentSession {
|
|
|
1266
1096
|
this.input.push(sdkMessage);
|
|
1267
1097
|
}
|
|
1268
1098
|
catch (error) {
|
|
1269
|
-
this.
|
|
1099
|
+
this.finishForegroundTurn(this.buildTurnFailedEvent(error instanceof Error ? error.message : "Claude stream failed"));
|
|
1270
1100
|
finishedNaturally = true;
|
|
1271
1101
|
}
|
|
1272
1102
|
try {
|
|
@@ -1306,16 +1136,8 @@ class ClaudeAgentSession {
|
|
|
1306
1136
|
this.cancelCurrentTurn();
|
|
1307
1137
|
return;
|
|
1308
1138
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
this.flushPendingToolCalls();
|
|
1312
|
-
for (const run of autonomousRuns) {
|
|
1313
|
-
this.emitRunEvent(run, {
|
|
1314
|
-
type: "turn_canceled",
|
|
1315
|
-
provider: "claude",
|
|
1316
|
-
reason: "Interrupted",
|
|
1317
|
-
});
|
|
1318
|
-
}
|
|
1139
|
+
if (this.autonomousTurn) {
|
|
1140
|
+
this.cancelAutonomousTurn("Interrupted");
|
|
1319
1141
|
}
|
|
1320
1142
|
await this.interruptActiveTurn();
|
|
1321
1143
|
}
|
|
@@ -1464,12 +1286,12 @@ class ClaudeAgentSession {
|
|
|
1464
1286
|
this.cancelCurrentTurn?.();
|
|
1465
1287
|
this.activeForegroundTurn?.queue.end();
|
|
1466
1288
|
this.activeForegroundTurn = null;
|
|
1289
|
+
this.autonomousTurn = null;
|
|
1467
1290
|
this.cancelCurrentTurn = null;
|
|
1468
1291
|
this.turnState = "idle";
|
|
1469
|
-
this.suppressLocalReplayActivity = false;
|
|
1470
|
-
this.pendingAutonomousWakeReservations = 0;
|
|
1471
1292
|
this.liveEventQueue.end();
|
|
1472
1293
|
this.activeTurnPromise = null;
|
|
1294
|
+
this.sidechainTracker.clear();
|
|
1473
1295
|
this.input?.end();
|
|
1474
1296
|
await this.awaitWithTimeout(this.query?.interrupt?.(), "close query interrupt");
|
|
1475
1297
|
await this.awaitWithTimeout(this.query?.return?.(), "close query return");
|
|
@@ -1512,15 +1334,11 @@ class ClaudeAgentSession {
|
|
|
1512
1334
|
}
|
|
1513
1335
|
const withoutPrefix = trimmed.slice(1);
|
|
1514
1336
|
const firstWhitespaceIdx = withoutPrefix.search(/\s/);
|
|
1515
|
-
const commandName = firstWhitespaceIdx === -1
|
|
1516
|
-
? withoutPrefix
|
|
1517
|
-
: withoutPrefix.slice(0, firstWhitespaceIdx);
|
|
1337
|
+
const commandName = firstWhitespaceIdx === -1 ? withoutPrefix : withoutPrefix.slice(0, firstWhitespaceIdx);
|
|
1518
1338
|
if (!commandName || commandName.includes("/")) {
|
|
1519
1339
|
return null;
|
|
1520
1340
|
}
|
|
1521
|
-
const rawArgs = firstWhitespaceIdx === -1
|
|
1522
|
-
? ""
|
|
1523
|
-
: withoutPrefix.slice(firstWhitespaceIdx + 1).trim();
|
|
1341
|
+
const rawArgs = firstWhitespaceIdx === -1 ? "" : withoutPrefix.slice(firstWhitespaceIdx + 1).trim();
|
|
1524
1342
|
return rawArgs.length > 0
|
|
1525
1343
|
? { commandName, args: rawArgs, rawInput: trimmed }
|
|
1526
1344
|
: { commandName, rawInput: trimmed };
|
|
@@ -1552,9 +1370,7 @@ class ClaudeAgentSession {
|
|
|
1552
1370
|
yield {
|
|
1553
1371
|
type: "turn_failed",
|
|
1554
1372
|
provider: "claude",
|
|
1555
|
-
error: error instanceof Error
|
|
1556
|
-
? error.message
|
|
1557
|
-
: "Failed to rewind tracked files",
|
|
1373
|
+
error: error instanceof Error ? error.message : "Failed to rewind tracked files",
|
|
1558
1374
|
};
|
|
1559
1375
|
}
|
|
1560
1376
|
}
|
|
@@ -1592,8 +1408,7 @@ class ClaudeAgentSession {
|
|
|
1592
1408
|
}
|
|
1593
1409
|
return {
|
|
1594
1410
|
messageId: null,
|
|
1595
|
-
error: rewindResult.error ??
|
|
1596
|
-
`No file checkpoint found for message ${candidate}.`,
|
|
1411
|
+
error: rewindResult.error ?? `No file checkpoint found for message ${candidate}.`,
|
|
1597
1412
|
};
|
|
1598
1413
|
}
|
|
1599
1414
|
const candidates = this.getRewindCandidateUserMessageIds();
|
|
@@ -1615,16 +1430,12 @@ class ClaudeAgentSession {
|
|
|
1615
1430
|
}
|
|
1616
1431
|
}
|
|
1617
1432
|
catch (error) {
|
|
1618
|
-
lastError =
|
|
1619
|
-
error instanceof Error
|
|
1620
|
-
? error.message
|
|
1621
|
-
: "Failed to rewind tracked files.";
|
|
1433
|
+
lastError = error instanceof Error ? error.message : "Failed to rewind tracked files.";
|
|
1622
1434
|
}
|
|
1623
1435
|
}
|
|
1624
1436
|
return {
|
|
1625
1437
|
messageId: null,
|
|
1626
|
-
error: lastError ??
|
|
1627
|
-
"No rewind checkpoints are currently available for this session.",
|
|
1438
|
+
error: lastError ?? "No rewind checkpoints are currently available for this session.",
|
|
1628
1439
|
};
|
|
1629
1440
|
}
|
|
1630
1441
|
async rewindFilesOnce(messageId) {
|
|
@@ -1648,9 +1459,7 @@ class ClaudeAgentSession {
|
|
|
1648
1459
|
getRewindCandidateUserMessageIds() {
|
|
1649
1460
|
const candidates = [];
|
|
1650
1461
|
const pushUnique = (value) => {
|
|
1651
|
-
if (typeof value === "string" &&
|
|
1652
|
-
value.length > 0 &&
|
|
1653
|
-
!candidates.includes(value)) {
|
|
1462
|
+
if (typeof value === "string" && value.length > 0 && !candidates.includes(value)) {
|
|
1654
1463
|
candidates.push(value);
|
|
1655
1464
|
}
|
|
1656
1465
|
};
|
|
@@ -1719,7 +1528,9 @@ class ClaudeAgentSession {
|
|
|
1719
1528
|
try {
|
|
1720
1529
|
await this.query.return?.();
|
|
1721
1530
|
}
|
|
1722
|
-
catch {
|
|
1531
|
+
catch {
|
|
1532
|
+
/* ignore */
|
|
1533
|
+
}
|
|
1723
1534
|
this.query = null;
|
|
1724
1535
|
this.input = null;
|
|
1725
1536
|
this.queryRestartNeeded = false;
|
|
@@ -1851,7 +1662,6 @@ class ClaudeAgentSession {
|
|
|
1851
1662
|
}
|
|
1852
1663
|
const messageId = randomUUID();
|
|
1853
1664
|
this.rememberUserMessageId(messageId);
|
|
1854
|
-
this.localUserMessageIds.add(messageId);
|
|
1855
1665
|
return {
|
|
1856
1666
|
type: "user",
|
|
1857
1667
|
message: {
|
|
@@ -1863,24 +1673,6 @@ class ClaudeAgentSession {
|
|
|
1863
1673
|
session_id: this.claudeSessionId ?? "",
|
|
1864
1674
|
};
|
|
1865
1675
|
}
|
|
1866
|
-
async awaitPendingInterruptPromise() {
|
|
1867
|
-
if (!this.pendingInterruptPromise) {
|
|
1868
|
-
return;
|
|
1869
|
-
}
|
|
1870
|
-
await this.pendingInterruptPromise;
|
|
1871
|
-
this.pendingInterruptPromise = null;
|
|
1872
|
-
}
|
|
1873
|
-
createRun(owner, queue) {
|
|
1874
|
-
const runId = `${owner}-run-${this.nextRunOrdinal++}`;
|
|
1875
|
-
const run = this.runTracker.createRun({
|
|
1876
|
-
id: runId,
|
|
1877
|
-
owner,
|
|
1878
|
-
queue,
|
|
1879
|
-
promptReplaySeen: owner === "autonomous",
|
|
1880
|
-
});
|
|
1881
|
-
this.logger.debug({ runId, owner, state: run.state }, "Created Claude run");
|
|
1882
|
-
return run;
|
|
1883
|
-
}
|
|
1884
1676
|
transitionTurnState(next, reason) {
|
|
1885
1677
|
if (this.turnState === next) {
|
|
1886
1678
|
return;
|
|
@@ -1888,20 +1680,17 @@ class ClaudeAgentSession {
|
|
|
1888
1680
|
this.logger.debug({ from: this.turnState, to: next, reason }, "Claude turn state transition");
|
|
1889
1681
|
this.turnState = next;
|
|
1890
1682
|
}
|
|
1891
|
-
|
|
1892
|
-
if (this.
|
|
1683
|
+
syncTurnState(reason) {
|
|
1684
|
+
if (this.activeForegroundTurn) {
|
|
1893
1685
|
this.transitionTurnState("foreground", reason);
|
|
1894
1686
|
return;
|
|
1895
1687
|
}
|
|
1896
|
-
if (this.
|
|
1688
|
+
if (this.autonomousTurn) {
|
|
1897
1689
|
this.transitionTurnState("autonomous", reason);
|
|
1898
1690
|
return;
|
|
1899
1691
|
}
|
|
1900
1692
|
this.transitionTurnState("idle", reason);
|
|
1901
1693
|
}
|
|
1902
|
-
failRun(run, errorMessage) {
|
|
1903
|
-
this.emitRunEvent(run, this.buildTurnFailedEvent(errorMessage));
|
|
1904
|
-
}
|
|
1905
1694
|
buildTurnFailedEvent(errorMessage) {
|
|
1906
1695
|
const normalized = errorMessage.trim() || "Claude run failed";
|
|
1907
1696
|
const exitCodeMatch = normalized.match(/\bcode\s+(\d+)\b/i);
|
|
@@ -1927,274 +1716,106 @@ class ClaudeAgentSession {
|
|
|
1927
1716
|
this.recentStderr = "";
|
|
1928
1717
|
}
|
|
1929
1718
|
getRecentStderrDiagnostic() {
|
|
1930
|
-
|
|
1931
|
-
return text.length > 0 ? text : undefined;
|
|
1719
|
+
return this.recentStderr.trim() || undefined;
|
|
1932
1720
|
}
|
|
1933
|
-
|
|
1934
|
-
this.
|
|
1935
|
-
this.emitRunEvent(run, event);
|
|
1721
|
+
createTurnId(owner) {
|
|
1722
|
+
return `${owner}-turn-${this.nextTurnOrdinal++}`;
|
|
1936
1723
|
}
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
event.type === "turn_completed" ||
|
|
1724
|
+
isTerminalTurnEvent(event) {
|
|
1725
|
+
return (event.type === "turn_completed" ||
|
|
1940
1726
|
event.type === "turn_failed" ||
|
|
1941
|
-
event.type === "turn_canceled")
|
|
1942
|
-
this.logger.trace({
|
|
1943
|
-
runId: run.id,
|
|
1944
|
-
owner: run.owner,
|
|
1945
|
-
runState: run.state,
|
|
1946
|
-
eventType: event.type,
|
|
1947
|
-
routedTo: run.owner === "foreground" && run.queue ? "foreground_queue" : "live_queue",
|
|
1948
|
-
}, "Claude run event emitted");
|
|
1949
|
-
}
|
|
1950
|
-
if (run.owner === "foreground" && run.queue) {
|
|
1951
|
-
run.queue.push(event);
|
|
1952
|
-
if (event.type === "turn_completed" ||
|
|
1953
|
-
event.type === "turn_failed" ||
|
|
1954
|
-
event.type === "turn_canceled") {
|
|
1955
|
-
run.queue.end();
|
|
1956
|
-
}
|
|
1957
|
-
}
|
|
1958
|
-
else {
|
|
1959
|
-
this.liveEventQueue.push(event);
|
|
1960
|
-
}
|
|
1961
|
-
this.handleRunTerminalEvent(run, event);
|
|
1727
|
+
event.type === "turn_canceled");
|
|
1962
1728
|
}
|
|
1963
|
-
|
|
1964
|
-
if (
|
|
1965
|
-
|
|
1966
|
-
}
|
|
1967
|
-
else if (event.type === "turn_failed") {
|
|
1968
|
-
this.runTracker.complete(run, "error");
|
|
1969
|
-
}
|
|
1970
|
-
else if (event.type === "turn_canceled") {
|
|
1971
|
-
this.runTracker.complete(run, "interrupted");
|
|
1972
|
-
}
|
|
1973
|
-
else {
|
|
1974
|
-
return;
|
|
1729
|
+
shouldRecoverInterruptedQueryAbort(error, consecutiveRecoveries) {
|
|
1730
|
+
if (consecutiveRecoveries >= 3) {
|
|
1731
|
+
return false;
|
|
1975
1732
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1733
|
+
const message = typeof error === "string"
|
|
1734
|
+
? error
|
|
1735
|
+
: error instanceof Error
|
|
1736
|
+
? `${error.message}\n${error.stack ?? ""}`
|
|
1737
|
+
: JSON.stringify(error);
|
|
1738
|
+
return message.toLowerCase().includes("request was aborted");
|
|
1739
|
+
}
|
|
1740
|
+
finishForegroundTurn(event) {
|
|
1741
|
+
if (event.type === "turn_failed" || event.type === "turn_canceled") {
|
|
1742
|
+
this.flushPendingToolCalls();
|
|
1979
1743
|
}
|
|
1980
|
-
this.
|
|
1981
|
-
runId: run.id,
|
|
1982
|
-
owner: run.owner,
|
|
1983
|
-
eventType: event.type,
|
|
1984
|
-
runState: run.state,
|
|
1985
|
-
hasActiveForegroundTurn: Boolean(this.activeForegroundTurn),
|
|
1986
|
-
}, "Claude run terminal event handled");
|
|
1987
|
-
this.transitionTurnStateFromActiveRuns(`run ${run.id} terminal`);
|
|
1744
|
+
this.dispatchForegroundEvents([event]);
|
|
1988
1745
|
}
|
|
1989
|
-
|
|
1990
|
-
const
|
|
1991
|
-
if (
|
|
1992
|
-
this.
|
|
1746
|
+
dispatchForegroundEvents(events) {
|
|
1747
|
+
const foregroundTurn = this.activeForegroundTurn;
|
|
1748
|
+
if (!foregroundTurn) {
|
|
1749
|
+
this.dispatchLiveEvents(events);
|
|
1993
1750
|
return;
|
|
1994
1751
|
}
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
this.
|
|
1999
|
-
type: "turn_canceled",
|
|
2000
|
-
provider: "claude",
|
|
2001
|
-
reason: "Interrupted by foreground prompt",
|
|
2002
|
-
});
|
|
2003
|
-
}
|
|
2004
|
-
this.pendingInterruptPromise = this.interruptActiveTurn().catch((error) => {
|
|
2005
|
-
this.logger.warn({ err: error }, "Failed to interrupt autonomous run during foreground transition");
|
|
2006
|
-
});
|
|
2007
|
-
await this.awaitPendingInterruptPromise();
|
|
2008
|
-
this.transitionTurnStateFromActiveRuns("autonomous interrupted for foreground");
|
|
2009
|
-
}
|
|
2010
|
-
routeMessage(normalized) {
|
|
2011
|
-
if (normalized.metadataOnly) {
|
|
2012
|
-
if ((normalized.message.type === "user" &&
|
|
2013
|
-
isTaskNotificationUserContent(normalized.message.message?.content)) ||
|
|
2014
|
-
(normalized.message.type === "system" &&
|
|
2015
|
-
normalized.message.subtype === "task_notification")) {
|
|
2016
|
-
this.reserveAutonomousWake("task_notification");
|
|
2017
|
-
}
|
|
2018
|
-
this.notePreReplayMetadata(normalized.message);
|
|
2019
|
-
return { run: null, reason: "metadata" };
|
|
2020
|
-
}
|
|
2021
|
-
const hasIdentifiers = Boolean(normalized.identifiers.taskId ||
|
|
2022
|
-
normalized.identifiers.parentMessageId ||
|
|
2023
|
-
normalized.identifiers.messageId);
|
|
2024
|
-
const byIdentifiers = this.runTracker.resolveByIdentifiers(normalized.identifiers);
|
|
2025
|
-
if (byIdentifiers.run) {
|
|
2026
|
-
return byIdentifiers;
|
|
2027
|
-
}
|
|
2028
|
-
const foregroundRun = this.activeForegroundTurn
|
|
2029
|
-
? this.runTracker.getRun(this.activeForegroundTurn.runId)
|
|
2030
|
-
: null;
|
|
2031
|
-
// A previously unseen task_id during foreground ownership is deterministic
|
|
2032
|
-
// evidence of a distinct autonomous wake/run, not foreground response text.
|
|
2033
|
-
if (this.turnState === "foreground" &&
|
|
2034
|
-
foregroundRun &&
|
|
2035
|
-
normalized.identifiers.taskId) {
|
|
2036
|
-
const incomingTaskId = normalized.identifiers.taskId;
|
|
2037
|
-
// Foreground must claim its first task_id; otherwise early foreground
|
|
2038
|
-
// result events can be misrouted to autonomous fallback runs.
|
|
2039
|
-
if (foregroundRun.taskIds.size === 0) {
|
|
2040
|
-
if (foregroundRun.state !== "finalizing") {
|
|
2041
|
-
return { run: foregroundRun, reason: "foreground" };
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2044
|
-
else if (foregroundRun.taskIds.has(incomingTaskId)) {
|
|
2045
|
-
return { run: foregroundRun, reason: "foreground" };
|
|
2046
|
-
}
|
|
2047
|
-
const autonomousRun = this.createRun("autonomous", null);
|
|
2048
|
-
this.emitRunEvent(autonomousRun, { type: "turn_started", provider: "claude" });
|
|
2049
|
-
return { run: autonomousRun, reason: "task_id_new" };
|
|
2050
|
-
}
|
|
2051
|
-
if (this.turnState === "foreground" &&
|
|
2052
|
-
foregroundRun &&
|
|
2053
|
-
this.shouldPreferForegroundRun({
|
|
2054
|
-
run: foregroundRun,
|
|
2055
|
-
message: normalized.message,
|
|
2056
|
-
})) {
|
|
2057
|
-
return { run: foregroundRun, reason: "foreground" };
|
|
2058
|
-
}
|
|
2059
|
-
if (this.pendingAutonomousWakeReservations > 0 &&
|
|
2060
|
-
!normalized.identifiers.taskId &&
|
|
2061
|
-
!normalized.identifiers.parentMessageId &&
|
|
2062
|
-
!normalized.identifiers.messageId) {
|
|
2063
|
-
const reservedAutonomousRun = this.claimOrCreateAutonomousRun("reservation_unbound");
|
|
2064
|
-
return {
|
|
2065
|
-
run: reservedAutonomousRun,
|
|
2066
|
-
reason: "reserved_autonomous",
|
|
2067
|
-
};
|
|
2068
|
-
}
|
|
2069
|
-
if (!hasIdentifiers) {
|
|
2070
|
-
const activeAutonomousRun = this.runTracker.getLatestActiveRun("autonomous");
|
|
2071
|
-
if (activeAutonomousRun) {
|
|
2072
|
-
return { run: activeAutonomousRun, reason: "unbound_autonomous" };
|
|
2073
|
-
}
|
|
2074
|
-
if (!foregroundRun &&
|
|
2075
|
-
(normalized.message.type === "assistant" ||
|
|
2076
|
-
normalized.message.type === "stream_event" ||
|
|
2077
|
-
normalized.message.type === "result" ||
|
|
2078
|
-
normalized.message.type === "tool_progress")) {
|
|
2079
|
-
const autonomousRun = this.claimOrCreateAutonomousRun("unbound_implicit");
|
|
2080
|
-
return { run: autonomousRun, reason: "unbound_autonomous" };
|
|
2081
|
-
}
|
|
2082
|
-
}
|
|
2083
|
-
if (this.pendingAutonomousWakeReservations > 0) {
|
|
2084
|
-
const reservedAutonomousRun = this.claimOrCreateAutonomousRun("reservation_fallback");
|
|
2085
|
-
return { run: reservedAutonomousRun, reason: "reserved_autonomous" };
|
|
2086
|
-
}
|
|
2087
|
-
this.logger.debug({
|
|
2088
|
-
messageType: normalized.message.type,
|
|
2089
|
-
hasIdentifiers,
|
|
2090
|
-
taskId: normalized.identifiers.taskId,
|
|
2091
|
-
parentMessageId: normalized.identifiers.parentMessageId,
|
|
2092
|
-
messageId: normalized.identifiers.messageId,
|
|
2093
|
-
turnState: this.turnState,
|
|
2094
|
-
pendingAutonomousWakeReservations: this.pendingAutonomousWakeReservations,
|
|
2095
|
-
}, "Ignoring unmatched Claude SDK message without explicit run start signal");
|
|
2096
|
-
return {
|
|
2097
|
-
run: null,
|
|
2098
|
-
reason: "ignored_unmatched",
|
|
2099
|
-
dispatchWithoutRun: false,
|
|
2100
|
-
};
|
|
2101
|
-
}
|
|
2102
|
-
shouldPreferForegroundRun(input) {
|
|
2103
|
-
const { run, message } = input;
|
|
2104
|
-
if (run.state === "completed" ||
|
|
2105
|
-
run.state === "interrupted" ||
|
|
2106
|
-
run.state === "error") {
|
|
2107
|
-
return false;
|
|
1752
|
+
let terminalSeen = false;
|
|
1753
|
+
for (const event of events) {
|
|
1754
|
+
foregroundTurn.queue.push(event);
|
|
1755
|
+
terminalSeen || (terminalSeen = this.isTerminalTurnEvent(event));
|
|
2108
1756
|
}
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
// was observed pre-replay, stay conservative and wait for replay.
|
|
2112
|
-
if (!run.promptReplaySeen) {
|
|
2113
|
-
if (this.isToolUseBoundaryStreamEvent(input.message)) {
|
|
2114
|
-
return true;
|
|
2115
|
-
}
|
|
2116
|
-
// Keep pre-replay result events with the foreground run so stale result
|
|
2117
|
-
// bursts cannot consume autonomous wake reservations.
|
|
2118
|
-
if (message.type === "result") {
|
|
2119
|
-
return true;
|
|
2120
|
-
}
|
|
2121
|
-
if (message.type === "assistant" ||
|
|
2122
|
-
message.type === "stream_event" ||
|
|
2123
|
-
message.type === "tool_progress") {
|
|
2124
|
-
return !this.preReplayMetadataSeen;
|
|
2125
|
-
}
|
|
2126
|
-
return true;
|
|
1757
|
+
if (!terminalSeen) {
|
|
1758
|
+
return;
|
|
2127
1759
|
}
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
1760
|
+
foregroundTurn.queue.end();
|
|
1761
|
+
if (this.activeForegroundTurn === foregroundTurn) {
|
|
1762
|
+
this.activeForegroundTurn = null;
|
|
2131
1763
|
}
|
|
2132
|
-
|
|
1764
|
+
this.syncTurnState("foreground turn terminal");
|
|
2133
1765
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
1766
|
+
dispatchLiveEvents(events) {
|
|
1767
|
+
let terminalSeen = false;
|
|
1768
|
+
for (const event of events) {
|
|
1769
|
+
this.liveEventQueue.push(event);
|
|
1770
|
+
terminalSeen || (terminalSeen = this.isTerminalTurnEvent(event));
|
|
2137
1771
|
}
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
1772
|
+
if (terminalSeen && this.autonomousTurn) {
|
|
1773
|
+
this.autonomousTurn = null;
|
|
1774
|
+
this.syncTurnState("autonomous turn terminal");
|
|
2141
1775
|
}
|
|
2142
|
-
const delta = "delta" in event && event.delta && typeof event.delta === "object"
|
|
2143
|
-
? event.delta
|
|
2144
|
-
: null;
|
|
2145
|
-
return delta?.stop_reason === "tool_use";
|
|
2146
1776
|
}
|
|
2147
|
-
|
|
2148
|
-
if (this.
|
|
1777
|
+
startAutonomousTurn() {
|
|
1778
|
+
if (this.autonomousTurn) {
|
|
2149
1779
|
return;
|
|
2150
1780
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
1781
|
+
this.autonomousTurn = {
|
|
1782
|
+
id: this.createTurnId("autonomous"),
|
|
1783
|
+
};
|
|
1784
|
+
this.liveEventQueue.push({ type: "turn_started", provider: "claude" });
|
|
1785
|
+
this.syncTurnState("autonomous turn started");
|
|
1786
|
+
}
|
|
1787
|
+
completeAutonomousTurn() {
|
|
1788
|
+
if (!this.autonomousTurn) {
|
|
2155
1789
|
return;
|
|
2156
1790
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
1791
|
+
this.autonomousTurn = null;
|
|
1792
|
+
this.liveEventQueue.push({ type: "turn_completed", provider: "claude" });
|
|
1793
|
+
this.syncTurnState("autonomous turn completed");
|
|
1794
|
+
}
|
|
1795
|
+
cancelAutonomousTurn(reason) {
|
|
1796
|
+
if (!this.autonomousTurn) {
|
|
2163
1797
|
return;
|
|
2164
1798
|
}
|
|
2165
|
-
this.
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
1799
|
+
this.flushPendingToolCalls();
|
|
1800
|
+
this.autonomousTurn = null;
|
|
1801
|
+
this.liveEventQueue.push({
|
|
1802
|
+
type: "turn_canceled",
|
|
1803
|
+
provider: "claude",
|
|
2170
1804
|
reason,
|
|
2171
|
-
|
|
2172
|
-
|
|
1805
|
+
});
|
|
1806
|
+
this.syncTurnState("autonomous turn canceled");
|
|
2173
1807
|
}
|
|
2174
|
-
|
|
2175
|
-
const
|
|
2176
|
-
if (
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
this.logger.debug({
|
|
2181
|
-
reason,
|
|
2182
|
-
runId: existing.id,
|
|
2183
|
-
pendingAutonomousWakeReservations: this.pendingAutonomousWakeReservations,
|
|
2184
|
-
}, "Claimed autonomous wake reservation on existing run");
|
|
2185
|
-
return existing;
|
|
1808
|
+
failActiveTurns(errorMessage) {
|
|
1809
|
+
const failure = this.buildTurnFailedEvent(errorMessage);
|
|
1810
|
+
if (this.activeForegroundTurn) {
|
|
1811
|
+
this.flushPendingToolCalls();
|
|
1812
|
+
this.dispatchForegroundEvents([failure]);
|
|
1813
|
+
return;
|
|
2186
1814
|
}
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
this.pendingAutonomousWakeReservations -= 1;
|
|
1815
|
+
if (this.autonomousTurn) {
|
|
1816
|
+
this.flushPendingToolCalls();
|
|
1817
|
+
this.dispatchLiveEvents([failure]);
|
|
2191
1818
|
}
|
|
2192
|
-
this.logger.debug({
|
|
2193
|
-
reason,
|
|
2194
|
-
runId: run.id,
|
|
2195
|
-
pendingAutonomousWakeReservations: this.pendingAutonomousWakeReservations,
|
|
2196
|
-
}, "Claimed autonomous wake reservation with new run");
|
|
2197
|
-
return run;
|
|
2198
1819
|
}
|
|
2199
1820
|
startQueryPump() {
|
|
2200
1821
|
if (this.closed || this.queryPumpPromise) {
|
|
@@ -2211,139 +1832,83 @@ class ClaudeAgentSession {
|
|
|
2211
1832
|
});
|
|
2212
1833
|
}
|
|
2213
1834
|
async runQueryPump() {
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
}
|
|
2239
|
-
this.logger.trace({ err: error }, "Claude query pump next() failed");
|
|
2240
|
-
for (const run of this.runTracker.listActiveRuns()) {
|
|
2241
|
-
this.failRun(run, error instanceof Error ? error.message : "Claude stream failed");
|
|
2242
|
-
}
|
|
2243
|
-
this.input?.end();
|
|
2244
|
-
await this.awaitWithTimeout(q.return?.(), "query pump return after failure");
|
|
2245
|
-
if (this.query === q) {
|
|
2246
|
-
this.query = null;
|
|
2247
|
-
this.input = null;
|
|
2248
|
-
}
|
|
2249
|
-
await this.waitForLiveHistoryPoll();
|
|
2250
|
-
continue;
|
|
2251
|
-
}
|
|
2252
|
-
if (next.done) {
|
|
2253
|
-
if (this.query !== q) {
|
|
2254
|
-
this.logger.trace({
|
|
2255
|
-
claudeSessionId: this.claudeSessionId,
|
|
2256
|
-
activeRunCount: this.runTracker.listActiveRuns().length,
|
|
2257
|
-
staleQuery: true,
|
|
2258
|
-
}, "Ignoring replaced Claude query pump completion");
|
|
2259
|
-
await this.awaitWithTimeout(q.return?.(), "query pump return on stale done");
|
|
2260
|
-
continue;
|
|
2261
|
-
}
|
|
2262
|
-
this.logger.trace({
|
|
2263
|
-
claudeSessionId: this.claudeSessionId,
|
|
2264
|
-
activeRunCount: this.runTracker.listActiveRuns().length,
|
|
2265
|
-
}, "Claude query pump next() returned done");
|
|
2266
|
-
this.input?.end();
|
|
2267
|
-
await this.awaitWithTimeout(q.return?.(), "query pump return on done");
|
|
2268
|
-
if (this.query === q) {
|
|
2269
|
-
this.query = null;
|
|
2270
|
-
this.input = null;
|
|
1835
|
+
let activeQuery;
|
|
1836
|
+
try {
|
|
1837
|
+
activeQuery = await this.ensureQuery();
|
|
1838
|
+
}
|
|
1839
|
+
catch (error) {
|
|
1840
|
+
this.logger.trace({ err: error }, "Failed to initialize Claude query pump");
|
|
1841
|
+
this.failActiveTurns(error instanceof Error ? error.message : "Claude stream failed");
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
let consecutiveInterruptAbortRecoveries = 0;
|
|
1845
|
+
try {
|
|
1846
|
+
while (!this.closed && this.query === activeQuery) {
|
|
1847
|
+
try {
|
|
1848
|
+
for await (const message of activeQuery) {
|
|
1849
|
+
consecutiveInterruptAbortRecoveries = 0;
|
|
1850
|
+
if (await this.handleMissingResumedConversation(message, activeQuery)) {
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1853
|
+
this.routeSdkMessageFromPump(message);
|
|
1854
|
+
}
|
|
1855
|
+
if (!this.closed && this.query === activeQuery) {
|
|
1856
|
+
this.failActiveTurns("Claude stream ended before terminal result");
|
|
1857
|
+
}
|
|
1858
|
+
return;
|
|
2271
1859
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
this.
|
|
1860
|
+
catch (error) {
|
|
1861
|
+
if (!this.closed &&
|
|
1862
|
+
this.query === activeQuery &&
|
|
1863
|
+
this.shouldRecoverInterruptedQueryAbort(error, consecutiveInterruptAbortRecoveries)) {
|
|
1864
|
+
consecutiveInterruptAbortRecoveries += 1;
|
|
1865
|
+
this.logger.debug({ recoveries: consecutiveInterruptAbortRecoveries }, "Recovering Claude query pump after interrupt abort");
|
|
1866
|
+
continue;
|
|
2276
1867
|
}
|
|
1868
|
+
if (!this.closed && this.query === activeQuery) {
|
|
1869
|
+
this.failActiveTurns(error instanceof Error ? error.message : "Claude stream failed");
|
|
1870
|
+
}
|
|
1871
|
+
return;
|
|
2277
1872
|
}
|
|
2278
|
-
await this.waitForLiveHistoryPoll();
|
|
2279
|
-
continue;
|
|
2280
|
-
}
|
|
2281
|
-
const sdkMessage = next.value;
|
|
2282
|
-
if (!sdkMessage) {
|
|
2283
|
-
continue;
|
|
2284
|
-
}
|
|
2285
|
-
if (this.query !== q) {
|
|
2286
|
-
this.logger.trace({
|
|
2287
|
-
claudeSessionId: this.claudeSessionId,
|
|
2288
|
-
messageType: sdkMessage.type,
|
|
2289
|
-
staleQuery: true,
|
|
2290
|
-
}, "Ignoring Claude SDK message from replaced query");
|
|
2291
|
-
await this.awaitWithTimeout(q.return?.(), "query pump return on stale message");
|
|
2292
|
-
continue;
|
|
2293
|
-
}
|
|
2294
|
-
if (await this.handleMissingResumedConversation(sdkMessage, q)) {
|
|
2295
|
-
continue;
|
|
2296
|
-
}
|
|
2297
|
-
try {
|
|
2298
|
-
this.routeSdkMessageFromPump(sdkMessage);
|
|
2299
1873
|
}
|
|
2300
|
-
|
|
2301
|
-
|
|
1874
|
+
}
|
|
1875
|
+
finally {
|
|
1876
|
+
if (this.query === activeQuery) {
|
|
1877
|
+
this.query = null;
|
|
1878
|
+
this.input = null;
|
|
2302
1879
|
}
|
|
2303
1880
|
}
|
|
2304
1881
|
}
|
|
2305
1882
|
routeSdkMessageFromPump(message) {
|
|
2306
|
-
|
|
1883
|
+
const routeToForeground = Boolean(this.activeForegroundTurn);
|
|
1884
|
+
const assistantishMessage = message.type === "assistant" ||
|
|
1885
|
+
message.type === "stream_event" ||
|
|
1886
|
+
message.type === "tool_progress";
|
|
1887
|
+
if (!routeToForeground && assistantishMessage) {
|
|
1888
|
+
this.startAutonomousTurn();
|
|
1889
|
+
}
|
|
1890
|
+
if (!routeToForeground && !this.autonomousTurn && message.type === "result") {
|
|
2307
1891
|
return;
|
|
2308
1892
|
}
|
|
1893
|
+
const turnId = this.activeForegroundTurn?.id ?? this.autonomousTurn?.id ?? null;
|
|
2309
1894
|
const identifiers = readEventIdentifiers(message);
|
|
2310
|
-
const metadataOnly = isMetadataOnlySdkMessage(message);
|
|
2311
|
-
const route = this.routeMessage({
|
|
2312
|
-
message,
|
|
2313
|
-
identifiers,
|
|
2314
|
-
metadataOnly,
|
|
2315
|
-
});
|
|
2316
|
-
const suppressTerminalEvents = this.shouldSuppressReplayResultTerminal({
|
|
2317
|
-
run: route.run,
|
|
2318
|
-
message,
|
|
2319
|
-
});
|
|
2320
1895
|
this.logger.trace({
|
|
2321
1896
|
claudeSessionId: this.claudeSessionId,
|
|
2322
1897
|
messageType: message.type,
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
runOwner: route.run?.owner ?? null,
|
|
2326
|
-
suppressTerminalEvents,
|
|
2327
|
-
metadataOnly,
|
|
1898
|
+
routedTo: routeToForeground ? "foreground_queue" : "live_queue",
|
|
1899
|
+
turnId,
|
|
2328
1900
|
}, "Claude query pump routed SDK message");
|
|
2329
|
-
if (route.run) {
|
|
2330
|
-
this.transitionTurnStateFromActiveRuns(`routed via ${route.reason}`);
|
|
2331
|
-
this.runTracker.bindIdentifiers(route.run, identifiers);
|
|
2332
|
-
if (!suppressTerminalEvents) {
|
|
2333
|
-
this.updateRunLifecycleForMessage(route.run, message, identifiers);
|
|
2334
|
-
}
|
|
2335
|
-
}
|
|
2336
1901
|
const messageEvents = this.translateMessageToEvents(message, {
|
|
2337
1902
|
suppressAssistantText: true,
|
|
2338
1903
|
suppressReasoning: true,
|
|
2339
|
-
suppressTerminalEvents,
|
|
2340
1904
|
});
|
|
2341
|
-
const
|
|
1905
|
+
const assistantTimelineEvents = this.timelineAssembler
|
|
1906
|
+
.consume({
|
|
2342
1907
|
message,
|
|
2343
|
-
runId:
|
|
1908
|
+
runId: turnId,
|
|
2344
1909
|
messageIdHint: identifiers.messageId,
|
|
2345
|
-
})
|
|
2346
|
-
|
|
1910
|
+
})
|
|
1911
|
+
.map((item) => ({
|
|
2347
1912
|
type: "timeline",
|
|
2348
1913
|
item,
|
|
2349
1914
|
provider: "claude",
|
|
@@ -2352,16 +1917,26 @@ class ClaudeAgentSession {
|
|
|
2352
1917
|
if (events.length === 0) {
|
|
2353
1918
|
return;
|
|
2354
1919
|
}
|
|
2355
|
-
if (
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
this.
|
|
1920
|
+
if (this.pendingInterruptAbort &&
|
|
1921
|
+
message.type === "result" &&
|
|
1922
|
+
events.some((event) => event.type === "turn_completed" || event.type === "turn_failed") &&
|
|
1923
|
+
(!this.activeForegroundTurn || !this.activeForegroundTurn.hasVisibleActivity)) {
|
|
1924
|
+
this.pendingInterruptAbort = false;
|
|
1925
|
+
this.logger.debug("Suppressing stale Claude interrupt terminal result");
|
|
2360
1926
|
return;
|
|
2361
1927
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
1928
|
+
if (this.activeForegroundTurn &&
|
|
1929
|
+
events.some((event) => event.type === "timeline" ||
|
|
1930
|
+
event.type === "permission_requested" ||
|
|
1931
|
+
event.type === "permission_resolved")) {
|
|
1932
|
+
this.activeForegroundTurn.hasVisibleActivity = true;
|
|
1933
|
+
this.pendingInterruptAbort = false;
|
|
1934
|
+
}
|
|
1935
|
+
if (routeToForeground) {
|
|
1936
|
+
this.dispatchForegroundEvents(events);
|
|
1937
|
+
return;
|
|
2364
1938
|
}
|
|
1939
|
+
this.dispatchLiveEvents(events);
|
|
2365
1940
|
}
|
|
2366
1941
|
async handleMissingResumedConversation(message, query) {
|
|
2367
1942
|
const staleResumeError = this.readMissingResumedConversationError(message);
|
|
@@ -2372,10 +1947,7 @@ class ClaudeAgentSession {
|
|
|
2372
1947
|
claudeSessionId: this.claudeSessionId,
|
|
2373
1948
|
error: staleResumeError,
|
|
2374
1949
|
}, "Claude resumed session no longer exists; invalidating persisted session");
|
|
2375
|
-
|
|
2376
|
-
this.failRun(run, staleResumeError);
|
|
2377
|
-
}
|
|
2378
|
-
this.transitionTurnStateFromActiveRuns("missing resumed conversation");
|
|
1950
|
+
this.failActiveTurns(staleResumeError);
|
|
2379
1951
|
this.input?.end();
|
|
2380
1952
|
await this.awaitWithTimeout(query.return?.(), "query pump return on missing resumed conversation");
|
|
2381
1953
|
if (this.query === query) {
|
|
@@ -2386,373 +1958,36 @@ class ClaudeAgentSession {
|
|
|
2386
1958
|
this.persistence = null;
|
|
2387
1959
|
this.persistedHistory = [];
|
|
2388
1960
|
this.historyPending = false;
|
|
1961
|
+
this.historyOffsetSessionId = null;
|
|
1962
|
+
this.historyReadOffsetBytes = 0;
|
|
1963
|
+
this.historyLineFragment = "";
|
|
2389
1964
|
this.cachedRuntimeInfo = null;
|
|
2390
1965
|
this.queryRestartNeeded = false;
|
|
1966
|
+
this.autonomousTurn = null;
|
|
1967
|
+
this.activeForegroundTurn = null;
|
|
1968
|
+
this.syncTurnState("missing resumed conversation");
|
|
2391
1969
|
return true;
|
|
2392
1970
|
}
|
|
2393
|
-
shouldSuppressReplayResultTerminal(input) {
|
|
2394
|
-
const { run, message } = input;
|
|
2395
|
-
if (!run || run.owner !== "foreground" || message.type !== "result") {
|
|
2396
|
-
return false;
|
|
2397
|
-
}
|
|
2398
|
-
if (run.promptReplaySeen) {
|
|
2399
|
-
return false;
|
|
2400
|
-
}
|
|
2401
|
-
if (run.state === "streaming" || run.state === "finalizing") {
|
|
2402
|
-
return false;
|
|
2403
|
-
}
|
|
2404
|
-
const resultSubtype = "subtype" in message && typeof message.subtype === "string"
|
|
2405
|
-
? message.subtype
|
|
2406
|
-
: null;
|
|
2407
|
-
// Pre-replay success results are stale in practice (leftover from an
|
|
2408
|
-
// earlier query segment) and must not end the current foreground run.
|
|
2409
|
-
if (resultSubtype === "success") {
|
|
2410
|
-
this.logger.trace({
|
|
2411
|
-
runId: run.id,
|
|
2412
|
-
runOwner: run.owner,
|
|
2413
|
-
runState: run.state,
|
|
2414
|
-
promptReplaySeen: run.promptReplaySeen,
|
|
2415
|
-
resultSubtype,
|
|
2416
|
-
}, "Suppressing pre-replay foreground success result terminal event");
|
|
2417
|
-
return true;
|
|
2418
|
-
}
|
|
2419
|
-
// For non-success results, keep the metadata-churn guard to avoid
|
|
2420
|
-
// suppressing legitimate hard failures.
|
|
2421
|
-
return this.preReplayMetadataSeen;
|
|
2422
|
-
}
|
|
2423
|
-
dispatchMetadataEvents(events) {
|
|
2424
|
-
for (const event of events) {
|
|
2425
|
-
this.pushEvent(event);
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
updateRunLifecycleForMessage(run, message, identifiers) {
|
|
2429
|
-
const previousState = run.state;
|
|
2430
|
-
if (message.type === "user" &&
|
|
2431
|
-
identifiers.messageId &&
|
|
2432
|
-
run.messageIds.has(identifiers.messageId)) {
|
|
2433
|
-
run.promptReplaySeen = true;
|
|
2434
|
-
this.preReplayMetadataSeen = false;
|
|
2435
|
-
}
|
|
2436
|
-
if (run.state === "queued") {
|
|
2437
|
-
this.runTracker.transition(run, "awaiting_response");
|
|
2438
|
-
}
|
|
2439
|
-
if (message.type === "assistant" ||
|
|
2440
|
-
message.type === "stream_event" ||
|
|
2441
|
-
message.type === "tool_progress") {
|
|
2442
|
-
this.runTracker.transition(run, "streaming");
|
|
2443
|
-
return;
|
|
2444
|
-
}
|
|
2445
|
-
if (message.type === "result") {
|
|
2446
|
-
this.runTracker.transition(run, "finalizing");
|
|
2447
|
-
}
|
|
2448
|
-
else {
|
|
2449
|
-
return;
|
|
2450
|
-
}
|
|
2451
|
-
if (run.state !== previousState) {
|
|
2452
|
-
this.logger.trace({
|
|
2453
|
-
runId: run.id,
|
|
2454
|
-
owner: run.owner,
|
|
2455
|
-
messageType: message.type,
|
|
2456
|
-
previousState,
|
|
2457
|
-
nextState: run.state,
|
|
2458
|
-
taskId: identifiers.taskId,
|
|
2459
|
-
parentMessageId: identifiers.parentMessageId,
|
|
2460
|
-
messageId: identifiers.messageId,
|
|
2461
|
-
}, "Updated Claude run lifecycle from SDK message");
|
|
2462
|
-
}
|
|
2463
|
-
}
|
|
2464
|
-
shouldSuppressLocalReplayActivity(message) {
|
|
2465
|
-
const localReplay = this.isLocalReplayUserMessage(message);
|
|
2466
|
-
if (!this.activeForegroundTurn && localReplay) {
|
|
2467
|
-
this.suppressLocalReplayActivity = true;
|
|
2468
|
-
this.logger.debug({ uuid: message.uuid }, "Suppressing local replay user message from live pump");
|
|
2469
|
-
return true;
|
|
2470
|
-
}
|
|
2471
|
-
if (!this.suppressLocalReplayActivity) {
|
|
2472
|
-
return false;
|
|
2473
|
-
}
|
|
2474
|
-
// Suppress only replay scaffolding. Do not suppress autonomous
|
|
2475
|
-
// assistant/result events; otherwise task-notification replies can be dropped.
|
|
2476
|
-
if (localReplay) {
|
|
2477
|
-
return true;
|
|
2478
|
-
}
|
|
2479
|
-
if (message.type === "system") {
|
|
2480
|
-
return true;
|
|
2481
|
-
}
|
|
2482
|
-
const identifiers = readEventIdentifiers(message);
|
|
2483
|
-
const hasIdentifiers = Boolean(identifiers.taskId || identifiers.parentMessageId || identifiers.messageId);
|
|
2484
|
-
if (message.type !== "user" && !hasIdentifiers) {
|
|
2485
|
-
if (this.pendingAutonomousWakeReservations > 0) {
|
|
2486
|
-
this.suppressLocalReplayActivity = false;
|
|
2487
|
-
return false;
|
|
2488
|
-
}
|
|
2489
|
-
return true;
|
|
2490
|
-
}
|
|
2491
|
-
if (message.type === "user") {
|
|
2492
|
-
this.suppressLocalReplayActivity = false;
|
|
2493
|
-
return false;
|
|
2494
|
-
}
|
|
2495
|
-
this.suppressLocalReplayActivity = false;
|
|
2496
|
-
return false;
|
|
2497
|
-
}
|
|
2498
|
-
isLocalReplayUserMessage(message) {
|
|
2499
|
-
if (message.type !== "user") {
|
|
2500
|
-
return false;
|
|
2501
|
-
}
|
|
2502
|
-
const uuid = readTrimmedString(message.uuid);
|
|
2503
|
-
if (!uuid) {
|
|
2504
|
-
return false;
|
|
2505
|
-
}
|
|
2506
|
-
return this.localUserMessageIds.has(uuid);
|
|
2507
|
-
}
|
|
2508
1971
|
async interruptActiveTurn() {
|
|
2509
1972
|
const queryToInterrupt = this.query;
|
|
2510
1973
|
if (!queryToInterrupt || typeof queryToInterrupt.interrupt !== "function") {
|
|
2511
1974
|
this.logger.trace("interruptActiveTurn: no query to interrupt");
|
|
2512
1975
|
return;
|
|
2513
1976
|
}
|
|
1977
|
+
this.pendingInterruptAbort = true;
|
|
2514
1978
|
try {
|
|
2515
|
-
this.logger.trace("interruptActiveTurn: calling query.interrupt()...");
|
|
2516
1979
|
await this.awaitWithTimeout(queryToInterrupt.interrupt(), "interruptActiveTurn query.interrupt()");
|
|
2517
|
-
this.input?.end();
|
|
2518
|
-
this.logger.trace("interruptActiveTurn: calling query.return()...");
|
|
2519
|
-
await this.awaitWithTimeout(queryToInterrupt.return?.(), "interruptActiveTurn query.return()");
|
|
2520
|
-
this.query = null;
|
|
2521
|
-
this.input = null;
|
|
2522
|
-
this.queryRestartNeeded = false;
|
|
2523
1980
|
}
|
|
2524
1981
|
catch (error) {
|
|
2525
1982
|
this.logger.warn({ err: error }, "Failed to interrupt active turn");
|
|
2526
|
-
this.input?.end();
|
|
2527
|
-
if (this.query === queryToInterrupt) {
|
|
2528
|
-
this.query = null;
|
|
2529
|
-
this.input = null;
|
|
2530
|
-
}
|
|
2531
|
-
// Try to force-close the iterator to unblock the pump's q.next() call.
|
|
2532
|
-
this.awaitWithTimeout(queryToInterrupt.return?.(), "interruptActiveTurn force return after failure").catch(() => { });
|
|
2533
|
-
// Disown the current pump and start a fresh one immediately so
|
|
2534
|
-
// autonomous wakes are not lost while waiting for the next user turn.
|
|
2535
|
-
this.queryPumpPromise = null;
|
|
2536
|
-
this.startQueryPump();
|
|
2537
|
-
}
|
|
2538
|
-
}
|
|
2539
|
-
handleSidechainMessage(message, parentToolUseId) {
|
|
2540
|
-
const state = this.activeSidechains.get(parentToolUseId) ??
|
|
2541
|
-
{
|
|
2542
|
-
actions: [],
|
|
2543
|
-
actionKeys: [],
|
|
2544
|
-
nextActionIndex: 1,
|
|
2545
|
-
actionIndexByKey: new Map(),
|
|
2546
|
-
};
|
|
2547
|
-
this.activeSidechains.set(parentToolUseId, state);
|
|
2548
|
-
const contextUpdated = this.updateSubAgentContextFromTaskInput(state, parentToolUseId);
|
|
2549
|
-
const actionCandidates = this.extractSubAgentActionCandidates(message);
|
|
2550
|
-
let actionUpdated = false;
|
|
2551
|
-
for (const action of actionCandidates) {
|
|
2552
|
-
if (this.appendSubAgentAction(state, action)) {
|
|
2553
|
-
actionUpdated = true;
|
|
2554
|
-
}
|
|
2555
|
-
}
|
|
2556
|
-
if (!contextUpdated && !actionUpdated) {
|
|
2557
|
-
return [];
|
|
2558
|
-
}
|
|
2559
|
-
const toolCall = mapClaudeRunningToolCall({
|
|
2560
|
-
name: "Task",
|
|
2561
|
-
callId: parentToolUseId,
|
|
2562
|
-
input: null,
|
|
2563
|
-
output: null,
|
|
2564
|
-
});
|
|
2565
|
-
if (!toolCall) {
|
|
2566
|
-
return [];
|
|
2567
|
-
}
|
|
2568
|
-
const detail = {
|
|
2569
|
-
type: "sub_agent",
|
|
2570
|
-
...(state.subAgentType ? { subAgentType: state.subAgentType } : {}),
|
|
2571
|
-
...(state.description ? { description: state.description } : {}),
|
|
2572
|
-
log: state.actions
|
|
2573
|
-
.map((action) => action.summary
|
|
2574
|
-
? `[${action.toolName}] ${action.summary}`
|
|
2575
|
-
: `[${action.toolName}]`)
|
|
2576
|
-
.join("\n"),
|
|
2577
|
-
actions: state.actions.map((action) => ({
|
|
2578
|
-
index: action.index,
|
|
2579
|
-
toolName: action.toolName,
|
|
2580
|
-
...(action.summary ? { summary: action.summary } : {}),
|
|
2581
|
-
})),
|
|
2582
|
-
};
|
|
2583
|
-
return [
|
|
2584
|
-
{
|
|
2585
|
-
type: "timeline",
|
|
2586
|
-
item: {
|
|
2587
|
-
...toolCall,
|
|
2588
|
-
detail,
|
|
2589
|
-
},
|
|
2590
|
-
provider: "claude",
|
|
2591
|
-
},
|
|
2592
|
-
];
|
|
2593
|
-
}
|
|
2594
|
-
updateSubAgentContextFromTaskInput(state, parentToolUseId) {
|
|
2595
|
-
const taskInput = this.toolUseCache.get(parentToolUseId)?.input;
|
|
2596
|
-
const nextSubAgentType = this.normalizeSubAgentText(taskInput?.subagent_type);
|
|
2597
|
-
const nextDescription = this.normalizeSubAgentText(taskInput?.description);
|
|
2598
|
-
let changed = false;
|
|
2599
|
-
if (nextSubAgentType && nextSubAgentType !== state.subAgentType) {
|
|
2600
|
-
state.subAgentType = nextSubAgentType;
|
|
2601
|
-
changed = true;
|
|
2602
|
-
}
|
|
2603
|
-
if (nextDescription && nextDescription !== state.description) {
|
|
2604
|
-
state.description = nextDescription;
|
|
2605
|
-
changed = true;
|
|
2606
|
-
}
|
|
2607
|
-
return changed;
|
|
2608
|
-
}
|
|
2609
|
-
normalizeSubAgentText(value) {
|
|
2610
|
-
const normalized = readTrimmedString(value)?.replace(/\s+/g, " ");
|
|
2611
|
-
if (!normalized) {
|
|
2612
|
-
return undefined;
|
|
2613
|
-
}
|
|
2614
|
-
if (normalized.length <= MAX_SUB_AGENT_SUMMARY_CHARS) {
|
|
2615
|
-
return normalized;
|
|
2616
|
-
}
|
|
2617
|
-
return `${normalized.slice(0, MAX_SUB_AGENT_SUMMARY_CHARS)}...`;
|
|
2618
|
-
}
|
|
2619
|
-
extractSubAgentActionCandidates(message) {
|
|
2620
|
-
if (message.type === "assistant") {
|
|
2621
|
-
const content = message.message?.content;
|
|
2622
|
-
if (!Array.isArray(content)) {
|
|
2623
|
-
return [];
|
|
2624
|
-
}
|
|
2625
|
-
const actions = [];
|
|
2626
|
-
for (const block of content) {
|
|
2627
|
-
if (!isClaudeContentChunk(block) ||
|
|
2628
|
-
!(block.type === "tool_use" ||
|
|
2629
|
-
block.type === "mcp_tool_use" ||
|
|
2630
|
-
block.type === "server_tool_use") ||
|
|
2631
|
-
typeof block.name !== "string") {
|
|
2632
|
-
continue;
|
|
2633
|
-
}
|
|
2634
|
-
const key = readTrimmedString(block.id) ??
|
|
2635
|
-
`assistant:${block.name}:${actions.length}`;
|
|
2636
|
-
actions.push({
|
|
2637
|
-
key,
|
|
2638
|
-
toolName: block.name,
|
|
2639
|
-
input: block.input ?? null,
|
|
2640
|
-
});
|
|
2641
|
-
}
|
|
2642
|
-
return actions;
|
|
2643
|
-
}
|
|
2644
|
-
if (message.type === "stream_event") {
|
|
2645
|
-
const event = message.event;
|
|
2646
|
-
if (event.type !== "content_block_start") {
|
|
2647
|
-
return [];
|
|
2648
|
-
}
|
|
2649
|
-
const block = isClaudeContentChunk(event.content_block)
|
|
2650
|
-
? event.content_block
|
|
2651
|
-
: null;
|
|
2652
|
-
if (!block ||
|
|
2653
|
-
!(block.type === "tool_use" ||
|
|
2654
|
-
block.type === "mcp_tool_use" ||
|
|
2655
|
-
block.type === "server_tool_use") ||
|
|
2656
|
-
typeof block.name !== "string") {
|
|
2657
|
-
return [];
|
|
2658
|
-
}
|
|
2659
|
-
const key = readTrimmedString(block.id) ??
|
|
2660
|
-
`stream:${block.name}:${typeof event.index === "number" ? event.index : 0}`;
|
|
2661
|
-
return [
|
|
2662
|
-
{
|
|
2663
|
-
key,
|
|
2664
|
-
toolName: block.name,
|
|
2665
|
-
input: block.input ?? null,
|
|
2666
|
-
},
|
|
2667
|
-
];
|
|
2668
|
-
}
|
|
2669
|
-
if (message.type === "tool_progress") {
|
|
2670
|
-
const toolName = readTrimmedString(message.tool_name);
|
|
2671
|
-
if (!toolName) {
|
|
2672
|
-
return [];
|
|
2673
|
-
}
|
|
2674
|
-
const key = readTrimmedString(message.tool_use_id) ?? `progress:${toolName}`;
|
|
2675
|
-
return [{ key, toolName, input: null }];
|
|
2676
|
-
}
|
|
2677
|
-
return [];
|
|
2678
|
-
}
|
|
2679
|
-
appendSubAgentAction(state, candidate) {
|
|
2680
|
-
const normalizedToolName = readTrimmedString(candidate.toolName);
|
|
2681
|
-
if (!normalizedToolName) {
|
|
2682
|
-
return false;
|
|
2683
|
-
}
|
|
2684
|
-
const summary = this.deriveSubAgentActionSummary(normalizedToolName, candidate.input);
|
|
2685
|
-
const existingIndex = state.actionIndexByKey.get(candidate.key);
|
|
2686
|
-
if (existingIndex !== undefined) {
|
|
2687
|
-
const existing = state.actions[existingIndex];
|
|
2688
|
-
if (!existing) {
|
|
2689
|
-
return false;
|
|
2690
|
-
}
|
|
2691
|
-
const nextSummary = existing.summary ?? summary;
|
|
2692
|
-
const unchanged = existing.toolName === normalizedToolName &&
|
|
2693
|
-
existing.summary === nextSummary;
|
|
2694
|
-
if (unchanged) {
|
|
2695
|
-
return false;
|
|
2696
|
-
}
|
|
2697
|
-
state.actions[existingIndex] = {
|
|
2698
|
-
...existing,
|
|
2699
|
-
toolName: normalizedToolName,
|
|
2700
|
-
...(nextSummary ? { summary: nextSummary } : {}),
|
|
2701
|
-
};
|
|
2702
|
-
return true;
|
|
2703
|
-
}
|
|
2704
|
-
const nextEntry = {
|
|
2705
|
-
index: state.nextActionIndex,
|
|
2706
|
-
toolName: normalizedToolName,
|
|
2707
|
-
...(summary ? { summary } : {}),
|
|
2708
|
-
};
|
|
2709
|
-
state.nextActionIndex += 1;
|
|
2710
|
-
state.actions.push(nextEntry);
|
|
2711
|
-
state.actionKeys.push(candidate.key);
|
|
2712
|
-
this.trimSubAgentTail(state);
|
|
2713
|
-
this.rebuildSubAgentActionIndex(state);
|
|
2714
|
-
return true;
|
|
2715
|
-
}
|
|
2716
|
-
trimSubAgentTail(state) {
|
|
2717
|
-
while (state.actions.length > MAX_SUB_AGENT_LOG_ENTRIES) {
|
|
2718
|
-
state.actions.shift();
|
|
2719
|
-
state.actionKeys.shift();
|
|
2720
1983
|
}
|
|
2721
1984
|
}
|
|
2722
|
-
rebuildSubAgentActionIndex(state) {
|
|
2723
|
-
state.actionIndexByKey.clear();
|
|
2724
|
-
for (let index = 0; index < state.actionKeys.length; index += 1) {
|
|
2725
|
-
const key = state.actionKeys[index];
|
|
2726
|
-
if (key) {
|
|
2727
|
-
state.actionIndexByKey.set(key, index);
|
|
2728
|
-
}
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
deriveSubAgentActionSummary(toolName, input) {
|
|
2732
|
-
const runningToolCall = mapClaudeRunningToolCall({
|
|
2733
|
-
name: toolName,
|
|
2734
|
-
callId: `sub-agent-summary-${toolName}`,
|
|
2735
|
-
input,
|
|
2736
|
-
output: null,
|
|
2737
|
-
});
|
|
2738
|
-
if (!runningToolCall) {
|
|
2739
|
-
return undefined;
|
|
2740
|
-
}
|
|
2741
|
-
const display = buildToolCallDisplayModel({
|
|
2742
|
-
name: runningToolCall.name,
|
|
2743
|
-
status: runningToolCall.status,
|
|
2744
|
-
error: runningToolCall.error,
|
|
2745
|
-
detail: runningToolCall.detail,
|
|
2746
|
-
metadata: runningToolCall.metadata,
|
|
2747
|
-
});
|
|
2748
|
-
return this.normalizeSubAgentText(display.summary);
|
|
2749
|
-
}
|
|
2750
1985
|
translateMessageToEvents(message, options) {
|
|
2751
1986
|
const parentToolUseId = "parent_tool_use_id" in message
|
|
2752
1987
|
? message.parent_tool_use_id
|
|
2753
1988
|
: null;
|
|
2754
1989
|
if (parentToolUseId) {
|
|
2755
|
-
return this.
|
|
1990
|
+
return this.sidechainTracker.handleMessage(message, parentToolUseId);
|
|
2756
1991
|
}
|
|
2757
1992
|
const events = [];
|
|
2758
1993
|
const fallbackThreadSessionId = this.captureSessionIdFromMessage(message);
|
|
@@ -2818,9 +2053,7 @@ class ClaudeAgentSession {
|
|
|
2818
2053
|
this.compacting = false;
|
|
2819
2054
|
break;
|
|
2820
2055
|
}
|
|
2821
|
-
const messageId = typeof message.uuid === "string" && message.uuid.length > 0
|
|
2822
|
-
? message.uuid
|
|
2823
|
-
: undefined;
|
|
2056
|
+
const messageId = typeof message.uuid === "string" && message.uuid.length > 0 ? message.uuid : undefined;
|
|
2824
2057
|
this.rememberUserMessageId(messageId);
|
|
2825
2058
|
const content = message.message?.content;
|
|
2826
2059
|
const taskNotificationItem = mapTaskNotificationUserContentToToolCall({
|
|
@@ -2836,19 +2069,22 @@ class ClaudeAgentSession {
|
|
|
2836
2069
|
break;
|
|
2837
2070
|
}
|
|
2838
2071
|
if (typeof content === "string" && content.length > 0) {
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2072
|
+
if (!isClaudeTranscriptNoiseText(content)) {
|
|
2073
|
+
events.push({
|
|
2074
|
+
type: "timeline",
|
|
2075
|
+
item: {
|
|
2076
|
+
type: "user_message",
|
|
2077
|
+
text: content,
|
|
2078
|
+
...(messageId ? { messageId } : {}),
|
|
2079
|
+
},
|
|
2080
|
+
provider: "claude",
|
|
2081
|
+
});
|
|
2082
|
+
}
|
|
2849
2083
|
}
|
|
2850
2084
|
else if (Array.isArray(content)) {
|
|
2851
|
-
const timelineItems = this.mapBlocksToTimeline(content
|
|
2085
|
+
const timelineItems = this.mapBlocksToTimeline(content, {
|
|
2086
|
+
textMessageType: "user_message",
|
|
2087
|
+
});
|
|
2852
2088
|
for (const item of timelineItems) {
|
|
2853
2089
|
if (item.type === "user_message" && messageId && !item.messageId) {
|
|
2854
2090
|
events.push({
|
|
@@ -2884,9 +2120,6 @@ class ClaudeAgentSession {
|
|
|
2884
2120
|
break;
|
|
2885
2121
|
}
|
|
2886
2122
|
case "result": {
|
|
2887
|
-
if (options?.suppressTerminalEvents) {
|
|
2888
|
-
break;
|
|
2889
|
-
}
|
|
2890
2123
|
const usage = this.convertUsage(message);
|
|
2891
2124
|
if (message.subtype === "success") {
|
|
2892
2125
|
events.push({ type: "turn_completed", provider: "claude", usage });
|
|
@@ -2948,18 +2181,14 @@ class ClaudeAgentSession {
|
|
|
2948
2181
|
const existingSessionId = this.claudeSessionId;
|
|
2949
2182
|
let threadStartedSessionId = null;
|
|
2950
2183
|
if (existingSessionId === null) {
|
|
2951
|
-
// First time setting session ID (empty → filled) - this is expected
|
|
2952
2184
|
this.claudeSessionId = newSessionId;
|
|
2953
2185
|
threadStartedSessionId = newSessionId;
|
|
2954
2186
|
this.logger.debug({ sessionId: newSessionId }, "Claude session ID set for the first time");
|
|
2955
2187
|
}
|
|
2956
2188
|
else if (existingSessionId === newSessionId) {
|
|
2957
|
-
// Same session ID - no-op, but log for visibility
|
|
2958
2189
|
this.logger.debug({ sessionId: newSessionId }, "Claude session ID unchanged (same value)");
|
|
2959
2190
|
}
|
|
2960
2191
|
else {
|
|
2961
|
-
// CRITICAL: Session ID is being overwritten with a different value
|
|
2962
|
-
// This should NEVER happen and indicates a serious bug
|
|
2963
2192
|
throw new Error(`CRITICAL: Claude session ID overwrite detected! ` +
|
|
2964
2193
|
`Existing: ${existingSessionId}, New: ${newSessionId}. ` +
|
|
2965
2194
|
`This indicates a session identity corruption bug.`);
|
|
@@ -2967,7 +2196,6 @@ class ClaudeAgentSession {
|
|
|
2967
2196
|
this.availableModes = DEFAULT_MODES;
|
|
2968
2197
|
this.currentMode = message.permissionMode;
|
|
2969
2198
|
this.persistence = null;
|
|
2970
|
-
// Capture actual model from SDK init message (not just the configured model)
|
|
2971
2199
|
if (message.model) {
|
|
2972
2200
|
const normalizedModel = normalizeClaudeRuntimeModelId({
|
|
2973
2201
|
runtimeModelId: message.model,
|
|
@@ -2978,7 +2206,6 @@ class ClaudeAgentSession {
|
|
|
2978
2206
|
});
|
|
2979
2207
|
this.logger.debug({ model: message.model, normalizedModel }, "Captured model from SDK init");
|
|
2980
2208
|
this.lastOptionsModel = normalizedModel;
|
|
2981
|
-
// Invalidate cached runtime info so it picks up the new model
|
|
2982
2209
|
this.cachedRuntimeInfo = null;
|
|
2983
2210
|
}
|
|
2984
2211
|
return threadStartedSessionId;
|
|
@@ -3031,7 +2258,7 @@ class ClaudeAgentSession {
|
|
|
3031
2258
|
}
|
|
3032
2259
|
}
|
|
3033
2260
|
this.toolUseCache.clear();
|
|
3034
|
-
this.
|
|
2261
|
+
this.sidechainTracker.clear();
|
|
3035
2262
|
}
|
|
3036
2263
|
pushToolCall(item, target) {
|
|
3037
2264
|
if (!item) {
|
|
@@ -3046,15 +2273,8 @@ class ClaudeAgentSession {
|
|
|
3046
2273
|
pushEvent(event) {
|
|
3047
2274
|
const foregroundTurn = this.activeForegroundTurn;
|
|
3048
2275
|
if (foregroundTurn) {
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
run.owner === "foreground" &&
|
|
3052
|
-
run.queue === foregroundTurn.queue &&
|
|
3053
|
-
this.runTracker.isRunActive(run)) {
|
|
3054
|
-
foregroundTurn.queue.push(event);
|
|
3055
|
-
return;
|
|
3056
|
-
}
|
|
3057
|
-
this.activeForegroundTurn = null;
|
|
2276
|
+
foregroundTurn.queue.push(event);
|
|
2277
|
+
return;
|
|
3058
2278
|
}
|
|
3059
2279
|
this.liveEventQueue.push(event);
|
|
3060
2280
|
}
|
|
@@ -3072,47 +2292,125 @@ class ClaudeAgentSession {
|
|
|
3072
2292
|
this.pendingPermissions.delete(id);
|
|
3073
2293
|
}
|
|
3074
2294
|
}
|
|
3075
|
-
|
|
3076
|
-
return new Promise((resolve) => setTimeout(resolve, 250));
|
|
3077
|
-
}
|
|
3078
|
-
loadPersistedHistory(sessionId) {
|
|
2295
|
+
loadPersistedHistory(sessionId, options) {
|
|
3079
2296
|
try {
|
|
3080
2297
|
const historyPath = this.resolveHistoryPath(sessionId);
|
|
3081
2298
|
if (!historyPath || !fs.existsSync(historyPath)) {
|
|
3082
2299
|
return;
|
|
3083
2300
|
}
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
if (!trimmed)
|
|
3089
|
-
continue;
|
|
3090
|
-
try {
|
|
3091
|
-
const entry = JSON.parse(trimmed);
|
|
3092
|
-
if (entry.isSidechain) {
|
|
3093
|
-
continue;
|
|
3094
|
-
}
|
|
3095
|
-
if (entry.type === "user" && typeof entry.uuid === "string") {
|
|
3096
|
-
this.rememberUserMessageId(entry.uuid);
|
|
3097
|
-
}
|
|
3098
|
-
const items = this.convertHistoryEntry(entry);
|
|
3099
|
-
if (items.length > 0) {
|
|
3100
|
-
timeline.push(...items);
|
|
3101
|
-
}
|
|
3102
|
-
}
|
|
3103
|
-
catch (error) {
|
|
3104
|
-
// ignore malformed history line
|
|
3105
|
-
}
|
|
2301
|
+
if (this.historyOffsetSessionId !== sessionId) {
|
|
2302
|
+
this.historyOffsetSessionId = sessionId;
|
|
2303
|
+
this.historyReadOffsetBytes = 0;
|
|
2304
|
+
this.historyLineFragment = "";
|
|
3106
2305
|
}
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
this.
|
|
2306
|
+
const content = fs.readFileSync(historyPath);
|
|
2307
|
+
if (content.byteLength < this.historyReadOffsetBytes) {
|
|
2308
|
+
this.historyReadOffsetBytes = 0;
|
|
2309
|
+
this.historyLineFragment = "";
|
|
3110
2310
|
}
|
|
2311
|
+
if (content.byteLength === this.historyReadOffsetBytes) {
|
|
2312
|
+
return;
|
|
2313
|
+
}
|
|
2314
|
+
const unreadChunk = content.subarray(this.historyReadOffsetBytes).toString("utf8");
|
|
2315
|
+
this.historyReadOffsetBytes = content.byteLength;
|
|
2316
|
+
this.ingestPersistedHistoryChunk(unreadChunk, {
|
|
2317
|
+
dispatchLive: options?.dispatchLive ?? false,
|
|
2318
|
+
});
|
|
3111
2319
|
}
|
|
3112
2320
|
catch (error) {
|
|
3113
2321
|
// ignore history load failures
|
|
3114
2322
|
}
|
|
3115
2323
|
}
|
|
2324
|
+
ingestPersistedHistoryChunk(chunk, options) {
|
|
2325
|
+
if (!chunk) {
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
const combined = `${this.historyLineFragment}${chunk}`;
|
|
2329
|
+
this.historyLineFragment = "";
|
|
2330
|
+
const lines = combined.split(/\r?\n/);
|
|
2331
|
+
const trailing = lines.pop() ?? "";
|
|
2332
|
+
const timeline = [];
|
|
2333
|
+
for (const line of lines) {
|
|
2334
|
+
this.ingestPersistedHistoryLine(line, {
|
|
2335
|
+
dispatchLive: options.dispatchLive,
|
|
2336
|
+
timeline,
|
|
2337
|
+
});
|
|
2338
|
+
}
|
|
2339
|
+
if (trailing.trim().length > 0) {
|
|
2340
|
+
const handled = this.ingestPersistedHistoryLine(trailing, {
|
|
2341
|
+
dispatchLive: options.dispatchLive,
|
|
2342
|
+
timeline,
|
|
2343
|
+
});
|
|
2344
|
+
if (!handled) {
|
|
2345
|
+
this.historyLineFragment = trailing;
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
if (!options.dispatchLive && timeline.length > 0) {
|
|
2349
|
+
this.persistedHistory = [...this.persistedHistory, ...timeline];
|
|
2350
|
+
this.historyPending = true;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
ingestPersistedHistoryLine(line, options) {
|
|
2354
|
+
const trimmed = line.trim();
|
|
2355
|
+
if (!trimmed) {
|
|
2356
|
+
return true;
|
|
2357
|
+
}
|
|
2358
|
+
let entry;
|
|
2359
|
+
try {
|
|
2360
|
+
entry = JSON.parse(trimmed);
|
|
2361
|
+
}
|
|
2362
|
+
catch {
|
|
2363
|
+
return false;
|
|
2364
|
+
}
|
|
2365
|
+
if (entry.isSidechain) {
|
|
2366
|
+
return true;
|
|
2367
|
+
}
|
|
2368
|
+
if (entry.type === "user" && typeof entry.uuid === "string") {
|
|
2369
|
+
this.rememberUserMessageId(entry.uuid);
|
|
2370
|
+
}
|
|
2371
|
+
if (options.dispatchLive) {
|
|
2372
|
+
this.dispatchPersistedHistoryEntry(entry);
|
|
2373
|
+
return true;
|
|
2374
|
+
}
|
|
2375
|
+
const items = this.convertHistoryEntry(entry);
|
|
2376
|
+
if (items.length > 0) {
|
|
2377
|
+
options.timeline.push(...items);
|
|
2378
|
+
}
|
|
2379
|
+
return true;
|
|
2380
|
+
}
|
|
2381
|
+
dispatchPersistedHistoryEntry(entry) {
|
|
2382
|
+
const liveMessage = this.normalizePersistedHistoryEntryToLiveMessage(entry);
|
|
2383
|
+
if (liveMessage) {
|
|
2384
|
+
this.routeSdkMessageFromPump(liveMessage);
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
const items = this.convertHistoryEntry(entry);
|
|
2388
|
+
for (const item of items) {
|
|
2389
|
+
this.pushEvent({
|
|
2390
|
+
type: "timeline",
|
|
2391
|
+
item,
|
|
2392
|
+
provider: "claude",
|
|
2393
|
+
});
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
normalizePersistedHistoryEntryToLiveMessage(entry) {
|
|
2397
|
+
const taskNotificationMessage = coerceTaskNotificationHistoryRecordToSystemMessage(entry);
|
|
2398
|
+
if (taskNotificationMessage) {
|
|
2399
|
+
return taskNotificationMessage;
|
|
2400
|
+
}
|
|
2401
|
+
const type = readTrimmedString(entry.type);
|
|
2402
|
+
switch (type) {
|
|
2403
|
+
case "assistant":
|
|
2404
|
+
case "result":
|
|
2405
|
+
case "stream_event":
|
|
2406
|
+
case "system":
|
|
2407
|
+
case "tool_progress":
|
|
2408
|
+
case "user":
|
|
2409
|
+
return entry;
|
|
2410
|
+
default:
|
|
2411
|
+
return null;
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
3116
2414
|
resolveHistoryPath(sessionId) {
|
|
3117
2415
|
const cwd = this.config.cwd;
|
|
3118
2416
|
if (!cwd)
|
|
@@ -3126,25 +2424,50 @@ class ClaudeAgentSession {
|
|
|
3126
2424
|
convertHistoryEntry(entry) {
|
|
3127
2425
|
return convertClaudeHistoryEntry(entry, (content) => this.mapBlocksToTimeline(content));
|
|
3128
2426
|
}
|
|
2427
|
+
// Maps Claude content blocks into AgentTimelineItems.
|
|
2428
|
+
//
|
|
2429
|
+
// textMessageType controls what type text blocks emit:
|
|
2430
|
+
// - "assistant_message" (default): one item per text block (streaming granularity)
|
|
2431
|
+
// - "user_message": coalesces all text blocks into a single user_message
|
|
2432
|
+
// (matches extractUserMessageText semantics: trim each block, join with "\n\n")
|
|
2433
|
+
//
|
|
2434
|
+
// suppressAssistantText only applies when textMessageType is "assistant_message" — user text
|
|
2435
|
+
// must never be suppressed since the TimelineAssembler only handles assistant text.
|
|
2436
|
+
//
|
|
2437
|
+
// NOTE: convertClaudeHistoryEntry uses extractUserMessageText directly instead of this function
|
|
2438
|
+
// for user entries. Both paths must produce equivalent user_message items.
|
|
3129
2439
|
mapBlocksToTimeline(content, options) {
|
|
3130
|
-
const
|
|
2440
|
+
const textMessageType = options?.textMessageType ?? "assistant_message";
|
|
2441
|
+
const suppressText = textMessageType === "assistant_message" && (options?.suppressAssistantText ?? false);
|
|
3131
2442
|
const suppressReasoning = options?.suppressReasoning ?? false;
|
|
3132
2443
|
if (typeof content === "string") {
|
|
3133
|
-
if (!content ||
|
|
2444
|
+
if (!content ||
|
|
2445
|
+
content === INTERRUPT_TOOL_USE_PLACEHOLDER ||
|
|
2446
|
+
isClaudeTranscriptNoiseText(content)) {
|
|
3134
2447
|
return [];
|
|
3135
2448
|
}
|
|
3136
|
-
if (
|
|
2449
|
+
if (suppressText) {
|
|
3137
2450
|
return [];
|
|
3138
2451
|
}
|
|
3139
|
-
return [{ type:
|
|
2452
|
+
return [{ type: textMessageType, text: content }];
|
|
3140
2453
|
}
|
|
3141
2454
|
const items = [];
|
|
2455
|
+
// User SDK entries can arrive as multiple text blocks, but Paseo treats them as one message.
|
|
2456
|
+
const userTextParts = [];
|
|
3142
2457
|
for (const block of content) {
|
|
3143
2458
|
switch (block.type) {
|
|
3144
2459
|
case "text":
|
|
3145
2460
|
case "text_delta":
|
|
3146
|
-
if (block.text &&
|
|
3147
|
-
|
|
2461
|
+
if (block.text &&
|
|
2462
|
+
block.text !== INTERRUPT_TOOL_USE_PLACEHOLDER &&
|
|
2463
|
+
!isClaudeTranscriptNoiseText(block.text)) {
|
|
2464
|
+
if (textMessageType === "user_message") {
|
|
2465
|
+
const trimmed = block.text.trim();
|
|
2466
|
+
if (trimmed) {
|
|
2467
|
+
userTextParts.push(trimmed);
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
else if (!suppressText) {
|
|
3148
2471
|
items.push({ type: "assistant_message", text: block.text });
|
|
3149
2472
|
}
|
|
3150
2473
|
}
|
|
@@ -3177,6 +2500,12 @@ class ClaudeAgentSession {
|
|
|
3177
2500
|
break;
|
|
3178
2501
|
}
|
|
3179
2502
|
}
|
|
2503
|
+
if (textMessageType === "user_message" && userTextParts.length > 0) {
|
|
2504
|
+
items.unshift({
|
|
2505
|
+
type: "user_message",
|
|
2506
|
+
text: userTextParts.join("\n\n"),
|
|
2507
|
+
});
|
|
2508
|
+
}
|
|
3180
2509
|
return items;
|
|
3181
2510
|
}
|
|
3182
2511
|
handleToolUseStart(block, items) {
|
|
@@ -3201,7 +2530,7 @@ class ClaudeAgentSession {
|
|
|
3201
2530
|
const toolName = entry?.name ?? block.tool_name ?? "tool";
|
|
3202
2531
|
const callId = typeof block.tool_use_id === "string" && block.tool_use_id.length > 0
|
|
3203
2532
|
? block.tool_use_id
|
|
3204
|
-
: entry?.id ?? null;
|
|
2533
|
+
: (entry?.id ?? null);
|
|
3205
2534
|
// Extract output from block.content (SDK always returns content in string form)
|
|
3206
2535
|
const output = this.buildToolOutput(block, entry);
|
|
3207
2536
|
if (block.is_error) {
|
|
@@ -3223,7 +2552,7 @@ class ClaudeAgentSession {
|
|
|
3223
2552
|
}
|
|
3224
2553
|
if (typeof block.tool_use_id === "string") {
|
|
3225
2554
|
this.toolUseCache.delete(block.tool_use_id);
|
|
3226
|
-
this.
|
|
2555
|
+
this.sidechainTracker.delete(block.tool_use_id);
|
|
3227
2556
|
}
|
|
3228
2557
|
}
|
|
3229
2558
|
buildToolOutput(block, entry) {
|
|
@@ -3296,12 +2625,24 @@ class ClaudeAgentSession {
|
|
|
3296
2625
|
normalizedTool === "apply_diff") {
|
|
3297
2626
|
if (input && typeof input.file_path === "string") {
|
|
3298
2627
|
// Support both old_str/new_str and old_string/new_string parameter names
|
|
3299
|
-
const oldContent = typeof input.old_str === "string"
|
|
3300
|
-
|
|
2628
|
+
const oldContent = typeof input.old_str === "string"
|
|
2629
|
+
? input.old_str
|
|
2630
|
+
: typeof input.old_string === "string"
|
|
2631
|
+
? input.old_string
|
|
2632
|
+
: undefined;
|
|
2633
|
+
const newContent = typeof input.new_str === "string"
|
|
2634
|
+
? input.new_str
|
|
2635
|
+
: typeof input.new_string === "string"
|
|
2636
|
+
? input.new_string
|
|
2637
|
+
: undefined;
|
|
3301
2638
|
return {
|
|
3302
2639
|
type: "file_edit",
|
|
3303
2640
|
filePath: input.file_path,
|
|
3304
|
-
diff: typeof input.patch === "string"
|
|
2641
|
+
diff: typeof input.patch === "string"
|
|
2642
|
+
? input.patch
|
|
2643
|
+
: typeof input.diff === "string"
|
|
2644
|
+
? input.diff
|
|
2645
|
+
: undefined,
|
|
3305
2646
|
oldContent,
|
|
3306
2647
|
newContent,
|
|
3307
2648
|
};
|
|
@@ -3324,7 +2665,9 @@ class ClaudeAgentSession {
|
|
|
3324
2665
|
mapPartialEvent(event, options) {
|
|
3325
2666
|
if (event.type === "content_block_start") {
|
|
3326
2667
|
const block = isClaudeContentChunk(event.content_block) ? event.content_block : null;
|
|
3327
|
-
if (block?.type === "tool_use" &&
|
|
2668
|
+
if (block?.type === "tool_use" &&
|
|
2669
|
+
typeof event.index === "number" &&
|
|
2670
|
+
typeof block.id === "string") {
|
|
3328
2671
|
this.toolUseIndexToId.set(event.index, block.id);
|
|
3329
2672
|
this.toolUseInputBuffers.delete(block.id);
|
|
3330
2673
|
}
|
|
@@ -3389,7 +2732,9 @@ class ClaudeAgentSession {
|
|
|
3389
2732
|
else if (!existing.server) {
|
|
3390
2733
|
existing.server = existing.name;
|
|
3391
2734
|
}
|
|
3392
|
-
if (block.type === "tool_use" ||
|
|
2735
|
+
if (block.type === "tool_use" ||
|
|
2736
|
+
block.type === "mcp_tool_use" ||
|
|
2737
|
+
block.type === "server_tool_use") {
|
|
3393
2738
|
const input = this.normalizeToolInput(block.input);
|
|
3394
2739
|
if (input) {
|
|
3395
2740
|
this.applyToolInput(existing, input);
|
|
@@ -3465,7 +2810,10 @@ class ClaudeAgentSession {
|
|
|
3465
2810
|
}
|
|
3466
2811
|
isCommandTool(name, input) {
|
|
3467
2812
|
const normalized = name.toLowerCase();
|
|
3468
|
-
if (normalized.includes("bash") ||
|
|
2813
|
+
if (normalized.includes("bash") ||
|
|
2814
|
+
normalized.includes("shell") ||
|
|
2815
|
+
normalized.includes("terminal") ||
|
|
2816
|
+
normalized.includes("command")) {
|
|
3469
2817
|
return true;
|
|
3470
2818
|
}
|
|
3471
2819
|
if (typeof input.command === "string" || Array.isArray(input.command)) {
|
|
@@ -3509,7 +2857,10 @@ class ClaudeAgentSession {
|
|
|
3509
2857
|
const files = [];
|
|
3510
2858
|
for (const value of input.files) {
|
|
3511
2859
|
if (typeof value === "string" && value.length > 0) {
|
|
3512
|
-
files.push({
|
|
2860
|
+
files.push({
|
|
2861
|
+
path: this.relativizePath(value) ?? value,
|
|
2862
|
+
kind: this.detectFileKind(value),
|
|
2863
|
+
});
|
|
3513
2864
|
}
|
|
3514
2865
|
}
|
|
3515
2866
|
if (files.length > 0) {
|
|
@@ -3572,11 +2923,7 @@ function hasToolLikeBlock(block) {
|
|
|
3572
2923
|
return type.includes("tool");
|
|
3573
2924
|
}
|
|
3574
2925
|
function readCompactionMetadata(source) {
|
|
3575
|
-
const candidates = [
|
|
3576
|
-
source.compact_metadata,
|
|
3577
|
-
source.compactMetadata,
|
|
3578
|
-
source.compactionMetadata,
|
|
3579
|
-
];
|
|
2926
|
+
const candidates = [source.compact_metadata, source.compactMetadata, source.compactionMetadata];
|
|
3580
2927
|
for (const candidate of candidates) {
|
|
3581
2928
|
if (!candidate || typeof candidate !== "object") {
|
|
3582
2929
|
continue;
|
|
@@ -3602,18 +2949,18 @@ function normalizeHistoryBlocks(content) {
|
|
|
3602
2949
|
export function convertClaudeHistoryEntry(entry, mapBlocks) {
|
|
3603
2950
|
if (entry.type === "system" && entry.subtype === "compact_boundary") {
|
|
3604
2951
|
const compactMetadata = readCompactionMetadata(entry);
|
|
3605
|
-
return [
|
|
2952
|
+
return [
|
|
2953
|
+
{
|
|
3606
2954
|
type: "compaction",
|
|
3607
2955
|
status: "completed",
|
|
3608
2956
|
trigger: compactMetadata?.trigger === "manual" ? "manual" : "auto",
|
|
3609
2957
|
preTokens: compactMetadata?.preTokens,
|
|
3610
|
-
}
|
|
2958
|
+
},
|
|
2959
|
+
];
|
|
3611
2960
|
}
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
return [taskNotificationItem];
|
|
3616
|
-
}
|
|
2961
|
+
const taskNotificationItem = mapTaskNotificationSystemRecordToToolCall(entry);
|
|
2962
|
+
if (taskNotificationItem) {
|
|
2963
|
+
return [taskNotificationItem];
|
|
3617
2964
|
}
|
|
3618
2965
|
if (entry.isCompactSummary) {
|
|
3619
2966
|
return [];
|
|
@@ -3626,10 +2973,12 @@ export function convertClaudeHistoryEntry(entry, mapBlocks) {
|
|
|
3626
2973
|
return [];
|
|
3627
2974
|
}
|
|
3628
2975
|
const content = message.content;
|
|
2976
|
+
if ((entry.type === "user" || entry.type === "assistant") &&
|
|
2977
|
+
isClaudeTranscriptNoiseContent(content)) {
|
|
2978
|
+
return [];
|
|
2979
|
+
}
|
|
3629
2980
|
const normalizedBlocks = normalizeHistoryBlocks(content);
|
|
3630
|
-
const contentValue = typeof content === "string"
|
|
3631
|
-
? content
|
|
3632
|
-
: normalizedBlocks;
|
|
2981
|
+
const contentValue = typeof content === "string" ? content : normalizedBlocks;
|
|
3633
2982
|
const hasToolBlock = normalizedBlocks?.some((block) => hasToolLikeBlock(block)) ?? false;
|
|
3634
2983
|
const userMessageId = entry.type === "user" && typeof entry.uuid === "string" && entry.uuid.length > 0
|
|
3635
2984
|
? entry.uuid
|
|
@@ -3762,9 +3111,7 @@ async function collectRecentClaudeSessions(root, limit) {
|
|
|
3762
3111
|
}
|
|
3763
3112
|
}
|
|
3764
3113
|
}
|
|
3765
|
-
return candidates
|
|
3766
|
-
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())
|
|
3767
|
-
.slice(0, limit);
|
|
3114
|
+
return candidates.sort((a, b) => b.mtime.getTime() - a.mtime.getTime()).slice(0, limit);
|
|
3768
3115
|
}
|
|
3769
3116
|
async function parseClaudeSessionDescriptor(filePath, mtime) {
|
|
3770
3117
|
let content;
|
|
@@ -3847,15 +3194,20 @@ function extractClaudeUserText(message) {
|
|
|
3847
3194
|
return null;
|
|
3848
3195
|
}
|
|
3849
3196
|
if (typeof message.content === "string") {
|
|
3850
|
-
|
|
3197
|
+
const normalized = message.content.trim();
|
|
3198
|
+
return normalized && !isClaudeTranscriptNoiseText(normalized) ? normalized : null;
|
|
3851
3199
|
}
|
|
3852
3200
|
if (typeof message.text === "string") {
|
|
3853
|
-
|
|
3201
|
+
const normalized = message.text.trim();
|
|
3202
|
+
return normalized && !isClaudeTranscriptNoiseText(normalized) ? normalized : null;
|
|
3854
3203
|
}
|
|
3855
3204
|
if (Array.isArray(message.content)) {
|
|
3856
3205
|
for (const block of message.content) {
|
|
3857
3206
|
if (block && typeof block.text === "string") {
|
|
3858
|
-
|
|
3207
|
+
const normalized = block.text.trim();
|
|
3208
|
+
if (normalized && !isClaudeTranscriptNoiseText(normalized)) {
|
|
3209
|
+
return normalized;
|
|
3210
|
+
}
|
|
3859
3211
|
}
|
|
3860
3212
|
}
|
|
3861
3213
|
}
|