@getpaseo/server 0.1.30 → 0.1.33
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 +488 -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 +10 -10
- 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 +1240 -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 +9 -48
- package/dist/server/terminal/terminal.d.ts.map +1 -1
- package/dist/server/terminal/terminal.js +49 -126
- 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 +488 -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 +1240 -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 +49 -126
- 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,13 +1286,14 @@ 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();
|
|
1296
|
+
this.query?.close();
|
|
1474
1297
|
await this.awaitWithTimeout(this.query?.interrupt?.(), "close query interrupt");
|
|
1475
1298
|
await this.awaitWithTimeout(this.query?.return?.(), "close query return");
|
|
1476
1299
|
this.query = null;
|
|
@@ -1512,15 +1335,11 @@ class ClaudeAgentSession {
|
|
|
1512
1335
|
}
|
|
1513
1336
|
const withoutPrefix = trimmed.slice(1);
|
|
1514
1337
|
const firstWhitespaceIdx = withoutPrefix.search(/\s/);
|
|
1515
|
-
const commandName = firstWhitespaceIdx === -1
|
|
1516
|
-
? withoutPrefix
|
|
1517
|
-
: withoutPrefix.slice(0, firstWhitespaceIdx);
|
|
1338
|
+
const commandName = firstWhitespaceIdx === -1 ? withoutPrefix : withoutPrefix.slice(0, firstWhitespaceIdx);
|
|
1518
1339
|
if (!commandName || commandName.includes("/")) {
|
|
1519
1340
|
return null;
|
|
1520
1341
|
}
|
|
1521
|
-
const rawArgs = firstWhitespaceIdx === -1
|
|
1522
|
-
? ""
|
|
1523
|
-
: withoutPrefix.slice(firstWhitespaceIdx + 1).trim();
|
|
1342
|
+
const rawArgs = firstWhitespaceIdx === -1 ? "" : withoutPrefix.slice(firstWhitespaceIdx + 1).trim();
|
|
1524
1343
|
return rawArgs.length > 0
|
|
1525
1344
|
? { commandName, args: rawArgs, rawInput: trimmed }
|
|
1526
1345
|
: { commandName, rawInput: trimmed };
|
|
@@ -1552,9 +1371,7 @@ class ClaudeAgentSession {
|
|
|
1552
1371
|
yield {
|
|
1553
1372
|
type: "turn_failed",
|
|
1554
1373
|
provider: "claude",
|
|
1555
|
-
error: error instanceof Error
|
|
1556
|
-
? error.message
|
|
1557
|
-
: "Failed to rewind tracked files",
|
|
1374
|
+
error: error instanceof Error ? error.message : "Failed to rewind tracked files",
|
|
1558
1375
|
};
|
|
1559
1376
|
}
|
|
1560
1377
|
}
|
|
@@ -1592,8 +1409,7 @@ class ClaudeAgentSession {
|
|
|
1592
1409
|
}
|
|
1593
1410
|
return {
|
|
1594
1411
|
messageId: null,
|
|
1595
|
-
error: rewindResult.error ??
|
|
1596
|
-
`No file checkpoint found for message ${candidate}.`,
|
|
1412
|
+
error: rewindResult.error ?? `No file checkpoint found for message ${candidate}.`,
|
|
1597
1413
|
};
|
|
1598
1414
|
}
|
|
1599
1415
|
const candidates = this.getRewindCandidateUserMessageIds();
|
|
@@ -1615,16 +1431,12 @@ class ClaudeAgentSession {
|
|
|
1615
1431
|
}
|
|
1616
1432
|
}
|
|
1617
1433
|
catch (error) {
|
|
1618
|
-
lastError =
|
|
1619
|
-
error instanceof Error
|
|
1620
|
-
? error.message
|
|
1621
|
-
: "Failed to rewind tracked files.";
|
|
1434
|
+
lastError = error instanceof Error ? error.message : "Failed to rewind tracked files.";
|
|
1622
1435
|
}
|
|
1623
1436
|
}
|
|
1624
1437
|
return {
|
|
1625
1438
|
messageId: null,
|
|
1626
|
-
error: lastError ??
|
|
1627
|
-
"No rewind checkpoints are currently available for this session.",
|
|
1439
|
+
error: lastError ?? "No rewind checkpoints are currently available for this session.",
|
|
1628
1440
|
};
|
|
1629
1441
|
}
|
|
1630
1442
|
async rewindFilesOnce(messageId) {
|
|
@@ -1648,9 +1460,7 @@ class ClaudeAgentSession {
|
|
|
1648
1460
|
getRewindCandidateUserMessageIds() {
|
|
1649
1461
|
const candidates = [];
|
|
1650
1462
|
const pushUnique = (value) => {
|
|
1651
|
-
if (typeof value === "string" &&
|
|
1652
|
-
value.length > 0 &&
|
|
1653
|
-
!candidates.includes(value)) {
|
|
1463
|
+
if (typeof value === "string" && value.length > 0 && !candidates.includes(value)) {
|
|
1654
1464
|
candidates.push(value);
|
|
1655
1465
|
}
|
|
1656
1466
|
};
|
|
@@ -1716,10 +1526,13 @@ class ClaudeAgentSession {
|
|
|
1716
1526
|
}
|
|
1717
1527
|
if (this.queryRestartNeeded && this.query) {
|
|
1718
1528
|
this.input?.end();
|
|
1529
|
+
this.query.close();
|
|
1719
1530
|
try {
|
|
1720
1531
|
await this.query.return?.();
|
|
1721
1532
|
}
|
|
1722
|
-
catch {
|
|
1533
|
+
catch {
|
|
1534
|
+
/* ignore */
|
|
1535
|
+
}
|
|
1723
1536
|
this.query = null;
|
|
1724
1537
|
this.input = null;
|
|
1725
1538
|
this.queryRestartNeeded = false;
|
|
@@ -1851,7 +1664,6 @@ class ClaudeAgentSession {
|
|
|
1851
1664
|
}
|
|
1852
1665
|
const messageId = randomUUID();
|
|
1853
1666
|
this.rememberUserMessageId(messageId);
|
|
1854
|
-
this.localUserMessageIds.add(messageId);
|
|
1855
1667
|
return {
|
|
1856
1668
|
type: "user",
|
|
1857
1669
|
message: {
|
|
@@ -1863,24 +1675,6 @@ class ClaudeAgentSession {
|
|
|
1863
1675
|
session_id: this.claudeSessionId ?? "",
|
|
1864
1676
|
};
|
|
1865
1677
|
}
|
|
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
1678
|
transitionTurnState(next, reason) {
|
|
1885
1679
|
if (this.turnState === next) {
|
|
1886
1680
|
return;
|
|
@@ -1888,20 +1682,17 @@ class ClaudeAgentSession {
|
|
|
1888
1682
|
this.logger.debug({ from: this.turnState, to: next, reason }, "Claude turn state transition");
|
|
1889
1683
|
this.turnState = next;
|
|
1890
1684
|
}
|
|
1891
|
-
|
|
1892
|
-
if (this.
|
|
1685
|
+
syncTurnState(reason) {
|
|
1686
|
+
if (this.activeForegroundTurn) {
|
|
1893
1687
|
this.transitionTurnState("foreground", reason);
|
|
1894
1688
|
return;
|
|
1895
1689
|
}
|
|
1896
|
-
if (this.
|
|
1690
|
+
if (this.autonomousTurn) {
|
|
1897
1691
|
this.transitionTurnState("autonomous", reason);
|
|
1898
1692
|
return;
|
|
1899
1693
|
}
|
|
1900
1694
|
this.transitionTurnState("idle", reason);
|
|
1901
1695
|
}
|
|
1902
|
-
failRun(run, errorMessage) {
|
|
1903
|
-
this.emitRunEvent(run, this.buildTurnFailedEvent(errorMessage));
|
|
1904
|
-
}
|
|
1905
1696
|
buildTurnFailedEvent(errorMessage) {
|
|
1906
1697
|
const normalized = errorMessage.trim() || "Claude run failed";
|
|
1907
1698
|
const exitCodeMatch = normalized.match(/\bcode\s+(\d+)\b/i);
|
|
@@ -1927,274 +1718,106 @@ class ClaudeAgentSession {
|
|
|
1927
1718
|
this.recentStderr = "";
|
|
1928
1719
|
}
|
|
1929
1720
|
getRecentStderrDiagnostic() {
|
|
1930
|
-
|
|
1931
|
-
return text.length > 0 ? text : undefined;
|
|
1721
|
+
return this.recentStderr.trim() || undefined;
|
|
1932
1722
|
}
|
|
1933
|
-
|
|
1934
|
-
this.
|
|
1935
|
-
this.emitRunEvent(run, event);
|
|
1723
|
+
createTurnId(owner) {
|
|
1724
|
+
return `${owner}-turn-${this.nextTurnOrdinal++}`;
|
|
1936
1725
|
}
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
event.type === "turn_completed" ||
|
|
1726
|
+
isTerminalTurnEvent(event) {
|
|
1727
|
+
return (event.type === "turn_completed" ||
|
|
1940
1728
|
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);
|
|
1729
|
+
event.type === "turn_canceled");
|
|
1962
1730
|
}
|
|
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;
|
|
1731
|
+
shouldRecoverInterruptedQueryAbort(error, consecutiveRecoveries) {
|
|
1732
|
+
if (consecutiveRecoveries >= 3) {
|
|
1733
|
+
return false;
|
|
1975
1734
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1735
|
+
const message = typeof error === "string"
|
|
1736
|
+
? error
|
|
1737
|
+
: error instanceof Error
|
|
1738
|
+
? `${error.message}\n${error.stack ?? ""}`
|
|
1739
|
+
: JSON.stringify(error);
|
|
1740
|
+
return message.toLowerCase().includes("request was aborted");
|
|
1741
|
+
}
|
|
1742
|
+
finishForegroundTurn(event) {
|
|
1743
|
+
if (event.type === "turn_failed" || event.type === "turn_canceled") {
|
|
1744
|
+
this.flushPendingToolCalls();
|
|
1979
1745
|
}
|
|
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`);
|
|
1746
|
+
this.dispatchForegroundEvents([event]);
|
|
1988
1747
|
}
|
|
1989
|
-
|
|
1990
|
-
const
|
|
1991
|
-
if (
|
|
1992
|
-
this.
|
|
1748
|
+
dispatchForegroundEvents(events) {
|
|
1749
|
+
const foregroundTurn = this.activeForegroundTurn;
|
|
1750
|
+
if (!foregroundTurn) {
|
|
1751
|
+
this.dispatchLiveEvents(events);
|
|
1993
1752
|
return;
|
|
1994
1753
|
}
|
|
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;
|
|
1754
|
+
let terminalSeen = false;
|
|
1755
|
+
for (const event of events) {
|
|
1756
|
+
foregroundTurn.queue.push(event);
|
|
1757
|
+
terminalSeen || (terminalSeen = this.isTerminalTurnEvent(event));
|
|
2108
1758
|
}
|
|
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;
|
|
1759
|
+
if (!terminalSeen) {
|
|
1760
|
+
return;
|
|
2127
1761
|
}
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
1762
|
+
foregroundTurn.queue.end();
|
|
1763
|
+
if (this.activeForegroundTurn === foregroundTurn) {
|
|
1764
|
+
this.activeForegroundTurn = null;
|
|
2131
1765
|
}
|
|
2132
|
-
|
|
1766
|
+
this.syncTurnState("foreground turn terminal");
|
|
2133
1767
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
1768
|
+
dispatchLiveEvents(events) {
|
|
1769
|
+
let terminalSeen = false;
|
|
1770
|
+
for (const event of events) {
|
|
1771
|
+
this.liveEventQueue.push(event);
|
|
1772
|
+
terminalSeen || (terminalSeen = this.isTerminalTurnEvent(event));
|
|
2137
1773
|
}
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
1774
|
+
if (terminalSeen && this.autonomousTurn) {
|
|
1775
|
+
this.autonomousTurn = null;
|
|
1776
|
+
this.syncTurnState("autonomous turn terminal");
|
|
2141
1777
|
}
|
|
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
1778
|
}
|
|
2147
|
-
|
|
2148
|
-
if (this.
|
|
1779
|
+
startAutonomousTurn() {
|
|
1780
|
+
if (this.autonomousTurn) {
|
|
2149
1781
|
return;
|
|
2150
1782
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
1783
|
+
this.autonomousTurn = {
|
|
1784
|
+
id: this.createTurnId("autonomous"),
|
|
1785
|
+
};
|
|
1786
|
+
this.liveEventQueue.push({ type: "turn_started", provider: "claude" });
|
|
1787
|
+
this.syncTurnState("autonomous turn started");
|
|
1788
|
+
}
|
|
1789
|
+
completeAutonomousTurn() {
|
|
1790
|
+
if (!this.autonomousTurn) {
|
|
2155
1791
|
return;
|
|
2156
1792
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
1793
|
+
this.autonomousTurn = null;
|
|
1794
|
+
this.liveEventQueue.push({ type: "turn_completed", provider: "claude" });
|
|
1795
|
+
this.syncTurnState("autonomous turn completed");
|
|
1796
|
+
}
|
|
1797
|
+
cancelAutonomousTurn(reason) {
|
|
1798
|
+
if (!this.autonomousTurn) {
|
|
2163
1799
|
return;
|
|
2164
1800
|
}
|
|
2165
|
-
this.
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
1801
|
+
this.flushPendingToolCalls();
|
|
1802
|
+
this.autonomousTurn = null;
|
|
1803
|
+
this.liveEventQueue.push({
|
|
1804
|
+
type: "turn_canceled",
|
|
1805
|
+
provider: "claude",
|
|
2170
1806
|
reason,
|
|
2171
|
-
|
|
2172
|
-
|
|
1807
|
+
});
|
|
1808
|
+
this.syncTurnState("autonomous turn canceled");
|
|
2173
1809
|
}
|
|
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;
|
|
1810
|
+
failActiveTurns(errorMessage) {
|
|
1811
|
+
const failure = this.buildTurnFailedEvent(errorMessage);
|
|
1812
|
+
if (this.activeForegroundTurn) {
|
|
1813
|
+
this.flushPendingToolCalls();
|
|
1814
|
+
this.dispatchForegroundEvents([failure]);
|
|
1815
|
+
return;
|
|
2186
1816
|
}
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
this.pendingAutonomousWakeReservations -= 1;
|
|
1817
|
+
if (this.autonomousTurn) {
|
|
1818
|
+
this.flushPendingToolCalls();
|
|
1819
|
+
this.dispatchLiveEvents([failure]);
|
|
2191
1820
|
}
|
|
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
1821
|
}
|
|
2199
1822
|
startQueryPump() {
|
|
2200
1823
|
if (this.closed || this.queryPumpPromise) {
|
|
@@ -2211,139 +1834,83 @@ class ClaudeAgentSession {
|
|
|
2211
1834
|
});
|
|
2212
1835
|
}
|
|
2213
1836
|
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;
|
|
1837
|
+
let activeQuery;
|
|
1838
|
+
try {
|
|
1839
|
+
activeQuery = await this.ensureQuery();
|
|
1840
|
+
}
|
|
1841
|
+
catch (error) {
|
|
1842
|
+
this.logger.trace({ err: error }, "Failed to initialize Claude query pump");
|
|
1843
|
+
this.failActiveTurns(error instanceof Error ? error.message : "Claude stream failed");
|
|
1844
|
+
return;
|
|
1845
|
+
}
|
|
1846
|
+
let consecutiveInterruptAbortRecoveries = 0;
|
|
1847
|
+
try {
|
|
1848
|
+
while (!this.closed && this.query === activeQuery) {
|
|
1849
|
+
try {
|
|
1850
|
+
for await (const message of activeQuery) {
|
|
1851
|
+
consecutiveInterruptAbortRecoveries = 0;
|
|
1852
|
+
if (await this.handleMissingResumedConversation(message, activeQuery)) {
|
|
1853
|
+
return;
|
|
1854
|
+
}
|
|
1855
|
+
this.routeSdkMessageFromPump(message);
|
|
1856
|
+
}
|
|
1857
|
+
if (!this.closed && this.query === activeQuery) {
|
|
1858
|
+
this.failActiveTurns("Claude stream ended before terminal result");
|
|
1859
|
+
}
|
|
1860
|
+
return;
|
|
2271
1861
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
this.
|
|
1862
|
+
catch (error) {
|
|
1863
|
+
if (!this.closed &&
|
|
1864
|
+
this.query === activeQuery &&
|
|
1865
|
+
this.shouldRecoverInterruptedQueryAbort(error, consecutiveInterruptAbortRecoveries)) {
|
|
1866
|
+
consecutiveInterruptAbortRecoveries += 1;
|
|
1867
|
+
this.logger.debug({ recoveries: consecutiveInterruptAbortRecoveries }, "Recovering Claude query pump after interrupt abort");
|
|
1868
|
+
continue;
|
|
2276
1869
|
}
|
|
1870
|
+
if (!this.closed && this.query === activeQuery) {
|
|
1871
|
+
this.failActiveTurns(error instanceof Error ? error.message : "Claude stream failed");
|
|
1872
|
+
}
|
|
1873
|
+
return;
|
|
2277
1874
|
}
|
|
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
1875
|
}
|
|
2300
|
-
|
|
2301
|
-
|
|
1876
|
+
}
|
|
1877
|
+
finally {
|
|
1878
|
+
if (this.query === activeQuery) {
|
|
1879
|
+
this.query = null;
|
|
1880
|
+
this.input = null;
|
|
2302
1881
|
}
|
|
2303
1882
|
}
|
|
2304
1883
|
}
|
|
2305
1884
|
routeSdkMessageFromPump(message) {
|
|
2306
|
-
|
|
1885
|
+
const routeToForeground = Boolean(this.activeForegroundTurn);
|
|
1886
|
+
const assistantishMessage = message.type === "assistant" ||
|
|
1887
|
+
message.type === "stream_event" ||
|
|
1888
|
+
message.type === "tool_progress";
|
|
1889
|
+
if (!routeToForeground && assistantishMessage) {
|
|
1890
|
+
this.startAutonomousTurn();
|
|
1891
|
+
}
|
|
1892
|
+
if (!routeToForeground && !this.autonomousTurn && message.type === "result") {
|
|
2307
1893
|
return;
|
|
2308
1894
|
}
|
|
1895
|
+
const turnId = this.activeForegroundTurn?.id ?? this.autonomousTurn?.id ?? null;
|
|
2309
1896
|
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
1897
|
this.logger.trace({
|
|
2321
1898
|
claudeSessionId: this.claudeSessionId,
|
|
2322
1899
|
messageType: message.type,
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
runOwner: route.run?.owner ?? null,
|
|
2326
|
-
suppressTerminalEvents,
|
|
2327
|
-
metadataOnly,
|
|
1900
|
+
routedTo: routeToForeground ? "foreground_queue" : "live_queue",
|
|
1901
|
+
turnId,
|
|
2328
1902
|
}, "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
1903
|
const messageEvents = this.translateMessageToEvents(message, {
|
|
2337
1904
|
suppressAssistantText: true,
|
|
2338
1905
|
suppressReasoning: true,
|
|
2339
|
-
suppressTerminalEvents,
|
|
2340
1906
|
});
|
|
2341
|
-
const
|
|
1907
|
+
const assistantTimelineEvents = this.timelineAssembler
|
|
1908
|
+
.consume({
|
|
2342
1909
|
message,
|
|
2343
|
-
runId:
|
|
1910
|
+
runId: turnId,
|
|
2344
1911
|
messageIdHint: identifiers.messageId,
|
|
2345
|
-
})
|
|
2346
|
-
|
|
1912
|
+
})
|
|
1913
|
+
.map((item) => ({
|
|
2347
1914
|
type: "timeline",
|
|
2348
1915
|
item,
|
|
2349
1916
|
provider: "claude",
|
|
@@ -2352,16 +1919,26 @@ class ClaudeAgentSession {
|
|
|
2352
1919
|
if (events.length === 0) {
|
|
2353
1920
|
return;
|
|
2354
1921
|
}
|
|
2355
|
-
if (
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
this.
|
|
1922
|
+
if (this.pendingInterruptAbort &&
|
|
1923
|
+
message.type === "result" &&
|
|
1924
|
+
events.some((event) => event.type === "turn_completed" || event.type === "turn_failed") &&
|
|
1925
|
+
(!this.activeForegroundTurn || !this.activeForegroundTurn.hasVisibleActivity)) {
|
|
1926
|
+
this.pendingInterruptAbort = false;
|
|
1927
|
+
this.logger.debug("Suppressing stale Claude interrupt terminal result");
|
|
2360
1928
|
return;
|
|
2361
1929
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
1930
|
+
if (this.activeForegroundTurn &&
|
|
1931
|
+
events.some((event) => event.type === "timeline" ||
|
|
1932
|
+
event.type === "permission_requested" ||
|
|
1933
|
+
event.type === "permission_resolved")) {
|
|
1934
|
+
this.activeForegroundTurn.hasVisibleActivity = true;
|
|
1935
|
+
this.pendingInterruptAbort = false;
|
|
1936
|
+
}
|
|
1937
|
+
if (routeToForeground) {
|
|
1938
|
+
this.dispatchForegroundEvents(events);
|
|
1939
|
+
return;
|
|
2364
1940
|
}
|
|
1941
|
+
this.dispatchLiveEvents(events);
|
|
2365
1942
|
}
|
|
2366
1943
|
async handleMissingResumedConversation(message, query) {
|
|
2367
1944
|
const staleResumeError = this.readMissingResumedConversationError(message);
|
|
@@ -2372,10 +1949,7 @@ class ClaudeAgentSession {
|
|
|
2372
1949
|
claudeSessionId: this.claudeSessionId,
|
|
2373
1950
|
error: staleResumeError,
|
|
2374
1951
|
}, "Claude resumed session no longer exists; invalidating persisted session");
|
|
2375
|
-
|
|
2376
|
-
this.failRun(run, staleResumeError);
|
|
2377
|
-
}
|
|
2378
|
-
this.transitionTurnStateFromActiveRuns("missing resumed conversation");
|
|
1952
|
+
this.failActiveTurns(staleResumeError);
|
|
2379
1953
|
this.input?.end();
|
|
2380
1954
|
await this.awaitWithTimeout(query.return?.(), "query pump return on missing resumed conversation");
|
|
2381
1955
|
if (this.query === query) {
|
|
@@ -2386,373 +1960,36 @@ class ClaudeAgentSession {
|
|
|
2386
1960
|
this.persistence = null;
|
|
2387
1961
|
this.persistedHistory = [];
|
|
2388
1962
|
this.historyPending = false;
|
|
1963
|
+
this.historyOffsetSessionId = null;
|
|
1964
|
+
this.historyReadOffsetBytes = 0;
|
|
1965
|
+
this.historyLineFragment = "";
|
|
2389
1966
|
this.cachedRuntimeInfo = null;
|
|
2390
1967
|
this.queryRestartNeeded = false;
|
|
1968
|
+
this.autonomousTurn = null;
|
|
1969
|
+
this.activeForegroundTurn = null;
|
|
1970
|
+
this.syncTurnState("missing resumed conversation");
|
|
2391
1971
|
return true;
|
|
2392
1972
|
}
|
|
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
1973
|
async interruptActiveTurn() {
|
|
2509
1974
|
const queryToInterrupt = this.query;
|
|
2510
1975
|
if (!queryToInterrupt || typeof queryToInterrupt.interrupt !== "function") {
|
|
2511
1976
|
this.logger.trace("interruptActiveTurn: no query to interrupt");
|
|
2512
1977
|
return;
|
|
2513
1978
|
}
|
|
1979
|
+
this.pendingInterruptAbort = true;
|
|
2514
1980
|
try {
|
|
2515
|
-
this.logger.trace("interruptActiveTurn: calling query.interrupt()...");
|
|
2516
1981
|
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
1982
|
}
|
|
2524
1983
|
catch (error) {
|
|
2525
1984
|
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
1985
|
}
|
|
2721
1986
|
}
|
|
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
1987
|
translateMessageToEvents(message, options) {
|
|
2751
1988
|
const parentToolUseId = "parent_tool_use_id" in message
|
|
2752
1989
|
? message.parent_tool_use_id
|
|
2753
1990
|
: null;
|
|
2754
1991
|
if (parentToolUseId) {
|
|
2755
|
-
return this.
|
|
1992
|
+
return this.sidechainTracker.handleMessage(message, parentToolUseId);
|
|
2756
1993
|
}
|
|
2757
1994
|
const events = [];
|
|
2758
1995
|
const fallbackThreadSessionId = this.captureSessionIdFromMessage(message);
|
|
@@ -2818,9 +2055,7 @@ class ClaudeAgentSession {
|
|
|
2818
2055
|
this.compacting = false;
|
|
2819
2056
|
break;
|
|
2820
2057
|
}
|
|
2821
|
-
const messageId = typeof message.uuid === "string" && message.uuid.length > 0
|
|
2822
|
-
? message.uuid
|
|
2823
|
-
: undefined;
|
|
2058
|
+
const messageId = typeof message.uuid === "string" && message.uuid.length > 0 ? message.uuid : undefined;
|
|
2824
2059
|
this.rememberUserMessageId(messageId);
|
|
2825
2060
|
const content = message.message?.content;
|
|
2826
2061
|
const taskNotificationItem = mapTaskNotificationUserContentToToolCall({
|
|
@@ -2836,19 +2071,22 @@ class ClaudeAgentSession {
|
|
|
2836
2071
|
break;
|
|
2837
2072
|
}
|
|
2838
2073
|
if (typeof content === "string" && content.length > 0) {
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2074
|
+
if (!isClaudeTranscriptNoiseText(content)) {
|
|
2075
|
+
events.push({
|
|
2076
|
+
type: "timeline",
|
|
2077
|
+
item: {
|
|
2078
|
+
type: "user_message",
|
|
2079
|
+
text: content,
|
|
2080
|
+
...(messageId ? { messageId } : {}),
|
|
2081
|
+
},
|
|
2082
|
+
provider: "claude",
|
|
2083
|
+
});
|
|
2084
|
+
}
|
|
2849
2085
|
}
|
|
2850
2086
|
else if (Array.isArray(content)) {
|
|
2851
|
-
const timelineItems = this.mapBlocksToTimeline(content
|
|
2087
|
+
const timelineItems = this.mapBlocksToTimeline(content, {
|
|
2088
|
+
textMessageType: "user_message",
|
|
2089
|
+
});
|
|
2852
2090
|
for (const item of timelineItems) {
|
|
2853
2091
|
if (item.type === "user_message" && messageId && !item.messageId) {
|
|
2854
2092
|
events.push({
|
|
@@ -2884,9 +2122,6 @@ class ClaudeAgentSession {
|
|
|
2884
2122
|
break;
|
|
2885
2123
|
}
|
|
2886
2124
|
case "result": {
|
|
2887
|
-
if (options?.suppressTerminalEvents) {
|
|
2888
|
-
break;
|
|
2889
|
-
}
|
|
2890
2125
|
const usage = this.convertUsage(message);
|
|
2891
2126
|
if (message.subtype === "success") {
|
|
2892
2127
|
events.push({ type: "turn_completed", provider: "claude", usage });
|
|
@@ -2948,18 +2183,14 @@ class ClaudeAgentSession {
|
|
|
2948
2183
|
const existingSessionId = this.claudeSessionId;
|
|
2949
2184
|
let threadStartedSessionId = null;
|
|
2950
2185
|
if (existingSessionId === null) {
|
|
2951
|
-
// First time setting session ID (empty → filled) - this is expected
|
|
2952
2186
|
this.claudeSessionId = newSessionId;
|
|
2953
2187
|
threadStartedSessionId = newSessionId;
|
|
2954
2188
|
this.logger.debug({ sessionId: newSessionId }, "Claude session ID set for the first time");
|
|
2955
2189
|
}
|
|
2956
2190
|
else if (existingSessionId === newSessionId) {
|
|
2957
|
-
// Same session ID - no-op, but log for visibility
|
|
2958
2191
|
this.logger.debug({ sessionId: newSessionId }, "Claude session ID unchanged (same value)");
|
|
2959
2192
|
}
|
|
2960
2193
|
else {
|
|
2961
|
-
// CRITICAL: Session ID is being overwritten with a different value
|
|
2962
|
-
// This should NEVER happen and indicates a serious bug
|
|
2963
2194
|
throw new Error(`CRITICAL: Claude session ID overwrite detected! ` +
|
|
2964
2195
|
`Existing: ${existingSessionId}, New: ${newSessionId}. ` +
|
|
2965
2196
|
`This indicates a session identity corruption bug.`);
|
|
@@ -2967,7 +2198,6 @@ class ClaudeAgentSession {
|
|
|
2967
2198
|
this.availableModes = DEFAULT_MODES;
|
|
2968
2199
|
this.currentMode = message.permissionMode;
|
|
2969
2200
|
this.persistence = null;
|
|
2970
|
-
// Capture actual model from SDK init message (not just the configured model)
|
|
2971
2201
|
if (message.model) {
|
|
2972
2202
|
const normalizedModel = normalizeClaudeRuntimeModelId({
|
|
2973
2203
|
runtimeModelId: message.model,
|
|
@@ -2978,7 +2208,6 @@ class ClaudeAgentSession {
|
|
|
2978
2208
|
});
|
|
2979
2209
|
this.logger.debug({ model: message.model, normalizedModel }, "Captured model from SDK init");
|
|
2980
2210
|
this.lastOptionsModel = normalizedModel;
|
|
2981
|
-
// Invalidate cached runtime info so it picks up the new model
|
|
2982
2211
|
this.cachedRuntimeInfo = null;
|
|
2983
2212
|
}
|
|
2984
2213
|
return threadStartedSessionId;
|
|
@@ -3031,7 +2260,7 @@ class ClaudeAgentSession {
|
|
|
3031
2260
|
}
|
|
3032
2261
|
}
|
|
3033
2262
|
this.toolUseCache.clear();
|
|
3034
|
-
this.
|
|
2263
|
+
this.sidechainTracker.clear();
|
|
3035
2264
|
}
|
|
3036
2265
|
pushToolCall(item, target) {
|
|
3037
2266
|
if (!item) {
|
|
@@ -3046,15 +2275,8 @@ class ClaudeAgentSession {
|
|
|
3046
2275
|
pushEvent(event) {
|
|
3047
2276
|
const foregroundTurn = this.activeForegroundTurn;
|
|
3048
2277
|
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;
|
|
2278
|
+
foregroundTurn.queue.push(event);
|
|
2279
|
+
return;
|
|
3058
2280
|
}
|
|
3059
2281
|
this.liveEventQueue.push(event);
|
|
3060
2282
|
}
|
|
@@ -3072,47 +2294,125 @@ class ClaudeAgentSession {
|
|
|
3072
2294
|
this.pendingPermissions.delete(id);
|
|
3073
2295
|
}
|
|
3074
2296
|
}
|
|
3075
|
-
|
|
3076
|
-
return new Promise((resolve) => setTimeout(resolve, 250));
|
|
3077
|
-
}
|
|
3078
|
-
loadPersistedHistory(sessionId) {
|
|
2297
|
+
loadPersistedHistory(sessionId, options) {
|
|
3079
2298
|
try {
|
|
3080
2299
|
const historyPath = this.resolveHistoryPath(sessionId);
|
|
3081
2300
|
if (!historyPath || !fs.existsSync(historyPath)) {
|
|
3082
2301
|
return;
|
|
3083
2302
|
}
|
|
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
|
-
}
|
|
2303
|
+
if (this.historyOffsetSessionId !== sessionId) {
|
|
2304
|
+
this.historyOffsetSessionId = sessionId;
|
|
2305
|
+
this.historyReadOffsetBytes = 0;
|
|
2306
|
+
this.historyLineFragment = "";
|
|
3106
2307
|
}
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
this.
|
|
2308
|
+
const content = fs.readFileSync(historyPath);
|
|
2309
|
+
if (content.byteLength < this.historyReadOffsetBytes) {
|
|
2310
|
+
this.historyReadOffsetBytes = 0;
|
|
2311
|
+
this.historyLineFragment = "";
|
|
3110
2312
|
}
|
|
2313
|
+
if (content.byteLength === this.historyReadOffsetBytes) {
|
|
2314
|
+
return;
|
|
2315
|
+
}
|
|
2316
|
+
const unreadChunk = content.subarray(this.historyReadOffsetBytes).toString("utf8");
|
|
2317
|
+
this.historyReadOffsetBytes = content.byteLength;
|
|
2318
|
+
this.ingestPersistedHistoryChunk(unreadChunk, {
|
|
2319
|
+
dispatchLive: options?.dispatchLive ?? false,
|
|
2320
|
+
});
|
|
3111
2321
|
}
|
|
3112
2322
|
catch (error) {
|
|
3113
2323
|
// ignore history load failures
|
|
3114
2324
|
}
|
|
3115
2325
|
}
|
|
2326
|
+
ingestPersistedHistoryChunk(chunk, options) {
|
|
2327
|
+
if (!chunk) {
|
|
2328
|
+
return;
|
|
2329
|
+
}
|
|
2330
|
+
const combined = `${this.historyLineFragment}${chunk}`;
|
|
2331
|
+
this.historyLineFragment = "";
|
|
2332
|
+
const lines = combined.split(/\r?\n/);
|
|
2333
|
+
const trailing = lines.pop() ?? "";
|
|
2334
|
+
const timeline = [];
|
|
2335
|
+
for (const line of lines) {
|
|
2336
|
+
this.ingestPersistedHistoryLine(line, {
|
|
2337
|
+
dispatchLive: options.dispatchLive,
|
|
2338
|
+
timeline,
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
if (trailing.trim().length > 0) {
|
|
2342
|
+
const handled = this.ingestPersistedHistoryLine(trailing, {
|
|
2343
|
+
dispatchLive: options.dispatchLive,
|
|
2344
|
+
timeline,
|
|
2345
|
+
});
|
|
2346
|
+
if (!handled) {
|
|
2347
|
+
this.historyLineFragment = trailing;
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
if (!options.dispatchLive && timeline.length > 0) {
|
|
2351
|
+
this.persistedHistory = [...this.persistedHistory, ...timeline];
|
|
2352
|
+
this.historyPending = true;
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
ingestPersistedHistoryLine(line, options) {
|
|
2356
|
+
const trimmed = line.trim();
|
|
2357
|
+
if (!trimmed) {
|
|
2358
|
+
return true;
|
|
2359
|
+
}
|
|
2360
|
+
let entry;
|
|
2361
|
+
try {
|
|
2362
|
+
entry = JSON.parse(trimmed);
|
|
2363
|
+
}
|
|
2364
|
+
catch {
|
|
2365
|
+
return false;
|
|
2366
|
+
}
|
|
2367
|
+
if (entry.isSidechain) {
|
|
2368
|
+
return true;
|
|
2369
|
+
}
|
|
2370
|
+
if (entry.type === "user" && typeof entry.uuid === "string") {
|
|
2371
|
+
this.rememberUserMessageId(entry.uuid);
|
|
2372
|
+
}
|
|
2373
|
+
if (options.dispatchLive) {
|
|
2374
|
+
this.dispatchPersistedHistoryEntry(entry);
|
|
2375
|
+
return true;
|
|
2376
|
+
}
|
|
2377
|
+
const items = this.convertHistoryEntry(entry);
|
|
2378
|
+
if (items.length > 0) {
|
|
2379
|
+
options.timeline.push(...items);
|
|
2380
|
+
}
|
|
2381
|
+
return true;
|
|
2382
|
+
}
|
|
2383
|
+
dispatchPersistedHistoryEntry(entry) {
|
|
2384
|
+
const liveMessage = this.normalizePersistedHistoryEntryToLiveMessage(entry);
|
|
2385
|
+
if (liveMessage) {
|
|
2386
|
+
this.routeSdkMessageFromPump(liveMessage);
|
|
2387
|
+
return;
|
|
2388
|
+
}
|
|
2389
|
+
const items = this.convertHistoryEntry(entry);
|
|
2390
|
+
for (const item of items) {
|
|
2391
|
+
this.pushEvent({
|
|
2392
|
+
type: "timeline",
|
|
2393
|
+
item,
|
|
2394
|
+
provider: "claude",
|
|
2395
|
+
});
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
normalizePersistedHistoryEntryToLiveMessage(entry) {
|
|
2399
|
+
const taskNotificationMessage = coerceTaskNotificationHistoryRecordToSystemMessage(entry);
|
|
2400
|
+
if (taskNotificationMessage) {
|
|
2401
|
+
return taskNotificationMessage;
|
|
2402
|
+
}
|
|
2403
|
+
const type = readTrimmedString(entry.type);
|
|
2404
|
+
switch (type) {
|
|
2405
|
+
case "assistant":
|
|
2406
|
+
case "result":
|
|
2407
|
+
case "stream_event":
|
|
2408
|
+
case "system":
|
|
2409
|
+
case "tool_progress":
|
|
2410
|
+
case "user":
|
|
2411
|
+
return entry;
|
|
2412
|
+
default:
|
|
2413
|
+
return null;
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
3116
2416
|
resolveHistoryPath(sessionId) {
|
|
3117
2417
|
const cwd = this.config.cwd;
|
|
3118
2418
|
if (!cwd)
|
|
@@ -3126,25 +2426,50 @@ class ClaudeAgentSession {
|
|
|
3126
2426
|
convertHistoryEntry(entry) {
|
|
3127
2427
|
return convertClaudeHistoryEntry(entry, (content) => this.mapBlocksToTimeline(content));
|
|
3128
2428
|
}
|
|
2429
|
+
// Maps Claude content blocks into AgentTimelineItems.
|
|
2430
|
+
//
|
|
2431
|
+
// textMessageType controls what type text blocks emit:
|
|
2432
|
+
// - "assistant_message" (default): one item per text block (streaming granularity)
|
|
2433
|
+
// - "user_message": coalesces all text blocks into a single user_message
|
|
2434
|
+
// (matches extractUserMessageText semantics: trim each block, join with "\n\n")
|
|
2435
|
+
//
|
|
2436
|
+
// suppressAssistantText only applies when textMessageType is "assistant_message" — user text
|
|
2437
|
+
// must never be suppressed since the TimelineAssembler only handles assistant text.
|
|
2438
|
+
//
|
|
2439
|
+
// NOTE: convertClaudeHistoryEntry uses extractUserMessageText directly instead of this function
|
|
2440
|
+
// for user entries. Both paths must produce equivalent user_message items.
|
|
3129
2441
|
mapBlocksToTimeline(content, options) {
|
|
3130
|
-
const
|
|
2442
|
+
const textMessageType = options?.textMessageType ?? "assistant_message";
|
|
2443
|
+
const suppressText = textMessageType === "assistant_message" && (options?.suppressAssistantText ?? false);
|
|
3131
2444
|
const suppressReasoning = options?.suppressReasoning ?? false;
|
|
3132
2445
|
if (typeof content === "string") {
|
|
3133
|
-
if (!content ||
|
|
2446
|
+
if (!content ||
|
|
2447
|
+
content === INTERRUPT_TOOL_USE_PLACEHOLDER ||
|
|
2448
|
+
isClaudeTranscriptNoiseText(content)) {
|
|
3134
2449
|
return [];
|
|
3135
2450
|
}
|
|
3136
|
-
if (
|
|
2451
|
+
if (suppressText) {
|
|
3137
2452
|
return [];
|
|
3138
2453
|
}
|
|
3139
|
-
return [{ type:
|
|
2454
|
+
return [{ type: textMessageType, text: content }];
|
|
3140
2455
|
}
|
|
3141
2456
|
const items = [];
|
|
2457
|
+
// User SDK entries can arrive as multiple text blocks, but Paseo treats them as one message.
|
|
2458
|
+
const userTextParts = [];
|
|
3142
2459
|
for (const block of content) {
|
|
3143
2460
|
switch (block.type) {
|
|
3144
2461
|
case "text":
|
|
3145
2462
|
case "text_delta":
|
|
3146
|
-
if (block.text &&
|
|
3147
|
-
|
|
2463
|
+
if (block.text &&
|
|
2464
|
+
block.text !== INTERRUPT_TOOL_USE_PLACEHOLDER &&
|
|
2465
|
+
!isClaudeTranscriptNoiseText(block.text)) {
|
|
2466
|
+
if (textMessageType === "user_message") {
|
|
2467
|
+
const trimmed = block.text.trim();
|
|
2468
|
+
if (trimmed) {
|
|
2469
|
+
userTextParts.push(trimmed);
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
else if (!suppressText) {
|
|
3148
2473
|
items.push({ type: "assistant_message", text: block.text });
|
|
3149
2474
|
}
|
|
3150
2475
|
}
|
|
@@ -3177,6 +2502,12 @@ class ClaudeAgentSession {
|
|
|
3177
2502
|
break;
|
|
3178
2503
|
}
|
|
3179
2504
|
}
|
|
2505
|
+
if (textMessageType === "user_message" && userTextParts.length > 0) {
|
|
2506
|
+
items.unshift({
|
|
2507
|
+
type: "user_message",
|
|
2508
|
+
text: userTextParts.join("\n\n"),
|
|
2509
|
+
});
|
|
2510
|
+
}
|
|
3180
2511
|
return items;
|
|
3181
2512
|
}
|
|
3182
2513
|
handleToolUseStart(block, items) {
|
|
@@ -3201,7 +2532,7 @@ class ClaudeAgentSession {
|
|
|
3201
2532
|
const toolName = entry?.name ?? block.tool_name ?? "tool";
|
|
3202
2533
|
const callId = typeof block.tool_use_id === "string" && block.tool_use_id.length > 0
|
|
3203
2534
|
? block.tool_use_id
|
|
3204
|
-
: entry?.id ?? null;
|
|
2535
|
+
: (entry?.id ?? null);
|
|
3205
2536
|
// Extract output from block.content (SDK always returns content in string form)
|
|
3206
2537
|
const output = this.buildToolOutput(block, entry);
|
|
3207
2538
|
if (block.is_error) {
|
|
@@ -3223,7 +2554,7 @@ class ClaudeAgentSession {
|
|
|
3223
2554
|
}
|
|
3224
2555
|
if (typeof block.tool_use_id === "string") {
|
|
3225
2556
|
this.toolUseCache.delete(block.tool_use_id);
|
|
3226
|
-
this.
|
|
2557
|
+
this.sidechainTracker.delete(block.tool_use_id);
|
|
3227
2558
|
}
|
|
3228
2559
|
}
|
|
3229
2560
|
buildToolOutput(block, entry) {
|
|
@@ -3296,12 +2627,24 @@ class ClaudeAgentSession {
|
|
|
3296
2627
|
normalizedTool === "apply_diff") {
|
|
3297
2628
|
if (input && typeof input.file_path === "string") {
|
|
3298
2629
|
// Support both old_str/new_str and old_string/new_string parameter names
|
|
3299
|
-
const oldContent = typeof input.old_str === "string"
|
|
3300
|
-
|
|
2630
|
+
const oldContent = typeof input.old_str === "string"
|
|
2631
|
+
? input.old_str
|
|
2632
|
+
: typeof input.old_string === "string"
|
|
2633
|
+
? input.old_string
|
|
2634
|
+
: undefined;
|
|
2635
|
+
const newContent = typeof input.new_str === "string"
|
|
2636
|
+
? input.new_str
|
|
2637
|
+
: typeof input.new_string === "string"
|
|
2638
|
+
? input.new_string
|
|
2639
|
+
: undefined;
|
|
3301
2640
|
return {
|
|
3302
2641
|
type: "file_edit",
|
|
3303
2642
|
filePath: input.file_path,
|
|
3304
|
-
diff: typeof input.patch === "string"
|
|
2643
|
+
diff: typeof input.patch === "string"
|
|
2644
|
+
? input.patch
|
|
2645
|
+
: typeof input.diff === "string"
|
|
2646
|
+
? input.diff
|
|
2647
|
+
: undefined,
|
|
3305
2648
|
oldContent,
|
|
3306
2649
|
newContent,
|
|
3307
2650
|
};
|
|
@@ -3324,7 +2667,9 @@ class ClaudeAgentSession {
|
|
|
3324
2667
|
mapPartialEvent(event, options) {
|
|
3325
2668
|
if (event.type === "content_block_start") {
|
|
3326
2669
|
const block = isClaudeContentChunk(event.content_block) ? event.content_block : null;
|
|
3327
|
-
if (block?.type === "tool_use" &&
|
|
2670
|
+
if (block?.type === "tool_use" &&
|
|
2671
|
+
typeof event.index === "number" &&
|
|
2672
|
+
typeof block.id === "string") {
|
|
3328
2673
|
this.toolUseIndexToId.set(event.index, block.id);
|
|
3329
2674
|
this.toolUseInputBuffers.delete(block.id);
|
|
3330
2675
|
}
|
|
@@ -3389,7 +2734,9 @@ class ClaudeAgentSession {
|
|
|
3389
2734
|
else if (!existing.server) {
|
|
3390
2735
|
existing.server = existing.name;
|
|
3391
2736
|
}
|
|
3392
|
-
if (block.type === "tool_use" ||
|
|
2737
|
+
if (block.type === "tool_use" ||
|
|
2738
|
+
block.type === "mcp_tool_use" ||
|
|
2739
|
+
block.type === "server_tool_use") {
|
|
3393
2740
|
const input = this.normalizeToolInput(block.input);
|
|
3394
2741
|
if (input) {
|
|
3395
2742
|
this.applyToolInput(existing, input);
|
|
@@ -3465,7 +2812,10 @@ class ClaudeAgentSession {
|
|
|
3465
2812
|
}
|
|
3466
2813
|
isCommandTool(name, input) {
|
|
3467
2814
|
const normalized = name.toLowerCase();
|
|
3468
|
-
if (normalized.includes("bash") ||
|
|
2815
|
+
if (normalized.includes("bash") ||
|
|
2816
|
+
normalized.includes("shell") ||
|
|
2817
|
+
normalized.includes("terminal") ||
|
|
2818
|
+
normalized.includes("command")) {
|
|
3469
2819
|
return true;
|
|
3470
2820
|
}
|
|
3471
2821
|
if (typeof input.command === "string" || Array.isArray(input.command)) {
|
|
@@ -3509,7 +2859,10 @@ class ClaudeAgentSession {
|
|
|
3509
2859
|
const files = [];
|
|
3510
2860
|
for (const value of input.files) {
|
|
3511
2861
|
if (typeof value === "string" && value.length > 0) {
|
|
3512
|
-
files.push({
|
|
2862
|
+
files.push({
|
|
2863
|
+
path: this.relativizePath(value) ?? value,
|
|
2864
|
+
kind: this.detectFileKind(value),
|
|
2865
|
+
});
|
|
3513
2866
|
}
|
|
3514
2867
|
}
|
|
3515
2868
|
if (files.length > 0) {
|
|
@@ -3572,11 +2925,7 @@ function hasToolLikeBlock(block) {
|
|
|
3572
2925
|
return type.includes("tool");
|
|
3573
2926
|
}
|
|
3574
2927
|
function readCompactionMetadata(source) {
|
|
3575
|
-
const candidates = [
|
|
3576
|
-
source.compact_metadata,
|
|
3577
|
-
source.compactMetadata,
|
|
3578
|
-
source.compactionMetadata,
|
|
3579
|
-
];
|
|
2928
|
+
const candidates = [source.compact_metadata, source.compactMetadata, source.compactionMetadata];
|
|
3580
2929
|
for (const candidate of candidates) {
|
|
3581
2930
|
if (!candidate || typeof candidate !== "object") {
|
|
3582
2931
|
continue;
|
|
@@ -3602,18 +2951,18 @@ function normalizeHistoryBlocks(content) {
|
|
|
3602
2951
|
export function convertClaudeHistoryEntry(entry, mapBlocks) {
|
|
3603
2952
|
if (entry.type === "system" && entry.subtype === "compact_boundary") {
|
|
3604
2953
|
const compactMetadata = readCompactionMetadata(entry);
|
|
3605
|
-
return [
|
|
2954
|
+
return [
|
|
2955
|
+
{
|
|
3606
2956
|
type: "compaction",
|
|
3607
2957
|
status: "completed",
|
|
3608
2958
|
trigger: compactMetadata?.trigger === "manual" ? "manual" : "auto",
|
|
3609
2959
|
preTokens: compactMetadata?.preTokens,
|
|
3610
|
-
}
|
|
2960
|
+
},
|
|
2961
|
+
];
|
|
3611
2962
|
}
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
return [taskNotificationItem];
|
|
3616
|
-
}
|
|
2963
|
+
const taskNotificationItem = mapTaskNotificationSystemRecordToToolCall(entry);
|
|
2964
|
+
if (taskNotificationItem) {
|
|
2965
|
+
return [taskNotificationItem];
|
|
3617
2966
|
}
|
|
3618
2967
|
if (entry.isCompactSummary) {
|
|
3619
2968
|
return [];
|
|
@@ -3626,10 +2975,12 @@ export function convertClaudeHistoryEntry(entry, mapBlocks) {
|
|
|
3626
2975
|
return [];
|
|
3627
2976
|
}
|
|
3628
2977
|
const content = message.content;
|
|
2978
|
+
if ((entry.type === "user" || entry.type === "assistant") &&
|
|
2979
|
+
isClaudeTranscriptNoiseContent(content)) {
|
|
2980
|
+
return [];
|
|
2981
|
+
}
|
|
3629
2982
|
const normalizedBlocks = normalizeHistoryBlocks(content);
|
|
3630
|
-
const contentValue = typeof content === "string"
|
|
3631
|
-
? content
|
|
3632
|
-
: normalizedBlocks;
|
|
2983
|
+
const contentValue = typeof content === "string" ? content : normalizedBlocks;
|
|
3633
2984
|
const hasToolBlock = normalizedBlocks?.some((block) => hasToolLikeBlock(block)) ?? false;
|
|
3634
2985
|
const userMessageId = entry.type === "user" && typeof entry.uuid === "string" && entry.uuid.length > 0
|
|
3635
2986
|
? entry.uuid
|
|
@@ -3762,9 +3113,7 @@ async function collectRecentClaudeSessions(root, limit) {
|
|
|
3762
3113
|
}
|
|
3763
3114
|
}
|
|
3764
3115
|
}
|
|
3765
|
-
return candidates
|
|
3766
|
-
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())
|
|
3767
|
-
.slice(0, limit);
|
|
3116
|
+
return candidates.sort((a, b) => b.mtime.getTime() - a.mtime.getTime()).slice(0, limit);
|
|
3768
3117
|
}
|
|
3769
3118
|
async function parseClaudeSessionDescriptor(filePath, mtime) {
|
|
3770
3119
|
let content;
|
|
@@ -3847,15 +3196,20 @@ function extractClaudeUserText(message) {
|
|
|
3847
3196
|
return null;
|
|
3848
3197
|
}
|
|
3849
3198
|
if (typeof message.content === "string") {
|
|
3850
|
-
|
|
3199
|
+
const normalized = message.content.trim();
|
|
3200
|
+
return normalized && !isClaudeTranscriptNoiseText(normalized) ? normalized : null;
|
|
3851
3201
|
}
|
|
3852
3202
|
if (typeof message.text === "string") {
|
|
3853
|
-
|
|
3203
|
+
const normalized = message.text.trim();
|
|
3204
|
+
return normalized && !isClaudeTranscriptNoiseText(normalized) ? normalized : null;
|
|
3854
3205
|
}
|
|
3855
3206
|
if (Array.isArray(message.content)) {
|
|
3856
3207
|
for (const block of message.content) {
|
|
3857
3208
|
if (block && typeof block.text === "string") {
|
|
3858
|
-
|
|
3209
|
+
const normalized = block.text.trim();
|
|
3210
|
+
if (normalized && !isClaudeTranscriptNoiseText(normalized)) {
|
|
3211
|
+
return normalized;
|
|
3212
|
+
}
|
|
3859
3213
|
}
|
|
3860
3214
|
}
|
|
3861
3215
|
}
|