@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
|
@@ -9,29 +9,40 @@ import {
|
|
|
9
9
|
assistantEventHub,
|
|
10
10
|
broadcastMessage,
|
|
11
11
|
} from "../runtime/assistant-event-hub.js";
|
|
12
|
+
import {
|
|
13
|
+
ambiguousSameUserError,
|
|
14
|
+
enforceSameActorOrErrorResult,
|
|
15
|
+
pickSameUserAutoResolve,
|
|
16
|
+
} from "../runtime/auth/same-actor.js";
|
|
12
17
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
13
18
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
14
19
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
15
20
|
import { getLogger } from "../util/logger.js";
|
|
16
|
-
import type { ServerMessage } from "./message-protocol.js";
|
|
17
21
|
|
|
18
22
|
const log = getLogger("host-transfer-proxy");
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Lightweight entry for the transfers map (keyed by transferId).
|
|
26
|
+
* Points back to the requestId so route handlers can correlate
|
|
27
|
+
* content endpoints with the pending interaction.
|
|
28
|
+
*/
|
|
29
|
+
interface TransferEntry {
|
|
24
30
|
requestId: string;
|
|
25
31
|
transferId: string;
|
|
26
|
-
conversationId: string;
|
|
27
32
|
direction: "to_host" | "to_sandbox";
|
|
28
33
|
filePath: string;
|
|
29
34
|
overwrite?: boolean;
|
|
30
35
|
sizeBytes?: number;
|
|
31
36
|
sha256?: string;
|
|
32
37
|
fileBuffer?: Buffer;
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
targetClientId?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Snapshot of `targetClientId`'s `actorPrincipalId` taken at registration
|
|
41
|
+
* time. Persisted so the GET/PUT content routes compare against a stable
|
|
42
|
+
* value rather than the live hub — the target client's SSE subscription
|
|
43
|
+
* may briefly disconnect between dispatch and content fetch/upload.
|
|
44
|
+
*/
|
|
45
|
+
targetActorPrincipalId?: string;
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
/**
|
|
@@ -82,10 +93,22 @@ export class HostTransferProxy {
|
|
|
82
93
|
HostTransferProxy._instance = null;
|
|
83
94
|
}
|
|
84
95
|
|
|
85
|
-
/** Pending transfers keyed by requestId (for resolution from client results). */
|
|
86
|
-
private pending = new Map<string, PendingTransfer>();
|
|
87
96
|
/** Pending transfers keyed by transferId (for content endpoint lookups). */
|
|
88
|
-
private transfers = new Map<string,
|
|
97
|
+
private transfers = new Map<string, TransferEntry>();
|
|
98
|
+
/**
|
|
99
|
+
* Briefly retains size/sha256 of a just-consumed transfer so the GET-content
|
|
100
|
+
* route's `resolveResponseHeaders` callback (which the HTTP adapter invokes
|
|
101
|
+
* AFTER the request handler) can still set `Content-Length` and
|
|
102
|
+
* `X-Transfer-SHA256` headers. Without this, the handler's `getTransferContent`
|
|
103
|
+
* call deletes the entry before the header resolver runs, and the resolver
|
|
104
|
+
* silently falls back to default headers — meaning the documented response
|
|
105
|
+
* headers were never actually sent. Entries here self-clear on read; a 30s
|
|
106
|
+
* fallback timer prevents long-term retention if the resolver never runs.
|
|
107
|
+
*/
|
|
108
|
+
private justConsumedMetadata = new Map<
|
|
109
|
+
string,
|
|
110
|
+
{ sizeBytes: number; sha256: string }
|
|
111
|
+
>();
|
|
89
112
|
|
|
90
113
|
/**
|
|
91
114
|
* Whether a client with `host_file` capability is connected.
|
|
@@ -97,10 +120,6 @@ export class HostTransferProxy {
|
|
|
97
120
|
);
|
|
98
121
|
}
|
|
99
122
|
|
|
100
|
-
private send(msg: ServerMessage): void {
|
|
101
|
-
broadcastMessage(msg, undefined, { targetCapability: "host_file" });
|
|
102
|
-
}
|
|
103
|
-
|
|
104
123
|
/**
|
|
105
124
|
* Request a file transfer from the sandbox to the host machine.
|
|
106
125
|
*
|
|
@@ -114,20 +133,63 @@ export class HostTransferProxy {
|
|
|
114
133
|
destPath: string;
|
|
115
134
|
overwrite: boolean;
|
|
116
135
|
conversationId: string;
|
|
136
|
+
targetClientId?: string;
|
|
117
137
|
},
|
|
118
138
|
signal?: AbortSignal,
|
|
139
|
+
// Principal ID of the actor on whose behalf this request is initiated.
|
|
140
|
+
sourceActorPrincipalId?: string,
|
|
119
141
|
): Promise<ToolExecutionResult> {
|
|
120
142
|
if (signal?.aborted) {
|
|
121
143
|
return Promise.resolve({ content: "Aborted", isError: true });
|
|
122
144
|
}
|
|
123
145
|
|
|
146
|
+
let resolvedTargetClientId: string | undefined = input.targetClientId;
|
|
147
|
+
if (resolvedTargetClientId != null) {
|
|
148
|
+
const client = assistantEventHub.getClientById(resolvedTargetClientId);
|
|
149
|
+
if (!client) {
|
|
150
|
+
return Promise.resolve({
|
|
151
|
+
content: `No connected client with id '${resolvedTargetClientId}' supports host_file. Run \`assistant clients list --capability host_file\` to see available clients.`,
|
|
152
|
+
isError: true,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (!client.capabilities.includes("host_file")) {
|
|
156
|
+
return Promise.resolve({
|
|
157
|
+
content: `Client '${resolvedTargetClientId}' does not support host_file. Run \`assistant clients list --capability host_file\` to see available clients.`,
|
|
158
|
+
isError: true,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
// Auto-resolve to the unique same-user client; reject ambiguous
|
|
163
|
+
// (multi-machine) cases so a single targeted-style transfer cannot
|
|
164
|
+
// fan out across the user's machines.
|
|
165
|
+
const resolved = pickSameUserAutoResolve({
|
|
166
|
+
hub: assistantEventHub,
|
|
167
|
+
capability: "host_file",
|
|
168
|
+
sourceActorPrincipalId,
|
|
169
|
+
});
|
|
170
|
+
if (resolved.kind === "ambiguous") {
|
|
171
|
+
return Promise.resolve(ambiguousSameUserError("host_file"));
|
|
172
|
+
}
|
|
173
|
+
resolvedTargetClientId =
|
|
174
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (resolvedTargetClientId != null) {
|
|
178
|
+
const rejection = enforceSameActorOrErrorResult({
|
|
179
|
+
hub: assistantEventHub,
|
|
180
|
+
sourceActorPrincipalId,
|
|
181
|
+
targetClientId: resolvedTargetClientId,
|
|
182
|
+
op: "host_transfer",
|
|
183
|
+
});
|
|
184
|
+
if (rejection != null) return Promise.resolve(rejection);
|
|
185
|
+
}
|
|
186
|
+
|
|
124
187
|
const requestId = uuid();
|
|
125
188
|
const transferId = uuid();
|
|
126
189
|
|
|
127
190
|
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
128
191
|
readFile(input.sourcePath)
|
|
129
192
|
.then((fileBuffer) => {
|
|
130
|
-
// Check again after async read in case signal fired during I/O.
|
|
131
193
|
if (signal?.aborted) {
|
|
132
194
|
resolve({ content: "Aborted", isError: true });
|
|
133
195
|
return;
|
|
@@ -142,37 +204,40 @@ export class HostTransferProxy {
|
|
|
142
204
|
let detachAbort: () => void = () => {};
|
|
143
205
|
|
|
144
206
|
const timer = setTimeout(() => {
|
|
145
|
-
this.pending.delete(requestId);
|
|
146
207
|
this.transfers.delete(transferId);
|
|
147
|
-
detachAbort();
|
|
148
208
|
pendingInteractions.resolve(requestId);
|
|
149
209
|
log.warn(
|
|
150
210
|
{ requestId, transferId, direction: "to_host" },
|
|
151
211
|
"Host transfer proxy request timed out",
|
|
152
212
|
);
|
|
153
213
|
resolve({
|
|
154
|
-
content:
|
|
155
|
-
|
|
214
|
+
content: resolvedTargetClientId
|
|
215
|
+
? `Host transfer proxy timed out waiting for response from client '${resolvedTargetClientId}'`
|
|
216
|
+
: "Host transfer proxy timed out waiting for client response",
|
|
156
217
|
isError: true,
|
|
157
218
|
});
|
|
158
219
|
}, timeoutMs);
|
|
159
220
|
|
|
160
221
|
if (signal) {
|
|
161
222
|
const onAbort = () => {
|
|
162
|
-
if (
|
|
163
|
-
clearTimeout(timer);
|
|
164
|
-
this.pending.delete(requestId);
|
|
223
|
+
if (pendingInteractions.get(requestId)) {
|
|
165
224
|
this.transfers.delete(transferId);
|
|
166
|
-
detachAbort();
|
|
167
225
|
pendingInteractions.resolve(requestId);
|
|
168
226
|
try {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
227
|
+
broadcastMessage(
|
|
228
|
+
{
|
|
229
|
+
type: "host_transfer_cancel",
|
|
230
|
+
requestId,
|
|
231
|
+
conversationId: input.conversationId,
|
|
232
|
+
...(resolvedTargetClientId != null
|
|
233
|
+
? { targetClientId: resolvedTargetClientId }
|
|
234
|
+
: {}),
|
|
235
|
+
},
|
|
236
|
+
input.conversationId,
|
|
237
|
+
{ targetClientId: resolvedTargetClientId },
|
|
238
|
+
);
|
|
174
239
|
} catch {
|
|
175
|
-
// Best-effort cancel notification
|
|
240
|
+
// Best-effort cancel notification
|
|
176
241
|
}
|
|
177
242
|
resolve({ content: "Aborted", isError: true });
|
|
178
243
|
}
|
|
@@ -181,40 +246,61 @@ export class HostTransferProxy {
|
|
|
181
246
|
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
182
247
|
}
|
|
183
248
|
|
|
184
|
-
|
|
185
|
-
resolve,
|
|
186
|
-
reject,
|
|
187
|
-
timer,
|
|
249
|
+
this.transfers.set(transferId, {
|
|
188
250
|
requestId,
|
|
189
251
|
transferId,
|
|
190
|
-
conversationId: input.conversationId,
|
|
191
252
|
direction: "to_host",
|
|
192
253
|
filePath: input.destPath,
|
|
193
254
|
sizeBytes,
|
|
194
255
|
sha256,
|
|
195
256
|
fileBuffer,
|
|
257
|
+
targetClientId: resolvedTargetClientId,
|
|
258
|
+
targetActorPrincipalId:
|
|
259
|
+
resolvedTargetClientId != null
|
|
260
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
261
|
+
resolvedTargetClientId,
|
|
262
|
+
)
|
|
263
|
+
: undefined,
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
pendingInteractions.register(requestId, {
|
|
267
|
+
conversationId: input.conversationId,
|
|
268
|
+
kind: "host_transfer",
|
|
269
|
+
targetClientId: resolvedTargetClientId,
|
|
270
|
+
targetActorPrincipalId:
|
|
271
|
+
resolvedTargetClientId != null
|
|
272
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
273
|
+
resolvedTargetClientId,
|
|
274
|
+
)
|
|
275
|
+
: undefined,
|
|
276
|
+
rpcResolve: resolve,
|
|
277
|
+
rpcReject: reject,
|
|
278
|
+
timer,
|
|
196
279
|
detachAbort,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
this.transfers.set(transferId, entry);
|
|
280
|
+
metadata: { transferId },
|
|
281
|
+
});
|
|
200
282
|
|
|
201
283
|
try {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
284
|
+
broadcastMessage(
|
|
285
|
+
{
|
|
286
|
+
type: "host_transfer_request",
|
|
287
|
+
requestId,
|
|
288
|
+
conversationId: input.conversationId,
|
|
289
|
+
direction: "to_host",
|
|
290
|
+
transferId,
|
|
291
|
+
destPath: input.destPath,
|
|
292
|
+
sizeBytes,
|
|
293
|
+
sha256,
|
|
294
|
+
overwrite: input.overwrite,
|
|
295
|
+
...(resolvedTargetClientId != null
|
|
296
|
+
? { targetClientId: resolvedTargetClientId }
|
|
297
|
+
: {}),
|
|
298
|
+
},
|
|
299
|
+
input.conversationId,
|
|
300
|
+
{ targetClientId: resolvedTargetClientId },
|
|
301
|
+
);
|
|
213
302
|
} catch (err) {
|
|
214
|
-
clearTimeout(timer);
|
|
215
|
-
this.pending.delete(requestId);
|
|
216
303
|
this.transfers.delete(transferId);
|
|
217
|
-
detachAbort();
|
|
218
304
|
pendingInteractions.resolve(requestId);
|
|
219
305
|
log.warn(
|
|
220
306
|
{ requestId, transferId, err },
|
|
@@ -249,13 +335,57 @@ export class HostTransferProxy {
|
|
|
249
335
|
destPath: string;
|
|
250
336
|
overwrite?: boolean;
|
|
251
337
|
conversationId: string;
|
|
338
|
+
targetClientId?: string;
|
|
252
339
|
},
|
|
253
340
|
signal?: AbortSignal,
|
|
341
|
+
// Principal ID of the actor on whose behalf this request is initiated.
|
|
342
|
+
sourceActorPrincipalId?: string,
|
|
254
343
|
): Promise<ToolExecutionResult> {
|
|
255
344
|
if (signal?.aborted) {
|
|
256
345
|
return Promise.resolve({ content: "Aborted", isError: true });
|
|
257
346
|
}
|
|
258
347
|
|
|
348
|
+
let resolvedTargetClientId: string | undefined = input.targetClientId;
|
|
349
|
+
if (resolvedTargetClientId != null) {
|
|
350
|
+
const client = assistantEventHub.getClientById(resolvedTargetClientId);
|
|
351
|
+
if (!client) {
|
|
352
|
+
return Promise.resolve({
|
|
353
|
+
content: `No connected client with id '${resolvedTargetClientId}' supports host_file. Run \`assistant clients list --capability host_file\` to see available clients.`,
|
|
354
|
+
isError: true,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
if (!client.capabilities.includes("host_file")) {
|
|
358
|
+
return Promise.resolve({
|
|
359
|
+
content: `Client '${resolvedTargetClientId}' does not support host_file. Run \`assistant clients list --capability host_file\` to see available clients.`,
|
|
360
|
+
isError: true,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
// Auto-resolve to the unique same-user client; reject ambiguous
|
|
365
|
+
// (multi-machine) cases so a single targeted-style transfer cannot
|
|
366
|
+
// fan out across the user's machines.
|
|
367
|
+
const resolved = pickSameUserAutoResolve({
|
|
368
|
+
hub: assistantEventHub,
|
|
369
|
+
capability: "host_file",
|
|
370
|
+
sourceActorPrincipalId,
|
|
371
|
+
});
|
|
372
|
+
if (resolved.kind === "ambiguous") {
|
|
373
|
+
return Promise.resolve(ambiguousSameUserError("host_file"));
|
|
374
|
+
}
|
|
375
|
+
resolvedTargetClientId =
|
|
376
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (resolvedTargetClientId != null) {
|
|
380
|
+
const rejection = enforceSameActorOrErrorResult({
|
|
381
|
+
hub: assistantEventHub,
|
|
382
|
+
sourceActorPrincipalId,
|
|
383
|
+
targetClientId: resolvedTargetClientId,
|
|
384
|
+
op: "host_transfer",
|
|
385
|
+
});
|
|
386
|
+
if (rejection != null) return Promise.resolve(rejection);
|
|
387
|
+
}
|
|
388
|
+
|
|
259
389
|
const requestId = uuid();
|
|
260
390
|
const transferId = uuid();
|
|
261
391
|
|
|
@@ -265,36 +395,40 @@ export class HostTransferProxy {
|
|
|
265
395
|
let detachAbort: () => void = () => {};
|
|
266
396
|
|
|
267
397
|
const timer = setTimeout(() => {
|
|
268
|
-
this.pending.delete(requestId);
|
|
269
398
|
this.transfers.delete(transferId);
|
|
270
|
-
detachAbort();
|
|
271
399
|
pendingInteractions.resolve(requestId);
|
|
272
400
|
log.warn(
|
|
273
401
|
{ requestId, transferId, direction: "to_sandbox" },
|
|
274
402
|
"Host transfer proxy request timed out",
|
|
275
403
|
);
|
|
276
404
|
resolve({
|
|
277
|
-
content:
|
|
405
|
+
content: resolvedTargetClientId
|
|
406
|
+
? `Host transfer proxy timed out waiting for response from client '${resolvedTargetClientId}'`
|
|
407
|
+
: "Host transfer proxy timed out waiting for client response",
|
|
278
408
|
isError: true,
|
|
279
409
|
});
|
|
280
410
|
}, timeoutMs);
|
|
281
411
|
|
|
282
412
|
if (signal) {
|
|
283
413
|
const onAbort = () => {
|
|
284
|
-
if (
|
|
285
|
-
clearTimeout(timer);
|
|
286
|
-
this.pending.delete(requestId);
|
|
414
|
+
if (pendingInteractions.get(requestId)) {
|
|
287
415
|
this.transfers.delete(transferId);
|
|
288
|
-
detachAbort();
|
|
289
416
|
pendingInteractions.resolve(requestId);
|
|
290
417
|
try {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
418
|
+
broadcastMessage(
|
|
419
|
+
{
|
|
420
|
+
type: "host_transfer_cancel",
|
|
421
|
+
requestId,
|
|
422
|
+
conversationId: input.conversationId,
|
|
423
|
+
...(resolvedTargetClientId != null
|
|
424
|
+
? { targetClientId: resolvedTargetClientId }
|
|
425
|
+
: {}),
|
|
426
|
+
},
|
|
427
|
+
input.conversationId,
|
|
428
|
+
{ targetClientId: resolvedTargetClientId },
|
|
429
|
+
);
|
|
296
430
|
} catch {
|
|
297
|
-
// Best-effort cancel notification
|
|
431
|
+
// Best-effort cancel notification
|
|
298
432
|
}
|
|
299
433
|
resolve({ content: "Aborted", isError: true });
|
|
300
434
|
}
|
|
@@ -303,35 +437,56 @@ export class HostTransferProxy {
|
|
|
303
437
|
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
304
438
|
}
|
|
305
439
|
|
|
306
|
-
|
|
307
|
-
resolve,
|
|
308
|
-
reject,
|
|
309
|
-
timer,
|
|
440
|
+
this.transfers.set(transferId, {
|
|
310
441
|
requestId,
|
|
311
442
|
transferId,
|
|
312
|
-
conversationId: input.conversationId,
|
|
313
443
|
direction: "to_sandbox",
|
|
314
444
|
filePath: input.destPath,
|
|
315
445
|
overwrite: input.overwrite,
|
|
446
|
+
targetClientId: resolvedTargetClientId,
|
|
447
|
+
targetActorPrincipalId:
|
|
448
|
+
resolvedTargetClientId != null
|
|
449
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
450
|
+
resolvedTargetClientId,
|
|
451
|
+
)
|
|
452
|
+
: undefined,
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
pendingInteractions.register(requestId, {
|
|
456
|
+
conversationId: input.conversationId,
|
|
457
|
+
kind: "host_transfer",
|
|
458
|
+
targetClientId: resolvedTargetClientId,
|
|
459
|
+
targetActorPrincipalId:
|
|
460
|
+
resolvedTargetClientId != null
|
|
461
|
+
? assistantEventHub.getActorPrincipalIdForClient(
|
|
462
|
+
resolvedTargetClientId,
|
|
463
|
+
)
|
|
464
|
+
: undefined,
|
|
465
|
+
rpcResolve: resolve,
|
|
466
|
+
rpcReject: reject,
|
|
467
|
+
timer,
|
|
316
468
|
detachAbort,
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
this.transfers.set(transferId, entry);
|
|
469
|
+
metadata: { transferId },
|
|
470
|
+
});
|
|
320
471
|
|
|
321
472
|
try {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
473
|
+
broadcastMessage(
|
|
474
|
+
{
|
|
475
|
+
type: "host_transfer_request",
|
|
476
|
+
requestId,
|
|
477
|
+
conversationId: input.conversationId,
|
|
478
|
+
direction: "to_sandbox",
|
|
479
|
+
transferId,
|
|
480
|
+
sourcePath: input.sourcePath,
|
|
481
|
+
...(resolvedTargetClientId != null
|
|
482
|
+
? { targetClientId: resolvedTargetClientId }
|
|
483
|
+
: {}),
|
|
484
|
+
},
|
|
485
|
+
input.conversationId,
|
|
486
|
+
{ targetClientId: resolvedTargetClientId },
|
|
487
|
+
);
|
|
330
488
|
} catch (err) {
|
|
331
|
-
clearTimeout(timer);
|
|
332
|
-
this.pending.delete(requestId);
|
|
333
489
|
this.transfers.delete(transferId);
|
|
334
|
-
detachAbort();
|
|
335
490
|
pendingInteractions.resolve(requestId);
|
|
336
491
|
log.warn(
|
|
337
492
|
{ requestId, transferId, err },
|
|
@@ -353,23 +508,21 @@ export class HostTransferProxy {
|
|
|
353
508
|
errorMessage?: string;
|
|
354
509
|
},
|
|
355
510
|
): void {
|
|
356
|
-
const
|
|
357
|
-
if (!
|
|
511
|
+
const interaction = pendingInteractions.resolve(requestId);
|
|
512
|
+
if (!interaction?.rpcResolve) {
|
|
358
513
|
log.warn({ requestId }, "No pending host transfer request for response");
|
|
359
514
|
return;
|
|
360
515
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
this.pending.delete(requestId);
|
|
364
|
-
this.transfers.delete(entry.transferId);
|
|
516
|
+
const transferId = interaction.metadata?.transferId as string | undefined;
|
|
517
|
+
if (transferId) this.transfers.delete(transferId);
|
|
365
518
|
|
|
366
519
|
if (result.isError) {
|
|
367
|
-
|
|
520
|
+
interaction.rpcResolve({
|
|
368
521
|
content: result.errorMessage ?? "Host transfer failed",
|
|
369
522
|
isError: true,
|
|
370
523
|
});
|
|
371
524
|
} else {
|
|
372
|
-
|
|
525
|
+
interaction.rpcResolve({
|
|
373
526
|
content: `File transferred successfully${result.bytesWritten != null ? ` (${result.bytesWritten} bytes)` : ""}`,
|
|
374
527
|
isError: false,
|
|
375
528
|
});
|
|
@@ -394,8 +547,21 @@ export class HostTransferProxy {
|
|
|
394
547
|
) {
|
|
395
548
|
return null;
|
|
396
549
|
}
|
|
397
|
-
//
|
|
398
|
-
//
|
|
550
|
+
// Stash size/sha256 so the GET-content route's `resolveResponseHeaders`
|
|
551
|
+
// callback can still set `Content-Length` and `X-Transfer-SHA256` on the
|
|
552
|
+
// response. The HTTP adapter invokes the handler (this method) BEFORE the
|
|
553
|
+
// response-header resolver, so without this stash the resolver sees a
|
|
554
|
+
// deleted entry and silently falls back to default headers.
|
|
555
|
+
this.justConsumedMetadata.set(transferId, {
|
|
556
|
+
sizeBytes: entry.sizeBytes,
|
|
557
|
+
sha256: entry.sha256,
|
|
558
|
+
});
|
|
559
|
+
// Fallback cleanup: if the resolver never reads (e.g., handler error after
|
|
560
|
+
// consume, request abort), drop the metadata after a short grace window.
|
|
561
|
+
// `unref()` so the timer never holds the process open.
|
|
562
|
+
setTimeout(() => {
|
|
563
|
+
this.justConsumedMetadata.delete(transferId);
|
|
564
|
+
}, 30_000).unref?.();
|
|
399
565
|
this.transfers.delete(transferId);
|
|
400
566
|
return {
|
|
401
567
|
buffer: entry.fileBuffer,
|
|
@@ -404,6 +570,23 @@ export class HostTransferProxy {
|
|
|
404
570
|
};
|
|
405
571
|
}
|
|
406
572
|
|
|
573
|
+
/**
|
|
574
|
+
* Returns and clears the size/sha256 metadata for a transfer that was just
|
|
575
|
+
* consumed by `getTransferContent`. Intended for use by the GET-content
|
|
576
|
+
* route's `resolveResponseHeaders` callback to populate `Content-Length` and
|
|
577
|
+
* `X-Transfer-SHA256` response headers. Returns null if no metadata is
|
|
578
|
+
* cached (e.g., transfer was never consumed, or already read by a previous
|
|
579
|
+
* resolver call).
|
|
580
|
+
*/
|
|
581
|
+
takeJustConsumedTransferMetadata(
|
|
582
|
+
transferId: string,
|
|
583
|
+
): { sizeBytes: number; sha256: string } | null {
|
|
584
|
+
const meta = this.justConsumedMetadata.get(transferId);
|
|
585
|
+
if (!meta) return null;
|
|
586
|
+
this.justConsumedMetadata.delete(transferId);
|
|
587
|
+
return meta;
|
|
588
|
+
}
|
|
589
|
+
|
|
407
590
|
/**
|
|
408
591
|
* Receive file content from the client for a to_sandbox transfer (the PUT content endpoint).
|
|
409
592
|
*
|
|
@@ -437,29 +620,25 @@ export class HostTransferProxy {
|
|
|
437
620
|
|
|
438
621
|
const { requestId } = entry;
|
|
439
622
|
|
|
440
|
-
// Enforce overwrite policy before writing.
|
|
441
623
|
if (entry.overwrite !== true && existsSync(entry.filePath)) {
|
|
442
624
|
const errorMsg = `Destination file already exists: ${entry.filePath}. Set overwrite to true to replace it.`;
|
|
443
|
-
|
|
444
|
-
entry.detachAbort();
|
|
445
|
-
this.pending.delete(requestId);
|
|
625
|
+
const interaction = pendingInteractions.resolve(requestId);
|
|
446
626
|
this.transfers.delete(transferId);
|
|
447
|
-
|
|
627
|
+
interaction?.rpcResolve?.({ content: errorMsg, isError: true });
|
|
448
628
|
return { accepted: false, error: errorMsg };
|
|
449
629
|
}
|
|
450
630
|
|
|
451
631
|
const cleanup = () => {
|
|
452
|
-
|
|
453
|
-
entry.detachAbort();
|
|
454
|
-
this.pending.delete(requestId);
|
|
632
|
+
pendingInteractions.resolve(requestId);
|
|
455
633
|
this.transfers.delete(transferId);
|
|
456
634
|
};
|
|
457
635
|
|
|
458
636
|
try {
|
|
459
637
|
await mkdir(dirname(entry.filePath), { recursive: true });
|
|
460
638
|
await writeFile(entry.filePath, data);
|
|
639
|
+
const interaction = pendingInteractions.get(requestId);
|
|
461
640
|
cleanup();
|
|
462
|
-
|
|
641
|
+
interaction?.rpcResolve?.({
|
|
463
642
|
content: `File received and written to ${entry.filePath} (${data.length} bytes)`,
|
|
464
643
|
isError: false,
|
|
465
644
|
});
|
|
@@ -470,31 +649,37 @@ export class HostTransferProxy {
|
|
|
470
649
|
{ transferId, filePath: entry.filePath, err },
|
|
471
650
|
"Failed to write received transfer content",
|
|
472
651
|
);
|
|
652
|
+
const interaction = pendingInteractions.get(requestId);
|
|
473
653
|
cleanup();
|
|
474
|
-
|
|
654
|
+
interaction?.rpcResolve?.({ content: errorMsg, isError: true });
|
|
475
655
|
return { accepted: false, error: errorMsg };
|
|
476
656
|
}
|
|
477
657
|
}
|
|
478
658
|
|
|
479
659
|
/** Cancel a pending transfer by requestId. */
|
|
480
660
|
cancel(requestId: string): void {
|
|
481
|
-
const
|
|
482
|
-
if (!
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
this.pending.delete(requestId);
|
|
486
|
-
this.transfers.delete(entry.transferId);
|
|
661
|
+
const interaction = pendingInteractions.get(requestId);
|
|
662
|
+
if (!interaction) return;
|
|
663
|
+
const transferId = interaction.metadata?.transferId as string | undefined;
|
|
664
|
+
if (transferId) this.transfers.delete(transferId);
|
|
487
665
|
pendingInteractions.resolve(requestId);
|
|
488
666
|
try {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
667
|
+
broadcastMessage(
|
|
668
|
+
{
|
|
669
|
+
type: "host_transfer_cancel",
|
|
670
|
+
requestId,
|
|
671
|
+
conversationId: interaction.conversationId,
|
|
672
|
+
...(interaction.targetClientId != null
|
|
673
|
+
? { targetClientId: interaction.targetClientId }
|
|
674
|
+
: {}),
|
|
675
|
+
},
|
|
676
|
+
interaction.conversationId,
|
|
677
|
+
{ targetClientId: interaction.targetClientId },
|
|
678
|
+
);
|
|
494
679
|
} catch {
|
|
495
|
-
// Best-effort cancel notification
|
|
680
|
+
// Best-effort cancel notification
|
|
496
681
|
}
|
|
497
|
-
|
|
682
|
+
interaction.rpcResolve?.({ content: "Transfer cancelled", isError: true });
|
|
498
683
|
}
|
|
499
684
|
|
|
500
685
|
hasPendingTransfer(transferId: string): boolean {
|
|
@@ -511,28 +696,52 @@ export class HostTransferProxy {
|
|
|
511
696
|
return entry?.requestId ?? null;
|
|
512
697
|
}
|
|
513
698
|
|
|
699
|
+
/**
|
|
700
|
+
* Look up the targetClientId for a given transferId without consuming the entry.
|
|
701
|
+
* Routes call this to verify ownership without affecting the transfer state.
|
|
702
|
+
* Returns null when untargeted (no validation needed).
|
|
703
|
+
*/
|
|
704
|
+
getTargetClientIdForTransfer(transferId: string): string | null {
|
|
705
|
+
return this.transfers.get(transferId)?.targetClientId ?? null;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Look up the persisted `targetActorPrincipalId` for a given transferId
|
|
710
|
+
* without consuming the entry. Routes call this for the same-actor
|
|
711
|
+
* binding check so it's stable across brief SSE reconnects.
|
|
712
|
+
*/
|
|
713
|
+
getTargetActorPrincipalIdForTransfer(transferId: string): string | undefined {
|
|
714
|
+
return this.transfers.get(transferId)?.targetActorPrincipalId;
|
|
715
|
+
}
|
|
716
|
+
|
|
514
717
|
dispose(): void {
|
|
515
|
-
for (const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
pendingInteractions.resolve(requestId);
|
|
718
|
+
for (const entry of pendingInteractions.getByKind("host_transfer")) {
|
|
719
|
+
const transferId = entry.metadata?.transferId as string | undefined;
|
|
720
|
+
if (transferId) this.transfers.delete(transferId);
|
|
721
|
+
pendingInteractions.resolve(entry.requestId);
|
|
519
722
|
try {
|
|
520
|
-
|
|
723
|
+
broadcastMessage(
|
|
724
|
+
{
|
|
521
725
|
type: "host_transfer_cancel",
|
|
522
|
-
requestId,
|
|
726
|
+
requestId: entry.requestId,
|
|
523
727
|
conversationId: entry.conversationId,
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
728
|
+
...(entry.targetClientId != null
|
|
729
|
+
? { targetClientId: entry.targetClientId }
|
|
730
|
+
: {}),
|
|
731
|
+
},
|
|
732
|
+
entry.conversationId,
|
|
733
|
+
{ targetClientId: entry.targetClientId },
|
|
734
|
+
);
|
|
735
|
+
} catch {
|
|
736
|
+
// Best-effort cancel notification
|
|
737
|
+
}
|
|
738
|
+
entry.rpcReject?.(
|
|
529
739
|
new AssistantError(
|
|
530
740
|
"Host transfer proxy disposed",
|
|
531
741
|
ErrorCode.INTERNAL_ERROR,
|
|
532
742
|
),
|
|
533
743
|
);
|
|
534
744
|
}
|
|
535
|
-
this.pending.clear();
|
|
536
745
|
this.transfers.clear();
|
|
537
746
|
}
|
|
538
747
|
}
|