@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
|
@@ -4,12 +4,16 @@ import {
|
|
|
4
4
|
assistantEventHub,
|
|
5
5
|
broadcastMessage,
|
|
6
6
|
} from "../runtime/assistant-event-hub.js";
|
|
7
|
+
import {
|
|
8
|
+
ambiguousSameUserError,
|
|
9
|
+
enforceSameActorOrErrorResult,
|
|
10
|
+
pickSameUserAutoResolve,
|
|
11
|
+
} from "../runtime/auth/same-actor.js";
|
|
7
12
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
8
13
|
import { readImageBase64 } from "../tools/shared/filesystem/image-read.js";
|
|
9
14
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
10
15
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
11
16
|
import { getLogger } from "../util/logger.js";
|
|
12
|
-
import type { ServerMessage } from "./message-protocol.js";
|
|
13
17
|
import type { HostFileRequest } from "./message-types/host-file.js";
|
|
14
18
|
|
|
15
19
|
/** Distributive omit that preserves union variant fields. */
|
|
@@ -25,17 +29,6 @@ export type HostFileInput = DistributiveOmit<
|
|
|
25
29
|
|
|
26
30
|
const log = getLogger("host-file-proxy");
|
|
27
31
|
|
|
28
|
-
interface PendingRequest {
|
|
29
|
-
resolve: (result: ToolExecutionResult) => void;
|
|
30
|
-
reject: (err: Error) => void;
|
|
31
|
-
timer: ReturnType<typeof setTimeout>;
|
|
32
|
-
operation: HostFileInput["operation"];
|
|
33
|
-
path: string;
|
|
34
|
-
conversationId: string;
|
|
35
|
-
/** Detach the abort listener from the caller's signal. No-op when no signal was passed. */
|
|
36
|
-
detachAbort: () => void;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
32
|
export class HostFileProxy {
|
|
40
33
|
private static _instance: HostFileProxy | null = null;
|
|
41
34
|
|
|
@@ -65,8 +58,6 @@ export class HostFileProxy {
|
|
|
65
58
|
HostFileProxy._instance = null;
|
|
66
59
|
}
|
|
67
60
|
|
|
68
|
-
private pending = new Map<string, PendingRequest>();
|
|
69
|
-
|
|
70
61
|
/**
|
|
71
62
|
* Whether a client with `host_file` capability is connected.
|
|
72
63
|
* Note: host_file covers both file operations and transfers.
|
|
@@ -77,56 +68,106 @@ export class HostFileProxy {
|
|
|
77
68
|
);
|
|
78
69
|
}
|
|
79
70
|
|
|
80
|
-
private send(msg: ServerMessage): void {
|
|
81
|
-
broadcastMessage(msg, undefined, { targetCapability: "host_file" });
|
|
82
|
-
}
|
|
83
|
-
|
|
84
71
|
request(
|
|
85
72
|
input: HostFileInput,
|
|
86
73
|
conversationId: string,
|
|
87
74
|
signal?: AbortSignal,
|
|
75
|
+
targetClientId?: string,
|
|
76
|
+
sourceActorPrincipalId?: string,
|
|
88
77
|
): Promise<ToolExecutionResult> {
|
|
89
78
|
if (signal?.aborted) {
|
|
90
79
|
return Promise.resolve({ content: "Aborted", isError: true });
|
|
91
80
|
}
|
|
92
81
|
|
|
82
|
+
// Resolve targetClientId: explicit → validate; single same-user
|
|
83
|
+
// capable client → auto-resolve. Callers may embed targetClientId in
|
|
84
|
+
// the input object (tool handlers) or pass it as the 4th parameter
|
|
85
|
+
// (legacy). Prefer the explicit param; fall back to input field.
|
|
86
|
+
let resolvedTargetClientId: string | undefined =
|
|
87
|
+
targetClientId ?? input.targetClientId;
|
|
88
|
+
if (resolvedTargetClientId != null) {
|
|
89
|
+
const client = assistantEventHub.getClientById(resolvedTargetClientId);
|
|
90
|
+
if (!client) {
|
|
91
|
+
return Promise.resolve({
|
|
92
|
+
content: `No connected client with id '${resolvedTargetClientId}' supports host_file. Run \`assistant clients list --capability host_file\` to see available clients.`,
|
|
93
|
+
isError: true,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (!client.capabilities.includes("host_file")) {
|
|
97
|
+
return Promise.resolve({
|
|
98
|
+
content: `Client '${resolvedTargetClientId}' does not support host_file. Run \`assistant clients list --capability host_file\` to see available clients.`,
|
|
99
|
+
isError: true,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
// Auto-resolve to the unique same-user client. Reject ambiguous
|
|
104
|
+
// (multi-machine) cases so a single targeted-style request cannot
|
|
105
|
+
// fan out across the user's machines.
|
|
106
|
+
const resolved = pickSameUserAutoResolve({
|
|
107
|
+
hub: assistantEventHub,
|
|
108
|
+
capability: "host_file",
|
|
109
|
+
sourceActorPrincipalId,
|
|
110
|
+
});
|
|
111
|
+
if (resolved.kind === "ambiguous") {
|
|
112
|
+
return Promise.resolve(ambiguousSameUserError("host_file"));
|
|
113
|
+
}
|
|
114
|
+
resolvedTargetClientId =
|
|
115
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Same-user check: targeted host_file requests must be bound to the same
|
|
119
|
+
// authenticated user identity that opened the target client's SSE stream.
|
|
120
|
+
// Prevents cross-user routing through actor token mis-targeting.
|
|
121
|
+
if (resolvedTargetClientId != null) {
|
|
122
|
+
const rejection = enforceSameActorOrErrorResult({
|
|
123
|
+
hub: assistantEventHub,
|
|
124
|
+
sourceActorPrincipalId,
|
|
125
|
+
targetClientId: resolvedTargetClientId,
|
|
126
|
+
op: "host_file",
|
|
127
|
+
});
|
|
128
|
+
if (rejection) return Promise.resolve(rejection);
|
|
129
|
+
}
|
|
130
|
+
|
|
93
131
|
const requestId = uuid();
|
|
94
132
|
|
|
95
133
|
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
96
|
-
// File operations should be fast — 30 second timeout.
|
|
97
134
|
const timeoutSec = 30;
|
|
98
135
|
|
|
99
136
|
let detachAbort: () => void = () => {};
|
|
100
137
|
|
|
101
138
|
const timer = setTimeout(() => {
|
|
102
|
-
this.pending.delete(requestId);
|
|
103
|
-
detachAbort();
|
|
104
139
|
pendingInteractions.resolve(requestId);
|
|
105
140
|
log.warn(
|
|
106
141
|
{ requestId, operation: input.operation },
|
|
107
142
|
"Host file proxy request timed out",
|
|
108
143
|
);
|
|
109
144
|
resolve({
|
|
110
|
-
content:
|
|
145
|
+
content: resolvedTargetClientId
|
|
146
|
+
? `Host file proxy timed out waiting for response from client '${resolvedTargetClientId}'`
|
|
147
|
+
: "Host file proxy timed out waiting for client response",
|
|
111
148
|
isError: true,
|
|
112
149
|
});
|
|
113
150
|
}, timeoutSec * 1000);
|
|
114
151
|
|
|
115
152
|
if (signal) {
|
|
116
153
|
const onAbort = () => {
|
|
117
|
-
if (
|
|
118
|
-
clearTimeout(timer);
|
|
119
|
-
this.pending.delete(requestId);
|
|
120
|
-
detachAbort();
|
|
154
|
+
if (pendingInteractions.get(requestId)) {
|
|
121
155
|
pendingInteractions.resolve(requestId);
|
|
122
156
|
try {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
157
|
+
broadcastMessage(
|
|
158
|
+
{
|
|
159
|
+
type: "host_file_cancel",
|
|
160
|
+
requestId,
|
|
161
|
+
conversationId,
|
|
162
|
+
...(resolvedTargetClientId != null
|
|
163
|
+
? { targetClientId: resolvedTargetClientId }
|
|
164
|
+
: {}),
|
|
165
|
+
},
|
|
126
166
|
conversationId,
|
|
127
|
-
|
|
167
|
+
{ targetClientId: resolvedTargetClientId },
|
|
168
|
+
);
|
|
128
169
|
} catch {
|
|
129
|
-
// Best-effort cancel notification
|
|
170
|
+
// Best-effort cancel notification
|
|
130
171
|
}
|
|
131
172
|
resolve({ content: "Aborted", isError: true });
|
|
132
173
|
}
|
|
@@ -135,27 +176,40 @@ export class HostFileProxy {
|
|
|
135
176
|
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
136
177
|
}
|
|
137
178
|
|
|
138
|
-
|
|
139
|
-
resolve,
|
|
140
|
-
reject,
|
|
141
|
-
timer,
|
|
142
|
-
operation: input.operation,
|
|
143
|
-
path: input.path,
|
|
179
|
+
pendingInteractions.register(requestId, {
|
|
144
180
|
conversationId,
|
|
181
|
+
kind: "host_file",
|
|
182
|
+
targetClientId: resolvedTargetClientId,
|
|
183
|
+
targetActorPrincipalId:
|
|
184
|
+
resolvedTargetClientId != null
|
|
185
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
186
|
+
resolvedTargetClientId,
|
|
187
|
+
)
|
|
188
|
+
: undefined,
|
|
189
|
+
rpcResolve: resolve,
|
|
190
|
+
rpcReject: reject,
|
|
191
|
+
timer,
|
|
145
192
|
detachAbort,
|
|
193
|
+
metadata: { operation: input.operation, path: input.path },
|
|
146
194
|
});
|
|
147
195
|
|
|
148
196
|
try {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
197
|
+
broadcastMessage(
|
|
198
|
+
{
|
|
199
|
+
...input,
|
|
200
|
+
type: "host_file_request",
|
|
201
|
+
requestId,
|
|
202
|
+
conversationId,
|
|
203
|
+
// Always include in message body so the receiving client can verify
|
|
204
|
+
// which endpoint was targeted (even when auto-resolved).
|
|
205
|
+
...(resolvedTargetClientId != null
|
|
206
|
+
? { targetClientId: resolvedTargetClientId }
|
|
207
|
+
: {}),
|
|
208
|
+
},
|
|
153
209
|
conversationId,
|
|
154
|
-
|
|
210
|
+
{ targetClientId: resolvedTargetClientId },
|
|
211
|
+
);
|
|
155
212
|
} catch (err) {
|
|
156
|
-
clearTimeout(timer);
|
|
157
|
-
this.pending.delete(requestId);
|
|
158
|
-
detachAbort();
|
|
159
213
|
pendingInteractions.resolve(requestId);
|
|
160
214
|
log.warn(
|
|
161
215
|
{ requestId, operation: input.operation, err },
|
|
@@ -166,55 +220,61 @@ export class HostFileProxy {
|
|
|
166
220
|
});
|
|
167
221
|
}
|
|
168
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Process a client result and resolve the RPC. Called by route handlers.
|
|
225
|
+
*/
|
|
169
226
|
resolve(
|
|
170
227
|
requestId: string,
|
|
171
228
|
response: { content: string; isError: boolean; imageData?: string },
|
|
172
229
|
): void {
|
|
173
|
-
const
|
|
174
|
-
if (!
|
|
230
|
+
const interaction = pendingInteractions.resolve(requestId);
|
|
231
|
+
if (!interaction?.rpcResolve) {
|
|
175
232
|
log.warn({ requestId }, "No pending host file request for response");
|
|
176
233
|
return;
|
|
177
234
|
}
|
|
178
|
-
|
|
179
|
-
entry.detachAbort();
|
|
180
|
-
this.pending.delete(requestId);
|
|
235
|
+
const meta = interaction.metadata ?? {};
|
|
181
236
|
if (
|
|
182
|
-
|
|
237
|
+
meta.operation === "read" &&
|
|
183
238
|
!response.isError &&
|
|
184
239
|
typeof response.imageData === "string" &&
|
|
185
240
|
response.imageData.length > 0
|
|
186
241
|
) {
|
|
187
|
-
|
|
242
|
+
interaction.rpcResolve(
|
|
243
|
+
readImageBase64(response.imageData, meta.path as string),
|
|
244
|
+
);
|
|
188
245
|
return;
|
|
189
246
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return this.pending.has(requestId);
|
|
247
|
+
interaction.rpcResolve({
|
|
248
|
+
content: response.content,
|
|
249
|
+
isError: response.isError,
|
|
250
|
+
});
|
|
195
251
|
}
|
|
196
252
|
|
|
197
253
|
dispose(): void {
|
|
198
|
-
for (const
|
|
199
|
-
|
|
200
|
-
entry.detachAbort();
|
|
201
|
-
pendingInteractions.resolve(requestId);
|
|
254
|
+
for (const entry of pendingInteractions.getByKind("host_file")) {
|
|
255
|
+
pendingInteractions.resolve(entry.requestId);
|
|
202
256
|
try {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
257
|
+
broadcastMessage(
|
|
258
|
+
{
|
|
259
|
+
type: "host_file_cancel",
|
|
260
|
+
requestId: entry.requestId,
|
|
261
|
+
conversationId: entry.conversationId,
|
|
262
|
+
...(entry.targetClientId != null
|
|
263
|
+
? { targetClientId: entry.targetClientId }
|
|
264
|
+
: {}),
|
|
265
|
+
},
|
|
266
|
+
entry.conversationId,
|
|
267
|
+
{ targetClientId: entry.targetClientId as string | undefined },
|
|
268
|
+
);
|
|
208
269
|
} catch {
|
|
209
|
-
// Best-effort cancel notification
|
|
270
|
+
// Best-effort cancel notification
|
|
210
271
|
}
|
|
211
|
-
entry.
|
|
272
|
+
entry.rpcReject?.(
|
|
212
273
|
new AssistantError(
|
|
213
274
|
"Host file proxy disposed",
|
|
214
275
|
ErrorCode.INTERNAL_ERROR,
|
|
215
276
|
),
|
|
216
277
|
);
|
|
217
278
|
}
|
|
218
|
-
this.pending.clear();
|
|
219
279
|
}
|
|
220
280
|
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared lifecycle base for host-proxy classes (HostBashProxy, HostCuProxy,
|
|
3
|
+
* HostFileProxy, HostTransferProxy, HostBrowserProxy, ...).
|
|
4
|
+
*
|
|
5
|
+
* Each host proxy:
|
|
6
|
+
* - dispatches a request to the desktop client via the assistant event hub,
|
|
7
|
+
* - tracks the request in a pending map keyed by `requestId`,
|
|
8
|
+
* - times the request out after a configurable interval,
|
|
9
|
+
* - cancels the request when the caller's `AbortSignal` fires,
|
|
10
|
+
* - rejects all pending requests on `dispose()`,
|
|
11
|
+
* - exposes `isAvailable()` based on the connected client's capabilities.
|
|
12
|
+
*
|
|
13
|
+
* Subclasses keep proxy-specific concerns (envelope shape, observation
|
|
14
|
+
* formatting, per-proxy state like CU's step counter) out of the base.
|
|
15
|
+
*/
|
|
16
|
+
import { v4 as uuid } from "uuid";
|
|
17
|
+
|
|
18
|
+
import type { HostProxyCapability } from "../channels/types.js";
|
|
19
|
+
import {
|
|
20
|
+
assistantEventHub,
|
|
21
|
+
broadcastMessage,
|
|
22
|
+
} from "../runtime/assistant-event-hub.js";
|
|
23
|
+
import type { PendingInteraction } from "../runtime/pending-interactions.js";
|
|
24
|
+
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
25
|
+
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
26
|
+
import { getLogger } from "../util/logger.js";
|
|
27
|
+
import type { ServerMessage } from "./message-protocol.js";
|
|
28
|
+
|
|
29
|
+
const log = getLogger("host-proxy-base");
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* `broadcastMessage` is statically typed against the discriminated
|
|
33
|
+
* `ServerMessage` union. The base class assembles envelopes from
|
|
34
|
+
* constructor-supplied event names and untyped extra fields, so static
|
|
35
|
+
* narrowing is impossible — subclasses are responsible for passing event
|
|
36
|
+
* names that match a real `ServerMessage` variant.
|
|
37
|
+
*/
|
|
38
|
+
function broadcastDynamic(
|
|
39
|
+
envelope: Record<string, unknown>,
|
|
40
|
+
targetClientId?: string,
|
|
41
|
+
): void {
|
|
42
|
+
broadcastMessage(
|
|
43
|
+
envelope as unknown as ServerMessage,
|
|
44
|
+
undefined,
|
|
45
|
+
targetClientId ? { targetClientId } : undefined,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
50
|
+
|
|
51
|
+
/** Reason a pending request was rejected by the base. */
|
|
52
|
+
export type HostProxyRejectionReason = "timeout" | "aborted" | "disposed";
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Error thrown by the base when a pending request is rejected via the
|
|
56
|
+
* lifecycle paths (timeout, abort, dispose). Subclasses inspect `reason`
|
|
57
|
+
* to map back to their proxy-specific error / observation shape.
|
|
58
|
+
*/
|
|
59
|
+
export class HostProxyRequestError extends AssistantError {
|
|
60
|
+
constructor(
|
|
61
|
+
message: string,
|
|
62
|
+
public readonly reason: HostProxyRejectionReason,
|
|
63
|
+
) {
|
|
64
|
+
super(message, ErrorCode.INTERNAL_ERROR);
|
|
65
|
+
this.name = "HostProxyRequestError";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface PendingEntry<TResultPayload> {
|
|
70
|
+
resolve: (payload: TResultPayload) => void;
|
|
71
|
+
reject: (err: Error) => void;
|
|
72
|
+
timer: ReturnType<typeof setTimeout>;
|
|
73
|
+
conversationId: string;
|
|
74
|
+
targetClientId?: string;
|
|
75
|
+
/** Detach the abort listener from the caller's signal. No-op when no signal was passed. */
|
|
76
|
+
detachAbort: () => void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface HostProxyBaseOptions {
|
|
80
|
+
/** Capability advertised by clients that can service this proxy. */
|
|
81
|
+
capabilityName: HostProxyCapability;
|
|
82
|
+
/** Outbound message `type` for new requests (e.g. `"host_cu_request"`). */
|
|
83
|
+
requestEventName: string;
|
|
84
|
+
/** Outbound message `type` for cancellation (e.g. `"host_cu_cancel"`). */
|
|
85
|
+
cancelEventName: string;
|
|
86
|
+
/** Tag used to identify this proxy's requests in `pendingInteractions`. */
|
|
87
|
+
resultPendingKind: PendingInteraction["kind"];
|
|
88
|
+
/** Per-request timeout. Defaults to 60s. */
|
|
89
|
+
timeoutMs?: number;
|
|
90
|
+
/** Customizable disposed-rejection message (used in test assertions). */
|
|
91
|
+
disposedMessage?: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export abstract class HostProxyBase<TRequest, TResultPayload> {
|
|
95
|
+
protected pending = new Map<string, PendingEntry<TResultPayload>>();
|
|
96
|
+
|
|
97
|
+
protected readonly capabilityName: HostProxyCapability;
|
|
98
|
+
protected readonly requestEventName: string;
|
|
99
|
+
protected readonly cancelEventName: string;
|
|
100
|
+
protected readonly resultPendingKind: PendingInteraction["kind"];
|
|
101
|
+
protected readonly timeoutMs: number;
|
|
102
|
+
protected readonly disposedMessage: string;
|
|
103
|
+
|
|
104
|
+
constructor(opts: HostProxyBaseOptions) {
|
|
105
|
+
this.capabilityName = opts.capabilityName;
|
|
106
|
+
this.requestEventName = opts.requestEventName;
|
|
107
|
+
this.cancelEventName = opts.cancelEventName;
|
|
108
|
+
this.resultPendingKind = opts.resultPendingKind;
|
|
109
|
+
this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
110
|
+
this.disposedMessage = opts.disposedMessage ?? "Host proxy disposed";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Whether a client advertising the configured capability is connected.
|
|
115
|
+
*/
|
|
116
|
+
isAvailable(): boolean {
|
|
117
|
+
return (
|
|
118
|
+
assistantEventHub.getMostRecentClientByCapability(this.capabilityName) !=
|
|
119
|
+
null
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Dispatch a request envelope to the connected client and return a
|
|
125
|
+
* promise that resolves when the client responds (via `resolve()`),
|
|
126
|
+
* rejects on timeout/abort/dispose, or rejects synchronously if the
|
|
127
|
+
* broadcast itself fails.
|
|
128
|
+
*
|
|
129
|
+
* `extraFields` is shallow-merged into the broadcast envelope so
|
|
130
|
+
* subclasses can include proxy-specific top-level fields (e.g. CU's
|
|
131
|
+
* `stepNumber` / `reasoning`) without nesting them inside `input`.
|
|
132
|
+
*
|
|
133
|
+
* Named `dispatchRequest` rather than `request` so subclasses are free to
|
|
134
|
+
* expose their own public `request(...)` with a proxy-specific signature
|
|
135
|
+
* (e.g. CU passes `stepNumber` and `reasoning` to its callers).
|
|
136
|
+
*/
|
|
137
|
+
protected dispatchRequest(
|
|
138
|
+
toolName: string,
|
|
139
|
+
input: TRequest,
|
|
140
|
+
conversationId: string,
|
|
141
|
+
signal?: AbortSignal,
|
|
142
|
+
extraFields?: Record<string, unknown>,
|
|
143
|
+
targetClientId?: string,
|
|
144
|
+
): Promise<TResultPayload> {
|
|
145
|
+
const requestId = uuid();
|
|
146
|
+
|
|
147
|
+
return new Promise<TResultPayload>((resolve, reject) => {
|
|
148
|
+
// Declared up-front so onAbort can close over a stable reference once
|
|
149
|
+
// it's wired below.
|
|
150
|
+
let detachAbort: () => void = () => {};
|
|
151
|
+
|
|
152
|
+
const timer = setTimeout(() => {
|
|
153
|
+
this.pending.delete(requestId);
|
|
154
|
+
detachAbort();
|
|
155
|
+
pendingInteractions.resolve(requestId);
|
|
156
|
+
log.warn(
|
|
157
|
+
{ requestId, toolName, kind: this.resultPendingKind },
|
|
158
|
+
"Host proxy request timed out",
|
|
159
|
+
);
|
|
160
|
+
reject(new HostProxyRequestError("timeout", "timeout"));
|
|
161
|
+
}, this.timeoutMs);
|
|
162
|
+
|
|
163
|
+
if (signal) {
|
|
164
|
+
const onAbort = () => {
|
|
165
|
+
if (this.pending.has(requestId)) {
|
|
166
|
+
clearTimeout(timer);
|
|
167
|
+
this.pending.delete(requestId);
|
|
168
|
+
detachAbort();
|
|
169
|
+
pendingInteractions.resolve(requestId);
|
|
170
|
+
try {
|
|
171
|
+
broadcastDynamic(
|
|
172
|
+
{
|
|
173
|
+
type: this.cancelEventName,
|
|
174
|
+
requestId,
|
|
175
|
+
conversationId,
|
|
176
|
+
targetClientId,
|
|
177
|
+
},
|
|
178
|
+
targetClientId,
|
|
179
|
+
);
|
|
180
|
+
} catch {
|
|
181
|
+
// Best-effort cancel notification — connection may already be closed.
|
|
182
|
+
}
|
|
183
|
+
reject(new HostProxyRequestError("aborted", "aborted"));
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
187
|
+
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this.pending.set(requestId, {
|
|
191
|
+
resolve,
|
|
192
|
+
reject,
|
|
193
|
+
timer,
|
|
194
|
+
conversationId,
|
|
195
|
+
targetClientId,
|
|
196
|
+
detachAbort,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Register in the global pendingInteractions store so the result-route
|
|
200
|
+
// handler (e.g. POST /v1/host-app-control-result) can look up the
|
|
201
|
+
// request by id and route it back to this proxy. Without this the
|
|
202
|
+
// route silently drops the response — see host-app-control-routes.ts:
|
|
203
|
+
// `if (!peeked || peeked.kind !== "host_app_control") return ...`.
|
|
204
|
+
// (HostCuProxy bypasses dispatchRequest entirely with its own inline
|
|
205
|
+
// request method that registers directly, which is why CU works
|
|
206
|
+
// without this base-level fix.)
|
|
207
|
+
pendingInteractions.register(requestId, {
|
|
208
|
+
conversationId,
|
|
209
|
+
kind: this.resultPendingKind,
|
|
210
|
+
...(targetClientId != null ? { targetClientId } : {}),
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
broadcastDynamic(
|
|
215
|
+
{
|
|
216
|
+
type: this.requestEventName,
|
|
217
|
+
requestId,
|
|
218
|
+
conversationId,
|
|
219
|
+
toolName,
|
|
220
|
+
input,
|
|
221
|
+
targetClientId,
|
|
222
|
+
...(extraFields ?? {}),
|
|
223
|
+
},
|
|
224
|
+
targetClientId,
|
|
225
|
+
);
|
|
226
|
+
} catch (err) {
|
|
227
|
+
clearTimeout(timer);
|
|
228
|
+
this.pending.delete(requestId);
|
|
229
|
+
detachAbort();
|
|
230
|
+
pendingInteractions.resolve(requestId);
|
|
231
|
+
log.warn(
|
|
232
|
+
{ requestId, toolName, kind: this.resultPendingKind, err },
|
|
233
|
+
"Host proxy send failed",
|
|
234
|
+
);
|
|
235
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Resolve a pending request with the client-provided payload. No-op when
|
|
242
|
+
* no entry is registered for `requestId` (late responses after timeout
|
|
243
|
+
* or abort fall through to here).
|
|
244
|
+
*/
|
|
245
|
+
resolve(requestId: string, payload: TResultPayload): void {
|
|
246
|
+
const entry = this.pending.get(requestId);
|
|
247
|
+
if (!entry) {
|
|
248
|
+
log.warn(
|
|
249
|
+
{ requestId, kind: this.resultPendingKind },
|
|
250
|
+
"No pending host proxy request for response",
|
|
251
|
+
);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
clearTimeout(entry.timer);
|
|
255
|
+
entry.detachAbort();
|
|
256
|
+
this.pending.delete(requestId);
|
|
257
|
+
entry.resolve(payload);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Whether `requestId` is still registered as pending. Useful to subclasses
|
|
262
|
+
* that need to reason about the lifecycle in tests.
|
|
263
|
+
*/
|
|
264
|
+
hasPendingRequest(requestId: string): boolean {
|
|
265
|
+
return this.pending.has(requestId);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Reject every pending request and clear the map. Called during graceful
|
|
270
|
+
* shutdown or proxy teardown.
|
|
271
|
+
*/
|
|
272
|
+
dispose(): void {
|
|
273
|
+
for (const [requestId, entry] of this.pending) {
|
|
274
|
+
clearTimeout(entry.timer);
|
|
275
|
+
entry.detachAbort();
|
|
276
|
+
pendingInteractions.resolve(requestId);
|
|
277
|
+
try {
|
|
278
|
+
broadcastDynamic(
|
|
279
|
+
{
|
|
280
|
+
type: this.cancelEventName,
|
|
281
|
+
requestId,
|
|
282
|
+
conversationId: entry.conversationId,
|
|
283
|
+
targetClientId: entry.targetClientId,
|
|
284
|
+
},
|
|
285
|
+
entry.targetClientId,
|
|
286
|
+
);
|
|
287
|
+
} catch {
|
|
288
|
+
// Best-effort cancel notification — connection may already be closed.
|
|
289
|
+
}
|
|
290
|
+
entry.reject(new HostProxyRequestError(this.disposedMessage, "disposed"));
|
|
291
|
+
}
|
|
292
|
+
this.pending.clear();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared host-proxy skill preactivation registry.
|
|
3
|
+
*
|
|
4
|
+
* Several call sites need to mark host-proxy-backed skills as preactivated
|
|
5
|
+
* for a turn whenever the source interface supports the corresponding
|
|
6
|
+
* `HostProxyCapability`:
|
|
7
|
+
*
|
|
8
|
+
* - `runtime/routes/conversation-routes.ts` (create path, /v1/messages)
|
|
9
|
+
* - `daemon/process-message.ts` (create path, prepareConversationForMessage)
|
|
10
|
+
* - `daemon/conversation-process.ts` `drainSingleMessage` (re-add after dequeue)
|
|
11
|
+
* - `daemon/conversation-process.ts` `drainBatch` (re-add after dequeue)
|
|
12
|
+
*
|
|
13
|
+
* The create paths additionally instantiate the proxy itself; that
|
|
14
|
+
* instantiation logic is per-proxy-class and stays inline at each create
|
|
15
|
+
* site (constructors take different argument shapes — `HostCuProxy()` vs
|
|
16
|
+
* `HostAppControlProxy(conversationId)`). This module owns only the
|
|
17
|
+
* capability-to-skill mapping and the preactivation step. Adding a new
|
|
18
|
+
* host-proxy-backed skill is a one-line registry change here instead of
|
|
19
|
+
* touching all four call sites.
|
|
20
|
+
*
|
|
21
|
+
* Why a registry instead of repeated branches: each new host-proxy-backed
|
|
22
|
+
* skill that ships (e.g. a future `host_focus` capability with a `focus`
|
|
23
|
+
* skill) would otherwise add four near-identical `if (supportsHostProxy(...))
|
|
24
|
+
* conversation.addPreactivatedSkillId("...")` blocks across these files.
|
|
25
|
+
* Centralizing the list makes the contract obvious and prevents drift
|
|
26
|
+
* where one call site re-adds a skill but another forgets to.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import type { HostProxyCapability, InterfaceId } from "../channels/types.js";
|
|
30
|
+
import { supportsHostProxy } from "../channels/types.js";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Subset of Conversation/ProcessConversationContext that
|
|
34
|
+
* `preactivateHostProxySkills` needs. Both `Conversation` and
|
|
35
|
+
* `ProcessConversationContext` satisfy this structurally.
|
|
36
|
+
*/
|
|
37
|
+
export interface HostProxyPreactivationTarget {
|
|
38
|
+
addPreactivatedSkillId(id: string): void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Registry mapping each host-proxy capability to the skill that must be
|
|
43
|
+
* preactivated when that capability is supported by the source interface.
|
|
44
|
+
*
|
|
45
|
+
* Keep this list in sync with `HostProxyCapability` for any capability that
|
|
46
|
+
* has a corresponding bundled skill.
|
|
47
|
+
*
|
|
48
|
+
* Capabilities NOT listed here:
|
|
49
|
+
* - `host_bash`, `host_file` — these are surfaced as built-in tools rather
|
|
50
|
+
* than skills, so there is nothing to preactivate.
|
|
51
|
+
* - `host_browser` — the browser proxy is provisioned via the assistant
|
|
52
|
+
* event hub for chrome-extension and its skill projection is governed by
|
|
53
|
+
* a different code path (`host-browser-proxy.ts`).
|
|
54
|
+
*/
|
|
55
|
+
export const HOST_PROXY_SKILL_PREACTIVATIONS: ReadonlyArray<{
|
|
56
|
+
capability: HostProxyCapability;
|
|
57
|
+
skillId: string;
|
|
58
|
+
}> = [
|
|
59
|
+
{ capability: "host_cu", skillId: "computer-use" },
|
|
60
|
+
{ capability: "host_app_control", skillId: "app-control" },
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Preactivate every host-proxy-backed skill that the given source interface
|
|
65
|
+
* supports. No-op when `sourceInterface` is undefined.
|
|
66
|
+
*
|
|
67
|
+
* Callers are responsible for any additional gating (e.g. only preactivating
|
|
68
|
+
* when the conversation is idle vs. when re-adding after dequeue), since
|
|
69
|
+
* those constraints differ across create vs. drain paths. This helper just
|
|
70
|
+
* iterates the registry and dispatches.
|
|
71
|
+
*/
|
|
72
|
+
export function preactivateHostProxySkills(
|
|
73
|
+
conversation: HostProxyPreactivationTarget,
|
|
74
|
+
sourceInterface: InterfaceId | undefined,
|
|
75
|
+
): void {
|
|
76
|
+
if (!sourceInterface) return;
|
|
77
|
+
for (const { capability, skillId } of HOST_PROXY_SKILL_PREACTIVATIONS) {
|
|
78
|
+
if (supportsHostProxy(sourceInterface, capability)) {
|
|
79
|
+
conversation.addPreactivatedSkillId(skillId);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|