@getpaseo/server 0.1.62 → 0.1.63
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/README.md +4 -0
- package/dist/server/client/daemon-client-runtime-metrics.d.ts +6 -6
- package/dist/server/client/daemon-client-runtime-metrics.d.ts.map +1 -1
- package/dist/server/client/daemon-client-transport-types.d.ts +13 -13
- package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -1
- package/dist/server/client/daemon-client-websocket-transport.d.ts +1 -1
- package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -1
- package/dist/server/client/daemon-client-websocket-transport.js +5 -4
- package/dist/server/client/daemon-client-websocket-transport.js.map +1 -1
- package/dist/server/client/daemon-client.d.ts +59 -37
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +62 -17
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/server/agent/agent-loading.d.ts.map +1 -1
- package/dist/server/server/agent/agent-loading.js +5 -3
- package/dist/server/server/agent/agent-loading.js.map +1 -1
- package/dist/server/server/agent/agent-manager.d.ts +45 -19
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
- package/dist/server/server/agent/agent-manager.js +393 -290
- package/dist/server/server/agent/agent-manager.js.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.d.ts +6 -6
- package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.js +46 -38
- package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
- package/dist/server/server/agent/agent-projections.d.ts +4 -6
- package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
- package/dist/server/server/agent/agent-projections.js +59 -65
- package/dist/server/server/agent/agent-projections.js.map +1 -1
- package/dist/server/server/agent/agent-response-loop.d.ts +4 -4
- package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -1
- package/dist/server/server/agent/agent-response-loop.js +58 -45
- package/dist/server/server/agent/agent-response-loop.js.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts +43 -40
- 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 +2 -2
- package/dist/server/server/agent/agent-storage.d.ts.map +1 -1
- package/dist/server/server/agent/agent-storage.js +29 -36
- package/dist/server/server/agent/agent-storage.js.map +1 -1
- package/dist/server/server/agent/agent-stream-coalescer.d.ts +6 -6
- package/dist/server/server/agent/agent-stream-coalescer.d.ts.map +1 -1
- package/dist/server/server/agent/agent-timeline-store-types.d.ts +10 -10
- package/dist/server/server/agent/agent-timeline-store-types.d.ts.map +1 -1
- package/dist/server/server/agent/agent-timeline-store.d.ts +2 -2
- package/dist/server/server/agent/agent-timeline-store.d.ts.map +1 -1
- package/dist/server/server/agent/agent-timeline-store.js +85 -64
- package/dist/server/server/agent/agent-timeline-store.js.map +1 -1
- package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
- package/dist/server/server/agent/mcp-server.js +185 -148
- package/dist/server/server/agent/mcp-server.js.map +1 -1
- package/dist/server/server/agent/mcp-shared.d.ts +9 -2
- package/dist/server/server/agent/mcp-shared.d.ts.map +1 -1
- package/dist/server/server/agent/mcp-shared.js +2 -0
- package/dist/server/server/agent/mcp-shared.js.map +1 -1
- package/dist/server/server/agent/model-resolver.d.ts +2 -2
- package/dist/server/server/agent/model-resolver.d.ts.map +1 -1
- package/dist/server/server/agent/model-resolver.js +9 -5
- package/dist/server/server/agent/model-resolver.js.map +1 -1
- package/dist/server/server/agent/provider-launch-config.d.ts +28 -17
- package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -1
- package/dist/server/server/agent/provider-launch-config.js +20 -9
- package/dist/server/server/agent/provider-launch-config.js.map +1 -1
- package/dist/server/server/agent/provider-registry.d.ts +4 -2
- package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
- package/dist/server/server/agent/provider-registry.js +24 -21
- package/dist/server/server/agent/provider-registry.js.map +1 -1
- package/dist/server/server/agent/provider-snapshot-manager.d.ts +6 -5
- package/dist/server/server/agent/provider-snapshot-manager.d.ts.map +1 -1
- package/dist/server/server/agent/provider-snapshot-manager.js +40 -31
- package/dist/server/server/agent/provider-snapshot-manager.js.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.d.ts +11 -12
- package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.js +148 -122
- package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
- package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +2 -0
- package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/sidechain-tracker.js +47 -45
- package/dist/server/server/agent/providers/claude/sidechain-tracker.js.map +1 -1
- package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +2 -2
- 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 +10 -5
- 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 +11 -2
- 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 +2 -2
- 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 +20 -13
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/claude-agent.d.ts +20 -8
- package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude-agent.js +610 -460
- 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 +2 -2
- 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-mapper.d.ts +2 -2
- 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 +49 -44
- 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 +27 -8
- 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 +564 -492
- 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 +2 -2
- package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex-rollout-timeline.js +58 -47
- package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -1
- package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +2 -2
- package/dist/server/server/agent/providers/copilot-acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/diagnostic-utils.d.ts +3 -3
- package/dist/server/server/agent/providers/diagnostic-utils.d.ts.map +1 -1
- package/dist/server/server/agent/providers/diagnostic-utils.js +82 -9
- package/dist/server/server/agent/providers/diagnostic-utils.js.map +1 -1
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +2 -2
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/mock-load-test-agent.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +2 -2
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts +2 -2
- package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.js +385 -360
- package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
- package/dist/server/server/agent/providers/pi-direct-agent.d.ts +1 -0
- package/dist/server/server/agent/providers/pi-direct-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/pi-direct-agent.js +109 -140
- package/dist/server/server/agent/providers/pi-direct-agent.js.map +1 -1
- package/dist/server/server/agent/providers/test-utils/session-stream-adapter.d.ts.map +1 -1
- package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js +3 -1
- package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js.map +1 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +3 -3
- 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 +102 -73
- 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 +2 -2
- package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
- package/dist/server/server/agent/stt-manager.d.ts.map +1 -1
- package/dist/server/server/agent/stt-manager.js +63 -53
- package/dist/server/server/agent/stt-manager.js.map +1 -1
- package/dist/server/server/agent/timeline-projection.d.ts +6 -6
- package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
- package/dist/server/server/agent/timeline-projection.js +11 -6
- 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 +1 -0
- package/dist/server/server/agent/tts-manager.js.map +1 -1
- package/dist/server/server/agent-attention-policy.d.ts +2 -2
- package/dist/server/server/agent-attention-policy.d.ts.map +1 -1
- package/dist/server/server/bootstrap.d.ts +4 -4
- package/dist/server/server/bootstrap.d.ts.map +1 -1
- package/dist/server/server/bootstrap.js +493 -485
- package/dist/server/server/bootstrap.js.map +1 -1
- package/dist/server/server/chat/chat-service.d.ts +1 -1
- package/dist/server/server/chat/chat-service.d.ts.map +1 -1
- package/dist/server/server/chat/chat-service.js +3 -3
- package/dist/server/server/chat/chat-service.js.map +1 -1
- package/dist/server/server/checkout-diff-manager.d.ts +2 -2
- package/dist/server/server/checkout-diff-manager.d.ts.map +1 -1
- package/dist/server/server/checkout-git-utils.d.ts +5 -3
- package/dist/server/server/checkout-git-utils.d.ts.map +1 -1
- package/dist/server/server/checkout-git-utils.js +1 -2
- package/dist/server/server/checkout-git-utils.js.map +1 -1
- package/dist/server/server/config.d.ts.map +1 -1
- package/dist/server/server/config.js +68 -39
- package/dist/server/server/config.js.map +1 -1
- package/dist/server/server/connection-offer.d.ts +2 -2
- package/dist/server/server/connection-offer.d.ts.map +1 -1
- package/dist/server/server/daemon-config-store.d.ts +5 -3
- package/dist/server/server/daemon-config-store.d.ts.map +1 -1
- package/dist/server/server/daemon-config-store.js +26 -0
- package/dist/server/server/daemon-config-store.js.map +1 -1
- package/dist/server/server/daemon-keypair.d.ts +2 -2
- package/dist/server/server/daemon-keypair.d.ts.map +1 -1
- package/dist/server/server/editor-targets.d.ts +4 -4
- package/dist/server/server/editor-targets.d.ts.map +1 -1
- package/dist/server/server/editor-targets.js +11 -15
- package/dist/server/server/editor-targets.js.map +1 -1
- package/dist/server/server/exports.d.ts +3 -3
- package/dist/server/server/exports.d.ts.map +1 -1
- package/dist/server/server/exports.js +1 -3
- package/dist/server/server/exports.js.map +1 -1
- package/dist/server/server/file-download/token-store.d.ts +4 -4
- package/dist/server/server/file-download/token-store.d.ts.map +1 -1
- package/dist/server/server/index.js +16 -12
- package/dist/server/server/index.js.map +1 -1
- package/dist/server/server/logger.d.ts +4 -4
- package/dist/server/server/logger.d.ts.map +1 -1
- package/dist/server/server/logger.js +26 -20
- package/dist/server/server/logger.js.map +1 -1
- package/dist/server/server/loop/rpc-schemas.d.ts +52 -52
- package/dist/server/server/loop-service.d.ts +13 -12
- package/dist/server/server/loop-service.d.ts.map +1 -1
- package/dist/server/server/loop-service.js +22 -18
- package/dist/server/server/loop-service.js.map +1 -1
- package/dist/server/server/package-version.d.ts +2 -2
- package/dist/server/server/package-version.d.ts.map +1 -1
- package/dist/server/server/package-version.js +19 -17
- package/dist/server/server/package-version.js.map +1 -1
- package/dist/server/server/pairing-offer.d.ts +2 -2
- package/dist/server/server/pairing-offer.d.ts.map +1 -1
- package/dist/server/server/paseo-env.d.ts +9 -0
- package/dist/server/server/paseo-env.d.ts.map +1 -0
- package/dist/server/server/paseo-env.js +70 -0
- package/dist/server/server/paseo-env.js.map +1 -0
- package/dist/server/server/paseo-worktree-archive-service.d.ts +4 -4
- package/dist/server/server/paseo-worktree-archive-service.d.ts.map +1 -1
- package/dist/server/server/paseo-worktree-archive-service.js +11 -11
- package/dist/server/server/paseo-worktree-archive-service.js.map +1 -1
- package/dist/server/server/persisted-config.d.ts +62 -62
- package/dist/server/server/persisted-config.d.ts.map +1 -1
- package/dist/server/server/persisted-config.js +4 -4
- package/dist/server/server/persisted-config.js.map +1 -1
- package/dist/server/server/persistence-hooks.d.ts +8 -9
- package/dist/server/server/persistence-hooks.d.ts.map +1 -1
- package/dist/server/server/persistence-hooks.js +4 -12
- package/dist/server/server/persistence-hooks.js.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 +1 -3
- package/dist/server/server/push/push-service.js.map +1 -1
- package/dist/server/server/relay-transport.d.ts +8 -8
- package/dist/server/server/relay-transport.d.ts.map +1 -1
- package/dist/server/server/relay-transport.js +27 -16
- package/dist/server/server/relay-transport.js.map +1 -1
- package/dist/server/server/schedule/service.d.ts.map +1 -1
- package/dist/server/server/schedule/service.js +2 -2
- package/dist/server/server/schedule/service.js.map +1 -1
- package/dist/server/server/script-health-monitor.d.ts.map +1 -1
- package/dist/server/server/script-health-monitor.js +7 -6
- package/dist/server/server/script-health-monitor.js.map +1 -1
- package/dist/server/server/script-proxy.js +1 -1
- package/dist/server/server/script-proxy.js.map +1 -1
- package/dist/server/server/script-status-projection.d.ts +4 -4
- package/dist/server/server/script-status-projection.d.ts.map +1 -1
- package/dist/server/server/script-status-projection.js +54 -44
- package/dist/server/server/script-status-projection.js.map +1 -1
- package/dist/server/server/server-id.d.ts +4 -4
- package/dist/server/server/server-id.d.ts.map +1 -1
- package/dist/server/server/session.d.ts +45 -14
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +1098 -761
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/server/speech/audio.js +1 -1
- package/dist/server/server/speech/audio.js.map +1 -1
- package/dist/server/server/speech/providers/local/config.d.ts +6 -6
- package/dist/server/server/speech/providers/local/config.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/config.js +41 -16
- package/dist/server/server/speech/providers/local/config.js.map +1 -1
- package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts +2 -2
- 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 +42 -19
- 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 +4 -4
- package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/runtime.js +108 -77
- package/dist/server/server/speech/providers/local/runtime.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +2 -2
- 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 +1 -4
- 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 +2 -2
- 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 +19 -19
- 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 +28 -7
- 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.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts +23 -4
- 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 +35 -28
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts +5 -5
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +7 -7
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +5 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.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 +3 -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 +2 -2
- 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 +3 -1
- 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 +10 -4
- package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +2 -2
- package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts.map +1 -1
- package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts +2 -2
- 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 +4 -1
- 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 +2 -2
- 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 +18 -11
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -1
- package/dist/server/server/speech/providers/openai/config.d.ts +2 -2
- package/dist/server/server/speech/providers/openai/config.d.ts.map +1 -1
- package/dist/server/server/speech/providers/openai/config.js +58 -31
- 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 +2 -2
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.js.map +1 -1
- package/dist/server/server/speech/providers/openai/runtime.d.ts +4 -4
- package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -1
- package/dist/server/server/speech/providers/openai/runtime.js +37 -32
- 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 +4 -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 +3 -2
- 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 +46 -17
- package/dist/server/server/speech/speech-config-resolver.js.map +1 -1
- package/dist/server/server/speech/speech-provider.d.ts +2 -2
- package/dist/server/server/speech/speech-provider.d.ts.map +1 -1
- package/dist/server/server/speech/speech-runtime.d.ts +6 -6
- package/dist/server/server/speech/speech-runtime.d.ts.map +1 -1
- package/dist/server/server/speech/speech-runtime.js +17 -17
- package/dist/server/server/speech/speech-runtime.js.map +1 -1
- package/dist/server/server/speech/speech-types.d.ts +2 -2
- package/dist/server/server/speech/speech-types.d.ts.map +1 -1
- package/dist/server/server/speech/turn-detection-provider.d.ts +2 -2
- package/dist/server/server/speech/turn-detection-provider.d.ts.map +1 -1
- package/dist/server/server/utils/diff-highlighter.d.ts +0 -3
- package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -1
- package/dist/server/server/utils/diff-highlighter.js +67 -66
- package/dist/server/server/utils/diff-highlighter.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 -0
- package/dist/server/server/voice/voice-turn-controller.js.map +1 -1
- package/dist/server/server/voice-types.d.ts +2 -2
- package/dist/server/server/voice-types.d.ts.map +1 -1
- package/dist/server/server/websocket-server.d.ts +31 -21
- package/dist/server/server/websocket-server.d.ts.map +1 -1
- package/dist/server/server/websocket-server.js +299 -197
- package/dist/server/server/websocket-server.js.map +1 -1
- package/dist/server/server/workspace-git-metadata.d.ts +2 -2
- package/dist/server/server/workspace-git-metadata.d.ts.map +1 -1
- package/dist/server/server/workspace-git-metadata.js +2 -32
- package/dist/server/server/workspace-git-metadata.js.map +1 -1
- package/dist/server/server/workspace-git-service.d.ts +8 -4
- package/dist/server/server/workspace-git-service.d.ts.map +1 -1
- package/dist/server/server/workspace-git-service.js +163 -115
- package/dist/server/server/workspace-git-service.js.map +1 -1
- package/dist/server/server/workspace-reconciliation-service.d.ts +5 -4
- package/dist/server/server/workspace-reconciliation-service.d.ts.map +1 -1
- package/dist/server/server/workspace-reconciliation-service.js +82 -82
- package/dist/server/server/workspace-reconciliation-service.js.map +1 -1
- package/dist/server/server/workspace-registry-bootstrap.d.ts.map +1 -1
- package/dist/server/server/workspace-registry-bootstrap.js +40 -33
- package/dist/server/server/workspace-registry-bootstrap.js.map +1 -1
- package/dist/server/server/workspace-registry-model.d.ts +19 -6
- package/dist/server/server/workspace-registry-model.d.ts.map +1 -1
- package/dist/server/server/workspace-registry-model.js +35 -21
- package/dist/server/server/workspace-registry-model.js.map +1 -1
- package/dist/server/server/workspace-registry.d.ts +2 -2
- package/dist/server/server/workspace-script-runtime-store.d.ts +2 -2
- package/dist/server/server/workspace-script-runtime-store.d.ts.map +1 -1
- package/dist/server/server/workspace-service-env.js +3 -3
- package/dist/server/server/workspace-service-env.js.map +1 -1
- package/dist/server/server/worktree-bootstrap.d.ts +4 -4
- package/dist/server/server/worktree-bootstrap.d.ts.map +1 -1
- package/dist/server/server/worktree-bootstrap.js +95 -67
- package/dist/server/server/worktree-bootstrap.js.map +1 -1
- package/dist/server/server/worktree-session.d.ts +8 -8
- package/dist/server/server/worktree-session.d.ts.map +1 -1
- package/dist/server/server/worktree-session.js +27 -19
- package/dist/server/server/worktree-session.js.map +1 -1
- package/dist/server/services/github-service.d.ts +1 -7
- package/dist/server/services/github-service.d.ts.map +1 -1
- package/dist/server/services/github-service.js +123 -143
- package/dist/server/services/github-service.js.map +1 -1
- package/dist/server/shared/agent-attention-notification.d.ts +9 -8
- package/dist/server/shared/agent-attention-notification.d.ts.map +1 -1
- package/dist/server/shared/agent-attention-notification.js +27 -17
- package/dist/server/shared/agent-attention-notification.js.map +1 -1
- package/dist/server/shared/daemon-endpoints.d.ts +2 -2
- package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
- package/dist/server/shared/daemon-endpoints.js +17 -2
- package/dist/server/shared/daemon-endpoints.js.map +1 -1
- package/dist/server/shared/messages.d.ts +21962 -3049
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +79 -2
- package/dist/server/shared/messages.js.map +1 -1
- package/dist/server/shared/terminal-stream-protocol.d.ts +2 -2
- package/dist/server/shared/terminal-stream-protocol.d.ts.map +1 -1
- package/dist/server/shared/tool-call-display.d.ts +2 -2
- package/dist/server/shared/tool-call-display.d.ts.map +1 -1
- package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
- package/dist/server/terminal/terminal-manager.js +1 -3
- package/dist/server/terminal/terminal-manager.js.map +1 -1
- package/dist/server/terminal/terminal-output-coalescer.d.ts +6 -6
- package/dist/server/terminal/terminal-output-coalescer.d.ts.map +1 -1
- package/dist/server/terminal/terminal.d.ts +3 -2
- package/dist/server/terminal/terminal.d.ts.map +1 -1
- package/dist/server/terminal/terminal.js +57 -19
- package/dist/server/terminal/terminal.js.map +1 -1
- package/dist/server/utils/checkout-git.d.ts +13 -12
- package/dist/server/utils/checkout-git.d.ts.map +1 -1
- package/dist/server/utils/checkout-git.js +351 -281
- package/dist/server/utils/checkout-git.js.map +1 -1
- package/dist/server/utils/directory-suggestions.js +12 -33
- package/dist/server/utils/directory-suggestions.js.map +1 -1
- package/dist/server/utils/executable.d.ts +1 -14
- package/dist/server/utils/executable.d.ts.map +1 -1
- package/dist/server/utils/executable.js +13 -49
- package/dist/server/utils/executable.js.map +1 -1
- package/dist/server/utils/github-remote.d.ts +13 -0
- package/dist/server/utils/github-remote.d.ts.map +1 -0
- package/dist/server/utils/github-remote.js +128 -0
- package/dist/server/utils/github-remote.js.map +1 -0
- package/dist/server/utils/paseo-config-file.d.ts +30 -0
- package/dist/server/utils/paseo-config-file.d.ts.map +1 -0
- package/dist/server/utils/paseo-config-file.js +90 -0
- package/dist/server/utils/paseo-config-file.js.map +1 -0
- package/dist/server/utils/paseo-config-schema.d.ts +290 -0
- package/dist/server/utils/paseo-config-schema.d.ts.map +1 -0
- package/dist/server/utils/paseo-config-schema.js +60 -0
- package/dist/server/utils/paseo-config-schema.js.map +1 -0
- package/dist/server/utils/project-icon.d.ts.map +1 -1
- package/dist/server/utils/project-icon.js +84 -109
- package/dist/server/utils/project-icon.js.map +1 -1
- package/dist/server/utils/promise-timeout.d.ts +2 -2
- package/dist/server/utils/promise-timeout.d.ts.map +1 -1
- package/dist/server/utils/run-git-command.d.ts +3 -1
- package/dist/server/utils/run-git-command.d.ts.map +1 -1
- package/dist/server/utils/run-git-command.js +10 -1
- package/dist/server/utils/run-git-command.js.map +1 -1
- package/dist/server/utils/script-hostname.d.ts +2 -2
- package/dist/server/utils/script-hostname.d.ts.map +1 -1
- package/dist/server/utils/spawn.d.ts +10 -3
- package/dist/server/utils/spawn.d.ts.map +1 -1
- package/dist/server/utils/spawn.js +30 -5
- package/dist/server/utils/spawn.js.map +1 -1
- package/dist/server/utils/windows-command.d.ts +15 -0
- package/dist/server/utils/windows-command.d.ts.map +1 -0
- package/dist/server/utils/windows-command.js +37 -0
- package/dist/server/utils/windows-command.js.map +1 -0
- package/dist/server/utils/worktree.d.ts +10 -7
- package/dist/server/utils/worktree.d.ts.map +1 -1
- package/dist/server/utils/worktree.js +64 -55
- package/dist/server/utils/worktree.js.map +1 -1
- package/dist/src/server/pid-lock.js.map +1 -1
- package/package.json +15 -20
- package/dist/server/server/agent/llm-openai.d.ts +0 -7
- package/dist/server/server/agent/llm-openai.d.ts.map +0 -1
- package/dist/server/server/agent/llm-openai.js +0 -8
- package/dist/server/server/agent/llm-openai.js.map +0 -1
- package/dist/server/server/agent/orchestrator.d.ts +0 -12
- package/dist/server/server/agent/orchestrator.d.ts.map +0 -1
- package/dist/server/server/agent/orchestrator.js +0 -12
- package/dist/server/server/agent/orchestrator.js.map +0 -1
- package/dist/server/server/types.d.ts +0 -5
- package/dist/server/server/types.d.ts.map +0 -1
- package/dist/server/server/types.js +0 -3
- package/dist/server/server/types.js.map +0 -1
- package/dist/server/server/workspace-registry.test-helpers.d.ts +0 -37
- package/dist/server/server/workspace-registry.test-helpers.d.ts.map +0 -1
- package/dist/server/server/workspace-registry.test-helpers.js +0 -121
- package/dist/server/server/workspace-registry.test-helpers.js.map +0 -1
|
@@ -2,7 +2,8 @@ import equal from "fast-deep-equal";
|
|
|
2
2
|
import { v4 as uuidv4 } from "uuid";
|
|
3
3
|
import { TTLCache } from "@isaacs/ttlcache";
|
|
4
4
|
import pMemoize from "p-memoize";
|
|
5
|
-
import {
|
|
5
|
+
import { realpathSync } from "node:fs";
|
|
6
|
+
import { basename, resolve, sep } from "path";
|
|
6
7
|
import { homedir } from "node:os";
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
import { isLegacyEditorTargetId, serializeAgentStreamEvent, } from "./messages.js";
|
|
@@ -16,7 +17,7 @@ import { isPaseoDictationDebugEnabled } from "./agent/recordings-debug.js";
|
|
|
16
17
|
import { listAvailableEditorTargets, openInEditorTarget } from "./editor-targets.js";
|
|
17
18
|
import { DictationStreamManager, } from "./dictation/dictation-stream-manager.js";
|
|
18
19
|
import { createVoiceTurnController, } from "./voice/voice-turn-controller.js";
|
|
19
|
-
import { buildConfigOverrides, extractTimestamps, toAgentPersistenceHandle, } from "./persistence-hooks.js";
|
|
20
|
+
import { buildConfigOverrides, extractTimestamps, isStoredAgentProviderAvailable, toAgentPersistenceHandle, } from "./persistence-hooks.js";
|
|
20
21
|
import { ensureAgentLoaded } from "./agent/agent-loading.js";
|
|
21
22
|
import { sendPromptToAgent, unarchiveAgentState } from "./agent/mcp-shared.js";
|
|
22
23
|
import { experimental_createMCPClient } from "ai";
|
|
@@ -24,6 +25,7 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/
|
|
|
24
25
|
import { buildWorkspaceScriptPayloads } from "./script-status-projection.js";
|
|
25
26
|
import { deriveProjectSlug } from "./workspace-git-metadata.js";
|
|
26
27
|
import { spawnWorkspaceScript } from "./worktree-bootstrap.js";
|
|
28
|
+
import { applyMutableProviderConfigToOverrides } from "./daemon-config-store.js";
|
|
27
29
|
import { buildProviderRegistry } from "./agent/provider-registry.js";
|
|
28
30
|
import { resolveSnapshotCwd } from "./agent/provider-snapshot-manager.js";
|
|
29
31
|
import { scheduleAgentMetadataGeneration } from "./agent/agent-metadata-generator.js";
|
|
@@ -32,11 +34,12 @@ import { MAX_EXPLICIT_AGENT_TITLE_CHARS } from "./agent/agent-title-limits.js";
|
|
|
32
34
|
import { appendTimelineItemIfAgentKnown, emitLiveTimelineItemIfAgentKnown, } from "./agent/timeline-append.js";
|
|
33
35
|
import { projectTimelineRows, selectTimelineWindowByProjectedLimit, } from "./agent/timeline-projection.js";
|
|
34
36
|
import { DEFAULT_STRUCTURED_GENERATION_PROVIDERS, StructuredAgentFallbackError, StructuredAgentResponseError, generateStructuredAgentResponseWithFallback, } from "./agent/agent-response-loop.js";
|
|
35
|
-
import { checkoutLiteFromGitSnapshot, normalizeWorkspaceId as normalizePersistedWorkspaceId, deriveProjectGroupingName,
|
|
37
|
+
import { checkoutLiteFromGitSnapshot, normalizeWorkspaceId as normalizePersistedWorkspaceId, deriveProjectGroupingName, classifyDirectoryForProjectMembership, deriveWorkspaceDisplayName, } from "./workspace-registry-model.js";
|
|
36
38
|
import { createPersistedProjectRecord, createPersistedWorkspaceRecord, } from "./workspace-registry.js";
|
|
37
39
|
import { buildVoiceModeSystemPrompt, stripVoiceModeSystemPrompt, wrapSpokenInput, } from "./voice-config.js";
|
|
38
40
|
import { isVoicePermissionAllowed } from "./voice-permission-policy.js";
|
|
39
41
|
import { listDirectoryEntries, readExplorerFile, getDownloadableFileInfo, } from "./file-explorer/service.js";
|
|
42
|
+
import { readPaseoConfigForEdit, writePaseoConfigForEdit, } from "../utils/paseo-config-file.js";
|
|
40
43
|
import { runAsyncWorktreeBootstrap } from "./worktree-bootstrap.js";
|
|
41
44
|
import { archivePersistedWorkspaceRecord } from "./workspace-archive-service.js";
|
|
42
45
|
import { WorkspaceReconciliationService } from "./workspace-reconciliation-service.js";
|
|
@@ -58,12 +61,97 @@ import { killTerminalsUnderPath as killWorktreeTerminalsUnderPath } from "./pase
|
|
|
58
61
|
import { toWorktreeWireError } from "./worktree-errors.js";
|
|
59
62
|
const MAX_INITIAL_AGENT_TITLE_CHARS = Math.min(60, MAX_EXPLICIT_AGENT_TITLE_CHARS);
|
|
60
63
|
const WORKSPACE_GIT_WATCH_REMOVED_STATE_KEY = "__removed__";
|
|
64
|
+
async function resolveKnownProjectRootForConfig(input) {
|
|
65
|
+
const requestedRoot = canonicalizeConfigRoot(input.repoRoot);
|
|
66
|
+
const projects = await input.projectRegistry.list();
|
|
67
|
+
for (const project of projects) {
|
|
68
|
+
if (project.archivedAt !== null) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const projectRoot = canonicalizeConfigRoot(project.rootPath);
|
|
72
|
+
if (requestedRoot === projectRoot) {
|
|
73
|
+
return projectRoot;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
function canonicalizeConfigRoot(repoRoot) {
|
|
79
|
+
const resolved = resolve(repoRoot);
|
|
80
|
+
try {
|
|
81
|
+
return stripTrailingPathSeparators(realpathSync(resolved));
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return stripTrailingPathSeparators(resolved);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function stripTrailingPathSeparators(path) {
|
|
88
|
+
let normalized = path;
|
|
89
|
+
while (normalized.length > 1 && normalized.endsWith(sep)) {
|
|
90
|
+
normalized = normalized.slice(0, -1);
|
|
91
|
+
}
|
|
92
|
+
return normalized;
|
|
93
|
+
}
|
|
61
94
|
// TODO: Remove once all app store clients are on >=0.1.45 and understand arbitrary provider strings.
|
|
62
95
|
// Clients before 0.1.45 validate providers with z.enum(["claude", "codex", "opencode"]) and reject
|
|
63
96
|
// the entire session message if they encounter an unknown provider.
|
|
64
97
|
const LEGACY_PROVIDER_IDS = new Set(["claude", "codex", "opencode"]);
|
|
65
98
|
const MIN_VERSION_ALL_PROVIDERS = "0.1.45";
|
|
66
99
|
const MIN_VERSION_FLEXIBLE_EDITOR_IDS = "0.1.50";
|
|
100
|
+
function errorToFriendlyMessage(error) {
|
|
101
|
+
if (error instanceof Error)
|
|
102
|
+
return error.message;
|
|
103
|
+
if (typeof error === "string")
|
|
104
|
+
return error;
|
|
105
|
+
return "Unknown error";
|
|
106
|
+
}
|
|
107
|
+
function resolveSubscriptionId(subscribe, requestedSubscriptionId) {
|
|
108
|
+
if (!subscribe)
|
|
109
|
+
return null;
|
|
110
|
+
if (requestedSubscriptionId && requestedSubscriptionId.length > 0) {
|
|
111
|
+
return requestedSubscriptionId;
|
|
112
|
+
}
|
|
113
|
+
return uuidv4();
|
|
114
|
+
}
|
|
115
|
+
function diffChangeTypeFor(file) {
|
|
116
|
+
if (file.isNew)
|
|
117
|
+
return "A";
|
|
118
|
+
if (file.isDeleted)
|
|
119
|
+
return "D";
|
|
120
|
+
return "M";
|
|
121
|
+
}
|
|
122
|
+
function buildWorkspaceCheckout(workspace, project) {
|
|
123
|
+
if (project.kind !== "git") {
|
|
124
|
+
return {
|
|
125
|
+
cwd: workspace.cwd,
|
|
126
|
+
isGit: false,
|
|
127
|
+
currentBranch: null,
|
|
128
|
+
remoteUrl: null,
|
|
129
|
+
worktreeRoot: null,
|
|
130
|
+
isPaseoOwnedWorktree: false,
|
|
131
|
+
mainRepoRoot: null,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
if (workspace.kind === "worktree") {
|
|
135
|
+
return {
|
|
136
|
+
cwd: workspace.cwd,
|
|
137
|
+
isGit: true,
|
|
138
|
+
currentBranch: workspace.displayName,
|
|
139
|
+
remoteUrl: null,
|
|
140
|
+
worktreeRoot: workspace.cwd,
|
|
141
|
+
isPaseoOwnedWorktree: true,
|
|
142
|
+
mainRepoRoot: project.rootPath,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
cwd: workspace.cwd,
|
|
147
|
+
isGit: true,
|
|
148
|
+
currentBranch: workspace.displayName,
|
|
149
|
+
remoteUrl: null,
|
|
150
|
+
worktreeRoot: workspace.cwd,
|
|
151
|
+
isPaseoOwnedWorktree: false,
|
|
152
|
+
mainRepoRoot: null,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
67
155
|
function isAppVersionAtLeast(appVersion, minVersion) {
|
|
68
156
|
if (!appVersion)
|
|
69
157
|
return false;
|
|
@@ -119,6 +207,50 @@ export function resolveCreateAgentTitles(options) {
|
|
|
119
207
|
provisionalTitle,
|
|
120
208
|
};
|
|
121
209
|
}
|
|
210
|
+
function parseFetchWorkspacesCursorSort(raw) {
|
|
211
|
+
const cursorSort = [];
|
|
212
|
+
for (const item of raw) {
|
|
213
|
+
if (!item ||
|
|
214
|
+
typeof item !== "object" ||
|
|
215
|
+
typeof item.key !== "string" ||
|
|
216
|
+
typeof item.direction !== "string") {
|
|
217
|
+
throw new SessionRequestError("invalid_cursor", "Invalid fetch_workspaces cursor");
|
|
218
|
+
}
|
|
219
|
+
const key = item.key;
|
|
220
|
+
const direction = item.direction;
|
|
221
|
+
if ((key !== "status_priority" &&
|
|
222
|
+
key !== "activity_at" &&
|
|
223
|
+
key !== "name" &&
|
|
224
|
+
key !== "project_id") ||
|
|
225
|
+
(direction !== "asc" && direction !== "desc")) {
|
|
226
|
+
throw new SessionRequestError("invalid_cursor", "Invalid fetch_workspaces cursor");
|
|
227
|
+
}
|
|
228
|
+
cursorSort.push({ key, direction });
|
|
229
|
+
}
|
|
230
|
+
return cursorSort;
|
|
231
|
+
}
|
|
232
|
+
function parseFetchAgentsCursorSort(raw) {
|
|
233
|
+
const cursorSort = [];
|
|
234
|
+
for (const item of raw) {
|
|
235
|
+
if (!item ||
|
|
236
|
+
typeof item !== "object" ||
|
|
237
|
+
typeof item.key !== "string" ||
|
|
238
|
+
typeof item.direction !== "string") {
|
|
239
|
+
throw new SessionRequestError("invalid_cursor", "Invalid fetch_agents cursor");
|
|
240
|
+
}
|
|
241
|
+
const key = item.key;
|
|
242
|
+
const direction = item.direction;
|
|
243
|
+
if ((key !== "status_priority" &&
|
|
244
|
+
key !== "created_at" &&
|
|
245
|
+
key !== "updated_at" &&
|
|
246
|
+
key !== "title") ||
|
|
247
|
+
(direction !== "asc" && direction !== "desc")) {
|
|
248
|
+
throw new SessionRequestError("invalid_cursor", "Invalid fetch_agents cursor");
|
|
249
|
+
}
|
|
250
|
+
cursorSort.push({ key, direction });
|
|
251
|
+
}
|
|
252
|
+
return cursorSort;
|
|
253
|
+
}
|
|
122
254
|
export function resolveWaitForFinishError(options) {
|
|
123
255
|
if (options.status !== "error") {
|
|
124
256
|
return null;
|
|
@@ -292,53 +424,13 @@ export class Session {
|
|
|
292
424
|
this.getDaemonTcpPort = getDaemonTcpPort ?? null;
|
|
293
425
|
this.getDaemonTcpHost = getDaemonTcpHost ?? null;
|
|
294
426
|
this.resolveScriptHealth = resolveScriptHealth ?? null;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
if (this.providerSnapshotManager) {
|
|
299
|
-
const handleProviderSnapshotChange = (entries, cwd) => {
|
|
300
|
-
// COMPAT(providersSnapshot): keep provider visibility gating for older clients.
|
|
301
|
-
const visibleEntries = entries.filter((entry) => this.isProviderVisibleToClient(entry.provider));
|
|
302
|
-
this.emit({
|
|
303
|
-
type: "providers_snapshot_update",
|
|
304
|
-
payload: {
|
|
305
|
-
cwd,
|
|
306
|
-
entries: visibleEntries,
|
|
307
|
-
generatedAt: new Date().toISOString(),
|
|
308
|
-
},
|
|
309
|
-
});
|
|
310
|
-
};
|
|
311
|
-
this.providerSnapshotManager.on("change", handleProviderSnapshotChange);
|
|
312
|
-
this.unsubscribeProviderSnapshotEvents = () => {
|
|
313
|
-
this.providerSnapshotManager?.off("change", handleProviderSnapshotChange);
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
this.resolveVoiceTurnDetection = toResolver(voice?.turnDetection ?? null);
|
|
317
|
-
this.registerVoiceSpeakHandler = voiceBridge?.registerVoiceSpeakHandler;
|
|
318
|
-
this.unregisterVoiceSpeakHandler = voiceBridge?.unregisterVoiceSpeakHandler;
|
|
319
|
-
this.registerVoiceCallerContext = voiceBridge?.registerVoiceCallerContext;
|
|
320
|
-
this.unregisterVoiceCallerContext = voiceBridge?.unregisterVoiceCallerContext;
|
|
321
|
-
this.getSpeechReadiness = dictation?.getSpeechReadiness;
|
|
427
|
+
this.subscribeToOptionalManagers();
|
|
428
|
+
this.bindVoiceBridges({ voice, voiceBridge, dictation });
|
|
322
429
|
this.agentProviderRuntimeSettings = agentProviderRuntimeSettings;
|
|
323
430
|
this.providerOverrides = providerOverrides;
|
|
324
431
|
this.isDev = isDev === true;
|
|
325
432
|
this.abortController = new AbortController();
|
|
326
|
-
this.
|
|
327
|
-
runtimeSettings: this.agentProviderRuntimeSettings,
|
|
328
|
-
providerOverrides: this.providerOverrides,
|
|
329
|
-
workspaceGitService: this.workspaceGitService,
|
|
330
|
-
isDev: this.isDev,
|
|
331
|
-
});
|
|
332
|
-
// Initialize per-session managers
|
|
333
|
-
this.ttsManager = new TTSManager(this.sessionId, this.sessionLogger, tts);
|
|
334
|
-
this.sttManager = new STTManager(this.sessionId, this.sessionLogger, stt);
|
|
335
|
-
this.dictationStreamManager = new DictationStreamManager({
|
|
336
|
-
logger: this.sessionLogger,
|
|
337
|
-
sessionId: this.sessionId,
|
|
338
|
-
emit: (msg) => this.handleDictationManagerMessage(msg),
|
|
339
|
-
stt: dictation?.stt ?? null,
|
|
340
|
-
finalTimeoutMs: dictation?.finalTimeoutMs,
|
|
341
|
-
});
|
|
433
|
+
this.initializePerSessionManagers({ tts, stt, dictation });
|
|
342
434
|
// Initialize agent MCP client asynchronously
|
|
343
435
|
void this.initializeAgentMcp();
|
|
344
436
|
this.subscribeToAgentEvents();
|
|
@@ -427,16 +519,11 @@ export class Session {
|
|
|
427
519
|
return;
|
|
428
520
|
}
|
|
429
521
|
this.sessionLogger.debug({ agentId, lifecycle: snapshot.lifecycle, hasInFlightRun }, "interruptAgentIfRunning: interrupting");
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
this.sessionLogger.warn({ agentId }, "interruptAgentIfRunning: reported running but no active run was cancelled");
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
catch (error) {
|
|
439
|
-
throw error;
|
|
522
|
+
const t0 = Date.now();
|
|
523
|
+
const cancelled = await this.agentManager.cancelAgentRun(agentId);
|
|
524
|
+
this.sessionLogger.debug({ agentId, cancelled, durationMs: Date.now() - t0 }, "interruptAgentIfRunning: cancelAgentRun completed");
|
|
525
|
+
if (!cancelled) {
|
|
526
|
+
this.sessionLogger.warn({ agentId }, "interruptAgentIfRunning: reported running but no active run was cancelled");
|
|
440
527
|
}
|
|
441
528
|
}
|
|
442
529
|
hasActiveAgentRun(agentId) {
|
|
@@ -464,12 +551,7 @@ export class Session {
|
|
|
464
551
|
}
|
|
465
552
|
catch (error) {
|
|
466
553
|
this.handleAgentRunError(agentId, error, "Failed to start agent run");
|
|
467
|
-
|
|
468
|
-
? error.message
|
|
469
|
-
: typeof error === "string"
|
|
470
|
-
? error
|
|
471
|
-
: "Unknown error";
|
|
472
|
-
return { ok: false, error: message };
|
|
554
|
+
return { ok: false, error: errorToFriendlyMessage(error) };
|
|
473
555
|
}
|
|
474
556
|
void (async () => {
|
|
475
557
|
try {
|
|
@@ -486,7 +568,7 @@ export class Session {
|
|
|
486
568
|
return { ok: true };
|
|
487
569
|
}
|
|
488
570
|
handleAgentRunError(agentId, error, context) {
|
|
489
|
-
const message = error
|
|
571
|
+
const message = errorToFriendlyMessage(error);
|
|
490
572
|
this.sessionLogger.error({ err: error, agentId, context }, `${context} for agent ${agentId}`);
|
|
491
573
|
this.emit({
|
|
492
574
|
type: "activity_log",
|
|
@@ -522,6 +604,50 @@ export class Session {
|
|
|
522
604
|
/**
|
|
523
605
|
* Subscribe to AgentManager events and forward them to the client
|
|
524
606
|
*/
|
|
607
|
+
subscribeToOptionalManagers() {
|
|
608
|
+
if (this.terminalManager) {
|
|
609
|
+
this.unsubscribeTerminalsChanged = this.terminalManager.subscribeTerminalsChanged((event) => this.handleTerminalsChanged(event));
|
|
610
|
+
}
|
|
611
|
+
if (this.providerSnapshotManager) {
|
|
612
|
+
const handleProviderSnapshotChange = (entries, cwd) => {
|
|
613
|
+
// COMPAT(providersSnapshot): keep provider visibility gating for older clients.
|
|
614
|
+
const visibleEntries = entries.filter((entry) => this.isProviderVisibleToClient(entry.provider));
|
|
615
|
+
this.emit({
|
|
616
|
+
type: "providers_snapshot_update",
|
|
617
|
+
payload: {
|
|
618
|
+
cwd,
|
|
619
|
+
entries: visibleEntries,
|
|
620
|
+
generatedAt: new Date().toISOString(),
|
|
621
|
+
},
|
|
622
|
+
});
|
|
623
|
+
};
|
|
624
|
+
this.providerSnapshotManager.on("change", handleProviderSnapshotChange);
|
|
625
|
+
this.unsubscribeProviderSnapshotEvents = () => {
|
|
626
|
+
this.providerSnapshotManager?.off("change", handleProviderSnapshotChange);
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
bindVoiceBridges(params) {
|
|
631
|
+
const { voice, voiceBridge, dictation } = params;
|
|
632
|
+
this.resolveVoiceTurnDetection = toResolver(voice?.turnDetection ?? null);
|
|
633
|
+
this.registerVoiceSpeakHandler = voiceBridge?.registerVoiceSpeakHandler;
|
|
634
|
+
this.unregisterVoiceSpeakHandler = voiceBridge?.unregisterVoiceSpeakHandler;
|
|
635
|
+
this.registerVoiceCallerContext = voiceBridge?.registerVoiceCallerContext;
|
|
636
|
+
this.unregisterVoiceCallerContext = voiceBridge?.unregisterVoiceCallerContext;
|
|
637
|
+
this.getSpeechReadiness = dictation?.getSpeechReadiness;
|
|
638
|
+
}
|
|
639
|
+
initializePerSessionManagers(params) {
|
|
640
|
+
const { tts, stt, dictation } = params;
|
|
641
|
+
this.ttsManager = new TTSManager(this.sessionId, this.sessionLogger, tts);
|
|
642
|
+
this.sttManager = new STTManager(this.sessionId, this.sessionLogger, stt);
|
|
643
|
+
this.dictationStreamManager = new DictationStreamManager({
|
|
644
|
+
logger: this.sessionLogger,
|
|
645
|
+
sessionId: this.sessionId,
|
|
646
|
+
emit: (msg) => this.handleDictationManagerMessage(msg),
|
|
647
|
+
stt: dictation?.stt ?? null,
|
|
648
|
+
finalTimeoutMs: dictation?.finalTimeoutMs,
|
|
649
|
+
});
|
|
650
|
+
}
|
|
525
651
|
subscribeToAgentEvents() {
|
|
526
652
|
if (this.unsubscribeAgentEvents) {
|
|
527
653
|
this.unsubscribeAgentEvents();
|
|
@@ -618,8 +744,19 @@ export class Session {
|
|
|
618
744
|
payload.archivedAt = storedRecord?.archivedAt ?? null;
|
|
619
745
|
return payload;
|
|
620
746
|
}
|
|
621
|
-
|
|
622
|
-
return
|
|
747
|
+
getProviderRegistry() {
|
|
748
|
+
return buildProviderRegistry(this.sessionLogger, {
|
|
749
|
+
runtimeSettings: this.agentProviderRuntimeSettings,
|
|
750
|
+
providerOverrides: applyMutableProviderConfigToOverrides(this.providerOverrides, this.daemonConfigStore.get().providers),
|
|
751
|
+
workspaceGitService: this.workspaceGitService,
|
|
752
|
+
isDev: this.isDev,
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
getRegisteredProviderIds() {
|
|
756
|
+
return Object.keys(this.getProviderRegistry());
|
|
757
|
+
}
|
|
758
|
+
buildStoredAgentPayload(record, registeredProviderIds = this.getRegisteredProviderIds()) {
|
|
759
|
+
return buildStoredAgentPayload(record, registeredProviderIds);
|
|
623
760
|
}
|
|
624
761
|
isProviderVisibleToClient(provider) {
|
|
625
762
|
if (clientSupportsAllProviders(this.appVersion)) {
|
|
@@ -633,44 +770,34 @@ export class Session {
|
|
|
633
770
|
}
|
|
634
771
|
return editors.filter((editor) => isLegacyEditorTargetId(editor.id));
|
|
635
772
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
const matchesLabels = Object.entries(filter.labels).every(([key, value]) => agent.labels[key] === value);
|
|
640
|
-
if (!matchesLabels) {
|
|
641
|
-
return false;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
const includeArchived = filter?.includeArchived ?? false;
|
|
645
|
-
if (!includeArchived && agent.archivedAt) {
|
|
646
|
-
return false;
|
|
773
|
+
agentThinkingOptionMatchesFilter(agent, filter) {
|
|
774
|
+
if (filter.thinkingOptionId === undefined) {
|
|
775
|
+
return true;
|
|
647
776
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
777
|
+
const expectedThinkingOptionId = resolveEffectiveThinkingOptionId({
|
|
778
|
+
configuredThinkingOptionId: filter.thinkingOptionId ?? null,
|
|
779
|
+
});
|
|
780
|
+
const resolvedThinkingOptionId = agent.effectiveThinkingOptionId ??
|
|
781
|
+
resolveEffectiveThinkingOptionId({
|
|
782
|
+
runtimeInfo: agent.runtimeInfo,
|
|
783
|
+
configuredThinkingOptionId: agent.thinkingOptionId ?? null,
|
|
651
784
|
});
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
});
|
|
657
|
-
if (resolvedThinkingOptionId !== expectedThinkingOptionId) {
|
|
658
|
-
return false;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
if (filter?.statuses && filter.statuses.length > 0) {
|
|
785
|
+
return resolvedThinkingOptionId === expectedThinkingOptionId;
|
|
786
|
+
}
|
|
787
|
+
matchesAgentStructuralFilter(agent, project, filter) {
|
|
788
|
+
if (filter.statuses && filter.statuses.length > 0) {
|
|
662
789
|
const statuses = new Set(filter.statuses);
|
|
663
790
|
if (!statuses.has(agent.status)) {
|
|
664
791
|
return false;
|
|
665
792
|
}
|
|
666
793
|
}
|
|
667
|
-
if (typeof filter
|
|
794
|
+
if (typeof filter.requiresAttention === "boolean") {
|
|
668
795
|
const requiresAttention = agent.requiresAttention ?? false;
|
|
669
796
|
if (requiresAttention !== filter.requiresAttention) {
|
|
670
797
|
return false;
|
|
671
798
|
}
|
|
672
799
|
}
|
|
673
|
-
if (filter
|
|
800
|
+
if (filter.projectKeys && filter.projectKeys.length > 0) {
|
|
674
801
|
const projectKeys = new Set(filter.projectKeys.filter((item) => item.trim().length > 0));
|
|
675
802
|
if (projectKeys.size > 0 && !projectKeys.has(project.projectKey)) {
|
|
676
803
|
return false;
|
|
@@ -678,6 +805,26 @@ export class Session {
|
|
|
678
805
|
}
|
|
679
806
|
return true;
|
|
680
807
|
}
|
|
808
|
+
matchesAgentFilter(options) {
|
|
809
|
+
const { agent, project, filter } = options;
|
|
810
|
+
if (filter?.labels) {
|
|
811
|
+
const matchesLabels = Object.entries(filter.labels).every(([key, value]) => agent.labels[key] === value);
|
|
812
|
+
if (!matchesLabels) {
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
const includeArchived = filter?.includeArchived ?? false;
|
|
817
|
+
if (!includeArchived && agent.archivedAt) {
|
|
818
|
+
return false;
|
|
819
|
+
}
|
|
820
|
+
if (filter && !this.agentThinkingOptionMatchesFilter(agent, filter)) {
|
|
821
|
+
return false;
|
|
822
|
+
}
|
|
823
|
+
if (filter && !this.matchesAgentStructuralFilter(agent, project, filter)) {
|
|
824
|
+
return false;
|
|
825
|
+
}
|
|
826
|
+
return true;
|
|
827
|
+
}
|
|
681
828
|
getAgentUpdateTargetId(update) {
|
|
682
829
|
return update.kind === "remove" ? update.agentId : update.agent.id;
|
|
683
830
|
}
|
|
@@ -724,54 +871,26 @@ export class Session {
|
|
|
724
871
|
const workspaceId = this.resolveRegisteredWorkspaceIdForCwd(normalizedCwd, workspaces);
|
|
725
872
|
return workspaces.find((workspace) => workspace.workspaceId === workspaceId) ?? null;
|
|
726
873
|
}
|
|
874
|
+
async findExactWorkspaceByDirectory(cwd, options) {
|
|
875
|
+
const normalizedCwd = await this.resolveWorkspaceDirectory(cwd, options);
|
|
876
|
+
const workspaces = await this.workspaceRegistry.list();
|
|
877
|
+
return workspaces.find((workspace) => workspace.cwd === normalizedCwd) ?? null;
|
|
878
|
+
}
|
|
727
879
|
async resolveWorkspaceDirectory(cwd, options) {
|
|
728
880
|
const normalizedCwd = normalizePersistedWorkspaceId(cwd);
|
|
729
881
|
if (options?.refreshGit === false) {
|
|
730
882
|
const snapshot = this.workspaceGitService.peekSnapshot(normalizedCwd);
|
|
731
883
|
return normalizePersistedWorkspaceId(snapshot?.git.repoRoot ?? normalizedCwd);
|
|
732
884
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
return normalizePersistedWorkspaceId(snapshot.git.repoRoot ?? normalizedCwd);
|
|
736
|
-
}
|
|
737
|
-
catch {
|
|
738
|
-
return normalizedCwd;
|
|
739
|
-
}
|
|
885
|
+
const checkout = await this.workspaceGitService.getCheckout(normalizedCwd);
|
|
886
|
+
return normalizePersistedWorkspaceId(checkout.worktreeRoot ?? normalizedCwd);
|
|
740
887
|
}
|
|
741
888
|
async buildProjectPlacementForWorkspace(workspace, projectRecord) {
|
|
742
889
|
const project = projectRecord ?? (await this.projectRegistry.get(workspace.projectId));
|
|
743
890
|
if (!project) {
|
|
744
891
|
throw new Error(`Project not found for workspace ${workspace.workspaceId}`);
|
|
745
892
|
}
|
|
746
|
-
const checkout = project
|
|
747
|
-
? {
|
|
748
|
-
cwd: workspace.cwd,
|
|
749
|
-
isGit: false,
|
|
750
|
-
currentBranch: null,
|
|
751
|
-
remoteUrl: null,
|
|
752
|
-
worktreeRoot: null,
|
|
753
|
-
isPaseoOwnedWorktree: false,
|
|
754
|
-
mainRepoRoot: null,
|
|
755
|
-
}
|
|
756
|
-
: workspace.kind === "worktree"
|
|
757
|
-
? {
|
|
758
|
-
cwd: workspace.cwd,
|
|
759
|
-
isGit: true,
|
|
760
|
-
currentBranch: workspace.displayName,
|
|
761
|
-
remoteUrl: null,
|
|
762
|
-
worktreeRoot: workspace.cwd,
|
|
763
|
-
isPaseoOwnedWorktree: true,
|
|
764
|
-
mainRepoRoot: project.rootPath,
|
|
765
|
-
}
|
|
766
|
-
: {
|
|
767
|
-
cwd: workspace.cwd,
|
|
768
|
-
isGit: true,
|
|
769
|
-
currentBranch: workspace.displayName,
|
|
770
|
-
remoteUrl: null,
|
|
771
|
-
worktreeRoot: workspace.cwd,
|
|
772
|
-
isPaseoOwnedWorktree: false,
|
|
773
|
-
mainRepoRoot: null,
|
|
774
|
-
};
|
|
893
|
+
const checkout = buildWorkspaceCheckout(workspace, project);
|
|
775
894
|
return {
|
|
776
895
|
projectKey: project.projectId,
|
|
777
896
|
projectName: project.displayName,
|
|
@@ -851,360 +970,7 @@ export class Session {
|
|
|
851
970
|
try {
|
|
852
971
|
this.sessionLogger.trace({ messageType: msg.type, payloadBytes: JSON.stringify(msg).length }, "inbound message");
|
|
853
972
|
try {
|
|
854
|
-
|
|
855
|
-
case "voice_audio_chunk":
|
|
856
|
-
await this.handleAudioChunk(msg);
|
|
857
|
-
break;
|
|
858
|
-
case "abort_request":
|
|
859
|
-
await this.handleAbort();
|
|
860
|
-
break;
|
|
861
|
-
case "audio_played":
|
|
862
|
-
this.handleAudioPlayed(msg.id);
|
|
863
|
-
break;
|
|
864
|
-
case "fetch_agents_request":
|
|
865
|
-
await this.handleFetchAgents(msg);
|
|
866
|
-
break;
|
|
867
|
-
case "fetch_agent_history_request":
|
|
868
|
-
await this.handleFetchAgentHistory(msg);
|
|
869
|
-
break;
|
|
870
|
-
case "fetch_workspaces_request":
|
|
871
|
-
await this.handleFetchWorkspacesRequest(msg);
|
|
872
|
-
break;
|
|
873
|
-
case "fetch_agent_request":
|
|
874
|
-
await this.handleFetchAgent(msg.agentId, msg.requestId);
|
|
875
|
-
break;
|
|
876
|
-
case "delete_agent_request":
|
|
877
|
-
await this.handleDeleteAgentRequest(msg.agentId, msg.requestId);
|
|
878
|
-
break;
|
|
879
|
-
case "archive_agent_request":
|
|
880
|
-
await this.handleArchiveAgentRequest(msg.agentId, msg.requestId);
|
|
881
|
-
break;
|
|
882
|
-
case "close_items_request":
|
|
883
|
-
await this.handleCloseItemsRequest(msg);
|
|
884
|
-
break;
|
|
885
|
-
case "update_agent_request":
|
|
886
|
-
await this.handleUpdateAgentRequest(msg.agentId, msg.name, msg.labels, msg.requestId);
|
|
887
|
-
break;
|
|
888
|
-
case "set_voice_mode":
|
|
889
|
-
await this.handleSetVoiceMode(msg.enabled, msg.agentId, msg.requestId);
|
|
890
|
-
break;
|
|
891
|
-
case "send_agent_message_request":
|
|
892
|
-
await this.handleSendAgentMessageRequest(msg);
|
|
893
|
-
break;
|
|
894
|
-
case "wait_for_finish_request":
|
|
895
|
-
await this.handleWaitForFinish(msg.agentId, msg.requestId, msg.timeoutMs);
|
|
896
|
-
break;
|
|
897
|
-
case "get_daemon_config_request":
|
|
898
|
-
this.emit({
|
|
899
|
-
type: "get_daemon_config_response",
|
|
900
|
-
payload: {
|
|
901
|
-
requestId: msg.requestId,
|
|
902
|
-
config: this.daemonConfigStore.get(),
|
|
903
|
-
},
|
|
904
|
-
});
|
|
905
|
-
break;
|
|
906
|
-
case "set_daemon_config_request":
|
|
907
|
-
this.emit({
|
|
908
|
-
type: "set_daemon_config_response",
|
|
909
|
-
payload: {
|
|
910
|
-
requestId: msg.requestId,
|
|
911
|
-
config: this.daemonConfigStore.patch(msg.config),
|
|
912
|
-
},
|
|
913
|
-
});
|
|
914
|
-
break;
|
|
915
|
-
case "dictation_stream_start":
|
|
916
|
-
{
|
|
917
|
-
const unavailable = this.resolveVoiceFeatureUnavailableContext("dictation");
|
|
918
|
-
if (unavailable) {
|
|
919
|
-
this.emit({
|
|
920
|
-
type: "dictation_stream_error",
|
|
921
|
-
payload: {
|
|
922
|
-
dictationId: msg.dictationId,
|
|
923
|
-
error: unavailable.message,
|
|
924
|
-
retryable: unavailable.retryable,
|
|
925
|
-
reasonCode: unavailable.reasonCode,
|
|
926
|
-
missingModelIds: unavailable.missingModelIds,
|
|
927
|
-
},
|
|
928
|
-
});
|
|
929
|
-
break;
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
await this.dictationStreamManager.handleStart(msg.dictationId, msg.format);
|
|
933
|
-
break;
|
|
934
|
-
case "dictation_stream_chunk":
|
|
935
|
-
await this.dictationStreamManager.handleChunk({
|
|
936
|
-
dictationId: msg.dictationId,
|
|
937
|
-
seq: msg.seq,
|
|
938
|
-
audioBase64: msg.audio,
|
|
939
|
-
format: msg.format,
|
|
940
|
-
});
|
|
941
|
-
break;
|
|
942
|
-
case "dictation_stream_finish":
|
|
943
|
-
await this.dictationStreamManager.handleFinish(msg.dictationId, msg.finalSeq);
|
|
944
|
-
break;
|
|
945
|
-
case "dictation_stream_cancel":
|
|
946
|
-
this.dictationStreamManager.handleCancel(msg.dictationId);
|
|
947
|
-
break;
|
|
948
|
-
case "create_agent_request":
|
|
949
|
-
await this.handleCreateAgentRequest(msg);
|
|
950
|
-
break;
|
|
951
|
-
case "resume_agent_request":
|
|
952
|
-
await this.handleResumeAgentRequest(msg);
|
|
953
|
-
break;
|
|
954
|
-
case "refresh_agent_request":
|
|
955
|
-
await this.handleRefreshAgentRequest(msg);
|
|
956
|
-
break;
|
|
957
|
-
case "cancel_agent_request":
|
|
958
|
-
await this.handleCancelAgentRequest(msg.agentId, msg.requestId);
|
|
959
|
-
break;
|
|
960
|
-
case "restart_server_request":
|
|
961
|
-
await this.handleRestartServerRequest(msg.requestId, msg.reason);
|
|
962
|
-
break;
|
|
963
|
-
case "shutdown_server_request":
|
|
964
|
-
await this.handleShutdownServerRequest(msg.requestId);
|
|
965
|
-
break;
|
|
966
|
-
case "fetch_agent_timeline_request":
|
|
967
|
-
await this.handleFetchAgentTimelineRequest(msg);
|
|
968
|
-
break;
|
|
969
|
-
case "set_agent_mode_request":
|
|
970
|
-
await this.handleSetAgentModeRequest(msg.agentId, msg.modeId, msg.requestId);
|
|
971
|
-
break;
|
|
972
|
-
case "set_agent_model_request":
|
|
973
|
-
await this.handleSetAgentModelRequest(msg.agentId, msg.modelId, msg.requestId);
|
|
974
|
-
break;
|
|
975
|
-
case "set_agent_feature_request":
|
|
976
|
-
await this.handleSetAgentFeatureRequest(msg.agentId, msg.featureId, msg.value, msg.requestId);
|
|
977
|
-
break;
|
|
978
|
-
case "set_agent_thinking_request":
|
|
979
|
-
await this.handleSetAgentThinkingRequest(msg.agentId, msg.thinkingOptionId, msg.requestId);
|
|
980
|
-
break;
|
|
981
|
-
case "agent_permission_response":
|
|
982
|
-
await this.handleAgentPermissionResponse(msg.agentId, msg.requestId, msg.response);
|
|
983
|
-
break;
|
|
984
|
-
case "checkout_status_request":
|
|
985
|
-
await this.handleCheckoutStatusRequest(msg);
|
|
986
|
-
break;
|
|
987
|
-
case "validate_branch_request":
|
|
988
|
-
await this.handleValidateBranchRequest(msg);
|
|
989
|
-
break;
|
|
990
|
-
case "branch_suggestions_request":
|
|
991
|
-
await this.handleBranchSuggestionsRequest(msg);
|
|
992
|
-
break;
|
|
993
|
-
case "directory_suggestions_request":
|
|
994
|
-
await this.handleDirectorySuggestionsRequest(msg);
|
|
995
|
-
break;
|
|
996
|
-
case "subscribe_checkout_diff_request":
|
|
997
|
-
await this.handleSubscribeCheckoutDiffRequest(msg);
|
|
998
|
-
break;
|
|
999
|
-
case "unsubscribe_checkout_diff_request":
|
|
1000
|
-
this.handleUnsubscribeCheckoutDiffRequest(msg);
|
|
1001
|
-
break;
|
|
1002
|
-
case "checkout_switch_branch_request":
|
|
1003
|
-
await this.handleCheckoutSwitchBranchRequest(msg);
|
|
1004
|
-
break;
|
|
1005
|
-
case "stash_save_request":
|
|
1006
|
-
await this.handleStashSaveRequest(msg);
|
|
1007
|
-
break;
|
|
1008
|
-
case "stash_pop_request":
|
|
1009
|
-
await this.handleStashPopRequest(msg);
|
|
1010
|
-
break;
|
|
1011
|
-
case "stash_list_request":
|
|
1012
|
-
await this.handleStashListRequest(msg);
|
|
1013
|
-
break;
|
|
1014
|
-
case "checkout_commit_request":
|
|
1015
|
-
await this.handleCheckoutCommitRequest(msg);
|
|
1016
|
-
break;
|
|
1017
|
-
case "checkout_merge_request":
|
|
1018
|
-
await this.handleCheckoutMergeRequest(msg);
|
|
1019
|
-
break;
|
|
1020
|
-
case "checkout_merge_from_base_request":
|
|
1021
|
-
await this.handleCheckoutMergeFromBaseRequest(msg);
|
|
1022
|
-
break;
|
|
1023
|
-
case "checkout_pull_request":
|
|
1024
|
-
await this.handleCheckoutPullRequest(msg);
|
|
1025
|
-
break;
|
|
1026
|
-
case "checkout_push_request":
|
|
1027
|
-
await this.handleCheckoutPushRequest(msg);
|
|
1028
|
-
break;
|
|
1029
|
-
case "checkout_pr_create_request":
|
|
1030
|
-
await this.handleCheckoutPrCreateRequest(msg);
|
|
1031
|
-
break;
|
|
1032
|
-
case "checkout_pr_status_request":
|
|
1033
|
-
await this.handleCheckoutPrStatusRequest(msg);
|
|
1034
|
-
break;
|
|
1035
|
-
case "pull_request_timeline_request":
|
|
1036
|
-
await this.handlePullRequestTimelineRequest(msg);
|
|
1037
|
-
break;
|
|
1038
|
-
case "github_search_request":
|
|
1039
|
-
await this.handleGitHubSearchRequest(msg);
|
|
1040
|
-
break;
|
|
1041
|
-
case "paseo_worktree_list_request":
|
|
1042
|
-
await this.handlePaseoWorktreeListRequest(msg);
|
|
1043
|
-
break;
|
|
1044
|
-
case "paseo_worktree_archive_request":
|
|
1045
|
-
await this.handlePaseoWorktreeArchiveRequest(msg);
|
|
1046
|
-
break;
|
|
1047
|
-
case "create_paseo_worktree_request":
|
|
1048
|
-
await this.handleCreatePaseoWorktreeRequest(msg);
|
|
1049
|
-
break;
|
|
1050
|
-
case "workspace_setup_status_request":
|
|
1051
|
-
await this.handleWorkspaceSetupStatusRequest(msg);
|
|
1052
|
-
break;
|
|
1053
|
-
case "list_available_editors_request":
|
|
1054
|
-
await this.handleListAvailableEditorsRequest(msg);
|
|
1055
|
-
break;
|
|
1056
|
-
case "open_in_editor_request":
|
|
1057
|
-
await this.handleOpenInEditorRequest(msg);
|
|
1058
|
-
break;
|
|
1059
|
-
case "open_project_request":
|
|
1060
|
-
await this.handleOpenProjectRequest(msg);
|
|
1061
|
-
break;
|
|
1062
|
-
case "archive_workspace_request":
|
|
1063
|
-
await this.handleArchiveWorkspaceRequest(msg);
|
|
1064
|
-
break;
|
|
1065
|
-
case "file_explorer_request":
|
|
1066
|
-
await this.handleFileExplorerRequest(msg);
|
|
1067
|
-
break;
|
|
1068
|
-
case "project_icon_request":
|
|
1069
|
-
await this.handleProjectIconRequest(msg);
|
|
1070
|
-
break;
|
|
1071
|
-
case "file_download_token_request":
|
|
1072
|
-
await this.handleFileDownloadTokenRequest(msg);
|
|
1073
|
-
break;
|
|
1074
|
-
case "list_provider_models_request":
|
|
1075
|
-
await this.handleListProviderModelsRequest(msg);
|
|
1076
|
-
break;
|
|
1077
|
-
case "list_provider_modes_request":
|
|
1078
|
-
await this.handleListProviderModesRequest(msg);
|
|
1079
|
-
break;
|
|
1080
|
-
case "list_provider_features_request":
|
|
1081
|
-
await this.handleListProviderFeaturesRequest(msg);
|
|
1082
|
-
break;
|
|
1083
|
-
case "list_available_providers_request":
|
|
1084
|
-
await this.handleListAvailableProvidersRequest(msg);
|
|
1085
|
-
break;
|
|
1086
|
-
case "get_providers_snapshot_request":
|
|
1087
|
-
await this.handleGetProvidersSnapshotRequest(msg);
|
|
1088
|
-
break;
|
|
1089
|
-
case "refresh_providers_snapshot_request":
|
|
1090
|
-
await this.handleRefreshProvidersSnapshotRequest(msg);
|
|
1091
|
-
break;
|
|
1092
|
-
case "provider_diagnostic_request":
|
|
1093
|
-
await this.handleProviderDiagnosticRequest(msg);
|
|
1094
|
-
break;
|
|
1095
|
-
case "clear_agent_attention":
|
|
1096
|
-
await this.handleClearAgentAttention(msg.agentId, msg.requestId);
|
|
1097
|
-
break;
|
|
1098
|
-
case "client_heartbeat":
|
|
1099
|
-
this.handleClientHeartbeat(msg);
|
|
1100
|
-
break;
|
|
1101
|
-
case "ping": {
|
|
1102
|
-
const now = Date.now();
|
|
1103
|
-
this.emit({
|
|
1104
|
-
type: "pong",
|
|
1105
|
-
payload: {
|
|
1106
|
-
requestId: msg.requestId,
|
|
1107
|
-
clientSentAt: msg.clientSentAt,
|
|
1108
|
-
serverReceivedAt: now,
|
|
1109
|
-
serverSentAt: now,
|
|
1110
|
-
},
|
|
1111
|
-
});
|
|
1112
|
-
break;
|
|
1113
|
-
}
|
|
1114
|
-
case "list_commands_request":
|
|
1115
|
-
await this.handleListCommandsRequest(msg);
|
|
1116
|
-
break;
|
|
1117
|
-
case "register_push_token":
|
|
1118
|
-
this.handleRegisterPushToken(msg.token);
|
|
1119
|
-
break;
|
|
1120
|
-
case "subscribe_terminals_request":
|
|
1121
|
-
this.handleSubscribeTerminalsRequest(msg);
|
|
1122
|
-
break;
|
|
1123
|
-
case "unsubscribe_terminals_request":
|
|
1124
|
-
this.handleUnsubscribeTerminalsRequest(msg);
|
|
1125
|
-
break;
|
|
1126
|
-
case "list_terminals_request":
|
|
1127
|
-
await this.handleListTerminalsRequest(msg);
|
|
1128
|
-
break;
|
|
1129
|
-
case "create_terminal_request":
|
|
1130
|
-
await this.handleCreateTerminalRequest(msg);
|
|
1131
|
-
break;
|
|
1132
|
-
case "start_workspace_script_request":
|
|
1133
|
-
await this.handleStartWorkspaceScriptRequest(msg);
|
|
1134
|
-
break;
|
|
1135
|
-
case "subscribe_terminal_request":
|
|
1136
|
-
await this.handleSubscribeTerminalRequest(msg);
|
|
1137
|
-
break;
|
|
1138
|
-
case "unsubscribe_terminal_request":
|
|
1139
|
-
this.handleUnsubscribeTerminalRequest(msg);
|
|
1140
|
-
break;
|
|
1141
|
-
case "terminal_input":
|
|
1142
|
-
this.handleTerminalInput(msg);
|
|
1143
|
-
break;
|
|
1144
|
-
case "kill_terminal_request":
|
|
1145
|
-
await this.handleKillTerminalRequest(msg);
|
|
1146
|
-
break;
|
|
1147
|
-
case "capture_terminal_request":
|
|
1148
|
-
await this.handleCaptureTerminalRequest(msg);
|
|
1149
|
-
break;
|
|
1150
|
-
case "chat/create":
|
|
1151
|
-
await this.handleChatCreateRequest(msg);
|
|
1152
|
-
break;
|
|
1153
|
-
case "chat/list":
|
|
1154
|
-
await this.handleChatListRequest(msg);
|
|
1155
|
-
break;
|
|
1156
|
-
case "chat/inspect":
|
|
1157
|
-
await this.handleChatInspectRequest(msg);
|
|
1158
|
-
break;
|
|
1159
|
-
case "chat/delete":
|
|
1160
|
-
await this.handleChatDeleteRequest(msg);
|
|
1161
|
-
break;
|
|
1162
|
-
case "chat/post":
|
|
1163
|
-
await this.handleChatPostRequest(msg);
|
|
1164
|
-
break;
|
|
1165
|
-
case "chat/read":
|
|
1166
|
-
await this.handleChatReadRequest(msg);
|
|
1167
|
-
break;
|
|
1168
|
-
case "chat/wait":
|
|
1169
|
-
await this.handleChatWaitRequest(msg);
|
|
1170
|
-
break;
|
|
1171
|
-
case "schedule/create":
|
|
1172
|
-
await this.handleScheduleCreateRequest(msg);
|
|
1173
|
-
break;
|
|
1174
|
-
case "schedule/list":
|
|
1175
|
-
await this.handleScheduleListRequest(msg);
|
|
1176
|
-
break;
|
|
1177
|
-
case "schedule/inspect":
|
|
1178
|
-
await this.handleScheduleInspectRequest(msg);
|
|
1179
|
-
break;
|
|
1180
|
-
case "schedule/logs":
|
|
1181
|
-
await this.handleScheduleLogsRequest(msg);
|
|
1182
|
-
break;
|
|
1183
|
-
case "schedule/pause":
|
|
1184
|
-
await this.handleSchedulePauseRequest(msg);
|
|
1185
|
-
break;
|
|
1186
|
-
case "schedule/resume":
|
|
1187
|
-
await this.handleScheduleResumeRequest(msg);
|
|
1188
|
-
break;
|
|
1189
|
-
case "schedule/delete":
|
|
1190
|
-
await this.handleScheduleDeleteRequest(msg);
|
|
1191
|
-
break;
|
|
1192
|
-
case "loop/run":
|
|
1193
|
-
await this.handleLoopRunRequest(msg);
|
|
1194
|
-
break;
|
|
1195
|
-
case "loop/list":
|
|
1196
|
-
await this.handleLoopListRequest(msg);
|
|
1197
|
-
break;
|
|
1198
|
-
case "loop/inspect":
|
|
1199
|
-
await this.handleLoopInspectRequest(msg);
|
|
1200
|
-
break;
|
|
1201
|
-
case "loop/logs":
|
|
1202
|
-
await this.handleLoopLogsRequest(msg);
|
|
1203
|
-
break;
|
|
1204
|
-
case "loop/stop":
|
|
1205
|
-
await this.handleLoopStopRequest(msg);
|
|
1206
|
-
break;
|
|
1207
|
-
}
|
|
973
|
+
await this.dispatchInboundMessage(msg);
|
|
1208
974
|
}
|
|
1209
975
|
catch (error) {
|
|
1210
976
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
@@ -1241,6 +1007,418 @@ export class Session {
|
|
|
1241
1007
|
this.inflightRequests--;
|
|
1242
1008
|
}
|
|
1243
1009
|
}
|
|
1010
|
+
async dispatchInboundMessage(msg) {
|
|
1011
|
+
const promise = this.dispatchVoiceAndControlMessage(msg) ??
|
|
1012
|
+
this.dispatchAgentLifecycleMessage(msg) ??
|
|
1013
|
+
this.dispatchAgentConfigMessage(msg) ??
|
|
1014
|
+
this.dispatchCheckoutMessage(msg) ??
|
|
1015
|
+
this.dispatchWorkspaceAndProjectMessage(msg) ??
|
|
1016
|
+
this.dispatchProviderMessage(msg) ??
|
|
1017
|
+
this.dispatchTerminalMessage(msg) ??
|
|
1018
|
+
this.dispatchChatScheduleLoopMessage(msg) ??
|
|
1019
|
+
this.dispatchMiscMessage(msg);
|
|
1020
|
+
if (promise)
|
|
1021
|
+
await promise;
|
|
1022
|
+
}
|
|
1023
|
+
dispatchVoiceAndControlMessage(msg) {
|
|
1024
|
+
switch (msg.type) {
|
|
1025
|
+
case "voice_audio_chunk":
|
|
1026
|
+
return this.handleAudioChunk(msg);
|
|
1027
|
+
case "abort_request":
|
|
1028
|
+
return this.handleAbort();
|
|
1029
|
+
case "audio_played":
|
|
1030
|
+
this.handleAudioPlayed(msg.id);
|
|
1031
|
+
return undefined;
|
|
1032
|
+
case "set_voice_mode":
|
|
1033
|
+
return this.handleSetVoiceMode(msg.enabled, msg.agentId, msg.requestId);
|
|
1034
|
+
case "dictation_stream_start":
|
|
1035
|
+
return this.handleDictationStreamStart(msg);
|
|
1036
|
+
case "dictation_stream_chunk":
|
|
1037
|
+
return this.dictationStreamManager.handleChunk({
|
|
1038
|
+
dictationId: msg.dictationId,
|
|
1039
|
+
seq: msg.seq,
|
|
1040
|
+
audioBase64: msg.audio,
|
|
1041
|
+
format: msg.format,
|
|
1042
|
+
});
|
|
1043
|
+
case "dictation_stream_finish":
|
|
1044
|
+
return this.dictationStreamManager.handleFinish(msg.dictationId, msg.finalSeq);
|
|
1045
|
+
case "dictation_stream_cancel":
|
|
1046
|
+
this.dictationStreamManager.handleCancel(msg.dictationId);
|
|
1047
|
+
return undefined;
|
|
1048
|
+
case "restart_server_request":
|
|
1049
|
+
return this.handleRestartServerRequest(msg.requestId, msg.reason);
|
|
1050
|
+
case "shutdown_server_request":
|
|
1051
|
+
return this.handleShutdownServerRequest(msg.requestId);
|
|
1052
|
+
case "client_heartbeat":
|
|
1053
|
+
this.handleClientHeartbeat(msg);
|
|
1054
|
+
return undefined;
|
|
1055
|
+
case "ping": {
|
|
1056
|
+
const now = Date.now();
|
|
1057
|
+
this.emit({
|
|
1058
|
+
type: "pong",
|
|
1059
|
+
payload: {
|
|
1060
|
+
requestId: msg.requestId,
|
|
1061
|
+
clientSentAt: msg.clientSentAt,
|
|
1062
|
+
serverReceivedAt: now,
|
|
1063
|
+
serverSentAt: now,
|
|
1064
|
+
},
|
|
1065
|
+
});
|
|
1066
|
+
return undefined;
|
|
1067
|
+
}
|
|
1068
|
+
default:
|
|
1069
|
+
return undefined;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
async handleDictationStreamStart(msg) {
|
|
1073
|
+
const unavailable = this.resolveVoiceFeatureUnavailableContext("dictation");
|
|
1074
|
+
if (unavailable) {
|
|
1075
|
+
this.emit({
|
|
1076
|
+
type: "dictation_stream_error",
|
|
1077
|
+
payload: {
|
|
1078
|
+
dictationId: msg.dictationId,
|
|
1079
|
+
error: unavailable.message,
|
|
1080
|
+
retryable: unavailable.retryable,
|
|
1081
|
+
reasonCode: unavailable.reasonCode,
|
|
1082
|
+
missingModelIds: unavailable.missingModelIds,
|
|
1083
|
+
},
|
|
1084
|
+
});
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
await this.dictationStreamManager.handleStart(msg.dictationId, msg.format);
|
|
1088
|
+
}
|
|
1089
|
+
dispatchAgentLifecycleMessage(msg) {
|
|
1090
|
+
switch (msg.type) {
|
|
1091
|
+
case "fetch_agents_request":
|
|
1092
|
+
return this.handleFetchAgents(msg);
|
|
1093
|
+
case "fetch_agent_history_request":
|
|
1094
|
+
return this.handleFetchAgentHistory(msg);
|
|
1095
|
+
case "fetch_agent_request":
|
|
1096
|
+
return this.handleFetchAgent(msg.agentId, msg.requestId);
|
|
1097
|
+
case "delete_agent_request":
|
|
1098
|
+
return this.handleDeleteAgentRequest(msg.agentId, msg.requestId);
|
|
1099
|
+
case "archive_agent_request":
|
|
1100
|
+
return this.handleArchiveAgentRequest(msg.agentId, msg.requestId);
|
|
1101
|
+
case "close_items_request":
|
|
1102
|
+
return this.handleCloseItemsRequest(msg);
|
|
1103
|
+
case "update_agent_request":
|
|
1104
|
+
return this.handleUpdateAgentRequest(msg.agentId, msg.name, msg.labels, msg.requestId);
|
|
1105
|
+
case "send_agent_message_request":
|
|
1106
|
+
return this.handleSendAgentMessageRequest(msg);
|
|
1107
|
+
case "wait_for_finish_request":
|
|
1108
|
+
return this.handleWaitForFinish(msg.agentId, msg.requestId, msg.timeoutMs);
|
|
1109
|
+
case "create_agent_request":
|
|
1110
|
+
return this.handleCreateAgentRequest(msg);
|
|
1111
|
+
case "resume_agent_request":
|
|
1112
|
+
return this.handleResumeAgentRequest(msg);
|
|
1113
|
+
case "refresh_agent_request":
|
|
1114
|
+
return this.handleRefreshAgentRequest(msg);
|
|
1115
|
+
case "cancel_agent_request":
|
|
1116
|
+
return this.handleCancelAgentRequest(msg.agentId, msg.requestId);
|
|
1117
|
+
case "fetch_agent_timeline_request":
|
|
1118
|
+
return this.handleFetchAgentTimelineRequest(msg);
|
|
1119
|
+
case "agent_permission_response":
|
|
1120
|
+
return this.handleAgentPermissionResponse(msg.agentId, msg.requestId, msg.response);
|
|
1121
|
+
case "clear_agent_attention":
|
|
1122
|
+
return this.handleClearAgentAttention(msg.agentId, msg.requestId);
|
|
1123
|
+
default:
|
|
1124
|
+
return undefined;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
dispatchAgentConfigMessage(msg) {
|
|
1128
|
+
switch (msg.type) {
|
|
1129
|
+
case "set_agent_mode_request":
|
|
1130
|
+
return this.handleSetAgentModeRequest(msg.agentId, msg.modeId, msg.requestId);
|
|
1131
|
+
case "set_agent_model_request":
|
|
1132
|
+
return this.handleSetAgentModelRequest(msg.agentId, msg.modelId, msg.requestId);
|
|
1133
|
+
case "set_agent_feature_request":
|
|
1134
|
+
return this.handleSetAgentFeatureRequest(msg.agentId, msg.featureId, msg.value, msg.requestId);
|
|
1135
|
+
case "set_agent_thinking_request":
|
|
1136
|
+
return this.handleSetAgentThinkingRequest(msg.agentId, msg.thinkingOptionId, msg.requestId);
|
|
1137
|
+
case "get_daemon_config_request":
|
|
1138
|
+
this.emit({
|
|
1139
|
+
type: "get_daemon_config_response",
|
|
1140
|
+
payload: { requestId: msg.requestId, config: this.daemonConfigStore.get() },
|
|
1141
|
+
});
|
|
1142
|
+
return undefined;
|
|
1143
|
+
case "set_daemon_config_request":
|
|
1144
|
+
this.emit({
|
|
1145
|
+
type: "set_daemon_config_response",
|
|
1146
|
+
payload: {
|
|
1147
|
+
requestId: msg.requestId,
|
|
1148
|
+
config: this.daemonConfigStore.patch(msg.config),
|
|
1149
|
+
},
|
|
1150
|
+
});
|
|
1151
|
+
return undefined;
|
|
1152
|
+
case "read_project_config_request":
|
|
1153
|
+
return this.handleReadProjectConfigRequest(msg);
|
|
1154
|
+
case "write_project_config_request":
|
|
1155
|
+
return this.handleWriteProjectConfigRequest(msg);
|
|
1156
|
+
default:
|
|
1157
|
+
return undefined;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
async handleReadProjectConfigRequest(msg) {
|
|
1161
|
+
const repoRoot = await resolveKnownProjectRootForConfig({
|
|
1162
|
+
repoRoot: msg.repoRoot,
|
|
1163
|
+
projectRegistry: this.projectRegistry,
|
|
1164
|
+
});
|
|
1165
|
+
if (!repoRoot) {
|
|
1166
|
+
this.emitProjectConfigReadFailure(msg, { code: "project_not_found" });
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const result = readPaseoConfigForEdit(repoRoot);
|
|
1170
|
+
if (!result.ok) {
|
|
1171
|
+
this.sessionLogger.warn({ repoRoot, requestId: msg.requestId, outcome: result.error.code }, "Failed to read project config");
|
|
1172
|
+
this.emitProjectConfigReadFailure(msg, result.error, repoRoot);
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
if (result.config === null) {
|
|
1176
|
+
this.sessionLogger.debug({ repoRoot, requestId: msg.requestId, outcome: "missing_project_config" }, "Project config missing");
|
|
1177
|
+
}
|
|
1178
|
+
this.emit({
|
|
1179
|
+
type: "read_project_config_response",
|
|
1180
|
+
payload: {
|
|
1181
|
+
requestId: msg.requestId,
|
|
1182
|
+
repoRoot,
|
|
1183
|
+
ok: true,
|
|
1184
|
+
config: result.config,
|
|
1185
|
+
revision: result.revision,
|
|
1186
|
+
},
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
async handleWriteProjectConfigRequest(msg) {
|
|
1190
|
+
const repoRoot = await resolveKnownProjectRootForConfig({
|
|
1191
|
+
repoRoot: msg.repoRoot,
|
|
1192
|
+
projectRegistry: this.projectRegistry,
|
|
1193
|
+
});
|
|
1194
|
+
if (!repoRoot) {
|
|
1195
|
+
this.emitProjectConfigWriteFailure(msg, { code: "project_not_found" });
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
this.sessionLogger.debug({ repoRoot, requestId: msg.requestId, outcome: "write_attempt" }, "Writing project config");
|
|
1199
|
+
const result = writePaseoConfigForEdit({
|
|
1200
|
+
repoRoot,
|
|
1201
|
+
config: msg.config,
|
|
1202
|
+
expectedRevision: msg.expectedRevision,
|
|
1203
|
+
});
|
|
1204
|
+
if (!result.ok) {
|
|
1205
|
+
this.sessionLogger.debug({ repoRoot, requestId: msg.requestId, outcome: result.error.code }, "Project config write did not complete");
|
|
1206
|
+
this.emitProjectConfigWriteFailure(msg, result.error, repoRoot);
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
this.sessionLogger.debug({ repoRoot, requestId: msg.requestId, outcome: "written" }, "Project config written");
|
|
1210
|
+
this.emit({
|
|
1211
|
+
type: "write_project_config_response",
|
|
1212
|
+
payload: {
|
|
1213
|
+
requestId: msg.requestId,
|
|
1214
|
+
repoRoot,
|
|
1215
|
+
ok: true,
|
|
1216
|
+
config: result.config,
|
|
1217
|
+
revision: result.revision,
|
|
1218
|
+
},
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
emitProjectConfigReadFailure(msg, error, repoRoot = msg.repoRoot) {
|
|
1222
|
+
this.emit({
|
|
1223
|
+
type: "read_project_config_response",
|
|
1224
|
+
payload: {
|
|
1225
|
+
requestId: msg.requestId,
|
|
1226
|
+
repoRoot,
|
|
1227
|
+
ok: false,
|
|
1228
|
+
error,
|
|
1229
|
+
},
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
emitProjectConfigWriteFailure(msg, error, repoRoot = msg.repoRoot) {
|
|
1233
|
+
this.emit({
|
|
1234
|
+
type: "write_project_config_response",
|
|
1235
|
+
payload: {
|
|
1236
|
+
requestId: msg.requestId,
|
|
1237
|
+
repoRoot,
|
|
1238
|
+
ok: false,
|
|
1239
|
+
error,
|
|
1240
|
+
},
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
dispatchCheckoutMessage(msg) {
|
|
1244
|
+
switch (msg.type) {
|
|
1245
|
+
case "checkout_status_request":
|
|
1246
|
+
return this.handleCheckoutStatusRequest(msg);
|
|
1247
|
+
case "validate_branch_request":
|
|
1248
|
+
return this.handleValidateBranchRequest(msg);
|
|
1249
|
+
case "branch_suggestions_request":
|
|
1250
|
+
return this.handleBranchSuggestionsRequest(msg);
|
|
1251
|
+
case "directory_suggestions_request":
|
|
1252
|
+
return this.handleDirectorySuggestionsRequest(msg);
|
|
1253
|
+
case "subscribe_checkout_diff_request":
|
|
1254
|
+
return this.handleSubscribeCheckoutDiffRequest(msg);
|
|
1255
|
+
case "unsubscribe_checkout_diff_request":
|
|
1256
|
+
this.handleUnsubscribeCheckoutDiffRequest(msg);
|
|
1257
|
+
return undefined;
|
|
1258
|
+
case "checkout_switch_branch_request":
|
|
1259
|
+
return this.handleCheckoutSwitchBranchRequest(msg);
|
|
1260
|
+
case "stash_save_request":
|
|
1261
|
+
return this.handleStashSaveRequest(msg);
|
|
1262
|
+
case "stash_pop_request":
|
|
1263
|
+
return this.handleStashPopRequest(msg);
|
|
1264
|
+
case "stash_list_request":
|
|
1265
|
+
return this.handleStashListRequest(msg);
|
|
1266
|
+
case "checkout_commit_request":
|
|
1267
|
+
return this.handleCheckoutCommitRequest(msg);
|
|
1268
|
+
case "checkout_merge_request":
|
|
1269
|
+
return this.handleCheckoutMergeRequest(msg);
|
|
1270
|
+
case "checkout_merge_from_base_request":
|
|
1271
|
+
return this.handleCheckoutMergeFromBaseRequest(msg);
|
|
1272
|
+
case "checkout_pull_request":
|
|
1273
|
+
return this.handleCheckoutPullRequest(msg);
|
|
1274
|
+
case "checkout_push_request":
|
|
1275
|
+
return this.handleCheckoutPushRequest(msg);
|
|
1276
|
+
case "checkout_pr_create_request":
|
|
1277
|
+
return this.handleCheckoutPrCreateRequest(msg);
|
|
1278
|
+
case "checkout_pr_status_request":
|
|
1279
|
+
return this.handleCheckoutPrStatusRequest(msg);
|
|
1280
|
+
case "pull_request_timeline_request":
|
|
1281
|
+
return this.handlePullRequestTimelineRequest(msg);
|
|
1282
|
+
case "github_search_request":
|
|
1283
|
+
return this.handleGitHubSearchRequest(msg);
|
|
1284
|
+
default:
|
|
1285
|
+
return undefined;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
dispatchWorkspaceAndProjectMessage(msg) {
|
|
1289
|
+
switch (msg.type) {
|
|
1290
|
+
case "fetch_workspaces_request":
|
|
1291
|
+
return this.handleFetchWorkspacesRequest(msg);
|
|
1292
|
+
case "paseo_worktree_list_request":
|
|
1293
|
+
return this.handlePaseoWorktreeListRequest(msg);
|
|
1294
|
+
case "paseo_worktree_archive_request":
|
|
1295
|
+
return this.handlePaseoWorktreeArchiveRequest(msg);
|
|
1296
|
+
case "create_paseo_worktree_request":
|
|
1297
|
+
return this.handleCreatePaseoWorktreeRequest(msg);
|
|
1298
|
+
case "workspace_setup_status_request":
|
|
1299
|
+
return this.handleWorkspaceSetupStatusRequest(msg);
|
|
1300
|
+
case "list_available_editors_request":
|
|
1301
|
+
return this.handleListAvailableEditorsRequest(msg);
|
|
1302
|
+
case "open_in_editor_request":
|
|
1303
|
+
return this.handleOpenInEditorRequest(msg);
|
|
1304
|
+
case "open_project_request":
|
|
1305
|
+
return this.handleOpenProjectRequest(msg);
|
|
1306
|
+
case "archive_workspace_request":
|
|
1307
|
+
return this.handleArchiveWorkspaceRequest(msg);
|
|
1308
|
+
case "file_explorer_request":
|
|
1309
|
+
return this.handleFileExplorerRequest(msg);
|
|
1310
|
+
case "project_icon_request":
|
|
1311
|
+
return this.handleProjectIconRequest(msg);
|
|
1312
|
+
case "file_download_token_request":
|
|
1313
|
+
return this.handleFileDownloadTokenRequest(msg);
|
|
1314
|
+
default:
|
|
1315
|
+
return undefined;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
dispatchProviderMessage(msg) {
|
|
1319
|
+
switch (msg.type) {
|
|
1320
|
+
case "list_provider_models_request":
|
|
1321
|
+
return this.handleListProviderModelsRequest(msg);
|
|
1322
|
+
case "list_provider_modes_request":
|
|
1323
|
+
return this.handleListProviderModesRequest(msg);
|
|
1324
|
+
case "list_provider_features_request":
|
|
1325
|
+
return this.handleListProviderFeaturesRequest(msg);
|
|
1326
|
+
case "list_available_providers_request":
|
|
1327
|
+
return this.handleListAvailableProvidersRequest(msg);
|
|
1328
|
+
case "get_providers_snapshot_request":
|
|
1329
|
+
return this.handleGetProvidersSnapshotRequest(msg);
|
|
1330
|
+
case "refresh_providers_snapshot_request":
|
|
1331
|
+
return this.handleRefreshProvidersSnapshotRequest(msg);
|
|
1332
|
+
case "provider_diagnostic_request":
|
|
1333
|
+
return this.handleProviderDiagnosticRequest(msg);
|
|
1334
|
+
default:
|
|
1335
|
+
return undefined;
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
dispatchTerminalMessage(msg) {
|
|
1339
|
+
switch (msg.type) {
|
|
1340
|
+
case "subscribe_terminals_request":
|
|
1341
|
+
this.handleSubscribeTerminalsRequest(msg);
|
|
1342
|
+
return undefined;
|
|
1343
|
+
case "unsubscribe_terminals_request":
|
|
1344
|
+
this.handleUnsubscribeTerminalsRequest(msg);
|
|
1345
|
+
return undefined;
|
|
1346
|
+
case "list_terminals_request":
|
|
1347
|
+
return this.handleListTerminalsRequest(msg);
|
|
1348
|
+
case "create_terminal_request":
|
|
1349
|
+
return this.handleCreateTerminalRequest(msg);
|
|
1350
|
+
case "start_workspace_script_request":
|
|
1351
|
+
return this.handleStartWorkspaceScriptRequest(msg);
|
|
1352
|
+
case "subscribe_terminal_request":
|
|
1353
|
+
return this.handleSubscribeTerminalRequest(msg);
|
|
1354
|
+
case "unsubscribe_terminal_request":
|
|
1355
|
+
this.handleUnsubscribeTerminalRequest(msg);
|
|
1356
|
+
return undefined;
|
|
1357
|
+
case "terminal_input":
|
|
1358
|
+
this.handleTerminalInput(msg);
|
|
1359
|
+
return undefined;
|
|
1360
|
+
case "kill_terminal_request":
|
|
1361
|
+
return this.handleKillTerminalRequest(msg);
|
|
1362
|
+
case "capture_terminal_request":
|
|
1363
|
+
return this.handleCaptureTerminalRequest(msg);
|
|
1364
|
+
default:
|
|
1365
|
+
return undefined;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
dispatchChatScheduleLoopMessage(msg) {
|
|
1369
|
+
switch (msg.type) {
|
|
1370
|
+
case "chat/create":
|
|
1371
|
+
return this.handleChatCreateRequest(msg);
|
|
1372
|
+
case "chat/list":
|
|
1373
|
+
return this.handleChatListRequest(msg);
|
|
1374
|
+
case "chat/inspect":
|
|
1375
|
+
return this.handleChatInspectRequest(msg);
|
|
1376
|
+
case "chat/delete":
|
|
1377
|
+
return this.handleChatDeleteRequest(msg);
|
|
1378
|
+
case "chat/post":
|
|
1379
|
+
return this.handleChatPostRequest(msg);
|
|
1380
|
+
case "chat/read":
|
|
1381
|
+
return this.handleChatReadRequest(msg);
|
|
1382
|
+
case "chat/wait":
|
|
1383
|
+
return this.handleChatWaitRequest(msg);
|
|
1384
|
+
case "schedule/create":
|
|
1385
|
+
return this.handleScheduleCreateRequest(msg);
|
|
1386
|
+
case "schedule/list":
|
|
1387
|
+
return this.handleScheduleListRequest(msg);
|
|
1388
|
+
case "schedule/inspect":
|
|
1389
|
+
return this.handleScheduleInspectRequest(msg);
|
|
1390
|
+
case "schedule/logs":
|
|
1391
|
+
return this.handleScheduleLogsRequest(msg);
|
|
1392
|
+
case "schedule/pause":
|
|
1393
|
+
return this.handleSchedulePauseRequest(msg);
|
|
1394
|
+
case "schedule/resume":
|
|
1395
|
+
return this.handleScheduleResumeRequest(msg);
|
|
1396
|
+
case "schedule/delete":
|
|
1397
|
+
return this.handleScheduleDeleteRequest(msg);
|
|
1398
|
+
case "loop/run":
|
|
1399
|
+
return this.handleLoopRunRequest(msg);
|
|
1400
|
+
case "loop/list":
|
|
1401
|
+
return this.handleLoopListRequest(msg);
|
|
1402
|
+
case "loop/inspect":
|
|
1403
|
+
return this.handleLoopInspectRequest(msg);
|
|
1404
|
+
case "loop/logs":
|
|
1405
|
+
return this.handleLoopLogsRequest(msg);
|
|
1406
|
+
case "loop/stop":
|
|
1407
|
+
return this.handleLoopStopRequest(msg);
|
|
1408
|
+
default:
|
|
1409
|
+
return undefined;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
async dispatchMiscMessage(msg) {
|
|
1413
|
+
switch (msg.type) {
|
|
1414
|
+
case "list_commands_request":
|
|
1415
|
+
await this.handleListCommandsRequest(msg);
|
|
1416
|
+
return;
|
|
1417
|
+
case "register_push_token":
|
|
1418
|
+
this.handleRegisterPushToken(msg.token);
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1244
1422
|
resetPeakInflight() {
|
|
1245
1423
|
this.peakInflightRequests = this.inflightRequests;
|
|
1246
1424
|
}
|
|
@@ -1441,13 +1619,15 @@ export class Session {
|
|
|
1441
1619
|
return { agentId, archivedAt: archivedRecord.archivedAt };
|
|
1442
1620
|
}
|
|
1443
1621
|
async handleCloseItemsRequest(msg) {
|
|
1622
|
+
const archiveResults = await Promise.allSettled(msg.agentIds.map((agentId) => this.archiveAgentForClose(agentId)));
|
|
1444
1623
|
const agents = [];
|
|
1445
|
-
for (
|
|
1446
|
-
|
|
1447
|
-
|
|
1624
|
+
for (let i = 0; i < archiveResults.length; i += 1) {
|
|
1625
|
+
const result = archiveResults[i];
|
|
1626
|
+
if (result.status === "fulfilled") {
|
|
1627
|
+
agents.push(result.value);
|
|
1448
1628
|
}
|
|
1449
|
-
|
|
1450
|
-
this.sessionLogger.warn({ err:
|
|
1629
|
+
else {
|
|
1630
|
+
this.sessionLogger.warn({ err: result.reason, agentId: msg.agentIds[i], requestId: msg.requestId }, "Failed to archive agent during close_items batch");
|
|
1451
1631
|
}
|
|
1452
1632
|
}
|
|
1453
1633
|
const terminals = [];
|
|
@@ -1529,7 +1709,9 @@ export class Session {
|
|
|
1529
1709
|
requestId,
|
|
1530
1710
|
agentId,
|
|
1531
1711
|
accepted: false,
|
|
1532
|
-
error: error?.message
|
|
1712
|
+
error: error?.message
|
|
1713
|
+
? String(error.message)
|
|
1714
|
+
: "Failed to update agent",
|
|
1533
1715
|
},
|
|
1534
1716
|
});
|
|
1535
1717
|
}
|
|
@@ -1899,24 +2081,15 @@ export class Session {
|
|
|
1899
2081
|
initialPrompt: trimmedPrompt,
|
|
1900
2082
|
});
|
|
1901
2083
|
await this.forwardAgentUpdate(snapshot);
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
deps: {
|
|
1912
|
-
workspaceGitService: this.workspaceGitService,
|
|
1913
|
-
},
|
|
1914
|
-
});
|
|
1915
|
-
const started = await this.handleSendAgentMessage(snapshot.id, trimmedPrompt || "", resolveClientMessageId(clientMessageId), images, attachments, outputSchema ? { outputSchema } : undefined);
|
|
1916
|
-
if (!started.ok) {
|
|
1917
|
-
throw new Error(started.error);
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
2084
|
+
await this.sendInitialCreateAgentPrompt({
|
|
2085
|
+
snapshot,
|
|
2086
|
+
trimmedPrompt,
|
|
2087
|
+
images,
|
|
2088
|
+
attachments,
|
|
2089
|
+
clientMessageId,
|
|
2090
|
+
outputSchema,
|
|
2091
|
+
explicitTitle,
|
|
2092
|
+
});
|
|
1920
2093
|
if (requestId) {
|
|
1921
2094
|
const agentPayload = await this.buildAgentPayload(snapshot);
|
|
1922
2095
|
this.emit({
|
|
@@ -1975,6 +2148,31 @@ export class Session {
|
|
|
1975
2148
|
});
|
|
1976
2149
|
}
|
|
1977
2150
|
}
|
|
2151
|
+
async sendInitialCreateAgentPrompt(params) {
|
|
2152
|
+
const { snapshot, trimmedPrompt, images, attachments, clientMessageId, outputSchema } = params;
|
|
2153
|
+
const hasPrompt = Boolean(trimmedPrompt);
|
|
2154
|
+
const hasImages = (images?.length ?? 0) > 0;
|
|
2155
|
+
const hasAttachments = (attachments?.length ?? 0) > 0;
|
|
2156
|
+
if (!hasPrompt && !hasImages && !hasAttachments) {
|
|
2157
|
+
return;
|
|
2158
|
+
}
|
|
2159
|
+
scheduleAgentMetadataGeneration({
|
|
2160
|
+
agentManager: this.agentManager,
|
|
2161
|
+
agentId: snapshot.id,
|
|
2162
|
+
cwd: snapshot.cwd,
|
|
2163
|
+
initialPrompt: trimmedPrompt,
|
|
2164
|
+
explicitTitle: params.explicitTitle,
|
|
2165
|
+
paseoHome: this.paseoHome,
|
|
2166
|
+
logger: this.sessionLogger,
|
|
2167
|
+
deps: {
|
|
2168
|
+
workspaceGitService: this.workspaceGitService,
|
|
2169
|
+
},
|
|
2170
|
+
});
|
|
2171
|
+
const started = await this.handleSendAgentMessage(snapshot.id, trimmedPrompt || "", resolveClientMessageId(clientMessageId), images, attachments, outputSchema ? { outputSchema } : undefined);
|
|
2172
|
+
if (!started.ok) {
|
|
2173
|
+
throw new Error(started.error);
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
1978
2176
|
async handleResumeAgentRequest(msg) {
|
|
1979
2177
|
const { handle, overrides, requestId } = msg;
|
|
1980
2178
|
if (!handle) {
|
|
@@ -2041,7 +2239,11 @@ export class Session {
|
|
|
2041
2239
|
if (!record) {
|
|
2042
2240
|
throw new Error(`Agent not found: ${agentId}`);
|
|
2043
2241
|
}
|
|
2044
|
-
const
|
|
2242
|
+
const providerRegistry = this.getProviderRegistry();
|
|
2243
|
+
if (!isStoredAgentProviderAvailable(record, Object.keys(providerRegistry))) {
|
|
2244
|
+
throw new Error(`Agent ${agentId} references unavailable provider '${record.provider}'`);
|
|
2245
|
+
}
|
|
2246
|
+
const handle = toAgentPersistenceHandle(providerRegistry, record.persistence);
|
|
2045
2247
|
if (!handle) {
|
|
2046
2248
|
throw new Error(`Agent ${agentId} cannot be refreshed because it lacks persistence`);
|
|
2047
2249
|
}
|
|
@@ -2107,13 +2309,32 @@ export class Session {
|
|
|
2107
2309
|
github: this.github,
|
|
2108
2310
|
}, config, gitOptions, legacyWorktreeName, attachments);
|
|
2109
2311
|
}
|
|
2312
|
+
emitProviderDisabledResponse(kind, provider, requestId, fetchedAt) {
|
|
2313
|
+
const payload = {
|
|
2314
|
+
provider,
|
|
2315
|
+
error: `Provider ${provider} is disabled`,
|
|
2316
|
+
fetchedAt,
|
|
2317
|
+
requestId,
|
|
2318
|
+
};
|
|
2319
|
+
if (kind === "models") {
|
|
2320
|
+
this.emit({ type: "list_provider_models_response", payload });
|
|
2321
|
+
}
|
|
2322
|
+
else {
|
|
2323
|
+
this.emit({ type: "list_provider_modes_response", payload });
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2110
2326
|
async handleListProviderModelsRequest(msg) {
|
|
2111
2327
|
const cwd = resolveSnapshotCwd(msg.cwd ? expandTilde(msg.cwd) : undefined);
|
|
2112
2328
|
const fetchedAt = new Date().toISOString();
|
|
2113
2329
|
const manager = this.providerSnapshotManager;
|
|
2114
2330
|
if (!manager) {
|
|
2115
2331
|
try {
|
|
2116
|
-
const
|
|
2332
|
+
const definition = this.getProviderRegistry()[msg.provider];
|
|
2333
|
+
if (!definition.enabled) {
|
|
2334
|
+
this.emitProviderDisabledResponse("models", msg.provider, msg.requestId, fetchedAt);
|
|
2335
|
+
return;
|
|
2336
|
+
}
|
|
2337
|
+
const models = await definition.fetchModels({
|
|
2117
2338
|
cwd,
|
|
2118
2339
|
force: false,
|
|
2119
2340
|
});
|
|
@@ -2155,6 +2376,10 @@ export class Session {
|
|
|
2155
2376
|
});
|
|
2156
2377
|
return;
|
|
2157
2378
|
}
|
|
2379
|
+
if (!entry.enabled) {
|
|
2380
|
+
this.emitProviderDisabledResponse("models", msg.provider, msg.requestId, fetchedAt);
|
|
2381
|
+
return;
|
|
2382
|
+
}
|
|
2158
2383
|
if (entry.status === "ready") {
|
|
2159
2384
|
this.emit({
|
|
2160
2385
|
type: "list_provider_models_response",
|
|
@@ -2199,6 +2424,10 @@ export class Session {
|
|
|
2199
2424
|
});
|
|
2200
2425
|
return;
|
|
2201
2426
|
}
|
|
2427
|
+
if (!entry.enabled) {
|
|
2428
|
+
this.emitProviderDisabledResponse("modes", msg.provider, msg.requestId, fetchedAt);
|
|
2429
|
+
return;
|
|
2430
|
+
}
|
|
2202
2431
|
if (entry.status === "ready") {
|
|
2203
2432
|
this.emit({
|
|
2204
2433
|
type: "list_provider_modes_response",
|
|
@@ -2227,7 +2456,12 @@ export class Session {
|
|
|
2227
2456
|
return;
|
|
2228
2457
|
}
|
|
2229
2458
|
try {
|
|
2230
|
-
const
|
|
2459
|
+
const definition = this.getProviderRegistry()[msg.provider];
|
|
2460
|
+
if (!definition.enabled) {
|
|
2461
|
+
this.emitProviderDisabledResponse("modes", msg.provider, msg.requestId, fetchedAt);
|
|
2462
|
+
return;
|
|
2463
|
+
}
|
|
2464
|
+
const modes = await definition.fetchModes({
|
|
2231
2465
|
cwd,
|
|
2232
2466
|
force: false,
|
|
2233
2467
|
});
|
|
@@ -2262,6 +2496,9 @@ export class Session {
|
|
|
2262
2496
|
}
|
|
2263
2497
|
const findEntry = () => manager.getSnapshot(cwd).find((candidate) => candidate.provider === provider);
|
|
2264
2498
|
let entry = findEntry();
|
|
2499
|
+
if (entry && !entry.enabled) {
|
|
2500
|
+
return entry;
|
|
2501
|
+
}
|
|
2265
2502
|
if (!entry || entry.status === "loading") {
|
|
2266
2503
|
// Awaits the in-flight warmup (deduped per-cwd) so old clients still get
|
|
2267
2504
|
// a resolved answer rather than a loading placeholder.
|
|
@@ -2374,7 +2611,7 @@ export class Session {
|
|
|
2374
2611
|
}
|
|
2375
2612
|
async handleProviderDiagnosticRequest(msg) {
|
|
2376
2613
|
try {
|
|
2377
|
-
const client = this.
|
|
2614
|
+
const client = this.getProviderRegistry()[msg.provider].createClient(this.sessionLogger);
|
|
2378
2615
|
const diagnostic = client.getDiagnostic
|
|
2379
2616
|
? (await client.getDiagnostic()).diagnostic
|
|
2380
2617
|
: "No diagnostic available for this provider.";
|
|
@@ -2431,7 +2668,7 @@ export class Session {
|
|
|
2431
2668
|
? [
|
|
2432
2669
|
"Files changed:",
|
|
2433
2670
|
...diff.structured.map((file) => {
|
|
2434
|
-
const changeType = file
|
|
2671
|
+
const changeType = diffChangeTypeFor(file);
|
|
2435
2672
|
const status = file.status && file.status !== "ok" ? ` [${file.status}]` : "";
|
|
2436
2673
|
return `${changeType}\t${file.path}\t(+${file.additions} -${file.deletions})${status}`;
|
|
2437
2674
|
}),
|
|
@@ -2487,7 +2724,7 @@ export class Session {
|
|
|
2487
2724
|
? [
|
|
2488
2725
|
"Files changed:",
|
|
2489
2726
|
...diff.structured.map((file) => {
|
|
2490
|
-
const changeType = file
|
|
2727
|
+
const changeType = diffChangeTypeFor(file);
|
|
2491
2728
|
const status = file.status && file.status !== "ok" ? ` [${file.status}]` : "";
|
|
2492
2729
|
return `${changeType}\t${file.path}\t(+${file.additions} -${file.deletions})${status}`;
|
|
2493
2730
|
}),
|
|
@@ -2543,7 +2780,9 @@ export class Session {
|
|
|
2543
2780
|
return snapshot.git.isDirty === true;
|
|
2544
2781
|
}
|
|
2545
2782
|
catch (error) {
|
|
2546
|
-
throw new Error(`Unable to inspect git status for ${cwd}: ${error.message}
|
|
2783
|
+
throw new Error(`Unable to inspect git status for ${cwd}: ${error.message}`, {
|
|
2784
|
+
cause: error,
|
|
2785
|
+
});
|
|
2547
2786
|
}
|
|
2548
2787
|
}
|
|
2549
2788
|
async checkoutExistingBranch(cwd, branch) {
|
|
@@ -2623,7 +2862,9 @@ export class Session {
|
|
|
2623
2862
|
requestId,
|
|
2624
2863
|
agentId,
|
|
2625
2864
|
accepted: false,
|
|
2626
|
-
error: error?.message
|
|
2865
|
+
error: error?.message
|
|
2866
|
+
? String(error.message)
|
|
2867
|
+
: "Failed to set agent mode",
|
|
2627
2868
|
},
|
|
2628
2869
|
});
|
|
2629
2870
|
}
|
|
@@ -2655,7 +2896,9 @@ export class Session {
|
|
|
2655
2896
|
requestId,
|
|
2656
2897
|
agentId,
|
|
2657
2898
|
accepted: false,
|
|
2658
|
-
error: error?.message
|
|
2899
|
+
error: error?.message
|
|
2900
|
+
? String(error.message)
|
|
2901
|
+
: "Failed to set agent model",
|
|
2659
2902
|
},
|
|
2660
2903
|
});
|
|
2661
2904
|
}
|
|
@@ -2687,7 +2930,9 @@ export class Session {
|
|
|
2687
2930
|
requestId,
|
|
2688
2931
|
agentId,
|
|
2689
2932
|
accepted: false,
|
|
2690
|
-
error: error?.message
|
|
2933
|
+
error: error?.message
|
|
2934
|
+
? String(error.message)
|
|
2935
|
+
: "Failed to set agent feature",
|
|
2691
2936
|
},
|
|
2692
2937
|
});
|
|
2693
2938
|
}
|
|
@@ -2719,7 +2964,9 @@ export class Session {
|
|
|
2719
2964
|
requestId,
|
|
2720
2965
|
agentId,
|
|
2721
2966
|
accepted: false,
|
|
2722
|
-
error: error?.message
|
|
2967
|
+
error: error?.message
|
|
2968
|
+
? String(error.message)
|
|
2969
|
+
: "Failed to set agent thinking option",
|
|
2723
2970
|
},
|
|
2724
2971
|
});
|
|
2725
2972
|
}
|
|
@@ -3232,6 +3479,7 @@ export class Session {
|
|
|
3232
3479
|
cwd,
|
|
3233
3480
|
isGit: true,
|
|
3234
3481
|
repoRoot: snapshot.git.repoRoot,
|
|
3482
|
+
mainRepoRoot: snapshot.git.mainRepoRoot,
|
|
3235
3483
|
currentBranch: snapshot.git.currentBranch ?? null,
|
|
3236
3484
|
isDirty: snapshot.git.isDirty,
|
|
3237
3485
|
baseRef: snapshot.git.baseRef ?? null,
|
|
@@ -3322,7 +3570,9 @@ export class Session {
|
|
|
3322
3570
|
const message = branchLabel
|
|
3323
3571
|
? `${Session.PASEO_STASH_PREFIX} ${branchLabel}`
|
|
3324
3572
|
: `${Session.PASEO_STASH_PREFIX} unnamed`;
|
|
3325
|
-
await execCommand("git", ["stash", "push", "--include-untracked", "-m", message], {
|
|
3573
|
+
await execCommand("git", ["stash", "push", "--include-untracked", "-m", message], {
|
|
3574
|
+
cwd,
|
|
3575
|
+
});
|
|
3326
3576
|
await this.notifyGitMutation(cwd, "stash-push");
|
|
3327
3577
|
this.checkoutDiffManager.scheduleRefreshForCwd(cwd);
|
|
3328
3578
|
this.emit({
|
|
@@ -3340,7 +3590,9 @@ export class Session {
|
|
|
3340
3590
|
async handleStashPopRequest(msg) {
|
|
3341
3591
|
const { cwd, stashIndex, requestId } = msg;
|
|
3342
3592
|
try {
|
|
3343
|
-
await execCommand("git", ["stash", "pop", `stash@{${stashIndex}}`], {
|
|
3593
|
+
await execCommand("git", ["stash", "pop", `stash@{${stashIndex}}`], {
|
|
3594
|
+
cwd,
|
|
3595
|
+
});
|
|
3344
3596
|
await this.notifyGitMutation(cwd, "stash-pop");
|
|
3345
3597
|
this.checkoutDiffManager.scheduleRefreshForCwd(cwd);
|
|
3346
3598
|
this.emit({
|
|
@@ -3568,7 +3820,7 @@ export class Session {
|
|
|
3568
3820
|
title,
|
|
3569
3821
|
body,
|
|
3570
3822
|
base: msg.baseRef,
|
|
3571
|
-
}, this.github
|
|
3823
|
+
}, this.github);
|
|
3572
3824
|
await this.notifyGitMutation(cwd, "create-pr", { invalidateGithub: true });
|
|
3573
3825
|
this.emit({
|
|
3574
3826
|
type: "checkout_pr_create_response",
|
|
@@ -3912,9 +4164,12 @@ export class Session {
|
|
|
3912
4164
|
// (excluding internal agents which are for ephemeral system tasks)
|
|
3913
4165
|
const registryRecords = await this.agentStorage.list();
|
|
3914
4166
|
const liveIds = new Set(agentSnapshots.map((a) => a.id));
|
|
4167
|
+
const registeredProviderIds = this.getRegisteredProviderIds();
|
|
3915
4168
|
const persistedAgents = registryRecords
|
|
3916
4169
|
.filter((record) => !liveIds.has(record.id) && !record.internal)
|
|
3917
|
-
.
|
|
4170
|
+
.filter((record) => filter?.includeUnavailablePersisted === true ||
|
|
4171
|
+
isStoredAgentProviderAvailable(record, registeredProviderIds))
|
|
4172
|
+
.map((record) => this.buildStoredAgentPayload(record, registeredProviderIds));
|
|
3918
4173
|
let agents = [...liveAgents, ...persistedAgents];
|
|
3919
4174
|
agents = agents.filter((agent) => this.isProviderVisibleToClient(agent.provider));
|
|
3920
4175
|
// Filter by labels if filter provided
|
|
@@ -4095,25 +4350,7 @@ export class Session {
|
|
|
4095
4350
|
if (!payload.values || typeof payload.values !== "object") {
|
|
4096
4351
|
throw new SessionRequestError("invalid_cursor", "Invalid fetch_agents cursor");
|
|
4097
4352
|
}
|
|
4098
|
-
const cursorSort =
|
|
4099
|
-
for (const item of payload.sort) {
|
|
4100
|
-
if (!item ||
|
|
4101
|
-
typeof item !== "object" ||
|
|
4102
|
-
typeof item.key !== "string" ||
|
|
4103
|
-
typeof item.direction !== "string") {
|
|
4104
|
-
throw new SessionRequestError("invalid_cursor", "Invalid fetch_agents cursor");
|
|
4105
|
-
}
|
|
4106
|
-
const key = item.key;
|
|
4107
|
-
const direction = item.direction;
|
|
4108
|
-
if ((key !== "status_priority" &&
|
|
4109
|
-
key !== "created_at" &&
|
|
4110
|
-
key !== "updated_at" &&
|
|
4111
|
-
key !== "title") ||
|
|
4112
|
-
(direction !== "asc" && direction !== "desc")) {
|
|
4113
|
-
throw new SessionRequestError("invalid_cursor", "Invalid fetch_agents cursor");
|
|
4114
|
-
}
|
|
4115
|
-
cursorSort.push({ key, direction });
|
|
4116
|
-
}
|
|
4353
|
+
const cursorSort = parseFetchAgentsCursorSort(payload.sort);
|
|
4117
4354
|
if (cursorSort.length !== sort.length ||
|
|
4118
4355
|
cursorSort.some((entry, index) => entry.key !== sort[index]?.key || entry.direction !== sort[index]?.direction)) {
|
|
4119
4356
|
throw new SessionRequestError("invalid_cursor", "fetch_agents cursor does not match current sort");
|
|
@@ -4145,18 +4382,49 @@ export class Session {
|
|
|
4145
4382
|
.filter((project) => !project.archivedAt)
|
|
4146
4383
|
.map((project) => [project.projectId, project]));
|
|
4147
4384
|
const placementsByCwd = new Map();
|
|
4148
|
-
|
|
4149
|
-
if (workspace.archivedAt)
|
|
4150
|
-
|
|
4151
|
-
}
|
|
4385
|
+
const pairs = persistedWorkspaces.flatMap((workspace) => {
|
|
4386
|
+
if (workspace.archivedAt)
|
|
4387
|
+
return [];
|
|
4152
4388
|
const project = activeProjects.get(workspace.projectId);
|
|
4153
|
-
if (!project)
|
|
4154
|
-
|
|
4155
|
-
}
|
|
4156
|
-
|
|
4389
|
+
if (!project)
|
|
4390
|
+
return [];
|
|
4391
|
+
return [{ workspace, project }];
|
|
4392
|
+
});
|
|
4393
|
+
const placements = await Promise.all(pairs.map(({ workspace, project }) => this.buildProjectPlacementForWorkspace(workspace, project)));
|
|
4394
|
+
for (let i = 0; i < pairs.length; i += 1) {
|
|
4395
|
+
placementsByCwd.set(normalizePersistedWorkspaceId(pairs[i].workspace.cwd), placements[i]);
|
|
4157
4396
|
}
|
|
4158
4397
|
return placementsByCwd;
|
|
4159
4398
|
}
|
|
4399
|
+
async collectFetchAgentsEntries(params) {
|
|
4400
|
+
const { candidates, limit, getPlacement, filter } = params;
|
|
4401
|
+
const matchedEntries = [];
|
|
4402
|
+
const batchSize = 25;
|
|
4403
|
+
for (let start = 0; start < candidates.length && matchedEntries.length <= limit; start += batchSize) {
|
|
4404
|
+
const batch = candidates.slice(start, start + batchSize);
|
|
4405
|
+
const batchEntries = await Promise.all(batch.map(async (agent) => {
|
|
4406
|
+
const project = await getPlacement(agent.cwd);
|
|
4407
|
+
return project ? { agent, project } : null;
|
|
4408
|
+
}));
|
|
4409
|
+
for (const entry of batchEntries) {
|
|
4410
|
+
if (!entry) {
|
|
4411
|
+
continue;
|
|
4412
|
+
}
|
|
4413
|
+
if (!this.matchesAgentFilter({
|
|
4414
|
+
agent: entry.agent,
|
|
4415
|
+
project: entry.project,
|
|
4416
|
+
filter,
|
|
4417
|
+
})) {
|
|
4418
|
+
continue;
|
|
4419
|
+
}
|
|
4420
|
+
matchedEntries.push(entry);
|
|
4421
|
+
if (matchedEntries.length > limit) {
|
|
4422
|
+
break;
|
|
4423
|
+
}
|
|
4424
|
+
}
|
|
4425
|
+
}
|
|
4426
|
+
return matchedEntries;
|
|
4427
|
+
}
|
|
4160
4428
|
async listFetchAgentsEntries(request) {
|
|
4161
4429
|
const filter = request.type === "fetch_agent_history_request" &&
|
|
4162
4430
|
request.filter?.includeArchived === undefined
|
|
@@ -4166,6 +4434,7 @@ export class Session {
|
|
|
4166
4434
|
const sort = this.normalizeFetchAgentsSort(request.sort);
|
|
4167
4435
|
let agents = await this.listAgentPayloads({
|
|
4168
4436
|
labels: filter?.labels,
|
|
4437
|
+
includeUnavailablePersisted: request.type === "fetch_agent_history_request",
|
|
4169
4438
|
});
|
|
4170
4439
|
const activePlacementsByCwd = scope === "active" ? await this.buildActiveProjectPlacementsByWorkspaceCwd() : null;
|
|
4171
4440
|
if (activePlacementsByCwd) {
|
|
@@ -4192,31 +4461,12 @@ export class Session {
|
|
|
4192
4461
|
candidates = candidates.filter((agent) => this.compareAgentWithCursor(agent, cursor, sort) > 0);
|
|
4193
4462
|
}
|
|
4194
4463
|
const limit = request.page?.limit ?? 200;
|
|
4195
|
-
const matchedEntries =
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
return project ? { agent, project } : null;
|
|
4202
|
-
}));
|
|
4203
|
-
for (const entry of batchEntries) {
|
|
4204
|
-
if (!entry) {
|
|
4205
|
-
continue;
|
|
4206
|
-
}
|
|
4207
|
-
if (!this.matchesAgentFilter({
|
|
4208
|
-
agent: entry.agent,
|
|
4209
|
-
project: entry.project,
|
|
4210
|
-
filter,
|
|
4211
|
-
})) {
|
|
4212
|
-
continue;
|
|
4213
|
-
}
|
|
4214
|
-
matchedEntries.push(entry);
|
|
4215
|
-
if (matchedEntries.length > limit) {
|
|
4216
|
-
break;
|
|
4217
|
-
}
|
|
4218
|
-
}
|
|
4219
|
-
}
|
|
4464
|
+
const matchedEntries = await this.collectFetchAgentsEntries({
|
|
4465
|
+
candidates,
|
|
4466
|
+
limit,
|
|
4467
|
+
getPlacement,
|
|
4468
|
+
filter,
|
|
4469
|
+
});
|
|
4220
4470
|
const pagedEntries = matchedEntries.slice(0, limit);
|
|
4221
4471
|
const hasMore = matchedEntries.length > limit;
|
|
4222
4472
|
const nextCursor = hasMore && pagedEntries.length > 0
|
|
@@ -4277,6 +4527,11 @@ export class Session {
|
|
|
4277
4527
|
resolveHealth: this.resolveScriptHealth ?? undefined,
|
|
4278
4528
|
})
|
|
4279
4529
|
: [],
|
|
4530
|
+
...(resolvedProjectRecord
|
|
4531
|
+
? {
|
|
4532
|
+
project: await this.buildProjectPlacementForWorkspace(workspace, resolvedProjectRecord),
|
|
4533
|
+
}
|
|
4534
|
+
: {}),
|
|
4280
4535
|
};
|
|
4281
4536
|
}
|
|
4282
4537
|
buildWorkspaceGitRuntimePayload(snapshot) {
|
|
@@ -4363,16 +4618,14 @@ export class Session {
|
|
|
4363
4618
|
const descriptorsByWorkspaceId = new Map();
|
|
4364
4619
|
const workspaceIds = options.workspaceIds ? new Set(options.workspaceIds) : null;
|
|
4365
4620
|
const workspaceIdsByDirectory = new Map(activeRecords.map((workspace) => [normalizePersistedWorkspaceId(workspace.cwd), workspace.workspaceId]));
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
includeGitData: options.includeGitData,
|
|
4375
|
-
}));
|
|
4621
|
+
const includedWorkspaces = activeRecords.filter((workspace) => !workspaceIds || workspaceIds.has(workspace.workspaceId));
|
|
4622
|
+
const workspaceDescriptors = await Promise.all(includedWorkspaces.map((workspace) => this.buildWorkspaceDescriptor({
|
|
4623
|
+
workspace,
|
|
4624
|
+
projectRecord: activeProjects.get(workspace.projectId) ?? null,
|
|
4625
|
+
includeGitData: options.includeGitData,
|
|
4626
|
+
})));
|
|
4627
|
+
for (let i = 0; i < includedWorkspaces.length; i += 1) {
|
|
4628
|
+
descriptorsByWorkspaceId.set(includedWorkspaces[i].workspaceId, workspaceDescriptors[i]);
|
|
4376
4629
|
}
|
|
4377
4630
|
for (const agent of agents) {
|
|
4378
4631
|
if (agent.archivedAt) {
|
|
@@ -4402,8 +4655,13 @@ export class Session {
|
|
|
4402
4655
|
if (exact) {
|
|
4403
4656
|
return exact.workspaceId;
|
|
4404
4657
|
}
|
|
4658
|
+
const userHome = homedir();
|
|
4405
4659
|
let bestMatch = null;
|
|
4406
4660
|
for (const workspace of workspaces) {
|
|
4661
|
+
if (workspace.cwd === userHome)
|
|
4662
|
+
continue;
|
|
4663
|
+
if (workspace.archivedAt)
|
|
4664
|
+
continue;
|
|
4407
4665
|
const prefix = workspace.cwd.endsWith(sep) ? workspace.cwd : `${workspace.cwd}${sep}`;
|
|
4408
4666
|
if (!normalizedCwd.startsWith(prefix)) {
|
|
4409
4667
|
continue;
|
|
@@ -4488,25 +4746,7 @@ export class Session {
|
|
|
4488
4746
|
if (!payload.values || typeof payload.values !== "object") {
|
|
4489
4747
|
throw new SessionRequestError("invalid_cursor", "Invalid fetch_workspaces cursor");
|
|
4490
4748
|
}
|
|
4491
|
-
const cursorSort =
|
|
4492
|
-
for (const item of payload.sort) {
|
|
4493
|
-
if (!item ||
|
|
4494
|
-
typeof item !== "object" ||
|
|
4495
|
-
typeof item.key !== "string" ||
|
|
4496
|
-
typeof item.direction !== "string") {
|
|
4497
|
-
throw new SessionRequestError("invalid_cursor", "Invalid fetch_workspaces cursor");
|
|
4498
|
-
}
|
|
4499
|
-
const key = item.key;
|
|
4500
|
-
const direction = item.direction;
|
|
4501
|
-
if ((key !== "status_priority" &&
|
|
4502
|
-
key !== "activity_at" &&
|
|
4503
|
-
key !== "name" &&
|
|
4504
|
-
key !== "project_id") ||
|
|
4505
|
-
(direction !== "asc" && direction !== "desc")) {
|
|
4506
|
-
throw new SessionRequestError("invalid_cursor", "Invalid fetch_workspaces cursor");
|
|
4507
|
-
}
|
|
4508
|
-
cursorSort.push({ key, direction });
|
|
4509
|
-
}
|
|
4749
|
+
const cursorSort = parseFetchWorkspacesCursorSort(payload.sort);
|
|
4510
4750
|
if (cursorSort.length !== sort.length ||
|
|
4511
4751
|
cursorSort.some((entry, index) => entry.key !== sort[index]?.key || entry.direction !== sort[index]?.direction)) {
|
|
4512
4752
|
throw new SessionRequestError("invalid_cursor", "fetch_workspaces cursor does not match current sort");
|
|
@@ -4633,41 +4873,121 @@ export class Session {
|
|
|
4633
4873
|
}
|
|
4634
4874
|
}
|
|
4635
4875
|
async findOrCreateWorkspaceForDirectory(cwd) {
|
|
4876
|
+
const inputCwd = normalizePersistedWorkspaceId(cwd);
|
|
4636
4877
|
const normalizedCwd = await this.resolveWorkspaceDirectory(cwd);
|
|
4637
|
-
const existingWorkspace = await this.
|
|
4878
|
+
const existingWorkspace = await this.findExactWorkspaceByDirectory(normalizedCwd, {
|
|
4879
|
+
refreshGit: false,
|
|
4880
|
+
});
|
|
4638
4881
|
if (existingWorkspace) {
|
|
4639
|
-
|
|
4882
|
+
if (existingWorkspace.archivedAt && inputCwd !== normalizedCwd) {
|
|
4883
|
+
const timestamp = new Date().toISOString();
|
|
4884
|
+
const displayName = basename(inputCwd) || inputCwd;
|
|
4885
|
+
const projectRecord = createPersistedProjectRecord({
|
|
4886
|
+
projectId: inputCwd,
|
|
4887
|
+
rootPath: inputCwd,
|
|
4888
|
+
kind: "non_git",
|
|
4889
|
+
displayName,
|
|
4890
|
+
createdAt: timestamp,
|
|
4891
|
+
updatedAt: timestamp,
|
|
4892
|
+
});
|
|
4893
|
+
await this.projectRegistry.upsert(projectRecord);
|
|
4894
|
+
const workspaceRecord = createPersistedWorkspaceRecord({
|
|
4895
|
+
workspaceId: inputCwd,
|
|
4896
|
+
projectId: projectRecord.projectId,
|
|
4897
|
+
cwd: inputCwd,
|
|
4898
|
+
kind: "directory",
|
|
4899
|
+
displayName,
|
|
4900
|
+
createdAt: timestamp,
|
|
4901
|
+
updatedAt: timestamp,
|
|
4902
|
+
});
|
|
4903
|
+
await this.workspaceRegistry.upsert(workspaceRecord);
|
|
4904
|
+
return workspaceRecord;
|
|
4905
|
+
}
|
|
4906
|
+
return this.reclassifyOrUnarchiveWorkspaceForDirectory({
|
|
4907
|
+
workspace: existingWorkspace,
|
|
4908
|
+
project: await this.projectRegistry.get(existingWorkspace.projectId),
|
|
4909
|
+
cwd: normalizedCwd,
|
|
4910
|
+
});
|
|
4640
4911
|
}
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
const
|
|
4912
|
+
return this.createWorkspaceForDirectory(normalizedCwd);
|
|
4913
|
+
}
|
|
4914
|
+
async createWorkspaceForDirectory(cwd) {
|
|
4915
|
+
const checkout = await this.workspaceGitService.getCheckout(cwd);
|
|
4916
|
+
const membership = classifyDirectoryForProjectMembership({ cwd, checkout });
|
|
4646
4917
|
const timestamp = new Date().toISOString();
|
|
4647
|
-
const projectRecord =
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
kind: deriveProjectKind(placement.checkout),
|
|
4651
|
-
displayName: placement.projectName,
|
|
4652
|
-
createdAt: timestamp,
|
|
4653
|
-
updatedAt: timestamp,
|
|
4918
|
+
const projectRecord = await this.resolveProjectRecordForPlacement({
|
|
4919
|
+
membership,
|
|
4920
|
+
timestamp,
|
|
4654
4921
|
});
|
|
4655
4922
|
await this.projectRegistry.upsert(projectRecord);
|
|
4656
4923
|
const workspaceRecord = createPersistedWorkspaceRecord({
|
|
4657
|
-
workspaceId,
|
|
4658
|
-
projectId:
|
|
4659
|
-
cwd
|
|
4660
|
-
kind:
|
|
4661
|
-
displayName:
|
|
4662
|
-
cwd: normalizedCwd,
|
|
4663
|
-
checkout: placement.checkout,
|
|
4664
|
-
}),
|
|
4924
|
+
workspaceId: membership.workspaceId,
|
|
4925
|
+
projectId: projectRecord.projectId,
|
|
4926
|
+
cwd,
|
|
4927
|
+
kind: membership.workspaceKind,
|
|
4928
|
+
displayName: membership.workspaceDisplayName,
|
|
4665
4929
|
createdAt: timestamp,
|
|
4666
4930
|
updatedAt: timestamp,
|
|
4667
4931
|
});
|
|
4668
4932
|
await this.workspaceRegistry.upsert(workspaceRecord);
|
|
4669
4933
|
return workspaceRecord;
|
|
4670
4934
|
}
|
|
4935
|
+
async reclassifyOrUnarchiveWorkspaceForDirectory(input) {
|
|
4936
|
+
const checkout = await this.workspaceGitService.getCheckout(input.cwd);
|
|
4937
|
+
const membership = classifyDirectoryForProjectMembership({ cwd: input.cwd, checkout });
|
|
4938
|
+
const timestamp = new Date().toISOString();
|
|
4939
|
+
const projectRecord = await this.resolveProjectRecordForPlacement({
|
|
4940
|
+
membership,
|
|
4941
|
+
timestamp,
|
|
4942
|
+
});
|
|
4943
|
+
const projectId = projectRecord.projectId;
|
|
4944
|
+
const kind = membership.workspaceKind;
|
|
4945
|
+
const displayName = membership.workspaceDisplayName;
|
|
4946
|
+
if (input.workspace.workspaceId === membership.workspaceId &&
|
|
4947
|
+
input.workspace.projectId === projectId &&
|
|
4948
|
+
input.workspace.kind === kind &&
|
|
4949
|
+
input.workspace.displayName === displayName) {
|
|
4950
|
+
return this.ensureWorkspaceRecordUnarchived(input.workspace);
|
|
4951
|
+
}
|
|
4952
|
+
await this.projectRegistry.upsert(projectRecord);
|
|
4953
|
+
const nextWorkspace = {
|
|
4954
|
+
...input.workspace,
|
|
4955
|
+
workspaceId: membership.workspaceId,
|
|
4956
|
+
projectId,
|
|
4957
|
+
cwd: input.cwd,
|
|
4958
|
+
kind,
|
|
4959
|
+
displayName,
|
|
4960
|
+
archivedAt: null,
|
|
4961
|
+
updatedAt: timestamp,
|
|
4962
|
+
};
|
|
4963
|
+
await this.workspaceRegistry.upsert(nextWorkspace);
|
|
4964
|
+
return nextWorkspace;
|
|
4965
|
+
}
|
|
4966
|
+
async resolveProjectRecordForPlacement(input) {
|
|
4967
|
+
const rootPath = input.membership.projectRootPath;
|
|
4968
|
+
const kind = input.membership.projectKind;
|
|
4969
|
+
const projects = await this.projectRegistry.list();
|
|
4970
|
+
const existingProject = projects.find((project) => !project.archivedAt && project.rootPath === rootPath) ??
|
|
4971
|
+
projects.find((project) => project.rootPath === rootPath) ??
|
|
4972
|
+
null;
|
|
4973
|
+
if (!existingProject) {
|
|
4974
|
+
return createPersistedProjectRecord({
|
|
4975
|
+
projectId: input.membership.projectKey,
|
|
4976
|
+
rootPath,
|
|
4977
|
+
kind,
|
|
4978
|
+
displayName: input.membership.projectName,
|
|
4979
|
+
createdAt: input.timestamp,
|
|
4980
|
+
updatedAt: input.timestamp,
|
|
4981
|
+
});
|
|
4982
|
+
}
|
|
4983
|
+
return {
|
|
4984
|
+
...existingProject,
|
|
4985
|
+
rootPath,
|
|
4986
|
+
kind,
|
|
4987
|
+
archivedAt: null,
|
|
4988
|
+
updatedAt: input.timestamp,
|
|
4989
|
+
};
|
|
4990
|
+
}
|
|
4671
4991
|
async ensureWorkspaceRecordUnarchived(workspace) {
|
|
4672
4992
|
const project = await this.projectRegistry.get(workspace.projectId);
|
|
4673
4993
|
if (!workspace.archivedAt && (!project || !project.archivedAt)) {
|
|
@@ -4749,7 +5069,7 @@ export class Session {
|
|
|
4749
5069
|
const result = await service.runOnce();
|
|
4750
5070
|
const changedWorkspaceIds = new Set();
|
|
4751
5071
|
const changedProjectIds = new Set();
|
|
4752
|
-
|
|
5072
|
+
await Promise.all(result.changesApplied.map(async (change) => {
|
|
4753
5073
|
switch (change.kind) {
|
|
4754
5074
|
case "workspace_archived":
|
|
4755
5075
|
await this.removeWorkspaceGitWatchTarget(change.directory);
|
|
@@ -4765,7 +5085,7 @@ export class Session {
|
|
|
4765
5085
|
changedProjectIds.add(change.projectId);
|
|
4766
5086
|
break;
|
|
4767
5087
|
}
|
|
4768
|
-
}
|
|
5088
|
+
}));
|
|
4769
5089
|
if (changedProjectIds.size > 0) {
|
|
4770
5090
|
for (const workspace of await this.workspaceRegistry.list()) {
|
|
4771
5091
|
if (changedProjectIds.has(workspace.projectId)) {
|
|
@@ -4844,11 +5164,7 @@ export class Session {
|
|
|
4844
5164
|
}
|
|
4845
5165
|
async handleFetchAgents(request) {
|
|
4846
5166
|
const requestedSubscriptionId = request.subscribe?.subscriptionId?.trim();
|
|
4847
|
-
const subscriptionId = request.subscribe
|
|
4848
|
-
? requestedSubscriptionId && requestedSubscriptionId.length > 0
|
|
4849
|
-
? requestedSubscriptionId
|
|
4850
|
-
: uuidv4()
|
|
4851
|
-
: null;
|
|
5167
|
+
const subscriptionId = resolveSubscriptionId(request.subscribe, requestedSubscriptionId);
|
|
4852
5168
|
try {
|
|
4853
5169
|
if (subscriptionId) {
|
|
4854
5170
|
this.agentUpdatesSubscription = {
|
|
@@ -4924,11 +5240,7 @@ export class Session {
|
|
|
4924
5240
|
}
|
|
4925
5241
|
async handleFetchWorkspacesRequest(request) {
|
|
4926
5242
|
const requestedSubscriptionId = request.subscribe?.subscriptionId?.trim();
|
|
4927
|
-
const subscriptionId = request.subscribe
|
|
4928
|
-
? requestedSubscriptionId && requestedSubscriptionId.length > 0
|
|
4929
|
-
? requestedSubscriptionId
|
|
4930
|
-
: uuidv4()
|
|
4931
|
-
: null;
|
|
5243
|
+
const subscriptionId = resolveSubscriptionId(request.subscribe, requestedSubscriptionId);
|
|
4932
5244
|
try {
|
|
4933
5245
|
this.sessionLogger.debug({
|
|
4934
5246
|
requestId: request.requestId,
|
|
@@ -4997,8 +5309,9 @@ export class Session {
|
|
|
4997
5309
|
async handleOpenProjectRequest(request) {
|
|
4998
5310
|
try {
|
|
4999
5311
|
const workspace = await this.findOrCreateWorkspaceForDirectory(request.cwd);
|
|
5312
|
+
await this.syncWorkspaceGitObserverForWorkspace(workspace);
|
|
5313
|
+
const descriptor = await this.describeWorkspaceRecord(workspace);
|
|
5000
5314
|
await this.emitWorkspaceUpdateForCwd(workspace.cwd);
|
|
5001
|
-
const descriptor = await this.describeWorkspaceRecordWithGitData(workspace);
|
|
5002
5315
|
this.emit({
|
|
5003
5316
|
type: "open_project_response",
|
|
5004
5317
|
payload: {
|
|
@@ -5007,6 +5320,15 @@ export class Session {
|
|
|
5007
5320
|
error: null,
|
|
5008
5321
|
},
|
|
5009
5322
|
});
|
|
5323
|
+
void this.workspaceGitService
|
|
5324
|
+
.getSnapshot(workspace.cwd, {
|
|
5325
|
+
force: true,
|
|
5326
|
+
includeGitHub: true,
|
|
5327
|
+
reason: "open_project",
|
|
5328
|
+
})
|
|
5329
|
+
.catch((error) => {
|
|
5330
|
+
this.sessionLogger.warn({ err: error, cwd: workspace.cwd }, "Background snapshot refresh failed after open_project");
|
|
5331
|
+
});
|
|
5010
5332
|
}
|
|
5011
5333
|
catch (error) {
|
|
5012
5334
|
const message = error instanceof Error ? error.message : "Failed to open project";
|
|
@@ -5274,6 +5596,55 @@ export class Session {
|
|
|
5274
5596
|
payload: { requestId, agent, project, error: null },
|
|
5275
5597
|
});
|
|
5276
5598
|
}
|
|
5599
|
+
loadProjectedTimelineWindow(params) {
|
|
5600
|
+
const { agentId, direction, cursor, requestedLimit, provider } = params;
|
|
5601
|
+
let timeline = params.timeline;
|
|
5602
|
+
const projectedLimit = Math.max(1, Math.floor(requestedLimit));
|
|
5603
|
+
let fetchLimit = projectedLimit;
|
|
5604
|
+
let projectedWindow = selectTimelineWindowByProjectedLimit({
|
|
5605
|
+
rows: timeline.rows,
|
|
5606
|
+
provider,
|
|
5607
|
+
direction,
|
|
5608
|
+
limit: projectedLimit,
|
|
5609
|
+
collapseToolLifecycle: false,
|
|
5610
|
+
});
|
|
5611
|
+
while (timeline.hasOlder) {
|
|
5612
|
+
const needsMoreProjectedEntries = projectedWindow.projectedEntries.length < projectedLimit;
|
|
5613
|
+
const firstLoadedRow = timeline.rows[0];
|
|
5614
|
+
const firstSelectedRow = projectedWindow.selectedRows[0];
|
|
5615
|
+
const startsAtLoadedBoundary = firstLoadedRow != null &&
|
|
5616
|
+
firstSelectedRow != null &&
|
|
5617
|
+
firstSelectedRow.seq === firstLoadedRow.seq;
|
|
5618
|
+
const boundaryIsAssistantChunk = startsAtLoadedBoundary && firstLoadedRow.item.type === "assistant_message";
|
|
5619
|
+
if (!needsMoreProjectedEntries && !boundaryIsAssistantChunk) {
|
|
5620
|
+
break;
|
|
5621
|
+
}
|
|
5622
|
+
const maxRows = Math.max(0, timeline.window.maxSeq - timeline.window.minSeq + 1);
|
|
5623
|
+
const nextFetchLimit = Math.min(maxRows, fetchLimit * 2);
|
|
5624
|
+
if (nextFetchLimit <= fetchLimit) {
|
|
5625
|
+
break;
|
|
5626
|
+
}
|
|
5627
|
+
fetchLimit = nextFetchLimit;
|
|
5628
|
+
timeline = this.agentManager.fetchTimeline(agentId, {
|
|
5629
|
+
direction,
|
|
5630
|
+
cursor,
|
|
5631
|
+
limit: fetchLimit,
|
|
5632
|
+
});
|
|
5633
|
+
projectedWindow = selectTimelineWindowByProjectedLimit({
|
|
5634
|
+
rows: timeline.rows,
|
|
5635
|
+
provider,
|
|
5636
|
+
direction,
|
|
5637
|
+
limit: projectedLimit,
|
|
5638
|
+
collapseToolLifecycle: false,
|
|
5639
|
+
});
|
|
5640
|
+
}
|
|
5641
|
+
return {
|
|
5642
|
+
timeline,
|
|
5643
|
+
selectedRows: projectedWindow.selectedRows,
|
|
5644
|
+
minSeq: projectedWindow.minSeq,
|
|
5645
|
+
maxSeq: projectedWindow.maxSeq,
|
|
5646
|
+
};
|
|
5647
|
+
}
|
|
5277
5648
|
async handleFetchAgentTimelineRequest(msg) {
|
|
5278
5649
|
const direction = msg.direction ?? (msg.cursor ? "after" : "tail");
|
|
5279
5650
|
const projection = msg.projection ?? "projected";
|
|
@@ -5309,51 +5680,20 @@ export class Session {
|
|
|
5309
5680
|
let endCursor = null;
|
|
5310
5681
|
let entries;
|
|
5311
5682
|
if (shouldLimitByProjectedWindow) {
|
|
5312
|
-
const
|
|
5313
|
-
|
|
5314
|
-
let projectedWindow = selectTimelineWindowByProjectedLimit({
|
|
5315
|
-
rows: timeline.rows,
|
|
5316
|
-
provider: snapshot.provider,
|
|
5683
|
+
const projectedResult = this.loadProjectedTimelineWindow({
|
|
5684
|
+
agentId: msg.agentId,
|
|
5317
5685
|
direction,
|
|
5318
|
-
|
|
5319
|
-
|
|
5686
|
+
cursor,
|
|
5687
|
+
requestedLimit,
|
|
5688
|
+
provider: snapshot.provider,
|
|
5689
|
+
timeline,
|
|
5320
5690
|
});
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
firstSelectedRow.seq === firstLoadedRow.seq;
|
|
5328
|
-
const boundaryIsAssistantChunk = startsAtLoadedBoundary && firstLoadedRow.item.type === "assistant_message";
|
|
5329
|
-
if (!needsMoreProjectedEntries && !boundaryIsAssistantChunk) {
|
|
5330
|
-
break;
|
|
5331
|
-
}
|
|
5332
|
-
const maxRows = Math.max(0, timeline.window.maxSeq - timeline.window.minSeq + 1);
|
|
5333
|
-
const nextFetchLimit = Math.min(maxRows, fetchLimit * 2);
|
|
5334
|
-
if (nextFetchLimit <= fetchLimit) {
|
|
5335
|
-
break;
|
|
5336
|
-
}
|
|
5337
|
-
fetchLimit = nextFetchLimit;
|
|
5338
|
-
timeline = this.agentManager.fetchTimeline(msg.agentId, {
|
|
5339
|
-
direction,
|
|
5340
|
-
cursor,
|
|
5341
|
-
limit: fetchLimit,
|
|
5342
|
-
});
|
|
5343
|
-
projectedWindow = selectTimelineWindowByProjectedLimit({
|
|
5344
|
-
rows: timeline.rows,
|
|
5345
|
-
provider: snapshot.provider,
|
|
5346
|
-
direction,
|
|
5347
|
-
limit: projectedLimit,
|
|
5348
|
-
collapseToolLifecycle: false,
|
|
5349
|
-
});
|
|
5350
|
-
}
|
|
5351
|
-
const selectedRows = projectedWindow.selectedRows;
|
|
5352
|
-
entries = projectTimelineRows(selectedRows, snapshot.provider, projection);
|
|
5353
|
-
if (projectedWindow.minSeq !== null && projectedWindow.maxSeq !== null) {
|
|
5354
|
-
startCursor = { epoch: timeline.epoch, seq: projectedWindow.minSeq };
|
|
5355
|
-
endCursor = { epoch: timeline.epoch, seq: projectedWindow.maxSeq };
|
|
5356
|
-
hasOlder = projectedWindow.minSeq > timeline.window.minSeq;
|
|
5691
|
+
timeline = projectedResult.timeline;
|
|
5692
|
+
entries = projectTimelineRows(projectedResult.selectedRows, snapshot.provider, projection);
|
|
5693
|
+
if (projectedResult.minSeq !== null && projectedResult.maxSeq !== null) {
|
|
5694
|
+
startCursor = { epoch: timeline.epoch, seq: projectedResult.minSeq };
|
|
5695
|
+
endCursor = { epoch: timeline.epoch, seq: projectedResult.maxSeq };
|
|
5696
|
+
hasOlder = projectedResult.minSeq > timeline.window.minSeq;
|
|
5357
5697
|
hasNewer = false;
|
|
5358
5698
|
}
|
|
5359
5699
|
}
|
|
@@ -5461,18 +5801,13 @@ export class Session {
|
|
|
5461
5801
|
await this.agentManager.waitForAgentRunStart(agentId, { signal: startAbort.signal });
|
|
5462
5802
|
}
|
|
5463
5803
|
catch (error) {
|
|
5464
|
-
const message = error instanceof Error
|
|
5465
|
-
? error.message
|
|
5466
|
-
: typeof error === "string"
|
|
5467
|
-
? error
|
|
5468
|
-
: "Unknown error";
|
|
5469
5804
|
this.emit({
|
|
5470
5805
|
type: "send_agent_message_response",
|
|
5471
5806
|
payload: {
|
|
5472
5807
|
requestId: msg.requestId,
|
|
5473
5808
|
agentId,
|
|
5474
5809
|
accepted: false,
|
|
5475
|
-
error:
|
|
5810
|
+
error: errorToFriendlyMessage(error),
|
|
5476
5811
|
},
|
|
5477
5812
|
});
|
|
5478
5813
|
return;
|
|
@@ -5491,18 +5826,13 @@ export class Session {
|
|
|
5491
5826
|
});
|
|
5492
5827
|
}
|
|
5493
5828
|
catch (error) {
|
|
5494
|
-
const message = error instanceof Error
|
|
5495
|
-
? error.message
|
|
5496
|
-
: typeof error === "string"
|
|
5497
|
-
? error
|
|
5498
|
-
: "Unknown error";
|
|
5499
5829
|
this.emit({
|
|
5500
5830
|
type: "send_agent_message_response",
|
|
5501
5831
|
payload: {
|
|
5502
5832
|
requestId: msg.requestId,
|
|
5503
5833
|
agentId: resolved.agentId,
|
|
5504
5834
|
accepted: false,
|
|
5505
|
-
error:
|
|
5835
|
+
error: errorToFriendlyMessage(error),
|
|
5506
5836
|
},
|
|
5507
5837
|
});
|
|
5508
5838
|
}
|
|
@@ -5540,11 +5870,16 @@ export class Session {
|
|
|
5540
5870
|
return;
|
|
5541
5871
|
}
|
|
5542
5872
|
const final = this.buildStoredAgentPayload(record);
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5873
|
+
let status;
|
|
5874
|
+
if (record.attentionReason === "permission") {
|
|
5875
|
+
status = "permission";
|
|
5876
|
+
}
|
|
5877
|
+
else if (record.lastStatus === "error") {
|
|
5878
|
+
status = "error";
|
|
5879
|
+
}
|
|
5880
|
+
else {
|
|
5881
|
+
status = "idle";
|
|
5882
|
+
}
|
|
5548
5883
|
const error = resolveWaitForFinishError({ status, final });
|
|
5549
5884
|
this.emit({
|
|
5550
5885
|
type: "wait_for_finish_response",
|
|
@@ -5568,11 +5903,16 @@ export class Session {
|
|
|
5568
5903
|
if (!final) {
|
|
5569
5904
|
throw new Error(`Agent ${agentId} disappeared while waiting`);
|
|
5570
5905
|
}
|
|
5571
|
-
let status
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5906
|
+
let status;
|
|
5907
|
+
if (result.permission) {
|
|
5908
|
+
status = "permission";
|
|
5909
|
+
}
|
|
5910
|
+
else if (result.status === "error") {
|
|
5911
|
+
status = "error";
|
|
5912
|
+
}
|
|
5913
|
+
else {
|
|
5914
|
+
status = "idle";
|
|
5915
|
+
}
|
|
5576
5916
|
const error = resolveWaitForFinishError({ status, final });
|
|
5577
5917
|
this.emit({
|
|
5578
5918
|
type: "wait_for_finish_response",
|
|
@@ -5583,11 +5923,7 @@ export class Session {
|
|
|
5583
5923
|
const isAbort = error instanceof Error &&
|
|
5584
5924
|
(error.name === "AbortError" || error.message.toLowerCase().includes("aborted"));
|
|
5585
5925
|
if (!isAbort) {
|
|
5586
|
-
const message = error
|
|
5587
|
-
? error.message
|
|
5588
|
-
: typeof error === "string"
|
|
5589
|
-
? error
|
|
5590
|
-
: "Unknown error";
|
|
5926
|
+
const message = errorToFriendlyMessage(error);
|
|
5591
5927
|
this.sessionLogger.error({ err: error, agentId }, "wait_for_finish_request failed");
|
|
5592
5928
|
const final = await this.getAgentPayloadById(agentId);
|
|
5593
5929
|
this.emit({
|
|
@@ -5604,7 +5940,7 @@ export class Session {
|
|
|
5604
5940
|
}
|
|
5605
5941
|
const final = await this.getAgentPayloadById(agentId);
|
|
5606
5942
|
if (!final) {
|
|
5607
|
-
throw new Error(`Agent ${agentId} disappeared while waiting
|
|
5943
|
+
throw new Error(`Agent ${agentId} disappeared while waiting`, { cause: error });
|
|
5608
5944
|
}
|
|
5609
5945
|
this.emit({
|
|
5610
5946
|
type: "wait_for_finish_response",
|
|
@@ -5620,44 +5956,7 @@ export class Session {
|
|
|
5620
5956
|
/**
|
|
5621
5957
|
* Handle audio chunk for buffering and transcription
|
|
5622
5958
|
*/
|
|
5623
|
-
async
|
|
5624
|
-
if (!this.isVoiceMode) {
|
|
5625
|
-
this.sessionLogger.warn("Received voice_audio_chunk while voice mode is disabled; transcript will be emitted but voice assistant turn is skipped");
|
|
5626
|
-
}
|
|
5627
|
-
const chunkFormat = msg.format || "audio/wav";
|
|
5628
|
-
if (this.isVoiceMode) {
|
|
5629
|
-
if (!this.voiceTurnController) {
|
|
5630
|
-
throw new Error("Voice mode is enabled but the voice turn controller is not running");
|
|
5631
|
-
}
|
|
5632
|
-
const chunkBytes = Buffer.byteLength(msg.audio, "base64");
|
|
5633
|
-
this.voiceInputChunkCount += 1;
|
|
5634
|
-
this.voiceInputBytes += chunkBytes;
|
|
5635
|
-
if (this.voiceInputChunkCount === 1) {
|
|
5636
|
-
this.sessionLogger.info({
|
|
5637
|
-
format: chunkFormat,
|
|
5638
|
-
audioBytes: chunkBytes,
|
|
5639
|
-
}, "Received first voice_audio_chunk for active voice mode");
|
|
5640
|
-
}
|
|
5641
|
-
const now = Date.now();
|
|
5642
|
-
if (this.voiceInputChunkCount % 50 === 0 || now - this.voiceInputWindowStartedAt >= 1000) {
|
|
5643
|
-
this.sessionLogger.info({
|
|
5644
|
-
chunkCount: this.voiceInputChunkCount,
|
|
5645
|
-
audioBytes: this.voiceInputBytes,
|
|
5646
|
-
windowMs: now - this.voiceInputWindowStartedAt,
|
|
5647
|
-
format: chunkFormat,
|
|
5648
|
-
}, "Voice input chunk summary");
|
|
5649
|
-
this.voiceInputWindowStartedAt = now;
|
|
5650
|
-
this.voiceInputChunkCount = 0;
|
|
5651
|
-
this.voiceInputBytes = 0;
|
|
5652
|
-
}
|
|
5653
|
-
await this.voiceTurnController.appendClientChunk({
|
|
5654
|
-
audioBase64: msg.audio,
|
|
5655
|
-
format: chunkFormat,
|
|
5656
|
-
});
|
|
5657
|
-
return;
|
|
5658
|
-
}
|
|
5659
|
-
const chunkBuffer = Buffer.from(msg.audio, "base64");
|
|
5660
|
-
const isPCMChunk = chunkFormat.toLowerCase().includes("pcm");
|
|
5959
|
+
async ensureAudioBufferForFormat(chunkFormat, isPCMChunk) {
|
|
5661
5960
|
if (!this.audioBuffer) {
|
|
5662
5961
|
this.audioBuffer = {
|
|
5663
5962
|
chunks: [],
|
|
@@ -5665,8 +5964,8 @@ export class Session {
|
|
|
5665
5964
|
isPCM: isPCMChunk,
|
|
5666
5965
|
totalPCMBytes: 0,
|
|
5667
5966
|
};
|
|
5967
|
+
return this.audioBuffer;
|
|
5668
5968
|
}
|
|
5669
|
-
// If the format changes mid-stream, flush what we have first
|
|
5670
5969
|
if (this.audioBuffer.isPCM !== isPCMChunk) {
|
|
5671
5970
|
this.sessionLogger.debug({
|
|
5672
5971
|
oldFormat: this.audioBuffer.isPCM ? "pcm" : this.audioBuffer.format,
|
|
@@ -5682,19 +5981,61 @@ export class Session {
|
|
|
5682
5981
|
isPCM: isPCMChunk,
|
|
5683
5982
|
totalPCMBytes: 0,
|
|
5684
5983
|
};
|
|
5984
|
+
return this.audioBuffer;
|
|
5685
5985
|
}
|
|
5686
|
-
|
|
5687
|
-
// Keep latest format info for non-PCM blobs
|
|
5986
|
+
if (!this.audioBuffer.isPCM) {
|
|
5688
5987
|
this.audioBuffer.format = chunkFormat;
|
|
5689
5988
|
}
|
|
5690
|
-
this.audioBuffer
|
|
5691
|
-
|
|
5692
|
-
|
|
5989
|
+
return this.audioBuffer;
|
|
5990
|
+
}
|
|
5991
|
+
async forwardAudioChunkToVoiceTurn(msg, chunkFormat) {
|
|
5992
|
+
if (!this.voiceTurnController) {
|
|
5993
|
+
throw new Error("Voice mode is enabled but the voice turn controller is not running");
|
|
5994
|
+
}
|
|
5995
|
+
const chunkBytes = Buffer.byteLength(msg.audio, "base64");
|
|
5996
|
+
this.voiceInputChunkCount += 1;
|
|
5997
|
+
this.voiceInputBytes += chunkBytes;
|
|
5998
|
+
if (this.voiceInputChunkCount === 1) {
|
|
5999
|
+
this.sessionLogger.info({
|
|
6000
|
+
format: chunkFormat,
|
|
6001
|
+
audioBytes: chunkBytes,
|
|
6002
|
+
}, "Received first voice_audio_chunk for active voice mode");
|
|
6003
|
+
}
|
|
6004
|
+
const now = Date.now();
|
|
6005
|
+
if (this.voiceInputChunkCount % 50 === 0 || now - this.voiceInputWindowStartedAt >= 1000) {
|
|
6006
|
+
this.sessionLogger.info({
|
|
6007
|
+
chunkCount: this.voiceInputChunkCount,
|
|
6008
|
+
audioBytes: this.voiceInputBytes,
|
|
6009
|
+
windowMs: now - this.voiceInputWindowStartedAt,
|
|
6010
|
+
format: chunkFormat,
|
|
6011
|
+
}, "Voice input chunk summary");
|
|
6012
|
+
this.voiceInputWindowStartedAt = now;
|
|
6013
|
+
this.voiceInputChunkCount = 0;
|
|
6014
|
+
this.voiceInputBytes = 0;
|
|
6015
|
+
}
|
|
6016
|
+
await this.voiceTurnController.appendClientChunk({
|
|
6017
|
+
audioBase64: msg.audio,
|
|
6018
|
+
format: chunkFormat,
|
|
6019
|
+
});
|
|
6020
|
+
}
|
|
6021
|
+
async handleAudioChunk(msg) {
|
|
6022
|
+
if (!this.isVoiceMode) {
|
|
6023
|
+
this.sessionLogger.warn("Received voice_audio_chunk while voice mode is disabled; transcript will be emitted but voice assistant turn is skipped");
|
|
6024
|
+
}
|
|
6025
|
+
const chunkFormat = msg.format || "audio/wav";
|
|
6026
|
+
if (this.isVoiceMode) {
|
|
6027
|
+
await this.forwardAudioChunkToVoiceTurn(msg, chunkFormat);
|
|
6028
|
+
return;
|
|
6029
|
+
}
|
|
6030
|
+
const chunkBuffer = Buffer.from(msg.audio, "base64");
|
|
6031
|
+
const isPCMChunk = chunkFormat.toLowerCase().includes("pcm");
|
|
6032
|
+
const buffer = await this.ensureAudioBufferForFormat(chunkFormat, isPCMChunk);
|
|
6033
|
+
buffer.chunks.push(chunkBuffer);
|
|
6034
|
+
if (buffer.isPCM) {
|
|
6035
|
+
buffer.totalPCMBytes += chunkBuffer.length;
|
|
5693
6036
|
}
|
|
5694
6037
|
// In non-voice mode, use streaming threshold to process chunks
|
|
5695
|
-
const reachedStreamingThreshold = !this.isVoiceMode &&
|
|
5696
|
-
this.audioBuffer.isPCM &&
|
|
5697
|
-
this.audioBuffer.totalPCMBytes >= MIN_STREAMING_SEGMENT_BYTES;
|
|
6038
|
+
const reachedStreamingThreshold = !this.isVoiceMode && buffer.isPCM && buffer.totalPCMBytes >= MIN_STREAMING_SEGMENT_BYTES;
|
|
5698
6039
|
if (!msg.isLast && reachedStreamingThreshold) {
|
|
5699
6040
|
return;
|
|
5700
6041
|
}
|
|
@@ -6261,7 +6602,7 @@ export class Session {
|
|
|
6261
6602
|
async handleChatPostRequest(request) {
|
|
6262
6603
|
try {
|
|
6263
6604
|
const authorAgentId = request.authorAgentId?.trim() || this.clientId;
|
|
6264
|
-
const message = await this.chatService.
|
|
6605
|
+
const message = await this.chatService.dispatchMessage({
|
|
6265
6606
|
room: request.room,
|
|
6266
6607
|
authorAgentId,
|
|
6267
6608
|
body: request.body,
|
|
@@ -6611,11 +6952,7 @@ export class Session {
|
|
|
6611
6952
|
}
|
|
6612
6953
|
this.emitTerminalsChangedSnapshot({
|
|
6613
6954
|
cwd: event.cwd,
|
|
6614
|
-
terminals: this.filterStandaloneTerminals(event.terminals).map((terminal) => ({
|
|
6615
|
-
id: terminal.id,
|
|
6616
|
-
name: terminal.name,
|
|
6617
|
-
...(terminal.title ? { title: terminal.title } : {}),
|
|
6618
|
-
})),
|
|
6955
|
+
terminals: this.filterStandaloneTerminals(event.terminals).map((terminal) => Object.assign({ id: terminal.id, name: terminal.name }, terminal.title ? { title: terminal.title } : {})),
|
|
6619
6956
|
});
|
|
6620
6957
|
}
|
|
6621
6958
|
handleSubscribeTerminalsRequest(msg) {
|
|
@@ -7037,7 +7374,7 @@ export class Session {
|
|
|
7037
7374
|
return true;
|
|
7038
7375
|
}
|
|
7039
7376
|
disposeTerminalSubscriptions() {
|
|
7040
|
-
for (const terminalId of
|
|
7377
|
+
for (const terminalId of Array.from(this.terminalIdToSlot.keys())) {
|
|
7041
7378
|
this.detachTerminalStream(terminalId, { emitExit: false });
|
|
7042
7379
|
}
|
|
7043
7380
|
}
|