@vellumai/assistant 0.6.2 → 0.6.4
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/ARCHITECTURE.md +273 -10
- package/Dockerfile +2 -3
- package/bun.lock +41 -49
- package/bunfig.toml +3 -0
- package/docs/architecture/memory.md +1 -1
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/stt-provider-onboarding.md +120 -0
- package/knip.json +12 -2
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +3 -3
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +1111 -86
- package/package.json +40 -42
- package/scripts/generate-openapi.ts +0 -2
- package/scripts/test.sh +73 -18
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop.test.ts +123 -0
- package/src/__tests__/anthropic-provider.test.ts +263 -10
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
- package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
- package/src/__tests__/browser-fill-credential.test.ts +240 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/browser-skill-endstate.test.ts +31 -7
- package/src/__tests__/btw-routes.test.ts +7 -0
- package/src/__tests__/call-controller.test.ts +581 -20
- package/src/__tests__/catalog-files.test.ts +1000 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/channel-invite-transport.test.ts +2 -2
- package/src/__tests__/channel-readiness-routes.test.ts +16 -20
- package/src/__tests__/channel-readiness-service.test.ts +12 -7
- package/src/__tests__/checker.test.ts +157 -10
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/config-analysis.test.ts +100 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +1248 -224
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +43 -8
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/contact-store-user-file.test.ts +512 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-overflow-approval.test.ts +16 -1
- package/src/__tests__/context-window-manager.test.ts +88 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +99 -3
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +290 -0
- package/src/__tests__/conversation-error.test.ts +70 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +12 -4
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +946 -62
- package/src/__tests__/conversation-routes-disk-view.test.ts +275 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +324 -46
- package/src/__tests__/conversation-skill-tools.test.ts +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +89 -18
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +6 -3
- package/src/__tests__/credential-vault-unit.test.ts +383 -7
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +42 -18
- package/src/__tests__/cross-provider-web-search.test.ts +146 -35
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +222 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +386 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +2 -0
- package/src/__tests__/gemini-provider.test.ts +66 -2
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
- package/src/__tests__/gmail-archive-gate.test.ts +246 -0
- package/src/__tests__/gmail-preferences.test.ts +117 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +738 -359
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +528 -49
- package/src/__tests__/headless-browser-read-tools.test.ts +274 -100
- package/src/__tests__/headless-browser-snapshot.test.ts +250 -77
- package/src/__tests__/heartbeat-service.test.ts +70 -17
- package/src/__tests__/home-state-routes.test.ts +162 -0
- package/src/__tests__/host-bash-proxy.test.ts +145 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +596 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +423 -0
- package/src/__tests__/host-cu-proxy.test.ts +166 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/llm-context-normalization.test.ts +488 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/media-stream-output.test.ts +555 -0
- package/src/__tests__/media-stream-parser.test.ts +374 -0
- package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
- package/src/__tests__/media-stream-stt-session.test.ts +588 -0
- package/src/__tests__/media-turn-detector.test.ts +440 -0
- package/src/__tests__/message-queue.test.ts +125 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +67 -8
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +109 -7
- package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +151 -0
- package/src/__tests__/model-intents.test.ts +2 -2
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/oauth-apps-routes.test.ts +18 -12
- package/src/__tests__/oauth-cli.test.ts +709 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +118 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +147 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +52 -14
- package/src/__tests__/oauth-store.test.ts +1465 -176
- package/src/__tests__/oauth2-gateway-transport.test.ts +460 -26
- package/src/__tests__/onboarding-template-contract.test.ts +81 -70
- package/src/__tests__/openai-provider.test.ts +178 -2
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1105 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +32 -3
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +343 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +174 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
- package/src/__tests__/relationship-state-contract.test.ts +175 -0
- package/src/__tests__/relay-server.test.ts +423 -5
- package/src/__tests__/require-fresh-approval.test.ts +40 -1
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/secret-scanner-executor.test.ts +4 -0
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +8 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +49 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +801 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +738 -0
- package/src/__tests__/skills.test.ts +5 -2
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +576 -16
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +184 -27
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +25 -5
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +33 -24
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +14 -29
- package/src/__tests__/trust-store.test.ts +7 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/tts-catalog-parity.test.ts +345 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
- package/src/__tests__/twilio-routes.test.ts +376 -0
- package/src/__tests__/unicode.test.ts +293 -0
- package/src/__tests__/update-bulletin-format.test.ts +59 -0
- package/src/__tests__/update-bulletin.test.ts +206 -5
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
- package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
- package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
- package/src/__tests__/workspace-migration-meets.test.ts +244 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
- package/src/__tests__/workspace-policy.test.ts +2 -0
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +55 -9
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/backup/__tests__/backup-key.test.ts +152 -0
- package/src/backup/__tests__/backup-worker.test.ts +767 -0
- package/src/backup/__tests__/list-snapshots.test.ts +87 -0
- package/src/backup/__tests__/local-writer.test.ts +218 -0
- package/src/backup/__tests__/offsite-writer.test.ts +641 -0
- package/src/backup/__tests__/paths.test.ts +300 -0
- package/src/backup/__tests__/restore.test.ts +498 -0
- package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
- package/src/backup/__tests__/stream-crypt.test.ts +228 -0
- package/src/backup/backup-key.ts +137 -0
- package/src/backup/backup-worker.ts +459 -0
- package/src/backup/list-snapshots.ts +147 -0
- package/src/backup/local-writer.ts +133 -0
- package/src/backup/offsite-writer.ts +222 -0
- package/src/backup/paths.ts +226 -0
- package/src/backup/restore.ts +322 -0
- package/src/backup/snapshot-lock.ts +431 -0
- package/src/backup/stream-crypt.ts +263 -0
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/bundler/package-resolver.ts +4 -0
- package/src/calls/audio-store.ts +11 -5
- package/src/calls/call-controller.ts +226 -71
- package/src/calls/call-domain.ts +9 -0
- package/src/calls/call-speech-output.ts +190 -0
- package/src/calls/call-transport.ts +77 -0
- package/src/calls/media-stream-audio-transcode.ts +173 -0
- package/src/calls/media-stream-output.ts +660 -0
- package/src/calls/media-stream-parser.ts +300 -0
- package/src/calls/media-stream-protocol.ts +166 -0
- package/src/calls/media-stream-server.ts +592 -0
- package/src/calls/media-stream-stt-session.ts +460 -0
- package/src/calls/media-turn-detector.ts +230 -0
- package/src/calls/relay-server.ts +90 -75
- package/src/calls/resolve-call-tts-provider.ts +136 -0
- package/src/calls/telephony-stt-routing.ts +145 -0
- package/src/calls/tts-call-strategy.ts +161 -0
- package/src/calls/tts-text-sanitizer.ts +32 -16
- package/src/calls/twilio-routes.ts +281 -17
- package/src/calls/voice-quality.ts +78 -35
- package/src/calls/voice-session-bridge.ts +8 -1
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +69 -3
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
- package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
- package/src/cli/commands/__tests__/email-download.test.ts +16 -1
- package/src/cli/commands/__tests__/email-list.test.ts +22 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +37 -4
- package/src/cli/commands/__tests__/email-status.test.ts +5 -1
- package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/conversations.ts +77 -0
- package/src/cli/commands/credentials.ts +3 -4
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +273 -16
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +56 -44
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +32 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +330 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +117 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +6 -3
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +215 -36
- package/src/cli/commands/oauth/shared.ts +7 -6
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +254 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +30 -4
- package/src/config/__tests__/backup-schema.test.ts +134 -0
- package/src/config/assistant-feature-flags.ts +61 -62
- package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +141 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/browser/SKILL.md +30 -5
- package/src/config/bundled-skills/browser/TOOLS.json +123 -0
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
- package/src/config/bundled-skills/contacts/SKILL.md +5 -2
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +54 -8
- package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
- package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
- package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/outlook/SKILL.md +9 -2
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
- package/src/config/bundled-skills/slack/SKILL.md +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
- package/src/config/bundled-tool-registry.ts +8 -0
- package/src/config/env-registry.ts +38 -0
- package/src/config/env.ts +49 -4
- package/src/config/feature-flag-registry.json +85 -14
- package/src/config/loader.ts +82 -13
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +81 -15
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +51 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -26
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +47 -7
- package/src/config/schemas/heartbeat.ts +27 -5
- package/src/config/schemas/host-browser.ts +112 -0
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +52 -0
- package/src/config/schemas/stt.ts +59 -0
- package/src/config/schemas/tts.ts +230 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/skills.ts +4 -0
- package/src/config/types.ts +4 -1
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/post-turn-tool-result-truncation.ts +177 -0
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +61 -10
- package/src/credential-execution/approval-bridge.ts +49 -15
- package/src/credential-execution/executable-discovery.ts +12 -2
- package/src/credential-execution/process-manager.ts +33 -2
- package/src/credential-health/credential-health-service.ts +366 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +195 -0
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +99 -5
- package/src/daemon/context-overflow-approval.ts +5 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +23 -2
- package/src/daemon/conversation-agent-loop.ts +153 -42
- package/src/daemon/conversation-attachments.ts +40 -0
- package/src/daemon/conversation-error.ts +11 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +59 -9
- package/src/daemon/conversation-messaging.ts +37 -3
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +622 -13
- package/src/daemon/conversation-queue-manager.ts +24 -0
- package/src/daemon/conversation-runtime-assembly.ts +128 -36
- package/src/daemon/conversation-slash.ts +36 -0
- package/src/daemon/conversation-surfaces.ts +131 -40
- package/src/daemon/conversation-tool-setup.ts +99 -8
- package/src/daemon/conversation-usage.ts +7 -4
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +292 -16
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +13 -141
- package/src/daemon/handlers/shared.ts +80 -0
- package/src/daemon/handlers/skills.ts +483 -44
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +192 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +179 -28
- package/src/daemon/message-protocol.ts +13 -0
- package/src/daemon/message-types/conversations.ts +89 -14
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +19 -5
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +26 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/server.ts +439 -14
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +15 -0
- package/src/daemon/transport-hints.ts +5 -24
- package/src/email/html-renderer.ts +76 -0
- package/src/heartbeat/heartbeat-service.ts +93 -7
- package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
- package/src/home/__tests__/emit-feed-event.test.ts +169 -0
- package/src/home/__tests__/feed-scheduler.test.ts +194 -0
- package/src/home/__tests__/feed-types.test.ts +275 -0
- package/src/home/__tests__/feed-writer.test.ts +688 -0
- package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
- package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
- package/src/home/__tests__/progress-formula.test.ts +213 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
- package/src/home/__tests__/rollup-producer.test.ts +398 -0
- package/src/home/assistant-feed-authoring.ts +124 -0
- package/src/home/emit-feed-event.ts +158 -0
- package/src/home/feed-scheduler.ts +247 -0
- package/src/home/feed-types.ts +181 -0
- package/src/home/feed-writer.ts +469 -0
- package/src/home/platform-gmail-digest.ts +163 -0
- package/src/home/progress-formula.ts +86 -0
- package/src/home/relationship-state-writer.ts +824 -0
- package/src/home/relationship-state.ts +143 -0
- package/src/home/rollup-producer.ts +384 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +30 -20
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/cli-client.ts +151 -0
- package/src/ipc/cli-server.ts +234 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/index.ts +5 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/mcp/client.ts +59 -24
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
- package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/app-store.ts +31 -1
- package/src/memory/attachments-store.ts +70 -0
- package/src/memory/auto-analysis-enqueue.ts +127 -0
- package/src/memory/auto-analysis-guard.ts +27 -0
- package/src/memory/cleanup-schedule-state.ts +37 -0
- package/src/memory/conversation-analyze-job.ts +73 -0
- package/src/memory/conversation-crud.ts +122 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +34 -2
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +18 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +176 -17
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/conversation-graph-memory.ts +15 -0
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/extraction.test.ts +23 -0
- package/src/memory/graph/extraction.ts +8 -0
- package/src/memory/graph/retriever.ts +67 -40
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/group-crud.ts +6 -1
- package/src/memory/indexer.ts +95 -16
- package/src/memory/job-handlers/cleanup.ts +11 -8
- package/src/memory/job-handlers/conversation-starters.ts +16 -10
- package/src/memory/jobs-store.ts +64 -4
- package/src/memory/jobs-worker.ts +22 -9
- package/src/memory/llm-usage-store.ts +137 -60
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
- package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/oauth.ts +21 -13
- package/src/memory/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/client.ts +57 -6
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +143 -38
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/decision-engine.ts +3 -3
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +25 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +26 -9
- package/src/oauth/byo-connection.ts +10 -8
- package/src/oauth/connect-orchestrator.ts +25 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +22 -18
- package/src/oauth/connection.ts +3 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +223 -100
- package/src/oauth/platform-connection.test.ts +101 -3
- package/src/oauth/platform-connection.ts +56 -35
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +133 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +16 -6
- package/src/permissions/defaults.ts +49 -1
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -1
- package/src/permissions/trust-store.ts +3 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/permissions/workspace-policy.ts +3 -0
- package/src/platform/client.test.ts +10 -0
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +126 -2
- package/src/prompts/system-prompt.ts +76 -38
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -105
- package/src/prompts/templates/SOUL.md +3 -1
- package/src/prompts/templates/UPDATES.md +12 -0
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-format.ts +26 -9
- package/src/prompts/update-bulletin.ts +34 -23
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/anthropic/client.ts +157 -60
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +9 -1
- package/src/providers/model-catalog.ts +6 -0
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +474 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +502 -0
- package/src/providers/openrouter/client.ts +101 -4
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +14 -3
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
- package/src/providers/speech-to-text/deepgram.test.ts +332 -0
- package/src/providers/speech-to-text/deepgram.ts +115 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
- package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
- package/src/providers/speech-to-text/google-gemini.ts +101 -0
- package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
- package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
- package/src/providers/speech-to-text/openai-whisper.ts +63 -33
- package/src/providers/speech-to-text/provider-catalog.ts +306 -0
- package/src/providers/speech-to-text/resolve.ts +386 -6
- package/src/providers/types.ts +10 -1
- package/src/runtime/AGENTS.md +65 -0
- package/src/runtime/__tests__/agent-wake.test.ts +831 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
- package/src/runtime/agent-wake.ts +512 -0
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +48 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +33 -9
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-invite-transports/email.ts +14 -6
- package/src/runtime/channel-readiness-service.ts +12 -22
- package/src/runtime/chrome-extension-registry.ts +368 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +815 -75
- package/src/runtime/http-types.ts +6 -2
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +198 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/migration-transport.ts +7 -0
- package/src/runtime/migrations/migration-wizard.ts +23 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +96 -1
- package/src/runtime/migrations/vbundle-importer.ts +89 -5
- package/src/runtime/pending-interactions.ts +18 -13
- package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
- package/src/runtime/routes/app-management-routes.ts +12 -18
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +556 -0
- package/src/runtime/routes/btw-routes.ts +8 -6
- package/src/runtime/routes/contact-routes.test.ts +298 -0
- package/src/runtime/routes/contact-routes.ts +132 -5
- package/src/runtime/routes/conversation-analysis-routes.ts +22 -141
- package/src/runtime/routes/conversation-management-routes.ts +223 -0
- package/src/runtime/routes/conversation-routes.ts +598 -103
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/home-feed-routes.ts +334 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +268 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +262 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
- package/src/runtime/routes/integrations/slack/channel.ts +11 -3
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +303 -0
- package/src/runtime/routes/log-export-routes.ts +42 -22
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +122 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +31 -102
- package/src/runtime/routes/skills-routes.ts +128 -9
- package/src/runtime/routes/stt-routes.ts +233 -0
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/surface-action-routes.ts +41 -2
- package/src/runtime/routes/tts-routes.ts +108 -24
- package/src/runtime/routes/usage-routes.ts +38 -9
- package/src/runtime/routes/user-route-dispatcher.ts +50 -5
- package/src/runtime/routes/user-routes.ts +13 -1
- package/src/runtime/routes/work-items-routes.ts +8 -1
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
- package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
- package/src/runtime/services/analyze-conversation.ts +344 -0
- package/src/runtime/services/analyze-deps-singleton.ts +32 -0
- package/src/runtime/services/auto-analysis-prompt.ts +55 -0
- package/src/runtime/skill-route-registry.ts +49 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +57 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +68 -29
- package/src/security/secure-keys.ts +143 -27
- package/src/security/token-manager.ts +31 -10
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-files.ts +554 -0
- package/src/skills/category-inference.ts +122 -0
- package/src/skills/clawhub-files.ts +213 -0
- package/src/skills/clawhub.ts +84 -23
- package/src/skills/skill-file-provider.ts +40 -0
- package/src/skills/skillssh-files.ts +395 -0
- package/src/skills/skillssh-registry.ts +4 -4
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +195 -0
- package/src/stt/stt-stream-session.ts +499 -0
- package/src/stt/types.ts +330 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +169 -40
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +1787 -342
- package/src/tools/browser/browser-manager.ts +81 -12
- package/src/tools/browser/browser-mode-constants.ts +12 -0
- package/src/tools/browser/browser-mode.ts +92 -0
- package/src/tools/browser/browser-status-constants.ts +33 -0
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1263 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +359 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1993 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +1007 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +744 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +868 -0
- package/src/tools/browser/cdp-client/errors.ts +49 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +148 -0
- package/src/tools/browser/cdp-client/factory.ts +914 -0
- package/src/tools/browser/cdp-client/index.ts +28 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +120 -0
- package/src/tools/credentials/vault.ts +35 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/network/web-fetch.ts +5 -2
- package/src/tools/network/web-search.ts +5 -2
- package/src/tools/permission-checker.ts +77 -82
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -0
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +2 -0
- package/src/tools/skills/sandbox-runner.ts +3 -2
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +15 -0
- package/src/tools/terminal/shell.ts +36 -20
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/tool-manifest.ts +21 -0
- package/src/tools/types.ts +19 -0
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tts/__tests__/provider-adapters.test.ts +834 -0
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
- package/src/tts/__tests__/provider-catalog.test.ts +183 -0
- package/src/tts/__tests__/provider-registry.test.ts +90 -0
- package/src/tts/provider-catalog.ts +201 -0
- package/src/tts/provider-registry.ts +73 -0
- package/src/tts/providers/deepgram-provider.ts +219 -0
- package/src/tts/providers/elevenlabs-provider.ts +211 -0
- package/src/tts/providers/fish-audio-provider.ts +183 -0
- package/src/tts/providers/index.ts +42 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +153 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/util/abort-reasons.ts +58 -0
- package/src/util/device-id.ts +32 -16
- package/src/util/errors.ts +9 -1
- package/src/util/platform.ts +63 -24
- package/src/util/pricing.ts +66 -3
- package/src/util/spawn.ts +1 -1
- package/src/util/truncate.ts +4 -2
- package/src/util/unicode.ts +201 -0
- package/src/version.ts +19 -24
- package/src/watcher/engine.ts +23 -0
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/migrations/003-seed-device-id.ts +9 -3
- package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
- package/src/workspace/migrations/029-seed-pkb.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +317 -0
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
- package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
- package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
- package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/top-level-renderer.ts +31 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/cli/commands/browser-relay.ts +0 -536
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/email/guardrails.ts +0 -221
- package/src/email/provider.ts +0 -117
- package/src/email/providers/agentmail.ts +0 -361
- package/src/email/providers/index.ts +0 -65
- package/src/email/service.ts +0 -384
- package/src/email/types.ts +0 -126
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/prompts/templates/USER.md +0 -13
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
import { getLogger } from "../../../util/logger.js";
|
|
2
|
+
import {
|
|
3
|
+
buildBrowserWsUrl,
|
|
4
|
+
type DevToolsTarget,
|
|
5
|
+
type DevToolsVersionInfo,
|
|
6
|
+
discoverTargetsViaWs,
|
|
7
|
+
isHttpDiscoveryFallbackEligible,
|
|
8
|
+
listDevToolsTargets,
|
|
9
|
+
pickDefaultTarget,
|
|
10
|
+
probeDevToolsJsonVersion,
|
|
11
|
+
} from "./cdp-inspect/discovery.js";
|
|
12
|
+
import {
|
|
13
|
+
type CdpWsTransport,
|
|
14
|
+
CdpWsTransportError,
|
|
15
|
+
connectCdpWsTransport,
|
|
16
|
+
} from "./cdp-inspect/ws-transport.js";
|
|
17
|
+
import { CdpError } from "./errors.js";
|
|
18
|
+
import type { CdpClientKind, ScopedCdpClient } from "./types.js";
|
|
19
|
+
|
|
20
|
+
const log = getLogger("cdp-inspect-client");
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Default timeout (ms) for each discovery HTTP probe. Kept short so a
|
|
24
|
+
* user who has no chrome running on the configured port fails fast
|
|
25
|
+
* instead of blocking the entire tool invocation. The ws-transport
|
|
26
|
+
* has its own, separate connect timeout.
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_DISCOVERY_TIMEOUT_MS = 2_000;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Subset of DevTools endpoint config the CdpInspectClient needs. The
|
|
32
|
+
* higher-level factory is responsible for feeding these values
|
|
33
|
+
* from the user's settings. Everything else — connect timeouts, ws
|
|
34
|
+
* retries, abort plumbing — is controlled locally here so we don't
|
|
35
|
+
* leak transport knobs into tool call sites.
|
|
36
|
+
*/
|
|
37
|
+
export interface CdpInspectClientOptions {
|
|
38
|
+
/** Loopback host — enforced by discovery helpers before any I/O. */
|
|
39
|
+
host: string;
|
|
40
|
+
/** Port the user's Chrome is listening on for DevTools HTTP. */
|
|
41
|
+
port: number;
|
|
42
|
+
/** Optional per-attach discovery probe timeout. */
|
|
43
|
+
discoveryTimeoutMs?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Optional per-attach ws connect timeout. Forwarded verbatim to
|
|
46
|
+
* {@link connectCdpWsTransport}.
|
|
47
|
+
*/
|
|
48
|
+
wsConnectTimeoutMs?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Test seam: override the discovery / transport helpers so unit
|
|
51
|
+
* tests don't need a real Chrome or a Bun.serve-backed fake peer.
|
|
52
|
+
* The factory does not use this path.
|
|
53
|
+
*/
|
|
54
|
+
helpers?: CdpInspectHelpers;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Override shape used by tests. Each field defaults to the real
|
|
59
|
+
* implementation imported at the top of this module when omitted.
|
|
60
|
+
*/
|
|
61
|
+
export interface CdpInspectHelpers {
|
|
62
|
+
probeDevToolsJsonVersion?: typeof probeDevToolsJsonVersion;
|
|
63
|
+
listDevToolsTargets?: typeof listDevToolsTargets;
|
|
64
|
+
pickDefaultTarget?: typeof pickDefaultTarget;
|
|
65
|
+
connectCdpWsTransport?: typeof connectCdpWsTransport;
|
|
66
|
+
/** Override for the WS-only fallback target discovery. */
|
|
67
|
+
discoverTargetsViaWs?: typeof discoverTargetsViaWs;
|
|
68
|
+
/** Override for building the well-known browser WS URL. */
|
|
69
|
+
buildBrowserWsUrl?: typeof buildBrowserWsUrl;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface AttachedSession {
|
|
73
|
+
transport: CdpWsTransport;
|
|
74
|
+
sessionId: string;
|
|
75
|
+
target: DevToolsTarget;
|
|
76
|
+
/**
|
|
77
|
+
* Version info from HTTP `/json/version`. `null` when the session
|
|
78
|
+
* was established via the WS-only fallback path (no HTTP discovery).
|
|
79
|
+
*/
|
|
80
|
+
version: DevToolsVersionInfo | null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* In-flight attach handle. Wraps the shared attach promise with a
|
|
85
|
+
* dedicated {@link AbortController} and a ref-count of live callers
|
|
86
|
+
* waiting on the attach. When every caller has raced its own signal
|
|
87
|
+
* and given up, the ref-count drops to zero and the shared controller
|
|
88
|
+
* aborts so the underlying discovery / ws / `Target.attachToTarget`
|
|
89
|
+
* work stops promptly instead of wedging the socket.
|
|
90
|
+
*/
|
|
91
|
+
interface PendingAttach {
|
|
92
|
+
/** Shared attach promise — resolved exactly once per attach attempt. */
|
|
93
|
+
promise: Promise<AttachedSession>;
|
|
94
|
+
/** Controller wired through probe / list / connect / attach. */
|
|
95
|
+
controller: AbortController;
|
|
96
|
+
/** Number of live callers still awaiting this attach. */
|
|
97
|
+
waiters: number;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* CdpClient backed by the DevTools JSON protocol over a raw
|
|
102
|
+
* WebSocket (the `cdp-inspect` transport). Composes the discovery
|
|
103
|
+
* helpers (`probeDevToolsJsonVersion` + `listDevToolsTargets` +
|
|
104
|
+
* `pickDefaultTarget`) with the shared `connectCdpWsTransport` to
|
|
105
|
+
* reach an already-running Chrome instance the user has launched
|
|
106
|
+
* with `--remote-debugging-port`.
|
|
107
|
+
*
|
|
108
|
+
* Lifetime mirrors {@link import("./local-cdp-client.js").LocalCdpClient}:
|
|
109
|
+
*
|
|
110
|
+
* - Lazy one-time attach: the first `send()` performs version probe
|
|
111
|
+
* + target discovery + ws connect + `Target.attachToTarget`, then
|
|
112
|
+
* caches the session for every subsequent call.
|
|
113
|
+
* - Concurrent callers share a single in-flight attach promise so
|
|
114
|
+
* `Target.attachToTarget` runs exactly once per client instance.
|
|
115
|
+
* - Each `send(..., signal)` caller can race its own AbortSignal
|
|
116
|
+
* against the shared attach and cut through promptly. When every
|
|
117
|
+
* concurrent caller has aborted, the shared attach work is also
|
|
118
|
+
* cancelled so we don't leak discovery fetches or a half-open ws.
|
|
119
|
+
* - If the attach promise rejects, the cached promise is cleared so
|
|
120
|
+
* the next `send()` retries from scratch instead of replaying the
|
|
121
|
+
* same failure forever.
|
|
122
|
+
* - `dispose()` is idempotent and tears down the ws transport if an
|
|
123
|
+
* attach ever resolved.
|
|
124
|
+
*/
|
|
125
|
+
export class CdpInspectClient implements ScopedCdpClient {
|
|
126
|
+
readonly kind: CdpClientKind = "cdp-inspect";
|
|
127
|
+
|
|
128
|
+
private pending: PendingAttach | null = null;
|
|
129
|
+
private session: AttachedSession | null = null;
|
|
130
|
+
private disposed = false;
|
|
131
|
+
private readonly helpers: Required<CdpInspectHelpers>;
|
|
132
|
+
|
|
133
|
+
constructor(
|
|
134
|
+
public readonly conversationId: string,
|
|
135
|
+
private readonly options: CdpInspectClientOptions,
|
|
136
|
+
) {
|
|
137
|
+
this.helpers = {
|
|
138
|
+
probeDevToolsJsonVersion:
|
|
139
|
+
options.helpers?.probeDevToolsJsonVersion ?? probeDevToolsJsonVersion,
|
|
140
|
+
listDevToolsTargets:
|
|
141
|
+
options.helpers?.listDevToolsTargets ?? listDevToolsTargets,
|
|
142
|
+
pickDefaultTarget:
|
|
143
|
+
options.helpers?.pickDefaultTarget ?? pickDefaultTarget,
|
|
144
|
+
connectCdpWsTransport:
|
|
145
|
+
options.helpers?.connectCdpWsTransport ?? connectCdpWsTransport,
|
|
146
|
+
discoverTargetsViaWs:
|
|
147
|
+
options.helpers?.discoverTargetsViaWs ?? discoverTargetsViaWs,
|
|
148
|
+
buildBrowserWsUrl:
|
|
149
|
+
options.helpers?.buildBrowserWsUrl ?? buildBrowserWsUrl,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Lazily attach (and cache) a CDP session against the configured
|
|
155
|
+
* DevTools endpoint. Each caller races its own `signal` against the
|
|
156
|
+
* shared attach so an individual abort always wins promptly; when
|
|
157
|
+
* every waiter has aborted, the shared attach work is cancelled
|
|
158
|
+
* too via the pending attach's internal controller. See class-level
|
|
159
|
+
* docs for the resilience contract — in particular, transient
|
|
160
|
+
* attach failures must NOT poison the cached promise for subsequent
|
|
161
|
+
* calls.
|
|
162
|
+
*/
|
|
163
|
+
private async ensureSession(signal?: AbortSignal): Promise<AttachedSession> {
|
|
164
|
+
if (this.disposed) {
|
|
165
|
+
throw new CdpError("disposed", "CdpInspectClient already disposed");
|
|
166
|
+
}
|
|
167
|
+
if (this.session) return this.session;
|
|
168
|
+
|
|
169
|
+
const pending = this.pending ?? this.startAttach();
|
|
170
|
+
pending.waiters += 1;
|
|
171
|
+
|
|
172
|
+
// `onAbort` fires exactly once if this caller's signal wins the
|
|
173
|
+
// race. It (a) drops this caller's waiter slot and (b) aborts
|
|
174
|
+
// the shared controller iff no other caller is still listening,
|
|
175
|
+
// so the underlying discovery / ws / attach work is cancelled
|
|
176
|
+
// promptly instead of leaking into the background.
|
|
177
|
+
let released = false;
|
|
178
|
+
const onAbort = () => {
|
|
179
|
+
if (released) return;
|
|
180
|
+
released = true;
|
|
181
|
+
pending.waiters -= 1;
|
|
182
|
+
if (pending.waiters <= 0 && this.pending === pending) {
|
|
183
|
+
// Clear the cached pending attach synchronously BEFORE
|
|
184
|
+
// firing the shared controller's abort. Otherwise a new
|
|
185
|
+
// `send()` that enters `ensureSession` between this abort
|
|
186
|
+
// and the async `.catch()` handler in `startAttach()` would
|
|
187
|
+
// reuse this already-aborted attach and immediately fail
|
|
188
|
+
// with an `aborted` error even though the new caller never
|
|
189
|
+
// aborted its own signal.
|
|
190
|
+
this.pending = null;
|
|
191
|
+
try {
|
|
192
|
+
pending.controller.abort();
|
|
193
|
+
} catch {
|
|
194
|
+
// best effort
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
return await raceAbort(pending.promise, signal, onAbort);
|
|
201
|
+
} finally {
|
|
202
|
+
// Inner attach resolved or rejected before this caller's
|
|
203
|
+
// signal fired — drop the waiter slot without touching the
|
|
204
|
+
// shared controller (it's already settled). If `onAbort` ran,
|
|
205
|
+
// `released` is already true and this is a no-op.
|
|
206
|
+
if (!released) {
|
|
207
|
+
released = true;
|
|
208
|
+
pending.waiters -= 1;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Kick off a fresh shared attach. The returned {@link PendingAttach}
|
|
215
|
+
* is cached on `this.pending` until it either resolves (in which
|
|
216
|
+
* case the session is stashed on `this.session`) or rejects (in
|
|
217
|
+
* which case the cache is cleared so the next caller retries from
|
|
218
|
+
* scratch).
|
|
219
|
+
*/
|
|
220
|
+
private startAttach(): PendingAttach {
|
|
221
|
+
const controller = new AbortController();
|
|
222
|
+
const pending: PendingAttach = {
|
|
223
|
+
controller,
|
|
224
|
+
waiters: 0,
|
|
225
|
+
promise: this.attach(controller.signal),
|
|
226
|
+
};
|
|
227
|
+
this.pending = pending;
|
|
228
|
+
|
|
229
|
+
pending.promise
|
|
230
|
+
.then((session) => {
|
|
231
|
+
// Another concurrent attach may have won the race (e.g. after
|
|
232
|
+
// a dispose + retry). Only cache the result if we're still
|
|
233
|
+
// the current attempt.
|
|
234
|
+
if (this.pending === pending) {
|
|
235
|
+
this.pending = null;
|
|
236
|
+
if (this.disposed) {
|
|
237
|
+
// Dispose landed before we could publish the session —
|
|
238
|
+
// tear down the transport immediately so we don't leak.
|
|
239
|
+
try {
|
|
240
|
+
session.transport.dispose();
|
|
241
|
+
} catch {
|
|
242
|
+
// best effort
|
|
243
|
+
}
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
this.session = session;
|
|
247
|
+
} else {
|
|
248
|
+
// A stale attempt — drop the transport so we don't leak.
|
|
249
|
+
try {
|
|
250
|
+
session.transport.dispose();
|
|
251
|
+
} catch {
|
|
252
|
+
// best effort
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
})
|
|
256
|
+
.catch(() => {
|
|
257
|
+
// Clear the cached pending attach on rejection so the next
|
|
258
|
+
// call retries from scratch instead of replaying the same
|
|
259
|
+
// failure forever. Only clear if we're still the current
|
|
260
|
+
// attempt — a concurrent dispose may have already nulled it.
|
|
261
|
+
if (this.pending === pending) {
|
|
262
|
+
this.pending = null;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
return pending;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Perform the actual discovery + ws-connect + attach sequence. All
|
|
271
|
+
* underlying errors are rethrown unchanged so the `send()` wrapper
|
|
272
|
+
* can map them to stable `CdpError` codes without double-wrapping
|
|
273
|
+
* the already-typed discovery / ws-transport errors.
|
|
274
|
+
*
|
|
275
|
+
* Two discovery strategies are tried in order:
|
|
276
|
+
*
|
|
277
|
+
* 1. **HTTP discovery** (primary): `/json/version` + `/json/list`.
|
|
278
|
+
* 2. **WS-only fallback**: direct WebSocket connect to the well-known
|
|
279
|
+
* browser endpoint + CDP `Target.getTargets`. Only attempted when
|
|
280
|
+
* HTTP discovery fails with `invalid_response` or `unreachable`.
|
|
281
|
+
*
|
|
282
|
+
* The `signal` here is the shared, internal {@link PendingAttach}
|
|
283
|
+
* signal — NOT the per-caller signal. It is aborted when the last
|
|
284
|
+
* caller interested in this attach has given up, or when `dispose()`
|
|
285
|
+
* races an in-flight attach.
|
|
286
|
+
*/
|
|
287
|
+
private async attach(signal: AbortSignal): Promise<AttachedSession> {
|
|
288
|
+
const discoveryTimeoutMs =
|
|
289
|
+
this.options.discoveryTimeoutMs ?? DEFAULT_DISCOVERY_TIMEOUT_MS;
|
|
290
|
+
const { host, port } = this.options;
|
|
291
|
+
|
|
292
|
+
// --- Try HTTP discovery first ---
|
|
293
|
+
const httpResult = await this.tryHttpDiscovery(
|
|
294
|
+
host,
|
|
295
|
+
port,
|
|
296
|
+
discoveryTimeoutMs,
|
|
297
|
+
signal,
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
if (httpResult.ok) {
|
|
301
|
+
return this.connectAndAttach(
|
|
302
|
+
httpResult.wsUrl,
|
|
303
|
+
httpResult.target,
|
|
304
|
+
httpResult.version,
|
|
305
|
+
signal,
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// HTTP discovery failed — check if the error is eligible for the
|
|
310
|
+
// WS-only fallback.
|
|
311
|
+
if (!isHttpDiscoveryFallbackEligible(httpResult.error)) {
|
|
312
|
+
// Non-recoverable error (non_loopback, non_chrome, timeout) —
|
|
313
|
+
// rethrow without attempting the WS fallback.
|
|
314
|
+
throw httpResult.error;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Guard against the narrow race where tryHttpDiscovery returned a
|
|
318
|
+
// fallback-eligible error (unreachable / invalid_response) but the
|
|
319
|
+
// signal was aborted between that return and this check. The abort
|
|
320
|
+
// CdpError from tryHttpDiscovery itself only surfaces when the signal
|
|
321
|
+
// is already aborted *during* a fetch/probe; this covers the gap
|
|
322
|
+
// between the last await inside tryHttpDiscovery and the fallback
|
|
323
|
+
// eligibility check above.
|
|
324
|
+
if (signal.aborted) {
|
|
325
|
+
throw new CdpError("aborted", "CdpInspectClient attach aborted");
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// --- WS-only fallback path ---
|
|
329
|
+
log.debug(
|
|
330
|
+
{
|
|
331
|
+
conversationId: this.conversationId,
|
|
332
|
+
httpErrorCode: httpResult.error.code,
|
|
333
|
+
httpErrorMessage: httpResult.error.message,
|
|
334
|
+
},
|
|
335
|
+
"HTTP discovery unavailable, attempting WS-only fallback",
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
return this.tryWsFallback(host, port, httpResult.error, signal);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Attempt HTTP-based discovery (probe `/json/version` + enumerate
|
|
343
|
+
* `/json/list`). Returns a discriminated result so the caller can
|
|
344
|
+
* branch on success vs. failure without try/catch nesting.
|
|
345
|
+
*/
|
|
346
|
+
private async tryHttpDiscovery(
|
|
347
|
+
host: string,
|
|
348
|
+
port: number,
|
|
349
|
+
discoveryTimeoutMs: number,
|
|
350
|
+
signal: AbortSignal,
|
|
351
|
+
): Promise<
|
|
352
|
+
| {
|
|
353
|
+
ok: true;
|
|
354
|
+
version: DevToolsVersionInfo;
|
|
355
|
+
target: DevToolsTarget;
|
|
356
|
+
wsUrl: string;
|
|
357
|
+
}
|
|
358
|
+
| { ok: false; error: unknown }
|
|
359
|
+
> {
|
|
360
|
+
try {
|
|
361
|
+
const version = await this.helpers.probeDevToolsJsonVersion({
|
|
362
|
+
host,
|
|
363
|
+
port,
|
|
364
|
+
timeoutMs: discoveryTimeoutMs,
|
|
365
|
+
signal,
|
|
366
|
+
});
|
|
367
|
+
if (signal.aborted) {
|
|
368
|
+
return {
|
|
369
|
+
ok: false,
|
|
370
|
+
error: new CdpError("aborted", "CdpInspectClient attach aborted"),
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
const targets = await this.helpers.listDevToolsTargets({
|
|
374
|
+
host,
|
|
375
|
+
port,
|
|
376
|
+
timeoutMs: discoveryTimeoutMs,
|
|
377
|
+
signal,
|
|
378
|
+
});
|
|
379
|
+
if (signal.aborted) {
|
|
380
|
+
return {
|
|
381
|
+
ok: false,
|
|
382
|
+
error: new CdpError("aborted", "CdpInspectClient attach aborted"),
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
const target = this.helpers.pickDefaultTarget(targets);
|
|
386
|
+
const wsUrl = version.webSocketDebuggerUrl || target.webSocketDebuggerUrl;
|
|
387
|
+
return { ok: true, version, target, wsUrl };
|
|
388
|
+
} catch (err) {
|
|
389
|
+
return { ok: false, error: err };
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* WS-only fallback: connect directly to the well-known browser
|
|
395
|
+
* WebSocket endpoint, enumerate targets via CDP `Target.getTargets`,
|
|
396
|
+
* pick a default, and attach. Used when HTTP discovery endpoints
|
|
397
|
+
* (`/json/version`, `/json/list`) are absent.
|
|
398
|
+
*/
|
|
399
|
+
private async tryWsFallback(
|
|
400
|
+
host: string,
|
|
401
|
+
port: number,
|
|
402
|
+
httpError: unknown,
|
|
403
|
+
signal: AbortSignal,
|
|
404
|
+
): Promise<AttachedSession> {
|
|
405
|
+
let wsUrl: string;
|
|
406
|
+
try {
|
|
407
|
+
wsUrl = this.helpers.buildBrowserWsUrl(host, port);
|
|
408
|
+
} catch (err) {
|
|
409
|
+
// buildBrowserWsUrl enforces loopback — if it throws, the host
|
|
410
|
+
// is non-loopback and we should not attempt any WS connection.
|
|
411
|
+
throw err;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
let transport: CdpWsTransport;
|
|
415
|
+
try {
|
|
416
|
+
transport = await this.helpers.connectCdpWsTransport(wsUrl, {
|
|
417
|
+
connectTimeoutMs: this.options.wsConnectTimeoutMs,
|
|
418
|
+
signal,
|
|
419
|
+
});
|
|
420
|
+
} catch (wsConnectErr) {
|
|
421
|
+
// WS connect also failed — surface a classified error that
|
|
422
|
+
// explains both the HTTP and WS failures.
|
|
423
|
+
const wsMsg =
|
|
424
|
+
wsConnectErr instanceof Error
|
|
425
|
+
? wsConnectErr.message
|
|
426
|
+
: String(wsConnectErr);
|
|
427
|
+
const httpMsg =
|
|
428
|
+
httpError instanceof Error ? httpError.message : String(httpError);
|
|
429
|
+
throw new CdpError(
|
|
430
|
+
"transport_error",
|
|
431
|
+
`CDP endpoint unreachable: HTTP discovery failed (${httpMsg}) ` +
|
|
432
|
+
`and WS-only fallback also failed (${wsMsg}). ` +
|
|
433
|
+
`Ensure a Chrome/Chromium instance is listening on ${host}:${port} ` +
|
|
434
|
+
`with --remote-debugging-port or a compatible CDP proxy.`,
|
|
435
|
+
{ underlying: wsConnectErr },
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// dispose / abort checks after successful WS connect.
|
|
440
|
+
if (this.disposed) {
|
|
441
|
+
try {
|
|
442
|
+
transport.dispose();
|
|
443
|
+
} catch {
|
|
444
|
+
// best effort
|
|
445
|
+
}
|
|
446
|
+
throw new CdpError(
|
|
447
|
+
"disposed",
|
|
448
|
+
"CdpInspectClient disposed during WS fallback attach",
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
if (signal.aborted) {
|
|
452
|
+
try {
|
|
453
|
+
transport.dispose();
|
|
454
|
+
} catch {
|
|
455
|
+
// best effort
|
|
456
|
+
}
|
|
457
|
+
throw new CdpError(
|
|
458
|
+
"aborted",
|
|
459
|
+
"CdpInspectClient attach aborted during WS fallback",
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Discover targets via CDP Target.getTargets on the browser socket.
|
|
464
|
+
let targets: DevToolsTarget[];
|
|
465
|
+
try {
|
|
466
|
+
targets = await this.helpers.discoverTargetsViaWs({
|
|
467
|
+
transport,
|
|
468
|
+
host,
|
|
469
|
+
port,
|
|
470
|
+
signal,
|
|
471
|
+
});
|
|
472
|
+
} catch (err) {
|
|
473
|
+
try {
|
|
474
|
+
transport.dispose();
|
|
475
|
+
} catch {
|
|
476
|
+
// best effort
|
|
477
|
+
}
|
|
478
|
+
throw err;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (signal.aborted) {
|
|
482
|
+
try {
|
|
483
|
+
transport.dispose();
|
|
484
|
+
} catch {
|
|
485
|
+
// best effort
|
|
486
|
+
}
|
|
487
|
+
throw new CdpError(
|
|
488
|
+
"aborted",
|
|
489
|
+
"CdpInspectClient attach aborted after WS target discovery",
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const target = this.helpers.pickDefaultTarget(targets);
|
|
494
|
+
|
|
495
|
+
log.debug(
|
|
496
|
+
{
|
|
497
|
+
conversationId: this.conversationId,
|
|
498
|
+
targetId: target.id,
|
|
499
|
+
targetCount: targets.length,
|
|
500
|
+
},
|
|
501
|
+
"WS-only fallback: discovered targets via CDP Target.getTargets",
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
// Attach to the selected target using the browser-level transport.
|
|
505
|
+
return this.attachToTarget(transport, target, null, signal);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Shared attach-to-target + session-id extraction logic. Used by both
|
|
510
|
+
* the HTTP discovery path and the WS-only fallback path.
|
|
511
|
+
*/
|
|
512
|
+
private async connectAndAttach(
|
|
513
|
+
wsUrl: string,
|
|
514
|
+
target: DevToolsTarget,
|
|
515
|
+
version: DevToolsVersionInfo | null,
|
|
516
|
+
signal: AbortSignal,
|
|
517
|
+
): Promise<AttachedSession> {
|
|
518
|
+
const transport = await this.helpers.connectCdpWsTransport(wsUrl, {
|
|
519
|
+
connectTimeoutMs: this.options.wsConnectTimeoutMs,
|
|
520
|
+
signal,
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
if (this.disposed) {
|
|
524
|
+
try {
|
|
525
|
+
transport.dispose();
|
|
526
|
+
} catch {
|
|
527
|
+
// best effort
|
|
528
|
+
}
|
|
529
|
+
throw new CdpError("disposed", "CdpInspectClient disposed during attach");
|
|
530
|
+
}
|
|
531
|
+
if (signal.aborted) {
|
|
532
|
+
try {
|
|
533
|
+
transport.dispose();
|
|
534
|
+
} catch {
|
|
535
|
+
// best effort
|
|
536
|
+
}
|
|
537
|
+
throw new CdpError(
|
|
538
|
+
"aborted",
|
|
539
|
+
"CdpInspectClient attach aborted after ws connect",
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
return this.attachToTarget(transport, target, version, signal);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Send `Target.attachToTarget` over the transport and extract the
|
|
548
|
+
* session ID. Disposes the transport on failure so we don't leak
|
|
549
|
+
* sockets.
|
|
550
|
+
*/
|
|
551
|
+
private async attachToTarget(
|
|
552
|
+
transport: CdpWsTransport,
|
|
553
|
+
target: DevToolsTarget,
|
|
554
|
+
version: DevToolsVersionInfo | null,
|
|
555
|
+
signal: AbortSignal,
|
|
556
|
+
): Promise<AttachedSession> {
|
|
557
|
+
let attachResult: unknown;
|
|
558
|
+
try {
|
|
559
|
+
attachResult = await transport.send<unknown>(
|
|
560
|
+
"Target.attachToTarget",
|
|
561
|
+
{
|
|
562
|
+
targetId: target.id,
|
|
563
|
+
flatten: true,
|
|
564
|
+
},
|
|
565
|
+
{ signal },
|
|
566
|
+
);
|
|
567
|
+
} catch (err) {
|
|
568
|
+
try {
|
|
569
|
+
transport.dispose();
|
|
570
|
+
} catch {
|
|
571
|
+
// best effort
|
|
572
|
+
}
|
|
573
|
+
throw err;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
const sessionId = extractSessionId(attachResult);
|
|
577
|
+
if (!sessionId) {
|
|
578
|
+
try {
|
|
579
|
+
transport.dispose();
|
|
580
|
+
} catch {
|
|
581
|
+
// best effort
|
|
582
|
+
}
|
|
583
|
+
throw new CdpError(
|
|
584
|
+
"cdp_error",
|
|
585
|
+
"Target.attachToTarget did not return a sessionId",
|
|
586
|
+
{ cdpMethod: "Target.attachToTarget" },
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
log.debug(
|
|
591
|
+
{
|
|
592
|
+
conversationId: this.conversationId,
|
|
593
|
+
targetId: target.id,
|
|
594
|
+
sessionId,
|
|
595
|
+
discoveryMode: version ? "http" : "ws-only",
|
|
596
|
+
},
|
|
597
|
+
"Attached CdpInspectClient session",
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
return { transport, sessionId, target, version };
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
async send<T = unknown>(
|
|
604
|
+
method: string,
|
|
605
|
+
params?: Record<string, unknown>,
|
|
606
|
+
signal?: AbortSignal,
|
|
607
|
+
): Promise<T> {
|
|
608
|
+
if (this.disposed) {
|
|
609
|
+
throw new CdpError("disposed", "CdpInspectClient already disposed", {
|
|
610
|
+
cdpMethod: method,
|
|
611
|
+
cdpParams: params,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
if (signal?.aborted) {
|
|
615
|
+
throw new CdpError("aborted", "Aborted before send", {
|
|
616
|
+
cdpMethod: method,
|
|
617
|
+
cdpParams: params,
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
let attached: AttachedSession;
|
|
622
|
+
try {
|
|
623
|
+
attached = await this.ensureSession(signal);
|
|
624
|
+
} catch (err) {
|
|
625
|
+
if (signal?.aborted) {
|
|
626
|
+
throw new CdpError("aborted", "Aborted during send", {
|
|
627
|
+
cdpMethod: method,
|
|
628
|
+
cdpParams: params,
|
|
629
|
+
underlying: err,
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
// If a concurrent dispose() aborted the shared attach under us,
|
|
633
|
+
// surface a stable "disposed" error instead of the incidental
|
|
634
|
+
// discovery / transport rejection that the aborted work threw.
|
|
635
|
+
if (this.disposed) {
|
|
636
|
+
throw new CdpError("disposed", "CdpInspectClient already disposed", {
|
|
637
|
+
cdpMethod: method,
|
|
638
|
+
cdpParams: params,
|
|
639
|
+
underlying: err,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
throw mapEnsureSessionError(err, method, params);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// A late dispose may have landed while ensureSession was in
|
|
646
|
+
// flight — surface a "disposed" error instead of sending into a
|
|
647
|
+
// torn-down transport.
|
|
648
|
+
if (this.disposed) {
|
|
649
|
+
throw new CdpError("disposed", "CdpInspectClient already disposed", {
|
|
650
|
+
cdpMethod: method,
|
|
651
|
+
cdpParams: params,
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
try {
|
|
656
|
+
return (await attached.transport.send<T>(method, params, {
|
|
657
|
+
sessionId: attached.sessionId,
|
|
658
|
+
signal,
|
|
659
|
+
})) as T;
|
|
660
|
+
} catch (err) {
|
|
661
|
+
if (signal?.aborted) {
|
|
662
|
+
throw new CdpError("aborted", "Aborted during send", {
|
|
663
|
+
cdpMethod: method,
|
|
664
|
+
cdpParams: params,
|
|
665
|
+
underlying: err,
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
if (err instanceof CdpWsTransportError) {
|
|
669
|
+
if (err.code === "aborted") {
|
|
670
|
+
throw new CdpError("aborted", err.message, {
|
|
671
|
+
cdpMethod: method,
|
|
672
|
+
cdpParams: params,
|
|
673
|
+
underlying: err,
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
if (err.code === "cdp_error") {
|
|
677
|
+
throw new CdpError("cdp_error", err.cdpMessage ?? err.message, {
|
|
678
|
+
cdpMethod: method,
|
|
679
|
+
cdpParams: params,
|
|
680
|
+
underlying: err,
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
// closed / timeout / transport_error all map onto
|
|
684
|
+
// transport_error in the shared CdpClient taxonomy.
|
|
685
|
+
throw new CdpError("transport_error", err.message, {
|
|
686
|
+
cdpMethod: method,
|
|
687
|
+
cdpParams: params,
|
|
688
|
+
underlying: err,
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
if (err instanceof CdpError) {
|
|
692
|
+
throw err;
|
|
693
|
+
}
|
|
694
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
695
|
+
throw new CdpError("cdp_error", msg, {
|
|
696
|
+
cdpMethod: method,
|
|
697
|
+
cdpParams: params,
|
|
698
|
+
underlying: err,
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
dispose(): void {
|
|
704
|
+
if (this.disposed) return;
|
|
705
|
+
this.disposed = true;
|
|
706
|
+
|
|
707
|
+
// Cancel any in-flight attach so discovery / ws / Target.attach
|
|
708
|
+
// stop promptly. The `.then()` handler in startAttach() will
|
|
709
|
+
// tear down any transport that managed to open before dispose
|
|
710
|
+
// landed.
|
|
711
|
+
const pending = this.pending;
|
|
712
|
+
this.pending = null;
|
|
713
|
+
if (pending) {
|
|
714
|
+
try {
|
|
715
|
+
pending.controller.abort();
|
|
716
|
+
} catch {
|
|
717
|
+
// best effort
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
const session = this.session;
|
|
722
|
+
this.session = null;
|
|
723
|
+
if (session) {
|
|
724
|
+
try {
|
|
725
|
+
session.transport.dispose();
|
|
726
|
+
} catch (err) {
|
|
727
|
+
log.debug(
|
|
728
|
+
{ err },
|
|
729
|
+
"CdpInspectClient: transport.dispose threw (ignored)",
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Classify an `ensureSession()` rejection into a stable CdpError
|
|
738
|
+
* code. Discovery + ws-transport failures become `transport_error`,
|
|
739
|
+
* while CDP-level errors returned by `Target.attachToTarget` become
|
|
740
|
+
* `cdp_error`. Already-typed CdpErrors (e.g. a missing-sessionId
|
|
741
|
+
* attach response or a concurrent dispose) are rewritten so that
|
|
742
|
+
* the internal `cdpMethod` (`"Target.attachToTarget"`) is replaced
|
|
743
|
+
* with the caller's method, while preserving the underlying error
|
|
744
|
+
* shape.
|
|
745
|
+
*/
|
|
746
|
+
function mapEnsureSessionError(
|
|
747
|
+
err: unknown,
|
|
748
|
+
method: string,
|
|
749
|
+
params?: Record<string, unknown>,
|
|
750
|
+
): CdpError {
|
|
751
|
+
if (err instanceof CdpError) {
|
|
752
|
+
// Rewrite cdpMethod to the caller's method so attach-stage
|
|
753
|
+
// metadata (e.g. "Target.attachToTarget") doesn't leak into the
|
|
754
|
+
// caller-visible error. Preserve code, message, and the original
|
|
755
|
+
// underlying error so logging / upstream mapping can still
|
|
756
|
+
// introspect the real cause.
|
|
757
|
+
return new CdpError(err.code, err.message, {
|
|
758
|
+
cdpMethod: method,
|
|
759
|
+
cdpParams: params,
|
|
760
|
+
underlying: err.underlying ?? err,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
if (err instanceof CdpWsTransportError) {
|
|
764
|
+
if (err.code === "cdp_error") {
|
|
765
|
+
return new CdpError("cdp_error", err.cdpMessage ?? err.message, {
|
|
766
|
+
cdpMethod: method,
|
|
767
|
+
cdpParams: params,
|
|
768
|
+
underlying: err,
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
return new CdpError("transport_error", err.message, {
|
|
772
|
+
cdpMethod: method,
|
|
773
|
+
cdpParams: params,
|
|
774
|
+
underlying: err,
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
// DevToolsDiscoveryError (and any other non-CDP rejection) is
|
|
778
|
+
// treated as a transport-level failure.
|
|
779
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
780
|
+
return new CdpError("transport_error", msg, {
|
|
781
|
+
cdpMethod: method,
|
|
782
|
+
cdpParams: params,
|
|
783
|
+
underlying: err,
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Race a long-running shared promise against a per-caller
|
|
789
|
+
* {@link AbortSignal}. When the signal fires first, the returned
|
|
790
|
+
* promise rejects with a synthetic `abort` error and the optional
|
|
791
|
+
* `onAbort` hook is invoked exactly once so callers can decrement
|
|
792
|
+
* ref-counts, release locks, etc. The underlying `inner` promise is
|
|
793
|
+
* intentionally NOT cancelled here — shared in-flight work is
|
|
794
|
+
* cancelled separately via the owning {@link PendingAttach}
|
|
795
|
+
* controller once every waiter has given up.
|
|
796
|
+
*/
|
|
797
|
+
function raceAbort<T>(
|
|
798
|
+
inner: Promise<T>,
|
|
799
|
+
signal: AbortSignal | undefined,
|
|
800
|
+
onAbort: () => void,
|
|
801
|
+
): Promise<T> {
|
|
802
|
+
if (!signal) return inner;
|
|
803
|
+
if (signal.aborted) {
|
|
804
|
+
try {
|
|
805
|
+
onAbort();
|
|
806
|
+
} catch {
|
|
807
|
+
// best effort
|
|
808
|
+
}
|
|
809
|
+
return Promise.reject(new Error("aborted"));
|
|
810
|
+
}
|
|
811
|
+
return new Promise<T>((resolve, reject) => {
|
|
812
|
+
let settled = false;
|
|
813
|
+
const handleAbort = () => {
|
|
814
|
+
if (settled) return;
|
|
815
|
+
settled = true;
|
|
816
|
+
try {
|
|
817
|
+
onAbort();
|
|
818
|
+
} catch {
|
|
819
|
+
// best effort
|
|
820
|
+
}
|
|
821
|
+
reject(new Error("aborted"));
|
|
822
|
+
};
|
|
823
|
+
signal.addEventListener("abort", handleAbort, { once: true });
|
|
824
|
+
inner.then(
|
|
825
|
+
(value) => {
|
|
826
|
+
if (settled) return;
|
|
827
|
+
settled = true;
|
|
828
|
+
signal.removeEventListener("abort", handleAbort);
|
|
829
|
+
resolve(value);
|
|
830
|
+
},
|
|
831
|
+
(err) => {
|
|
832
|
+
if (settled) return;
|
|
833
|
+
settled = true;
|
|
834
|
+
signal.removeEventListener("abort", handleAbort);
|
|
835
|
+
reject(err);
|
|
836
|
+
},
|
|
837
|
+
);
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Pull the `sessionId` field out of a `Target.attachToTarget` CDP
|
|
843
|
+
* result. CDP returns an object shaped `{ sessionId: string }`; we
|
|
844
|
+
* guard defensively against malformed replies so a broken Chrome
|
|
845
|
+
* fork cannot silently send us into an un-typed send loop.
|
|
846
|
+
*/
|
|
847
|
+
function extractSessionId(result: unknown): string | null {
|
|
848
|
+
if (!result || typeof result !== "object") return null;
|
|
849
|
+
const record = result as Record<string, unknown>;
|
|
850
|
+
const sessionId = record.sessionId;
|
|
851
|
+
if (typeof sessionId === "string" && sessionId.length > 0) {
|
|
852
|
+
return sessionId;
|
|
853
|
+
}
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Factory for a fresh {@link CdpInspectClient} bound to a
|
|
859
|
+
* conversation. Keeping the constructor + factory split lets the
|
|
860
|
+
* cdp-client factory wires this up alongside local / extension
|
|
861
|
+
* without exposing the class directly to callers.
|
|
862
|
+
*/
|
|
863
|
+
export function createCdpInspectClient(
|
|
864
|
+
conversationId: string,
|
|
865
|
+
options: CdpInspectClientOptions,
|
|
866
|
+
): CdpInspectClient {
|
|
867
|
+
return new CdpInspectClient(conversationId, options);
|
|
868
|
+
}
|