@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
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifies that the queue-drain paths in `conversation-process.ts` re-add
|
|
3
|
+
* the `app-control` skill to the conversation's preactivated set when the
|
|
4
|
+
* dequeued message's `userMessageInterface` supports the `host_app_control`
|
|
5
|
+
* proxy capability.
|
|
6
|
+
*
|
|
7
|
+
* Both `drainSingleMessage` (single-message path) and `drainBatch`
|
|
8
|
+
* (batched path) reset `preactivatedSkillIds = undefined` at the top of
|
|
9
|
+
* each drain. Without an explicit re-add, queued messages 2+ would lose
|
|
10
|
+
* the `app-control` skill — its tools wouldn't be projected to the LLM —
|
|
11
|
+
* even though the `HostAppControlProxy` is still attached to the
|
|
12
|
+
* conversation. This mirrors the existing parallel re-add for
|
|
13
|
+
* `computer-use` and uses the same `supportsHostProxy(_, "host_app_control")`
|
|
14
|
+
* gate that `prepareConversationForMessage` and the `conversation-routes`
|
|
15
|
+
* instantiation block use at first-message time.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
19
|
+
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Module mocks for downstream side effects (DB writes, slash resolution,
|
|
22
|
+
// notification preference extraction). The drain paths must be allowed to
|
|
23
|
+
// reach the preactivation block; they must not be allowed to touch a real DB.
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
mock.module("../util/logger.js", () => ({
|
|
27
|
+
getLogger: () =>
|
|
28
|
+
new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
mock.module("../memory/conversation-crud.js", () => ({
|
|
32
|
+
setConversationOriginChannelIfUnset: () => {},
|
|
33
|
+
setConversationOriginInterfaceIfUnset: () => {},
|
|
34
|
+
provenanceFromTrustContext: () => ({
|
|
35
|
+
source: "user",
|
|
36
|
+
trustContext: undefined,
|
|
37
|
+
}),
|
|
38
|
+
addMessage: () => ({ id: "msg-mock" }),
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
mock.module("../memory/canonical-guardian-store.js", () => ({
|
|
42
|
+
listPendingRequestsByConversationScope: () => [],
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
mock.module("../memory/trace-event-store.js", () => ({
|
|
46
|
+
persistTraceEvent: () => {},
|
|
47
|
+
getMaxSequence: () => 0,
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
mock.module("../notifications/preference-extractor.js", () => ({
|
|
51
|
+
extractPreferences: async () => ({ detected: false, preferences: [] }),
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
mock.module("../notifications/preferences-store.js", () => ({
|
|
55
|
+
createPreference: () => {},
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
mock.module("../agent/attachments.ts", () => ({
|
|
59
|
+
enrichMessageWithSourcePaths: <T>(msg: T) => msg,
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
// Stub the batched-drain helper so the test doesn't fall through to real
|
|
63
|
+
// SQLite paths after the preactivation block has already run. The drain
|
|
64
|
+
// chain doesn't recurse here because our stubbed `runAgentLoop` is a no-op.
|
|
65
|
+
mock.module("../daemon/conversation-messaging.js", () => ({
|
|
66
|
+
persistQueuedMessageBody: async () => "user-msg-id",
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Imports under test (after mocks)
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
import type { TurnInterfaceContext } from "../channels/types.js";
|
|
74
|
+
import type { ProcessConversationContext } from "../daemon/conversation-process.js";
|
|
75
|
+
import { drainQueue } from "../daemon/conversation-process.js";
|
|
76
|
+
import {
|
|
77
|
+
MessageQueue,
|
|
78
|
+
type QueuedMessage,
|
|
79
|
+
} from "../daemon/conversation-queue-manager.js";
|
|
80
|
+
import { TraceEmitter } from "../daemon/trace-emitter.js";
|
|
81
|
+
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Fake context — captures preactivation calls, satisfies the bare minimum
|
|
84
|
+
// of `ProcessConversationContext`. `runAgentLoop` resolves immediately so
|
|
85
|
+
// the drain-chain does not recurse forever.
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
interface FakeRecord {
|
|
89
|
+
preactivatedSkillIdCalls: string[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function makeFakeContext(opts: {
|
|
93
|
+
queue: MessageQueue;
|
|
94
|
+
turnInterfaceContext?: TurnInterfaceContext;
|
|
95
|
+
}): ProcessConversationContext & FakeRecord {
|
|
96
|
+
const calls: string[] = [];
|
|
97
|
+
let preactivatedSkillIds: string[] | undefined = undefined;
|
|
98
|
+
const ctx = {
|
|
99
|
+
conversationId: "conv-app-control-preactivation",
|
|
100
|
+
messages: [],
|
|
101
|
+
processing: false,
|
|
102
|
+
abortController: null,
|
|
103
|
+
queue: opts.queue,
|
|
104
|
+
traceEmitter: new TraceEmitter("conv-app-control-preactivation", () => {}),
|
|
105
|
+
surfaceActionRequestIds: new Set<string>(),
|
|
106
|
+
usageStats: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
|
|
107
|
+
get preactivatedSkillIds(): string[] | undefined {
|
|
108
|
+
return preactivatedSkillIds;
|
|
109
|
+
},
|
|
110
|
+
set preactivatedSkillIds(value: string[] | undefined) {
|
|
111
|
+
preactivatedSkillIds = value;
|
|
112
|
+
},
|
|
113
|
+
preactivatedSkillIdCalls: calls,
|
|
114
|
+
addPreactivatedSkillId(id: string) {
|
|
115
|
+
calls.push(id);
|
|
116
|
+
if (!preactivatedSkillIds) {
|
|
117
|
+
preactivatedSkillIds = [id];
|
|
118
|
+
} else if (!preactivatedSkillIds.includes(id)) {
|
|
119
|
+
preactivatedSkillIds.push(id);
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
async ensureActorScopedHistory() {},
|
|
123
|
+
async persistUserMessage() {
|
|
124
|
+
return "user-msg-id";
|
|
125
|
+
},
|
|
126
|
+
async runAgentLoop() {
|
|
127
|
+
// No-op: the drain path's finally block would normally call drainQueue
|
|
128
|
+
// recursively. We intentionally do not chain another drain here so the
|
|
129
|
+
// test asserts on what the FIRST dequeue produced.
|
|
130
|
+
},
|
|
131
|
+
getTurnChannelContext: () => null,
|
|
132
|
+
setTurnChannelContext() {},
|
|
133
|
+
getTurnInterfaceContext: () => opts.turnInterfaceContext ?? null,
|
|
134
|
+
setTurnInterfaceContext() {},
|
|
135
|
+
emitActivityState() {},
|
|
136
|
+
async forceCompact() {
|
|
137
|
+
return {
|
|
138
|
+
compacted: false,
|
|
139
|
+
reason: "no-op",
|
|
140
|
+
estimatedInputTokens: 0,
|
|
141
|
+
previousEstimatedInputTokens: 0,
|
|
142
|
+
maxInputTokens: 100000,
|
|
143
|
+
compactedMessages: 0,
|
|
144
|
+
} as never;
|
|
145
|
+
},
|
|
146
|
+
setTransportHints() {},
|
|
147
|
+
applyHostEnvFromTransport() {},
|
|
148
|
+
} as unknown as ProcessConversationContext & FakeRecord;
|
|
149
|
+
return ctx;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function makeQueuedMessage(opts: {
|
|
153
|
+
requestId: string;
|
|
154
|
+
content?: string;
|
|
155
|
+
turnInterfaceContext?: TurnInterfaceContext;
|
|
156
|
+
}): QueuedMessage {
|
|
157
|
+
return {
|
|
158
|
+
content: opts.content ?? "follow up",
|
|
159
|
+
attachments: [],
|
|
160
|
+
requestId: opts.requestId,
|
|
161
|
+
onEvent: () => {},
|
|
162
|
+
metadata: {},
|
|
163
|
+
sentAt: Date.now(),
|
|
164
|
+
turnInterfaceContext: opts.turnInterfaceContext,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Tests
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
describe("drainQueue preactivation re-add for host-proxy interfaces", () => {
|
|
173
|
+
test("drainSingleMessage re-adds 'app-control' for macOS-sourced queued message", async () => {
|
|
174
|
+
const queue = new MessageQueue();
|
|
175
|
+
const ifCtx: TurnInterfaceContext = {
|
|
176
|
+
userMessageInterface: "macos",
|
|
177
|
+
assistantMessageInterface: "macos",
|
|
178
|
+
};
|
|
179
|
+
queue.push(
|
|
180
|
+
makeQueuedMessage({ requestId: "req-2", turnInterfaceContext: ifCtx }),
|
|
181
|
+
);
|
|
182
|
+
const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
|
|
183
|
+
|
|
184
|
+
await drainQueue(ctx);
|
|
185
|
+
|
|
186
|
+
// Both CU and app-control must be re-preactivated for queued macOS turns.
|
|
187
|
+
expect(ctx.preactivatedSkillIdCalls).toContain("computer-use");
|
|
188
|
+
expect(ctx.preactivatedSkillIdCalls).toContain("app-control");
|
|
189
|
+
expect(ctx.preactivatedSkillIds).toContain("app-control");
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("drainSingleMessage does not re-add 'app-control' for chrome-extension (host_app_control unsupported)", async () => {
|
|
193
|
+
const queue = new MessageQueue();
|
|
194
|
+
// chrome-extension supports host_browser but NOT host_app_control. The
|
|
195
|
+
// CU re-add (no-arg form) also returns false for chrome-extension, so
|
|
196
|
+
// neither skill should be re-preactivated.
|
|
197
|
+
const ifCtx: TurnInterfaceContext = {
|
|
198
|
+
userMessageInterface: "chrome-extension",
|
|
199
|
+
assistantMessageInterface: "chrome-extension",
|
|
200
|
+
};
|
|
201
|
+
queue.push(
|
|
202
|
+
makeQueuedMessage({ requestId: "req-2", turnInterfaceContext: ifCtx }),
|
|
203
|
+
);
|
|
204
|
+
const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
|
|
205
|
+
|
|
206
|
+
await drainQueue(ctx);
|
|
207
|
+
|
|
208
|
+
expect(ctx.preactivatedSkillIdCalls).not.toContain("computer-use");
|
|
209
|
+
expect(ctx.preactivatedSkillIdCalls).not.toContain("app-control");
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("drainSingleMessage does not re-add 'app-control' for non-host-proxy interface (slack)", async () => {
|
|
213
|
+
const queue = new MessageQueue();
|
|
214
|
+
const ifCtx: TurnInterfaceContext = {
|
|
215
|
+
userMessageInterface: "slack",
|
|
216
|
+
assistantMessageInterface: "slack",
|
|
217
|
+
};
|
|
218
|
+
queue.push(
|
|
219
|
+
makeQueuedMessage({ requestId: "req-2", turnInterfaceContext: ifCtx }),
|
|
220
|
+
);
|
|
221
|
+
const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
|
|
222
|
+
|
|
223
|
+
await drainQueue(ctx);
|
|
224
|
+
|
|
225
|
+
expect(ctx.preactivatedSkillIdCalls).not.toContain("computer-use");
|
|
226
|
+
expect(ctx.preactivatedSkillIdCalls).not.toContain("app-control");
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("drainBatch re-adds 'app-control' for macOS-sourced batched queue", async () => {
|
|
230
|
+
const queue = new MessageQueue();
|
|
231
|
+
const ifCtx: TurnInterfaceContext = {
|
|
232
|
+
userMessageInterface: "macos",
|
|
233
|
+
assistantMessageInterface: "macos",
|
|
234
|
+
};
|
|
235
|
+
// Two passthrough siblings with matching interface — buildPassthroughBatch
|
|
236
|
+
// groups them into a batch, exercising drainBatch.
|
|
237
|
+
queue.push(
|
|
238
|
+
makeQueuedMessage({
|
|
239
|
+
requestId: "req-2",
|
|
240
|
+
content: "msg-2",
|
|
241
|
+
turnInterfaceContext: ifCtx,
|
|
242
|
+
}),
|
|
243
|
+
);
|
|
244
|
+
queue.push(
|
|
245
|
+
makeQueuedMessage({
|
|
246
|
+
requestId: "req-3",
|
|
247
|
+
content: "msg-3",
|
|
248
|
+
turnInterfaceContext: ifCtx,
|
|
249
|
+
}),
|
|
250
|
+
);
|
|
251
|
+
const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
|
|
252
|
+
|
|
253
|
+
await drainQueue(ctx);
|
|
254
|
+
|
|
255
|
+
// Batched path mirrors the single-message preactivation block.
|
|
256
|
+
expect(ctx.preactivatedSkillIdCalls).toContain("computer-use");
|
|
257
|
+
expect(ctx.preactivatedSkillIdCalls).toContain("app-control");
|
|
258
|
+
expect(ctx.preactivatedSkillIds).toContain("app-control");
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test("drainSingleMessage skips 'app-control' re-add when isInteractive=false", async () => {
|
|
262
|
+
const queue = new MessageQueue();
|
|
263
|
+
const ifCtx: TurnInterfaceContext = {
|
|
264
|
+
userMessageInterface: "macos",
|
|
265
|
+
assistantMessageInterface: "macos",
|
|
266
|
+
};
|
|
267
|
+
const qm = makeQueuedMessage({
|
|
268
|
+
requestId: "req-2",
|
|
269
|
+
turnInterfaceContext: ifCtx,
|
|
270
|
+
});
|
|
271
|
+
qm.isInteractive = false;
|
|
272
|
+
queue.push(qm);
|
|
273
|
+
const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
|
|
274
|
+
|
|
275
|
+
await drainQueue(ctx);
|
|
276
|
+
|
|
277
|
+
// Both branches share the outer `isInteractive !== false` gate, so
|
|
278
|
+
// app-control follows CU's behavior and is skipped for non-interactive
|
|
279
|
+
// turns even on macOS.
|
|
280
|
+
expect(ctx.preactivatedSkillIdCalls).not.toContain("computer-use");
|
|
281
|
+
expect(ctx.preactivatedSkillIdCalls).not.toContain("app-control");
|
|
282
|
+
});
|
|
283
|
+
});
|
|
@@ -207,6 +207,12 @@ function createFakeConversation(conversationId: string): Conversation {
|
|
|
207
207
|
setHostCuProxy(this: { hostCuProxy: unknown }, proxy: unknown) {
|
|
208
208
|
this.hostCuProxy = proxy;
|
|
209
209
|
},
|
|
210
|
+
setHostAppControlProxy(
|
|
211
|
+
this: { hostAppControlProxy: unknown },
|
|
212
|
+
proxy: unknown,
|
|
213
|
+
) {
|
|
214
|
+
this.hostAppControlProxy = proxy;
|
|
215
|
+
},
|
|
210
216
|
restoreBrowserProxyAvailability: () => {},
|
|
211
217
|
addPreactivatedSkillId: () => {},
|
|
212
218
|
hasAnyPendingConfirmation: () => false,
|
|
@@ -172,13 +172,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
172
172
|
hasPendingConfirmation: () => false,
|
|
173
173
|
setHostBrowserProxy: () => {},
|
|
174
174
|
setHostCuProxy: () => {},
|
|
175
|
+
setHostAppControlProxy: () => {},
|
|
175
176
|
restoreBrowserProxyAvailability: () => {},
|
|
176
177
|
addPreactivatedSkillId: () => {},
|
|
177
178
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
178
179
|
|
|
179
180
|
const req = new Request("http://localhost/v1/messages", {
|
|
180
181
|
method: "POST",
|
|
181
|
-
headers: {
|
|
182
|
+
headers: {
|
|
183
|
+
"Content-Type": "application/json",
|
|
184
|
+
"x-vellum-actor-principal-id": "test-user",
|
|
185
|
+
"x-vellum-principal-type": "actor",
|
|
186
|
+
},
|
|
182
187
|
body: JSON.stringify({
|
|
183
188
|
conversationKey: "guardian-conversation-key",
|
|
184
189
|
content: "05BECB approve",
|
|
@@ -188,17 +193,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
188
193
|
});
|
|
189
194
|
|
|
190
195
|
const res = await callHandler(
|
|
191
|
-
(args) =>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
(args) =>
|
|
197
|
+
handleSendMessage(args, {
|
|
198
|
+
sendMessageDeps: {
|
|
199
|
+
getOrCreateConversation: async () => session,
|
|
200
|
+
assistantEventHub: { publish: async () => {} } as any,
|
|
201
|
+
resolveAttachments: () => [],
|
|
202
|
+
},
|
|
203
|
+
}),
|
|
198
204
|
req,
|
|
199
205
|
undefined,
|
|
200
206
|
202,
|
|
201
|
-
|
|
207
|
+
);
|
|
202
208
|
|
|
203
209
|
expect(res.status).toBe(202);
|
|
204
210
|
const body = (await res.json()) as {
|
|
@@ -250,13 +256,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
250
256
|
hasPendingConfirmation: () => false,
|
|
251
257
|
setHostBrowserProxy: () => {},
|
|
252
258
|
setHostCuProxy: () => {},
|
|
259
|
+
setHostAppControlProxy: () => {},
|
|
253
260
|
restoreBrowserProxyAvailability: () => {},
|
|
254
261
|
addPreactivatedSkillId: () => {},
|
|
255
262
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
256
263
|
|
|
257
264
|
const req = new Request("http://localhost/v1/messages", {
|
|
258
265
|
method: "POST",
|
|
259
|
-
headers: {
|
|
266
|
+
headers: {
|
|
267
|
+
"Content-Type": "application/json",
|
|
268
|
+
"x-vellum-actor-principal-id": "test-user",
|
|
269
|
+
"x-vellum-principal-type": "actor",
|
|
270
|
+
},
|
|
260
271
|
body: JSON.stringify({
|
|
261
272
|
conversationKey: "guardian-conversation-key",
|
|
262
273
|
content: "hello there",
|
|
@@ -266,17 +277,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
266
277
|
});
|
|
267
278
|
|
|
268
279
|
const res = await callHandler(
|
|
269
|
-
(args) =>
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
280
|
+
(args) =>
|
|
281
|
+
handleSendMessage(args, {
|
|
282
|
+
sendMessageDeps: {
|
|
283
|
+
getOrCreateConversation: async () => session,
|
|
284
|
+
assistantEventHub: { publish: async () => {} } as any,
|
|
285
|
+
resolveAttachments: () => [],
|
|
286
|
+
},
|
|
287
|
+
}),
|
|
276
288
|
req,
|
|
277
289
|
undefined,
|
|
278
290
|
202,
|
|
279
|
-
|
|
291
|
+
);
|
|
280
292
|
|
|
281
293
|
expect(res.status).toBe(202);
|
|
282
294
|
expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
|
|
@@ -324,13 +336,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
324
336
|
requestId === "tool-approval-live",
|
|
325
337
|
setHostBrowserProxy: () => {},
|
|
326
338
|
setHostCuProxy: () => {},
|
|
339
|
+
setHostAppControlProxy: () => {},
|
|
327
340
|
restoreBrowserProxyAvailability: () => {},
|
|
328
341
|
addPreactivatedSkillId: () => {},
|
|
329
342
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
330
343
|
|
|
331
344
|
const req = new Request("http://localhost/v1/messages", {
|
|
332
345
|
method: "POST",
|
|
333
|
-
headers: {
|
|
346
|
+
headers: {
|
|
347
|
+
"Content-Type": "application/json",
|
|
348
|
+
"x-vellum-actor-principal-id": "test-user",
|
|
349
|
+
"x-vellum-principal-type": "actor",
|
|
350
|
+
},
|
|
334
351
|
body: JSON.stringify({
|
|
335
352
|
conversationKey: "guardian-conversation-key",
|
|
336
353
|
content: "approve",
|
|
@@ -340,17 +357,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
340
357
|
});
|
|
341
358
|
|
|
342
359
|
const res = await callHandler(
|
|
343
|
-
(args) =>
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
360
|
+
(args) =>
|
|
361
|
+
handleSendMessage(args, {
|
|
362
|
+
sendMessageDeps: {
|
|
363
|
+
getOrCreateConversation: async () => session,
|
|
364
|
+
assistantEventHub: { publish: async () => {} } as any,
|
|
365
|
+
resolveAttachments: () => [],
|
|
366
|
+
},
|
|
367
|
+
}),
|
|
350
368
|
req,
|
|
351
369
|
undefined,
|
|
352
370
|
202,
|
|
353
|
-
|
|
371
|
+
);
|
|
354
372
|
|
|
355
373
|
expect(res.status).toBe(202);
|
|
356
374
|
expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
|
|
@@ -402,13 +420,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
402
420
|
hasPendingConfirmation: (id: string) => id === "tool-req-code-1",
|
|
403
421
|
setHostBrowserProxy: () => {},
|
|
404
422
|
setHostCuProxy: () => {},
|
|
423
|
+
setHostAppControlProxy: () => {},
|
|
405
424
|
restoreBrowserProxyAvailability: () => {},
|
|
406
425
|
addPreactivatedSkillId: () => {},
|
|
407
426
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
408
427
|
|
|
409
428
|
const req = new Request("http://localhost/v1/messages", {
|
|
410
429
|
method: "POST",
|
|
411
|
-
headers: {
|
|
430
|
+
headers: {
|
|
431
|
+
"Content-Type": "application/json",
|
|
432
|
+
"x-vellum-actor-principal-id": "test-user",
|
|
433
|
+
"x-vellum-principal-type": "actor",
|
|
434
|
+
},
|
|
412
435
|
body: JSON.stringify({
|
|
413
436
|
conversationKey: "guardian-conversation-key",
|
|
414
437
|
content: "A1B2C3 approve",
|
|
@@ -418,17 +441,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
418
441
|
});
|
|
419
442
|
|
|
420
443
|
const res = await callHandler(
|
|
421
|
-
(args) =>
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
444
|
+
(args) =>
|
|
445
|
+
handleSendMessage(args, {
|
|
446
|
+
sendMessageDeps: {
|
|
447
|
+
getOrCreateConversation: async () => session,
|
|
448
|
+
assistantEventHub: { publish: async () => {} } as any,
|
|
449
|
+
resolveAttachments: () => [],
|
|
450
|
+
},
|
|
451
|
+
}),
|
|
428
452
|
req,
|
|
429
453
|
undefined,
|
|
430
454
|
202,
|
|
431
|
-
|
|
455
|
+
);
|
|
432
456
|
|
|
433
457
|
expect(res.status).toBe(202);
|
|
434
458
|
expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
|
|
@@ -476,13 +500,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
476
500
|
hasPendingConfirmation: (id: string) => id === "pending-reject-1",
|
|
477
501
|
setHostBrowserProxy: () => {},
|
|
478
502
|
setHostCuProxy: () => {},
|
|
503
|
+
setHostAppControlProxy: () => {},
|
|
479
504
|
restoreBrowserProxyAvailability: () => {},
|
|
480
505
|
addPreactivatedSkillId: () => {},
|
|
481
506
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
482
507
|
|
|
483
508
|
const req = new Request("http://localhost/v1/messages", {
|
|
484
509
|
method: "POST",
|
|
485
|
-
headers: {
|
|
510
|
+
headers: {
|
|
511
|
+
"Content-Type": "application/json",
|
|
512
|
+
"x-vellum-actor-principal-id": "test-user",
|
|
513
|
+
"x-vellum-principal-type": "actor",
|
|
514
|
+
},
|
|
486
515
|
body: JSON.stringify({
|
|
487
516
|
conversationKey: "guardian-conversation-key",
|
|
488
517
|
content: "reject",
|
|
@@ -492,17 +521,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
492
521
|
});
|
|
493
522
|
|
|
494
523
|
const res = await callHandler(
|
|
495
|
-
(args) =>
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
524
|
+
(args) =>
|
|
525
|
+
handleSendMessage(args, {
|
|
526
|
+
sendMessageDeps: {
|
|
527
|
+
getOrCreateConversation: async () => session,
|
|
528
|
+
assistantEventHub: { publish: async () => {} } as any,
|
|
529
|
+
resolveAttachments: () => [],
|
|
530
|
+
},
|
|
531
|
+
}),
|
|
502
532
|
req,
|
|
503
533
|
undefined,
|
|
504
534
|
202,
|
|
505
|
-
|
|
535
|
+
);
|
|
506
536
|
|
|
507
537
|
expect(res.status).toBe(202);
|
|
508
538
|
expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
|
|
@@ -544,13 +574,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
544
574
|
hasPendingConfirmation: (id: string) => id === "pending-1",
|
|
545
575
|
setHostBrowserProxy: () => {},
|
|
546
576
|
setHostCuProxy: () => {},
|
|
577
|
+
setHostAppControlProxy: () => {},
|
|
547
578
|
restoreBrowserProxyAvailability: () => {},
|
|
548
579
|
addPreactivatedSkillId: () => {},
|
|
549
580
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
550
581
|
|
|
551
582
|
const req = new Request("http://localhost/v1/messages", {
|
|
552
583
|
method: "POST",
|
|
553
|
-
headers: {
|
|
584
|
+
headers: {
|
|
585
|
+
"Content-Type": "application/json",
|
|
586
|
+
"x-vellum-actor-principal-id": "test-user",
|
|
587
|
+
"x-vellum-principal-type": "actor",
|
|
588
|
+
},
|
|
554
589
|
body: JSON.stringify({
|
|
555
590
|
conversationKey: "guardian-conversation-key",
|
|
556
591
|
content: "tell me more about this request",
|
|
@@ -560,17 +595,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
560
595
|
});
|
|
561
596
|
|
|
562
597
|
const res = await callHandler(
|
|
563
|
-
(args) =>
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
598
|
+
(args) =>
|
|
599
|
+
handleSendMessage(args, {
|
|
600
|
+
sendMessageDeps: {
|
|
601
|
+
getOrCreateConversation: async () => session,
|
|
602
|
+
assistantEventHub: { publish: async () => {} } as any,
|
|
603
|
+
resolveAttachments: () => [],
|
|
604
|
+
},
|
|
605
|
+
}),
|
|
570
606
|
req,
|
|
571
607
|
undefined,
|
|
572
608
|
202,
|
|
573
|
-
|
|
609
|
+
);
|
|
574
610
|
|
|
575
611
|
expect(res.status).toBe(202);
|
|
576
612
|
expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
|
|
@@ -614,13 +650,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
614
650
|
hasPendingConfirmation: () => false,
|
|
615
651
|
setHostBrowserProxy: () => {},
|
|
616
652
|
setHostCuProxy: () => {},
|
|
653
|
+
setHostAppControlProxy: () => {},
|
|
617
654
|
restoreBrowserProxyAvailability: () => {},
|
|
618
655
|
addPreactivatedSkillId: () => {},
|
|
619
656
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
620
657
|
|
|
621
658
|
const req = new Request("http://localhost/v1/messages", {
|
|
622
659
|
method: "POST",
|
|
623
|
-
headers: {
|
|
660
|
+
headers: {
|
|
661
|
+
"Content-Type": "application/json",
|
|
662
|
+
"x-vellum-actor-principal-id": "test-user",
|
|
663
|
+
"x-vellum-principal-type": "actor",
|
|
664
|
+
},
|
|
624
665
|
body: JSON.stringify({
|
|
625
666
|
conversationKey: "guardian-conversation-key",
|
|
626
667
|
content: "no sorry, beats 0 and 3 should be new threads",
|
|
@@ -630,14 +671,15 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
630
671
|
});
|
|
631
672
|
|
|
632
673
|
await callHandler(
|
|
633
|
-
(args) =>
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
674
|
+
(args) =>
|
|
675
|
+
handleSendMessage(args, {
|
|
676
|
+
sendMessageDeps: {
|
|
677
|
+
getOrCreateConversation: async () => session,
|
|
678
|
+
assistantEventHub: { publish: async () => {} } as any,
|
|
679
|
+
resolveAttachments: () => [],
|
|
680
|
+
},
|
|
681
|
+
approvalConversationGenerator: mockGenerator as any,
|
|
682
|
+
}),
|
|
641
683
|
req,
|
|
642
684
|
undefined,
|
|
643
685
|
202,
|
|
@@ -685,13 +727,18 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
685
727
|
hasPendingConfirmation: () => false,
|
|
686
728
|
setHostBrowserProxy: () => {},
|
|
687
729
|
setHostCuProxy: () => {},
|
|
730
|
+
setHostAppControlProxy: () => {},
|
|
688
731
|
restoreBrowserProxyAvailability: () => {},
|
|
689
732
|
addPreactivatedSkillId: () => {},
|
|
690
733
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
691
734
|
|
|
692
735
|
const req = new Request("http://localhost/v1/messages", {
|
|
693
736
|
method: "POST",
|
|
694
|
-
headers: {
|
|
737
|
+
headers: {
|
|
738
|
+
"Content-Type": "application/json",
|
|
739
|
+
"x-vellum-actor-principal-id": "test-user",
|
|
740
|
+
"x-vellum-principal-type": "actor",
|
|
741
|
+
},
|
|
695
742
|
body: JSON.stringify({
|
|
696
743
|
conversationKey: "guardian-conversation-key",
|
|
697
744
|
content: "no sorry, beats 0 and 3 should be new threads",
|
|
@@ -701,14 +748,15 @@ describe("handleSendMessage canonical guardian reply interception", () => {
|
|
|
701
748
|
});
|
|
702
749
|
|
|
703
750
|
await callHandler(
|
|
704
|
-
(args) =>
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
751
|
+
(args) =>
|
|
752
|
+
handleSendMessage(args, {
|
|
753
|
+
sendMessageDeps: {
|
|
754
|
+
getOrCreateConversation: async () => session,
|
|
755
|
+
assistantEventHub: { publish: async () => {} } as any,
|
|
756
|
+
resolveAttachments: () => [],
|
|
757
|
+
},
|
|
758
|
+
approvalConversationGenerator: mockGenerator as any,
|
|
759
|
+
}),
|
|
712
760
|
req,
|
|
713
761
|
undefined,
|
|
714
762
|
202,
|