@getpaseo/server 0.1.15 → 0.1.17
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 +53 -14
- package/dist/scripts/daemon-runner.js.map +1 -1
- package/dist/scripts/dev-runner.js +9 -16
- package/dist/scripts/dev-runner.js.map +1 -1
- package/dist/scripts/supervisor.js +40 -13
- package/dist/scripts/supervisor.js.map +1 -1
- package/dist/server/client/daemon-client.d.ts +63 -6
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +436 -92
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/server/agent/agent-manager.d.ts +13 -1
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
- package/dist/server/server/agent/agent-manager.js +404 -39
- 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 +13 -4
- package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
- package/dist/server/server/agent/agent-projections.d.ts +5 -0
- package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
- package/dist/server/server/agent/agent-projections.js +24 -0
- package/dist/server/server/agent/agent-projections.js.map +1 -1
- package/dist/server/server/agent/agent-response-loop.js +1 -1
- package/dist/server/server/agent/agent-response-loop.js.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts +20 -0
- package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.js +11 -1
- package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
- package/dist/server/server/agent/agent-storage.d.ts +20 -6
- package/dist/server/server/agent/agent-storage.d.ts.map +1 -1
- package/dist/server/server/agent/agent-storage.js +43 -72
- package/dist/server/server/agent/agent-storage.js.map +1 -1
- package/dist/server/server/agent/agent-title-limits.d.ts +3 -0
- package/dist/server/server/agent/agent-title-limits.d.ts.map +1 -0
- package/dist/server/server/agent/agent-title-limits.js +3 -0
- package/dist/server/server/agent/agent-title-limits.js.map +1 -0
- package/dist/server/server/agent/providers/claude/model-catalog.d.ts +29 -0
- package/dist/server/server/agent/providers/claude/model-catalog.d.ts.map +1 -0
- package/dist/server/server/agent/providers/claude/model-catalog.js +70 -0
- package/dist/server/server/agent/providers/claude/model-catalog.js.map +1 -0
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +44 -0
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts.map +1 -0
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +250 -0
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.js.map +1 -0
- 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 +17 -0
- 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 +2 -0
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/claude-agent.d.ts +10 -3
- package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude-agent.js +1702 -330
- package/dist/server/server/agent/providers/claude-agent.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 +81 -28
- 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 +50 -9
- package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts +10 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.js +207 -176
- package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +55 -0
- 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 +1 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -1
- package/dist/server/server/agent/timeline-projection.d.ts +20 -0
- package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
- package/dist/server/server/agent/timeline-projection.js +73 -0
- package/dist/server/server/agent/timeline-projection.js.map +1 -1
- package/dist/server/server/bootstrap.d.ts +15 -0
- package/dist/server/server/bootstrap.d.ts.map +1 -1
- package/dist/server/server/bootstrap.js +27 -4
- package/dist/server/server/bootstrap.js.map +1 -1
- package/dist/server/server/client-message-id.d.ts +3 -0
- package/dist/server/server/client-message-id.d.ts.map +1 -0
- package/dist/server/server/client-message-id.js +12 -0
- package/dist/server/server/client-message-id.js.map +1 -0
- package/dist/server/server/file-download/token-store.d.ts +0 -1
- package/dist/server/server/file-download/token-store.d.ts.map +1 -1
- package/dist/server/server/file-download/token-store.js.map +1 -1
- package/dist/server/server/file-explorer/service.d.ts.map +1 -1
- package/dist/server/server/file-explorer/service.js +56 -36
- package/dist/server/server/file-explorer/service.js.map +1 -1
- package/dist/server/server/index.js +85 -29
- package/dist/server/server/index.js.map +1 -1
- package/dist/server/server/logger.d.ts +24 -3
- package/dist/server/server/logger.d.ts.map +1 -1
- package/dist/server/server/logger.js +157 -21
- package/dist/server/server/logger.js.map +1 -1
- package/dist/server/server/persisted-config.d.ts +94 -8
- package/dist/server/server/persisted-config.d.ts.map +1 -1
- package/dist/server/server/persisted-config.js +25 -3
- package/dist/server/server/persisted-config.js.map +1 -1
- package/dist/server/server/persistence-hooks.js +1 -1
- package/dist/server/server/persistence-hooks.js.map +1 -1
- package/dist/server/server/pid-lock.d.ts +6 -2
- package/dist/server/server/pid-lock.d.ts.map +1 -1
- package/dist/server/server/pid-lock.js +7 -10
- package/dist/server/server/pid-lock.js.map +1 -1
- package/dist/server/server/relay-transport.js +28 -28
- package/dist/server/server/relay-transport.js.map +1 -1
- package/dist/server/server/session.d.ts +60 -4
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +854 -190
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/server/websocket-server.d.ts +24 -5
- package/dist/server/server/websocket-server.d.ts.map +1 -1
- package/dist/server/server/websocket-server.js +400 -77
- package/dist/server/server/websocket-server.js.map +1 -1
- package/dist/server/server/worktree-bootstrap.d.ts.map +1 -1
- package/dist/server/server/worktree-bootstrap.js +45 -2
- package/dist/server/server/worktree-bootstrap.js.map +1 -1
- package/dist/server/shared/daemon-endpoints.d.ts +9 -1
- package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
- package/dist/server/shared/daemon-endpoints.js +18 -3
- package/dist/server/shared/daemon-endpoints.js.map +1 -1
- package/dist/server/shared/messages.d.ts +4432 -380
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +139 -6
- package/dist/server/shared/messages.js.map +1 -1
- package/dist/server/shared/tool-call-display.d.ts.map +1 -1
- package/dist/server/shared/tool-call-display.js +7 -0
- package/dist/server/shared/tool-call-display.js.map +1 -1
- package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
- package/dist/server/terminal/terminal-manager.js +1 -13
- package/dist/server/terminal/terminal-manager.js.map +1 -1
- package/dist/server/terminal/terminal.d.ts.map +1 -1
- package/dist/server/terminal/terminal.js +29 -5
- package/dist/server/terminal/terminal.js.map +1 -1
- package/dist/server/utils/worktree.d.ts +1 -0
- package/dist/server/utils/worktree.d.ts.map +1 -1
- package/dist/server/utils/worktree.js +17 -2
- package/dist/server/utils/worktree.js.map +1 -1
- package/dist/src/server/agent/activity-curator.js +228 -0
- package/dist/src/server/agent/activity-curator.js.map +1 -0
- package/dist/src/server/agent/agent-manager.js +1712 -0
- package/dist/src/server/agent/agent-manager.js.map +1 -0
- package/dist/src/server/agent/agent-metadata-generator.js +163 -0
- package/dist/src/server/agent/agent-metadata-generator.js.map +1 -0
- package/dist/src/server/agent/agent-projections.js +262 -0
- package/dist/src/server/agent/agent-projections.js.map +1 -0
- package/dist/src/server/agent/agent-response-loop.js +304 -0
- package/dist/src/server/agent/agent-response-loop.js.map +1 -0
- package/dist/src/server/agent/agent-sdk-types.js +12 -0
- package/dist/src/server/agent/agent-sdk-types.js.map +1 -0
- package/dist/src/server/agent/agent-storage.js +299 -0
- package/dist/src/server/agent/agent-storage.js.map +1 -0
- package/dist/src/server/agent/agent-title-limits.js +3 -0
- package/dist/src/server/agent/agent-title-limits.js.map +1 -0
- package/dist/src/server/agent/audio-utils.js +19 -0
- package/dist/src/server/agent/audio-utils.js.map +1 -0
- package/dist/src/server/agent/dictation-debug.js +50 -0
- package/dist/src/server/agent/dictation-debug.js.map +1 -0
- package/dist/src/server/agent/mcp-server.js +787 -0
- package/dist/src/server/agent/mcp-server.js.map +1 -0
- package/dist/src/server/agent/orchestrator-instructions.js +51 -0
- package/dist/src/server/agent/orchestrator-instructions.js.map +1 -0
- package/dist/src/server/agent/pcm16-resampler.js +63 -0
- package/dist/src/server/agent/pcm16-resampler.js.map +1 -0
- package/dist/src/server/agent/provider-launch-config.js +83 -0
- package/dist/src/server/agent/provider-launch-config.js.map +1 -0
- package/dist/src/server/agent/provider-manifest.js +97 -0
- package/dist/src/server/agent/provider-manifest.js.map +1 -0
- package/dist/src/server/agent/provider-registry.js +45 -0
- package/dist/src/server/agent/provider-registry.js.map +1 -0
- package/dist/src/server/agent/providers/claude/model-catalog.js +70 -0
- package/dist/src/server/agent/providers/claude/model-catalog.js.map +1 -0
- package/dist/src/server/agent/providers/claude/task-notification-tool-call.js +250 -0
- package/dist/src/server/agent/providers/claude/task-notification-tool-call.js.map +1 -0
- package/dist/src/server/agent/providers/claude/tool-call-detail-parser.js +109 -0
- package/dist/src/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -0
- package/dist/src/server/agent/providers/claude/tool-call-mapper.js +238 -0
- package/dist/src/server/agent/providers/claude/tool-call-mapper.js.map +1 -0
- package/dist/src/server/agent/providers/claude-agent.js +3747 -0
- package/dist/src/server/agent/providers/claude-agent.js.map +1 -0
- package/dist/src/server/agent/providers/codex/tool-call-detail-parser.js +104 -0
- package/dist/src/server/agent/providers/codex/tool-call-detail-parser.js.map +1 -0
- package/dist/src/server/agent/providers/codex/tool-call-mapper.js +720 -0
- package/dist/src/server/agent/providers/codex/tool-call-mapper.js.map +1 -0
- package/dist/src/server/agent/providers/codex-app-server-agent.js +2601 -0
- package/dist/src/server/agent/providers/codex-app-server-agent.js.map +1 -0
- package/dist/src/server/agent/providers/codex-rollout-timeline.js +487 -0
- package/dist/src/server/agent/providers/codex-rollout-timeline.js.map +1 -0
- package/dist/src/server/agent/providers/opencode/tool-call-detail-parser.js +39 -0
- package/dist/src/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -0
- package/dist/src/server/agent/providers/opencode/tool-call-mapper.js +151 -0
- package/dist/src/server/agent/providers/opencode/tool-call-mapper.js.map +1 -0
- package/dist/src/server/agent/providers/opencode-agent.js +905 -0
- package/dist/src/server/agent/providers/opencode-agent.js.map +1 -0
- package/dist/src/server/agent/providers/tool-call-detail-primitives.js +552 -0
- package/dist/src/server/agent/providers/tool-call-detail-primitives.js.map +1 -0
- package/dist/src/server/agent/providers/tool-call-mapper-utils.js +109 -0
- package/dist/src/server/agent/providers/tool-call-mapper-utils.js.map +1 -0
- package/dist/src/server/agent/recordings-debug.js +19 -0
- package/dist/src/server/agent/recordings-debug.js.map +1 -0
- package/dist/src/server/agent/stt-debug.js +33 -0
- package/dist/src/server/agent/stt-debug.js.map +1 -0
- package/dist/src/server/agent/stt-manager.js +233 -0
- package/dist/src/server/agent/stt-manager.js.map +1 -0
- package/dist/src/server/agent/timeline-append.js +27 -0
- package/dist/src/server/agent/timeline-append.js.map +1 -0
- package/dist/src/server/agent/timeline-projection.js +215 -0
- package/dist/src/server/agent/timeline-projection.js.map +1 -0
- package/dist/src/server/agent/tool-name-normalization.js +45 -0
- package/dist/src/server/agent/tool-name-normalization.js.map +1 -0
- package/dist/src/server/agent/tts-debug.js +24 -0
- package/dist/src/server/agent/tts-debug.js.map +1 -0
- package/dist/src/server/agent/tts-manager.js +249 -0
- package/dist/src/server/agent/tts-manager.js.map +1 -0
- package/dist/src/server/agent/wait-for-agent-tracker.js +53 -0
- package/dist/src/server/agent/wait-for-agent-tracker.js.map +1 -0
- package/dist/src/server/agent-attention-policy.js +40 -0
- package/dist/src/server/agent-attention-policy.js.map +1 -0
- package/dist/src/server/allowed-hosts.js +94 -0
- package/dist/src/server/allowed-hosts.js.map +1 -0
- package/dist/src/server/bootstrap.js +498 -0
- package/dist/src/server/bootstrap.js.map +1 -0
- package/dist/src/server/client-message-id.js +12 -0
- package/dist/src/server/client-message-id.js.map +1 -0
- package/dist/src/server/config.js +84 -0
- package/dist/src/server/config.js.map +1 -0
- package/dist/src/server/connection-offer.js +60 -0
- package/dist/src/server/connection-offer.js.map +1 -0
- package/dist/src/server/daemon-keypair.js +40 -0
- package/dist/src/server/daemon-keypair.js.map +1 -0
- package/dist/src/server/daemon-version.js +22 -0
- package/dist/src/server/daemon-version.js.map +1 -0
- package/dist/src/server/dictation/dictation-stream-manager.js +568 -0
- package/dist/src/server/dictation/dictation-stream-manager.js.map +1 -0
- package/dist/src/server/file-download/token-store.js +40 -0
- package/dist/src/server/file-download/token-store.js.map +1 -0
- package/dist/src/server/file-explorer/service.js +183 -0
- package/dist/src/server/file-explorer/service.js.map +1 -0
- package/dist/src/server/json-utils.js +45 -0
- package/dist/src/server/json-utils.js.map +1 -0
- package/dist/src/server/messages.js +29 -0
- package/dist/src/server/messages.js.map +1 -0
- package/dist/src/server/package-version.js +47 -0
- package/dist/src/server/package-version.js.map +1 -0
- package/dist/src/server/paseo-home.js +19 -0
- package/dist/src/server/paseo-home.js.map +1 -0
- package/dist/src/server/path-utils.js +20 -0
- package/dist/src/server/path-utils.js.map +1 -0
- package/dist/src/server/persisted-config.js +259 -0
- package/dist/src/server/persisted-config.js.map +1 -0
- package/dist/src/server/persistence-hooks.js +60 -0
- package/dist/src/server/persistence-hooks.js.map +1 -0
- package/dist/src/server/pid-lock.js +126 -0
- package/dist/src/server/pid-lock.js.map +1 -0
- package/dist/src/server/push/push-service.js +68 -0
- package/dist/src/server/push/push-service.js.map +1 -0
- package/dist/src/server/push/token-store.js +70 -0
- package/dist/src/server/push/token-store.js.map +1 -0
- package/dist/src/server/relay-transport.js +457 -0
- package/dist/src/server/relay-transport.js.map +1 -0
- package/dist/src/server/server-id.js +63 -0
- package/dist/src/server/server-id.js.map +1 -0
- package/dist/src/server/session.js +5947 -0
- package/dist/src/server/session.js.map +1 -0
- package/dist/src/server/speech/audio.js +101 -0
- package/dist/src/server/speech/audio.js.map +1 -0
- package/dist/src/server/speech/provider-resolver.js +7 -0
- package/dist/src/server/speech/provider-resolver.js.map +1 -0
- package/dist/src/server/speech/providers/local/config.js +83 -0
- package/dist/src/server/speech/providers/local/config.js.map +1 -0
- package/dist/src/server/speech/providers/local/models.js +17 -0
- package/dist/src/server/speech/providers/local/models.js.map +1 -0
- package/dist/src/server/speech/providers/local/pocket/pocket-tts-onnx.js +422 -0
- package/dist/src/server/speech/providers/local/pocket/pocket-tts-onnx.js.map +1 -0
- package/dist/src/server/speech/providers/local/runtime.js +253 -0
- package/dist/src/server/speech/providers/local/runtime.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/model-catalog.js +166 -0
- package/dist/src/server/speech/providers/local/sherpa/model-catalog.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/model-downloader.js +165 -0
- package/dist/src/server/speech/providers/local/sherpa/model-downloader.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +68 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-online-recognizer.js +79 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-onnx-loader.js +11 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-onnx-loader.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +102 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +131 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +132 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-realtime-session.js +112 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-stt.js +140 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-stt.js.map +1 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-tts.js +95 -0
- package/dist/src/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -0
- package/dist/src/server/speech/providers/openai/config.js +99 -0
- package/dist/src/server/speech/providers/openai/config.js.map +1 -0
- package/dist/src/server/speech/providers/openai/realtime-transcription-session.js +165 -0
- package/dist/src/server/speech/providers/openai/realtime-transcription-session.js.map +1 -0
- package/dist/src/server/speech/providers/openai/runtime.js +114 -0
- package/dist/src/server/speech/providers/openai/runtime.js.map +1 -0
- package/dist/src/server/speech/providers/openai/stt.js +208 -0
- package/dist/src/server/speech/providers/openai/stt.js.map +1 -0
- package/dist/src/server/speech/providers/openai/tts.js +46 -0
- package/dist/src/server/speech/providers/openai/tts.js.map +1 -0
- package/dist/src/server/speech/speech-config-resolver.js +85 -0
- package/dist/src/server/speech/speech-config-resolver.js.map +1 -0
- package/dist/src/server/speech/speech-provider.js +2 -0
- package/dist/src/server/speech/speech-provider.js.map +1 -0
- package/dist/src/server/speech/speech-runtime.js +497 -0
- package/dist/src/server/speech/speech-runtime.js.map +1 -0
- package/dist/src/server/speech/speech-types.js +8 -0
- package/dist/src/server/speech/speech-types.js.map +1 -0
- package/dist/src/server/utils/diff-highlighter.js +244 -0
- package/dist/src/server/utils/diff-highlighter.js.map +1 -0
- package/dist/src/server/utils/syntax-highlighter.js +145 -0
- package/dist/src/server/utils/syntax-highlighter.js.map +1 -0
- package/dist/src/server/voice-config.js +51 -0
- package/dist/src/server/voice-config.js.map +1 -0
- package/dist/src/server/voice-mcp-bridge-command.js +31 -0
- package/dist/src/server/voice-mcp-bridge-command.js.map +1 -0
- package/dist/src/server/voice-mcp-bridge.js +109 -0
- package/dist/src/server/voice-mcp-bridge.js.map +1 -0
- package/dist/src/server/voice-permission-policy.js +13 -0
- package/dist/src/server/voice-permission-policy.js.map +1 -0
- package/dist/src/server/voice-types.js +2 -0
- package/dist/src/server/voice-types.js.map +1 -0
- package/dist/src/server/websocket-server.js +967 -0
- package/dist/src/server/websocket-server.js.map +1 -0
- package/dist/src/server/worktree-bootstrap.js +497 -0
- package/dist/src/server/worktree-bootstrap.js.map +1 -0
- package/dist/src/shared/agent-attention-notification.js +130 -0
- package/dist/src/shared/agent-attention-notification.js.map +1 -0
- package/dist/src/shared/agent-lifecycle.js +8 -0
- package/dist/src/shared/agent-lifecycle.js.map +1 -0
- package/dist/src/shared/binary-mux.js +114 -0
- package/dist/src/shared/binary-mux.js.map +1 -0
- package/dist/src/shared/connection-offer.js +17 -0
- package/dist/src/shared/connection-offer.js.map +1 -0
- package/dist/src/shared/daemon-endpoints.js +113 -0
- package/dist/src/shared/daemon-endpoints.js.map +1 -0
- package/dist/src/shared/messages.js +2001 -0
- package/dist/src/shared/messages.js.map +1 -0
- package/dist/src/shared/path-utils.js +16 -0
- package/dist/src/shared/path-utils.js.map +1 -0
- package/dist/src/shared/tool-call-display.js +93 -0
- package/dist/src/shared/tool-call-display.js.map +1 -0
- package/dist/src/terminal/terminal-manager.js +136 -0
- package/dist/src/terminal/terminal-manager.js.map +1 -0
- package/dist/src/terminal/terminal.js +410 -0
- package/dist/src/terminal/terminal.js.map +1 -0
- package/dist/src/utils/checkout-git.js +1397 -0
- package/dist/src/utils/checkout-git.js.map +1 -0
- package/dist/src/utils/directory-suggestions.js +655 -0
- package/dist/src/utils/directory-suggestions.js.map +1 -0
- package/dist/src/utils/path.js +15 -0
- package/dist/src/utils/path.js.map +1 -0
- package/dist/src/utils/project-icon.js +391 -0
- package/dist/src/utils/project-icon.js.map +1 -0
- package/dist/src/utils/worktree-metadata.js +116 -0
- package/dist/src/utils/worktree-metadata.js.map +1 -0
- package/dist/src/utils/worktree.js +741 -0
- package/dist/src/utils/worktree.js.map +1 -0
- package/package.json +15 -7
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import { AgentCreateFailedStatusPayloadSchema, AgentCreatedStatusPayloadSchema, AgentRefreshedStatusPayloadSchema, AgentResumedStatusPayloadSchema, RestartRequestedStatusPayloadSchema, SessionInboundMessageSchema, WSOutboundMessageSchema, } from '../shared/messages.js';
|
|
1
|
+
import { AgentCreateFailedStatusPayloadSchema, AgentCreatedStatusPayloadSchema, AgentRefreshedStatusPayloadSchema, AgentResumedStatusPayloadSchema, RestartRequestedStatusPayloadSchema, ShutdownRequestedStatusPayloadSchema, SessionInboundMessageSchema, WSOutboundMessageSchema, } from '../shared/messages.js';
|
|
2
2
|
import { getAgentProviderDefinition } from '../server/agent/provider-manifest.js';
|
|
3
3
|
import { isRelayClientWebSocketUrl } from '../shared/daemon-endpoints.js';
|
|
4
4
|
import { asUint8Array, decodeBinaryMuxFrame, encodeBinaryMuxFrame, BinaryMuxChannel, TerminalBinaryFlags, TerminalBinaryMessageType, } from '../shared/binary-mux.js';
|
|
5
5
|
import { encodeTerminalKeyInput } from '../shared/terminal-key-input.js';
|
|
6
6
|
import { TerminalStreamManager, } from './daemon-client-terminal-stream-manager.js';
|
|
7
|
-
import { createRelayE2eeTransportFactory, createWebSocketTransportFactory, decodeMessageData, defaultWebSocketFactory, describeTransportClose, describeTransportError, encodeUtf8String,
|
|
7
|
+
import { createRelayE2eeTransportFactory, createWebSocketTransportFactory, decodeMessageData, defaultWebSocketFactory, describeTransportClose, describeTransportError, encodeUtf8String, } from './daemon-client-transport.js';
|
|
8
8
|
const consoleLogger = {
|
|
9
|
-
debug: (
|
|
9
|
+
debug: () => { },
|
|
10
10
|
info: (obj, msg) => console.info(msg, obj),
|
|
11
11
|
warn: (obj, msg) => console.warn(msg, obj),
|
|
12
12
|
error: (obj, msg) => console.error(msg, obj),
|
|
13
13
|
};
|
|
14
|
+
function getNowMs() {
|
|
15
|
+
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
|
|
16
|
+
return performance.now();
|
|
17
|
+
}
|
|
18
|
+
return Date.now();
|
|
19
|
+
}
|
|
14
20
|
class DaemonRpcError extends Error {
|
|
15
21
|
constructor(params) {
|
|
16
22
|
super(params.error);
|
|
@@ -22,6 +28,7 @@ class DaemonRpcError extends Error {
|
|
|
22
28
|
}
|
|
23
29
|
const DEFAULT_RECONNECT_BASE_DELAY_MS = 1500;
|
|
24
30
|
const DEFAULT_RECONNECT_MAX_DELAY_MS = 30000;
|
|
31
|
+
const DEFAULT_CONNECT_TIMEOUT_MS = 15000;
|
|
25
32
|
/** Default timeout for waiting for connection before sending queued messages */
|
|
26
33
|
const DEFAULT_SEND_QUEUE_TIMEOUT_MS = 10000;
|
|
27
34
|
const DEFAULT_DICTATION_FINISH_ACCEPT_TIMEOUT_MS = 15000;
|
|
@@ -30,6 +37,42 @@ const DEFAULT_DICTATION_FINISH_TIMEOUT_GRACE_MS = 5000;
|
|
|
30
37
|
function isWaiterTimeoutError(error) {
|
|
31
38
|
return error instanceof Error && error.message.startsWith('Timeout waiting for message');
|
|
32
39
|
}
|
|
40
|
+
function normalizeClientId(value) {
|
|
41
|
+
if (typeof value !== 'string') {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const trimmed = value.trim();
|
|
45
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
46
|
+
}
|
|
47
|
+
function hashForLog(value) {
|
|
48
|
+
let hash = 0;
|
|
49
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
50
|
+
hash = (hash * 31 + value.charCodeAt(index)) | 0;
|
|
51
|
+
}
|
|
52
|
+
return `h_${Math.abs(hash).toString(16)}`;
|
|
53
|
+
}
|
|
54
|
+
function toReasonCode(reason) {
|
|
55
|
+
if (!reason) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const normalized = reason.toLowerCase();
|
|
59
|
+
if (normalized.includes('timed out')) {
|
|
60
|
+
return 'connect_timeout';
|
|
61
|
+
}
|
|
62
|
+
if (normalized.includes('disposed')) {
|
|
63
|
+
return 'disposed';
|
|
64
|
+
}
|
|
65
|
+
if (normalized.includes('client closed')) {
|
|
66
|
+
return 'client_closed';
|
|
67
|
+
}
|
|
68
|
+
if (normalized.includes('transport')) {
|
|
69
|
+
return 'transport_error';
|
|
70
|
+
}
|
|
71
|
+
if (normalized.includes('failed to connect')) {
|
|
72
|
+
return 'connect_failed';
|
|
73
|
+
}
|
|
74
|
+
return 'unknown';
|
|
75
|
+
}
|
|
33
76
|
export class DaemonClient {
|
|
34
77
|
constructor(config) {
|
|
35
78
|
this.config = config;
|
|
@@ -42,6 +85,7 @@ export class DaemonClient {
|
|
|
42
85
|
this.checkoutStatusInFlight = new Map();
|
|
43
86
|
this.connectionListeners = new Set();
|
|
44
87
|
this.reconnectTimeout = null;
|
|
88
|
+
this.connectTimeout = null;
|
|
45
89
|
this.pendingGenericTransportErrorTimeout = null;
|
|
46
90
|
this.reconnectAttempt = 0;
|
|
47
91
|
this.shouldReconnect = true;
|
|
@@ -53,8 +97,28 @@ export class DaemonClient {
|
|
|
53
97
|
this.checkoutDiffSubscriptions = new Map();
|
|
54
98
|
this.terminalDirectorySubscriptions = new Set();
|
|
55
99
|
this.pendingSendQueue = [];
|
|
56
|
-
this.
|
|
100
|
+
this.lastWelcomeMessage = null;
|
|
57
101
|
this.logger = config.logger ?? consoleLogger;
|
|
102
|
+
this.logConnectionPath = isRelayClientWebSocketUrl(this.config.url) ? 'relay' : 'direct';
|
|
103
|
+
let parsedUrlForLog = null;
|
|
104
|
+
try {
|
|
105
|
+
parsedUrlForLog = new URL(this.config.url);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
parsedUrlForLog = null;
|
|
109
|
+
}
|
|
110
|
+
const parsedServerIdForLog = normalizeClientId(parsedUrlForLog?.searchParams.get('serverId'));
|
|
111
|
+
this.logServerId = parsedServerIdForLog ?? parsedUrlForLog?.host ?? null;
|
|
112
|
+
const resolvedClientId = normalizeClientId(this.config.clientId);
|
|
113
|
+
if (!resolvedClientId) {
|
|
114
|
+
throw new Error('Daemon client requires a non-empty clientId');
|
|
115
|
+
}
|
|
116
|
+
this.config.clientId = resolvedClientId;
|
|
117
|
+
this.logClientIdHash = hashForLog(resolvedClientId);
|
|
118
|
+
this.logGeneration =
|
|
119
|
+
typeof this.config.runtimeGeneration === 'number' && Number.isFinite(this.config.runtimeGeneration)
|
|
120
|
+
? this.config.runtimeGeneration
|
|
121
|
+
: null;
|
|
58
122
|
this.terminalStreams = new TerminalStreamManager({
|
|
59
123
|
sendAck: (ack) => {
|
|
60
124
|
this.sendBinaryFrame({
|
|
@@ -66,27 +130,22 @@ export class DaemonClient {
|
|
|
66
130
|
});
|
|
67
131
|
},
|
|
68
132
|
});
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
this.relayClientId = `clt_${safeRandomId()}`;
|
|
77
|
-
parsed.searchParams.set('clientId', this.relayClientId);
|
|
78
|
-
this.config.url = parsed.toString();
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
// ignore - invalid URL will be handled on connect
|
|
83
|
-
}
|
|
133
|
+
}
|
|
134
|
+
emitDiagnosticsEvent(event) {
|
|
135
|
+
try {
|
|
136
|
+
this.config.onDiagnosticsEvent?.(event);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Diagnostics hooks must never break daemon message handling.
|
|
84
140
|
}
|
|
85
141
|
}
|
|
86
142
|
// ============================================================================
|
|
87
143
|
// Connection
|
|
88
144
|
// ============================================================================
|
|
89
145
|
async connect() {
|
|
146
|
+
if (this.connectionState.status === 'disposed') {
|
|
147
|
+
throw new Error('Daemon client is disposed');
|
|
148
|
+
}
|
|
90
149
|
if (this.connectionState.status === 'connected') {
|
|
91
150
|
return;
|
|
92
151
|
}
|
|
@@ -102,6 +161,10 @@ export class DaemonClient {
|
|
|
102
161
|
return this.connectPromise;
|
|
103
162
|
}
|
|
104
163
|
attemptConnect() {
|
|
164
|
+
if (this.connectionState.status === 'disposed') {
|
|
165
|
+
this.rejectConnect(new Error('Daemon client is disposed'));
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
105
168
|
if (!this.shouldReconnect) {
|
|
106
169
|
this.rejectConnect(new Error('Daemon client is closed'));
|
|
107
170
|
return;
|
|
@@ -114,10 +177,8 @@ export class DaemonClient {
|
|
|
114
177
|
headers['Authorization'] = this.config.authHeader;
|
|
115
178
|
}
|
|
116
179
|
try {
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
// concurrent relay sockets. Cloudflare then closes the old one with
|
|
120
|
-
// "Replaced by new connection", causing a disconnect loop.
|
|
180
|
+
// Reconnect can overlap with browser close/error delivery ordering.
|
|
181
|
+
// Always dispose previous transport before constructing the next one.
|
|
121
182
|
this.disposeTransport();
|
|
122
183
|
const baseTransportFactory = this.config.transportFactory ??
|
|
123
184
|
createWebSocketTransportFactory(this.config.webSocketFactory ?? defaultWebSocketFactory);
|
|
@@ -134,12 +195,28 @@ export class DaemonClient {
|
|
|
134
195
|
logger: this.logger,
|
|
135
196
|
});
|
|
136
197
|
}
|
|
137
|
-
const
|
|
198
|
+
const transportUrl = this.resolveTransportUrlForAttempt();
|
|
199
|
+
const transport = transportFactory({ url: transportUrl, headers });
|
|
138
200
|
this.transport = transport;
|
|
201
|
+
this.lastWelcomeMessage = null;
|
|
139
202
|
this.updateConnectionState({
|
|
140
203
|
status: 'connecting',
|
|
141
204
|
attempt: this.reconnectAttempt,
|
|
142
|
-
});
|
|
205
|
+
}, { event: 'CONNECT_REQUEST' });
|
|
206
|
+
this.resetConnectTimeout();
|
|
207
|
+
const timeoutMs = Math.max(1, this.config.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS);
|
|
208
|
+
this.connectTimeout = setTimeout(() => {
|
|
209
|
+
if (this.connectionState.status !== 'connecting') {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
this.lastErrorValue = 'Connection timed out';
|
|
213
|
+
this.disposeTransport(1001, 'Connection timed out');
|
|
214
|
+
this.scheduleReconnect({
|
|
215
|
+
reason: 'Connection timed out',
|
|
216
|
+
event: 'CONNECT_TIMEOUT',
|
|
217
|
+
reasonCode: 'connect_timeout',
|
|
218
|
+
});
|
|
219
|
+
}, timeoutMs);
|
|
143
220
|
this.transportCleanup = [
|
|
144
221
|
transport.onOpen(() => {
|
|
145
222
|
if (this.pendingGenericTransportErrorTimeout) {
|
|
@@ -147,48 +224,26 @@ export class DaemonClient {
|
|
|
147
224
|
this.pendingGenericTransportErrorTimeout = null;
|
|
148
225
|
}
|
|
149
226
|
this.lastErrorValue = null;
|
|
150
|
-
this.
|
|
151
|
-
this.updateConnectionState({ status: 'connected' });
|
|
152
|
-
this.resubscribeCheckoutDiffSubscriptions();
|
|
153
|
-
this.resubscribeTerminalDirectorySubscriptions();
|
|
154
|
-
this.flushPendingSendQueue();
|
|
155
|
-
this.resolveConnect();
|
|
227
|
+
this.sendHelloMessage();
|
|
156
228
|
}),
|
|
157
229
|
transport.onClose((event) => {
|
|
230
|
+
this.resetConnectTimeout();
|
|
158
231
|
if (this.pendingGenericTransportErrorTimeout) {
|
|
159
232
|
clearTimeout(this.pendingGenericTransportErrorTimeout);
|
|
160
233
|
this.pendingGenericTransportErrorTimeout = null;
|
|
161
234
|
}
|
|
162
|
-
const closeRecord = event;
|
|
163
|
-
const closeCode = closeRecord && typeof closeRecord === 'object' && typeof closeRecord.code === 'number'
|
|
164
|
-
? closeRecord.code
|
|
165
|
-
: null;
|
|
166
|
-
const closeReason = closeRecord && typeof closeRecord === 'object' && typeof closeRecord.reason === 'string'
|
|
167
|
-
? closeRecord.reason
|
|
168
|
-
: null;
|
|
169
235
|
const reason = describeTransportClose(event);
|
|
170
236
|
if (reason) {
|
|
171
237
|
this.lastErrorValue = reason;
|
|
172
238
|
}
|
|
173
|
-
this.
|
|
174
|
-
|
|
175
|
-
|
|
239
|
+
this.scheduleReconnect({
|
|
240
|
+
reason,
|
|
241
|
+
event: 'TRANSPORT_CLOSE',
|
|
242
|
+
reasonCode: 'transport_closed',
|
|
176
243
|
});
|
|
177
|
-
// When connecting over the relay, only one client connection is allowed at a time.
|
|
178
|
-
// If another device/tab takes over, we should not auto-reconnect and "fight" the new
|
|
179
|
-
// connection (which causes flapping where both sides repeatedly replace each other).
|
|
180
|
-
if (isRelayClientWebSocketUrl(this.config.url) &&
|
|
181
|
-
closeCode === 1008 &&
|
|
182
|
-
(closeReason ?? reason) === 'Replaced by new connection') {
|
|
183
|
-
this.shouldReconnect = false;
|
|
184
|
-
this.clearWaiters(new Error(reason ?? 'Replaced by new connection'));
|
|
185
|
-
this.rejectPendingSendQueue(new Error(reason ?? 'Replaced by new connection'));
|
|
186
|
-
this.rejectConnect(new Error(reason ?? 'Replaced by new connection'));
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
this.scheduleReconnect(reason);
|
|
190
244
|
}),
|
|
191
245
|
transport.onError((event) => {
|
|
246
|
+
this.resetConnectTimeout();
|
|
192
247
|
const reason = describeTransportError(event);
|
|
193
248
|
const isGeneric = reason === 'Transport error';
|
|
194
249
|
// Browser WebSocket.onerror often provides no useful details and is followed
|
|
@@ -202,8 +257,11 @@ export class DaemonClient {
|
|
|
202
257
|
if (this.connectionState.status === 'connected' ||
|
|
203
258
|
this.connectionState.status === 'connecting') {
|
|
204
259
|
this.lastErrorValue = reason;
|
|
205
|
-
this.
|
|
206
|
-
|
|
260
|
+
this.scheduleReconnect({
|
|
261
|
+
reason,
|
|
262
|
+
event: 'TRANSPORT_ERROR',
|
|
263
|
+
reasonCode: 'transport_error',
|
|
264
|
+
});
|
|
207
265
|
}
|
|
208
266
|
}, 250);
|
|
209
267
|
}
|
|
@@ -214,16 +272,24 @@ export class DaemonClient {
|
|
|
214
272
|
this.pendingGenericTransportErrorTimeout = null;
|
|
215
273
|
}
|
|
216
274
|
this.lastErrorValue = reason;
|
|
217
|
-
this.
|
|
218
|
-
|
|
275
|
+
this.scheduleReconnect({
|
|
276
|
+
reason,
|
|
277
|
+
event: 'TRANSPORT_ERROR',
|
|
278
|
+
reasonCode: 'transport_error',
|
|
279
|
+
});
|
|
219
280
|
}),
|
|
220
281
|
transport.onMessage((data) => this.handleTransportMessage(data)),
|
|
221
282
|
];
|
|
222
283
|
}
|
|
223
284
|
catch (error) {
|
|
285
|
+
this.resetConnectTimeout();
|
|
224
286
|
const message = error instanceof Error ? error.message : 'Failed to connect';
|
|
225
287
|
this.lastErrorValue = message;
|
|
226
|
-
this.scheduleReconnect(
|
|
288
|
+
this.scheduleReconnect({
|
|
289
|
+
reason: message,
|
|
290
|
+
event: 'CONNECT_FAILED',
|
|
291
|
+
reasonCode: 'connect_failed',
|
|
292
|
+
});
|
|
227
293
|
this.rejectConnect(error instanceof Error ? error : new Error(message));
|
|
228
294
|
}
|
|
229
295
|
}
|
|
@@ -244,6 +310,9 @@ export class DaemonClient {
|
|
|
244
310
|
this.connectReject = null;
|
|
245
311
|
}
|
|
246
312
|
async close() {
|
|
313
|
+
if (this.connectionState.status === 'disposed') {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
247
316
|
this.shouldReconnect = false;
|
|
248
317
|
this.connectPromise = null;
|
|
249
318
|
this.connectResolve = null;
|
|
@@ -252,15 +321,18 @@ export class DaemonClient {
|
|
|
252
321
|
clearTimeout(this.reconnectTimeout);
|
|
253
322
|
this.reconnectTimeout = null;
|
|
254
323
|
}
|
|
324
|
+
this.resetConnectTimeout();
|
|
255
325
|
this.disposeTransport(1000, 'Client closed');
|
|
256
326
|
this.clearWaiters(new Error('Daemon client closed'));
|
|
327
|
+
this.rejectPendingSendQueue(new Error('Daemon client closed'));
|
|
257
328
|
this.terminalStreams.clearAll();
|
|
258
|
-
this.
|
|
259
|
-
|
|
260
|
-
reason: 'client_closed',
|
|
261
|
-
});
|
|
329
|
+
this.lastWelcomeMessage = null;
|
|
330
|
+
this.updateConnectionState({ status: 'disposed' }, { event: 'DISPOSE', reason: 'Client closed', reasonCode: 'disposed' });
|
|
262
331
|
}
|
|
263
332
|
ensureConnected() {
|
|
333
|
+
if (this.connectionState.status === 'disposed') {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
264
336
|
if (!this.shouldReconnect) {
|
|
265
337
|
this.shouldReconnect = true;
|
|
266
338
|
}
|
|
@@ -589,6 +661,32 @@ export class DaemonClient {
|
|
|
589
661
|
},
|
|
590
662
|
});
|
|
591
663
|
}
|
|
664
|
+
async fetchWorkspaces(options) {
|
|
665
|
+
const resolvedRequestId = this.createRequestId(options?.requestId);
|
|
666
|
+
const message = SessionInboundMessageSchema.parse({
|
|
667
|
+
type: 'fetch_workspaces_request',
|
|
668
|
+
requestId: resolvedRequestId,
|
|
669
|
+
...(options?.filter ? { filter: options.filter } : {}),
|
|
670
|
+
...(options?.sort ? { sort: options.sort } : {}),
|
|
671
|
+
...(options?.page ? { page: options.page } : {}),
|
|
672
|
+
...(options?.subscribe ? { subscribe: options.subscribe } : {}),
|
|
673
|
+
});
|
|
674
|
+
return this.sendRequest({
|
|
675
|
+
requestId: resolvedRequestId,
|
|
676
|
+
message,
|
|
677
|
+
timeout: 10000,
|
|
678
|
+
options: { skipQueue: true },
|
|
679
|
+
select: (msg) => {
|
|
680
|
+
if (msg.type !== 'fetch_workspaces_response') {
|
|
681
|
+
return null;
|
|
682
|
+
}
|
|
683
|
+
if (msg.payload.requestId !== resolvedRequestId) {
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
686
|
+
return msg.payload;
|
|
687
|
+
},
|
|
688
|
+
});
|
|
689
|
+
}
|
|
592
690
|
async fetchAgent(agentId, requestId) {
|
|
593
691
|
const resolvedRequestId = this.createRequestId(requestId);
|
|
594
692
|
const message = SessionInboundMessageSchema.parse({
|
|
@@ -614,7 +712,10 @@ export class DaemonClient {
|
|
|
614
712
|
if (payload.error) {
|
|
615
713
|
throw new Error(payload.error);
|
|
616
714
|
}
|
|
617
|
-
|
|
715
|
+
if (!payload.agent) {
|
|
716
|
+
return null;
|
|
717
|
+
}
|
|
718
|
+
return { agent: payload.agent, project: payload.project ?? null };
|
|
618
719
|
}
|
|
619
720
|
resubscribeCheckoutDiffSubscriptions() {
|
|
620
721
|
if (this.checkoutDiffSubscriptions.size === 0) {
|
|
@@ -653,6 +754,7 @@ export class DaemonClient {
|
|
|
653
754
|
requestId,
|
|
654
755
|
config,
|
|
655
756
|
...(options.initialPrompt ? { initialPrompt: options.initialPrompt } : {}),
|
|
757
|
+
...(options.clientMessageId ? { clientMessageId: options.clientMessageId } : {}),
|
|
656
758
|
...(options.outputSchema ? { outputSchema: options.outputSchema } : {}),
|
|
657
759
|
...(options.images && options.images.length > 0 ? { images: options.images } : {}),
|
|
658
760
|
...(options.git ? { git: options.git } : {}),
|
|
@@ -991,6 +1093,32 @@ export class DaemonClient {
|
|
|
991
1093
|
},
|
|
992
1094
|
});
|
|
993
1095
|
}
|
|
1096
|
+
async shutdownServer(requestId) {
|
|
1097
|
+
const resolvedRequestId = this.createRequestId(requestId);
|
|
1098
|
+
const message = SessionInboundMessageSchema.parse({
|
|
1099
|
+
type: 'shutdown_server_request',
|
|
1100
|
+
requestId: resolvedRequestId,
|
|
1101
|
+
});
|
|
1102
|
+
return this.sendRequest({
|
|
1103
|
+
requestId: resolvedRequestId,
|
|
1104
|
+
message,
|
|
1105
|
+
timeout: 10000,
|
|
1106
|
+
options: { skipQueue: true },
|
|
1107
|
+
select: (msg) => {
|
|
1108
|
+
if (msg.type !== 'status') {
|
|
1109
|
+
return null;
|
|
1110
|
+
}
|
|
1111
|
+
const shutdown = ShutdownRequestedStatusPayloadSchema.safeParse(msg.payload);
|
|
1112
|
+
if (!shutdown.success) {
|
|
1113
|
+
return null;
|
|
1114
|
+
}
|
|
1115
|
+
if (shutdown.data.requestId !== resolvedRequestId) {
|
|
1116
|
+
return null;
|
|
1117
|
+
}
|
|
1118
|
+
return shutdown.data;
|
|
1119
|
+
},
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
994
1122
|
// ============================================================================
|
|
995
1123
|
// Audio / Voice
|
|
996
1124
|
// ============================================================================
|
|
@@ -1457,12 +1585,12 @@ export class DaemonClient {
|
|
|
1457
1585
|
// ============================================================================
|
|
1458
1586
|
// File Explorer
|
|
1459
1587
|
// ============================================================================
|
|
1460
|
-
async exploreFileSystem(
|
|
1588
|
+
async exploreFileSystem(cwd, path, mode = 'list', requestId) {
|
|
1461
1589
|
return this.sendCorrelatedSessionRequest({
|
|
1462
1590
|
requestId,
|
|
1463
1591
|
message: {
|
|
1464
1592
|
type: 'file_explorer_request',
|
|
1465
|
-
|
|
1593
|
+
cwd,
|
|
1466
1594
|
path,
|
|
1467
1595
|
mode,
|
|
1468
1596
|
},
|
|
@@ -1470,12 +1598,12 @@ export class DaemonClient {
|
|
|
1470
1598
|
timeout: 10000,
|
|
1471
1599
|
});
|
|
1472
1600
|
}
|
|
1473
|
-
async requestDownloadToken(
|
|
1601
|
+
async requestDownloadToken(cwd, path, requestId) {
|
|
1474
1602
|
return this.sendCorrelatedSessionRequest({
|
|
1475
1603
|
requestId,
|
|
1476
1604
|
message: {
|
|
1477
1605
|
type: 'file_download_token_request',
|
|
1478
|
-
|
|
1606
|
+
cwd,
|
|
1479
1607
|
path,
|
|
1480
1608
|
},
|
|
1481
1609
|
responseType: 'file_download_token_response',
|
|
@@ -1505,7 +1633,8 @@ export class DaemonClient {
|
|
|
1505
1633
|
cwd: options?.cwd,
|
|
1506
1634
|
},
|
|
1507
1635
|
responseType: 'list_provider_models_response',
|
|
1508
|
-
|
|
1636
|
+
// Provider SDK cold starts (especially model discovery) can exceed 30s.
|
|
1637
|
+
timeout: 45000,
|
|
1509
1638
|
});
|
|
1510
1639
|
}
|
|
1511
1640
|
async listAvailableProviders(options) {
|
|
@@ -1594,29 +1723,106 @@ export class DaemonClient {
|
|
|
1594
1723
|
// Waiting / Streaming Helpers
|
|
1595
1724
|
// ============================================================================
|
|
1596
1725
|
async waitForAgentUpsert(agentId, predicate, timeout = 60000) {
|
|
1597
|
-
const
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1726
|
+
const initialResult = await this.fetchAgent(agentId).catch(() => null);
|
|
1727
|
+
if (initialResult && predicate(initialResult.agent)) {
|
|
1728
|
+
return initialResult.agent;
|
|
1729
|
+
}
|
|
1730
|
+
const deadline = Date.now() + timeout;
|
|
1731
|
+
return await new Promise((resolve, reject) => {
|
|
1732
|
+
let settled = false;
|
|
1733
|
+
let pollInFlight = false;
|
|
1734
|
+
let pollTimer = null;
|
|
1735
|
+
let timeoutTimer = null;
|
|
1736
|
+
let unsubscribe = null;
|
|
1737
|
+
const finish = (result) => {
|
|
1738
|
+
if (settled) {
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1741
|
+
settled = true;
|
|
1742
|
+
if (timeoutTimer) {
|
|
1743
|
+
clearTimeout(timeoutTimer);
|
|
1744
|
+
timeoutTimer = null;
|
|
1745
|
+
}
|
|
1746
|
+
if (pollTimer) {
|
|
1747
|
+
clearInterval(pollTimer);
|
|
1748
|
+
pollTimer = null;
|
|
1749
|
+
}
|
|
1750
|
+
if (unsubscribe) {
|
|
1751
|
+
unsubscribe();
|
|
1752
|
+
unsubscribe = null;
|
|
1753
|
+
}
|
|
1754
|
+
if (result.kind === 'ok') {
|
|
1755
|
+
resolve(result.snapshot);
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
reject(result.error);
|
|
1759
|
+
};
|
|
1760
|
+
const maybeResolve = (snapshot) => {
|
|
1761
|
+
if (!snapshot) {
|
|
1762
|
+
return false;
|
|
1763
|
+
}
|
|
1764
|
+
if (!predicate(snapshot)) {
|
|
1765
|
+
return false;
|
|
1766
|
+
}
|
|
1767
|
+
finish({ kind: 'ok', snapshot });
|
|
1768
|
+
return true;
|
|
1769
|
+
};
|
|
1770
|
+
const poll = async () => {
|
|
1771
|
+
if (settled || pollInFlight) {
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1774
|
+
pollInFlight = true;
|
|
1775
|
+
try {
|
|
1776
|
+
const result = await this.fetchAgent(agentId).catch(() => null);
|
|
1777
|
+
maybeResolve(result?.agent ?? null);
|
|
1778
|
+
}
|
|
1779
|
+
finally {
|
|
1780
|
+
pollInFlight = false;
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
unsubscribe = this.on('agent_update', (message) => {
|
|
1784
|
+
if (settled) {
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
if (message.type !== 'agent_update') {
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1790
|
+
if (message.payload.kind !== 'upsert') {
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
const snapshot = message.payload.agent;
|
|
1794
|
+
if (snapshot.id !== agentId) {
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1797
|
+
maybeResolve(snapshot);
|
|
1798
|
+
});
|
|
1799
|
+
const remaining = Math.max(1, deadline - Date.now());
|
|
1800
|
+
timeoutTimer = setTimeout(() => {
|
|
1801
|
+
finish({
|
|
1802
|
+
kind: 'error',
|
|
1803
|
+
error: new Error(`Timed out waiting for agent ${agentId}`),
|
|
1804
|
+
});
|
|
1805
|
+
}, remaining);
|
|
1806
|
+
pollTimer = setInterval(() => {
|
|
1807
|
+
void poll();
|
|
1808
|
+
}, 250);
|
|
1809
|
+
void poll();
|
|
1810
|
+
});
|
|
1606
1811
|
}
|
|
1607
1812
|
async waitForFinish(agentId, timeout = 60000) {
|
|
1608
1813
|
const requestId = this.createRequestId();
|
|
1814
|
+
const hasTimeout = Number.isFinite(timeout) && timeout > 0;
|
|
1609
1815
|
const message = SessionInboundMessageSchema.parse({
|
|
1610
1816
|
type: 'wait_for_finish_request',
|
|
1611
1817
|
requestId,
|
|
1612
1818
|
agentId,
|
|
1613
|
-
timeoutMs: timeout,
|
|
1819
|
+
...(hasTimeout ? { timeoutMs: timeout } : {}),
|
|
1614
1820
|
});
|
|
1615
1821
|
const payload = await this.sendCorrelatedRequest({
|
|
1616
1822
|
requestId,
|
|
1617
1823
|
message,
|
|
1618
1824
|
responseType: 'wait_for_finish_response',
|
|
1619
|
-
timeout: timeout + 5000,
|
|
1825
|
+
timeout: hasTimeout ? timeout + 5000 : 0,
|
|
1620
1826
|
options: { skipQueue: true },
|
|
1621
1827
|
});
|
|
1622
1828
|
return {
|
|
@@ -1822,6 +2028,39 @@ export class DaemonClient {
|
|
|
1822
2028
|
createRequestId(requestId) {
|
|
1823
2029
|
return requestId ?? crypto.randomUUID();
|
|
1824
2030
|
}
|
|
2031
|
+
getLastWelcomeMessage() {
|
|
2032
|
+
return this.lastWelcomeMessage;
|
|
2033
|
+
}
|
|
2034
|
+
resolveTransportUrlForAttempt() {
|
|
2035
|
+
return this.config.url;
|
|
2036
|
+
}
|
|
2037
|
+
sendHelloMessage() {
|
|
2038
|
+
if (!this.transport) {
|
|
2039
|
+
this.scheduleReconnect({
|
|
2040
|
+
reason: 'Transport unavailable before hello',
|
|
2041
|
+
event: 'HELLO_TRANSPORT_MISSING',
|
|
2042
|
+
reasonCode: 'transport_error',
|
|
2043
|
+
});
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
try {
|
|
2047
|
+
this.transport.send(JSON.stringify({
|
|
2048
|
+
type: 'hello',
|
|
2049
|
+
clientId: this.config.clientId,
|
|
2050
|
+
clientType: this.config.clientType ?? 'cli',
|
|
2051
|
+
protocolVersion: 1,
|
|
2052
|
+
}));
|
|
2053
|
+
}
|
|
2054
|
+
catch (error) {
|
|
2055
|
+
const message = error instanceof Error ? error.message : 'Failed to send hello message';
|
|
2056
|
+
this.lastErrorValue = message;
|
|
2057
|
+
this.scheduleReconnect({
|
|
2058
|
+
reason: message,
|
|
2059
|
+
event: 'HELLO_SEND_FAILED',
|
|
2060
|
+
reasonCode: 'transport_error',
|
|
2061
|
+
});
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
1825
2064
|
disposeTransport(code = 1001, reason = 'Reconnecting') {
|
|
1826
2065
|
this.cleanupTransport();
|
|
1827
2066
|
if (this.transport) {
|
|
@@ -1835,6 +2074,7 @@ export class DaemonClient {
|
|
|
1835
2074
|
}
|
|
1836
2075
|
}
|
|
1837
2076
|
cleanupTransport() {
|
|
2077
|
+
this.resetConnectTimeout();
|
|
1838
2078
|
if (this.pendingGenericTransportErrorTimeout) {
|
|
1839
2079
|
clearTimeout(this.pendingGenericTransportErrorTimeout);
|
|
1840
2080
|
this.pendingGenericTransportErrorTimeout = null;
|
|
@@ -1849,12 +2089,39 @@ export class DaemonClient {
|
|
|
1849
2089
|
}
|
|
1850
2090
|
this.transportCleanup = [];
|
|
1851
2091
|
}
|
|
2092
|
+
resetConnectTimeout() {
|
|
2093
|
+
if (!this.connectTimeout) {
|
|
2094
|
+
return;
|
|
2095
|
+
}
|
|
2096
|
+
clearTimeout(this.connectTimeout);
|
|
2097
|
+
this.connectTimeout = null;
|
|
2098
|
+
}
|
|
1852
2099
|
handleTransportMessage(data) {
|
|
2100
|
+
const startedAtMs = getNowMs();
|
|
1853
2101
|
const rawData = data && typeof data === 'object' && 'data' in data ? data.data : data;
|
|
2102
|
+
if (typeof Blob !== 'undefined' &&
|
|
2103
|
+
rawData instanceof Blob &&
|
|
2104
|
+
typeof rawData.arrayBuffer === 'function') {
|
|
2105
|
+
void rawData
|
|
2106
|
+
.arrayBuffer()
|
|
2107
|
+
.then((buffer) => {
|
|
2108
|
+
this.handleTransportMessage(buffer);
|
|
2109
|
+
})
|
|
2110
|
+
.catch(() => {
|
|
2111
|
+
// Ignore failed blob decoding and allow reconnect logic to recover.
|
|
2112
|
+
});
|
|
2113
|
+
return;
|
|
2114
|
+
}
|
|
1854
2115
|
const rawBytes = asUint8Array(rawData);
|
|
1855
2116
|
if (rawBytes) {
|
|
1856
2117
|
const frame = decodeBinaryMuxFrame(rawBytes);
|
|
1857
2118
|
if (frame) {
|
|
2119
|
+
this.emitDiagnosticsEvent({
|
|
2120
|
+
type: 'transport_binary_frame',
|
|
2121
|
+
channel: frame.channel,
|
|
2122
|
+
messageType: frame.messageType,
|
|
2123
|
+
payloadBytes: frame.payload?.byteLength ?? 0,
|
|
2124
|
+
});
|
|
1858
2125
|
this.handleBinaryFrame(frame);
|
|
1859
2126
|
return;
|
|
1860
2127
|
}
|
|
@@ -1864,21 +2131,64 @@ export class DaemonClient {
|
|
|
1864
2131
|
return;
|
|
1865
2132
|
}
|
|
1866
2133
|
let parsedJson;
|
|
2134
|
+
let parseMs = 0;
|
|
1867
2135
|
try {
|
|
2136
|
+
const parseStartedAtMs = getNowMs();
|
|
1868
2137
|
parsedJson = JSON.parse(payload);
|
|
2138
|
+
parseMs = getNowMs() - parseStartedAtMs;
|
|
1869
2139
|
}
|
|
1870
2140
|
catch {
|
|
2141
|
+
this.emitDiagnosticsEvent({
|
|
2142
|
+
type: 'transport_message_timing',
|
|
2143
|
+
messageType: 'unknown',
|
|
2144
|
+
payloadBytes: payload.length,
|
|
2145
|
+
parseMs: 0,
|
|
2146
|
+
validateMs: 0,
|
|
2147
|
+
totalMs: getNowMs() - startedAtMs,
|
|
2148
|
+
outcome: 'parse_error',
|
|
2149
|
+
});
|
|
1871
2150
|
return;
|
|
1872
2151
|
}
|
|
2152
|
+
const validateStartedAtMs = getNowMs();
|
|
1873
2153
|
const parsed = WSOutboundMessageSchema.safeParse(parsedJson);
|
|
2154
|
+
const validateMs = getNowMs() - validateStartedAtMs;
|
|
1874
2155
|
if (!parsed.success) {
|
|
1875
|
-
const msgType = parsedJson?.
|
|
2156
|
+
const msgType = parsedJson?.type ?? 'unknown';
|
|
2157
|
+
this.emitDiagnosticsEvent({
|
|
2158
|
+
type: 'transport_message_timing',
|
|
2159
|
+
messageType: msgType,
|
|
2160
|
+
payloadBytes: payload.length,
|
|
2161
|
+
parseMs,
|
|
2162
|
+
validateMs,
|
|
2163
|
+
totalMs: getNowMs() - startedAtMs,
|
|
2164
|
+
outcome: 'validation_error',
|
|
2165
|
+
});
|
|
1876
2166
|
this.logger.warn({ msgType, error: parsed.error.message }, 'Message validation failed');
|
|
1877
2167
|
return;
|
|
1878
2168
|
}
|
|
2169
|
+
this.emitDiagnosticsEvent({
|
|
2170
|
+
type: 'transport_message_timing',
|
|
2171
|
+
messageType: parsed.data.type,
|
|
2172
|
+
payloadBytes: payload.length,
|
|
2173
|
+
parseMs,
|
|
2174
|
+
validateMs,
|
|
2175
|
+
totalMs: getNowMs() - startedAtMs,
|
|
2176
|
+
outcome: 'ok',
|
|
2177
|
+
});
|
|
1879
2178
|
if (parsed.data.type === 'pong') {
|
|
1880
2179
|
return;
|
|
1881
2180
|
}
|
|
2181
|
+
if (parsed.data.type === 'welcome') {
|
|
2182
|
+
this.lastWelcomeMessage = parsed.data;
|
|
2183
|
+
this.resetConnectTimeout();
|
|
2184
|
+
this.reconnectAttempt = 0;
|
|
2185
|
+
this.updateConnectionState({ status: 'connected' }, { event: 'HELLO_WELCOME' });
|
|
2186
|
+
this.resubscribeCheckoutDiffSubscriptions();
|
|
2187
|
+
this.resubscribeTerminalDirectorySubscriptions();
|
|
2188
|
+
this.flushPendingSendQueue();
|
|
2189
|
+
this.resolveConnect();
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
1882
2192
|
this.handleSessionMessage(parsed.data.message);
|
|
1883
2193
|
}
|
|
1884
2194
|
handleBinaryFrame(frame) {
|
|
@@ -1895,8 +2205,25 @@ export class DaemonClient {
|
|
|
1895
2205
|
return;
|
|
1896
2206
|
}
|
|
1897
2207
|
}
|
|
1898
|
-
updateConnectionState(next) {
|
|
2208
|
+
updateConnectionState(next, metadata) {
|
|
2209
|
+
const previous = this.connectionState;
|
|
1899
2210
|
this.connectionState = next;
|
|
2211
|
+
const reasonFromNext = next.status === 'disconnected' && typeof next.reason === 'string'
|
|
2212
|
+
? next.reason
|
|
2213
|
+
: null;
|
|
2214
|
+
const reason = metadata?.reason ?? reasonFromNext;
|
|
2215
|
+
const reasonCode = metadata?.reasonCode ?? toReasonCode(reason);
|
|
2216
|
+
this.logger.debug({
|
|
2217
|
+
serverId: this.logServerId,
|
|
2218
|
+
clientIdHash: this.logClientIdHash,
|
|
2219
|
+
from: previous.status,
|
|
2220
|
+
to: next.status,
|
|
2221
|
+
event: metadata?.event ?? 'STATE_UPDATE',
|
|
2222
|
+
connectionPath: this.logConnectionPath,
|
|
2223
|
+
generation: this.logGeneration,
|
|
2224
|
+
reasonCode,
|
|
2225
|
+
reason,
|
|
2226
|
+
}, 'DaemonClientTransition');
|
|
1900
2227
|
for (const listener of this.connectionListeners) {
|
|
1901
2228
|
try {
|
|
1902
2229
|
listener(next);
|
|
@@ -1906,20 +2233,13 @@ export class DaemonClient {
|
|
|
1906
2233
|
}
|
|
1907
2234
|
}
|
|
1908
2235
|
}
|
|
1909
|
-
scheduleReconnect(
|
|
2236
|
+
scheduleReconnect(input) {
|
|
1910
2237
|
if (this.reconnectTimeout) {
|
|
1911
2238
|
clearTimeout(this.reconnectTimeout);
|
|
1912
2239
|
this.reconnectTimeout = null;
|
|
1913
2240
|
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
return;
|
|
1917
|
-
}
|
|
1918
|
-
const attempt = this.reconnectAttempt;
|
|
1919
|
-
const baseDelay = this.config.reconnect?.baseDelayMs ?? DEFAULT_RECONNECT_BASE_DELAY_MS;
|
|
1920
|
-
const maxDelay = this.config.reconnect?.maxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS;
|
|
1921
|
-
const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
|
|
1922
|
-
this.reconnectAttempt = attempt + 1;
|
|
2241
|
+
const wasDisposed = this.connectionState.status === 'disposed';
|
|
2242
|
+
const reason = input?.reason;
|
|
1923
2243
|
if (typeof reason === 'string' && reason.trim().length > 0) {
|
|
1924
2244
|
this.lastErrorValue = reason.trim();
|
|
1925
2245
|
}
|
|
@@ -1928,10 +2248,28 @@ export class DaemonClient {
|
|
|
1928
2248
|
this.clearWaiters(new Error(reason ?? 'Connection lost'));
|
|
1929
2249
|
this.rejectPendingSendQueue(new Error(reason ?? 'Connection lost'));
|
|
1930
2250
|
this.terminalStreams.clearAll();
|
|
2251
|
+
this.lastWelcomeMessage = null;
|
|
2252
|
+
if (wasDisposed) {
|
|
2253
|
+
this.rejectConnect(new Error(reason ?? 'Daemon client is disposed'));
|
|
2254
|
+
return;
|
|
2255
|
+
}
|
|
1931
2256
|
this.updateConnectionState({
|
|
1932
2257
|
status: 'disconnected',
|
|
1933
2258
|
...(reason ? { reason } : {}),
|
|
2259
|
+
}, {
|
|
2260
|
+
event: input?.event ?? 'TRANSPORT_CLOSE',
|
|
2261
|
+
...(reason ? { reason } : {}),
|
|
2262
|
+
...(input?.reasonCode ? { reasonCode: input.reasonCode } : {}),
|
|
1934
2263
|
});
|
|
2264
|
+
if (!this.shouldReconnect || this.config.reconnect?.enabled === false) {
|
|
2265
|
+
this.rejectConnect(new Error(reason ?? 'Transport disconnected before connect'));
|
|
2266
|
+
return;
|
|
2267
|
+
}
|
|
2268
|
+
const attempt = this.reconnectAttempt;
|
|
2269
|
+
const baseDelay = this.config.reconnect?.baseDelayMs ?? DEFAULT_RECONNECT_BASE_DELAY_MS;
|
|
2270
|
+
const maxDelay = this.config.reconnect?.maxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS;
|
|
2271
|
+
const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
|
|
2272
|
+
this.reconnectAttempt = attempt + 1;
|
|
1935
2273
|
this.reconnectTimeout = setTimeout(() => {
|
|
1936
2274
|
this.reconnectTimeout = null;
|
|
1937
2275
|
if (!this.shouldReconnect) {
|
|
@@ -2002,6 +2340,12 @@ export class DaemonClient {
|
|
|
2002
2340
|
agentId: msg.payload.kind === 'upsert' ? msg.payload.agent.id : msg.payload.agentId,
|
|
2003
2341
|
payload: msg.payload,
|
|
2004
2342
|
};
|
|
2343
|
+
case 'workspace_update':
|
|
2344
|
+
return {
|
|
2345
|
+
type: 'workspace_update',
|
|
2346
|
+
workspaceId: msg.payload.kind === 'upsert' ? msg.payload.workspace.id : msg.payload.id,
|
|
2347
|
+
payload: msg.payload,
|
|
2348
|
+
};
|
|
2005
2349
|
case 'agent_stream':
|
|
2006
2350
|
return {
|
|
2007
2351
|
type: 'agent_stream',
|