@getpaseo/server 0.1.62 → 0.1.65
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 +15 -13
- package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -1
- package/dist/server/client/daemon-client-websocket-transport.d.ts +3 -2
- package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -1
- package/dist/server/client/daemon-client-websocket-transport.js +9 -8
- package/dist/server/client/daemon-client-websocket-transport.js.map +1 -1
- package/dist/server/client/daemon-client.d.ts +88 -56
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +264 -111
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/client/terminal-stream-router.d.ts +24 -0
- package/dist/server/client/terminal-stream-router.d.ts.map +1 -0
- package/dist/server/client/terminal-stream-router.js +100 -0
- package/dist/server/client/terminal-stream-router.js.map +1 -0
- package/dist/server/server/agent/activity-curator.d.ts +6 -3
- package/dist/server/server/agent/activity-curator.d.ts.map +1 -1
- package/dist/server/server/agent/activity-curator.js +45 -138
- package/dist/server/server/agent/activity-curator.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 +46 -31
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
- package/dist/server/server/agent/agent-manager.js +457 -419
- package/dist/server/server/agent/agent-manager.js.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.d.ts +6 -11
- package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.js +3 -85
- 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 +58 -41
- 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 +7 -7
- package/dist/server/server/agent/agent-stream-coalescer.d.ts.map +1 -1
- package/dist/server/server/agent/agent-stream-coalescer.js +1 -1
- package/dist/server/server/agent/agent-stream-coalescer.js.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 +103 -85
- package/dist/server/server/agent/agent-timeline-store.js.map +1 -1
- package/dist/server/server/agent/foreground-run-state.d.ts +50 -0
- package/dist/server/server/agent/foreground-run-state.d.ts.map +1 -0
- package/dist/server/server/agent/foreground-run-state.js +162 -0
- package/dist/server/server/agent/foreground-run-state.js.map +1 -0
- package/dist/server/server/agent/mcp-server.d.ts +5 -3
- package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
- package/dist/server/server/agent/mcp-server.js +282 -234
- 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 +9 -1
- 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/prompt-attachments.d.ts +4 -3
- package/dist/server/server/agent/prompt-attachments.d.ts.map +1 -1
- package/dist/server/server/agent/prompt-attachments.js +43 -4
- package/dist/server/server/agent/prompt-attachments.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-manifest.d.ts.map +1 -1
- package/dist/server/server/agent/provider-manifest.js +7 -0
- package/dist/server/server/agent/provider-manifest.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 +49 -13
- package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.js +404 -261
- 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 +83 -206
- 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 +654 -554
- 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 +174 -185
- 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 +62 -13
- 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 +873 -646
- 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 +6 -2
- 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 +294 -113
- package/dist/server/server/agent/providers/mock-load-test-agent.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +94 -2
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +2 -2
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +24 -115
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts +104 -3
- package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.js +786 -503
- 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/provider-runner.d.ts +27 -0
- package/dist/server/server/agent/providers/provider-runner.d.ts.map +1 -0
- package/dist/server/server/agent/providers/provider-runner.js +80 -0
- package/dist/server/server/agent/providers/provider-runner.js.map +1 -0
- 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 +9 -6
- 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 +4 -2
- package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js +31 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -1
- package/dist/server/server/agent/stt-manager.d.ts.map +1 -1
- package/dist/server/server/agent/stt-manager.js +63 -53
- package/dist/server/server/agent/stt-manager.js.map +1 -1
- package/dist/server/server/agent/timeline-projection.d.ts +27 -11
- package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
- package/dist/server/server/agent/timeline-projection.js +70 -15
- 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/auth.d.ts +25 -0
- package/dist/server/server/auth.d.ts.map +1 -0
- package/dist/server/server/auth.js +93 -0
- package/dist/server/server/auth.js.map +1 -0
- package/dist/server/server/bootstrap.d.ts +7 -5
- package/dist/server/server/bootstrap.d.ts.map +1 -1
- package/dist/server/server/bootstrap.js +550 -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 +79 -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 +10 -4
- package/dist/server/server/exports.d.ts.map +1 -1
- package/dist/server/server/exports.js +7 -4
- 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/file-explorer/service.d.ts +10 -0
- package/dist/server/server/file-explorer/service.d.ts.map +1 -1
- package/dist/server/server/file-explorer/service.js +38 -4
- package/dist/server/server/file-explorer/service.js.map +1 -1
- package/dist/server/server/index.js +25 -18
- 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 +41 -21
- 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/pagination/cursor.d.ts +16 -0
- package/dist/server/server/pagination/cursor.d.ts.map +1 -0
- package/dist/server/server/pagination/cursor.js +62 -0
- package/dist/server/server/pagination/cursor.js.map +1 -0
- package/dist/server/server/pagination/sortable-pager.d.ts +24 -0
- package/dist/server/server/pagination/sortable-pager.d.ts.map +1 -0
- package/dist/server/server/pagination/sortable-pager.js +68 -0
- package/dist/server/server/pagination/sortable-pager.js.map +1 -0
- 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 +7 -5
- package/dist/server/server/paseo-worktree-archive-service.d.ts.map +1 -1
- package/dist/server/server/paseo-worktree-archive-service.js +70 -62
- package/dist/server/server/paseo-worktree-archive-service.js.map +1 -1
- package/dist/server/server/paseo-worktree-service.d.ts +13 -0
- package/dist/server/server/paseo-worktree-service.d.ts.map +1 -1
- package/dist/server/server/paseo-worktree-service.js +72 -3
- package/dist/server/server/paseo-worktree-service.js.map +1 -1
- package/dist/server/server/persisted-config.d.ts +87 -62
- package/dist/server/server/persisted-config.d.ts.map +1 -1
- package/dist/server/server/persisted-config.js +13 -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 +43 -20
- package/dist/server/server/relay-transport.js.map +1 -1
- package/dist/server/server/resolve-worktree-creation-intent.d.ts +0 -10
- package/dist/server/server/resolve-worktree-creation-intent.d.ts.map +1 -1
- package/dist/server/server/resolve-worktree-creation-intent.js +1 -45
- package/dist/server/server/resolve-worktree-creation-intent.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 +10 -5
- package/dist/server/server/script-status-projection.d.ts.map +1 -1
- package/dist/server/server/script-status-projection.js +66 -47
- 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 +64 -65
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +1356 -1734
- 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 +34 -22
- package/dist/server/server/websocket-server.d.ts.map +1 -1
- package/dist/server/server/websocket-server.js +360 -205
- package/dist/server/server/websocket-server.js.map +1 -1
- package/dist/server/server/workspace-directory.d.ts +69 -0
- package/dist/server/server/workspace-directory.d.ts.map +1 -0
- package/dist/server/server/workspace-directory.js +229 -0
- package/dist/server/server/workspace-directory.js.map +1 -0
- 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 +101 -69
- package/dist/server/server/worktree-bootstrap.js.map +1 -1
- package/dist/server/server/worktree-core.d.ts +2 -0
- package/dist/server/server/worktree-core.d.ts.map +1 -1
- package/dist/server/server/worktree-core.js.map +1 -1
- package/dist/server/server/worktree-errors.d.ts +1 -1
- package/dist/server/server/worktree-errors.d.ts.map +1 -1
- package/dist/server/server/worktree-errors.js +1 -4
- package/dist/server/server/worktree-errors.js.map +1 -1
- package/dist/server/server/worktree-session.d.ts +54 -27
- package/dist/server/server/worktree-session.d.ts.map +1 -1
- package/dist/server/server/worktree-session.js +95 -44
- 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/binary-frames/file-transfer.d.ts +56 -0
- package/dist/server/shared/binary-frames/file-transfer.d.ts.map +1 -0
- package/dist/server/shared/binary-frames/file-transfer.js +108 -0
- package/dist/server/shared/binary-frames/file-transfer.js.map +1 -0
- package/dist/server/shared/binary-frames/index.d.ts +3 -0
- package/dist/server/shared/binary-frames/index.d.ts.map +1 -0
- package/dist/server/shared/binary-frames/index.js +3 -0
- package/dist/server/shared/binary-frames/index.js.map +1 -0
- package/dist/server/shared/{terminal-stream-protocol.d.ts → binary-frames/terminal.d.ts} +4 -4
- package/dist/server/shared/binary-frames/terminal.d.ts.map +1 -0
- package/dist/server/shared/{terminal-stream-protocol.js → binary-frames/terminal.js} +2 -2
- package/dist/server/shared/binary-frames/terminal.js.map +1 -0
- package/dist/server/shared/client-capabilities.d.ts +5 -0
- package/dist/server/shared/client-capabilities.d.ts.map +1 -0
- package/dist/server/shared/client-capabilities.js +4 -0
- package/dist/server/shared/client-capabilities.js.map +1 -0
- package/dist/server/shared/connection-offer.d.ts +8 -0
- package/dist/server/shared/connection-offer.d.ts.map +1 -1
- package/dist/server/shared/connection-offer.js +35 -0
- package/dist/server/shared/connection-offer.js.map +1 -1
- package/dist/server/shared/daemon-endpoints.d.ts +18 -3
- package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
- package/dist/server/shared/daemon-endpoints.js +82 -8
- package/dist/server/shared/daemon-endpoints.js.map +1 -1
- package/dist/server/shared/host-connection-schema.d.ts +23 -0
- package/dist/server/shared/host-connection-schema.d.ts.map +1 -0
- package/dist/server/shared/host-connection-schema.js +9 -0
- package/dist/server/shared/host-connection-schema.js.map +1 -0
- package/dist/server/shared/messages.d.ts +25073 -3453
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +152 -36
- package/dist/server/shared/messages.js.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-factory.d.ts +7 -0
- package/dist/server/terminal/terminal-manager-factory.d.ts.map +1 -0
- package/dist/server/terminal/terminal-manager-factory.js +13 -0
- package/dist/server/terminal/terminal-manager-factory.js.map +1 -0
- package/dist/server/terminal/terminal-manager.d.ts +7 -1
- package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
- package/dist/server/terminal/terminal-manager.js +15 -4
- 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-session-controller.d.ts +63 -0
- package/dist/server/terminal/terminal-session-controller.d.ts.map +1 -0
- package/dist/server/terminal/terminal-session-controller.js +615 -0
- package/dist/server/terminal/terminal-session-controller.js.map +1 -0
- package/dist/server/terminal/terminal-ts-loader.mjs +20 -0
- package/dist/server/terminal/terminal-worker-process.d.ts +2 -0
- package/dist/server/terminal/terminal-worker-process.d.ts.map +1 -0
- package/dist/server/terminal/terminal-worker-process.js +221 -0
- package/dist/server/terminal/terminal-worker-process.js.map +1 -0
- package/dist/server/terminal/terminal-worker-protocol.d.ts +113 -0
- package/dist/server/terminal/terminal-worker-protocol.d.ts.map +1 -0
- package/dist/server/terminal/terminal-worker-protocol.js +2 -0
- package/dist/server/terminal/terminal-worker-protocol.js.map +1 -0
- package/dist/server/terminal/terminal.d.ts +10 -2
- package/dist/server/terminal/terminal.d.ts.map +1 -1
- package/dist/server/terminal/terminal.js +79 -28
- package/dist/server/terminal/terminal.js.map +1 -1
- package/dist/server/terminal/worker-terminal-manager.d.ts +19 -0
- package/dist/server/terminal/worker-terminal-manager.d.ts.map +1 -0
- package/dist/server/terminal/worker-terminal-manager.js +466 -0
- package/dist/server/terminal/worker-terminal-manager.js.map +1 -0
- 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.d.ts.map +1 -1
- package/dist/server/utils/directory-suggestions.js +22 -34
- 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/process-tree.d.ts +25 -0
- package/dist/server/utils/process-tree.d.ts.map +1 -0
- package/dist/server/utils/process-tree.js +96 -0
- package/dist/server/utils/process-tree.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 +41 -0
- package/dist/server/utils/windows-command.js.map +1 -0
- package/dist/server/utils/worktree-metadata.d.ts +44 -0
- package/dist/server/utils/worktree-metadata.d.ts.map +1 -1
- package/dist/server/utils/worktree-metadata.js +58 -0
- package/dist/server/utils/worktree-metadata.js.map +1 -1
- package/dist/server/utils/worktree.d.ts +23 -8
- package/dist/server/utils/worktree.d.ts.map +1 -1
- package/dist/server/utils/worktree.js +81 -63
- package/dist/server/utils/worktree.js.map +1 -1
- package/dist/src/server/pid-lock.js.map +1 -1
- package/package.json +17 -21
- 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
- package/dist/server/shared/terminal-stream-protocol.d.ts.map +0 -1
- package/dist/server/shared/terminal-stream-protocol.js.map +0 -1
|
@@ -2,12 +2,15 @@ import { homedir } from "node:os";
|
|
|
2
2
|
import { createOpencodeClient, } from "@opencode-ai/sdk/v2/client";
|
|
3
3
|
import net from "node:net";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import {
|
|
5
|
+
import { createProviderEnvSpec, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
|
|
6
6
|
import { findExecutable, isCommandAvailable } from "../../../utils/executable.js";
|
|
7
|
+
import { terminateProcessTree } from "../../../utils/process-tree.js";
|
|
7
8
|
import { withTimeout } from "../../../utils/promise-timeout.js";
|
|
8
9
|
import { spawnProcess } from "../../../utils/spawn.js";
|
|
10
|
+
import { buildToolCallDisplayModel } from "../../../shared/tool-call-display.js";
|
|
9
11
|
import { mapOpencodeToolCall } from "./opencode/tool-call-mapper.js";
|
|
10
12
|
import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, resolveBinaryVersion, toDiagnosticErrorMessage, } from "./diagnostic-utils.js";
|
|
13
|
+
import { runProviderTurn } from "./provider-runner.js";
|
|
11
14
|
import { renderPromptAttachmentAsText } from "../prompt-attachments.js";
|
|
12
15
|
const OPENCODE_CAPABILITIES = {
|
|
13
16
|
supportsStreaming: true,
|
|
@@ -17,9 +20,11 @@ const OPENCODE_CAPABILITIES = {
|
|
|
17
20
|
supportsReasoningStream: true,
|
|
18
21
|
supportsToolInvocations: true,
|
|
19
22
|
};
|
|
23
|
+
const OPENCODE_BUILD_MODE_ID = "build";
|
|
24
|
+
const OPENCODE_FULL_ACCESS_MODE_ID = "full-access";
|
|
20
25
|
const DEFAULT_MODES = [
|
|
21
26
|
{
|
|
22
|
-
id:
|
|
27
|
+
id: OPENCODE_BUILD_MODE_ID,
|
|
23
28
|
label: "Build",
|
|
24
29
|
description: "Allows edits and tool execution for implementation work",
|
|
25
30
|
},
|
|
@@ -28,9 +33,20 @@ const DEFAULT_MODES = [
|
|
|
28
33
|
label: "Plan",
|
|
29
34
|
description: "Read-only planning mode that avoids file edits",
|
|
30
35
|
},
|
|
36
|
+
{
|
|
37
|
+
id: OPENCODE_FULL_ACCESS_MODE_ID,
|
|
38
|
+
label: "Full Access",
|
|
39
|
+
description: "Automatically approves all tool permission prompts for the session",
|
|
40
|
+
},
|
|
31
41
|
];
|
|
32
42
|
const MCP_ALREADY_PRESENT_ERROR_TOKENS = ["already", "exists", "connected"];
|
|
33
43
|
const OPENCODE_PROVIDER_LIST_TIMEOUT_MS = 30000;
|
|
44
|
+
const OPENCODE_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS = 5000;
|
|
45
|
+
const OPENCODE_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS = 1000;
|
|
46
|
+
const OPENCODE_HANDLED_BUILTIN_SLASH_COMMANDS = [
|
|
47
|
+
{ name: "compact", description: "Compact the current session", argumentHint: "" },
|
|
48
|
+
{ name: "summarize", description: "Compact the current session", argumentHint: "" },
|
|
49
|
+
];
|
|
34
50
|
const OPENCODE_FATAL_RETRY_MESSAGE_TOKENS = [
|
|
35
51
|
"insufficient balance",
|
|
36
52
|
"no resource package",
|
|
@@ -140,20 +156,18 @@ function toOpenCodeMcpConfig(config) {
|
|
|
140
156
|
enabled: true,
|
|
141
157
|
};
|
|
142
158
|
}
|
|
143
|
-
function
|
|
144
|
-
if (
|
|
145
|
-
return
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
159
|
+
function toTerminalTurnEvent(event) {
|
|
160
|
+
if (event.type === "turn_failed") {
|
|
161
|
+
return {
|
|
162
|
+
type: "turn_failed",
|
|
163
|
+
provider: "opencode",
|
|
164
|
+
error: toDiagnosticErrorMessage(event.error),
|
|
165
|
+
};
|
|
149
166
|
}
|
|
150
|
-
|
|
151
|
-
return
|
|
167
|
+
if (event.type === "turn_completed" || event.type === "turn_canceled") {
|
|
168
|
+
return event;
|
|
152
169
|
}
|
|
153
|
-
|
|
154
|
-
function normalizeTurnFailureError(error) {
|
|
155
|
-
const normalized = stringifyUnknownError(error).trim();
|
|
156
|
-
return normalized.length > 0 ? normalized : "Unknown error";
|
|
170
|
+
return null;
|
|
157
171
|
}
|
|
158
172
|
function isOpenCodeNotFoundError(error) {
|
|
159
173
|
return (typeof error === "object" &&
|
|
@@ -171,14 +185,14 @@ async function reconcileOpenCodeSessionClose(params) {
|
|
|
171
185
|
if (response.error && !isOpenCodeNotFoundError(response.error)) {
|
|
172
186
|
logger.warn({
|
|
173
187
|
sessionId,
|
|
174
|
-
error:
|
|
188
|
+
error: toDiagnosticErrorMessage(response.error),
|
|
175
189
|
}, "Failed to abort OpenCode session during close");
|
|
176
190
|
}
|
|
177
191
|
}
|
|
178
192
|
catch (error) {
|
|
179
193
|
logger.warn({
|
|
180
194
|
sessionId,
|
|
181
|
-
error:
|
|
195
|
+
error: toDiagnosticErrorMessage(error),
|
|
182
196
|
}, "Failed to abort OpenCode session during close");
|
|
183
197
|
}
|
|
184
198
|
try {
|
|
@@ -190,14 +204,14 @@ async function reconcileOpenCodeSessionClose(params) {
|
|
|
190
204
|
if (response.error && !isOpenCodeNotFoundError(response.error)) {
|
|
191
205
|
logger.warn({
|
|
192
206
|
sessionId,
|
|
193
|
-
error:
|
|
207
|
+
error: toDiagnosticErrorMessage(response.error),
|
|
194
208
|
}, "Failed to archive OpenCode session during close");
|
|
195
209
|
}
|
|
196
210
|
}
|
|
197
211
|
catch (error) {
|
|
198
212
|
logger.warn({
|
|
199
213
|
sessionId,
|
|
200
|
-
error:
|
|
214
|
+
error: toDiagnosticErrorMessage(error),
|
|
201
215
|
}, "Failed to archive OpenCode session during close");
|
|
202
216
|
}
|
|
203
217
|
}
|
|
@@ -216,18 +230,19 @@ function isOpenCodeHeadersTimeoutFailure(error) {
|
|
|
216
230
|
if (!current) {
|
|
217
231
|
continue;
|
|
218
232
|
}
|
|
219
|
-
const normalized =
|
|
233
|
+
const normalized = toDiagnosticErrorMessage(current).trim().toLowerCase();
|
|
220
234
|
if (normalized) {
|
|
221
235
|
diagnostics.add(normalized);
|
|
222
236
|
}
|
|
223
237
|
if (typeof current === "object") {
|
|
224
238
|
const record = current;
|
|
225
239
|
for (const value of [record.message, record.code, record.name]) {
|
|
226
|
-
if (typeof value
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
240
|
+
if (typeof value !== "string") {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const diagnostic = value.trim().toLowerCase();
|
|
244
|
+
if (diagnostic) {
|
|
245
|
+
diagnostics.add(diagnostic);
|
|
231
246
|
}
|
|
232
247
|
}
|
|
233
248
|
if (record.cause) {
|
|
@@ -238,7 +253,7 @@ function isOpenCodeHeadersTimeoutFailure(error) {
|
|
|
238
253
|
return [...diagnostics].some((diagnostic) => OPENCODE_HEADERS_TIMEOUT_TOKENS.some((token) => diagnostic.includes(token)));
|
|
239
254
|
}
|
|
240
255
|
function isAlreadyPresentMcpError(error) {
|
|
241
|
-
const normalized =
|
|
256
|
+
const normalized = toDiagnosticErrorMessage(error).toLowerCase();
|
|
242
257
|
return MCP_ALREADY_PRESENT_ERROR_TOKENS.some((token) => normalized.includes(token));
|
|
243
258
|
}
|
|
244
259
|
async function findAvailablePort() {
|
|
@@ -269,10 +284,26 @@ function resolvePartDedupeKey(part, partType) {
|
|
|
269
284
|
function normalizeOpenCodeModeId(modeId) {
|
|
270
285
|
const trimmed = typeof modeId === "string" ? modeId.trim() : "";
|
|
271
286
|
if (!trimmed || trimmed === "default") {
|
|
272
|
-
return
|
|
287
|
+
return OPENCODE_BUILD_MODE_ID;
|
|
273
288
|
}
|
|
274
289
|
return trimmed;
|
|
275
290
|
}
|
|
291
|
+
function resolveOpenCodeRuntimeAgentId(modeId) {
|
|
292
|
+
const normalizedModeId = normalizeOpenCodeModeId(modeId);
|
|
293
|
+
return normalizedModeId === OPENCODE_FULL_ACCESS_MODE_ID
|
|
294
|
+
? OPENCODE_BUILD_MODE_ID
|
|
295
|
+
: normalizedModeId;
|
|
296
|
+
}
|
|
297
|
+
function isSelectableOpenCodeAgent(agent) {
|
|
298
|
+
return (agent.mode === "primary" || agent.mode === "all") && agent.hidden !== true;
|
|
299
|
+
}
|
|
300
|
+
function mergeOpenCodeModes(discoveredModes) {
|
|
301
|
+
const modesById = new Map(DEFAULT_MODES.map((mode) => [mode.id, mode]));
|
|
302
|
+
for (const mode of discoveredModes) {
|
|
303
|
+
modesById.set(mode.id, mode);
|
|
304
|
+
}
|
|
305
|
+
return sortOpenCodeModes(Array.from(modesById.values()));
|
|
306
|
+
}
|
|
276
307
|
function sortOpenCodeModes(modes) {
|
|
277
308
|
const order = new Map(DEFAULT_MODES.map((mode, index) => [mode.id, index]));
|
|
278
309
|
return [...modes].sort((left, right) => {
|
|
@@ -458,18 +489,18 @@ function buildOpenCodePromptParts(prompt) {
|
|
|
458
489
|
output.push({ type: "text", text: part.text });
|
|
459
490
|
continue;
|
|
460
491
|
}
|
|
461
|
-
if (part.type === "
|
|
462
|
-
|
|
492
|
+
if (part.type === "image") {
|
|
493
|
+
attachmentOrdinal += 1;
|
|
494
|
+
const normalized = toOpenCodeDataUrl(part.mimeType, part.data);
|
|
495
|
+
output.push({
|
|
496
|
+
type: "file",
|
|
497
|
+
mime: normalized.mimeType,
|
|
498
|
+
filename: `attachment-${attachmentOrdinal}.${getOpenCodeAttachmentExtension(normalized.mimeType)}`,
|
|
499
|
+
url: normalized.url,
|
|
500
|
+
});
|
|
463
501
|
continue;
|
|
464
502
|
}
|
|
465
|
-
|
|
466
|
-
const normalized = toOpenCodeDataUrl(part.mimeType, part.data);
|
|
467
|
-
output.push({
|
|
468
|
-
type: "file",
|
|
469
|
-
mime: normalized.mimeType,
|
|
470
|
-
filename: `attachment-${attachmentOrdinal}.${getOpenCodeAttachmentExtension(normalized.mimeType)}`,
|
|
471
|
-
url: normalized.url,
|
|
472
|
-
});
|
|
503
|
+
output.push({ type: "text", text: renderPromptAttachmentAsText(part) });
|
|
473
504
|
}
|
|
474
505
|
return output;
|
|
475
506
|
}
|
|
@@ -485,6 +516,10 @@ export const __openCodeInternals = {
|
|
|
485
516
|
reconcileOpenCodeSessionClose,
|
|
486
517
|
resolveOpenCodeModelLookupKeyFromAssistantMessage,
|
|
487
518
|
resolveOpenCodeSelectedModelContextWindow,
|
|
519
|
+
isSelectableOpenCodeAgent,
|
|
520
|
+
get OpenCodeAgentSession() {
|
|
521
|
+
return OpenCodeAgentSession;
|
|
522
|
+
},
|
|
488
523
|
};
|
|
489
524
|
export class OpenCodeServerManager {
|
|
490
525
|
constructor(logger, runtimeSettings) {
|
|
@@ -601,17 +636,41 @@ export class OpenCodeServerManager {
|
|
|
601
636
|
const launchPrefix = await resolveProviderCommandPrefix(this.runtimeSettings?.command, resolveOpenCodeBinary);
|
|
602
637
|
return new Promise((resolve, reject) => {
|
|
603
638
|
const serverProcess = spawnProcess(launchPrefix.command, [...launchPrefix.args, "serve", "--port", String(port)], {
|
|
639
|
+
detached: process.platform !== "win32",
|
|
604
640
|
stdio: ["ignore", "pipe", "pipe"],
|
|
605
|
-
|
|
641
|
+
...createProviderEnvSpec({ runtimeSettings: this.runtimeSettings }),
|
|
606
642
|
});
|
|
607
643
|
let started = false;
|
|
644
|
+
let stderrBuffer = "";
|
|
645
|
+
let stdoutBuffer = "";
|
|
646
|
+
const STARTUP_BUFFER_CAP = 8192;
|
|
647
|
+
const appendCapped = (current, chunk) => {
|
|
648
|
+
if (current.length >= STARTUP_BUFFER_CAP) {
|
|
649
|
+
return current;
|
|
650
|
+
}
|
|
651
|
+
const remaining = STARTUP_BUFFER_CAP - current.length;
|
|
652
|
+
return current + chunk.slice(0, remaining);
|
|
653
|
+
};
|
|
654
|
+
const buildStartupErrorMessage = (headline) => {
|
|
655
|
+
const sections = [headline];
|
|
656
|
+
const stderrTrimmed = stderrBuffer.trim();
|
|
657
|
+
if (stderrTrimmed.length > 0) {
|
|
658
|
+
sections.push(`stderr: ${stderrTrimmed}`);
|
|
659
|
+
}
|
|
660
|
+
const stdoutTrimmed = stdoutBuffer.trim();
|
|
661
|
+
if (stdoutTrimmed.length > 0) {
|
|
662
|
+
sections.push(`stdout: ${stdoutTrimmed}`);
|
|
663
|
+
}
|
|
664
|
+
return sections.join("\n");
|
|
665
|
+
};
|
|
608
666
|
const timeout = setTimeout(() => {
|
|
609
667
|
if (!started) {
|
|
610
|
-
reject(new Error("OpenCode server startup timeout"));
|
|
668
|
+
reject(new Error(buildStartupErrorMessage("OpenCode server startup timeout")));
|
|
611
669
|
}
|
|
612
670
|
}, 30000);
|
|
613
671
|
serverProcess.stdout?.on("data", (data) => {
|
|
614
672
|
const output = data.toString();
|
|
673
|
+
stdoutBuffer = appendCapped(stdoutBuffer, output);
|
|
615
674
|
if (output.includes("listening on") && !started) {
|
|
616
675
|
started = true;
|
|
617
676
|
clearTimeout(timeout);
|
|
@@ -625,16 +684,19 @@ export class OpenCodeServerManager {
|
|
|
625
684
|
}
|
|
626
685
|
});
|
|
627
686
|
serverProcess.stderr?.on("data", (data) => {
|
|
628
|
-
|
|
687
|
+
const output = data.toString();
|
|
688
|
+
stderrBuffer = appendCapped(stderrBuffer, output);
|
|
689
|
+
this.logger.error({ stderr: output.trim() }, "OpenCode server stderr");
|
|
629
690
|
});
|
|
630
691
|
serverProcess.on("error", (error) => {
|
|
631
692
|
clearTimeout(timeout);
|
|
632
|
-
|
|
693
|
+
const headline = error instanceof Error ? error.message : String(error);
|
|
694
|
+
reject(new Error(buildStartupErrorMessage(headline)));
|
|
633
695
|
});
|
|
634
696
|
serverProcess.on("exit", (code) => {
|
|
635
697
|
if (!started) {
|
|
636
698
|
clearTimeout(timeout);
|
|
637
|
-
reject(new Error(`OpenCode server exited with code ${code}`));
|
|
699
|
+
reject(new Error(buildStartupErrorMessage(`OpenCode server exited with code ${code}`)));
|
|
638
700
|
}
|
|
639
701
|
if (this.currentServer?.process === serverProcess) {
|
|
640
702
|
this.currentServer = null;
|
|
@@ -652,9 +714,7 @@ export class OpenCodeServerManager {
|
|
|
652
714
|
...(this.currentServer ? [this.currentServer] : []),
|
|
653
715
|
...Array.from(this.retiredServers),
|
|
654
716
|
];
|
|
655
|
-
|
|
656
|
-
await this.killServer(server);
|
|
657
|
-
}
|
|
717
|
+
await Promise.all(servers.map((server) => this.killServer(server)));
|
|
658
718
|
this.currentServer = null;
|
|
659
719
|
this.retiredServers.clear();
|
|
660
720
|
}
|
|
@@ -670,17 +730,16 @@ export class OpenCodeServerManager {
|
|
|
670
730
|
if (server.process.killed) {
|
|
671
731
|
return;
|
|
672
732
|
}
|
|
673
|
-
await
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
clearTimeout(timeout);
|
|
680
|
-
resolve();
|
|
681
|
-
});
|
|
682
|
-
server.process.kill("SIGTERM");
|
|
733
|
+
const result = await terminateProcessTree(server.process, {
|
|
734
|
+
gracefulTimeoutMs: OPENCODE_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS,
|
|
735
|
+
forceTimeoutMs: OPENCODE_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS,
|
|
736
|
+
onForceSignal: () => {
|
|
737
|
+
this.logger.warn({ timeoutMs: OPENCODE_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS }, "OpenCode server did not exit after SIGTERM; sending SIGKILL");
|
|
738
|
+
},
|
|
683
739
|
});
|
|
740
|
+
if (result === "kill-timeout") {
|
|
741
|
+
this.logger.warn({ timeoutMs: OPENCODE_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS }, "OpenCode server did not report exit after SIGKILL");
|
|
742
|
+
}
|
|
684
743
|
}
|
|
685
744
|
}
|
|
686
745
|
OpenCodeServerManager.instance = null;
|
|
@@ -801,16 +860,14 @@ export class OpenCodeAgentClient {
|
|
|
801
860
|
if (response.error || !response.data) {
|
|
802
861
|
return DEFAULT_MODES;
|
|
803
862
|
}
|
|
804
|
-
const discovered = response.data
|
|
805
|
-
.filter((agent) => agent.mode === "primary" && agent.hidden !== true)
|
|
806
|
-
.map((agent) => ({
|
|
863
|
+
const discovered = response.data.filter(isSelectableOpenCodeAgent).map((agent) => ({
|
|
807
864
|
id: agent.name,
|
|
808
865
|
label: agent.name.charAt(0).toUpperCase() + agent.name.slice(1),
|
|
809
866
|
description: typeof agent.description === "string" && agent.description.trim().length > 0
|
|
810
867
|
? agent.description.trim()
|
|
811
868
|
: DEFAULT_MODES.find((mode) => mode.id === agent.name)?.description,
|
|
812
869
|
}));
|
|
813
|
-
return
|
|
870
|
+
return mergeOpenCodeModes(discovered);
|
|
814
871
|
}
|
|
815
872
|
finally {
|
|
816
873
|
acquisition.release();
|
|
@@ -839,7 +896,7 @@ export class OpenCodeAgentClient {
|
|
|
839
896
|
serverStatus = `Running (${url})`;
|
|
840
897
|
}
|
|
841
898
|
catch (error) {
|
|
842
|
-
serverStatus = `Unavailable (${
|
|
899
|
+
serverStatus = `Unavailable (${toDiagnosticErrorMessage(error)})`;
|
|
843
900
|
}
|
|
844
901
|
if (available) {
|
|
845
902
|
try {
|
|
@@ -905,6 +962,8 @@ export class OpenCodeAgentClient {
|
|
|
905
962
|
}
|
|
906
963
|
}
|
|
907
964
|
}
|
|
965
|
+
const MAX_OPENCODE_SUB_AGENT_ACTIONS = 200;
|
|
966
|
+
const MAX_OPENCODE_PENDING_CHILD_TOOL_PARTS = 200;
|
|
908
967
|
function stringifyStructuredAssistantMessage(value) {
|
|
909
968
|
if (value === undefined) {
|
|
910
969
|
return null;
|
|
@@ -1039,309 +1098,518 @@ export function translateOpenCodeEvent(event, state) {
|
|
|
1039
1098
|
const events = [];
|
|
1040
1099
|
switch (event.type) {
|
|
1041
1100
|
case "session.created":
|
|
1042
|
-
case "session.updated":
|
|
1043
|
-
|
|
1044
|
-
events.push({
|
|
1045
|
-
type: "thread_started",
|
|
1046
|
-
sessionId: state.sessionId,
|
|
1047
|
-
provider: "opencode",
|
|
1048
|
-
});
|
|
1049
|
-
}
|
|
1101
|
+
case "session.updated":
|
|
1102
|
+
appendOpenCodeSessionCreatedOrUpdated(event, state, events);
|
|
1050
1103
|
break;
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
const info = event.properties.info;
|
|
1054
|
-
if (info.sessionID !== state.sessionId) {
|
|
1055
|
-
break;
|
|
1056
|
-
}
|
|
1057
|
-
state.messageRoles.set(info.id, info.role);
|
|
1058
|
-
if (info.role === "assistant") {
|
|
1059
|
-
const modelLookupKey = resolveOpenCodeModelLookupKeyFromAssistantMessage(info);
|
|
1060
|
-
if (modelLookupKey) {
|
|
1061
|
-
const contextWindowMaxTokens = state.modelContextWindowsByModelKey?.get(modelLookupKey);
|
|
1062
|
-
if (contextWindowMaxTokens !== undefined) {
|
|
1063
|
-
state.onAssistantModelContextWindowResolved?.(contextWindowMaxTokens);
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
if (!state.emittedStructuredMessageIds.has(info.id) && info.time?.completed !== undefined) {
|
|
1067
|
-
const text = stringifyStructuredAssistantMessage(info.structured);
|
|
1068
|
-
if (text) {
|
|
1069
|
-
state.emittedStructuredMessageIds.add(info.id);
|
|
1070
|
-
events.push({
|
|
1071
|
-
type: "timeline",
|
|
1072
|
-
provider: "opencode",
|
|
1073
|
-
item: { type: "assistant_message", text },
|
|
1074
|
-
});
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1104
|
+
case "message.updated":
|
|
1105
|
+
appendOpenCodeMessageUpdated(event, state, events);
|
|
1078
1106
|
break;
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
if (partKey && state.streamedPartKeys.delete(partKey)) {
|
|
1094
|
-
break;
|
|
1095
|
-
}
|
|
1096
|
-
if (part.text) {
|
|
1097
|
-
events.push({
|
|
1098
|
-
type: "timeline",
|
|
1099
|
-
provider: "opencode",
|
|
1100
|
-
item: { type: "assistant_message", text: part.text },
|
|
1101
|
-
});
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
else if (part.type === "reasoning") {
|
|
1106
|
-
const partKey = resolvePartDedupeKey(part, "reasoning");
|
|
1107
|
-
if (part.time.end) {
|
|
1108
|
-
if (partKey && state.streamedPartKeys.delete(partKey)) {
|
|
1109
|
-
break;
|
|
1110
|
-
}
|
|
1111
|
-
if (part.text) {
|
|
1112
|
-
events.push({
|
|
1113
|
-
type: "timeline",
|
|
1114
|
-
provider: "opencode",
|
|
1115
|
-
item: { type: "reasoning", text: part.text },
|
|
1116
|
-
});
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
else if (part.type === "tool") {
|
|
1121
|
-
const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
|
|
1122
|
-
if (parsedToolPart.success && parsedToolPart.data) {
|
|
1123
|
-
events.push({
|
|
1124
|
-
type: "timeline",
|
|
1125
|
-
provider: "opencode",
|
|
1126
|
-
item: parsedToolPart.data,
|
|
1127
|
-
});
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
else if (part.type === "compaction") {
|
|
1107
|
+
case "message.part.updated":
|
|
1108
|
+
appendOpenCodeMessagePartUpdated(event, state, events);
|
|
1109
|
+
break;
|
|
1110
|
+
case "message.part.delta":
|
|
1111
|
+
appendOpenCodeMessagePartDelta(event, state, events);
|
|
1112
|
+
break;
|
|
1113
|
+
case "permission.asked":
|
|
1114
|
+
appendOpenCodePermissionAsked(event, state, events);
|
|
1115
|
+
break;
|
|
1116
|
+
case "question.asked":
|
|
1117
|
+
appendOpenCodeQuestionAsked(event, state, events);
|
|
1118
|
+
break;
|
|
1119
|
+
case "todo.updated":
|
|
1120
|
+
if (event.properties.sessionID === state.sessionId) {
|
|
1131
1121
|
events.push({
|
|
1132
1122
|
type: "timeline",
|
|
1133
1123
|
provider: "opencode",
|
|
1134
|
-
item:
|
|
1124
|
+
item: mapOpenCodeTodosToTimelineItems(event.properties.todos),
|
|
1135
1125
|
});
|
|
1136
1126
|
}
|
|
1137
|
-
else if (part.type === "step-finish") {
|
|
1138
|
-
mergeOpenCodeStepFinishUsage(state.accumulatedUsage, part);
|
|
1139
|
-
if (hasNormalizedOpenCodeUsage(state.accumulatedUsage)) {
|
|
1140
|
-
events.push({
|
|
1141
|
-
type: "usage_updated",
|
|
1142
|
-
provider: "opencode",
|
|
1143
|
-
usage: { ...state.accumulatedUsage },
|
|
1144
|
-
});
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
1127
|
break;
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
const { sessionID, messageID, partID, field, delta } = event.properties;
|
|
1151
|
-
if (sessionID !== state.sessionId) {
|
|
1152
|
-
break;
|
|
1153
|
-
}
|
|
1154
|
-
if (!delta || !field) {
|
|
1155
|
-
break;
|
|
1156
|
-
}
|
|
1157
|
-
const messageRole = messageID ? state.messageRoles.get(messageID) : undefined;
|
|
1158
|
-
const knownPartType = partID ? state.partTypes.get(partID) : undefined;
|
|
1159
|
-
const isReasoning = knownPartType === "reasoning" || field === "reasoning";
|
|
1160
|
-
if (isReasoning) {
|
|
1161
|
-
if (partID) {
|
|
1162
|
-
state.streamedPartKeys.add(`reasoning:${partID}`);
|
|
1163
|
-
}
|
|
1128
|
+
case "session.compacted":
|
|
1129
|
+
if (event.properties.sessionID === state.sessionId) {
|
|
1164
1130
|
events.push({
|
|
1165
1131
|
type: "timeline",
|
|
1166
1132
|
provider: "opencode",
|
|
1167
|
-
item:
|
|
1133
|
+
item: createCompactionTimelineItem("completed"),
|
|
1168
1134
|
});
|
|
1169
1135
|
}
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1136
|
+
break;
|
|
1137
|
+
case "session.idle":
|
|
1138
|
+
if (event.properties.sessionID === state.sessionId) {
|
|
1139
|
+
resetOpenCodeTurnTrackingState(state);
|
|
1140
|
+
events.push({ type: "turn_completed", provider: "opencode", usage: undefined });
|
|
1141
|
+
}
|
|
1142
|
+
break;
|
|
1143
|
+
case "session.error":
|
|
1144
|
+
if (event.properties.sessionID === state.sessionId) {
|
|
1145
|
+
resetOpenCodeTurnTrackingState(state);
|
|
1177
1146
|
events.push({
|
|
1178
|
-
type: "
|
|
1147
|
+
type: "turn_failed",
|
|
1179
1148
|
provider: "opencode",
|
|
1180
|
-
|
|
1149
|
+
error: toDiagnosticErrorMessage(event.properties.error),
|
|
1181
1150
|
});
|
|
1182
1151
|
}
|
|
1183
1152
|
break;
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
if (event.properties.sessionID !== state.sessionId) {
|
|
1187
|
-
break;
|
|
1188
|
-
}
|
|
1189
|
-
const metadata = readOpenCodeRecord(event.properties.metadata);
|
|
1190
|
-
const tool = readOpenCodeRecord(event.properties.tool);
|
|
1191
|
-
const patterns = Array.isArray(event.properties.patterns)
|
|
1192
|
-
? event.properties.patterns.filter((value) => typeof value === "string")
|
|
1193
|
-
: [];
|
|
1194
|
-
const command = readPermissionField(metadata, PERMISSION_COMMAND_KEYS);
|
|
1195
|
-
const cwd = readPermissionField(metadata, PERMISSION_CWD_KEYS);
|
|
1196
|
-
const reason = readPermissionField(metadata, PERMISSION_REASON_KEYS);
|
|
1197
|
-
const input = buildOpenCodePermissionInput({
|
|
1198
|
-
patterns,
|
|
1199
|
-
metadata,
|
|
1200
|
-
tool,
|
|
1201
|
-
command,
|
|
1202
|
-
});
|
|
1203
|
-
const detail = buildOpenCodePermissionDetail({
|
|
1204
|
-
permission: event.properties.permission,
|
|
1205
|
-
input,
|
|
1206
|
-
command,
|
|
1207
|
-
cwd,
|
|
1208
|
-
});
|
|
1209
|
-
const description = buildOpenCodePermissionDescription({
|
|
1210
|
-
reason,
|
|
1211
|
-
patterns,
|
|
1212
|
-
});
|
|
1213
|
-
events.push({
|
|
1214
|
-
type: "permission_requested",
|
|
1215
|
-
provider: "opencode",
|
|
1216
|
-
request: {
|
|
1217
|
-
id: event.properties.id,
|
|
1218
|
-
provider: "opencode",
|
|
1219
|
-
name: event.properties.permission,
|
|
1220
|
-
kind: "tool",
|
|
1221
|
-
title: toHumanReadablePermissionTitle(event.properties.permission),
|
|
1222
|
-
...(description ? { description } : {}),
|
|
1223
|
-
input,
|
|
1224
|
-
detail,
|
|
1225
|
-
},
|
|
1226
|
-
});
|
|
1153
|
+
case "session.status":
|
|
1154
|
+
appendOpenCodeSessionStatus(event, state, events);
|
|
1227
1155
|
break;
|
|
1156
|
+
}
|
|
1157
|
+
return events;
|
|
1158
|
+
}
|
|
1159
|
+
function resetOpenCodeTurnTrackingState(state) {
|
|
1160
|
+
state.streamedPartKeys.clear();
|
|
1161
|
+
state.partTypes.clear();
|
|
1162
|
+
}
|
|
1163
|
+
function getOpenCodeSubAgentMaps(state) {
|
|
1164
|
+
state.subAgentsByCallId ?? (state.subAgentsByCallId = new Map());
|
|
1165
|
+
state.subAgentCallIdByChildSessionId ?? (state.subAgentCallIdByChildSessionId = new Map());
|
|
1166
|
+
state.pendingChildToolPartsBySessionId ?? (state.pendingChildToolPartsBySessionId = new Map());
|
|
1167
|
+
return {
|
|
1168
|
+
byCallId: state.subAgentsByCallId,
|
|
1169
|
+
callIdByChildSessionId: state.subAgentCallIdByChildSessionId,
|
|
1170
|
+
pendingChildToolPartsBySessionId: state.pendingChildToolPartsBySessionId,
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
function getOpenCodeSubAgentState(callId, state, toolCall) {
|
|
1174
|
+
const maps = getOpenCodeSubAgentMaps(state);
|
|
1175
|
+
const existing = maps.byCallId.get(callId);
|
|
1176
|
+
if (existing) {
|
|
1177
|
+
existing.toolCall = toolCall;
|
|
1178
|
+
return existing;
|
|
1179
|
+
}
|
|
1180
|
+
const created = {
|
|
1181
|
+
toolCall,
|
|
1182
|
+
actions: [],
|
|
1183
|
+
actionIndexByKey: new Map(),
|
|
1184
|
+
nextActionIndex: 1,
|
|
1185
|
+
};
|
|
1186
|
+
maps.byCallId.set(callId, created);
|
|
1187
|
+
return created;
|
|
1188
|
+
}
|
|
1189
|
+
function linkOpenCodeSubAgentChildSession(activity, childSessionId, state) {
|
|
1190
|
+
activity.childSessionId = childSessionId;
|
|
1191
|
+
const maps = getOpenCodeSubAgentMaps(state);
|
|
1192
|
+
maps.callIdByChildSessionId.set(childSessionId, activity.toolCall.callId);
|
|
1193
|
+
}
|
|
1194
|
+
function buildOpenCodeSubAgentLog(detail, activity) {
|
|
1195
|
+
const actionLog = activity.actions
|
|
1196
|
+
.map((action) => action.summary ? `[${action.toolName}] ${action.summary}` : `[${action.toolName}]`)
|
|
1197
|
+
.join("\n");
|
|
1198
|
+
const parts = [actionLog, detail.log].filter((part) => part.trim().length > 0);
|
|
1199
|
+
return parts.join("\n\n");
|
|
1200
|
+
}
|
|
1201
|
+
function buildOpenCodeSubAgentTimelineItem(activity) {
|
|
1202
|
+
const toolCall = activity.toolCall;
|
|
1203
|
+
if (toolCall.detail.type !== "sub_agent") {
|
|
1204
|
+
return toolCall;
|
|
1205
|
+
}
|
|
1206
|
+
const childSessionId = activity.childSessionId ?? toolCall.detail.childSessionId;
|
|
1207
|
+
return {
|
|
1208
|
+
...toolCall,
|
|
1209
|
+
detail: {
|
|
1210
|
+
...toolCall.detail,
|
|
1211
|
+
...(childSessionId ? { childSessionId } : {}),
|
|
1212
|
+
log: buildOpenCodeSubAgentLog(toolCall.detail, activity),
|
|
1213
|
+
},
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
function registerOpenCodeSubAgentToolCall(item, state) {
|
|
1217
|
+
if (item.detail.type !== "sub_agent") {
|
|
1218
|
+
return item;
|
|
1219
|
+
}
|
|
1220
|
+
const activity = getOpenCodeSubAgentState(item.callId, state, item);
|
|
1221
|
+
if (item.detail.childSessionId) {
|
|
1222
|
+
linkOpenCodeSubAgentChildSession(activity, item.detail.childSessionId, state);
|
|
1223
|
+
}
|
|
1224
|
+
return buildOpenCodeSubAgentTimelineItem(activity);
|
|
1225
|
+
}
|
|
1226
|
+
function bufferOpenCodeSubAgentChildToolPart(part, state) {
|
|
1227
|
+
const maps = getOpenCodeSubAgentMaps(state);
|
|
1228
|
+
if (maps.byCallId.size === 0) {
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
const totalPending = [...maps.pendingChildToolPartsBySessionId.values()].reduce((total, parts) => total + parts.length, 0);
|
|
1232
|
+
if (totalPending >= MAX_OPENCODE_PENDING_CHILD_TOOL_PARTS) {
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
const pending = maps.pendingChildToolPartsBySessionId.get(part.sessionID) ?? [];
|
|
1236
|
+
pending.push(part);
|
|
1237
|
+
maps.pendingChildToolPartsBySessionId.set(part.sessionID, pending);
|
|
1238
|
+
}
|
|
1239
|
+
function flushOpenCodeSubAgentChildToolParts(childSessionId, state, events) {
|
|
1240
|
+
const maps = getOpenCodeSubAgentMaps(state);
|
|
1241
|
+
const pending = maps.pendingChildToolPartsBySessionId.get(childSessionId);
|
|
1242
|
+
if (!pending || pending.length === 0) {
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
maps.pendingChildToolPartsBySessionId.delete(childSessionId);
|
|
1246
|
+
for (const part of pending) {
|
|
1247
|
+
appendOpenCodeSubAgentChildToolPart(part, state, events);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
function findOnlyOpenCodeSubAgentWaitingForChild(state) {
|
|
1251
|
+
const maps = getOpenCodeSubAgentMaps(state);
|
|
1252
|
+
const candidates = [...maps.byCallId.values()].filter((activity) => activity.toolCall.status === "running" &&
|
|
1253
|
+
activity.toolCall.detail.type === "sub_agent" &&
|
|
1254
|
+
!activity.childSessionId);
|
|
1255
|
+
return candidates.length === 1 ? (candidates[0] ?? null) : null;
|
|
1256
|
+
}
|
|
1257
|
+
function summarizeOpenCodeSubAgentAction(item, cwd) {
|
|
1258
|
+
const display = buildToolCallDisplayModel({
|
|
1259
|
+
name: item.name,
|
|
1260
|
+
status: item.status,
|
|
1261
|
+
error: item.error,
|
|
1262
|
+
metadata: item.metadata,
|
|
1263
|
+
detail: item.detail,
|
|
1264
|
+
cwd,
|
|
1265
|
+
});
|
|
1266
|
+
return display.summary ?? display.errorText;
|
|
1267
|
+
}
|
|
1268
|
+
function appendOpenCodeSubAgentAction(activity, item, cwd) {
|
|
1269
|
+
const key = item.callId || `${item.name}:${activity.actions.length}`;
|
|
1270
|
+
const existingIndex = activity.actionIndexByKey.get(key);
|
|
1271
|
+
const summary = summarizeOpenCodeSubAgentAction(item, cwd);
|
|
1272
|
+
if (existingIndex !== undefined) {
|
|
1273
|
+
const action = activity.actions[existingIndex];
|
|
1274
|
+
if (!action) {
|
|
1275
|
+
return false;
|
|
1276
|
+
}
|
|
1277
|
+
const changed = action.toolName !== item.name || action.summary !== summary;
|
|
1278
|
+
action.toolName = item.name;
|
|
1279
|
+
if (summary) {
|
|
1280
|
+
action.summary = summary;
|
|
1228
1281
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
break;
|
|
1232
|
-
}
|
|
1233
|
-
const questions = event.properties.questions.flatMap((q) => {
|
|
1234
|
-
if (!q.question || !q.header) {
|
|
1235
|
-
return [];
|
|
1236
|
-
}
|
|
1237
|
-
const options = q.options?.map((o) => ({
|
|
1238
|
-
label: o.label,
|
|
1239
|
-
...(o.description ? { description: o.description } : {}),
|
|
1240
|
-
})) ?? [];
|
|
1241
|
-
return [
|
|
1242
|
-
{
|
|
1243
|
-
question: q.question,
|
|
1244
|
-
header: q.header,
|
|
1245
|
-
options,
|
|
1246
|
-
...(q.multiple === true ? { multiSelect: true } : {}),
|
|
1247
|
-
},
|
|
1248
|
-
];
|
|
1249
|
-
});
|
|
1250
|
-
if (questions.length === 0) {
|
|
1251
|
-
break;
|
|
1252
|
-
}
|
|
1253
|
-
events.push({
|
|
1254
|
-
type: "permission_requested",
|
|
1255
|
-
provider: "opencode",
|
|
1256
|
-
request: {
|
|
1257
|
-
id: event.properties.id,
|
|
1258
|
-
provider: "opencode",
|
|
1259
|
-
name: "question",
|
|
1260
|
-
kind: "question",
|
|
1261
|
-
title: "Question",
|
|
1262
|
-
input: { questions },
|
|
1263
|
-
metadata: {
|
|
1264
|
-
source: "opencode_question",
|
|
1265
|
-
...(event.properties.tool ?? {}),
|
|
1266
|
-
},
|
|
1267
|
-
},
|
|
1268
|
-
});
|
|
1269
|
-
break;
|
|
1282
|
+
else {
|
|
1283
|
+
delete action.summary;
|
|
1270
1284
|
}
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1285
|
+
return changed;
|
|
1286
|
+
}
|
|
1287
|
+
if (activity.actions.length >= MAX_OPENCODE_SUB_AGENT_ACTIONS) {
|
|
1288
|
+
return false;
|
|
1289
|
+
}
|
|
1290
|
+
activity.actionIndexByKey.set(key, activity.actions.length);
|
|
1291
|
+
activity.actions.push({
|
|
1292
|
+
index: activity.nextActionIndex,
|
|
1293
|
+
key,
|
|
1294
|
+
toolName: item.name,
|
|
1295
|
+
...(summary ? { summary } : {}),
|
|
1296
|
+
});
|
|
1297
|
+
activity.nextActionIndex += 1;
|
|
1298
|
+
return true;
|
|
1299
|
+
}
|
|
1300
|
+
function appendOpenCodeToolCallTimelineItem(item, state, events) {
|
|
1301
|
+
const timelineItem = registerOpenCodeSubAgentToolCall(item, state);
|
|
1302
|
+
events.push({
|
|
1303
|
+
type: "timeline",
|
|
1304
|
+
provider: "opencode",
|
|
1305
|
+
item: timelineItem,
|
|
1306
|
+
});
|
|
1307
|
+
if (timelineItem.detail.type === "sub_agent" && timelineItem.detail.childSessionId) {
|
|
1308
|
+
flushOpenCodeSubAgentChildToolParts(timelineItem.detail.childSessionId, state, events);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
function appendOpenCodeSubAgentChildSessionLinked(childSessionId, state, events) {
|
|
1312
|
+
const activity = findOnlyOpenCodeSubAgentWaitingForChild(state);
|
|
1313
|
+
if (!activity) {
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
linkOpenCodeSubAgentChildSession(activity, childSessionId, state);
|
|
1317
|
+
events.push({
|
|
1318
|
+
type: "timeline",
|
|
1319
|
+
provider: "opencode",
|
|
1320
|
+
item: buildOpenCodeSubAgentTimelineItem(activity),
|
|
1321
|
+
});
|
|
1322
|
+
flushOpenCodeSubAgentChildToolParts(childSessionId, state, events);
|
|
1323
|
+
}
|
|
1324
|
+
function appendOpenCodeSubAgentChildToolPart(part, state, events) {
|
|
1325
|
+
const maps = getOpenCodeSubAgentMaps(state);
|
|
1326
|
+
const parentCallId = maps.callIdByChildSessionId.get(part.sessionID);
|
|
1327
|
+
if (!parentCallId) {
|
|
1328
|
+
bufferOpenCodeSubAgentChildToolPart(part, state);
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
const activity = maps.byCallId.get(parentCallId);
|
|
1332
|
+
if (!activity) {
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
|
|
1336
|
+
if (!parsedToolPart.success || !parsedToolPart.data) {
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
if (!appendOpenCodeSubAgentAction(activity, parsedToolPart.data, state.cwd)) {
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
events.push({
|
|
1343
|
+
type: "timeline",
|
|
1344
|
+
provider: "opencode",
|
|
1345
|
+
item: buildOpenCodeSubAgentTimelineItem(activity),
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
function appendOpenCodeSessionCreatedOrUpdated(event, state, events) {
|
|
1349
|
+
if (event.properties.info.id === state.sessionId) {
|
|
1350
|
+
events.push({
|
|
1351
|
+
type: "thread_started",
|
|
1352
|
+
sessionId: state.sessionId,
|
|
1353
|
+
provider: "opencode",
|
|
1354
|
+
});
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
const info = readOpenCodeRecord(event.properties.info);
|
|
1358
|
+
const parentSessionId = readNonEmptyString(info?.parentID) ?? readNonEmptyString(info?.parentId);
|
|
1359
|
+
if (parentSessionId === state.sessionId) {
|
|
1360
|
+
appendOpenCodeSubAgentChildSessionLinked(event.properties.info.id, state, events);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
function appendOpenCodeMessageUpdated(event, state, events) {
|
|
1364
|
+
const info = event.properties.info;
|
|
1365
|
+
if (info.sessionID !== state.sessionId) {
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
state.messageRoles.set(info.id, info.role);
|
|
1369
|
+
if (info.role !== "assistant") {
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
const modelLookupKey = resolveOpenCodeModelLookupKeyFromAssistantMessage(info);
|
|
1373
|
+
if (modelLookupKey) {
|
|
1374
|
+
const contextWindowMaxTokens = state.modelContextWindowsByModelKey?.get(modelLookupKey);
|
|
1375
|
+
if (contextWindowMaxTokens !== undefined) {
|
|
1376
|
+
state.onAssistantModelContextWindowResolved?.(contextWindowMaxTokens);
|
|
1281
1377
|
}
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1378
|
+
}
|
|
1379
|
+
if (state.emittedStructuredMessageIds.has(info.id) || info.time?.completed === undefined) {
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1382
|
+
const text = stringifyStructuredAssistantMessage(info.structured);
|
|
1383
|
+
if (!text) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
state.emittedStructuredMessageIds.add(info.id);
|
|
1387
|
+
events.push({
|
|
1388
|
+
type: "timeline",
|
|
1389
|
+
provider: "opencode",
|
|
1390
|
+
item: { type: "assistant_message", text },
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
function appendOpenCodeMessagePartUpdated(event, state, events) {
|
|
1394
|
+
const part = event.properties.part;
|
|
1395
|
+
if (part.sessionID !== state.sessionId) {
|
|
1396
|
+
if (part.type === "tool") {
|
|
1397
|
+
appendOpenCodeSubAgentChildToolPart(part, state, events);
|
|
1398
|
+
}
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
1401
|
+
const messageRole = state.messageRoles.get(part.messageID);
|
|
1402
|
+
state.partTypes.set(part.id, part.type);
|
|
1403
|
+
if (part.type === "text") {
|
|
1404
|
+
appendOpenCodeTextPart(part, messageRole, state, events);
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
if (part.type === "reasoning") {
|
|
1408
|
+
appendOpenCodeReasoningPart(part, state, events);
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
if (part.type === "tool") {
|
|
1412
|
+
const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
|
|
1413
|
+
if (parsedToolPart.success && parsedToolPart.data) {
|
|
1414
|
+
appendOpenCodeToolCallTimelineItem(parsedToolPart.data, state, events);
|
|
1415
|
+
}
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
if (part.type === "compaction") {
|
|
1419
|
+
events.push({
|
|
1420
|
+
type: "timeline",
|
|
1421
|
+
provider: "opencode",
|
|
1422
|
+
item: createCompactionTimelineItem("loading", part.auto ? "auto" : "manual"),
|
|
1423
|
+
});
|
|
1424
|
+
return;
|
|
1425
|
+
}
|
|
1426
|
+
if (part.type === "step-finish") {
|
|
1427
|
+
mergeOpenCodeStepFinishUsage(state.accumulatedUsage, part);
|
|
1428
|
+
if (hasNormalizedOpenCodeUsage(state.accumulatedUsage)) {
|
|
1286
1429
|
events.push({
|
|
1287
|
-
type: "
|
|
1430
|
+
type: "usage_updated",
|
|
1288
1431
|
provider: "opencode",
|
|
1289
|
-
|
|
1432
|
+
usage: { ...state.accumulatedUsage },
|
|
1290
1433
|
});
|
|
1291
|
-
break;
|
|
1292
|
-
}
|
|
1293
|
-
case "session.idle": {
|
|
1294
|
-
if (event.properties.sessionID === state.sessionId) {
|
|
1295
|
-
state.streamedPartKeys.clear();
|
|
1296
|
-
state.partTypes.clear();
|
|
1297
|
-
events.push({
|
|
1298
|
-
type: "turn_completed",
|
|
1299
|
-
provider: "opencode",
|
|
1300
|
-
usage: undefined,
|
|
1301
|
-
});
|
|
1302
|
-
}
|
|
1303
|
-
break;
|
|
1304
|
-
}
|
|
1305
|
-
case "session.error": {
|
|
1306
|
-
if (event.properties.sessionID === state.sessionId) {
|
|
1307
|
-
state.streamedPartKeys.clear();
|
|
1308
|
-
state.partTypes.clear();
|
|
1309
|
-
events.push({
|
|
1310
|
-
type: "turn_failed",
|
|
1311
|
-
provider: "opencode",
|
|
1312
|
-
error: normalizeTurnFailureError(event.properties.error),
|
|
1313
|
-
});
|
|
1314
|
-
}
|
|
1315
|
-
break;
|
|
1316
1434
|
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
function appendOpenCodeTextPart(part, messageRole, state, events) {
|
|
1438
|
+
if (messageRole === "user") {
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
if (!part.time?.end) {
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
const partKey = resolvePartDedupeKey(part, "text");
|
|
1445
|
+
if (partKey && state.streamedPartKeys.delete(partKey)) {
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1448
|
+
if (part.text) {
|
|
1449
|
+
events.push({
|
|
1450
|
+
type: "timeline",
|
|
1451
|
+
provider: "opencode",
|
|
1452
|
+
item: { type: "assistant_message", text: part.text },
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
function appendOpenCodeReasoningPart(part, state, events) {
|
|
1457
|
+
if (!part.time.end) {
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
const partKey = resolvePartDedupeKey(part, "reasoning");
|
|
1461
|
+
if (partKey && state.streamedPartKeys.delete(partKey)) {
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
if (part.text) {
|
|
1465
|
+
events.push({
|
|
1466
|
+
type: "timeline",
|
|
1467
|
+
provider: "opencode",
|
|
1468
|
+
item: { type: "reasoning", text: part.text },
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
function appendOpenCodeMessagePartDelta(event, state, events) {
|
|
1473
|
+
const { sessionID, messageID, partID, field, delta } = event.properties;
|
|
1474
|
+
if (sessionID !== state.sessionId) {
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
if (!delta || !field) {
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
const messageRole = messageID ? state.messageRoles.get(messageID) : undefined;
|
|
1481
|
+
const knownPartType = partID ? state.partTypes.get(partID) : undefined;
|
|
1482
|
+
const isReasoning = knownPartType === "reasoning" || field === "reasoning";
|
|
1483
|
+
if (isReasoning) {
|
|
1484
|
+
if (partID) {
|
|
1485
|
+
state.streamedPartKeys.add(`reasoning:${partID}`);
|
|
1486
|
+
}
|
|
1487
|
+
events.push({
|
|
1488
|
+
type: "timeline",
|
|
1489
|
+
provider: "opencode",
|
|
1490
|
+
item: { type: "reasoning", text: delta },
|
|
1491
|
+
});
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
if (field !== "text") {
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
if (messageRole === "user") {
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
if (partID) {
|
|
1501
|
+
state.streamedPartKeys.add(`text:${partID}`);
|
|
1502
|
+
}
|
|
1503
|
+
events.push({
|
|
1504
|
+
type: "timeline",
|
|
1505
|
+
provider: "opencode",
|
|
1506
|
+
item: { type: "assistant_message", text: delta },
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
function appendOpenCodePermissionAsked(event, state, events) {
|
|
1510
|
+
if (event.properties.sessionID !== state.sessionId) {
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
const metadata = readOpenCodeRecord(event.properties.metadata);
|
|
1514
|
+
const tool = readOpenCodeRecord(event.properties.tool);
|
|
1515
|
+
const patterns = Array.isArray(event.properties.patterns)
|
|
1516
|
+
? event.properties.patterns.filter((value) => typeof value === "string")
|
|
1517
|
+
: [];
|
|
1518
|
+
const command = readPermissionField(metadata, PERMISSION_COMMAND_KEYS);
|
|
1519
|
+
const cwd = readPermissionField(metadata, PERMISSION_CWD_KEYS);
|
|
1520
|
+
const reason = readPermissionField(metadata, PERMISSION_REASON_KEYS);
|
|
1521
|
+
const input = buildOpenCodePermissionInput({ patterns, metadata, tool, command });
|
|
1522
|
+
const detail = buildOpenCodePermissionDetail({
|
|
1523
|
+
permission: event.properties.permission,
|
|
1524
|
+
input,
|
|
1525
|
+
command,
|
|
1526
|
+
cwd,
|
|
1527
|
+
});
|
|
1528
|
+
const description = buildOpenCodePermissionDescription({ reason, patterns });
|
|
1529
|
+
events.push({
|
|
1530
|
+
type: "permission_requested",
|
|
1531
|
+
provider: "opencode",
|
|
1532
|
+
request: {
|
|
1533
|
+
id: event.properties.id,
|
|
1534
|
+
provider: "opencode",
|
|
1535
|
+
name: event.properties.permission,
|
|
1536
|
+
kind: "tool",
|
|
1537
|
+
title: toHumanReadablePermissionTitle(event.properties.permission),
|
|
1538
|
+
...(description ? { description } : {}),
|
|
1539
|
+
input,
|
|
1540
|
+
detail,
|
|
1541
|
+
},
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1544
|
+
function appendOpenCodeQuestionAsked(event, state, events) {
|
|
1545
|
+
if (event.properties.sessionID !== state.sessionId) {
|
|
1546
|
+
return;
|
|
1547
|
+
}
|
|
1548
|
+
const questions = event.properties.questions.flatMap((q) => {
|
|
1549
|
+
if (!q.question || !q.header) {
|
|
1550
|
+
return [];
|
|
1342
1551
|
}
|
|
1552
|
+
const options = q.options?.map((o) => ({
|
|
1553
|
+
label: o.label,
|
|
1554
|
+
...(o.description ? { description: o.description } : {}),
|
|
1555
|
+
})) ?? [];
|
|
1556
|
+
return [
|
|
1557
|
+
{
|
|
1558
|
+
question: q.question,
|
|
1559
|
+
header: q.header,
|
|
1560
|
+
options,
|
|
1561
|
+
...(q.multiple === true ? { multiSelect: true } : {}),
|
|
1562
|
+
},
|
|
1563
|
+
];
|
|
1564
|
+
});
|
|
1565
|
+
if (questions.length === 0) {
|
|
1566
|
+
return;
|
|
1343
1567
|
}
|
|
1344
|
-
|
|
1568
|
+
events.push({
|
|
1569
|
+
type: "permission_requested",
|
|
1570
|
+
provider: "opencode",
|
|
1571
|
+
request: {
|
|
1572
|
+
id: event.properties.id,
|
|
1573
|
+
provider: "opencode",
|
|
1574
|
+
name: "question",
|
|
1575
|
+
kind: "question",
|
|
1576
|
+
title: "Question",
|
|
1577
|
+
input: { questions },
|
|
1578
|
+
metadata: {
|
|
1579
|
+
source: "opencode_question",
|
|
1580
|
+
...event.properties.tool,
|
|
1581
|
+
},
|
|
1582
|
+
},
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
function appendOpenCodeSessionStatus(event, state, events) {
|
|
1586
|
+
if (event.properties.sessionID !== state.sessionId) {
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
const { status } = event.properties;
|
|
1590
|
+
if (status.type === "idle") {
|
|
1591
|
+
resetOpenCodeTurnTrackingState(state);
|
|
1592
|
+
events.push({ type: "turn_completed", provider: "opencode", usage: undefined });
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
if (status.type === "retry" && isFatalOpenCodeRetryMessage(status.message)) {
|
|
1596
|
+
resetOpenCodeTurnTrackingState(state);
|
|
1597
|
+
events.push({
|
|
1598
|
+
type: "turn_failed",
|
|
1599
|
+
provider: "opencode",
|
|
1600
|
+
error: toDiagnosticErrorMessage(status.message),
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
// "retry" and "busy" are transient — no terminal event.
|
|
1604
|
+
}
|
|
1605
|
+
function createDeferred() {
|
|
1606
|
+
let resolve;
|
|
1607
|
+
let reject;
|
|
1608
|
+
const promise = new Promise((res, rej) => {
|
|
1609
|
+
resolve = res;
|
|
1610
|
+
reject = rej;
|
|
1611
|
+
});
|
|
1612
|
+
return { promise, resolve, reject };
|
|
1345
1613
|
}
|
|
1346
1614
|
class OpenCodeAgentSession {
|
|
1347
1615
|
constructor(config, client, sessionId, logger, modelContextWindowsByModelKey = new Map(), releaseServer) {
|
|
@@ -1366,6 +1634,9 @@ class OpenCodeAgentSession {
|
|
|
1366
1634
|
this.nextTurnOrdinal = 0;
|
|
1367
1635
|
this.activeForegroundTurnId = null;
|
|
1368
1636
|
this.runningToolCalls = new Map();
|
|
1637
|
+
this.subAgentsByCallId = new Map();
|
|
1638
|
+
this.subAgentCallIdByChildSessionId = new Map();
|
|
1639
|
+
this.pendingChildToolPartsBySessionId = new Map();
|
|
1369
1640
|
this.config = config;
|
|
1370
1641
|
this.client = client;
|
|
1371
1642
|
this.sessionId = sessionId;
|
|
@@ -1398,75 +1669,13 @@ class OpenCodeAgentSession {
|
|
|
1398
1669
|
this.config.thinkingOptionId = normalizedThinkingOptionId ?? undefined;
|
|
1399
1670
|
}
|
|
1400
1671
|
async run(prompt, options) {
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
let resolveCompletion;
|
|
1408
|
-
let rejectCompletion;
|
|
1409
|
-
const processEvent = (event) => {
|
|
1410
|
-
if (settled) {
|
|
1411
|
-
return;
|
|
1412
|
-
}
|
|
1413
|
-
const eventTurnId = event.turnId;
|
|
1414
|
-
if (turnId && eventTurnId && eventTurnId !== turnId) {
|
|
1415
|
-
return;
|
|
1416
|
-
}
|
|
1417
|
-
if (event.type === "timeline") {
|
|
1418
|
-
timeline.push(event.item);
|
|
1419
|
-
if (event.item.type === "assistant_message") {
|
|
1420
|
-
finalText = event.item.text;
|
|
1421
|
-
}
|
|
1422
|
-
return;
|
|
1423
|
-
}
|
|
1424
|
-
if (event.type === "turn_completed") {
|
|
1425
|
-
usage = event.usage;
|
|
1426
|
-
settled = true;
|
|
1427
|
-
resolveCompletion();
|
|
1428
|
-
return;
|
|
1429
|
-
}
|
|
1430
|
-
if (event.type === "turn_failed") {
|
|
1431
|
-
settled = true;
|
|
1432
|
-
rejectCompletion(new Error(event.error));
|
|
1433
|
-
return;
|
|
1434
|
-
}
|
|
1435
|
-
if (event.type === "turn_canceled") {
|
|
1436
|
-
settled = true;
|
|
1437
|
-
resolveCompletion();
|
|
1438
|
-
}
|
|
1439
|
-
};
|
|
1440
|
-
const completion = new Promise((resolve, reject) => {
|
|
1441
|
-
resolveCompletion = resolve;
|
|
1442
|
-
rejectCompletion = reject;
|
|
1443
|
-
});
|
|
1444
|
-
const unsubscribe = this.subscribe((event) => {
|
|
1445
|
-
if (!turnId) {
|
|
1446
|
-
bufferedEvents.push(event);
|
|
1447
|
-
return;
|
|
1448
|
-
}
|
|
1449
|
-
processEvent(event);
|
|
1672
|
+
return runProviderTurn({
|
|
1673
|
+
prompt,
|
|
1674
|
+
runOptions: options,
|
|
1675
|
+
startTurn: (p, o) => this.startTurn(p, o),
|
|
1676
|
+
subscribe: (callback) => this.subscribe(callback),
|
|
1677
|
+
getSessionId: () => this.sessionId,
|
|
1450
1678
|
});
|
|
1451
|
-
try {
|
|
1452
|
-
const result = await this.startTurn(prompt, options);
|
|
1453
|
-
turnId = result.turnId;
|
|
1454
|
-
for (const event of bufferedEvents) {
|
|
1455
|
-
processEvent(event);
|
|
1456
|
-
}
|
|
1457
|
-
if (!settled) {
|
|
1458
|
-
await completion;
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
|
-
finally {
|
|
1462
|
-
unsubscribe();
|
|
1463
|
-
}
|
|
1464
|
-
return {
|
|
1465
|
-
sessionId: this.sessionId,
|
|
1466
|
-
finalText,
|
|
1467
|
-
usage,
|
|
1468
|
-
timeline,
|
|
1469
|
-
};
|
|
1470
1679
|
}
|
|
1471
1680
|
async interrupt() {
|
|
1472
1681
|
const turnId = this.activeForegroundTurnId;
|
|
@@ -1485,6 +1694,9 @@ class OpenCodeAgentSession {
|
|
|
1485
1694
|
throw new Error("A foreground turn is already active");
|
|
1486
1695
|
}
|
|
1487
1696
|
this.runningToolCalls.clear();
|
|
1697
|
+
this.subAgentsByCallId.clear();
|
|
1698
|
+
this.subAgentCallIdByChildSessionId.clear();
|
|
1699
|
+
this.pendingChildToolPartsBySessionId.clear();
|
|
1488
1700
|
const turnAbortController = new AbortController();
|
|
1489
1701
|
this.abortController = turnAbortController;
|
|
1490
1702
|
await this.ensureMcpServersConfigured();
|
|
@@ -1494,12 +1706,54 @@ class OpenCodeAgentSession {
|
|
|
1494
1706
|
const model = this.parseModel(this.config.model);
|
|
1495
1707
|
const thinkingOptionId = this.config.thinkingOptionId;
|
|
1496
1708
|
const effectiveVariant = thinkingOptionId ?? undefined;
|
|
1497
|
-
const effectiveMode =
|
|
1709
|
+
const effectiveMode = resolveOpenCodeRuntimeAgentId(this.currentMode);
|
|
1498
1710
|
const turnId = this.createTurnId();
|
|
1499
1711
|
this.activeForegroundTurnId = turnId;
|
|
1500
|
-
|
|
1712
|
+
// OpenCode's /event SSE endpoint does NOT replay past events. If we send
|
|
1713
|
+
// the prompt before our reader is connected, terminal events fired early
|
|
1714
|
+
// by the server (e.g. session.error / session.idle for invalid model or
|
|
1715
|
+
// mode) are missed and the turn hangs forever. Wait for the subscription
|
|
1716
|
+
// to be established before sending anything.
|
|
1717
|
+
const subscriptionReady = createDeferred();
|
|
1718
|
+
void this.consumeEventStream(turnId, turnAbortController, subscriptionReady);
|
|
1719
|
+
try {
|
|
1720
|
+
await subscriptionReady.promise;
|
|
1721
|
+
}
|
|
1722
|
+
catch {
|
|
1723
|
+
// consumeEventStream already finished the turn with the subscription error.
|
|
1724
|
+
return { turnId };
|
|
1725
|
+
}
|
|
1501
1726
|
const slashCommand = await this.resolveSlashCommandInvocation(prompt);
|
|
1502
1727
|
if (slashCommand) {
|
|
1728
|
+
if (slashCommand.commandName === "compact" || slashCommand.commandName === "summarize") {
|
|
1729
|
+
void this.client.session
|
|
1730
|
+
.summarize({
|
|
1731
|
+
sessionID: this.sessionId,
|
|
1732
|
+
directory: this.config.cwd,
|
|
1733
|
+
...(model ? { providerID: model.providerID, modelID: model.modelID } : {}),
|
|
1734
|
+
})
|
|
1735
|
+
.then((response) => {
|
|
1736
|
+
if (response.error) {
|
|
1737
|
+
this.finishForegroundTurn({
|
|
1738
|
+
type: "turn_failed",
|
|
1739
|
+
provider: "opencode",
|
|
1740
|
+
error: toDiagnosticErrorMessage(response.error),
|
|
1741
|
+
}, turnId);
|
|
1742
|
+
}
|
|
1743
|
+
else {
|
|
1744
|
+
this.finishForegroundTurn({ type: "turn_completed", provider: "opencode", usage: undefined }, turnId);
|
|
1745
|
+
}
|
|
1746
|
+
return;
|
|
1747
|
+
})
|
|
1748
|
+
.catch((error) => {
|
|
1749
|
+
this.finishForegroundTurn({
|
|
1750
|
+
type: "turn_failed",
|
|
1751
|
+
provider: "opencode",
|
|
1752
|
+
error: toDiagnosticErrorMessage(error),
|
|
1753
|
+
}, turnId);
|
|
1754
|
+
});
|
|
1755
|
+
return { turnId };
|
|
1756
|
+
}
|
|
1503
1757
|
// command() blocks until the server finishes processing. OpenCode's SSE
|
|
1504
1758
|
// endpoint does NOT replay past events, so if the command completes before
|
|
1505
1759
|
// our SSE reader connects, we miss `session.idle` and the turn hangs.
|
|
@@ -1526,12 +1780,13 @@ class OpenCodeAgentSession {
|
|
|
1526
1780
|
}, "OpenCode slash command hit a header timeout; waiting for SSE terminal event");
|
|
1527
1781
|
return;
|
|
1528
1782
|
}
|
|
1529
|
-
const errorMsg =
|
|
1783
|
+
const errorMsg = toDiagnosticErrorMessage(response.error);
|
|
1530
1784
|
this.finishForegroundTurn({ type: "turn_failed", provider: "opencode", error: errorMsg }, turnId);
|
|
1531
1785
|
}
|
|
1532
1786
|
else {
|
|
1533
1787
|
this.finishForegroundTurn({ type: "turn_completed", provider: "opencode", usage: undefined }, turnId);
|
|
1534
1788
|
}
|
|
1789
|
+
return;
|
|
1535
1790
|
})
|
|
1536
1791
|
.catch((err) => {
|
|
1537
1792
|
if (isOpenCodeHeadersTimeoutFailure(err)) {
|
|
@@ -1542,44 +1797,48 @@ class OpenCodeAgentSession {
|
|
|
1542
1797
|
}, "OpenCode slash command hit a header timeout; waiting for SSE terminal event");
|
|
1543
1798
|
return;
|
|
1544
1799
|
}
|
|
1545
|
-
this.finishForegroundTurn({ type: "turn_failed", provider: "opencode", error:
|
|
1800
|
+
this.finishForegroundTurn({ type: "turn_failed", provider: "opencode", error: toDiagnosticErrorMessage(err) }, turnId);
|
|
1546
1801
|
});
|
|
1547
1802
|
}
|
|
1548
1803
|
else {
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1804
|
+
// Wrap in an async IIFE so a synchronous throw from promptAsync (e.g.
|
|
1805
|
+
// SDK input validation) is caught alongside async rejections. A plain
|
|
1806
|
+
// `.then().catch()` chain would let a sync throw escape unhandled.
|
|
1807
|
+
void (async () => {
|
|
1808
|
+
try {
|
|
1809
|
+
const promptResponse = await this.client.session.promptAsync({
|
|
1810
|
+
sessionID: this.sessionId,
|
|
1811
|
+
directory: this.config.cwd,
|
|
1812
|
+
parts,
|
|
1813
|
+
...(options?.outputSchema
|
|
1814
|
+
? {
|
|
1815
|
+
format: {
|
|
1816
|
+
type: "json_schema",
|
|
1817
|
+
schema: options.outputSchema,
|
|
1818
|
+
},
|
|
1819
|
+
}
|
|
1820
|
+
: {}),
|
|
1821
|
+
...(this.config.systemPrompt ? { system: this.config.systemPrompt } : {}),
|
|
1822
|
+
...(model ? { model } : {}),
|
|
1823
|
+
...(effectiveMode ? { agent: effectiveMode } : {}),
|
|
1824
|
+
...(effectiveVariant ? { variant: effectiveVariant } : {}),
|
|
1825
|
+
});
|
|
1826
|
+
if (promptResponse.error) {
|
|
1827
|
+
this.finishForegroundTurn({
|
|
1828
|
+
type: "turn_failed",
|
|
1829
|
+
provider: "opencode",
|
|
1830
|
+
error: toDiagnosticErrorMessage(promptResponse.error),
|
|
1831
|
+
}, turnId);
|
|
1560
1832
|
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
...(model ? { model } : {}),
|
|
1564
|
-
...(effectiveMode ? { agent: effectiveMode } : {}),
|
|
1565
|
-
...(effectiveVariant ? { variant: effectiveVariant } : {}),
|
|
1566
|
-
})
|
|
1567
|
-
.then((promptResponse) => {
|
|
1568
|
-
if (promptResponse.error) {
|
|
1833
|
+
}
|
|
1834
|
+
catch (error) {
|
|
1569
1835
|
this.finishForegroundTurn({
|
|
1570
1836
|
type: "turn_failed",
|
|
1571
1837
|
provider: "opencode",
|
|
1572
|
-
error:
|
|
1838
|
+
error: toDiagnosticErrorMessage(error),
|
|
1573
1839
|
}, turnId);
|
|
1574
1840
|
}
|
|
1575
|
-
})
|
|
1576
|
-
.catch((error) => {
|
|
1577
|
-
this.finishForegroundTurn({
|
|
1578
|
-
type: "turn_failed",
|
|
1579
|
-
provider: "opencode",
|
|
1580
|
-
error: normalizeTurnFailureError(error),
|
|
1581
|
-
}, turnId);
|
|
1582
|
-
});
|
|
1841
|
+
})();
|
|
1583
1842
|
}
|
|
1584
1843
|
return { turnId };
|
|
1585
1844
|
}
|
|
@@ -1589,14 +1848,15 @@ class OpenCodeAgentSession {
|
|
|
1589
1848
|
this.subscribers.delete(callback);
|
|
1590
1849
|
};
|
|
1591
1850
|
}
|
|
1592
|
-
async consumeEventStream(turnId, turnAbortController) {
|
|
1851
|
+
async consumeEventStream(turnId, turnAbortController, subscriptionReady) {
|
|
1593
1852
|
try {
|
|
1594
1853
|
const result = await this.client.event.subscribe({ directory: this.config.cwd }, { signal: turnAbortController.signal, sseMaxRetryAttempts: 0 });
|
|
1854
|
+
subscriptionReady.resolve();
|
|
1595
1855
|
for await (const event of result.stream) {
|
|
1596
1856
|
if (turnAbortController.signal.aborted || this.activeForegroundTurnId !== turnId) {
|
|
1597
1857
|
break;
|
|
1598
1858
|
}
|
|
1599
|
-
const translated = this.translateEvent(event);
|
|
1859
|
+
const translated = await this.translateEvent(event);
|
|
1600
1860
|
for (const e of translated) {
|
|
1601
1861
|
if (this.activeForegroundTurnId !== turnId) {
|
|
1602
1862
|
return;
|
|
@@ -1604,19 +1864,9 @@ class OpenCodeAgentSession {
|
|
|
1604
1864
|
if (e.type === "timeline" && e.item.type === "tool_call") {
|
|
1605
1865
|
this.trackToolCall(e.item);
|
|
1606
1866
|
}
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
if (e.type === "turn_failed") {
|
|
1611
|
-
this.finishForegroundTurn({
|
|
1612
|
-
type: "turn_failed",
|
|
1613
|
-
provider: "opencode",
|
|
1614
|
-
error: normalizeTurnFailureError(e.error),
|
|
1615
|
-
}, turnId);
|
|
1616
|
-
}
|
|
1617
|
-
else {
|
|
1618
|
-
this.finishForegroundTurn(e, turnId);
|
|
1619
|
-
}
|
|
1867
|
+
const terminalEvent = toTerminalTurnEvent(e);
|
|
1868
|
+
if (terminalEvent) {
|
|
1869
|
+
this.finishForegroundTurn(terminalEvent, turnId);
|
|
1620
1870
|
return;
|
|
1621
1871
|
}
|
|
1622
1872
|
this.notifySubscribers(e, turnId);
|
|
@@ -1631,11 +1881,12 @@ class OpenCodeAgentSession {
|
|
|
1631
1881
|
}
|
|
1632
1882
|
}
|
|
1633
1883
|
catch (error) {
|
|
1884
|
+
subscriptionReady.reject(error);
|
|
1634
1885
|
if (!turnAbortController.signal.aborted && this.activeForegroundTurnId === turnId) {
|
|
1635
1886
|
this.finishForegroundTurn({
|
|
1636
1887
|
type: "turn_failed",
|
|
1637
1888
|
provider: "opencode",
|
|
1638
|
-
error:
|
|
1889
|
+
error: toDiagnosticErrorMessage(error),
|
|
1639
1890
|
}, turnId);
|
|
1640
1891
|
}
|
|
1641
1892
|
}
|
|
@@ -1677,13 +1928,22 @@ class OpenCodeAgentSession {
|
|
|
1677
1928
|
}
|
|
1678
1929
|
synthesizeInterruptedToolCalls(turnId) {
|
|
1679
1930
|
for (const item of this.runningToolCalls.values()) {
|
|
1931
|
+
const error = { message: "Tool execution aborted" };
|
|
1680
1932
|
this.notifySubscribers({
|
|
1681
1933
|
type: "timeline",
|
|
1682
1934
|
provider: "opencode",
|
|
1683
1935
|
item: {
|
|
1684
1936
|
...item,
|
|
1685
1937
|
status: "failed",
|
|
1686
|
-
error
|
|
1938
|
+
error,
|
|
1939
|
+
detail: item.detail.type === "sub_agent"
|
|
1940
|
+
? {
|
|
1941
|
+
...item.detail,
|
|
1942
|
+
log: [item.detail.log, error.message]
|
|
1943
|
+
.filter((entry) => entry.trim().length > 0)
|
|
1944
|
+
.join("\n"),
|
|
1945
|
+
}
|
|
1946
|
+
: item.detail,
|
|
1687
1947
|
},
|
|
1688
1948
|
}, turnId);
|
|
1689
1949
|
}
|
|
@@ -1729,34 +1989,33 @@ class OpenCodeAgentSession {
|
|
|
1729
1989
|
else {
|
|
1730
1990
|
let emittedAssistantText = false;
|
|
1731
1991
|
for (const part of parts) {
|
|
1732
|
-
if (part.type === "text") {
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
}
|
|
1992
|
+
if (part.type === "text" && part.text) {
|
|
1993
|
+
emittedAssistantText = true;
|
|
1994
|
+
yield {
|
|
1995
|
+
type: "timeline",
|
|
1996
|
+
provider: "opencode",
|
|
1997
|
+
item: { type: "assistant_message", text: part.text },
|
|
1998
|
+
};
|
|
1999
|
+
continue;
|
|
1741
2000
|
}
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
}
|
|
2001
|
+
if (part.type === "reasoning" && part.text) {
|
|
2002
|
+
yield {
|
|
2003
|
+
type: "timeline",
|
|
2004
|
+
provider: "opencode",
|
|
2005
|
+
item: { type: "reasoning", text: part.text },
|
|
2006
|
+
};
|
|
2007
|
+
continue;
|
|
1750
2008
|
}
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
2009
|
+
if (part.type !== "tool") {
|
|
2010
|
+
continue;
|
|
2011
|
+
}
|
|
2012
|
+
const parsedToolPart = OpencodeToolPartToTimelineItemSchema.safeParse(part);
|
|
2013
|
+
if (parsedToolPart.success && parsedToolPart.data) {
|
|
2014
|
+
yield {
|
|
2015
|
+
type: "timeline",
|
|
2016
|
+
provider: "opencode",
|
|
2017
|
+
item: parsedToolPart.data,
|
|
2018
|
+
};
|
|
1760
2019
|
}
|
|
1761
2020
|
}
|
|
1762
2021
|
if (!emittedAssistantText) {
|
|
@@ -1779,19 +2038,15 @@ class OpenCodeAgentSession {
|
|
|
1779
2038
|
const response = await this.client.app.agents({
|
|
1780
2039
|
directory: this.config.cwd,
|
|
1781
2040
|
});
|
|
1782
|
-
const
|
|
1783
|
-
|
|
1784
|
-
:
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
: DEFAULT_MODES.find((mode) => mode.id === agent.name)?.description,
|
|
1792
|
-
}));
|
|
1793
|
-
this.availableModesCache =
|
|
1794
|
-
discoveredModes.length > 0 ? sortOpenCodeModes(discoveredModes) : DEFAULT_MODES;
|
|
2041
|
+
const agents = response.error || !response.data ? [] : response.data;
|
|
2042
|
+
const discoveredModes = agents.filter(isSelectableOpenCodeAgent).map((agent) => ({
|
|
2043
|
+
id: agent.name,
|
|
2044
|
+
label: agent.name.charAt(0).toUpperCase() + agent.name.slice(1),
|
|
2045
|
+
description: typeof agent.description === "string" && agent.description.trim().length > 0
|
|
2046
|
+
? agent.description.trim()
|
|
2047
|
+
: DEFAULT_MODES.find((mode) => mode.id === agent.name)?.description,
|
|
2048
|
+
}));
|
|
2049
|
+
this.availableModesCache = mergeOpenCodeModes(discoveredModes);
|
|
1795
2050
|
return this.availableModesCache;
|
|
1796
2051
|
}
|
|
1797
2052
|
async getCurrentMode() {
|
|
@@ -1801,14 +2056,18 @@ class OpenCodeAgentSession {
|
|
|
1801
2056
|
const result = await this.client.command.list({
|
|
1802
2057
|
directory: this.config.cwd,
|
|
1803
2058
|
});
|
|
2059
|
+
const commandsByName = new Map(OPENCODE_HANDLED_BUILTIN_SLASH_COMMANDS.map((command) => [command.name, command]));
|
|
1804
2060
|
if (result.error || !result.data) {
|
|
1805
|
-
return
|
|
2061
|
+
return Array.from(commandsByName.values());
|
|
1806
2062
|
}
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
2063
|
+
for (const cmd of result.data) {
|
|
2064
|
+
commandsByName.set(cmd.name, {
|
|
2065
|
+
name: cmd.name,
|
|
2066
|
+
description: cmd.description ?? "",
|
|
2067
|
+
argumentHint: cmd.hints?.length ? cmd.hints.join(" ") : "",
|
|
2068
|
+
});
|
|
2069
|
+
}
|
|
2070
|
+
return Array.from(commandsByName.values());
|
|
1812
2071
|
}
|
|
1813
2072
|
async setMode(modeId) {
|
|
1814
2073
|
this.currentMode = normalizeOpenCodeModeId(modeId);
|
|
@@ -1950,10 +2209,7 @@ class OpenCodeAgentSession {
|
|
|
1950
2209
|
}
|
|
1951
2210
|
}
|
|
1952
2211
|
async configureMcpServers(mcpServers) {
|
|
1953
|
-
|
|
1954
|
-
const mappedConfig = toOpenCodeMcpConfig(serverConfig);
|
|
1955
|
-
await this.registerMcpServer(name, mappedConfig);
|
|
1956
|
-
}
|
|
2212
|
+
await Promise.all(Object.entries(mcpServers).map(([name, serverConfig]) => this.registerMcpServer(name, toOpenCodeMcpConfig(serverConfig))));
|
|
1957
2213
|
}
|
|
1958
2214
|
async registerMcpServer(name, config) {
|
|
1959
2215
|
await this.runMcpOperation("add", name, () => this.client.mcp.add({
|
|
@@ -1975,16 +2231,20 @@ class OpenCodeAgentSession {
|
|
|
1975
2231
|
if (isAlreadyPresentMcpError(error)) {
|
|
1976
2232
|
return;
|
|
1977
2233
|
}
|
|
1978
|
-
throw new Error(`Failed to ${operation} OpenCode MCP server '${name}': ${
|
|
2234
|
+
throw new Error(`Failed to ${operation} OpenCode MCP server '${name}': ${toDiagnosticErrorMessage(error)}`);
|
|
1979
2235
|
}
|
|
1980
|
-
translateEvent(event) {
|
|
2236
|
+
async translateEvent(event) {
|
|
1981
2237
|
const translated = translateOpenCodeEvent(event, {
|
|
1982
2238
|
sessionId: this.sessionId,
|
|
2239
|
+
cwd: this.config.cwd,
|
|
1983
2240
|
messageRoles: this.messageRoles,
|
|
1984
2241
|
accumulatedUsage: this.accumulatedUsage,
|
|
1985
2242
|
streamedPartKeys: this.streamedPartKeys,
|
|
1986
2243
|
emittedStructuredMessageIds: this.emittedStructuredMessageIds,
|
|
1987
2244
|
partTypes: this.partTypes,
|
|
2245
|
+
subAgentsByCallId: this.subAgentsByCallId,
|
|
2246
|
+
subAgentCallIdByChildSessionId: this.subAgentCallIdByChildSessionId,
|
|
2247
|
+
pendingChildToolPartsBySessionId: this.pendingChildToolPartsBySessionId,
|
|
1988
2248
|
modelContextWindowsByModelKey: this.modelContextWindowsByModelKey,
|
|
1989
2249
|
onAssistantModelContextWindowResolved: (contextWindowMaxTokens) => {
|
|
1990
2250
|
this.accumulatedUsage.contextWindowMaxTokens = contextWindowMaxTokens;
|
|
@@ -1993,8 +2253,13 @@ class OpenCodeAgentSession {
|
|
|
1993
2253
|
}
|
|
1994
2254
|
},
|
|
1995
2255
|
});
|
|
2256
|
+
const events = [];
|
|
1996
2257
|
for (const translatedEvent of translated) {
|
|
1997
2258
|
if (translatedEvent.type === "permission_requested") {
|
|
2259
|
+
const autoApproved = await this.tryAutoApproveToolPermission(translatedEvent.request);
|
|
2260
|
+
if (autoApproved) {
|
|
2261
|
+
continue;
|
|
2262
|
+
}
|
|
1998
2263
|
this.pendingPermissions.set(translatedEvent.request.id, translatedEvent.request);
|
|
1999
2264
|
}
|
|
2000
2265
|
if (translatedEvent.type === "turn_completed") {
|
|
@@ -2005,8 +2270,26 @@ class OpenCodeAgentSession {
|
|
|
2005
2270
|
this.accumulatedUsage =
|
|
2006
2271
|
contextWindowMaxTokens !== undefined ? { contextWindowMaxTokens } : {};
|
|
2007
2272
|
}
|
|
2273
|
+
events.push(translatedEvent);
|
|
2274
|
+
}
|
|
2275
|
+
return events;
|
|
2276
|
+
}
|
|
2277
|
+
async tryAutoApproveToolPermission(request) {
|
|
2278
|
+
if (this.currentMode !== OPENCODE_FULL_ACCESS_MODE_ID || request.kind !== "tool") {
|
|
2279
|
+
return false;
|
|
2280
|
+
}
|
|
2281
|
+
try {
|
|
2282
|
+
await this.client.permission.reply({
|
|
2283
|
+
requestID: request.id,
|
|
2284
|
+
directory: this.config.cwd,
|
|
2285
|
+
reply: "once",
|
|
2286
|
+
});
|
|
2287
|
+
return true;
|
|
2288
|
+
}
|
|
2289
|
+
catch (error) {
|
|
2290
|
+
this.logger.warn({ err: error, requestId: request.id }, "Failed to auto-approve OpenCode tool permission");
|
|
2291
|
+
return false;
|
|
2008
2292
|
}
|
|
2009
|
-
return translated;
|
|
2010
2293
|
}
|
|
2011
2294
|
resolveSelectedModelContextWindowMaxTokens() {
|
|
2012
2295
|
return this.selectedModelContextWindowMaxTokens;
|