@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
|
@@ -119,6 +119,7 @@ let mockSingletonProxy: HostBrowserProxy | null = null;
|
|
|
119
119
|
/** Default proxy that reports unavailable — used when no test override is set. */
|
|
120
120
|
const unavailableFallback: HostBrowserProxy = {
|
|
121
121
|
isAvailable: () => false,
|
|
122
|
+
hasExtensionClient: () => false,
|
|
122
123
|
request: () => Promise.reject(new Error("no extension")),
|
|
123
124
|
resolve: () => {},
|
|
124
125
|
hasPendingRequest: () => false,
|
|
@@ -161,23 +162,38 @@ function makeContext(
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
/**
|
|
164
|
-
* Create a fake HostBrowserProxy
|
|
165
|
+
* Create a fake HostBrowserProxy with a Chrome Extension client connected.
|
|
166
|
+
* Both isAvailable() and hasExtensionClient() return true.
|
|
165
167
|
*/
|
|
166
168
|
function makeAvailableProxy(): HostBrowserProxy {
|
|
167
169
|
return {
|
|
168
170
|
request: mock(async () => ({})),
|
|
169
171
|
isAvailable: () => true,
|
|
172
|
+
hasExtensionClient: () => true,
|
|
173
|
+
} as unknown as HostBrowserProxy;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Create a fake HostBrowserProxy where only the macOS SSE bridge is connected
|
|
178
|
+
* (no Chrome Extension). isAvailable() is true but hasExtensionClient() is false.
|
|
179
|
+
*/
|
|
180
|
+
function makeMacosBridgeOnlyProxy(): HostBrowserProxy {
|
|
181
|
+
return {
|
|
182
|
+
request: mock(async () => ({})),
|
|
183
|
+
isAvailable: () => true,
|
|
184
|
+
hasExtensionClient: () => false,
|
|
170
185
|
} as unknown as HostBrowserProxy;
|
|
171
186
|
}
|
|
172
187
|
|
|
173
188
|
/**
|
|
174
189
|
* Create a fake HostBrowserProxy that reports as unavailable
|
|
175
|
-
* (proxy exists but client is
|
|
190
|
+
* (proxy exists but no client of any kind is connected).
|
|
176
191
|
*/
|
|
177
192
|
function makeUnavailableProxy(): HostBrowserProxy {
|
|
178
193
|
return {
|
|
179
194
|
request: mock(async () => ({})),
|
|
180
195
|
isAvailable: () => false,
|
|
196
|
+
hasExtensionClient: () => false,
|
|
181
197
|
} as unknown as HostBrowserProxy;
|
|
182
198
|
}
|
|
183
199
|
|
|
@@ -682,6 +698,22 @@ describe("buildCandidateList", () => {
|
|
|
682
698
|
expect(candidates[0].kind).toBe("local");
|
|
683
699
|
});
|
|
684
700
|
|
|
701
|
+
test("excludes extension candidate when only macOS SSE bridge is connected", () => {
|
|
702
|
+
// isAvailable() = true but hasExtensionClient() = false: only macOS bridge.
|
|
703
|
+
// The macOS bridge routes through localhost:9222 on the host, so it must
|
|
704
|
+
// NOT be included under the "extension" candidate kind.
|
|
705
|
+
const fakeProxy = makeMacosBridgeOnlyProxy();
|
|
706
|
+
mockSingletonProxy = fakeProxy;
|
|
707
|
+
const ctx = makeContext({
|
|
708
|
+
conversationId: "candidates-macos-bridge-only",
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
const candidates = buildCandidateList(ctx);
|
|
712
|
+
|
|
713
|
+
expect(candidates.every((c) => c.kind !== "extension")).toBe(true);
|
|
714
|
+
expect(candidates[candidates.length - 1].kind).toBe("local");
|
|
715
|
+
});
|
|
716
|
+
|
|
685
717
|
test("includes cdp-inspect candidate when enabled in config", () => {
|
|
686
718
|
cdpInspectEnabled = true;
|
|
687
719
|
const ctx = makeContext({ conversationId: "candidates-inspect" });
|
|
@@ -1435,7 +1467,7 @@ describe("pinned-mode selection", () => {
|
|
|
1435
1467
|
const cdpErr = err as CdpError;
|
|
1436
1468
|
expect(cdpErr.code).toBe("transport_error");
|
|
1437
1469
|
expect(cdpErr.message).toContain('Pinned mode "extension" unavailable');
|
|
1438
|
-
expect(cdpErr.message).toContain("no
|
|
1470
|
+
expect(cdpErr.message).toContain("no Chrome Extension connected");
|
|
1439
1471
|
expect(cdpErr.attemptDiagnostics).toBeDefined();
|
|
1440
1472
|
expect(cdpErr.attemptDiagnostics).toHaveLength(1);
|
|
1441
1473
|
expect(cdpErr.attemptDiagnostics![0].candidateKind).toBe("extension");
|
|
@@ -1457,7 +1489,7 @@ describe("pinned-mode selection", () => {
|
|
|
1457
1489
|
} catch (err) {
|
|
1458
1490
|
const cdpErr = err as CdpError;
|
|
1459
1491
|
expect(cdpErr.code).toBe("transport_error");
|
|
1460
|
-
expect(cdpErr.message).toContain("no
|
|
1492
|
+
expect(cdpErr.message).toContain("no Chrome Extension connected");
|
|
1461
1493
|
expect(cdpErr.attemptDiagnostics![0].stage).toBe("candidate_selection");
|
|
1462
1494
|
}
|
|
1463
1495
|
});
|
|
@@ -1667,6 +1699,25 @@ describe("buildPinnedCandidateList", () => {
|
|
|
1667
1699
|
});
|
|
1668
1700
|
}
|
|
1669
1701
|
});
|
|
1702
|
+
|
|
1703
|
+
test("extension mode throws when only macOS SSE bridge is connected", () => {
|
|
1704
|
+
// This is the bug case: isAvailable() = true but hasExtensionClient() = false.
|
|
1705
|
+
// Before the fix, this would build an extension candidate that silently
|
|
1706
|
+
// dispatched to the macOS bridge and failed with a misleading localhost:9222 error.
|
|
1707
|
+
const fakeProxy = makeMacosBridgeOnlyProxy();
|
|
1708
|
+
mockSingletonProxy = fakeProxy;
|
|
1709
|
+
const ctx = makeContext({ conversationId: "bpl-ext-macos-bridge-only" });
|
|
1710
|
+
|
|
1711
|
+
try {
|
|
1712
|
+
buildPinnedCandidateList(ctx, "extension");
|
|
1713
|
+
expect(true).toBe(false); // should not reach
|
|
1714
|
+
} catch (err) {
|
|
1715
|
+
expect(err).toBeInstanceOf(CdpError);
|
|
1716
|
+
const cdpErr = err as CdpError;
|
|
1717
|
+
expect(cdpErr.code).toBe("transport_error");
|
|
1718
|
+
expect(cdpErr.message).toContain("no Chrome Extension connected");
|
|
1719
|
+
}
|
|
1720
|
+
});
|
|
1670
1721
|
});
|
|
1671
1722
|
|
|
1672
1723
|
// ── Attempt diagnostics & fallback log tests ─────────────────────────────
|
|
@@ -511,14 +511,19 @@ describe("connectCdpWsTransport", () => {
|
|
|
511
511
|
});
|
|
512
512
|
|
|
513
513
|
test("addEventListener returns an unsubscribe function", async () => {
|
|
514
|
+
// Use a sentinel request to gate event emission on the server: the
|
|
515
|
+
// listener is registered before send() runs, so by the time the server
|
|
516
|
+
// receives the sentinel and starts emitting events the client listener
|
|
517
|
+
// is guaranteed to be attached. A bare setTimeout-after-open race is
|
|
518
|
+
// tight enough to flake on busy CI runners.
|
|
514
519
|
const server = startFakeWsServer({
|
|
515
|
-
|
|
520
|
+
onMessage(ws, frame) {
|
|
521
|
+
if (frame.method !== "Test.startEvents") return;
|
|
522
|
+
ws.send(JSON.stringify({ id: frame.id, result: {} }));
|
|
523
|
+
ws.send(JSON.stringify({ method: "Ev.first", params: {} }));
|
|
516
524
|
setTimeout(() => {
|
|
517
|
-
ws.send(JSON.stringify({ method: "Ev.
|
|
518
|
-
|
|
519
|
-
ws.send(JSON.stringify({ method: "Ev.second", params: {} }));
|
|
520
|
-
}, 10);
|
|
521
|
-
}, 5);
|
|
525
|
+
ws.send(JSON.stringify({ method: "Ev.second", params: {} }));
|
|
526
|
+
}, 10);
|
|
522
527
|
},
|
|
523
528
|
});
|
|
524
529
|
try {
|
|
@@ -528,6 +533,7 @@ describe("connectCdpWsTransport", () => {
|
|
|
528
533
|
received.push(ev.method);
|
|
529
534
|
if (ev.method === "Ev.first") unsub();
|
|
530
535
|
});
|
|
536
|
+
await transport.send("Test.startEvents");
|
|
531
537
|
await new Promise((r) => setTimeout(r, 60));
|
|
532
538
|
expect(received).toEqual(["Ev.first"]);
|
|
533
539
|
});
|
|
@@ -187,25 +187,25 @@ export function buildPinnedCandidateList(
|
|
|
187
187
|
|
|
188
188
|
switch (mode) {
|
|
189
189
|
case "extension": {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
190
|
+
const hostBrowserProxy = HostBrowserProxy.instance;
|
|
191
|
+
if (!hostBrowserProxy.hasExtensionClient()) {
|
|
192
|
+
throw new CdpError(
|
|
193
|
+
"transport_error",
|
|
194
|
+
`Pinned mode "extension" unavailable: no Chrome Extension connected`,
|
|
195
|
+
{
|
|
196
|
+
attemptDiagnostics: [
|
|
197
|
+
{
|
|
198
|
+
candidateKind: "extension",
|
|
199
|
+
inclusionReason: `pinned mode: extension`,
|
|
200
|
+
stage: "candidate_selection",
|
|
201
|
+
errorCode: "transport_error",
|
|
202
|
+
errorMessage: "no Chrome Extension connected",
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
return [
|
|
209
209
|
{
|
|
210
210
|
kind: "extension",
|
|
211
211
|
reason: "pinned mode: extension",
|
|
@@ -291,12 +291,11 @@ export function buildCandidateList(context: ToolContext): BackendCandidate[] {
|
|
|
291
291
|
const candidates: BackendCandidate[] = [];
|
|
292
292
|
const hostBrowserProxy = HostBrowserProxy.instance;
|
|
293
293
|
|
|
294
|
-
// 1. Extension -- preferred when
|
|
295
|
-
|
|
296
|
-
if (hostBrowserProxy.isAvailable()) {
|
|
294
|
+
// 1. Extension -- preferred when a Chrome Extension client is connected.
|
|
295
|
+
if (hostBrowserProxy.hasExtensionClient()) {
|
|
297
296
|
candidates.push({
|
|
298
297
|
kind: "extension",
|
|
299
|
-
reason: "
|
|
298
|
+
reason: "Chrome Extension connected via registry singleton",
|
|
300
299
|
create() {
|
|
301
300
|
const client = createExtensionCdpClient(
|
|
302
301
|
hostBrowserProxy,
|
|
@@ -314,7 +313,7 @@ export function buildCandidateList(context: ToolContext): BackendCandidate[] {
|
|
|
314
313
|
} else {
|
|
315
314
|
log.debug(
|
|
316
315
|
{ conversationId },
|
|
317
|
-
"CDP factory: no
|
|
316
|
+
"CDP factory: no Chrome Extension connected, skipping extension candidate",
|
|
318
317
|
);
|
|
319
318
|
}
|
|
320
319
|
|
|
@@ -1,15 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
type CdpInspectClientOptions,
|
|
3
|
-
type CdpInspectHelpers,
|
|
4
|
-
} from "./cdp-inspect-client.js";
|
|
5
1
|
export { CdpError, type CdpErrorCode } from "./errors.js";
|
|
6
|
-
export {
|
|
7
|
-
export type {
|
|
8
|
-
AttemptDiagnostic,
|
|
9
|
-
AttemptStage,
|
|
10
|
-
BackendCandidate,
|
|
11
|
-
BrowserMode,
|
|
12
|
-
CdpClient,
|
|
13
|
-
CdpClientKind,
|
|
14
|
-
ScopedCdpClient,
|
|
15
|
-
} from "./types.js";
|
|
2
|
+
export type { CdpClient, CdpClientKind, ScopedCdpClient } from "./types.js";
|
|
@@ -21,12 +21,6 @@ function proxyExecute(): Promise<ToolExecutionResult> {
|
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const activityProperty = {
|
|
25
|
-
type: "string" as const,
|
|
26
|
-
description:
|
|
27
|
-
"Brief non-technical explanation of why this tool is being called",
|
|
28
|
-
};
|
|
29
|
-
|
|
30
24
|
// ---------------------------------------------------------------------------
|
|
31
25
|
// click (unified - click_type selects single / double / right)
|
|
32
26
|
// ---------------------------------------------------------------------------
|
|
@@ -69,7 +63,11 @@ export const computerUseClickTool: Tool = {
|
|
|
69
63
|
description:
|
|
70
64
|
"Explanation of what you see and why you are clicking here",
|
|
71
65
|
},
|
|
72
|
-
|
|
66
|
+
target_client_id: {
|
|
67
|
+
type: "string",
|
|
68
|
+
description:
|
|
69
|
+
"ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
|
|
70
|
+
},
|
|
73
71
|
},
|
|
74
72
|
required: ["reasoning"],
|
|
75
73
|
},
|
|
@@ -106,7 +104,11 @@ export const computerUseTypeTextTool: Tool = {
|
|
|
106
104
|
type: "string",
|
|
107
105
|
description: "Explanation of what you are typing and why",
|
|
108
106
|
},
|
|
109
|
-
|
|
107
|
+
target_client_id: {
|
|
108
|
+
type: "string",
|
|
109
|
+
description:
|
|
110
|
+
"ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
|
|
111
|
+
},
|
|
110
112
|
},
|
|
111
113
|
required: ["text", "reasoning"],
|
|
112
114
|
},
|
|
@@ -144,7 +146,11 @@ export const computerUseKeyTool: Tool = {
|
|
|
144
146
|
type: "string",
|
|
145
147
|
description: "Explanation of why you are pressing this key",
|
|
146
148
|
},
|
|
147
|
-
|
|
149
|
+
target_client_id: {
|
|
150
|
+
type: "string",
|
|
151
|
+
description:
|
|
152
|
+
"ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
|
|
153
|
+
},
|
|
148
154
|
},
|
|
149
155
|
required: ["key", "reasoning"],
|
|
150
156
|
},
|
|
@@ -199,7 +205,11 @@ export const computerUseScrollTool: Tool = {
|
|
|
199
205
|
type: "string",
|
|
200
206
|
description: "Explanation of why you are scrolling",
|
|
201
207
|
},
|
|
202
|
-
|
|
208
|
+
target_client_id: {
|
|
209
|
+
type: "string",
|
|
210
|
+
description:
|
|
211
|
+
"ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
|
|
212
|
+
},
|
|
203
213
|
},
|
|
204
214
|
required: ["direction", "amount", "reasoning"],
|
|
205
215
|
},
|
|
@@ -260,7 +270,11 @@ export const computerUseDragTool: Tool = {
|
|
|
260
270
|
type: "string",
|
|
261
271
|
description: "Explanation of what you are dragging and why",
|
|
262
272
|
},
|
|
263
|
-
|
|
273
|
+
target_client_id: {
|
|
274
|
+
type: "string",
|
|
275
|
+
description:
|
|
276
|
+
"ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
|
|
277
|
+
},
|
|
264
278
|
},
|
|
265
279
|
required: ["reasoning"],
|
|
266
280
|
},
|
|
@@ -296,7 +310,11 @@ export const computerUseWaitTool: Tool = {
|
|
|
296
310
|
type: "string",
|
|
297
311
|
description: "Explanation of what you are waiting for",
|
|
298
312
|
},
|
|
299
|
-
|
|
313
|
+
target_client_id: {
|
|
314
|
+
type: "string",
|
|
315
|
+
description:
|
|
316
|
+
"ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
|
|
317
|
+
},
|
|
300
318
|
},
|
|
301
319
|
required: ["duration_ms", "reasoning"],
|
|
302
320
|
},
|
|
@@ -335,7 +353,11 @@ export const computerUseOpenAppTool: Tool = {
|
|
|
335
353
|
description:
|
|
336
354
|
"Explanation of why you need to open or switch to this app",
|
|
337
355
|
},
|
|
338
|
-
|
|
356
|
+
target_client_id: {
|
|
357
|
+
type: "string",
|
|
358
|
+
description:
|
|
359
|
+
"ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
|
|
360
|
+
},
|
|
339
361
|
},
|
|
340
362
|
required: ["app_name", "reasoning"],
|
|
341
363
|
},
|
|
@@ -373,7 +395,11 @@ export const computerUseRunAppleScriptTool: Tool = {
|
|
|
373
395
|
description:
|
|
374
396
|
"Explanation of what this script does and why AppleScript is better than UI interaction for this step",
|
|
375
397
|
},
|
|
376
|
-
|
|
398
|
+
target_client_id: {
|
|
399
|
+
type: "string",
|
|
400
|
+
description:
|
|
401
|
+
"ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
|
|
402
|
+
},
|
|
377
403
|
},
|
|
378
404
|
required: ["script", "reasoning"],
|
|
379
405
|
},
|
|
@@ -406,7 +432,6 @@ export const computerUseDoneTool: Tool = {
|
|
|
406
432
|
type: "string",
|
|
407
433
|
description: "Human-readable summary of what was accomplished",
|
|
408
434
|
},
|
|
409
|
-
activity: activityProperty,
|
|
410
435
|
},
|
|
411
436
|
required: ["summary"],
|
|
412
437
|
},
|
|
@@ -443,7 +468,6 @@ export const computerUseRespondTool: Tool = {
|
|
|
443
468
|
type: "string",
|
|
444
469
|
description: "Explanation of how you determined the answer",
|
|
445
470
|
},
|
|
446
|
-
activity: activityProperty,
|
|
447
471
|
},
|
|
448
472
|
required: ["answer", "reasoning"],
|
|
449
473
|
},
|
|
@@ -471,10 +495,8 @@ const computerUseObserveTool: Tool = {
|
|
|
471
495
|
description: this.description,
|
|
472
496
|
input_schema: {
|
|
473
497
|
type: "object",
|
|
474
|
-
properties: {
|
|
475
|
-
|
|
476
|
-
},
|
|
477
|
-
required: ["activity"],
|
|
498
|
+
properties: {},
|
|
499
|
+
required: [],
|
|
478
500
|
},
|
|
479
501
|
};
|
|
480
502
|
},
|
package/src/tools/executor.ts
CHANGED
|
@@ -406,6 +406,8 @@ export class ToolExecutor {
|
|
|
406
406
|
requestId: context.requestId,
|
|
407
407
|
riskLevel,
|
|
408
408
|
matchedTrustRuleId: permMatchedTrustRuleId,
|
|
409
|
+
approvalMode: permApprovalMode,
|
|
410
|
+
approvalReason: permApprovalReason,
|
|
409
411
|
decision,
|
|
410
412
|
durationMs,
|
|
411
413
|
result: safeResult,
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { mkdtempSync, realpathSync, rmSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, describe, expect, mock, test } from "bun:test";
|
|
5
|
+
|
|
6
|
+
import type { ToolContext } from "../types.js";
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Singleton mocks — must precede the tool import so bun's module mock applies.
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
let mockProxyAvailable = false;
|
|
13
|
+
|
|
14
|
+
mock.module("../../daemon/host-file-proxy.js", () => ({
|
|
15
|
+
HostFileProxy: {
|
|
16
|
+
get instance() {
|
|
17
|
+
return {
|
|
18
|
+
isAvailable: () => mockProxyAvailable,
|
|
19
|
+
request: () => Promise.resolve({ content: "ok", isError: false }),
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
mock.module("../../runtime/assistant-event-hub.js", () => ({
|
|
26
|
+
assistantEventHub: {
|
|
27
|
+
listClientsByCapability: () => [],
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
const { hostFileEditTool } = await import("./edit.js");
|
|
32
|
+
|
|
33
|
+
const testDirs: string[] = [];
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
mockProxyAvailable = false;
|
|
37
|
+
for (const dir of testDirs.splice(0)) {
|
|
38
|
+
rmSync(dir, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
function makeTempDir(): string {
|
|
43
|
+
const dir = realpathSync(mkdtempSync(join(tmpdir(), "host-edit-test-")));
|
|
44
|
+
testDirs.push(dir);
|
|
45
|
+
return dir;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function makeContext(
|
|
49
|
+
workingDir: string,
|
|
50
|
+
transportInterface: ToolContext["transportInterface"],
|
|
51
|
+
): ToolContext {
|
|
52
|
+
return {
|
|
53
|
+
workingDir,
|
|
54
|
+
conversationId: "test-conv",
|
|
55
|
+
trustClass: "guardian",
|
|
56
|
+
transportInterface,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe("host_file_edit cross-client guards", () => {
|
|
61
|
+
test("returns 'no client' error on web transport when proxy unavailable and no targetClientId", async () => {
|
|
62
|
+
const workingDir = makeTempDir();
|
|
63
|
+
const result = await hostFileEditTool.execute(
|
|
64
|
+
{
|
|
65
|
+
path: "/some/host/path.txt",
|
|
66
|
+
old_string: "foo",
|
|
67
|
+
new_string: "bar",
|
|
68
|
+
},
|
|
69
|
+
makeContext(workingDir, "web"),
|
|
70
|
+
);
|
|
71
|
+
expect(result.isError).toBe(true);
|
|
72
|
+
expect(result.content).toContain(
|
|
73
|
+
"no client with host_file capability is connected",
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("returns 'specified client disconnected' error when targetClientId set but proxy unavailable on web", async () => {
|
|
78
|
+
const workingDir = makeTempDir();
|
|
79
|
+
const result = await hostFileEditTool.execute(
|
|
80
|
+
{
|
|
81
|
+
path: "/some/host/path.txt",
|
|
82
|
+
old_string: "foo",
|
|
83
|
+
new_string: "bar",
|
|
84
|
+
target_client_id: "abc-123",
|
|
85
|
+
},
|
|
86
|
+
makeContext(workingDir, "web"),
|
|
87
|
+
);
|
|
88
|
+
expect(result.isError).toBe(true);
|
|
89
|
+
expect(result.content).toContain(
|
|
90
|
+
'target client "abc-123" is no longer connected',
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("falls through to local fs on macos transport when proxy unavailable", async () => {
|
|
95
|
+
const workingDir = makeTempDir();
|
|
96
|
+
const result = await hostFileEditTool.execute(
|
|
97
|
+
{
|
|
98
|
+
path: "/nonexistent/x.txt",
|
|
99
|
+
old_string: "foo",
|
|
100
|
+
new_string: "bar",
|
|
101
|
+
},
|
|
102
|
+
makeContext(workingDir, "macos"),
|
|
103
|
+
);
|
|
104
|
+
// Proves the guard did NOT fire on macOS — instead we got the
|
|
105
|
+
// local FileSystemOps error path (file not found / IO error).
|
|
106
|
+
expect(result.isError).toBe(true);
|
|
107
|
+
expect(result.content.toLowerCase()).toMatch(/not found|enoent|editing/);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("does NOT reject on macos transport with a stale target_client_id when proxy unavailable (regression: P2 fix)", async () => {
|
|
111
|
+
const workingDir = makeTempDir();
|
|
112
|
+
const result = await hostFileEditTool.execute(
|
|
113
|
+
{
|
|
114
|
+
path: "/nonexistent/x.txt",
|
|
115
|
+
old_string: "foo",
|
|
116
|
+
new_string: "bar",
|
|
117
|
+
target_client_id: "stale-mac",
|
|
118
|
+
},
|
|
119
|
+
makeContext(workingDir, "macos"),
|
|
120
|
+
);
|
|
121
|
+
// The disconnected-target guard is scoped to non-host-proxy transports
|
|
122
|
+
// (!supportsHostProxy). On macos, a stale target_client_id auto-filled
|
|
123
|
+
// from a prior cross-client turn must be silently ignored and the call
|
|
124
|
+
// must fall through to local FileSystemOps, NOT reject with "target
|
|
125
|
+
// client ... is no longer connected".
|
|
126
|
+
expect(result.isError).toBe(true);
|
|
127
|
+
expect(result.content).not.toContain("is no longer connected");
|
|
128
|
+
expect(result.content.toLowerCase()).toMatch(/not found|enoent|editing/);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("rejects when target_client_id is set but transport metadata is missing (legacy/backwards-compat path)", async () => {
|
|
132
|
+
const workingDir = makeTempDir();
|
|
133
|
+
const result = await hostFileEditTool.execute(
|
|
134
|
+
{
|
|
135
|
+
path: "/some/host/path.txt",
|
|
136
|
+
old_string: "foo",
|
|
137
|
+
new_string: "bar",
|
|
138
|
+
target_client_id: "abc-123",
|
|
139
|
+
},
|
|
140
|
+
// transportInterface intentionally undefined (legacy callers).
|
|
141
|
+
makeContext(workingDir, undefined),
|
|
142
|
+
);
|
|
143
|
+
// Without transport metadata, falling through to local fs would
|
|
144
|
+
// silently target the daemon container. The guard fires for undefined
|
|
145
|
+
// transport AND non-host-proxy transports — only macos turns skip it.
|
|
146
|
+
expect(result.isError).toBe(true);
|
|
147
|
+
expect(result.content).toContain(
|
|
148
|
+
'target client "abc-123" is no longer connected',
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { supportsHostProxy } from "../../channels/types.js";
|
|
1
2
|
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
2
3
|
import { RiskLevel } from "../../permissions/types.js";
|
|
3
4
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
5
|
+
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
4
6
|
import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
|
|
5
7
|
import { formatEditDiff } from "../shared/filesystem/format-diff.js";
|
|
6
8
|
import { hostPolicy } from "../shared/filesystem/path-policy.js";
|
|
@@ -37,6 +39,11 @@ class HostFileEditTool implements Tool {
|
|
|
37
39
|
description:
|
|
38
40
|
"Replace all occurrences instead of requiring a unique match (default: false)",
|
|
39
41
|
},
|
|
42
|
+
target_client_id: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description:
|
|
45
|
+
"ID of the specific client to execute this on. Required when multiple clients support host_file; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_file`.",
|
|
46
|
+
},
|
|
40
47
|
},
|
|
41
48
|
required: ["path", "old_string", "new_string"],
|
|
42
49
|
},
|
|
@@ -84,6 +91,64 @@ class HostFileEditTool implements Tool {
|
|
|
84
91
|
|
|
85
92
|
const replaceAll = input.replace_all === true;
|
|
86
93
|
|
|
94
|
+
const targetClientId =
|
|
95
|
+
typeof input.target_client_id === "string" &&
|
|
96
|
+
input.target_client_id !== ""
|
|
97
|
+
? input.target_client_id
|
|
98
|
+
: undefined;
|
|
99
|
+
|
|
100
|
+
const transportInterface = context.transportInterface;
|
|
101
|
+
if (
|
|
102
|
+
targetClientId == null &&
|
|
103
|
+
transportInterface != null &&
|
|
104
|
+
!supportsHostProxy(transportInterface) &&
|
|
105
|
+
assistantEventHub.listClientsByCapability("host_file").length > 1
|
|
106
|
+
) {
|
|
107
|
+
return {
|
|
108
|
+
content: `Error: multiple clients support host_file. Specify which client to use with \`target_client_id\`. Run \`assistant clients list --capability host_file\` to see client IDs and labels.`,
|
|
109
|
+
isError: true,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Guard: non-host-proxy interfaces with no capable clients connected.
|
|
114
|
+
// Without this guard, the request would fall through to local
|
|
115
|
+
// FileSystemOps below and read the daemon container's filesystem
|
|
116
|
+
// instead of the user's host machine.
|
|
117
|
+
if (
|
|
118
|
+
targetClientId == null &&
|
|
119
|
+
transportInterface != null &&
|
|
120
|
+
!supportsHostProxy(transportInterface) &&
|
|
121
|
+
!HostFileProxy.instance.isAvailable()
|
|
122
|
+
) {
|
|
123
|
+
return {
|
|
124
|
+
content:
|
|
125
|
+
"Error: no client with host_file capability is connected. Connect a macOS client to use host_file from a non-desktop interface.",
|
|
126
|
+
isError: true,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Guard: explicit targetClientId provided but proxy is unavailable.
|
|
131
|
+
// Fires on non-host-proxy transports (web, ios) AND on legacy callers
|
|
132
|
+
// without transport metadata, where falling through to local fs would
|
|
133
|
+
// silently target the daemon container's filesystem instead of the
|
|
134
|
+
// intended host client. Skips only when transport is explicitly
|
|
135
|
+
// host-proxy-capable (macos), where local-fs fallback IS the intended
|
|
136
|
+
// offline behavior — a stale target_client_id auto-filled from a prior
|
|
137
|
+
// cross-client turn is silently ignored on those turns.
|
|
138
|
+
// Note: this scoping deliberately differs from host_bash
|
|
139
|
+
// (host-shell.ts:239-247), which rejects unconditionally for any
|
|
140
|
+
// stale target_client_id regardless of transport.
|
|
141
|
+
if (
|
|
142
|
+
targetClientId != null &&
|
|
143
|
+
!HostFileProxy.instance.isAvailable() &&
|
|
144
|
+
(transportInterface == null || !supportsHostProxy(transportInterface))
|
|
145
|
+
) {
|
|
146
|
+
return {
|
|
147
|
+
content: `Error: target client "${targetClientId}" is no longer connected. The specified client may have disconnected since the tool was called. Run \`assistant clients list --capability host_file\` to see currently connected clients.`,
|
|
148
|
+
isError: true,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
87
152
|
// Proxy to connected client for execution on the user's machine
|
|
88
153
|
// when a capable client is available (managed/cloud-hosted mode).
|
|
89
154
|
if (HostFileProxy.instance.isAvailable()) {
|
|
@@ -94,9 +159,12 @@ class HostFileEditTool implements Tool {
|
|
|
94
159
|
old_string: oldString as string,
|
|
95
160
|
new_string: newString as string,
|
|
96
161
|
replace_all: replaceAll,
|
|
162
|
+
targetClientId,
|
|
97
163
|
},
|
|
98
164
|
context.conversationId,
|
|
99
165
|
context.signal,
|
|
166
|
+
targetClientId,
|
|
167
|
+
context.sourceActorPrincipalId,
|
|
100
168
|
);
|
|
101
169
|
}
|
|
102
170
|
|