@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
package/src/calls/twilio-rest.ts
CHANGED
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
* config handler. Uses fetch() directly — no twilio npm package.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import {
|
|
10
|
+
lookupIncomingPhoneNumberSid,
|
|
11
|
+
twilioAuthHeader,
|
|
12
|
+
twilioBaseUrl,
|
|
13
|
+
TwilioRestError,
|
|
14
|
+
type TwilioWebhookUrls,
|
|
15
|
+
updatePhoneNumberWebhooks as updateTwilioPhoneNumberWebhooks,
|
|
16
|
+
} from "@vellumai/twilio-client";
|
|
17
|
+
|
|
9
18
|
import { loadConfig } from "../config/loader.js";
|
|
10
19
|
import { credentialKey } from "../security/credential-key.js";
|
|
11
20
|
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
@@ -56,20 +65,7 @@ export async function hasTwilioCredentials(): Promise<boolean> {
|
|
|
56
65
|
}
|
|
57
66
|
}
|
|
58
67
|
|
|
59
|
-
|
|
60
|
-
export function twilioAuthHeader(
|
|
61
|
-
accountSid: string,
|
|
62
|
-
authToken: string,
|
|
63
|
-
): string {
|
|
64
|
-
return (
|
|
65
|
-
"Basic " + Buffer.from(`${accountSid}:${authToken}`).toString("base64")
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Build the Twilio REST API base URL for a given account. */
|
|
70
|
-
export function twilioBaseUrl(accountSid: string): string {
|
|
71
|
-
return `https://api.twilio.com/2010-04-01/Accounts/${accountSid}`;
|
|
72
|
-
}
|
|
68
|
+
export { twilioAuthHeader, twilioBaseUrl };
|
|
73
69
|
|
|
74
70
|
export interface TwilioPhoneNumber {
|
|
75
71
|
phoneNumber: string;
|
|
@@ -210,9 +206,13 @@ export async function provisionPhoneNumber(
|
|
|
210
206
|
};
|
|
211
207
|
}
|
|
212
208
|
|
|
213
|
-
export
|
|
214
|
-
|
|
215
|
-
|
|
209
|
+
export type WebhookUrls = TwilioWebhookUrls;
|
|
210
|
+
|
|
211
|
+
function rethrowAsProviderError(err: unknown): never {
|
|
212
|
+
if (err instanceof TwilioRestError) {
|
|
213
|
+
throw new ProviderError(err.message, "twilio", err.status);
|
|
214
|
+
}
|
|
215
|
+
throw err;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
/**
|
|
@@ -227,69 +227,15 @@ export async function updatePhoneNumberWebhooks(
|
|
|
227
227
|
phoneNumber: string,
|
|
228
228
|
webhooks: WebhookUrls,
|
|
229
229
|
): Promise<void> {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
`${twilioBaseUrl(
|
|
230
|
+
try {
|
|
231
|
+
await updateTwilioPhoneNumberWebhooks({
|
|
233
232
|
accountSid,
|
|
234
|
-
|
|
233
|
+
authToken,
|
|
235
234
|
phoneNumber,
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
},
|
|
241
|
-
);
|
|
242
|
-
|
|
243
|
-
if (!listRes.ok) {
|
|
244
|
-
const text = await listRes.text();
|
|
245
|
-
throw new ProviderError(
|
|
246
|
-
`Twilio API error ${listRes.status} looking up phone number: ${text}`,
|
|
247
|
-
"twilio",
|
|
248
|
-
listRes.status,
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const listData = (await listRes.json()) as {
|
|
253
|
-
incoming_phone_numbers: Array<{ sid: string; phone_number: string }>;
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
const match = listData.incoming_phone_numbers.find(
|
|
257
|
-
(n) => n.phone_number === phoneNumber,
|
|
258
|
-
);
|
|
259
|
-
if (!match) {
|
|
260
|
-
throw new ProviderError(
|
|
261
|
-
`Phone number ${phoneNumber} not found on Twilio account ${accountSid}`,
|
|
262
|
-
"twilio",
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Update the phone number's webhook configuration
|
|
267
|
-
const body = new URLSearchParams({
|
|
268
|
-
VoiceUrl: webhooks.voiceUrl,
|
|
269
|
-
VoiceMethod: "POST",
|
|
270
|
-
StatusCallback: webhooks.statusCallbackUrl,
|
|
271
|
-
StatusCallbackMethod: "POST",
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
const updateRes = await fetch(
|
|
275
|
-
`${twilioBaseUrl(accountSid)}/IncomingPhoneNumbers/${match.sid}.json`,
|
|
276
|
-
{
|
|
277
|
-
method: "POST",
|
|
278
|
-
headers: {
|
|
279
|
-
Authorization: twilioAuthHeader(accountSid, authToken),
|
|
280
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
281
|
-
},
|
|
282
|
-
body: body.toString(),
|
|
283
|
-
},
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
if (!updateRes.ok) {
|
|
287
|
-
const text = await updateRes.text();
|
|
288
|
-
throw new ProviderError(
|
|
289
|
-
`Twilio API error ${updateRes.status} updating webhooks: ${text}`,
|
|
290
|
-
"twilio",
|
|
291
|
-
updateRes.status,
|
|
292
|
-
);
|
|
235
|
+
webhooks,
|
|
236
|
+
});
|
|
237
|
+
} catch (err) {
|
|
238
|
+
rethrowAsProviderError(err);
|
|
293
239
|
}
|
|
294
240
|
}
|
|
295
241
|
|
|
@@ -302,35 +248,17 @@ async function getPhoneNumberSid(
|
|
|
302
248
|
authToken: string,
|
|
303
249
|
phoneNumber: string,
|
|
304
250
|
): Promise<string | null> {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
method: "GET",
|
|
313
|
-
headers: { Authorization: twilioAuthHeader(accountSid, authToken) },
|
|
314
|
-
},
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
if (!res.ok) {
|
|
318
|
-
const text = await res.text();
|
|
319
|
-
throw new ProviderError(
|
|
320
|
-
`Twilio API error ${res.status} looking up phone number SID: ${text}`,
|
|
321
|
-
"twilio",
|
|
322
|
-
res.status,
|
|
251
|
+
try {
|
|
252
|
+
return (
|
|
253
|
+
(await lookupIncomingPhoneNumberSid({
|
|
254
|
+
accountSid,
|
|
255
|
+
authToken,
|
|
256
|
+
phoneNumber,
|
|
257
|
+
})) ?? null
|
|
323
258
|
);
|
|
259
|
+
} catch (err) {
|
|
260
|
+
rethrowAsProviderError(err);
|
|
324
261
|
}
|
|
325
|
-
|
|
326
|
-
const data = (await res.json()) as {
|
|
327
|
-
incoming_phone_numbers: Array<{ sid: string; phone_number: string }>;
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
const match = data.incoming_phone_numbers.find(
|
|
331
|
-
(n) => n.phone_number === phoneNumber,
|
|
332
|
-
);
|
|
333
|
-
return match?.sid ?? null;
|
|
334
262
|
}
|
|
335
263
|
|
|
336
264
|
/**
|
|
@@ -21,11 +21,13 @@
|
|
|
21
21
|
* server-side.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { loadConfig } from "../config/loader.js";
|
|
25
24
|
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
buildTwilioMediaStreamUrl,
|
|
26
|
+
buildTwilioRelayUrl,
|
|
27
|
+
TWILIO_PUBLIC_BASE_URL_PLACEHOLDER,
|
|
28
|
+
} from "@vellumai/service-contracts/twilio-ingress";
|
|
29
|
+
|
|
30
|
+
import { loadConfig } from "../config/loader.js";
|
|
29
31
|
import { getProviderEntry } from "../providers/speech-to-text/provider-catalog.js";
|
|
30
32
|
import {
|
|
31
33
|
BadRequestError,
|
|
@@ -444,7 +446,6 @@ function buildVoiceWebhookTwiml(
|
|
|
444
446
|
// calls don't fail entirely on a misconfigured provider.
|
|
445
447
|
return buildConversationRelayTwiml(
|
|
446
448
|
callSessionId,
|
|
447
|
-
cfg,
|
|
448
449
|
profile,
|
|
449
450
|
sessionContext,
|
|
450
451
|
verificationSessionId,
|
|
@@ -457,7 +458,6 @@ function buildVoiceWebhookTwiml(
|
|
|
457
458
|
if (strategy.strategy === "conversation-relay-native") {
|
|
458
459
|
return buildConversationRelayTwiml(
|
|
459
460
|
callSessionId,
|
|
460
|
-
cfg,
|
|
461
461
|
profile,
|
|
462
462
|
sessionContext,
|
|
463
463
|
verificationSessionId,
|
|
@@ -500,7 +500,6 @@ function buildVoiceWebhookTwiml(
|
|
|
500
500
|
// through the relay server which supports it natively.
|
|
501
501
|
return buildConversationRelayTwiml(
|
|
502
502
|
callSessionId,
|
|
503
|
-
cfg,
|
|
504
503
|
profile,
|
|
505
504
|
sessionContext,
|
|
506
505
|
verificationSessionId,
|
|
@@ -508,7 +507,7 @@ function buildVoiceWebhookTwiml(
|
|
|
508
507
|
);
|
|
509
508
|
}
|
|
510
509
|
|
|
511
|
-
return buildMediaStreamTwiml(callSessionId,
|
|
510
|
+
return buildMediaStreamTwiml(callSessionId, verificationSessionId);
|
|
512
511
|
}
|
|
513
512
|
|
|
514
513
|
/**
|
|
@@ -516,7 +515,6 @@ function buildVoiceWebhookTwiml(
|
|
|
516
515
|
*/
|
|
517
516
|
function buildConversationRelayTwiml(
|
|
518
517
|
callSessionId: string,
|
|
519
|
-
cfg: ReturnType<typeof loadConfig>,
|
|
520
518
|
profile: ReturnType<typeof resolveVoiceQualityProfile>,
|
|
521
519
|
sessionContext: {
|
|
522
520
|
task: string | null;
|
|
@@ -538,7 +536,7 @@ function buildConversationRelayTwiml(
|
|
|
538
536
|
interruptSensitivity: profile.interruptSensitivity,
|
|
539
537
|
};
|
|
540
538
|
|
|
541
|
-
const relayUrl =
|
|
539
|
+
const relayUrl = buildTwilioRelayUrl(TWILIO_PUBLIC_BASE_URL_PLACEHOLDER);
|
|
542
540
|
const welcomeGreeting = buildWelcomeGreeting(sessionContext?.task ?? null);
|
|
543
541
|
const relayToken = TWILIO_RELAY_TOKEN_PLACEHOLDER;
|
|
544
542
|
|
|
@@ -572,10 +570,11 @@ function buildConversationRelayTwiml(
|
|
|
572
570
|
*/
|
|
573
571
|
function buildMediaStreamTwiml(
|
|
574
572
|
callSessionId: string,
|
|
575
|
-
cfg: ReturnType<typeof loadConfig>,
|
|
576
573
|
verificationSessionId: string | null | undefined,
|
|
577
574
|
): string {
|
|
578
|
-
const streamUrl =
|
|
575
|
+
const streamUrl = buildTwilioMediaStreamUrl(
|
|
576
|
+
TWILIO_PUBLIC_BASE_URL_PLACEHOLDER,
|
|
577
|
+
);
|
|
579
578
|
const relayToken = TWILIO_RELAY_TOKEN_PLACEHOLDER;
|
|
580
579
|
|
|
581
580
|
const customParameters: Record<string, string> | undefined =
|
package/src/channels/types.ts
CHANGED
|
@@ -91,17 +91,18 @@ export function isInteractiveInterface(id: InterfaceId): boolean {
|
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
93
|
* Host proxy capabilities that an interface can support. The macOS client
|
|
94
|
-
* supports all
|
|
94
|
+
* supports all five; the chrome-extension interface only supports
|
|
95
95
|
* host_browser (via the Chrome DevTools Protocol proxy).
|
|
96
96
|
*/
|
|
97
97
|
export type HostProxyCapability =
|
|
98
98
|
| "host_bash"
|
|
99
99
|
| "host_file"
|
|
100
100
|
| "host_cu"
|
|
101
|
-
| "host_browser"
|
|
101
|
+
| "host_browser"
|
|
102
|
+
| "host_app_control";
|
|
102
103
|
|
|
103
104
|
/**
|
|
104
|
-
* Interfaces that support the full desktop host-proxy set (all
|
|
105
|
+
* Interfaces that support the full desktop host-proxy set (all five
|
|
105
106
|
* `HostProxyCapability` values). This is the capability-level identity used
|
|
106
107
|
* by the discriminated transport metadata union and by the
|
|
107
108
|
* `supportsHostProxy(id)` type predicate.
|
|
@@ -135,10 +136,10 @@ export function supportsHostProxy(
|
|
|
135
136
|
id: InterfaceId,
|
|
136
137
|
capability?: HostProxyCapability,
|
|
137
138
|
): boolean {
|
|
138
|
-
// macOS supports all
|
|
139
|
-
// The host_browser proxy is provisioned via the
|
|
140
|
-
// extension is connected, browser tools fall
|
|
141
|
-
// via the CDP factory's candidate chain.
|
|
139
|
+
// macOS supports all five host proxy capabilities including host_browser
|
|
140
|
+
// and host_app_control. The host_browser proxy is provisioned via the
|
|
141
|
+
// assistant event hub. When no extension is connected, browser tools fall
|
|
142
|
+
// through to cdp-inspect/local via the CDP factory's candidate chain.
|
|
142
143
|
if (id === "macos") return true;
|
|
143
144
|
if (id === "chrome-extension" && capability === "host_browser") return true;
|
|
144
145
|
return false;
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
* or via a commander program (for end-to-end arg parsing).
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { Readable } from "node:stream";
|
|
13
12
|
import {
|
|
14
13
|
afterEach,
|
|
15
14
|
beforeEach,
|
|
@@ -130,8 +129,8 @@ let mockDaemonRunning = false;
|
|
|
130
129
|
const recoveryCallOrder: string[] = [];
|
|
131
130
|
|
|
132
131
|
/** Number of times each recovery helper was invoked. */
|
|
133
|
-
let
|
|
134
|
-
let
|
|
132
|
+
let _mockResetDbCalls = 0;
|
|
133
|
+
let _mockInvalidateConfigCacheCalls = 0;
|
|
135
134
|
|
|
136
135
|
/** Log calls captured by the mocked logger. */
|
|
137
136
|
let mockLogInfo: string[] = [];
|
|
@@ -167,7 +166,7 @@ mock.module("../../../config/loader.js", () => ({
|
|
|
167
166
|
backup: getComputedBackupConfig(),
|
|
168
167
|
}),
|
|
169
168
|
invalidateConfigCache: () => {
|
|
170
|
-
|
|
169
|
+
_mockInvalidateConfigCacheCalls += 1;
|
|
171
170
|
recoveryCallOrder.push("invalidateConfigCache");
|
|
172
171
|
},
|
|
173
172
|
}));
|
|
@@ -178,7 +177,7 @@ mock.module("../../../daemon/daemon-control.js", () => ({
|
|
|
178
177
|
|
|
179
178
|
mock.module("../../../memory/db-connection.js", () => ({
|
|
180
179
|
resetDb: () => {
|
|
181
|
-
|
|
180
|
+
_mockResetDbCalls += 1;
|
|
182
181
|
recoveryCallOrder.push("resetDb");
|
|
183
182
|
},
|
|
184
183
|
}));
|
|
@@ -323,9 +322,6 @@ const {
|
|
|
323
322
|
handleDestinationsList,
|
|
324
323
|
handleStatus,
|
|
325
324
|
handleList,
|
|
326
|
-
handleCreate,
|
|
327
|
-
handleVerify,
|
|
328
|
-
handleRestore,
|
|
329
325
|
registerBackupCommand,
|
|
330
326
|
} = backupMod;
|
|
331
327
|
|
|
@@ -342,8 +338,8 @@ beforeEach(() => {
|
|
|
342
338
|
mockLogError = [];
|
|
343
339
|
mockCreateShouldThrow = null;
|
|
344
340
|
mockDaemonRunning = false;
|
|
345
|
-
|
|
346
|
-
|
|
341
|
+
_mockResetDbCalls = 0;
|
|
342
|
+
_mockInvalidateConfigCacheCalls = 0;
|
|
347
343
|
recoveryCallOrder.length = 0;
|
|
348
344
|
process.exitCode = 0;
|
|
349
345
|
mockVerifyResult = { valid: true };
|
|
@@ -768,273 +764,6 @@ describe("handleList", () => {
|
|
|
768
764
|
// create
|
|
769
765
|
// ---------------------------------------------------------------------------
|
|
770
766
|
|
|
771
|
-
describe("handleCreate", () => {
|
|
772
|
-
test("renders successful snapshot result with empty offsite", async () => {
|
|
773
|
-
await handleCreate();
|
|
774
|
-
const out = mockLogInfo.join("\n");
|
|
775
|
-
expect(out).toContain("Created snapshot:");
|
|
776
|
-
expect(out).toContain("backup-20260411-093000.vbundle");
|
|
777
|
-
expect(out).toContain("offsite: (none)");
|
|
778
|
-
});
|
|
779
|
-
|
|
780
|
-
test("renders per-destination outcome mix (ok, skipped, error)", async () => {
|
|
781
|
-
mockCreateSnapshotResult = {
|
|
782
|
-
...mockCreateSnapshotResult,
|
|
783
|
-
offsite: [
|
|
784
|
-
{
|
|
785
|
-
destination: { path: "/ok", encrypt: true },
|
|
786
|
-
entry: {
|
|
787
|
-
path: "/ok/f.vbundle.enc",
|
|
788
|
-
filename: "f.vbundle.enc",
|
|
789
|
-
createdAt: new Date(),
|
|
790
|
-
sizeBytes: 100,
|
|
791
|
-
encrypted: true,
|
|
792
|
-
},
|
|
793
|
-
},
|
|
794
|
-
{
|
|
795
|
-
destination: { path: "/skipped", encrypt: true },
|
|
796
|
-
entry: null,
|
|
797
|
-
skipped: "parent-missing",
|
|
798
|
-
},
|
|
799
|
-
{
|
|
800
|
-
destination: { path: "/broken", encrypt: false },
|
|
801
|
-
entry: null,
|
|
802
|
-
error: "disk full",
|
|
803
|
-
},
|
|
804
|
-
],
|
|
805
|
-
};
|
|
806
|
-
await handleCreate();
|
|
807
|
-
const out = mockLogInfo.join("\n");
|
|
808
|
-
expect(out).toContain("ok /ok");
|
|
809
|
-
expect(out).toContain("skipped /skipped");
|
|
810
|
-
expect(out).toContain("error /broken");
|
|
811
|
-
expect(out).toContain("disk full");
|
|
812
|
-
});
|
|
813
|
-
|
|
814
|
-
test("concurrency error prints clear message", async () => {
|
|
815
|
-
mockCreateShouldThrow = new Error("snapshot in progress");
|
|
816
|
-
await handleCreate();
|
|
817
|
-
expect(process.exitCode).toBe(1);
|
|
818
|
-
expect(
|
|
819
|
-
mockLogError.some((m) =>
|
|
820
|
-
m.toLowerCase().includes("already running"),
|
|
821
|
-
),
|
|
822
|
-
).toBe(true);
|
|
823
|
-
});
|
|
824
|
-
});
|
|
825
|
-
|
|
826
|
-
// ---------------------------------------------------------------------------
|
|
827
|
-
// verify
|
|
828
|
-
// ---------------------------------------------------------------------------
|
|
829
|
-
|
|
830
|
-
describe("handleVerify", () => {
|
|
831
|
-
test("returns valid result from verifySnapshot", async () => {
|
|
832
|
-
mockVerifyResult = {
|
|
833
|
-
valid: true,
|
|
834
|
-
manifest: {
|
|
835
|
-
schema_version: "1.0.0",
|
|
836
|
-
created_at: "2026-04-11T09:30:00Z",
|
|
837
|
-
source: "backup-worker",
|
|
838
|
-
files: [],
|
|
839
|
-
manifest_sha256: "abc",
|
|
840
|
-
},
|
|
841
|
-
};
|
|
842
|
-
await handleVerify("/tmp/local/backup.vbundle");
|
|
843
|
-
const out = mockLogInfo.join("\n");
|
|
844
|
-
expect(out).toContain("OK:");
|
|
845
|
-
expect(out).toContain("1.0.0");
|
|
846
|
-
expect(process.exitCode).toBe(0);
|
|
847
|
-
});
|
|
848
|
-
|
|
849
|
-
test("propagates invalid result with error details", async () => {
|
|
850
|
-
mockVerifyResult = { valid: false, error: "bad checksum" };
|
|
851
|
-
await handleVerify("/tmp/local/backup.vbundle");
|
|
852
|
-
expect(process.exitCode).toBe(1);
|
|
853
|
-
expect(
|
|
854
|
-
mockLogError.some((m) => m.includes("Invalid:")),
|
|
855
|
-
).toBe(true);
|
|
856
|
-
expect(
|
|
857
|
-
mockLogError.some((m) => m.includes("bad checksum")),
|
|
858
|
-
).toBe(true);
|
|
859
|
-
});
|
|
860
|
-
});
|
|
861
|
-
|
|
862
|
-
// ---------------------------------------------------------------------------
|
|
863
|
-
// restore
|
|
864
|
-
// ---------------------------------------------------------------------------
|
|
865
|
-
|
|
866
|
-
/**
|
|
867
|
-
* Replace `process.stdin` with a readable stream that emits the given line.
|
|
868
|
-
* `readline.createInterface` consumes this as a single line so prompt-based
|
|
869
|
-
* confirmation tests stay deterministic.
|
|
870
|
-
*/
|
|
871
|
-
function stubStdin(input: string): () => void {
|
|
872
|
-
const original = process.stdin;
|
|
873
|
-
const stream = Readable.from([input + "\n"]) as NodeJS.ReadableStream;
|
|
874
|
-
Object.defineProperty(process, "stdin", {
|
|
875
|
-
value: stream,
|
|
876
|
-
writable: true,
|
|
877
|
-
configurable: true,
|
|
878
|
-
});
|
|
879
|
-
return () => {
|
|
880
|
-
Object.defineProperty(process, "stdin", {
|
|
881
|
-
value: original,
|
|
882
|
-
writable: true,
|
|
883
|
-
configurable: true,
|
|
884
|
-
});
|
|
885
|
-
};
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
describe("handleRestore", () => {
|
|
889
|
-
test("--yes flag bypasses confirmation and calls restoreFromSnapshot", async () => {
|
|
890
|
-
await handleRestore({
|
|
891
|
-
path: "/tmp/local/backup-20260411-093000.vbundle",
|
|
892
|
-
yes: true,
|
|
893
|
-
});
|
|
894
|
-
expect(process.exitCode).toBe(0);
|
|
895
|
-
const out = mockLogInfo.join("\n");
|
|
896
|
-
expect(out).toContain("Restored from");
|
|
897
|
-
expect(out).toContain("files restored: 42");
|
|
898
|
-
});
|
|
899
|
-
|
|
900
|
-
test("without --yes and 'n' answer aborts", async () => {
|
|
901
|
-
const restore = stubStdin("n");
|
|
902
|
-
try {
|
|
903
|
-
await handleRestore({
|
|
904
|
-
path: "/tmp/local/backup-20260411-093000.vbundle",
|
|
905
|
-
});
|
|
906
|
-
} finally {
|
|
907
|
-
restore();
|
|
908
|
-
}
|
|
909
|
-
expect(process.exitCode).toBe(0);
|
|
910
|
-
const out = mockLogInfo.join("\n");
|
|
911
|
-
expect(out).toContain("Restore cancelled");
|
|
912
|
-
});
|
|
913
|
-
|
|
914
|
-
test("without --path and without --latest errors", async () => {
|
|
915
|
-
await handleRestore({});
|
|
916
|
-
expect(process.exitCode).toBe(1);
|
|
917
|
-
expect(
|
|
918
|
-
mockLogError.some((m) => m.includes("--path")),
|
|
919
|
-
).toBe(true);
|
|
920
|
-
});
|
|
921
|
-
|
|
922
|
-
test("both --path and --latest errors", async () => {
|
|
923
|
-
await handleRestore({
|
|
924
|
-
path: "/tmp/x.vbundle",
|
|
925
|
-
latest: true,
|
|
926
|
-
yes: true,
|
|
927
|
-
});
|
|
928
|
-
expect(process.exitCode).toBe(1);
|
|
929
|
-
expect(
|
|
930
|
-
mockLogError.some((m) => m.includes("Cannot combine")),
|
|
931
|
-
).toBe(true);
|
|
932
|
-
});
|
|
933
|
-
|
|
934
|
-
test("--latest with no local snapshots errors", async () => {
|
|
935
|
-
mockSnapshots["/tmp/local"] = [];
|
|
936
|
-
await handleRestore({ latest: true, yes: true });
|
|
937
|
-
expect(process.exitCode).toBe(1);
|
|
938
|
-
expect(
|
|
939
|
-
mockLogError.some((m) => m.includes("No local snapshots")),
|
|
940
|
-
).toBe(true);
|
|
941
|
-
});
|
|
942
|
-
|
|
943
|
-
test("--latest picks newest local snapshot", async () => {
|
|
944
|
-
mockSnapshots["/tmp/local"] = [
|
|
945
|
-
{
|
|
946
|
-
path: "/tmp/local/newest.vbundle",
|
|
947
|
-
filename: "newest.vbundle",
|
|
948
|
-
createdAt: new Date("2026-04-11T12:00:00Z"),
|
|
949
|
-
sizeBytes: 1024,
|
|
950
|
-
encrypted: false,
|
|
951
|
-
},
|
|
952
|
-
{
|
|
953
|
-
path: "/tmp/local/older.vbundle",
|
|
954
|
-
filename: "older.vbundle",
|
|
955
|
-
createdAt: new Date("2026-04-10T12:00:00Z"),
|
|
956
|
-
sizeBytes: 1024,
|
|
957
|
-
encrypted: false,
|
|
958
|
-
},
|
|
959
|
-
];
|
|
960
|
-
await handleRestore({ latest: true, yes: true });
|
|
961
|
-
expect(process.exitCode).toBe(0);
|
|
962
|
-
expect(mockLogInfo.some((m) => m.includes("newest.vbundle"))).toBe(
|
|
963
|
-
true,
|
|
964
|
-
);
|
|
965
|
-
});
|
|
966
|
-
|
|
967
|
-
test("refuses to run while the assistant is running (no --force)", async () => {
|
|
968
|
-
// Safety gate: the CLI must refuse to restore against a live assistant
|
|
969
|
-
// unless --force is passed. Restoring under a running assistant is
|
|
970
|
-
// dangerous — the open SQLite handle, cached config, and cached trust
|
|
971
|
-
// rules all contradict the on-disk state after the bundle is written.
|
|
972
|
-
mockDaemonRunning = true;
|
|
973
|
-
|
|
974
|
-
await handleRestore({
|
|
975
|
-
path: "/tmp/local/backup-20260411-093000.vbundle",
|
|
976
|
-
yes: true,
|
|
977
|
-
});
|
|
978
|
-
|
|
979
|
-
expect(process.exitCode).toBe(1);
|
|
980
|
-
expect(
|
|
981
|
-
mockLogError.some((m) =>
|
|
982
|
-
m.toLowerCase().includes("assistant is running"),
|
|
983
|
-
),
|
|
984
|
-
).toBe(true);
|
|
985
|
-
// restoreFromSnapshot must not have been called — the safety gate
|
|
986
|
-
// bails before reaching the recovery sequence.
|
|
987
|
-
expect(mockResetDbCalls).toBe(0);
|
|
988
|
-
expect(recoveryCallOrder).toEqual([]);
|
|
989
|
-
});
|
|
990
|
-
|
|
991
|
-
test("--force overrides the daemon-running refusal and still runs recovery sequence", async () => {
|
|
992
|
-
mockDaemonRunning = true;
|
|
993
|
-
|
|
994
|
-
await handleRestore({
|
|
995
|
-
path: "/tmp/local/backup-20260411-093000.vbundle",
|
|
996
|
-
yes: true,
|
|
997
|
-
force: true,
|
|
998
|
-
});
|
|
999
|
-
|
|
1000
|
-
expect(process.exitCode).toBe(0);
|
|
1001
|
-
// Recovery sequence must still run even with --force — the flag only
|
|
1002
|
-
// overrides the running-assistant refusal, not the DB reset or cache
|
|
1003
|
-
// invalidation.
|
|
1004
|
-
expect(mockResetDbCalls).toBe(1);
|
|
1005
|
-
expect(mockInvalidateConfigCacheCalls).toBe(1);
|
|
1006
|
-
expect(recoveryCallOrder).toEqual([
|
|
1007
|
-
"resetDb",
|
|
1008
|
-
"restoreFromSnapshot",
|
|
1009
|
-
"invalidateConfigCache", ]);
|
|
1010
|
-
});
|
|
1011
|
-
|
|
1012
|
-
test("successful restore runs resetDb, restore, then cache invalidation in order", async () => {
|
|
1013
|
-
// Regression test for the restore-corrupts-daemon-state gap. The CLI
|
|
1014
|
-
// handler must mirror the HTTP handler's recovery sequence so an
|
|
1015
|
-
// in-process CLI invocation leaves the shared runtime in a consistent
|
|
1016
|
-
// state.
|
|
1017
|
-
mockDaemonRunning = false;
|
|
1018
|
-
|
|
1019
|
-
await handleRestore({
|
|
1020
|
-
path: "/tmp/local/backup-20260411-093000.vbundle",
|
|
1021
|
-
yes: true,
|
|
1022
|
-
});
|
|
1023
|
-
|
|
1024
|
-
expect(process.exitCode).toBe(0);
|
|
1025
|
-
expect(mockResetDbCalls).toBe(1);
|
|
1026
|
-
expect(mockInvalidateConfigCacheCalls).toBe(1);
|
|
1027
|
-
expect(recoveryCallOrder).toEqual([
|
|
1028
|
-
"resetDb",
|
|
1029
|
-
"restoreFromSnapshot",
|
|
1030
|
-
"invalidateConfigCache", ]);
|
|
1031
|
-
});
|
|
1032
|
-
});
|
|
1033
|
-
|
|
1034
|
-
// ---------------------------------------------------------------------------
|
|
1035
|
-
// End-to-end: via Commander program
|
|
1036
|
-
// ---------------------------------------------------------------------------
|
|
1037
|
-
|
|
1038
767
|
async function runProgram(
|
|
1039
768
|
args: string[],
|
|
1040
769
|
): Promise<{ exitCode: number }> {
|