@vellumai/assistant 0.7.1 → 0.7.2
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 +32 -49
- package/Dockerfile +1 -0
- package/README.md +1 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
- package/bun.lock +26 -26
- package/docs/architecture/security.md +20 -0
- package/docs/plugins.md +7 -9
- package/knip.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +39 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
- package/node_modules/@vellumai/service-contracts/package.json +2 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +9 -0
- package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
- package/node_modules/@vellumai/twilio-client/package.json +18 -0
- package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
- package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
- package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
- package/openapi.yaml +565 -12
- package/package.json +6 -3
- package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
- package/src/__tests__/app-bundler.test.ts +170 -1
- package/src/__tests__/app-control-flow.test.ts +374 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
- package/src/__tests__/app-executors.test.ts +30 -43
- package/src/__tests__/approval-routes-http.test.ts +23 -6
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
- package/src/__tests__/assistant-event-hub.test.ts +109 -2
- package/src/__tests__/assistant-event.test.ts +10 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +7 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -7
- package/src/__tests__/background-shell-host-bash.test.ts +14 -15
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
- package/src/__tests__/btw-routes.test.ts +13 -4
- package/src/__tests__/call-controller.test.ts +49 -1
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/channel-readiness-service.test.ts +59 -1
- package/src/__tests__/checker.test.ts +3 -4
- package/src/__tests__/config-loader-backfill.test.ts +90 -155
- package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-lifecycle.test.ts +36 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-slash-commands.test.ts +0 -4
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +317 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
- package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
- package/src/__tests__/credentials-cli.test.ts +5 -12
- package/src/__tests__/cu-unified-flow.test.ts +185 -23
- package/src/__tests__/daemon-credential-client.test.ts +101 -19
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
- package/src/__tests__/heartbeat-service.test.ts +718 -1
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/host-app-control-proxy.test.ts +602 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +246 -47
- package/src/__tests__/host-bash-routes.test.ts +294 -0
- package/src/__tests__/host-browser-proxy.test.ts +24 -22
- package/src/__tests__/host-browser-routes.test.ts +39 -13
- package/src/__tests__/host-cu-proxy.test.ts +41 -52
- package/src/__tests__/host-cu-routes-targeted.test.ts +300 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +339 -0
- package/src/__tests__/host-file-proxy.test.ts +37 -43
- package/src/__tests__/host-file-read-tool.test.ts +17 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +262 -0
- package/src/__tests__/host-file-write-tool.test.ts +42 -1
- package/src/__tests__/host-proxy-base.test.ts +312 -0
- package/src/__tests__/host-shell-tool.test.ts +22 -4
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +583 -0
- package/src/__tests__/host-transfer-proxy.test.ts +121 -22
- package/src/__tests__/host-transfer-routes-targeted.test.ts +447 -0
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +29 -0
- package/src/__tests__/identity-routes.test.ts +103 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
- package/src/__tests__/inline-command-runner.test.ts +0 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
- package/src/__tests__/integration-status.test.ts +85 -5
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/migration-import-commit-http.test.ts +108 -2
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
- package/src/__tests__/prechat-onboarding-contract.test.ts +3 -1
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +97 -0
- package/src/__tests__/require-fresh-approval.test.ts +0 -1
- package/src/__tests__/retry-backoff.test.ts +87 -0
- package/src/__tests__/runtime-events-sse.test.ts +10 -6
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
- package/src/__tests__/skill-feature-flags.test.ts +43 -41
- package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
- package/src/__tests__/skill-load-inline-command.test.ts +0 -51
- package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
- package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +9 -14
- package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-config.test.ts +0 -1
- package/src/__tests__/test-preload.ts +8 -0
- package/src/__tests__/tool-approval-handler.test.ts +3 -4
- package/src/__tests__/tool-audit-listener.test.ts +48 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +3 -16
- package/src/__tests__/twilio-routes.test.ts +3 -5
- package/src/__tests__/twilio-validation.test.ts +93 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
- package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
- package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
- package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- package/src/backup/__tests__/paths.test.ts +0 -22
- package/src/backup/__tests__/restore.test.ts +51 -151
- package/src/backup/paths.ts +2 -18
- package/src/backup/restore.ts +107 -231
- package/src/bundler/app-bundler.ts +51 -3
- package/src/calls/relay-server.ts +4 -44
- package/src/calls/twilio-config.ts +2 -17
- package/src/calls/twilio-rest.ts +33 -105
- package/src/calls/twilio-routes.ts +11 -12
- package/src/channels/types.ts +8 -7
- package/src/cli/commands/__tests__/backup.test.ts +6 -277
- package/src/cli/commands/__tests__/gateway.test.ts +288 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -1
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/clients.ts +36 -37
- package/src/cli/commands/contacts.ts +73 -0
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +15 -7
- package/src/cli/commands/domain.ts +66 -15
- package/src/cli/commands/gateway.ts +183 -0
- package/src/cli/commands/keys.ts +9 -6
- package/src/cli/commands/mcp.ts +116 -156
- package/src/cli/commands/memory-v2.ts +296 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/status.test.ts +13 -15
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +0 -18
- package/src/cli/lib/daemon-credential-client.ts +110 -28
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +67 -10
- package/src/config/bundled-skills/acp/SKILL.md +6 -0
- package/src/config/bundled-skills/acp/TOOLS.json +1 -22
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
- package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
- package/src/config/bundled-skills/app-control/SKILL.md +75 -0
- package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
- package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
- package/src/config/bundled-skills/document/TOOLS.json +0 -8
- package/src/config/bundled-skills/followups/TOOLS.json +0 -12
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
- package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
- package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +19 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
- package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
- package/src/config/bundled-skills/settings/SKILL.md +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +0 -12
- package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
- package/src/config/bundled-skills/subagent/SKILL.md +6 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
- package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
- package/src/config/bundled-tool-registry.ts +21 -0
- package/src/config/env-registry.ts +0 -2
- package/src/config/env.ts +19 -12
- package/src/config/feature-flag-registry.json +21 -133
- package/src/config/loader.ts +73 -99
- package/src/config/sanitize-for-transfer.ts +2 -0
- package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +7 -4
- package/src/config/schemas/calls.ts +0 -9
- package/src/config/schemas/heartbeat.ts +63 -0
- package/src/config/schemas/ingress.ts +10 -6
- package/src/config/schemas/llm.ts +5 -10
- package/src/config/schemas/memory-lifecycle.ts +77 -24
- package/src/config/schemas/memory-v2.ts +48 -4
- package/src/config/schemas/platform.ts +6 -0
- package/src/config/schemas/services.ts +1 -15
- package/src/config/schemas/skills.ts +0 -6
- package/src/config/seed-inference-profiles.ts +1 -1
- package/src/contacts/contact-store.ts +0 -30
- package/src/contacts/contacts-write.ts +0 -27
- package/src/context/window-manager.ts +1 -2
- package/src/credential-execution/feature-gates.ts +10 -10
- package/src/credential-execution/process-manager.ts +12 -41
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +126 -5
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +4 -3
- package/src/daemon/conversation-agent-loop-handlers.ts +21 -3
- package/src/daemon/conversation-agent-loop.ts +32 -28
- package/src/daemon/conversation-lifecycle.ts +8 -1
- package/src/daemon/conversation-process.ts +16 -11
- package/src/daemon/conversation-runtime-assembly.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +125 -4
- package/src/daemon/conversation-tool-setup.ts +16 -55
- package/src/daemon/conversation.ts +21 -2
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/handlers/shared.ts +4 -1
- package/src/daemon/host-app-control-proxy.ts +293 -0
- package/src/daemon/host-bash-proxy.ts +84 -74
- package/src/daemon/host-browser-proxy.ts +67 -82
- package/src/daemon/host-cu-proxy.ts +81 -86
- package/src/daemon/host-file-proxy.ts +93 -69
- package/src/daemon/host-proxy-base.ts +294 -0
- package/src/daemon/host-proxy-preactivation.ts +82 -0
- package/src/daemon/host-transfer-proxy.ts +247 -129
- package/src/daemon/lifecycle.ts +115 -117
- package/src/daemon/message-protocol.ts +3 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +11 -8
- package/src/daemon/message-types/host-app-control.ts +150 -0
- package/src/daemon/message-types/host-bash.ts +4 -0
- package/src/daemon/message-types/host-cu.ts +2 -0
- package/src/daemon/message-types/host-file.ts +4 -0
- package/src/daemon/message-types/host-transfer.ts +3 -0
- package/src/daemon/message-types/schedules.ts +8 -3
- package/src/daemon/message-types/skills.ts +2 -2
- package/src/daemon/process-message.ts +18 -1
- package/src/daemon/shutdown-handlers.ts +0 -3
- package/src/daemon/tool-setup-types.ts +51 -0
- package/src/daemon/tool-side-effects.ts +1 -1
- package/src/events/tool-audit-listener.ts +2 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +15 -7
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +216 -0
- package/src/heartbeat/heartbeat-run-store.ts +236 -0
- package/src/heartbeat/heartbeat-service.ts +280 -49
- package/src/home/__tests__/post-connect-feed.test.ts +99 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
- package/src/home/__tests__/suggested-prompts.test.ts +89 -0
- package/src/home/post-connect-feed.ts +68 -0
- package/src/home/relationship-state-writer.ts +17 -92
- package/src/home/suggested-prompts.ts +46 -10
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/assistant-server.ts +14 -1
- package/src/ipc/cli-client.ts +32 -1
- package/src/live-voice/live-voice-metrics.ts +10 -10
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
- package/src/mcp/mcp-auth-orchestrator.ts +213 -0
- package/src/mcp/mcp-auth-state.ts +133 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
- package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
- package/src/memory/anisotropy.test.ts +247 -0
- package/src/memory/anisotropy.ts +443 -0
- package/src/memory/auto-analysis-constants.ts +17 -0
- package/src/memory/auto-analysis-guard.ts +5 -15
- package/src/memory/canonical-guardian-store.ts +7 -7
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
- package/src/memory/context-search/agent-protocol.ts +6 -6
- package/src/memory/context-search/agent-runner.ts +32 -7
- package/src/memory/context-search/sources/memory-v2.ts +17 -5
- package/src/memory/conversation-crud.ts +1 -1
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/db-init.ts +4 -0
- package/src/memory/embedding-backend.ts +9 -21
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +49 -4
- package/src/memory/graph/conversation-graph-memory.ts +1 -24
- package/src/memory/graph/graph-search.ts +8 -0
- package/src/memory/graph/retriever.ts +28 -0
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
- package/src/memory/jobs/embed-concept-page.ts +28 -2
- package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
- package/src/memory/jobs-store.ts +66 -22
- package/src/memory/jobs-worker.ts +112 -63
- package/src/memory/memory-v2-activation-log-store.ts +1 -1
- package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
- package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +50 -20
- package/src/memory/schema/infrastructure.ts +15 -0
- package/src/memory/search/semantic.ts +7 -0
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/v2/__tests__/activation.test.ts +77 -95
- package/src/memory/v2/__tests__/injection.test.ts +43 -21
- package/src/memory/v2/__tests__/sim.test.ts +166 -6
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +0 -1
- package/src/memory/v2/activation.ts +69 -88
- package/src/memory/v2/consolidation-job.ts +3 -5
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/injection.ts +86 -53
- package/src/memory/v2/prompts/consolidation.ts +312 -91
- package/src/memory/v2/qdrant.ts +99 -1
- package/src/memory/v2/sim.ts +126 -16
- package/src/memory/v2/skill-qdrant.ts +12 -3
- package/src/memory/v2/skill-store.ts +16 -1
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +6 -5
- package/src/messaging/providers/gmail/types.ts +0 -49
- package/src/messaging/providers/slack/adapter.ts +1 -31
- package/src/messaging/providers/slack/types.ts +0 -32
- package/src/notifications/README.md +10 -10
- package/src/notifications/broadcaster.ts +1 -1
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/oauth/connect-orchestrator.ts +4 -0
- package/src/oauth/credential-token-resolver.ts +1 -3
- package/src/oauth/manual-token-connection.ts +0 -4
- package/src/outbound-proxy/index.ts +1 -37
- package/src/outbound-proxy/logging.ts +1 -1
- package/src/outbound-proxy/policy.ts +6 -5
- package/src/outbound-proxy/router.ts +2 -1
- package/src/permissions/approval-policy.test.ts +6 -275
- package/src/permissions/approval-policy.ts +0 -51
- package/src/permissions/checker.test.ts +0 -1
- package/src/permissions/checker.ts +3 -17
- package/src/permissions/gateway-threshold-reader.ts +2 -0
- package/src/permissions/prompter.ts +34 -1
- package/src/permissions/secret-prompter.ts +6 -2
- package/src/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/system-prompt.ts +3 -18
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/runtime/assistant-event-hub.ts +118 -96
- package/src/runtime/assistant-event.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/middleware.ts +0 -96
- package/src/runtime/auth/route-policy.ts +19 -0
- package/src/runtime/btw-sidechain.ts +2 -3
- package/src/runtime/channel-invite-transport.ts +2 -48
- package/src/runtime/channel-invite-transports/email.ts +1 -1
- package/src/runtime/channel-invite-transports/slack.ts +1 -1
- package/src/runtime/channel-invite-transports/telegram.ts +1 -1
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
- package/src/runtime/channel-invite-types.ts +54 -0
- package/src/runtime/channel-readiness-service.ts +32 -13
- package/src/runtime/http-server.ts +3 -329
- package/src/runtime/http-types.ts +0 -5
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
- package/src/runtime/migrations/migration-transport.ts +7 -7
- package/src/runtime/migrations/vbundle-builder.ts +327 -60
- package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
- package/src/runtime/migrations/vbundle-importer.ts +245 -68
- package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
- package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
- package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
- package/src/runtime/migrations/vbundle-validator.ts +114 -0
- package/src/runtime/pending-interactions.ts +35 -9
- package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
- package/src/runtime/routes/approval-interception-types.ts +13 -0
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
- package/src/runtime/routes/backup-routes.ts +15 -38
- package/src/runtime/routes/btw-routes.ts +14 -37
- package/src/runtime/routes/client-routes.ts +1 -0
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/conversation-query-routes.ts +36 -1
- package/src/runtime/routes/conversation-routes.ts +30 -13
- package/src/runtime/routes/document-pdf-renderer.ts +165 -0
- package/src/runtime/routes/documents-routes.ts +30 -0
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +12 -6
- package/src/runtime/routes/gateway-log-routes.ts +79 -0
- package/src/runtime/routes/guardian-approval-interception.ts +2 -8
- package/src/runtime/routes/heartbeat-routes.ts +103 -38
- package/src/runtime/routes/host-app-control-routes.ts +134 -0
- package/src/runtime/routes/host-bash-routes.ts +36 -6
- package/src/runtime/routes/host-browser-routes.ts +108 -13
- package/src/runtime/routes/host-cu-routes.ts +44 -14
- package/src/runtime/routes/host-file-routes.ts +33 -10
- package/src/runtime/routes/host-transfer-routes.ts +64 -24
- package/src/runtime/routes/http-adapter.ts +1 -0
- package/src/runtime/routes/identity-intro-cache.ts +30 -0
- package/src/runtime/routes/identity-routes.ts +15 -43
- package/src/runtime/routes/inbound-message-handler.ts +1 -9
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +441 -1
- package/src/runtime/routes/migration-routes.ts +96 -0
- package/src/runtime/routes/schedule-routes.ts +7 -0
- package/src/runtime/verification-templates.ts +4 -7
- package/src/schedule/integration-status.ts +66 -2
- package/src/schedule/recurrence-engine.ts +4 -1
- package/src/schedule/retry-backoff.ts +18 -0
- package/src/schedule/retry-policy.ts +82 -0
- package/src/schedule/schedule-recovery.ts +64 -0
- package/src/schedule/schedule-store.ts +106 -2
- package/src/schedule/scheduler-types.ts +25 -0
- package/src/schedule/scheduler.ts +63 -38
- package/src/security/oauth-callback-registry.ts +8 -0
- package/src/sequence/analytics.ts +5 -5
- package/src/sequence/engine.ts +1 -1
- package/src/skills/catalog-files.ts +2 -8
- package/src/skills/include-graph.ts +5 -5
- package/src/skills/remote-skill-policy.ts +5 -5
- package/src/skills/skill-file-provider.ts +1 -1
- package/src/skills/skill-file-types.ts +13 -0
- package/src/skills/skillssh-audit-types.ts +28 -0
- package/src/skills/skillssh-registry.ts +8 -21
- package/src/telemetry/types.ts +2 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
- package/src/tools/apps/executors.ts +56 -69
- package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
- package/src/tools/browser/browser-execution.ts +2 -2
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
- package/src/tools/browser/cdp-client/factory.ts +23 -24
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/computer-use/definitions.ts +42 -20
- package/src/tools/executor.ts +2 -0
- package/src/tools/host-filesystem/edit.ts +26 -0
- package/src/tools/host-filesystem/read.ts +26 -0
- package/src/tools/host-filesystem/transfer.ts +31 -1
- package/src/tools/host-filesystem/write.ts +26 -0
- package/src/tools/host-terminal/host-shell.ts +58 -0
- package/src/tools/schedule/create.ts +6 -0
- package/src/tools/schedule/list.ts +2 -0
- package/src/tools/schedule/update.ts +10 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
- package/src/tools/shared/filesystem/path-policy.ts +25 -1
- package/src/tools/skills/load.ts +0 -32
- package/src/tools/tool-approval-handler.ts +1 -5
- package/src/tools/types.ts +4 -0
- package/src/usage/pricing.ts +1 -1
- package/src/workspace/hatched-date.ts +86 -0
- package/src/workspace/migrations/003-seed-device-id.ts +1 -1
- package/src/workspace/migrations/006-services-config.ts +8 -5
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/utils.ts +21 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
- package/src/__tests__/twilio-rest.test.ts +0 -34
- package/src/backup/__tests__/backup-key.test.ts +0 -152
- package/src/backup/__tests__/backup-worker.test.ts +0 -782
- package/src/backup/__tests__/offsite-writer.test.ts +0 -641
- package/src/backup/__tests__/stream-crypt.test.ts +0 -228
- package/src/backup/backup-key.ts +0 -137
- package/src/backup/backup-worker.ts +0 -472
- package/src/backup/offsite-writer.ts +0 -222
- package/src/backup/stream-crypt.ts +0 -263
- package/src/daemon/message-types/pairing.ts +0 -58
- package/src/outbound-proxy/config.ts +0 -20
- package/src/outbound-proxy/health.ts +0 -18
- package/src/outbound-proxy/types.ts +0 -150
- package/src/runtime/capability-tokens.ts +0 -190
- package/src/signals/mcp-reload.ts +0 -18
|
@@ -10,19 +10,9 @@ import { formatShellOutput } from "../tools/shared/shell-output.js";
|
|
|
10
10
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
11
11
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
12
12
|
import { getLogger } from "../util/logger.js";
|
|
13
|
-
import type { ServerMessage } from "./message-protocol.js";
|
|
14
13
|
|
|
15
14
|
const log = getLogger("host-bash-proxy");
|
|
16
15
|
|
|
17
|
-
interface PendingRequest {
|
|
18
|
-
resolve: (result: ToolExecutionResult) => void;
|
|
19
|
-
reject: (err: Error) => void;
|
|
20
|
-
timer: ReturnType<typeof setTimeout>;
|
|
21
|
-
timeoutSec: number;
|
|
22
|
-
conversationId: string;
|
|
23
|
-
/** Detach the abort listener from the caller's signal. No-op when no signal was passed. */
|
|
24
|
-
detachAbort: () => void;
|
|
25
|
-
}
|
|
26
16
|
|
|
27
17
|
export class HostBashProxy {
|
|
28
18
|
private static _instance: HostBashProxy | null = null;
|
|
@@ -53,8 +43,6 @@ export class HostBashProxy {
|
|
|
53
43
|
HostBashProxy._instance = null;
|
|
54
44
|
}
|
|
55
45
|
|
|
56
|
-
private pending = new Map<string, PendingRequest>();
|
|
57
|
-
|
|
58
46
|
/**
|
|
59
47
|
* Whether a client with `host_bash` capability is connected.
|
|
60
48
|
*/
|
|
@@ -64,16 +52,13 @@ export class HostBashProxy {
|
|
|
64
52
|
);
|
|
65
53
|
}
|
|
66
54
|
|
|
67
|
-
private send(msg: ServerMessage): void {
|
|
68
|
-
broadcastMessage(msg, undefined, { targetCapability: "host_bash" });
|
|
69
|
-
}
|
|
70
|
-
|
|
71
55
|
request(
|
|
72
56
|
input: {
|
|
73
57
|
command: string;
|
|
74
58
|
working_dir?: string;
|
|
75
59
|
timeout_seconds?: number;
|
|
76
60
|
env?: Record<string, string>;
|
|
61
|
+
targetClientId?: string;
|
|
77
62
|
},
|
|
78
63
|
conversationId: string,
|
|
79
64
|
signal?: AbortSignal,
|
|
@@ -83,30 +68,50 @@ export class HostBashProxy {
|
|
|
83
68
|
return Promise.resolve(result);
|
|
84
69
|
}
|
|
85
70
|
|
|
71
|
+
const capableClients = assistantEventHub.listClientsByCapability("host_bash");
|
|
72
|
+
|
|
73
|
+
let resolvedTargetClientId: string | undefined;
|
|
74
|
+
|
|
75
|
+
if (input.targetClientId) {
|
|
76
|
+
const target = assistantEventHub.getClientById(input.targetClientId);
|
|
77
|
+
if (!target || !target.capabilities.includes("host_bash")) {
|
|
78
|
+
return Promise.resolve({
|
|
79
|
+
content: `Error: client "${input.targetClientId}" is not connected or does not support host_bash. Run \`assistant clients list --capability host_bash\` to see available clients.`,
|
|
80
|
+
isError: true,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
resolvedTargetClientId = input.targetClientId;
|
|
84
|
+
} else if (capableClients.length === 1) {
|
|
85
|
+
// Auto-resolve when exactly one capable client is connected.
|
|
86
|
+
resolvedTargetClientId = capableClients[0].clientId;
|
|
87
|
+
}
|
|
88
|
+
// capableClients.length === 0 or > 1 without explicit target: resolvedTargetClientId
|
|
89
|
+
// stays undefined and falls through to untargeted broadcast — the existing timeout/error
|
|
90
|
+
// path handles the zero-client case, and multi-client ambiguity is enforced at the tool
|
|
91
|
+
// executor layer (not here) once target_client_id is exposed in the tool schema.
|
|
92
|
+
|
|
86
93
|
const requestId = uuid();
|
|
87
94
|
|
|
88
95
|
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
89
96
|
const shellMaxTimeoutSec = getConfig().timeouts.shellMaxTimeoutSec;
|
|
90
97
|
const timeoutSec = input.timeout_seconds ?? shellMaxTimeoutSec;
|
|
91
|
-
// Proxy timeout: slightly after client-side timeout, but before executor's outer timeout
|
|
92
98
|
const proxyTimeoutSec = timeoutSec + 3;
|
|
93
99
|
|
|
94
|
-
// Declared up-front so onAbort (defined before detachAbort is assigned)
|
|
95
|
-
// can close over a stable reference once it's wired below.
|
|
96
100
|
let detachAbort: () => void = () => {};
|
|
97
101
|
|
|
98
102
|
const timer = setTimeout(() => {
|
|
99
|
-
this.pending.delete(requestId);
|
|
100
|
-
detachAbort();
|
|
101
103
|
pendingInteractions.resolve(requestId);
|
|
102
104
|
log.warn(
|
|
103
105
|
{ requestId, command: input.command },
|
|
104
106
|
"Host bash proxy request timed out",
|
|
105
107
|
);
|
|
108
|
+
const timeoutMessage = resolvedTargetClientId
|
|
109
|
+
? `Host bash proxy timed out waiting for response from client ${resolvedTargetClientId}`
|
|
110
|
+
: "Host bash proxy timed out waiting for client response";
|
|
106
111
|
resolve(
|
|
107
112
|
formatShellOutput(
|
|
108
113
|
"",
|
|
109
|
-
|
|
114
|
+
timeoutMessage,
|
|
110
115
|
null,
|
|
111
116
|
true,
|
|
112
117
|
timeoutSec,
|
|
@@ -116,19 +121,21 @@ export class HostBashProxy {
|
|
|
116
121
|
|
|
117
122
|
if (signal) {
|
|
118
123
|
const onAbort = () => {
|
|
119
|
-
if (
|
|
120
|
-
clearTimeout(timer);
|
|
121
|
-
this.pending.delete(requestId);
|
|
122
|
-
detachAbort();
|
|
124
|
+
if (pendingInteractions.get(requestId)) {
|
|
123
125
|
pendingInteractions.resolve(requestId);
|
|
124
126
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
broadcastMessage(
|
|
128
|
+
{
|
|
129
|
+
type: "host_bash_cancel",
|
|
130
|
+
requestId,
|
|
131
|
+
conversationId,
|
|
132
|
+
targetClientId: resolvedTargetClientId,
|
|
133
|
+
},
|
|
128
134
|
conversationId,
|
|
129
|
-
|
|
135
|
+
{ targetClientId: resolvedTargetClientId },
|
|
136
|
+
);
|
|
130
137
|
} catch {
|
|
131
|
-
// Best-effort cancel notification
|
|
138
|
+
// Best-effort cancel notification
|
|
132
139
|
}
|
|
133
140
|
resolve(formatShellOutput("", "Aborted", null, false, 0));
|
|
134
141
|
}
|
|
@@ -137,31 +144,35 @@ export class HostBashProxy {
|
|
|
137
144
|
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
138
145
|
}
|
|
139
146
|
|
|
140
|
-
|
|
141
|
-
resolve,
|
|
142
|
-
reject,
|
|
143
|
-
timer,
|
|
144
|
-
timeoutSec,
|
|
147
|
+
pendingInteractions.register(requestId, {
|
|
145
148
|
conversationId,
|
|
149
|
+
kind: "host_bash",
|
|
150
|
+
rpcResolve: resolve,
|
|
151
|
+
rpcReject: reject,
|
|
152
|
+
timer,
|
|
146
153
|
detachAbort,
|
|
154
|
+
targetClientId: resolvedTargetClientId,
|
|
155
|
+
metadata: { timeoutSec },
|
|
147
156
|
});
|
|
148
157
|
|
|
149
158
|
try {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
broadcastMessage(
|
|
160
|
+
{
|
|
161
|
+
type: "host_bash_request",
|
|
162
|
+
requestId,
|
|
163
|
+
conversationId,
|
|
164
|
+
command: input.command,
|
|
165
|
+
working_dir: input.working_dir,
|
|
166
|
+
timeout_seconds: input.timeout_seconds,
|
|
167
|
+
targetClientId: resolvedTargetClientId,
|
|
168
|
+
...(input.env && Object.keys(input.env).length > 0
|
|
169
|
+
? { env: input.env }
|
|
170
|
+
: {}),
|
|
171
|
+
},
|
|
153
172
|
conversationId,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
timeout_seconds: input.timeout_seconds,
|
|
157
|
-
...(input.env && Object.keys(input.env).length > 0
|
|
158
|
-
? { env: input.env }
|
|
159
|
-
: {}),
|
|
160
|
-
});
|
|
173
|
+
{ targetClientId: resolvedTargetClientId },
|
|
174
|
+
);
|
|
161
175
|
} catch (err) {
|
|
162
|
-
clearTimeout(timer);
|
|
163
|
-
this.pending.delete(requestId);
|
|
164
|
-
detachAbort();
|
|
165
176
|
pendingInteractions.resolve(requestId);
|
|
166
177
|
log.warn(
|
|
167
178
|
{ requestId, command: input.command, err },
|
|
@@ -172,7 +183,10 @@ export class HostBashProxy {
|
|
|
172
183
|
});
|
|
173
184
|
}
|
|
174
185
|
|
|
175
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Process a client result and resolve the RPC. Called by route handlers.
|
|
188
|
+
*/
|
|
189
|
+
resolveResult(
|
|
176
190
|
requestId: string,
|
|
177
191
|
response: {
|
|
178
192
|
stdout: string;
|
|
@@ -181,49 +195,45 @@ export class HostBashProxy {
|
|
|
181
195
|
timedOut: boolean;
|
|
182
196
|
},
|
|
183
197
|
): void {
|
|
184
|
-
const
|
|
185
|
-
if (!
|
|
198
|
+
const interaction = pendingInteractions.resolve(requestId);
|
|
199
|
+
if (!interaction?.rpcResolve) {
|
|
186
200
|
log.warn({ requestId }, "No pending host bash request for response");
|
|
187
201
|
return;
|
|
188
202
|
}
|
|
189
|
-
|
|
190
|
-
entry.detachAbort();
|
|
191
|
-
this.pending.delete(requestId);
|
|
203
|
+
const timeoutSec = (interaction.metadata?.timeoutSec as number) ?? 0;
|
|
192
204
|
const result = formatShellOutput(
|
|
193
205
|
response.stdout,
|
|
194
206
|
response.stderr,
|
|
195
207
|
response.exitCode,
|
|
196
208
|
response.timedOut,
|
|
197
|
-
|
|
209
|
+
timeoutSec,
|
|
198
210
|
);
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
hasPendingRequest(requestId: string): boolean {
|
|
203
|
-
return this.pending.has(requestId);
|
|
211
|
+
interaction.rpcResolve(result);
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
dispose(): void {
|
|
207
|
-
for (const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
this.send({
|
|
215
|
+
for (const entry of pendingInteractions.getByKind("host_bash")) {
|
|
216
|
+
pendingInteractions.resolve(entry.requestId);
|
|
217
|
+
try {
|
|
218
|
+
broadcastMessage(
|
|
219
|
+
{
|
|
213
220
|
type: "host_bash_cancel",
|
|
214
|
-
requestId,
|
|
221
|
+
requestId: entry.requestId,
|
|
215
222
|
conversationId: entry.conversationId,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
223
|
+
targetClientId: entry.targetClientId,
|
|
224
|
+
},
|
|
225
|
+
entry.conversationId,
|
|
226
|
+
{ targetClientId: entry.targetClientId },
|
|
227
|
+
);
|
|
228
|
+
} catch {
|
|
229
|
+
// Best-effort cancel notification — connection may already be closed.
|
|
230
|
+
}
|
|
231
|
+
entry.rpcReject?.(
|
|
221
232
|
new AssistantError(
|
|
222
233
|
"Host bash proxy disposed",
|
|
223
234
|
ErrorCode.INTERNAL_ERROR,
|
|
224
235
|
),
|
|
225
236
|
);
|
|
226
237
|
}
|
|
227
|
-
this.pending.clear();
|
|
228
238
|
}
|
|
229
239
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { v4 as uuid } from "uuid";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import type { InterfaceId } from "../channels/types.js";
|
|
4
|
+
import {
|
|
5
|
+
assistantEventHub,
|
|
6
|
+
broadcastMessage,
|
|
7
|
+
} from "../runtime/assistant-event-hub.js";
|
|
8
|
+
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
5
9
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
6
10
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
7
11
|
import { getLogger } from "../util/logger.js";
|
|
8
|
-
import type { ServerMessage } from "./message-protocol.js";
|
|
9
12
|
import type { HostBrowserRequest } from "./message-types/host-browser.js";
|
|
10
13
|
|
|
11
14
|
/** Distributive omit that preserves union variant fields. */
|
|
@@ -21,13 +24,11 @@ export type HostBrowserInput = DistributiveOmit<
|
|
|
21
24
|
|
|
22
25
|
const log = getLogger("host-browser-proxy");
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
detachAbort: () => void;
|
|
30
|
-
}
|
|
27
|
+
/** Interface priority order for host_browser: Chrome Extension first, macOS SSE bridge second. */
|
|
28
|
+
const HOST_BROWSER_INTERFACE_PREFERENCE: InterfaceId[] = [
|
|
29
|
+
"chrome-extension",
|
|
30
|
+
"macos",
|
|
31
|
+
];
|
|
31
32
|
|
|
32
33
|
export class HostBrowserProxy {
|
|
33
34
|
private static _instance: HostBrowserProxy | null = null;
|
|
@@ -58,29 +59,29 @@ export class HostBrowserProxy {
|
|
|
58
59
|
HostBrowserProxy._instance = null;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
private pending = new Map<string, PendingRequest>();
|
|
62
|
-
|
|
63
62
|
/**
|
|
64
63
|
* Whether a client with `host_browser` capability is connected.
|
|
64
|
+
* Returns `true` when either the Chrome Extension or the macOS SSE
|
|
65
|
+
* bridge is available — i.e. any transport can forward host-browser
|
|
66
|
+
* requests.
|
|
65
67
|
*/
|
|
66
68
|
isAvailable(): boolean {
|
|
67
69
|
return (
|
|
68
|
-
assistantEventHub.
|
|
70
|
+
assistantEventHub.getPreferredClientByCapability(
|
|
71
|
+
"host_browser",
|
|
72
|
+
HOST_BROWSER_INTERFACE_PREFERENCE,
|
|
73
|
+
) != null
|
|
69
74
|
);
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
78
|
+
* Whether a Chrome Extension client specifically is connected.
|
|
79
|
+
* Returns `false` when only the macOS SSE bridge is available.
|
|
80
|
+
* Unlike {@link isAvailable}, this does not consider the macOS bridge
|
|
81
|
+
* a valid extension transport.
|
|
75
82
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.publish(buildAssistantEvent(msg), {
|
|
79
|
-
targetCapability: "host_browser",
|
|
80
|
-
})
|
|
81
|
-
.catch((err) => {
|
|
82
|
-
log.warn({ err }, "failed to publish host_browser event to hub");
|
|
83
|
-
});
|
|
83
|
+
hasExtensionClient(): boolean {
|
|
84
|
+
return assistantEventHub.listClientsByInterface("chrome-extension").length > 0;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
request(
|
|
@@ -95,42 +96,34 @@ export class HostBrowserProxy {
|
|
|
95
96
|
const requestId = uuid();
|
|
96
97
|
|
|
97
98
|
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
98
|
-
// CDP operations should be fast — 30 second default timeout matches host_file.
|
|
99
99
|
const timeoutSec = input.timeout_seconds ?? 30;
|
|
100
100
|
|
|
101
|
-
// Declared up-front so onAbort (defined before detachAbort is assigned)
|
|
102
|
-
// can close over a stable reference once it's wired below.
|
|
103
101
|
let detachAbort: () => void = () => {};
|
|
104
102
|
|
|
105
103
|
const timer = setTimeout(() => {
|
|
106
|
-
|
|
107
|
-
detachAbort();
|
|
104
|
+
pendingInteractions.resolve(requestId);
|
|
108
105
|
log.warn(
|
|
109
106
|
{ requestId, cdpMethod: input.cdpMethod },
|
|
110
107
|
"Host browser proxy request timed out",
|
|
111
108
|
);
|
|
112
109
|
resolve({
|
|
113
110
|
content:
|
|
114
|
-
"Host browser proxy timed out waiting for extension response (check
|
|
111
|
+
"Host browser proxy timed out waiting for extension response (check SSE connectivity and /v1/host-browser-result callback failures such as 404/401).",
|
|
115
112
|
isError: true,
|
|
116
113
|
});
|
|
117
114
|
}, timeoutSec * 1000);
|
|
118
115
|
|
|
119
116
|
if (signal) {
|
|
120
117
|
const onAbort = () => {
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
this.pending.delete(requestId);
|
|
124
|
-
// Abort fired — nothing to detach, but call the no-op for symmetry
|
|
125
|
-
// so callers can rely on detachAbort being idempotent.
|
|
126
|
-
detachAbort();
|
|
118
|
+
if (pendingInteractions.get(requestId)) {
|
|
119
|
+
pendingInteractions.resolve(requestId);
|
|
127
120
|
try {
|
|
128
|
-
|
|
121
|
+
broadcastMessage({
|
|
129
122
|
type: "host_browser_cancel",
|
|
130
123
|
requestId,
|
|
131
|
-
}
|
|
124
|
+
});
|
|
132
125
|
} catch {
|
|
133
|
-
// Best-effort cancel notification
|
|
126
|
+
// Best-effort cancel notification
|
|
134
127
|
}
|
|
135
128
|
resolve({ content: "Aborted", isError: true });
|
|
136
129
|
}
|
|
@@ -139,13 +132,22 @@ export class HostBrowserProxy {
|
|
|
139
132
|
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
140
133
|
}
|
|
141
134
|
|
|
142
|
-
|
|
135
|
+
pendingInteractions.register(requestId, {
|
|
136
|
+
conversationId,
|
|
137
|
+
kind: "host_browser",
|
|
138
|
+
rpcResolve: resolve,
|
|
139
|
+
rpcReject: reject,
|
|
140
|
+
timer,
|
|
141
|
+
detachAbort,
|
|
142
|
+
});
|
|
143
143
|
|
|
144
144
|
try {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
const preferredClient = assistantEventHub.getPreferredClientByCapability(
|
|
146
|
+
"host_browser",
|
|
147
|
+
HOST_BROWSER_INTERFACE_PREFERENCE,
|
|
148
|
+
);
|
|
149
|
+
if (!preferredClient) {
|
|
150
|
+
pendingInteractions.resolve(requestId);
|
|
149
151
|
reject(
|
|
150
152
|
new Error(
|
|
151
153
|
"host_browser send failed: no active extension connection",
|
|
@@ -154,19 +156,13 @@ export class HostBrowserProxy {
|
|
|
154
156
|
return;
|
|
155
157
|
}
|
|
156
158
|
|
|
157
|
-
|
|
158
|
-
...input,
|
|
159
|
-
type: "host_browser_request",
|
|
160
|
-
requestId,
|
|
159
|
+
broadcastMessage(
|
|
160
|
+
{ ...input, type: "host_browser_request", requestId, conversationId },
|
|
161
161
|
conversationId,
|
|
162
|
-
|
|
162
|
+
{ targetClientId: preferredClient.clientId },
|
|
163
|
+
);
|
|
163
164
|
} catch (err) {
|
|
164
|
-
|
|
165
|
-
// event emission). Clean up pending state and timer so we don't
|
|
166
|
-
// leak an in-flight entry that nothing will ever resolve.
|
|
167
|
-
clearTimeout(timer);
|
|
168
|
-
this.pending.delete(requestId);
|
|
169
|
-
detachAbort();
|
|
165
|
+
pendingInteractions.resolve(requestId);
|
|
170
166
|
log.warn(
|
|
171
167
|
{ requestId, cdpMethod: input.cdpMethod, err },
|
|
172
168
|
"Host browser proxy send failed",
|
|
@@ -176,55 +172,44 @@ export class HostBrowserProxy {
|
|
|
176
172
|
});
|
|
177
173
|
}
|
|
178
174
|
|
|
179
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Process a client result and resolve the RPC. Called by route handlers.
|
|
177
|
+
*/
|
|
178
|
+
resolveResult(
|
|
180
179
|
requestId: string,
|
|
181
180
|
response: { content: string; isError: boolean },
|
|
182
181
|
): void {
|
|
183
|
-
const
|
|
184
|
-
if (!
|
|
185
|
-
// Benign race, not an error. A late result frame with no matching
|
|
186
|
-
// pending entry means one of:
|
|
187
|
-
// - the proxy-side setTimeout has already resolved the caller;
|
|
188
|
-
// - the caller's AbortSignal fired and the entry was torn down;
|
|
189
|
-
// - a duplicate result frame was delivered (e.g. retry after a
|
|
190
|
-
// transient WS drop).
|
|
191
|
-
// Log at debug so operators don't chase false-positive "timeout"
|
|
192
|
-
// alerts on what is actually a cleanly-handled race.
|
|
182
|
+
const interaction = pendingInteractions.resolve(requestId);
|
|
183
|
+
if (!interaction?.rpcResolve) {
|
|
193
184
|
log.debug(
|
|
194
185
|
{ requestId },
|
|
195
186
|
"Ignoring host_browser_result for unknown or already-resolved request",
|
|
196
187
|
);
|
|
197
188
|
return;
|
|
198
189
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
hasPendingRequest(requestId: string): boolean {
|
|
206
|
-
return this.pending.has(requestId);
|
|
190
|
+
interaction.rpcResolve({
|
|
191
|
+
content: response.content,
|
|
192
|
+
isError: response.isError,
|
|
193
|
+
});
|
|
207
194
|
}
|
|
208
195
|
|
|
209
196
|
dispose(): void {
|
|
210
|
-
for (const
|
|
211
|
-
|
|
212
|
-
entry.detachAbort();
|
|
197
|
+
for (const entry of pendingInteractions.getByKind("host_browser")) {
|
|
198
|
+
pendingInteractions.resolve(entry.requestId);
|
|
213
199
|
try {
|
|
214
|
-
|
|
200
|
+
broadcastMessage({
|
|
215
201
|
type: "host_browser_cancel",
|
|
216
|
-
requestId,
|
|
217
|
-
}
|
|
202
|
+
requestId: entry.requestId,
|
|
203
|
+
});
|
|
218
204
|
} catch {
|
|
219
|
-
// Best-effort cancel notification
|
|
205
|
+
// Best-effort cancel notification
|
|
220
206
|
}
|
|
221
|
-
entry.
|
|
207
|
+
entry.rpcReject?.(
|
|
222
208
|
new AssistantError(
|
|
223
209
|
"Host browser proxy disposed",
|
|
224
210
|
ErrorCode.INTERNAL_ERROR,
|
|
225
211
|
),
|
|
226
212
|
);
|
|
227
213
|
}
|
|
228
|
-
this.pending.clear();
|
|
229
214
|
}
|
|
230
215
|
}
|