@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
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route handler for host app-control result submissions.
|
|
3
|
+
*
|
|
4
|
+
* Resolves pending host app-control proxy requests by requestId when the
|
|
5
|
+
* desktop client returns observation/action results via HTTP. App-control
|
|
6
|
+
* sessions are per-conversation (not a singleton like host-browser), so we
|
|
7
|
+
* look up the owning conversation through the pending-interactions tracker
|
|
8
|
+
* and forward the payload to that conversation's `hostAppControlProxy`.
|
|
9
|
+
*
|
|
10
|
+
* Late-delivery tolerance: returns 200 even when no pending interaction
|
|
11
|
+
* matches (e.g. the conversation was disposed before the client reported
|
|
12
|
+
* back). The proxy is best-effort — there is no consumer to notify, so a
|
|
13
|
+
* 4xx would only confuse a client that already executed the action.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
|
|
17
|
+
import { findConversation } from "../../daemon/conversation-store.js";
|
|
18
|
+
import type {
|
|
19
|
+
HostAppControlResultPayload,
|
|
20
|
+
HostAppControlState,
|
|
21
|
+
} from "../../daemon/message-types/host-app-control.js";
|
|
22
|
+
import * as pendingInteractions from "../pending-interactions.js";
|
|
23
|
+
import { BadRequestError } from "./errors.js";
|
|
24
|
+
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
25
|
+
|
|
26
|
+
const VALID_STATES: ReadonlySet<HostAppControlState> = new Set([
|
|
27
|
+
"running",
|
|
28
|
+
"missing",
|
|
29
|
+
"minimized",
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// POST /v1/host-app-control-result
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
function handleHostAppControlResult({ body }: RouteHandlerArgs) {
|
|
37
|
+
if (!body || typeof body !== "object") {
|
|
38
|
+
throw new BadRequestError("Request body is required");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const {
|
|
42
|
+
requestId,
|
|
43
|
+
state,
|
|
44
|
+
pngBase64,
|
|
45
|
+
windowBounds,
|
|
46
|
+
executionResult,
|
|
47
|
+
executionError,
|
|
48
|
+
} = body as {
|
|
49
|
+
requestId?: string;
|
|
50
|
+
state?: string;
|
|
51
|
+
pngBase64?: string;
|
|
52
|
+
windowBounds?: { x: number; y: number; width: number; height: number };
|
|
53
|
+
executionResult?: string;
|
|
54
|
+
executionError?: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
if (!requestId || typeof requestId !== "string") {
|
|
58
|
+
throw new BadRequestError("requestId is required");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!state || !VALID_STATES.has(state as HostAppControlState)) {
|
|
62
|
+
throw new BadRequestError(
|
|
63
|
+
"state must be one of: running, missing, minimized",
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Late-delivery tolerance: if the pending interaction is already gone (the
|
|
68
|
+
// proxy timed out, the conversation was disposed, etc.), accept the post
|
|
69
|
+
// and move on. There is no consumer left to fail loudly to.
|
|
70
|
+
const peeked = pendingInteractions.get(requestId);
|
|
71
|
+
if (!peeked || peeked.kind !== "host_app_control") {
|
|
72
|
+
return { accepted: true };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const interaction = pendingInteractions.resolve(requestId)!;
|
|
76
|
+
const conversation = findConversation(interaction.conversationId);
|
|
77
|
+
if (!conversation) {
|
|
78
|
+
return { accepted: true };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const payload: HostAppControlResultPayload = {
|
|
82
|
+
requestId,
|
|
83
|
+
state: state as HostAppControlState,
|
|
84
|
+
...(pngBase64 !== undefined ? { pngBase64 } : {}),
|
|
85
|
+
...(windowBounds !== undefined ? { windowBounds } : {}),
|
|
86
|
+
...(executionResult !== undefined ? { executionResult } : {}),
|
|
87
|
+
...(executionError !== undefined ? { executionError } : {}),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
conversation.hostAppControlProxy?.resolve(requestId, payload);
|
|
91
|
+
|
|
92
|
+
return { accepted: true };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Route definitions (shared HTTP + IPC)
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
export const ROUTES: RouteDefinition[] = [
|
|
100
|
+
{
|
|
101
|
+
operationId: "host_app_control_result",
|
|
102
|
+
endpoint: "host-app-control-result",
|
|
103
|
+
method: "POST",
|
|
104
|
+
requireGuardian: true,
|
|
105
|
+
summary: "Submit host app-control result",
|
|
106
|
+
description:
|
|
107
|
+
"Resolve a pending host app-control request by requestId. Returns 200 even when no pending interaction matches (late delivery is tolerated).",
|
|
108
|
+
tags: ["host"],
|
|
109
|
+
requestBody: z.object({
|
|
110
|
+
requestId: z.string().describe("Pending app-control request ID"),
|
|
111
|
+
state: z
|
|
112
|
+
.enum(["running", "missing", "minimized"])
|
|
113
|
+
.describe("Lifecycle state of the targeted application"),
|
|
114
|
+
pngBase64: z
|
|
115
|
+
.string()
|
|
116
|
+
.describe("Base64 PNG screenshot of the targeted app window")
|
|
117
|
+
.optional(),
|
|
118
|
+
windowBounds: z
|
|
119
|
+
.object({
|
|
120
|
+
x: z.number(),
|
|
121
|
+
y: z.number(),
|
|
122
|
+
width: z.number(),
|
|
123
|
+
height: z.number(),
|
|
124
|
+
})
|
|
125
|
+
.optional(),
|
|
126
|
+
executionResult: z.string().optional(),
|
|
127
|
+
executionError: z.string().optional(),
|
|
128
|
+
}),
|
|
129
|
+
responseBody: z.object({
|
|
130
|
+
accepted: z.boolean(),
|
|
131
|
+
}),
|
|
132
|
+
handler: handleHostAppControlResult,
|
|
133
|
+
},
|
|
134
|
+
];
|
|
@@ -7,10 +7,16 @@
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
9
9
|
import { HostBashProxy } from "../../daemon/host-bash-proxy.js";
|
|
10
|
+
import {
|
|
11
|
+
enforceSameActorOrThrow,
|
|
12
|
+
SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
13
|
+
} from "../auth/same-actor.js";
|
|
14
|
+
import { resolveActorPrincipalIdForLocalGuardian } from "../local-actor-identity.js";
|
|
10
15
|
import * as pendingInteractions from "../pending-interactions.js";
|
|
11
16
|
import {
|
|
12
17
|
BadRequestError,
|
|
13
18
|
ConflictError,
|
|
19
|
+
ForbiddenError,
|
|
14
20
|
NotFoundError,
|
|
15
21
|
} from "./errors.js";
|
|
16
22
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
@@ -19,7 +25,7 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
19
25
|
// POST /v1/host-bash-result
|
|
20
26
|
// ---------------------------------------------------------------------------
|
|
21
27
|
|
|
22
|
-
function handleHostBashResult({ body }: RouteHandlerArgs) {
|
|
28
|
+
function handleHostBashResult({ body, headers }: RouteHandlerArgs) {
|
|
23
29
|
if (!body || typeof body !== "object") {
|
|
24
30
|
throw new BadRequestError("Request body is required");
|
|
25
31
|
}
|
|
@@ -36,11 +42,15 @@ function handleHostBashResult({ body }: RouteHandlerArgs) {
|
|
|
36
42
|
throw new BadRequestError("requestId is required");
|
|
37
43
|
}
|
|
38
44
|
|
|
45
|
+
const submittingClientId =
|
|
46
|
+
headers?.["x-vellum-client-id"]?.trim() || undefined;
|
|
47
|
+
const submittingActorPrincipalId = resolveActorPrincipalIdForLocalGuardian(
|
|
48
|
+
headers?.["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
49
|
+
);
|
|
50
|
+
|
|
39
51
|
const peeked = pendingInteractions.get(requestId);
|
|
40
52
|
if (!peeked) {
|
|
41
|
-
throw new NotFoundError(
|
|
42
|
-
"No pending interaction found for this requestId",
|
|
43
|
-
);
|
|
53
|
+
throw new NotFoundError("No pending interaction found for this requestId");
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
if (peeked.kind !== "host_bash") {
|
|
@@ -49,9 +59,33 @@ function handleHostBashResult({ body }: RouteHandlerArgs) {
|
|
|
49
59
|
);
|
|
50
60
|
}
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
const { targetClientId } = peeked;
|
|
63
|
+
if (targetClientId) {
|
|
64
|
+
if (!submittingClientId) {
|
|
65
|
+
throw new BadRequestError(
|
|
66
|
+
"x-vellum-client-id header is required for targeted host bash requests",
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (submittingClientId !== targetClientId) {
|
|
70
|
+
throw new ForbiddenError(
|
|
71
|
+
`Client "${submittingClientId}" is not the target for this request (expected "${targetClientId}"). The targeted client must submit the result.`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Defense-in-depth on top of the client-id header binding above: the
|
|
76
|
+
// submitting actor's principal must match the actor principal stored
|
|
77
|
+
// for the target client at SSE subscription time. This prevents a
|
|
78
|
+
// cross-user submission even when the attacker can guess or spoof the
|
|
79
|
+
// target's client ID.
|
|
80
|
+
enforceSameActorOrThrow({
|
|
81
|
+
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
82
|
+
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
83
|
+
targetClientId,
|
|
84
|
+
op: "host_bash",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
53
87
|
|
|
54
|
-
HostBashProxy.instance.
|
|
88
|
+
HostBashProxy.instance.resolveResult(requestId, {
|
|
55
89
|
stdout: stdout ?? "",
|
|
56
90
|
stderr: stderr ?? "",
|
|
57
91
|
exitCode: exitCode ?? null,
|
|
@@ -84,6 +118,22 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
84
118
|
responseBody: z.object({
|
|
85
119
|
accepted: z.boolean(),
|
|
86
120
|
}),
|
|
121
|
+
additionalResponses: {
|
|
122
|
+
"400": {
|
|
123
|
+
description:
|
|
124
|
+
"x-vellum-client-id header is missing for a targeted host bash request.",
|
|
125
|
+
},
|
|
126
|
+
"403": {
|
|
127
|
+
description: SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
128
|
+
},
|
|
129
|
+
"404": {
|
|
130
|
+
description: "No pending interaction found for the given requestId.",
|
|
131
|
+
},
|
|
132
|
+
"409": {
|
|
133
|
+
description:
|
|
134
|
+
"Pending interaction exists but is of a different kind (e.g. host_file, host_cu).",
|
|
135
|
+
},
|
|
136
|
+
},
|
|
87
137
|
handler: handleHostBashResult,
|
|
88
138
|
},
|
|
89
139
|
];
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
publishCdpEvent,
|
|
12
12
|
} from "../../browser-session/events.js";
|
|
13
13
|
import { HostBrowserProxy } from "../../daemon/host-browser-proxy.js";
|
|
14
|
-
import
|
|
14
|
+
import * as pendingInteractions from "../pending-interactions.js";
|
|
15
|
+
import { BadRequestError, ConflictError, NotFoundError } from "./errors.js";
|
|
15
16
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -29,21 +30,26 @@ export type HostBrowserResultResolution =
|
|
|
29
30
|
| { ok: true }
|
|
30
31
|
| {
|
|
31
32
|
ok: false;
|
|
32
|
-
code: "BAD_REQUEST" | "NOT_FOUND";
|
|
33
|
-
status: 400 | 404;
|
|
33
|
+
code: "BAD_REQUEST" | "NOT_FOUND" | "CONFLICT";
|
|
34
|
+
status: 400 | 404 | 409;
|
|
34
35
|
message: string;
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
39
|
+
* Resolver for the `POST /v1/host-browser-result` HTTP route. Looks up
|
|
40
|
+
* the pending interaction by requestId, validates its kind is
|
|
41
|
+
* `host_browser`, and forwards the response to the owning conversation.
|
|
42
|
+
*
|
|
43
|
+
* NOTE: The WebSocket `host_browser_result` frame path does NOT go
|
|
44
|
+
* through this function — it is handled by `HostBrowserProxy.resolveResult`
|
|
45
|
+
* directly, which only consults `pendingInteractions` and does not
|
|
46
|
+
* currently perform a kind check. That asymmetry is pre-existing; if
|
|
47
|
+
* the WS path is ever opened to less-trusted clients, it should adopt
|
|
48
|
+
* the same kind-check guard added here.
|
|
42
49
|
*
|
|
43
50
|
* This function does NOT perform auth — callers are expected to have
|
|
44
51
|
* already authenticated the caller (the HTTP route uses
|
|
45
|
-
* `requireBoundGuardian
|
|
46
|
-
* at WebSocket upgrade time).
|
|
52
|
+
* `requireBoundGuardian`).
|
|
47
53
|
*/
|
|
48
54
|
export function resolveHostBrowserResultByRequestId(frame: {
|
|
49
55
|
requestId?: unknown;
|
|
@@ -61,20 +67,30 @@ export function resolveHostBrowserResultByRequestId(frame: {
|
|
|
61
67
|
};
|
|
62
68
|
}
|
|
63
69
|
|
|
64
|
-
const
|
|
65
|
-
if (!
|
|
70
|
+
const peeked = pendingInteractions.get(requestId);
|
|
71
|
+
if (!peeked) {
|
|
66
72
|
return {
|
|
67
73
|
ok: false,
|
|
68
74
|
code: "NOT_FOUND",
|
|
69
75
|
status: 404,
|
|
70
|
-
message: "No pending
|
|
76
|
+
message: "No pending browser request for this requestId",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (peeked.kind !== "host_browser") {
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
code: "CONFLICT",
|
|
84
|
+
status: 409,
|
|
85
|
+
message: `Pending interaction is of kind "${peeked.kind}", expected "host_browser"`,
|
|
71
86
|
};
|
|
72
87
|
}
|
|
73
88
|
|
|
74
89
|
const normalizedContent = typeof content === "string" ? content : "";
|
|
75
90
|
const normalizedIsError = typeof isError === "boolean" ? isError : false;
|
|
76
91
|
|
|
77
|
-
proxy.
|
|
92
|
+
const proxy = HostBrowserProxy.instance;
|
|
93
|
+
proxy.resolveResult(requestId, {
|
|
78
94
|
content: normalizedContent,
|
|
79
95
|
isError: normalizedIsError,
|
|
80
96
|
});
|
|
@@ -181,6 +197,42 @@ function handleHostBrowserResult({ body }: RouteHandlerArgs) {
|
|
|
181
197
|
if (!resolution.ok) {
|
|
182
198
|
if (resolution.code === "NOT_FOUND")
|
|
183
199
|
throw new NotFoundError(resolution.message);
|
|
200
|
+
if (resolution.code === "CONFLICT")
|
|
201
|
+
throw new ConflictError(resolution.message);
|
|
202
|
+
throw new BadRequestError(resolution.message);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return { accepted: true };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
// POST /v1/host-browser-event
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
|
|
212
|
+
function handleHostBrowserEvent({ body }: RouteHandlerArgs) {
|
|
213
|
+
if (!body || typeof body !== "object") {
|
|
214
|
+
throw new BadRequestError("Request body is required");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const resolution = resolveHostBrowserEvent(body);
|
|
218
|
+
if (!resolution.ok) {
|
|
219
|
+
throw new BadRequestError(resolution.message);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return { accepted: true };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
// POST /v1/host-browser-session-invalidated
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
|
|
229
|
+
function handleHostBrowserSessionInvalidated({ body }: RouteHandlerArgs) {
|
|
230
|
+
if (!body || typeof body !== "object") {
|
|
231
|
+
throw new BadRequestError("Request body is required");
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const resolution = resolveHostBrowserSessionInvalidated(body);
|
|
235
|
+
if (!resolution.ok) {
|
|
184
236
|
throw new BadRequestError(resolution.message);
|
|
185
237
|
}
|
|
186
238
|
|
|
@@ -210,4 +262,47 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
210
262
|
}),
|
|
211
263
|
handler: handleHostBrowserResult,
|
|
212
264
|
},
|
|
265
|
+
{
|
|
266
|
+
operationId: "host_browser_event",
|
|
267
|
+
endpoint: "host-browser-event",
|
|
268
|
+
method: "POST",
|
|
269
|
+
requireGuardian: true,
|
|
270
|
+
summary: "Forward a CDP event from the browser extension",
|
|
271
|
+
description:
|
|
272
|
+
"Publishes a chrome.debugger.onEvent firing into the runtime-side browser-session event bus.",
|
|
273
|
+
tags: ["host"],
|
|
274
|
+
requestBody: z.object({
|
|
275
|
+
method: z.string().describe("CDP event method name"),
|
|
276
|
+
params: z.unknown().optional().describe("CDP event parameters"),
|
|
277
|
+
cdpSessionId: z
|
|
278
|
+
.string()
|
|
279
|
+
.optional()
|
|
280
|
+
.describe("CDP session ID (if target-scoped)"),
|
|
281
|
+
}),
|
|
282
|
+
responseBody: z.object({
|
|
283
|
+
accepted: z.boolean(),
|
|
284
|
+
}),
|
|
285
|
+
handler: handleHostBrowserEvent,
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
operationId: "host_browser_session_invalidated",
|
|
289
|
+
endpoint: "host-browser-session-invalidated",
|
|
290
|
+
method: "POST",
|
|
291
|
+
requireGuardian: true,
|
|
292
|
+
summary: "Notify runtime that a CDP session was invalidated",
|
|
293
|
+
description:
|
|
294
|
+
"Marks the target as invalidated in the runtime-side browser session registry.",
|
|
295
|
+
tags: ["host"],
|
|
296
|
+
requestBody: z.object({
|
|
297
|
+
targetId: z
|
|
298
|
+
.string()
|
|
299
|
+
.optional()
|
|
300
|
+
.describe("CDP target that was detached"),
|
|
301
|
+
reason: z.string().optional().describe("Detach reason"),
|
|
302
|
+
}),
|
|
303
|
+
responseBody: z.object({
|
|
304
|
+
accepted: z.boolean(),
|
|
305
|
+
}),
|
|
306
|
+
handler: handleHostBrowserSessionInvalidated,
|
|
307
|
+
},
|
|
213
308
|
];
|
|
@@ -7,10 +7,16 @@
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
9
9
|
import { findConversation } from "../../daemon/conversation-store.js";
|
|
10
|
+
import {
|
|
11
|
+
enforceSameActorOrThrow,
|
|
12
|
+
SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
13
|
+
} from "../auth/same-actor.js";
|
|
14
|
+
import { resolveActorPrincipalIdForLocalGuardian } from "../local-actor-identity.js";
|
|
10
15
|
import * as pendingInteractions from "../pending-interactions.js";
|
|
11
16
|
import {
|
|
12
17
|
BadRequestError,
|
|
13
18
|
ConflictError,
|
|
19
|
+
ForbiddenError,
|
|
14
20
|
NotFoundError,
|
|
15
21
|
} from "./errors.js";
|
|
16
22
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
@@ -19,7 +25,7 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
19
25
|
// POST /v1/host-cu-result
|
|
20
26
|
// ---------------------------------------------------------------------------
|
|
21
27
|
|
|
22
|
-
function handleHostCuResult({ body }: RouteHandlerArgs) {
|
|
28
|
+
function handleHostCuResult({ body, headers }: RouteHandlerArgs) {
|
|
23
29
|
if (!body || typeof body !== "object") {
|
|
24
30
|
throw new BadRequestError("Request body is required");
|
|
25
31
|
}
|
|
@@ -58,9 +64,7 @@ function handleHostCuResult({ body }: RouteHandlerArgs) {
|
|
|
58
64
|
|
|
59
65
|
const peeked = pendingInteractions.get(requestId);
|
|
60
66
|
if (!peeked) {
|
|
61
|
-
throw new NotFoundError(
|
|
62
|
-
"No pending interaction found for this requestId",
|
|
63
|
-
);
|
|
67
|
+
throw new NotFoundError("No pending interaction found for this requestId");
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
if (peeked.kind !== "host_cu") {
|
|
@@ -69,13 +73,50 @@ function handleHostCuResult({ body }: RouteHandlerArgs) {
|
|
|
69
73
|
);
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
// Validate submitting client matches the targeted client (if any).
|
|
77
|
+
if (peeked.targetClientId != null) {
|
|
78
|
+
const headerMap = (headers as Record<string, string | undefined>) ?? {};
|
|
79
|
+
const submittingClientId =
|
|
80
|
+
headerMap["x-vellum-client-id"]?.trim() || undefined;
|
|
81
|
+
if (!submittingClientId) {
|
|
82
|
+
throw new BadRequestError(
|
|
83
|
+
"x-vellum-client-id header is missing for a targeted host CU request.",
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (submittingClientId !== peeked.targetClientId) {
|
|
87
|
+
throw new ForbiddenError(
|
|
88
|
+
`Client "${submittingClientId}" is not the target for this request (expected "${peeked.targetClientId}"). The targeted client must submit the result.`,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Defense-in-depth: require the submitting actor's principal id to match
|
|
93
|
+
// the actor principal id captured when the target client opened its SSE
|
|
94
|
+
// stream. This prevents a different authenticated user with knowledge of
|
|
95
|
+
// both the requestId and target clientId from submitting a result on
|
|
96
|
+
// behalf of the targeted client.
|
|
97
|
+
const submittingActorPrincipalId = resolveActorPrincipalIdForLocalGuardian(
|
|
98
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
99
|
+
);
|
|
100
|
+
enforceSameActorOrThrow({
|
|
101
|
+
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
102
|
+
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
103
|
+
targetClientId: peeked.targetClientId,
|
|
104
|
+
op: "host_cu",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const conversation = findConversation(peeked.conversationId);
|
|
74
109
|
if (!conversation) {
|
|
110
|
+
pendingInteractions.resolve(requestId);
|
|
75
111
|
throw new NotFoundError("Conversation not found for host CU result");
|
|
76
112
|
}
|
|
77
113
|
|
|
78
|
-
conversation.hostCuProxy
|
|
114
|
+
if (!conversation.hostCuProxy) {
|
|
115
|
+
pendingInteractions.resolve(requestId);
|
|
116
|
+
throw new NotFoundError("No host CU proxy for conversation");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
conversation.hostCuProxy.processObservation(requestId, {
|
|
79
120
|
axTree,
|
|
80
121
|
axDiff,
|
|
81
122
|
screenshot,
|
|
@@ -103,8 +144,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
103
144
|
method: "POST",
|
|
104
145
|
requireGuardian: true,
|
|
105
146
|
summary: "Submit host CU result",
|
|
106
|
-
description:
|
|
107
|
-
"Resolve a pending host computer-use request by requestId.",
|
|
147
|
+
description: "Resolve a pending host computer-use request by requestId.",
|
|
108
148
|
tags: ["host"],
|
|
109
149
|
requestBody: z.object({
|
|
110
150
|
requestId: z.string().describe("Pending CU request ID"),
|
|
@@ -123,6 +163,23 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
123
163
|
responseBody: z.object({
|
|
124
164
|
accepted: z.boolean(),
|
|
125
165
|
}),
|
|
166
|
+
additionalResponses: {
|
|
167
|
+
"400": {
|
|
168
|
+
description:
|
|
169
|
+
"x-vellum-client-id header is missing for a targeted host CU request.",
|
|
170
|
+
},
|
|
171
|
+
"403": {
|
|
172
|
+
description: SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
173
|
+
},
|
|
174
|
+
"404": {
|
|
175
|
+
description:
|
|
176
|
+
"No pending interaction found for the given requestId, or the conversation/proxy no longer exists.",
|
|
177
|
+
},
|
|
178
|
+
"409": {
|
|
179
|
+
description:
|
|
180
|
+
"Pending interaction exists but is of a different kind (e.g. host_bash, host_file).",
|
|
181
|
+
},
|
|
182
|
+
},
|
|
126
183
|
handler: handleHostCuResult,
|
|
127
184
|
},
|
|
128
185
|
];
|
|
@@ -7,10 +7,16 @@
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
9
9
|
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
10
|
+
import {
|
|
11
|
+
enforceSameActorOrThrow,
|
|
12
|
+
SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
13
|
+
} from "../auth/same-actor.js";
|
|
14
|
+
import { resolveActorPrincipalIdForLocalGuardian } from "../local-actor-identity.js";
|
|
10
15
|
import * as pendingInteractions from "../pending-interactions.js";
|
|
11
16
|
import {
|
|
12
17
|
BadRequestError,
|
|
13
18
|
ConflictError,
|
|
19
|
+
ForbiddenError,
|
|
14
20
|
NotFoundError,
|
|
15
21
|
} from "./errors.js";
|
|
16
22
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
@@ -19,7 +25,7 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
19
25
|
// POST /v1/host-file-result
|
|
20
26
|
// ---------------------------------------------------------------------------
|
|
21
27
|
|
|
22
|
-
function handleHostFileResult({ body }: RouteHandlerArgs) {
|
|
28
|
+
function handleHostFileResult({ body, headers }: RouteHandlerArgs) {
|
|
23
29
|
if (!body || typeof body !== "object") {
|
|
24
30
|
throw new BadRequestError("Request body is required");
|
|
25
31
|
}
|
|
@@ -37,9 +43,7 @@ function handleHostFileResult({ body }: RouteHandlerArgs) {
|
|
|
37
43
|
|
|
38
44
|
const peeked = pendingInteractions.get(requestId);
|
|
39
45
|
if (!peeked) {
|
|
40
|
-
throw new NotFoundError(
|
|
41
|
-
"No pending interaction found for this requestId",
|
|
42
|
-
);
|
|
46
|
+
throw new NotFoundError("No pending interaction found for this requestId");
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
if (peeked.kind !== "host_file") {
|
|
@@ -48,7 +52,36 @@ function handleHostFileResult({ body }: RouteHandlerArgs) {
|
|
|
48
52
|
);
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
// Validate submitting client matches the targeted client (if any).
|
|
56
|
+
if (peeked.targetClientId != null) {
|
|
57
|
+
const headerMap = (headers as Record<string, string | undefined>) ?? {};
|
|
58
|
+
const submittingClientId =
|
|
59
|
+
headerMap["x-vellum-client-id"]?.trim() || undefined;
|
|
60
|
+
if (!submittingClientId) {
|
|
61
|
+
throw new BadRequestError(
|
|
62
|
+
"x-vellum-client-id header is missing for a targeted host file request.",
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (submittingClientId !== peeked.targetClientId) {
|
|
66
|
+
throw new ForbiddenError(
|
|
67
|
+
`Client "${submittingClientId}" is not the target for this request (expected "${peeked.targetClientId}"). The targeted client must submit the result.`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Defense-in-depth: also require the submitting actor's principal id to
|
|
72
|
+
// match the actor that opened the target client's SSE stream. This blocks
|
|
73
|
+
// cross-user submissions even if a different user somehow obtains the
|
|
74
|
+
// target client id.
|
|
75
|
+
const submittingActorPrincipalId = resolveActorPrincipalIdForLocalGuardian(
|
|
76
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
77
|
+
);
|
|
78
|
+
enforceSameActorOrThrow({
|
|
79
|
+
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
80
|
+
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
81
|
+
targetClientId: peeked.targetClientId,
|
|
82
|
+
op: "host_file",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
52
85
|
|
|
53
86
|
HostFileProxy.instance.resolve(requestId, {
|
|
54
87
|
content: content ?? "",
|
|
@@ -90,6 +123,22 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
90
123
|
responseBody: z.object({
|
|
91
124
|
accepted: z.boolean(),
|
|
92
125
|
}),
|
|
126
|
+
additionalResponses: {
|
|
127
|
+
"400": {
|
|
128
|
+
description:
|
|
129
|
+
"x-vellum-client-id header is missing for a targeted host file request.",
|
|
130
|
+
},
|
|
131
|
+
"403": {
|
|
132
|
+
description: SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
133
|
+
},
|
|
134
|
+
"404": {
|
|
135
|
+
description: "No pending interaction found for the given requestId.",
|
|
136
|
+
},
|
|
137
|
+
"409": {
|
|
138
|
+
description:
|
|
139
|
+
"Pending interaction exists but is of a different kind (e.g. host_bash, host_cu).",
|
|
140
|
+
},
|
|
141
|
+
},
|
|
93
142
|
handler: handleHostFileResult,
|
|
94
143
|
},
|
|
95
144
|
];
|