@vellumai/assistant 0.7.1 → 0.7.3
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 +48 -50
- 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/memory.md +5 -2
- 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 +52 -5
- 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/slack-text/src/index.test.ts +18 -35
- package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
- 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 +1020 -40
- 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 +384 -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 +157 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -7
- package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
- package/src/__tests__/background-shell-host-bash.test.ts +14 -15
- package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
- 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-conversation-messages.test.ts +8 -2
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
- package/src/__tests__/channel-readiness-service.test.ts +62 -2
- package/src/__tests__/checker.test.ts +3 -4
- package/src/__tests__/config-loader-backfill.test.ts +461 -147
- 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-schema.test.ts +1 -0
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +20 -11
- package/src/__tests__/config-watcher.test.ts +142 -71
- package/src/__tests__/context-search-agent-runner.test.ts +61 -3
- package/src/__tests__/context-search-conversations-source.test.ts +0 -24
- package/src/__tests__/context-search-fanout.test.ts +0 -1
- package/src/__tests__/context-search-memory-source.test.ts +3 -7
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +0 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
- package/src/__tests__/conversation-agent-loop.test.ts +454 -5
- 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-error.test.ts +150 -3
- 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-process-callsite.test.ts +43 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -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-runtime-assembly.test.ts +65 -0
- package/src/__tests__/conversation-slash-commands.test.ts +0 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-store.test.ts +0 -18
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +328 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -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 +12 -12
- package/src/__tests__/cu-unified-flow.test.ts +351 -23
- package/src/__tests__/daemon-credential-client.test.ts +101 -19
- package/src/__tests__/date-context.test.ts +164 -2
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/disk-pressure-guard.test.ts +262 -0
- package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
- package/src/__tests__/disk-pressure-policy.test.ts +241 -0
- package/src/__tests__/disk-pressure-routes.test.ts +379 -0
- package/src/__tests__/disk-pressure-tools.test.ts +277 -0
- package/src/__tests__/disk-usage.test.ts +150 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/events-client-registration.test.ts +52 -0
- package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
- package/src/__tests__/file-write-tool.test.ts +4 -10
- package/src/__tests__/filing-service.test.ts +3 -4
- 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-disk-pressure.test.ts +183 -0
- package/src/__tests__/heartbeat-service.test.ts +968 -2
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/host-app-control-proxy.test.ts +772 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +439 -47
- package/src/__tests__/host-bash-routes.test.ts +459 -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 +248 -52
- package/src/__tests__/host-cu-routes-targeted.test.ts +429 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +378 -0
- package/src/__tests__/host-file-proxy.test.ts +301 -45
- package/src/__tests__/host-file-read-tool.test.ts +17 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +420 -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 +932 -0
- package/src/__tests__/host-transfer-proxy.test.ts +121 -22
- package/src/__tests__/host-transfer-routes-targeted.test.ts +662 -0
- package/src/__tests__/http-user-message-parity.test.ts +108 -1
- 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__/injector-chain.test.ts +18 -6
- package/src/__tests__/injector-disk-pressure.test.ts +224 -0
- 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-profile-guard.test.ts +18 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/mcp-abort-signal.test.ts +130 -0
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-admin-recall.test.ts +3 -11
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
- package/src/__tests__/migration-import-commit-http.test.ts +108 -2
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/normalize-onboarding.test.ts +180 -0
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth-connect-routes.test.ts +316 -0
- package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/onboarding-persona-write.test.ts +308 -0
- package/src/__tests__/openai-provider.test.ts +45 -8
- package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
- package/src/__tests__/platform-callback-registration.test.ts +21 -4
- package/src/__tests__/platform.test.ts +2 -1
- package/src/__tests__/playbook-execution.test.ts +0 -43
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +214 -25
- 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__/provider-tool-name.test.ts +23 -0
- package/src/__tests__/public-ingress-urls.test.ts +97 -0
- package/src/__tests__/relay-server.test.ts +15 -4
- 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 +2 -2
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- 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__/suggestion-routes.test.ts +46 -0
- 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-065-bump-stale-heartbeat-interval.test.ts +122 -0
- package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
- package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
- 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-safe-storage-limits-release.test.ts +90 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- package/src/approvals/guardian-decision-primitive.ts +13 -0
- package/src/approvals/guardian-request-resolvers.ts +16 -17
- 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/backup/snapshot-lock.ts +2 -27
- package/src/bundler/app-bundler.ts +51 -3
- package/src/bundler/compiler-tools.ts +3 -2
- package/src/calls/call-conversation-messages.ts +46 -10
- 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 -5
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/bash.ts +35 -108
- package/src/cli/commands/clients.ts +36 -37
- package/src/cli/commands/contacts.ts +137 -25
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +71 -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 +303 -7
- package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
- package/src/cli/commands/oauth/connect.ts +127 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -4
- package/src/cli/commands/platform/__tests__/connect.test.ts +7 -3
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -3
- package/src/cli/commands/platform/__tests__/status.test.ts +116 -21
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +16 -25
- package/src/cli/commands/status.ts +57 -0
- package/src/cli/lib/daemon-credential-client.ts +110 -28
- package/src/cli/program.ts +6 -2
- package/src/config/assistant-feature-flags.ts +79 -12
- 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/messaging/tools/messaging-analyze-style.ts +4 -3
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +25 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
- 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 -20
- package/src/config/feature-flag-registry.json +47 -135
- package/src/config/loader.ts +197 -104
- 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 +17 -9
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/calls.ts +0 -9
- package/src/config/schemas/channels.ts +0 -5
- package/src/config/schemas/heartbeat.ts +64 -1
- package/src/config/schemas/ingress.ts +10 -6
- package/src/config/schemas/llm.ts +7 -10
- package/src/config/schemas/memory-lifecycle.ts +90 -24
- package/src/config/schemas/memory-v2.ts +121 -13
- package/src/config/schemas/platform.ts +49 -3
- package/src/config/schemas/services.ts +29 -15
- package/src/config/schemas/skills.ts +0 -6
- package/src/config/seed-inference-profiles.ts +230 -33
- package/src/contacts/contact-store.ts +0 -55
- 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 +187 -5
- package/src/daemon/assistant-attachments.ts +4 -4
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +89 -60
- package/src/daemon/conversation-agent-loop-handlers.ts +27 -3
- package/src/daemon/conversation-agent-loop.ts +202 -61
- package/src/daemon/conversation-error.ts +87 -15
- package/src/daemon/conversation-lifecycle.ts +9 -4
- package/src/daemon/conversation-process.ts +24 -11
- package/src/daemon/conversation-runtime-assembly.ts +28 -2
- package/src/daemon/conversation-store.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +305 -4
- package/src/daemon/conversation-tool-setup.ts +66 -62
- package/src/daemon/conversation.ts +38 -24
- package/src/daemon/date-context.ts +71 -22
- package/src/daemon/disk-pressure-background-gate.ts +73 -0
- package/src/daemon/disk-pressure-guard.ts +343 -0
- package/src/daemon/disk-pressure-policy.ts +163 -0
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/handlers/shared.ts +4 -2
- package/src/daemon/handlers/skills.ts +3 -4
- package/src/daemon/host-app-control-proxy.ts +389 -0
- package/src/daemon/host-bash-proxy.ts +117 -82
- package/src/daemon/host-browser-proxy.ts +67 -82
- package/src/daemon/host-cu-proxy.ts +127 -86
- package/src/daemon/host-file-proxy.ts +129 -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 +338 -129
- package/src/daemon/lifecycle.ts +194 -145
- package/src/daemon/meet-host-supervisor.ts +4 -4
- package/src/daemon/meet-manifest-loader.ts +0 -1
- package/src/daemon/memory-v2-startup.ts +14 -4
- package/src/daemon/message-protocol.ts +6 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +15 -8
- package/src/daemon/message-types/disk-pressure.ts +9 -0
- 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/messages.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/profiler-run-store.ts +5 -5
- 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/documents/document-store.ts +85 -0
- package/src/events/tool-audit-listener.ts +2 -1
- package/src/filing/filing-service.ts +30 -5
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +24 -23
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +252 -0
- package/src/heartbeat/heartbeat-run-store.ts +249 -0
- package/src/heartbeat/heartbeat-service.ts +459 -54
- 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/feed-scheduler.ts +18 -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/platform-callback-registration.ts +8 -15
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/assistant-server.ts +70 -3
- package/src/ipc/cli-client.ts +32 -1
- package/src/ipc/gateway-client.ts +37 -3
- package/src/live-voice/live-voice-archive.ts +4 -4
- package/src/live-voice/live-voice-metrics.ts +10 -10
- package/src/live-voice/protocol.ts +5 -7
- 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/media/image-service.ts +1 -7
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -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/admin.ts +5 -9
- 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 +51 -9
- package/src/memory/context-search/sources/conversations.ts +2 -11
- package/src/memory/context-search/sources/memory-v2.ts +22 -9
- package/src/memory/context-search/sources/memory.ts +0 -1
- package/src/memory/context-search/types.ts +0 -1
- package/src/memory/conversation-crud.ts +5 -13
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/db-init.ts +6 -0
- package/src/memory/embedding-backend.ts +9 -21
- package/src/memory/embedding-runtime-manager.ts +119 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +81 -25
- package/src/memory/graph/conversation-graph-memory.ts +43 -78
- package/src/memory/graph/extraction.ts +1 -3
- package/src/memory/graph/graph-search.test.ts +10 -67
- package/src/memory/graph/graph-search.ts +9 -20
- package/src/memory/graph/retriever.test.ts +6 -0
- package/src/memory/graph/retriever.ts +34 -10
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/indexer.ts +54 -45
- package/src/memory/job-handlers/backfill.ts +2 -11
- package/src/memory/job-handlers/cleanup.ts +43 -0
- package/src/memory/job-handlers/embedding.ts +6 -8
- package/src/memory/job-handlers/summarization.ts +2 -7
- 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 +114 -22
- package/src/memory/jobs-worker.ts +193 -106
- package/src/memory/memory-v2-activation-log-store.ts +33 -15
- package/src/memory/memory-v2-concept-frequency.ts +169 -0
- 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/239-trace-events-created-at-index.ts +18 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +49 -32
- package/src/memory/rerank-local.ts +374 -0
- package/src/memory/schema/infrastructure.ts +15 -0
- package/src/memory/search/semantic.ts +13 -67
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/trace-event-store.ts +1 -17
- package/src/memory/v2/__tests__/activation.test.ts +387 -344
- package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
- package/src/memory/v2/__tests__/injection.test.ts +181 -169
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
- package/src/memory/v2/__tests__/reranker.test.ts +338 -0
- package/src/memory/v2/__tests__/sim.test.ts +154 -188
- package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +76 -2
- package/src/memory/v2/activation.ts +213 -239
- package/src/memory/v2/consolidation-job.ts +65 -17
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/injection.ts +123 -103
- package/src/memory/v2/prompts/consolidation.ts +348 -92
- package/src/memory/v2/qdrant.ts +198 -1
- package/src/memory/v2/reranker.ts +177 -0
- package/src/memory/v2/sim.ts +113 -77
- package/src/memory/v2/skill-content.ts +4 -3
- package/src/memory/v2/skill-store.ts +91 -53
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +28 -5
- package/src/memory/v2/types.ts +10 -10
- 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/copy-composer.ts +13 -0
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/notifications/signal.ts +4 -0
- package/src/oauth/AGENTS.md +3 -1
- package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
- package/src/oauth/connect-orchestrator.ts +6 -0
- package/src/oauth/connection-resolver.test.ts +66 -1
- package/src/oauth/connection-resolver.ts +55 -1
- package/src/oauth/credential-token-resolver.ts +1 -3
- package/src/oauth/manual-token-connection.ts +0 -4
- package/src/oauth/oauth-connect-state.ts +77 -0
- package/src/oauth/seed-providers.ts +58 -1
- 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/plugins/defaults/injectors.ts +35 -2
- package/src/plugins/defaults/memory-retrieval.ts +5 -6
- package/src/plugins/types.ts +7 -0
- package/src/proactive-artifact/aux-message-injector.ts +74 -0
- package/src/proactive-artifact/decision.test.ts +226 -0
- package/src/proactive-artifact/decision.ts +165 -0
- package/src/proactive-artifact/index.ts +7 -0
- package/src/proactive-artifact/job.test.ts +867 -0
- package/src/proactive-artifact/job.ts +352 -0
- package/src/proactive-artifact/message-copy.ts +41 -0
- package/src/proactive-artifact/trigger-state.test.ts +277 -0
- package/src/proactive-artifact/trigger-state.ts +119 -0
- package/src/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/normalize-onboarding.ts +80 -0
- package/src/prompts/persona-resolver.ts +101 -9
- package/src/prompts/system-prompt.ts +23 -24
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/providers/__tests__/retry-callsite.test.ts +222 -1
- package/src/providers/model-intents.ts +7 -0
- package/src/providers/openrouter/client.ts +8 -0
- package/src/providers/retry.ts +50 -0
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/providers/types.ts +1 -0
- package/src/runtime/__tests__/agent-wake.test.ts +456 -3
- package/src/runtime/agent-wake.ts +238 -100
- package/src/runtime/assistant-event-hub.ts +151 -99
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
- package/src/runtime/auth/middleware.ts +0 -96
- package/src/runtime/auth/route-policy.ts +32 -0
- package/src/runtime/auth/same-actor.ts +216 -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/channel-retry-sweep.ts +65 -1
- package/src/runtime/guardian-reply-router.ts +10 -0
- package/src/runtime/http-server.ts +3 -329
- package/src/runtime/http-types.ts +0 -5
- package/src/runtime/local-actor-identity.ts +52 -11
- 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 +43 -9
- package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
- package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -5
- 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 +21 -2
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/contact-routes.ts +0 -25
- package/src/runtime/routes/conversation-query-routes.ts +36 -1
- package/src/runtime/routes/conversation-routes.ts +65 -39
- package/src/runtime/routes/debug-bash-routes.ts +163 -0
- package/src/runtime/routes/disk-pressure-routes.ts +121 -0
- package/src/runtime/routes/document-pdf-renderer.ts +169 -0
- package/src/runtime/routes/documents-routes.ts +32 -75
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +38 -0
- 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 +56 -6
- package/src/runtime/routes/host-browser-routes.ts +108 -13
- package/src/runtime/routes/host-cu-routes.ts +66 -9
- package/src/runtime/routes/host-file-routes.ts +54 -5
- package/src/runtime/routes/host-transfer-routes.ts +122 -19
- 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 +21 -180
- package/src/runtime/routes/inbound-message-handler.ts +78 -21
- 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/guardian-reply-intercept.ts +3 -0
- 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 +14 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.test.ts +41 -15
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +474 -1
- package/src/runtime/routes/migration-routes.ts +96 -0
- package/src/runtime/routes/oauth-connect-routes.ts +153 -0
- package/src/runtime/routes/schedule-routes.ts +7 -0
- package/src/runtime/verification-outbound-actions.ts +4 -4
- 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/run-script.ts +37 -5
- 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 +83 -39
- package/src/security/encrypted-store.ts +2 -0
- package/src/security/oauth-callback-registry.ts +8 -0
- package/src/security/secure-keys.ts +55 -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 +10 -16
- 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/subagent/index.ts +1 -7
- package/src/subagent/manager.ts +1 -15
- package/src/tasks/task-runner.ts +0 -1
- package/src/tasks/task-store.ts +0 -3
- 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/background-tool-registry.ts +17 -3
- 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.test.ts +151 -0
- package/src/tools/host-filesystem/edit.ts +68 -0
- package/src/tools/host-filesystem/read.test.ts +129 -0
- package/src/tools/host-filesystem/read.ts +68 -0
- package/src/tools/host-filesystem/transfer.test.ts +127 -2
- package/src/tools/host-filesystem/transfer.ts +78 -3
- package/src/tools/host-filesystem/write.test.ts +134 -0
- package/src/tools/host-filesystem/write.ts +68 -0
- package/src/tools/host-terminal/host-shell.ts +66 -1
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/register.test.ts +12 -9
- package/src/tools/memory/register.ts +1 -2
- package/src/tools/provider-tool-name.ts +28 -0
- package/src/tools/registry.ts +30 -9
- 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/terminal/shell.ts +9 -1
- package/src/tools/tool-approval-handler.ts +32 -11
- package/src/tools/types.ts +28 -2
- package/src/tts/provider-catalog.ts +3 -5
- package/src/usage/pricing.ts +1 -1
- package/src/util/disk-usage.ts +138 -0
- package/src/util/platform.ts +21 -11
- package/src/util/process-liveness.ts +26 -0
- package/src/workspace/hatched-date.ts +86 -0
- package/src/workspace/heartbeat-service.ts +19 -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/065-bump-stale-heartbeat-interval.ts +60 -0
- package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
- package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/utils.ts +21 -0
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
- 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/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
- package/src/memory/v2/skill-qdrant.ts +0 -395
- 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/bash.ts +0 -198
- package/src/signals/mcp-reload.ts +0 -18
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* End-to-end smoke test for the self-hosted **capability-token**
|
|
3
|
-
* WebSocket round-trip over `/v1/browser-relay`.
|
|
4
|
-
*
|
|
5
|
-
* This file is the Phase 3 complement to `host-browser-e2e-cloud.test.ts`:
|
|
6
|
-
* it exercises the same mock-chrome-extension → runtime → HostBrowserProxy
|
|
7
|
-
* path, but the extension authenticates with a capability token minted
|
|
8
|
-
* by `mintHostBrowserCapability()` instead of a guardian-bound JWT.
|
|
9
|
-
*
|
|
10
|
-
* Invariants covered:
|
|
11
|
-
*
|
|
12
|
-
* 1. `/v1/browser-relay` accepts capability tokens directly.
|
|
13
|
-
* 2. The WS upgrade handler derives the registry-key guardianId from
|
|
14
|
-
* the capability claims so host_browser_request frames route
|
|
15
|
-
* back to the right connection.
|
|
16
|
-
* 3. A full `Browser.getVersion` request round-trips through the
|
|
17
|
-
* mock fixture and resolves on the proxy side.
|
|
18
|
-
*
|
|
19
|
-
* If this test fails, the self-hosted transport cutover is broken.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
23
|
-
|
|
24
|
-
// ── Module mocks (must be declared before the real imports below) ────
|
|
25
|
-
|
|
26
|
-
mock.module("../util/logger.js", () => ({
|
|
27
|
-
getLogger: () =>
|
|
28
|
-
new Proxy({} as Record<string, unknown>, {
|
|
29
|
-
get: () => () => {},
|
|
30
|
-
}),
|
|
31
|
-
}));
|
|
32
|
-
|
|
33
|
-
mock.module("../config/loader.js", () => ({
|
|
34
|
-
getConfig: () => ({
|
|
35
|
-
ui: {},
|
|
36
|
-
model: "test",
|
|
37
|
-
provider: "test",
|
|
38
|
-
memory: { enabled: false },
|
|
39
|
-
rateLimit: { maxRequestsPerMinute: 0 },
|
|
40
|
-
secretDetection: { enabled: false },
|
|
41
|
-
contextWindow: { maxInputTokens: 200000 },
|
|
42
|
-
services: {
|
|
43
|
-
inference: {
|
|
44
|
-
mode: "your-own",
|
|
45
|
-
provider: "anthropic",
|
|
46
|
-
model: "claude-opus-4-6",
|
|
47
|
-
},
|
|
48
|
-
"image-generation": {
|
|
49
|
-
mode: "your-own",
|
|
50
|
-
provider: "gemini",
|
|
51
|
-
model: "gemini-3.1-flash-image-preview",
|
|
52
|
-
},
|
|
53
|
-
"web-search": { mode: "your-own", provider: "inference-provider-native" },
|
|
54
|
-
},
|
|
55
|
-
}),
|
|
56
|
-
}));
|
|
57
|
-
|
|
58
|
-
// ── Real imports (after mocks) ──────────────────────────────────────
|
|
59
|
-
|
|
60
|
-
import { HostBrowserProxy } from "../daemon/host-browser-proxy.js";
|
|
61
|
-
import { getDb } from "../memory/db-connection.js";
|
|
62
|
-
import { initializeDb } from "../memory/db-init.js";
|
|
63
|
-
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
64
|
-
import { mintToken } from "../runtime/auth/token-service.js";
|
|
65
|
-
import {
|
|
66
|
-
mintHostBrowserCapability,
|
|
67
|
-
resetCapabilityTokenSecretForTests,
|
|
68
|
-
setCapabilityTokenSecretForTests,
|
|
69
|
-
} from "../runtime/capability-tokens.js";
|
|
70
|
-
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
71
|
-
|
|
72
|
-
initializeDb();
|
|
73
|
-
|
|
74
|
-
function mintSseToken(guardianId: string): string {
|
|
75
|
-
return mintToken({
|
|
76
|
-
aud: "vellum-daemon",
|
|
77
|
-
sub: `actor:self:${guardianId}`,
|
|
78
|
-
scope_profile: "actor_client_v1",
|
|
79
|
-
policy_epoch: 1,
|
|
80
|
-
ttlSeconds: 3600,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// ── Tests ───────────────────────────────────────────────────────────
|
|
85
|
-
|
|
86
|
-
describe("host_browser self-hosted capability-token e2e round-trip", () => {
|
|
87
|
-
let server: RuntimeHttpServer;
|
|
88
|
-
let port: number;
|
|
89
|
-
let runtimeBaseUrl: string;
|
|
90
|
-
|
|
91
|
-
beforeEach(async () => {
|
|
92
|
-
setCapabilityTokenSecretForTests(Buffer.alloc(32, 0xab));
|
|
93
|
-
|
|
94
|
-
const db = getDb();
|
|
95
|
-
db.run("DELETE FROM contact_channels");
|
|
96
|
-
db.run("DELETE FROM contacts");
|
|
97
|
-
HostBrowserProxy.reset();
|
|
98
|
-
|
|
99
|
-
port = 19600 + Math.floor(Math.random() * 200);
|
|
100
|
-
runtimeBaseUrl = `http://127.0.0.1:${port}`;
|
|
101
|
-
server = new RuntimeHttpServer({ port });
|
|
102
|
-
await server.start();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
afterEach(async () => {
|
|
106
|
-
await server?.stop();
|
|
107
|
-
HostBrowserProxy.reset();
|
|
108
|
-
resetCapabilityTokenSecretForTests();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test("capability token round-trips Browser.getVersion over WS result transport", async () => {
|
|
112
|
-
const guardianId = `self-hosted-guardian-${crypto.randomUUID()}`;
|
|
113
|
-
const { token } = mintHostBrowserCapability(guardianId);
|
|
114
|
-
|
|
115
|
-
const { createMockChromeExtension } =
|
|
116
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
117
|
-
const mockExt = createMockChromeExtension({
|
|
118
|
-
runtimeBaseUrl,
|
|
119
|
-
token,
|
|
120
|
-
sseToken: mintSseToken(guardianId),
|
|
121
|
-
resultTransport: "ws",
|
|
122
|
-
});
|
|
123
|
-
await mockExt.start();
|
|
124
|
-
await mockExt.waitForConnection();
|
|
125
|
-
await waitForRegistryEntry(guardianId);
|
|
126
|
-
|
|
127
|
-
const proxy = HostBrowserProxy.instance;
|
|
128
|
-
|
|
129
|
-
const result = await proxy.request(
|
|
130
|
-
{ cdpMethod: "Browser.getVersion" },
|
|
131
|
-
"conv-cap-happy-ws",
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
expect(result.isError).toBe(false);
|
|
135
|
-
expect(result.content).toContain("Chrome/MockTest");
|
|
136
|
-
|
|
137
|
-
const received = mockExt.receivedRequests();
|
|
138
|
-
expect(received).toHaveLength(1);
|
|
139
|
-
expect(received[0].cdpMethod).toBe("Browser.getVersion");
|
|
140
|
-
expect(received[0].conversationId).toBe("conv-cap-happy-ws");
|
|
141
|
-
|
|
142
|
-
await mockExt.stop();
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test("capability token round-trips Browser.getVersion over HTTP POST fallback", async () => {
|
|
146
|
-
const guardianId = `self-hosted-guardian-${crypto.randomUUID()}`;
|
|
147
|
-
const { token } = mintHostBrowserCapability(guardianId);
|
|
148
|
-
|
|
149
|
-
const { createMockChromeExtension } =
|
|
150
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
151
|
-
const mockExt = createMockChromeExtension({
|
|
152
|
-
runtimeBaseUrl,
|
|
153
|
-
token,
|
|
154
|
-
sseToken: mintSseToken(guardianId),
|
|
155
|
-
resultTransport: "http",
|
|
156
|
-
});
|
|
157
|
-
await mockExt.start();
|
|
158
|
-
await mockExt.waitForConnection();
|
|
159
|
-
await waitForRegistryEntry(guardianId);
|
|
160
|
-
|
|
161
|
-
const proxy = HostBrowserProxy.instance;
|
|
162
|
-
|
|
163
|
-
const result = await proxy.request(
|
|
164
|
-
{ cdpMethod: "Browser.getVersion" },
|
|
165
|
-
"conv-cap-happy-http",
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
expect(result.isError).toBe(false);
|
|
169
|
-
expect(result.content).toContain("Chrome/MockTest");
|
|
170
|
-
|
|
171
|
-
const received = mockExt.receivedRequests();
|
|
172
|
-
expect(received).toHaveLength(1);
|
|
173
|
-
expect(received[0].cdpMethod).toBe("Browser.getVersion");
|
|
174
|
-
expect(received[0].conversationId).toBe("conv-cap-happy-http");
|
|
175
|
-
|
|
176
|
-
await mockExt.stop();
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
test("an invalid capability token is rejected with 401", async () => {
|
|
180
|
-
const { createMockChromeExtension } =
|
|
181
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
182
|
-
const mockExt = createMockChromeExtension({
|
|
183
|
-
runtimeBaseUrl,
|
|
184
|
-
token: "totally-bogus-not-a-real-token",
|
|
185
|
-
});
|
|
186
|
-
let started = false;
|
|
187
|
-
try {
|
|
188
|
-
await mockExt.start();
|
|
189
|
-
started = true;
|
|
190
|
-
await mockExt.waitForConnection(500);
|
|
191
|
-
} catch {
|
|
192
|
-
// expected — SSE or WS auth rejects the bad token
|
|
193
|
-
}
|
|
194
|
-
// The extension must not reach a fully-connected state.
|
|
195
|
-
expect(started).toBe(false);
|
|
196
|
-
await mockExt.stop();
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
// ── Local wait helpers ──────────────────────────────────────────────
|
|
201
|
-
|
|
202
|
-
async function waitFor(
|
|
203
|
-
predicate: () => boolean,
|
|
204
|
-
timeoutMs = 2000,
|
|
205
|
-
): Promise<void> {
|
|
206
|
-
const deadline = Date.now() + timeoutMs;
|
|
207
|
-
while (!predicate()) {
|
|
208
|
-
if (Date.now() > deadline) {
|
|
209
|
-
throw new Error(
|
|
210
|
-
`waitFor: predicate did not become true within ${timeoutMs}ms`,
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
async function waitForRegistryEntry(
|
|
218
|
-
_guardianId: string,
|
|
219
|
-
timeoutMs = 2000,
|
|
220
|
-
): Promise<void> {
|
|
221
|
-
await waitFor(
|
|
222
|
-
() =>
|
|
223
|
-
assistantEventHub.getMostRecentClientByCapability("host_browser") != null,
|
|
224
|
-
timeoutMs,
|
|
225
|
-
);
|
|
226
|
-
}
|
|
@@ -1,427 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* End-to-end WebSocket dispatch test for the PR10 envelopes:
|
|
3
|
-
*
|
|
4
|
-
* - `host_browser_event` — the extension forwards every
|
|
5
|
-
* `chrome.debugger.onEvent` firing to the runtime over the
|
|
6
|
-
* browser-relay WebSocket. This test asserts that the runtime's
|
|
7
|
-
* inbound frame handler fans the event out to subscribers of the
|
|
8
|
-
* module-level browser-session event bus with the method + params
|
|
9
|
-
* + cdpSessionId preserved.
|
|
10
|
-
*
|
|
11
|
-
* - `host_browser_session_invalidated` — the extension forwards a
|
|
12
|
-
* detach notification over the same socket. This test asserts
|
|
13
|
-
* that the runtime-side `BrowserSessionManager` evicts any stale
|
|
14
|
-
* session whose `targetId` matches the invalidated envelope and
|
|
15
|
-
* that the next CDP command against that session throws, forcing
|
|
16
|
-
* the owning tool to create a fresh session (which in production
|
|
17
|
-
* triggers a reattach on the extension's dispatcher).
|
|
18
|
-
*
|
|
19
|
-
* Unlike the unit test in `host-browser-event-routes.test.ts`, this
|
|
20
|
-
* file stands up the full `RuntimeHttpServer` so the WS upgrade,
|
|
21
|
-
* frame parse, dispatch switch, and resolver helpers all run through
|
|
22
|
-
* their production code paths. The capability-token transport is
|
|
23
|
-
* used so the test does not depend on a valid guardian-bound JWT.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
27
|
-
|
|
28
|
-
// ── Module mocks (must be declared before the real imports below) ───
|
|
29
|
-
|
|
30
|
-
mock.module("../util/logger.js", () => ({
|
|
31
|
-
getLogger: () =>
|
|
32
|
-
new Proxy({} as Record<string, unknown>, {
|
|
33
|
-
get: () => () => {},
|
|
34
|
-
}),
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
mock.module("../config/loader.js", () => ({
|
|
38
|
-
getConfig: () => ({
|
|
39
|
-
ui: {},
|
|
40
|
-
model: "test",
|
|
41
|
-
provider: "test",
|
|
42
|
-
memory: { enabled: false },
|
|
43
|
-
rateLimit: { maxRequestsPerMinute: 0 },
|
|
44
|
-
secretDetection: { enabled: false },
|
|
45
|
-
contextWindow: { maxInputTokens: 200000 },
|
|
46
|
-
services: {
|
|
47
|
-
inference: {
|
|
48
|
-
mode: "your-own",
|
|
49
|
-
provider: "anthropic",
|
|
50
|
-
model: "claude-opus-4-6",
|
|
51
|
-
},
|
|
52
|
-
"image-generation": {
|
|
53
|
-
mode: "your-own",
|
|
54
|
-
provider: "gemini",
|
|
55
|
-
model: "gemini-3.1-flash-image-preview",
|
|
56
|
-
},
|
|
57
|
-
"web-search": { mode: "your-own", provider: "inference-provider-native" },
|
|
58
|
-
},
|
|
59
|
-
}),
|
|
60
|
-
}));
|
|
61
|
-
|
|
62
|
-
// ── Real imports (after mocks) ──────────────────────────────────────
|
|
63
|
-
|
|
64
|
-
import {
|
|
65
|
-
__resetBrowserSessionEventsForTests,
|
|
66
|
-
BrowserSessionManager,
|
|
67
|
-
createExtensionBackend,
|
|
68
|
-
type ForwardedCdpEvent,
|
|
69
|
-
onCdpEvent,
|
|
70
|
-
} from "../browser-session/index.js";
|
|
71
|
-
import { HostBrowserProxy } from "../daemon/host-browser-proxy.js";
|
|
72
|
-
import { getDb } from "../memory/db-connection.js";
|
|
73
|
-
import { initializeDb } from "../memory/db-init.js";
|
|
74
|
-
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
75
|
-
import { mintToken } from "../runtime/auth/token-service.js";
|
|
76
|
-
import {
|
|
77
|
-
mintHostBrowserCapability,
|
|
78
|
-
resetCapabilityTokenSecretForTests,
|
|
79
|
-
setCapabilityTokenSecretForTests,
|
|
80
|
-
} from "../runtime/capability-tokens.js";
|
|
81
|
-
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
82
|
-
|
|
83
|
-
initializeDb();
|
|
84
|
-
|
|
85
|
-
function mintSseToken(guardianId: string): string {
|
|
86
|
-
return mintToken({
|
|
87
|
-
aud: "vellum-daemon",
|
|
88
|
-
sub: `actor:self:${guardianId}`,
|
|
89
|
-
scope_profile: "actor_client_v1",
|
|
90
|
-
policy_epoch: 1,
|
|
91
|
-
ttlSeconds: 3600,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ── Helpers ─────────────────────────────────────────────────────────
|
|
96
|
-
|
|
97
|
-
async function waitFor(
|
|
98
|
-
predicate: () => boolean,
|
|
99
|
-
timeoutMs = 2000,
|
|
100
|
-
): Promise<void> {
|
|
101
|
-
const deadline = Date.now() + timeoutMs;
|
|
102
|
-
while (!predicate()) {
|
|
103
|
-
if (Date.now() > deadline) {
|
|
104
|
-
throw new Error(
|
|
105
|
-
`waitFor: predicate did not become true within ${timeoutMs}ms`,
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async function waitForRegistryEntry(
|
|
113
|
-
_guardianId: string,
|
|
114
|
-
timeoutMs = 2000,
|
|
115
|
-
): Promise<void> {
|
|
116
|
-
await waitFor(
|
|
117
|
-
() =>
|
|
118
|
-
assistantEventHub.getMostRecentClientByCapability("host_browser") != null,
|
|
119
|
-
timeoutMs,
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ── Tests ───────────────────────────────────────────────────────────
|
|
124
|
-
|
|
125
|
-
describe("host_browser WS event + invalidation e2e", () => {
|
|
126
|
-
let server: RuntimeHttpServer;
|
|
127
|
-
let port: number;
|
|
128
|
-
let runtimeBaseUrl: string;
|
|
129
|
-
|
|
130
|
-
beforeEach(async () => {
|
|
131
|
-
setCapabilityTokenSecretForTests(Buffer.alloc(32, 0xab));
|
|
132
|
-
|
|
133
|
-
const db = getDb();
|
|
134
|
-
db.run("DELETE FROM contact_channels");
|
|
135
|
-
db.run("DELETE FROM contacts");
|
|
136
|
-
HostBrowserProxy.reset();
|
|
137
|
-
__resetBrowserSessionEventsForTests();
|
|
138
|
-
|
|
139
|
-
// Pick a non-colliding port in the same band as the other
|
|
140
|
-
// host-browser e2e tests but offset so parallel runs don't
|
|
141
|
-
// step on one another.
|
|
142
|
-
port = 19900 + Math.floor(Math.random() * 200);
|
|
143
|
-
runtimeBaseUrl = `http://127.0.0.1:${port}`;
|
|
144
|
-
server = new RuntimeHttpServer({ port });
|
|
145
|
-
await server.start();
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
afterEach(async () => {
|
|
149
|
-
await server?.stop();
|
|
150
|
-
HostBrowserProxy.reset();
|
|
151
|
-
__resetBrowserSessionEventsForTests();
|
|
152
|
-
resetCapabilityTokenSecretForTests();
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
test("host_browser_event frame fans out to browser-session event bus subscribers", async () => {
|
|
156
|
-
const guardianId = `guardian-${crypto.randomUUID()}`;
|
|
157
|
-
const { token } = mintHostBrowserCapability(guardianId);
|
|
158
|
-
|
|
159
|
-
const { createMockChromeExtension } =
|
|
160
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
161
|
-
const mockExt = createMockChromeExtension({
|
|
162
|
-
runtimeBaseUrl,
|
|
163
|
-
token,
|
|
164
|
-
sseToken: mintSseToken(guardianId),
|
|
165
|
-
resultTransport: "ws",
|
|
166
|
-
});
|
|
167
|
-
await mockExt.start();
|
|
168
|
-
await mockExt.waitForConnection();
|
|
169
|
-
await waitForRegistryEntry(guardianId);
|
|
170
|
-
|
|
171
|
-
// Subscribe BEFORE sending the frame so we're guaranteed to see
|
|
172
|
-
// the fanout. The subscription is module-level so it survives
|
|
173
|
-
// across the WS round-trip naturally.
|
|
174
|
-
const observed: ForwardedCdpEvent[] = [];
|
|
175
|
-
const unsubscribe = onCdpEvent((event) => observed.push(event));
|
|
176
|
-
|
|
177
|
-
mockExt.sendHostBrowserEvent({
|
|
178
|
-
method: "Page.frameNavigated",
|
|
179
|
-
params: { frame: { id: "frame-1", url: "https://example.com" } },
|
|
180
|
-
cdpSessionId: "target-abc",
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
// The WS dispatch hop is asynchronous — poll until the event
|
|
184
|
-
// lands or the test times out.
|
|
185
|
-
await waitFor(() => observed.length === 1);
|
|
186
|
-
|
|
187
|
-
expect(observed[0].method).toBe("Page.frameNavigated");
|
|
188
|
-
expect(observed[0].params).toEqual({
|
|
189
|
-
frame: { id: "frame-1", url: "https://example.com" },
|
|
190
|
-
});
|
|
191
|
-
expect(observed[0].cdpSessionId).toBe("target-abc");
|
|
192
|
-
|
|
193
|
-
unsubscribe();
|
|
194
|
-
await mockExt.stop();
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
test("host_browser_event frames with no params are still routed", async () => {
|
|
198
|
-
const guardianId = `guardian-${crypto.randomUUID()}`;
|
|
199
|
-
const { token } = mintHostBrowserCapability(guardianId);
|
|
200
|
-
|
|
201
|
-
const { createMockChromeExtension } =
|
|
202
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
203
|
-
const mockExt = createMockChromeExtension({
|
|
204
|
-
runtimeBaseUrl,
|
|
205
|
-
token,
|
|
206
|
-
sseToken: mintSseToken(guardianId),
|
|
207
|
-
resultTransport: "ws",
|
|
208
|
-
});
|
|
209
|
-
await mockExt.start();
|
|
210
|
-
await mockExt.waitForConnection();
|
|
211
|
-
await waitForRegistryEntry(guardianId);
|
|
212
|
-
|
|
213
|
-
const observed: ForwardedCdpEvent[] = [];
|
|
214
|
-
const unsubscribe = onCdpEvent((event) => observed.push(event));
|
|
215
|
-
|
|
216
|
-
mockExt.sendHostBrowserEvent({ method: "Target.targetDestroyed" });
|
|
217
|
-
|
|
218
|
-
await waitFor(() => observed.length === 1);
|
|
219
|
-
expect(observed[0].method).toBe("Target.targetDestroyed");
|
|
220
|
-
expect(observed[0].params).toBeUndefined();
|
|
221
|
-
expect(observed[0].cdpSessionId).toBeUndefined();
|
|
222
|
-
|
|
223
|
-
unsubscribe();
|
|
224
|
-
await mockExt.stop();
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
test("host_browser_session_invalidated frame evicts stale sessions and the next command forces reattach", async () => {
|
|
228
|
-
const guardianId = `guardian-${crypto.randomUUID()}`;
|
|
229
|
-
const { token } = mintHostBrowserCapability(guardianId);
|
|
230
|
-
|
|
231
|
-
const { createMockChromeExtension } =
|
|
232
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
233
|
-
const mockExt = createMockChromeExtension({
|
|
234
|
-
runtimeBaseUrl,
|
|
235
|
-
token,
|
|
236
|
-
sseToken: mintSseToken(guardianId),
|
|
237
|
-
resultTransport: "ws",
|
|
238
|
-
});
|
|
239
|
-
await mockExt.start();
|
|
240
|
-
await mockExt.waitForConnection();
|
|
241
|
-
await waitForRegistryEntry(guardianId);
|
|
242
|
-
|
|
243
|
-
// Stand up a BrowserSessionManager that mirrors what a tool
|
|
244
|
-
// invocation would build. The backend counts dispatch attempts
|
|
245
|
-
// so we can assert the first post-invalidation send never
|
|
246
|
-
// reached the backend while the second (after reattach) did.
|
|
247
|
-
const sent: Array<{ method: string }> = [];
|
|
248
|
-
const backend = createExtensionBackend({
|
|
249
|
-
isAvailable: () => true,
|
|
250
|
-
sendCdp: async (command) => {
|
|
251
|
-
sent.push({ method: command.method });
|
|
252
|
-
return { result: { ok: true } };
|
|
253
|
-
},
|
|
254
|
-
dispose: () => {},
|
|
255
|
-
});
|
|
256
|
-
const manager = new BrowserSessionManager({ backends: [backend] });
|
|
257
|
-
const session = manager.createSession();
|
|
258
|
-
session.targetId = "tab-77";
|
|
259
|
-
|
|
260
|
-
// Fire the invalidation envelope from the extension side.
|
|
261
|
-
mockExt.sendSessionInvalidated({
|
|
262
|
-
targetId: "tab-77",
|
|
263
|
-
reason: "target_closed",
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
// Wait until the WS dispatch hop lands — `isTargetInvalidated`
|
|
267
|
-
// peeks at the registry without consuming the entry, so we can
|
|
268
|
-
// poll safely.
|
|
269
|
-
const { isTargetInvalidated } =
|
|
270
|
-
await import("../browser-session/events.js");
|
|
271
|
-
await waitFor(() => isTargetInvalidated("tab-77"));
|
|
272
|
-
|
|
273
|
-
// The next send against the invalidated session MUST throw —
|
|
274
|
-
// the manager consumes the invalidation flag, evicts the
|
|
275
|
-
// session, and rejects the command so the caller can create a
|
|
276
|
-
// fresh session (which triggers a reattach on the extension
|
|
277
|
-
// side).
|
|
278
|
-
await expect(
|
|
279
|
-
manager.send(session.id, { method: "Page.navigate" }),
|
|
280
|
-
).rejects.toThrow(/invalidated/);
|
|
281
|
-
|
|
282
|
-
// Sanity: the backend never saw the doomed command.
|
|
283
|
-
expect(sent).toHaveLength(0);
|
|
284
|
-
|
|
285
|
-
// The evicted session is gone — sending again throws
|
|
286
|
-
// "Unknown browser session", which is the signal a tool uses
|
|
287
|
-
// to rebuild a fresh session.
|
|
288
|
-
await expect(
|
|
289
|
-
manager.send(session.id, { method: "Page.navigate" }),
|
|
290
|
-
).rejects.toThrow(/Unknown browser session/);
|
|
291
|
-
|
|
292
|
-
// Creating a fresh session proves the reattach path works:
|
|
293
|
-
// the caller bounces through `createSession` and a subsequent
|
|
294
|
-
// send dispatches normally through the backend.
|
|
295
|
-
const fresh = manager.createSession();
|
|
296
|
-
const result = await manager.send(fresh.id, {
|
|
297
|
-
method: "Page.navigate",
|
|
298
|
-
});
|
|
299
|
-
expect(result.result).toEqual({ ok: true });
|
|
300
|
-
expect(sent).toEqual([{ method: "Page.navigate" }]);
|
|
301
|
-
|
|
302
|
-
await mockExt.stop();
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
test("keepalive frames are accepted without closing the socket or producing warnings", async () => {
|
|
306
|
-
const guardianId = `guardian-${crypto.randomUUID()}`;
|
|
307
|
-
const { token } = mintHostBrowserCapability(guardianId);
|
|
308
|
-
|
|
309
|
-
const { createMockChromeExtension } =
|
|
310
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
311
|
-
const mockExt = createMockChromeExtension({
|
|
312
|
-
runtimeBaseUrl,
|
|
313
|
-
token,
|
|
314
|
-
sseToken: mintSseToken(guardianId),
|
|
315
|
-
resultTransport: "ws",
|
|
316
|
-
});
|
|
317
|
-
await mockExt.start();
|
|
318
|
-
await mockExt.waitForConnection();
|
|
319
|
-
await waitForRegistryEntry(guardianId);
|
|
320
|
-
|
|
321
|
-
// Send a keepalive frame (the extension sends these periodically
|
|
322
|
-
// to prevent the runtime from considering the connection stale).
|
|
323
|
-
// The frame may contain extra keys (e.g. timestamp) that the
|
|
324
|
-
// runtime should silently ignore (lenient validation).
|
|
325
|
-
mockExt.sendRaw(JSON.stringify({ type: "keepalive", ts: Date.now() }));
|
|
326
|
-
|
|
327
|
-
// Small delay to let the keepalive frame process.
|
|
328
|
-
await new Promise((r) => setTimeout(r, 15));
|
|
329
|
-
|
|
330
|
-
// Verify the socket is still alive by sending a normal host_browser_event
|
|
331
|
-
// frame after the keepalive — if the socket had been torn down, this
|
|
332
|
-
// would never arrive.
|
|
333
|
-
const observed: ForwardedCdpEvent[] = [];
|
|
334
|
-
const unsubscribe = onCdpEvent((event) => observed.push(event));
|
|
335
|
-
|
|
336
|
-
mockExt.sendHostBrowserEvent({ method: "Page.loadEventFired" });
|
|
337
|
-
await waitFor(() => observed.length === 1);
|
|
338
|
-
expect(observed[0].method).toBe("Page.loadEventFired");
|
|
339
|
-
|
|
340
|
-
unsubscribe();
|
|
341
|
-
await mockExt.stop();
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
test("normal host_browser flows still pass after keepalive traffic", async () => {
|
|
345
|
-
const guardianId = `guardian-${crypto.randomUUID()}`;
|
|
346
|
-
const { token } = mintHostBrowserCapability(guardianId);
|
|
347
|
-
|
|
348
|
-
const { createMockChromeExtension } =
|
|
349
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
350
|
-
const mockExt = createMockChromeExtension({
|
|
351
|
-
runtimeBaseUrl,
|
|
352
|
-
token,
|
|
353
|
-
sseToken: mintSseToken(guardianId),
|
|
354
|
-
resultTransport: "ws",
|
|
355
|
-
});
|
|
356
|
-
await mockExt.start();
|
|
357
|
-
await mockExt.waitForConnection();
|
|
358
|
-
await waitForRegistryEntry(guardianId);
|
|
359
|
-
|
|
360
|
-
// Simulate a burst of keepalive frames (as would happen during an
|
|
361
|
-
// idle period with the extension's alarm-based keepalive ticker).
|
|
362
|
-
for (let i = 0; i < 5; i++) {
|
|
363
|
-
mockExt.sendRaw(JSON.stringify({ type: "keepalive" }));
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Small delay to let all keepalive frames process.
|
|
367
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
368
|
-
|
|
369
|
-
// Now send a host_browser_event and verify it still fans out
|
|
370
|
-
// correctly — proving keepalive traffic does not interfere with
|
|
371
|
-
// normal message processing.
|
|
372
|
-
const observed: ForwardedCdpEvent[] = [];
|
|
373
|
-
const unsubscribe = onCdpEvent((event) => observed.push(event));
|
|
374
|
-
|
|
375
|
-
mockExt.sendHostBrowserEvent({
|
|
376
|
-
method: "Network.requestWillBeSent",
|
|
377
|
-
params: { requestId: "req-42", url: "https://example.com/api" },
|
|
378
|
-
cdpSessionId: "session-xyz",
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
await waitFor(() => observed.length === 1);
|
|
382
|
-
expect(observed[0].method).toBe("Network.requestWillBeSent");
|
|
383
|
-
expect(observed[0].params).toEqual({
|
|
384
|
-
requestId: "req-42",
|
|
385
|
-
url: "https://example.com/api",
|
|
386
|
-
});
|
|
387
|
-
expect(observed[0].cdpSessionId).toBe("session-xyz");
|
|
388
|
-
|
|
389
|
-
unsubscribe();
|
|
390
|
-
await mockExt.stop();
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
test("malformed host_browser_event frames are dropped without tearing down the socket", async () => {
|
|
394
|
-
const guardianId = `guardian-${crypto.randomUUID()}`;
|
|
395
|
-
const { token } = mintHostBrowserCapability(guardianId);
|
|
396
|
-
|
|
397
|
-
const { createMockChromeExtension } =
|
|
398
|
-
await import("./fixtures/mock-chrome-extension.js");
|
|
399
|
-
const mockExt = createMockChromeExtension({
|
|
400
|
-
runtimeBaseUrl,
|
|
401
|
-
token,
|
|
402
|
-
sseToken: mintSseToken(guardianId),
|
|
403
|
-
resultTransport: "ws",
|
|
404
|
-
});
|
|
405
|
-
await mockExt.start();
|
|
406
|
-
await mockExt.waitForConnection();
|
|
407
|
-
await waitForRegistryEntry(guardianId);
|
|
408
|
-
|
|
409
|
-
const observed: ForwardedCdpEvent[] = [];
|
|
410
|
-
const unsubscribe = onCdpEvent((event) => observed.push(event));
|
|
411
|
-
|
|
412
|
-
// Send a frame with no method — the resolver must reject it
|
|
413
|
-
// and the WS dispatcher must swallow the rejection.
|
|
414
|
-
mockExt.sendHostBrowserEvent({ method: "" });
|
|
415
|
-
|
|
416
|
-
// Follow up with a valid frame and assert that ONLY the valid
|
|
417
|
-
// frame was published — proving the socket survived the bad
|
|
418
|
-
// frame and the dispatcher kept processing subsequent messages.
|
|
419
|
-
mockExt.sendHostBrowserEvent({ method: "Page.loadEventFired" });
|
|
420
|
-
|
|
421
|
-
await waitFor(() => observed.length === 1);
|
|
422
|
-
expect(observed[0].method).toBe("Page.loadEventFired");
|
|
423
|
-
|
|
424
|
-
unsubscribe();
|
|
425
|
-
await mockExt.stop();
|
|
426
|
-
});
|
|
427
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
|
|
3
|
-
import { twilioAuthHeader, twilioBaseUrl } from "../calls/twilio-rest.js";
|
|
4
|
-
|
|
5
|
-
describe("twilioAuthHeader", () => {
|
|
6
|
-
test("returns a valid Basic auth header", () => {
|
|
7
|
-
const header = twilioAuthHeader("AC_test_sid", "test_token");
|
|
8
|
-
const expected =
|
|
9
|
-
"Basic " + Buffer.from("AC_test_sid:test_token").toString("base64");
|
|
10
|
-
expect(header).toBe(expected);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test("encodes special characters correctly", () => {
|
|
14
|
-
const header = twilioAuthHeader("AC_special!@#", "tok$%^&");
|
|
15
|
-
const decoded = Buffer.from(
|
|
16
|
-
header.replace("Basic ", ""),
|
|
17
|
-
"base64",
|
|
18
|
-
).toString();
|
|
19
|
-
expect(decoded).toBe("AC_special!@#:tok$%^&");
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
describe("twilioBaseUrl", () => {
|
|
24
|
-
test("constructs correct base URL for a given account SID", () => {
|
|
25
|
-
const url = twilioBaseUrl("AC_abc123");
|
|
26
|
-
expect(url).toBe("https://api.twilio.com/2010-04-01/Accounts/AC_abc123");
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test("handles different account SIDs", () => {
|
|
30
|
-
const url = twilioBaseUrl("AC_xyz789");
|
|
31
|
-
expect(url).toContain("AC_xyz789");
|
|
32
|
-
expect(url).toStartWith("https://api.twilio.com/2010-04-01/Accounts/");
|
|
33
|
-
});
|
|
34
|
-
});
|