@vellumai/assistant 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +32 -49
- package/Dockerfile +1 -0
- package/README.md +1 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
- package/bun.lock +26 -26
- package/docs/architecture/security.md +20 -0
- package/docs/plugins.md +7 -9
- package/knip.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +39 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
- package/node_modules/@vellumai/service-contracts/package.json +2 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +9 -0
- package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
- package/node_modules/@vellumai/twilio-client/package.json +18 -0
- package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
- package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
- package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
- package/openapi.yaml +565 -12
- package/package.json +6 -3
- package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
- package/src/__tests__/app-bundler.test.ts +170 -1
- package/src/__tests__/app-control-flow.test.ts +374 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
- package/src/__tests__/app-executors.test.ts +30 -43
- package/src/__tests__/approval-routes-http.test.ts +23 -6
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
- package/src/__tests__/assistant-event-hub.test.ts +109 -2
- package/src/__tests__/assistant-event.test.ts +10 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +7 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -7
- package/src/__tests__/background-shell-host-bash.test.ts +14 -15
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
- package/src/__tests__/btw-routes.test.ts +13 -4
- package/src/__tests__/call-controller.test.ts +49 -1
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/channel-readiness-service.test.ts +59 -1
- package/src/__tests__/checker.test.ts +3 -4
- package/src/__tests__/config-loader-backfill.test.ts +90 -155
- package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-lifecycle.test.ts +36 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-slash-commands.test.ts +0 -4
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +317 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
- package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
- package/src/__tests__/credentials-cli.test.ts +5 -12
- package/src/__tests__/cu-unified-flow.test.ts +185 -23
- package/src/__tests__/daemon-credential-client.test.ts +101 -19
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
- package/src/__tests__/heartbeat-service.test.ts +718 -1
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/host-app-control-proxy.test.ts +602 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +246 -47
- package/src/__tests__/host-bash-routes.test.ts +294 -0
- package/src/__tests__/host-browser-proxy.test.ts +24 -22
- package/src/__tests__/host-browser-routes.test.ts +39 -13
- package/src/__tests__/host-cu-proxy.test.ts +41 -52
- package/src/__tests__/host-cu-routes-targeted.test.ts +300 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +339 -0
- package/src/__tests__/host-file-proxy.test.ts +37 -43
- package/src/__tests__/host-file-read-tool.test.ts +17 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +262 -0
- package/src/__tests__/host-file-write-tool.test.ts +42 -1
- package/src/__tests__/host-proxy-base.test.ts +312 -0
- package/src/__tests__/host-shell-tool.test.ts +22 -4
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +583 -0
- package/src/__tests__/host-transfer-proxy.test.ts +121 -22
- package/src/__tests__/host-transfer-routes-targeted.test.ts +447 -0
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +29 -0
- package/src/__tests__/identity-routes.test.ts +103 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
- package/src/__tests__/inline-command-runner.test.ts +0 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
- package/src/__tests__/integration-status.test.ts +85 -5
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/migration-import-commit-http.test.ts +108 -2
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
- package/src/__tests__/prechat-onboarding-contract.test.ts +3 -1
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +97 -0
- package/src/__tests__/require-fresh-approval.test.ts +0 -1
- package/src/__tests__/retry-backoff.test.ts +87 -0
- package/src/__tests__/runtime-events-sse.test.ts +10 -6
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
- package/src/__tests__/skill-feature-flags.test.ts +43 -41
- package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
- package/src/__tests__/skill-load-inline-command.test.ts +0 -51
- package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
- package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +9 -14
- package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-config.test.ts +0 -1
- package/src/__tests__/test-preload.ts +8 -0
- package/src/__tests__/tool-approval-handler.test.ts +3 -4
- package/src/__tests__/tool-audit-listener.test.ts +48 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +3 -16
- package/src/__tests__/twilio-routes.test.ts +3 -5
- package/src/__tests__/twilio-validation.test.ts +93 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
- package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
- package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
- package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- package/src/backup/__tests__/paths.test.ts +0 -22
- package/src/backup/__tests__/restore.test.ts +51 -151
- package/src/backup/paths.ts +2 -18
- package/src/backup/restore.ts +107 -231
- package/src/bundler/app-bundler.ts +51 -3
- package/src/calls/relay-server.ts +4 -44
- package/src/calls/twilio-config.ts +2 -17
- package/src/calls/twilio-rest.ts +33 -105
- package/src/calls/twilio-routes.ts +11 -12
- package/src/channels/types.ts +8 -7
- package/src/cli/commands/__tests__/backup.test.ts +6 -277
- package/src/cli/commands/__tests__/gateway.test.ts +288 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -1
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/clients.ts +36 -37
- package/src/cli/commands/contacts.ts +73 -0
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +15 -7
- package/src/cli/commands/domain.ts +66 -15
- package/src/cli/commands/gateway.ts +183 -0
- package/src/cli/commands/keys.ts +9 -6
- package/src/cli/commands/mcp.ts +116 -156
- package/src/cli/commands/memory-v2.ts +296 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/status.test.ts +13 -15
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +0 -18
- package/src/cli/lib/daemon-credential-client.ts +110 -28
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +67 -10
- package/src/config/bundled-skills/acp/SKILL.md +6 -0
- package/src/config/bundled-skills/acp/TOOLS.json +1 -22
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
- package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
- package/src/config/bundled-skills/app-control/SKILL.md +75 -0
- package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
- package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
- package/src/config/bundled-skills/document/TOOLS.json +0 -8
- package/src/config/bundled-skills/followups/TOOLS.json +0 -12
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
- package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
- package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +19 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
- package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
- package/src/config/bundled-skills/settings/SKILL.md +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +0 -12
- package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
- package/src/config/bundled-skills/subagent/SKILL.md +6 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
- package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
- package/src/config/bundled-tool-registry.ts +21 -0
- package/src/config/env-registry.ts +0 -2
- package/src/config/env.ts +19 -12
- package/src/config/feature-flag-registry.json +21 -133
- package/src/config/loader.ts +73 -99
- package/src/config/sanitize-for-transfer.ts +2 -0
- package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +7 -4
- package/src/config/schemas/calls.ts +0 -9
- package/src/config/schemas/heartbeat.ts +63 -0
- package/src/config/schemas/ingress.ts +10 -6
- package/src/config/schemas/llm.ts +5 -10
- package/src/config/schemas/memory-lifecycle.ts +77 -24
- package/src/config/schemas/memory-v2.ts +48 -4
- package/src/config/schemas/platform.ts +6 -0
- package/src/config/schemas/services.ts +1 -15
- package/src/config/schemas/skills.ts +0 -6
- package/src/config/seed-inference-profiles.ts +1 -1
- package/src/contacts/contact-store.ts +0 -30
- package/src/contacts/contacts-write.ts +0 -27
- package/src/context/window-manager.ts +1 -2
- package/src/credential-execution/feature-gates.ts +10 -10
- package/src/credential-execution/process-manager.ts +12 -41
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +126 -5
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +4 -3
- package/src/daemon/conversation-agent-loop-handlers.ts +21 -3
- package/src/daemon/conversation-agent-loop.ts +32 -28
- package/src/daemon/conversation-lifecycle.ts +8 -1
- package/src/daemon/conversation-process.ts +16 -11
- package/src/daemon/conversation-runtime-assembly.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +125 -4
- package/src/daemon/conversation-tool-setup.ts +16 -55
- package/src/daemon/conversation.ts +21 -2
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/handlers/shared.ts +4 -1
- package/src/daemon/host-app-control-proxy.ts +293 -0
- package/src/daemon/host-bash-proxy.ts +84 -74
- package/src/daemon/host-browser-proxy.ts +67 -82
- package/src/daemon/host-cu-proxy.ts +81 -86
- package/src/daemon/host-file-proxy.ts +93 -69
- package/src/daemon/host-proxy-base.ts +294 -0
- package/src/daemon/host-proxy-preactivation.ts +82 -0
- package/src/daemon/host-transfer-proxy.ts +247 -129
- package/src/daemon/lifecycle.ts +115 -117
- package/src/daemon/message-protocol.ts +3 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +11 -8
- package/src/daemon/message-types/host-app-control.ts +150 -0
- package/src/daemon/message-types/host-bash.ts +4 -0
- package/src/daemon/message-types/host-cu.ts +2 -0
- package/src/daemon/message-types/host-file.ts +4 -0
- package/src/daemon/message-types/host-transfer.ts +3 -0
- package/src/daemon/message-types/schedules.ts +8 -3
- package/src/daemon/message-types/skills.ts +2 -2
- package/src/daemon/process-message.ts +18 -1
- package/src/daemon/shutdown-handlers.ts +0 -3
- package/src/daemon/tool-setup-types.ts +51 -0
- package/src/daemon/tool-side-effects.ts +1 -1
- package/src/events/tool-audit-listener.ts +2 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +15 -7
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +216 -0
- package/src/heartbeat/heartbeat-run-store.ts +236 -0
- package/src/heartbeat/heartbeat-service.ts +280 -49
- package/src/home/__tests__/post-connect-feed.test.ts +99 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
- package/src/home/__tests__/suggested-prompts.test.ts +89 -0
- package/src/home/post-connect-feed.ts +68 -0
- package/src/home/relationship-state-writer.ts +17 -92
- package/src/home/suggested-prompts.ts +46 -10
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/assistant-server.ts +14 -1
- package/src/ipc/cli-client.ts +32 -1
- package/src/live-voice/live-voice-metrics.ts +10 -10
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
- package/src/mcp/mcp-auth-orchestrator.ts +213 -0
- package/src/mcp/mcp-auth-state.ts +133 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
- package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
- package/src/memory/anisotropy.test.ts +247 -0
- package/src/memory/anisotropy.ts +443 -0
- package/src/memory/auto-analysis-constants.ts +17 -0
- package/src/memory/auto-analysis-guard.ts +5 -15
- package/src/memory/canonical-guardian-store.ts +7 -7
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
- package/src/memory/context-search/agent-protocol.ts +6 -6
- package/src/memory/context-search/agent-runner.ts +32 -7
- package/src/memory/context-search/sources/memory-v2.ts +17 -5
- package/src/memory/conversation-crud.ts +1 -1
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/db-init.ts +4 -0
- package/src/memory/embedding-backend.ts +9 -21
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +49 -4
- package/src/memory/graph/conversation-graph-memory.ts +1 -24
- package/src/memory/graph/graph-search.ts +8 -0
- package/src/memory/graph/retriever.ts +28 -0
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
- package/src/memory/jobs/embed-concept-page.ts +28 -2
- package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
- package/src/memory/jobs-store.ts +66 -22
- package/src/memory/jobs-worker.ts +112 -63
- package/src/memory/memory-v2-activation-log-store.ts +1 -1
- package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
- package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +50 -20
- package/src/memory/schema/infrastructure.ts +15 -0
- package/src/memory/search/semantic.ts +7 -0
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/v2/__tests__/activation.test.ts +77 -95
- package/src/memory/v2/__tests__/injection.test.ts +43 -21
- package/src/memory/v2/__tests__/sim.test.ts +166 -6
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +0 -1
- package/src/memory/v2/activation.ts +69 -88
- package/src/memory/v2/consolidation-job.ts +3 -5
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/injection.ts +86 -53
- package/src/memory/v2/prompts/consolidation.ts +312 -91
- package/src/memory/v2/qdrant.ts +99 -1
- package/src/memory/v2/sim.ts +126 -16
- package/src/memory/v2/skill-qdrant.ts +12 -3
- package/src/memory/v2/skill-store.ts +16 -1
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +6 -5
- package/src/messaging/providers/gmail/types.ts +0 -49
- package/src/messaging/providers/slack/adapter.ts +1 -31
- package/src/messaging/providers/slack/types.ts +0 -32
- package/src/notifications/README.md +10 -10
- package/src/notifications/broadcaster.ts +1 -1
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/oauth/connect-orchestrator.ts +4 -0
- package/src/oauth/credential-token-resolver.ts +1 -3
- package/src/oauth/manual-token-connection.ts +0 -4
- package/src/outbound-proxy/index.ts +1 -37
- package/src/outbound-proxy/logging.ts +1 -1
- package/src/outbound-proxy/policy.ts +6 -5
- package/src/outbound-proxy/router.ts +2 -1
- package/src/permissions/approval-policy.test.ts +6 -275
- package/src/permissions/approval-policy.ts +0 -51
- package/src/permissions/checker.test.ts +0 -1
- package/src/permissions/checker.ts +3 -17
- package/src/permissions/gateway-threshold-reader.ts +2 -0
- package/src/permissions/prompter.ts +34 -1
- package/src/permissions/secret-prompter.ts +6 -2
- package/src/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/system-prompt.ts +3 -18
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/runtime/assistant-event-hub.ts +118 -96
- package/src/runtime/assistant-event.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/middleware.ts +0 -96
- package/src/runtime/auth/route-policy.ts +19 -0
- package/src/runtime/btw-sidechain.ts +2 -3
- package/src/runtime/channel-invite-transport.ts +2 -48
- package/src/runtime/channel-invite-transports/email.ts +1 -1
- package/src/runtime/channel-invite-transports/slack.ts +1 -1
- package/src/runtime/channel-invite-transports/telegram.ts +1 -1
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
- package/src/runtime/channel-invite-types.ts +54 -0
- package/src/runtime/channel-readiness-service.ts +32 -13
- package/src/runtime/http-server.ts +3 -329
- package/src/runtime/http-types.ts +0 -5
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
- package/src/runtime/migrations/migration-transport.ts +7 -7
- package/src/runtime/migrations/vbundle-builder.ts +327 -60
- package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
- package/src/runtime/migrations/vbundle-importer.ts +245 -68
- package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
- package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
- package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
- package/src/runtime/migrations/vbundle-validator.ts +114 -0
- package/src/runtime/pending-interactions.ts +35 -9
- package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
- package/src/runtime/routes/approval-interception-types.ts +13 -0
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
- package/src/runtime/routes/backup-routes.ts +15 -38
- package/src/runtime/routes/btw-routes.ts +14 -37
- package/src/runtime/routes/client-routes.ts +1 -0
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/conversation-query-routes.ts +36 -1
- package/src/runtime/routes/conversation-routes.ts +30 -13
- package/src/runtime/routes/document-pdf-renderer.ts +165 -0
- package/src/runtime/routes/documents-routes.ts +30 -0
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +12 -6
- package/src/runtime/routes/gateway-log-routes.ts +79 -0
- package/src/runtime/routes/guardian-approval-interception.ts +2 -8
- package/src/runtime/routes/heartbeat-routes.ts +103 -38
- package/src/runtime/routes/host-app-control-routes.ts +134 -0
- package/src/runtime/routes/host-bash-routes.ts +36 -6
- package/src/runtime/routes/host-browser-routes.ts +108 -13
- package/src/runtime/routes/host-cu-routes.ts +44 -14
- package/src/runtime/routes/host-file-routes.ts +33 -10
- package/src/runtime/routes/host-transfer-routes.ts +64 -24
- package/src/runtime/routes/http-adapter.ts +1 -0
- package/src/runtime/routes/identity-intro-cache.ts +30 -0
- package/src/runtime/routes/identity-routes.ts +15 -43
- package/src/runtime/routes/inbound-message-handler.ts +1 -9
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +441 -1
- package/src/runtime/routes/migration-routes.ts +96 -0
- package/src/runtime/routes/schedule-routes.ts +7 -0
- package/src/runtime/verification-templates.ts +4 -7
- package/src/schedule/integration-status.ts +66 -2
- package/src/schedule/recurrence-engine.ts +4 -1
- package/src/schedule/retry-backoff.ts +18 -0
- package/src/schedule/retry-policy.ts +82 -0
- package/src/schedule/schedule-recovery.ts +64 -0
- package/src/schedule/schedule-store.ts +106 -2
- package/src/schedule/scheduler-types.ts +25 -0
- package/src/schedule/scheduler.ts +63 -38
- package/src/security/oauth-callback-registry.ts +8 -0
- package/src/sequence/analytics.ts +5 -5
- package/src/sequence/engine.ts +1 -1
- package/src/skills/catalog-files.ts +2 -8
- package/src/skills/include-graph.ts +5 -5
- package/src/skills/remote-skill-policy.ts +5 -5
- package/src/skills/skill-file-provider.ts +1 -1
- package/src/skills/skill-file-types.ts +13 -0
- package/src/skills/skillssh-audit-types.ts +28 -0
- package/src/skills/skillssh-registry.ts +8 -21
- package/src/telemetry/types.ts +2 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
- package/src/tools/apps/executors.ts +56 -69
- package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
- package/src/tools/browser/browser-execution.ts +2 -2
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
- package/src/tools/browser/cdp-client/factory.ts +23 -24
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/computer-use/definitions.ts +42 -20
- package/src/tools/executor.ts +2 -0
- package/src/tools/host-filesystem/edit.ts +26 -0
- package/src/tools/host-filesystem/read.ts +26 -0
- package/src/tools/host-filesystem/transfer.ts +31 -1
- package/src/tools/host-filesystem/write.ts +26 -0
- package/src/tools/host-terminal/host-shell.ts +58 -0
- package/src/tools/schedule/create.ts +6 -0
- package/src/tools/schedule/list.ts +2 -0
- package/src/tools/schedule/update.ts +10 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
- package/src/tools/shared/filesystem/path-policy.ts +25 -1
- package/src/tools/skills/load.ts +0 -32
- package/src/tools/tool-approval-handler.ts +1 -5
- package/src/tools/types.ts +4 -0
- package/src/usage/pricing.ts +1 -1
- package/src/workspace/hatched-date.ts +86 -0
- package/src/workspace/migrations/003-seed-device-id.ts +1 -1
- package/src/workspace/migrations/006-services-config.ts +8 -5
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/utils.ts +21 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
- package/src/__tests__/twilio-rest.test.ts +0 -34
- package/src/backup/__tests__/backup-key.test.ts +0 -152
- package/src/backup/__tests__/backup-worker.test.ts +0 -782
- package/src/backup/__tests__/offsite-writer.test.ts +0 -641
- package/src/backup/__tests__/stream-crypt.test.ts +0 -228
- package/src/backup/backup-key.ts +0 -137
- package/src/backup/backup-worker.ts +0 -472
- package/src/backup/offsite-writer.ts +0 -222
- package/src/backup/stream-crypt.ts +0 -263
- package/src/daemon/message-types/pairing.ts +0 -58
- package/src/outbound-proxy/config.ts +0 -20
- package/src/outbound-proxy/health.ts +0 -18
- package/src/outbound-proxy/types.ts +0 -150
- package/src/runtime/capability-tokens.ts +0 -190
- package/src/signals/mcp-reload.ts +0 -18
|
@@ -34,7 +34,7 @@ import type {
|
|
|
34
34
|
* Twilio. A `<Stream>` media-stream is opened and the daemon transcribes
|
|
35
35
|
* audio server-side via the provider's batch API.
|
|
36
36
|
*/
|
|
37
|
-
|
|
37
|
+
type TelephonyStrategyKind =
|
|
38
38
|
| "conversation-relay-native"
|
|
39
39
|
| "media-stream-custom";
|
|
40
40
|
|
|
@@ -51,7 +51,7 @@ export type TwilioNativeProvider = "Deepgram" | "Google";
|
|
|
51
51
|
* ConversationRelay. Only present when `strategyKind` is
|
|
52
52
|
* `"conversation-relay-native"`.
|
|
53
53
|
*/
|
|
54
|
-
|
|
54
|
+
interface TwilioNativeMapping {
|
|
55
55
|
/** Twilio-native provider name for the TwiML `transcriptionProvider` attribute. */
|
|
56
56
|
readonly provider: TwilioNativeProvider;
|
|
57
57
|
/**
|
|
@@ -69,7 +69,7 @@ export interface TwilioNativeMapping {
|
|
|
69
69
|
* The telephony routing resolver reads these fields from the catalog
|
|
70
70
|
* instead of maintaining its own hardcoded maps.
|
|
71
71
|
*/
|
|
72
|
-
|
|
72
|
+
interface TelephonyRouting {
|
|
73
73
|
/** Which Twilio call-setup strategy this provider uses. */
|
|
74
74
|
readonly strategyKind: TelephonyStrategyKind;
|
|
75
75
|
/**
|
|
@@ -84,10 +84,10 @@ export interface TelephonyRouting {
|
|
|
84
84
|
// ---------------------------------------------------------------------------
|
|
85
85
|
|
|
86
86
|
/** How the provider's credentials are configured by the user. */
|
|
87
|
-
|
|
87
|
+
type SttSetupMode = "api-key" | "cli";
|
|
88
88
|
|
|
89
89
|
/** Guide for obtaining API credentials from a provider. */
|
|
90
|
-
|
|
90
|
+
interface SttCredentialsGuide {
|
|
91
91
|
readonly description: string;
|
|
92
92
|
readonly url: string;
|
|
93
93
|
readonly linkLabel: string;
|
|
@@ -100,7 +100,7 @@ export interface SttCredentialsGuide {
|
|
|
100
100
|
/**
|
|
101
101
|
* Metadata for a single STT provider.
|
|
102
102
|
*/
|
|
103
|
-
|
|
103
|
+
interface SttProviderEntry {
|
|
104
104
|
/** Canonical provider identifier (must match an {@link SttProviderId} variant). */
|
|
105
105
|
readonly id: SttProviderId;
|
|
106
106
|
|
|
@@ -262,8 +262,7 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
|
|
|
262
262
|
subtitle:
|
|
263
263
|
"High-accuracy speech-to-text powered by OpenAI Whisper. Requires an OpenAI API key.",
|
|
264
264
|
setupMode: "api-key",
|
|
265
|
-
setupHint:
|
|
266
|
-
"Enter your OpenAI API key to enable Whisper transcription.",
|
|
265
|
+
setupHint: "Enter your OpenAI API key to enable Whisper transcription.",
|
|
267
266
|
credentialProvider: "openai",
|
|
268
267
|
supportedBoundaries: new Set<SttBoundaryId>([
|
|
269
268
|
"daemon-batch",
|
|
@@ -14,6 +14,31 @@
|
|
|
14
14
|
|
|
15
15
|
import type { HostProxyCapability, InterfaceId } from "../channels/types.js";
|
|
16
16
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Message type → capability inference
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
const HOST_PREFIX_TO_CAPABILITY: Record<string, HostProxyCapability> = {
|
|
23
|
+
host_bash: "host_bash",
|
|
24
|
+
host_file: "host_file",
|
|
25
|
+
host_transfer: "host_file", // transfers piggyback on host_file capability
|
|
26
|
+
host_cu: "host_cu",
|
|
27
|
+
host_browser: "host_browser",
|
|
28
|
+
host_app_control: "host_app_control",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Infer the {@link HostProxyCapability} a message should be targeted at based
|
|
33
|
+
* on its `type` field. Returns `undefined` for message types that are not
|
|
34
|
+
* host-proxy messages (i.e. they should broadcast to all subscribers).
|
|
35
|
+
*/
|
|
36
|
+
export function capabilityForMessageType(
|
|
37
|
+
type: string,
|
|
38
|
+
): HostProxyCapability | undefined {
|
|
39
|
+
const stem = type.replace(/_(request|cancel)$/, "");
|
|
40
|
+
return HOST_PREFIX_TO_CAPABILITY[stem];
|
|
41
|
+
}
|
|
17
42
|
import { emitFeedEvent } from "../home/emit-feed-event.js";
|
|
18
43
|
import { rewriteCommandPreview } from "../home/rewrite-command-preview.js";
|
|
19
44
|
import { redactSecrets } from "../security/secret-scanner.js";
|
|
@@ -22,7 +47,6 @@ import { summarizeToolInput } from "../tools/tool-input-summary.js";
|
|
|
22
47
|
import { getLogger } from "../util/logger.js";
|
|
23
48
|
import type { AssistantEvent } from "./assistant-event.js";
|
|
24
49
|
import { buildAssistantEvent } from "./assistant-event.js";
|
|
25
|
-
import * as pendingInteractions from "./pending-interactions.js";
|
|
26
50
|
|
|
27
51
|
const log = getLogger("assistant-event-hub");
|
|
28
52
|
|
|
@@ -61,6 +85,7 @@ export interface ClientEntry extends BaseSubscriberEntry {
|
|
|
61
85
|
clientId: string;
|
|
62
86
|
interfaceId: InterfaceId;
|
|
63
87
|
capabilities: HostProxyCapability[];
|
|
88
|
+
machineName?: string;
|
|
64
89
|
}
|
|
65
90
|
|
|
66
91
|
export interface ProcessEntry extends BaseSubscriberEntry {
|
|
@@ -216,7 +241,12 @@ export class AssistantEventHub {
|
|
|
216
241
|
* Publish an event to all matching subscribers.
|
|
217
242
|
*
|
|
218
243
|
* Matching rules:
|
|
219
|
-
* - if `
|
|
244
|
+
* - if `targetClientId` is set, deliver only to the subscriber with that
|
|
245
|
+
* clientId, bypassing the conversation-id filter entirely (the web-origin
|
|
246
|
+
* event's conversationId differs from the macOS client's subscribed
|
|
247
|
+
* conversation).
|
|
248
|
+
* - if `filter.conversationId` is set (and `targetClientId` is not), the
|
|
249
|
+
* `event.conversationId` must equal it
|
|
220
250
|
* - if `targetCapability` is set, only subscribers whose capabilities include
|
|
221
251
|
* it receive the event; untargeted events go to all
|
|
222
252
|
*
|
|
@@ -225,7 +255,7 @@ export class AssistantEventHub {
|
|
|
225
255
|
*/
|
|
226
256
|
async publish(
|
|
227
257
|
event: AssistantEvent,
|
|
228
|
-
options?: { targetCapability?: HostProxyCapability },
|
|
258
|
+
options?: { targetCapability?: HostProxyCapability; targetClientId?: string },
|
|
229
259
|
): Promise<void> {
|
|
230
260
|
if (event.conversationId) {
|
|
231
261
|
try {
|
|
@@ -236,29 +266,40 @@ export class AssistantEventHub {
|
|
|
236
266
|
}
|
|
237
267
|
|
|
238
268
|
const targetCapability = options?.targetCapability;
|
|
269
|
+
const targetClientId = options?.targetClientId;
|
|
239
270
|
const snapshot = Array.from(this.subscribers);
|
|
240
271
|
const errors: unknown[] = [];
|
|
241
272
|
|
|
242
273
|
for (const entry of snapshot) {
|
|
243
274
|
if (!entry.active) continue;
|
|
244
275
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
entry.filter.conversationId != null &&
|
|
250
|
-
entry.filter.conversationId !== event.conversationId
|
|
251
|
-
)
|
|
252
|
-
continue;
|
|
253
|
-
|
|
254
|
-
// Capability targeting: targeted events only go to subscribers that
|
|
255
|
-
// declare the required capability.
|
|
256
|
-
if (targetCapability != null) {
|
|
276
|
+
if (targetClientId != null) {
|
|
277
|
+
// Targeted: bypass conversation filter, deliver only to the named client.
|
|
278
|
+
if (entry.type !== "client" || entry.clientId !== targetClientId)
|
|
279
|
+
continue;
|
|
257
280
|
if (
|
|
258
|
-
|
|
281
|
+
targetCapability != null &&
|
|
259
282
|
!entry.capabilities.includes(targetCapability)
|
|
260
283
|
)
|
|
261
284
|
continue;
|
|
285
|
+
} else {
|
|
286
|
+
// Untargeted: existing conversation-scoped + capability logic.
|
|
287
|
+
if (
|
|
288
|
+
event.conversationId != null &&
|
|
289
|
+
entry.filter.conversationId != null &&
|
|
290
|
+
entry.filter.conversationId !== event.conversationId
|
|
291
|
+
)
|
|
292
|
+
continue;
|
|
293
|
+
|
|
294
|
+
// Capability targeting: targeted events only go to subscribers that
|
|
295
|
+
// declare the required capability.
|
|
296
|
+
if (targetCapability != null) {
|
|
297
|
+
if (
|
|
298
|
+
entry.type !== "client" ||
|
|
299
|
+
!entry.capabilities.includes(targetCapability)
|
|
300
|
+
)
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
262
303
|
}
|
|
263
304
|
|
|
264
305
|
try {
|
|
@@ -276,6 +317,18 @@ export class AssistantEventHub {
|
|
|
276
317
|
}
|
|
277
318
|
}
|
|
278
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Return the active client subscriber with the given clientId, or
|
|
322
|
+
* `undefined` if no such subscriber exists.
|
|
323
|
+
*/
|
|
324
|
+
getClientById(clientId: string): ClientEntry | undefined {
|
|
325
|
+
for (const entry of this.subscribers) {
|
|
326
|
+
if (entry.active && entry.type === "client" && entry.clientId === clientId)
|
|
327
|
+
return entry;
|
|
328
|
+
}
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
|
|
279
332
|
/**
|
|
280
333
|
* Returns true when at least one active subscriber would receive the given
|
|
281
334
|
* event based on the same conversation matching rules as publish().
|
|
@@ -338,6 +391,35 @@ export class AssistantEventHub {
|
|
|
338
391
|
return this.listClientsByCapability(capability)[0];
|
|
339
392
|
}
|
|
340
393
|
|
|
394
|
+
/**
|
|
395
|
+
* Return the best client for the given capability using an explicit
|
|
396
|
+
* interface preference order. Among clients that support `capability`,
|
|
397
|
+
* the one whose `interfaceId` appears earliest in `interfacePreference`
|
|
398
|
+
* wins. Within the same interface tier, `lastActiveAt` is the tiebreaker
|
|
399
|
+
* (most recent first). Clients not in the preference list are considered last.
|
|
400
|
+
*
|
|
401
|
+
* Used by {@link HostBrowserProxy} to prefer the Chrome Extension
|
|
402
|
+
* (`chrome-extension`) over the macOS SSE bridge (`macos`) when both are
|
|
403
|
+
* connected, so `chrome.debugger` is used ahead of the localhost:9222 path.
|
|
404
|
+
*/
|
|
405
|
+
getPreferredClientByCapability(
|
|
406
|
+
capability: HostProxyCapability,
|
|
407
|
+
interfacePreference: InterfaceId[],
|
|
408
|
+
): ClientEntry | undefined {
|
|
409
|
+
const clients = this.listClientsByCapability(capability);
|
|
410
|
+
if (clients.length === 0) return undefined;
|
|
411
|
+
// listClientsByCapability returns clients sorted by lastActiveAt desc
|
|
412
|
+
// (most recent first). A stable sort by preference index preserves that
|
|
413
|
+
// ordering within each interface tier.
|
|
414
|
+
return clients.sort((a, b) => {
|
|
415
|
+
const ai = interfacePreference.indexOf(a.interfaceId);
|
|
416
|
+
const bi = interfacePreference.indexOf(b.interfaceId);
|
|
417
|
+
const ea = ai === -1 ? interfacePreference.length : ai;
|
|
418
|
+
const eb = bi === -1 ? interfacePreference.length : bi;
|
|
419
|
+
return ea - eb;
|
|
420
|
+
})[0];
|
|
421
|
+
}
|
|
422
|
+
|
|
341
423
|
/**
|
|
342
424
|
* Return all client subscribers with the given interface type,
|
|
343
425
|
* sorted by `lastActiveAt` descending.
|
|
@@ -372,10 +454,7 @@ export class AssistantEventHub {
|
|
|
372
454
|
disposeClient(clientId: string): number {
|
|
373
455
|
const targets: SubscriberEntry[] = [];
|
|
374
456
|
for (const entry of this.subscribers) {
|
|
375
|
-
if (
|
|
376
|
-
entry.type === "client" &&
|
|
377
|
-
entry.clientId === clientId
|
|
378
|
-
) {
|
|
457
|
+
if (entry.type === "client" && entry.clientId === clientId) {
|
|
379
458
|
targets.push(entry);
|
|
380
459
|
}
|
|
381
460
|
}
|
|
@@ -432,25 +511,27 @@ let _hubChain = Promise.resolve();
|
|
|
432
511
|
* When `conversationId` is omitted, it is auto-extracted from the message
|
|
433
512
|
* payload (if present).
|
|
434
513
|
*
|
|
514
|
+
* Target capability is inferred automatically from the message type — callers
|
|
515
|
+
* never need to specify it. Host-proxy messages (`host_bash_*`,
|
|
516
|
+
* `host_file_*`, `host_transfer_*`, `host_cu_*`, `host_browser_*`) are routed
|
|
517
|
+
* only to subscribers that declare the matching capability; all other messages
|
|
518
|
+
* broadcast to every subscriber.
|
|
519
|
+
*
|
|
435
520
|
* This is the primary entrypoint for emitting events — handlers, routes, and
|
|
436
521
|
* services should call this directly instead of threading a broadcast callback.
|
|
437
522
|
*/
|
|
438
523
|
export function broadcastMessage(
|
|
439
524
|
msg: ServerMessage,
|
|
440
525
|
conversationId?: string,
|
|
441
|
-
options?: {
|
|
526
|
+
options?: { targetClientId?: string },
|
|
442
527
|
): void {
|
|
443
528
|
const resolvedConversationId = conversationId ?? extractConversationId(msg);
|
|
529
|
+
const targetClientId = options?.targetClientId;
|
|
444
530
|
|
|
445
|
-
//
|
|
446
|
-
// regardless of which path triggered the broadcast.
|
|
447
|
-
if (resolvedConversationId) {
|
|
448
|
-
registerPendingInteraction(msg, resolvedConversationId);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// Emit feed events for confirmation requests (tool approval prompts).
|
|
531
|
+
// Confirmation-request side effects: feed event + canonical guardian request.
|
|
452
532
|
if (msg.type === "confirmation_request" && resolvedConversationId) {
|
|
453
533
|
void emitConfirmationFeedEvent(msg, resolvedConversationId);
|
|
534
|
+
void createCanonicalRequestForConfirmation(msg, resolvedConversationId);
|
|
454
535
|
}
|
|
455
536
|
|
|
456
537
|
// `conversation_list_invalidated` is a list-level system event — publish
|
|
@@ -460,8 +541,13 @@ export function broadcastMessage(
|
|
|
460
541
|
? undefined
|
|
461
542
|
: resolvedConversationId;
|
|
462
543
|
const event = buildAssistantEvent(msg, scopedConversationId);
|
|
544
|
+
const targetCapability = capabilityForMessageType(msg.type);
|
|
545
|
+
const publishOptions =
|
|
546
|
+
targetCapability != null || targetClientId != null
|
|
547
|
+
? { targetCapability, targetClientId }
|
|
548
|
+
: undefined;
|
|
463
549
|
_hubChain = _hubChain
|
|
464
|
-
.then(() => assistantEventHub.publish(event,
|
|
550
|
+
.then(() => assistantEventHub.publish(event, publishOptions))
|
|
465
551
|
.then(() => {
|
|
466
552
|
// When a conversation title changes, also broadcast an unscoped
|
|
467
553
|
// `conversation_list_invalidated` so every connected client's sidebar
|
|
@@ -495,7 +581,7 @@ function extractConversationId(msg: ServerMessage): string | undefined {
|
|
|
495
581
|
return undefined;
|
|
496
582
|
}
|
|
497
583
|
|
|
498
|
-
// ──
|
|
584
|
+
// ── Canonical guardian request ────────────────────────────────────────────────
|
|
499
585
|
|
|
500
586
|
function resolveCanonicalRequestSourceType(
|
|
501
587
|
sourceChannel: string,
|
|
@@ -505,74 +591,10 @@ function resolveCanonicalRequestSourceType(
|
|
|
505
591
|
return "channel";
|
|
506
592
|
}
|
|
507
593
|
|
|
508
|
-
/**
|
|
509
|
-
* Register pending interactions for request-type messages so approval and
|
|
510
|
-
* host prompts are tracked regardless of which code path broadcasts them.
|
|
511
|
-
*
|
|
512
|
-
* Heavy dependencies (conversation-store, canonical-guardian-store, etc.) are
|
|
513
|
-
* imported lazily so that loading this module during tests doesn't trigger
|
|
514
|
-
* config/data-dir side effects.
|
|
515
|
-
*/
|
|
516
|
-
function registerPendingInteraction(
|
|
517
|
-
msg: ServerMessage,
|
|
518
|
-
conversationId: string,
|
|
519
|
-
): void {
|
|
520
|
-
if (msg.type === "confirmation_request") {
|
|
521
|
-
pendingInteractions.register(msg.requestId, {
|
|
522
|
-
conversationId,
|
|
523
|
-
kind: "confirmation",
|
|
524
|
-
confirmationDetails: {
|
|
525
|
-
toolName: msg.toolName,
|
|
526
|
-
input: msg.input,
|
|
527
|
-
riskLevel: msg.riskLevel,
|
|
528
|
-
executionTarget: msg.executionTarget,
|
|
529
|
-
allowlistOptions: msg.allowlistOptions,
|
|
530
|
-
scopeOptions: msg.scopeOptions,
|
|
531
|
-
persistentDecisionsAllowed: msg.persistentDecisionsAllowed,
|
|
532
|
-
},
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
// Create canonical guardian request asynchronously — heavy deps are
|
|
536
|
-
// imported lazily to avoid pulling in conversation-store (and
|
|
537
|
-
// transitively config/loader → ensureDataDir) at module-load time.
|
|
538
|
-
void createCanonicalRequestForConfirmation(msg, conversationId);
|
|
539
|
-
} else if (msg.type === "secret_request") {
|
|
540
|
-
pendingInteractions.register(msg.requestId, {
|
|
541
|
-
conversationId,
|
|
542
|
-
kind: "secret",
|
|
543
|
-
});
|
|
544
|
-
} else if (msg.type === "host_bash_request") {
|
|
545
|
-
pendingInteractions.register(msg.requestId, {
|
|
546
|
-
conversationId,
|
|
547
|
-
kind: "host_bash",
|
|
548
|
-
});
|
|
549
|
-
} else if (msg.type === "host_browser_request") {
|
|
550
|
-
pendingInteractions.register(msg.requestId, {
|
|
551
|
-
conversationId,
|
|
552
|
-
kind: "host_browser",
|
|
553
|
-
});
|
|
554
|
-
} else if (msg.type === "host_file_request") {
|
|
555
|
-
pendingInteractions.register(msg.requestId, {
|
|
556
|
-
conversationId,
|
|
557
|
-
kind: "host_file",
|
|
558
|
-
});
|
|
559
|
-
} else if (msg.type === "host_cu_request") {
|
|
560
|
-
pendingInteractions.register(msg.requestId, {
|
|
561
|
-
conversationId,
|
|
562
|
-
kind: "host_cu",
|
|
563
|
-
});
|
|
564
|
-
} else if (msg.type === "host_transfer_request") {
|
|
565
|
-
pendingInteractions.register(msg.requestId, {
|
|
566
|
-
conversationId,
|
|
567
|
-
kind: "host_transfer",
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
594
|
/**
|
|
573
595
|
* Lazily load heavy dependencies and create a canonical guardian request +
|
|
574
|
-
* bridge for a confirmation_request message.
|
|
575
|
-
*
|
|
596
|
+
* bridge for a confirmation_request message. Called fire-and-forget from
|
|
597
|
+
* broadcastMessage.
|
|
576
598
|
*/
|
|
577
599
|
async function createCanonicalRequestForConfirmation(
|
|
578
600
|
msg: ServerMessage & { type: "confirmation_request" },
|
|
@@ -16,6 +16,7 @@ import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
|
16
16
|
export {
|
|
17
17
|
formatSseFrame,
|
|
18
18
|
formatSseHeartbeat,
|
|
19
|
+
formatSseHeartbeatWithData,
|
|
19
20
|
} from "@vellumai/skill-host-contracts";
|
|
20
21
|
|
|
21
22
|
/** Daemon-side specialization of the generic event envelope. */
|
|
@@ -35,12 +35,6 @@ mock.module("../../../config/env.js", () => ({
|
|
|
35
35
|
|
|
36
36
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../assistant-scope.js";
|
|
37
37
|
import {
|
|
38
|
-
mintHostBrowserCapability,
|
|
39
|
-
resetCapabilityTokenSecretForTests,
|
|
40
|
-
setCapabilityTokenSecretForTests,
|
|
41
|
-
} from "../../capability-tokens.js";
|
|
42
|
-
import {
|
|
43
|
-
authenticateHostBrowserResultRequest,
|
|
44
38
|
authenticateRequest,
|
|
45
39
|
} from "../middleware.js";
|
|
46
40
|
import { initAuthSigningKey, mintToken } from "../token-service.js";
|
|
@@ -272,55 +266,20 @@ describe("authenticateRequest", () => {
|
|
|
272
266
|
});
|
|
273
267
|
|
|
274
268
|
// ---------------------------------------------------------------------------
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
//
|
|
278
|
-
// JWT path and emits a 401 like any other invalid token.
|
|
269
|
+
// /v1/host-browser-result auth — exercises authenticateRequest with the
|
|
270
|
+
// same request shape the chrome extension sends. Validates that standard
|
|
271
|
+
// JWT auth applies after the capability-token system was removed.
|
|
279
272
|
// ---------------------------------------------------------------------------
|
|
280
273
|
|
|
281
|
-
describe("
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
beforeEach(() => {
|
|
285
|
-
// Pin the capability-token HMAC secret so mint/verify agree across
|
|
286
|
-
// the test run. The module-level secret cache is reset between
|
|
287
|
-
// tests so dev-bypass flipping doesn't leak stale state.
|
|
288
|
-
setCapabilityTokenSecretForTests(CAPABILITY_SECRET);
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
afterAll(() => {
|
|
292
|
-
resetCapabilityTokenSecretForTests();
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
test("accepts a valid capability token and synthesizes an actor AuthContext", async () => {
|
|
296
|
-
const { token } = mintHostBrowserCapability("guardian-cap-happy");
|
|
297
|
-
const req = new Request("http://localhost/v1/host-browser-result", {
|
|
298
|
-
method: "POST",
|
|
299
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
const result = await authenticateHostBrowserResultRequest(req);
|
|
303
|
-
expect(result.ok).toBe(true);
|
|
304
|
-
if (result.ok) {
|
|
305
|
-
expect(result.context.principalType).toBe("actor");
|
|
306
|
-
expect(result.context.assistantId).toBe(DAEMON_INTERNAL_ASSISTANT_ID);
|
|
307
|
-
expect(result.context.actorPrincipalId).toBe("guardian-cap-happy");
|
|
308
|
-
expect(result.context.scopeProfile).toBe("actor_client_v1");
|
|
309
|
-
// The synthetic context must carry the scopes the route policy
|
|
310
|
-
// requires — otherwise the router would 403 the POST even though
|
|
311
|
-
// auth succeeded.
|
|
312
|
-
expect(result.context.scopes.has("approval.write")).toBe(true);
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
test("accepts a valid daemon-audience JWT (regression for the legacy path)", async () => {
|
|
274
|
+
describe("authenticateRequest for /v1/host-browser-result", () => {
|
|
275
|
+
test("accepts a valid daemon-audience JWT", async () => {
|
|
317
276
|
const token = mintValidToken({ sub: "actor:self:jwt-principal" });
|
|
318
277
|
const req = new Request("http://localhost/v1/host-browser-result", {
|
|
319
278
|
method: "POST",
|
|
320
279
|
headers: { Authorization: `Bearer ${token}` },
|
|
321
280
|
});
|
|
322
281
|
|
|
323
|
-
const result = await
|
|
282
|
+
const result = await authenticateRequest(req);
|
|
324
283
|
expect(result.ok).toBe(true);
|
|
325
284
|
if (result.ok) {
|
|
326
285
|
expect(result.context.principalType).toBe("actor");
|
|
@@ -334,25 +293,21 @@ describe("authenticateHostBrowserResultRequest", () => {
|
|
|
334
293
|
method: "POST",
|
|
335
294
|
});
|
|
336
295
|
|
|
337
|
-
const result = await
|
|
296
|
+
const result = await authenticateRequest(req);
|
|
338
297
|
expect(result.ok).toBe(false);
|
|
339
298
|
if (!result.ok) {
|
|
340
299
|
expect(result.response.status).toBe(401);
|
|
341
300
|
}
|
|
342
301
|
});
|
|
343
302
|
|
|
344
|
-
test("malformed bearer
|
|
345
|
-
// A bearer that is
|
|
346
|
-
// parseable JWT must fail the JWT path and return 401. This is the
|
|
347
|
-
// primary regression guard against someone accidentally making the
|
|
348
|
-
// capability-token branch "allow-anything" by swallowing
|
|
349
|
-
// verification failures.
|
|
303
|
+
test("malformed bearer returns 401", async () => {
|
|
304
|
+
// A bearer that is not a parseable JWT must return 401.
|
|
350
305
|
const req = new Request("http://localhost/v1/host-browser-result", {
|
|
351
306
|
method: "POST",
|
|
352
307
|
headers: { Authorization: "Bearer not-a-token.xxxxxxxxxxxxx" },
|
|
353
308
|
});
|
|
354
309
|
|
|
355
|
-
const result = await
|
|
310
|
+
const result = await authenticateRequest(req);
|
|
356
311
|
expect(result.ok).toBe(false);
|
|
357
312
|
if (!result.ok) {
|
|
358
313
|
expect(result.response.status).toBe(401);
|
|
@@ -366,7 +321,7 @@ describe("authenticateHostBrowserResultRequest", () => {
|
|
|
366
321
|
method: "POST",
|
|
367
322
|
});
|
|
368
323
|
|
|
369
|
-
const result = await
|
|
324
|
+
const result = await authenticateRequest(req);
|
|
370
325
|
expect(result.ok).toBe(true);
|
|
371
326
|
if (result.ok) {
|
|
372
327
|
// Same synthetic context shape as authenticateRequest's dev
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
import { isHttpAuthDisabled } from "../../config/env.js";
|
|
26
26
|
import { getLogger } from "../../util/logger.js";
|
|
27
27
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
28
|
-
import { verifyHostBrowserCapability } from "../capability-tokens.js";
|
|
29
28
|
import { extractBearerToken } from "../middleware/auth.js";
|
|
30
29
|
import { buildAuthContext } from "./context.js";
|
|
31
30
|
import { resolveScopeProfile } from "./scopes.js";
|
|
@@ -188,99 +187,4 @@ export function authenticateRequest(req: Request): AuthenticateResult {
|
|
|
188
187
|
return { ok: true, context: contextResult.context };
|
|
189
188
|
}
|
|
190
189
|
|
|
191
|
-
// ---------------------------------------------------------------------------
|
|
192
|
-
// Capability-token-aware auth for /v1/host-browser-result
|
|
193
|
-
// ---------------------------------------------------------------------------
|
|
194
190
|
|
|
195
|
-
/**
|
|
196
|
-
* Build a synthetic AuthContext from a verified host_browser capability
|
|
197
|
-
* claim. The resulting context is shaped to look like an
|
|
198
|
-
* `actor_client_v1` actor so downstream route policy (which requires
|
|
199
|
-
* `approval.write`) and `requireBoundGuardian` (which compares
|
|
200
|
-
* `actorPrincipalId` against the bound guardian) both accept it.
|
|
201
|
-
*
|
|
202
|
-
* The capability token already carries its own HMAC-checked expiry, so
|
|
203
|
-
* there is no policy-epoch gate to apply here — we pin `policyEpoch` to
|
|
204
|
-
* `Number.MAX_SAFE_INTEGER` the same way the dev-bypass context does.
|
|
205
|
-
*/
|
|
206
|
-
function buildCapabilityAuthContext(guardianId: string): AuthContext {
|
|
207
|
-
return {
|
|
208
|
-
subject: `actor:${DAEMON_INTERNAL_ASSISTANT_ID}:${guardianId}`,
|
|
209
|
-
principalType: "actor",
|
|
210
|
-
assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
211
|
-
actorPrincipalId: guardianId,
|
|
212
|
-
scopeProfile: "actor_client_v1",
|
|
213
|
-
scopes: resolveScopeProfile("actor_client_v1"),
|
|
214
|
-
policyEpoch: Number.MAX_SAFE_INTEGER,
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Authenticate a request that is allowed to present either a JWT or a
|
|
220
|
-
* host_browser capability token. This is the auth entry point for
|
|
221
|
-
* `/v1/host-browser-result` POST specifically — the chrome extension
|
|
222
|
-
* stores a capability token (minted by the
|
|
223
|
-
* `/v1/browser-extension-pair` flow) rather than a daemon JWT, so the
|
|
224
|
-
* POST fallback used when the `/v1/browser-relay` WebSocket is
|
|
225
|
-
* unavailable would otherwise 401 through the JWT-only
|
|
226
|
-
* `authenticateRequest` path.
|
|
227
|
-
*
|
|
228
|
-
* Order of operations (mirrors `handleBrowserRelayUpgrade`):
|
|
229
|
-
* 1. Extract the bearer token. Missing header → 401.
|
|
230
|
-
* 2. Try `verifyHostBrowserCapability(token)` first. If it succeeds,
|
|
231
|
-
* derive `guardianId` from the capability claims and synthesize an
|
|
232
|
-
* AuthContext.
|
|
233
|
-
* 3. Otherwise fall through to the standard JWT path so daemon-minted
|
|
234
|
-
* JWTs (gateway-proxied or direct) continue to work as a
|
|
235
|
-
* regression-safe compatibility path.
|
|
236
|
-
*
|
|
237
|
-
* Dev bypass (`isHttpAuthDisabled()`) is honored the same way as
|
|
238
|
-
* `authenticateRequest` — we delegate to it directly to pick up the
|
|
239
|
-
* shared synthetic dev-bypass context.
|
|
240
|
-
*/
|
|
241
|
-
export async function authenticateHostBrowserResultRequest(
|
|
242
|
-
req: Request,
|
|
243
|
-
): Promise<AuthenticateResult> {
|
|
244
|
-
if (isHttpAuthDisabled()) {
|
|
245
|
-
return { ok: true, context: buildDevBypassContext() };
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const rawToken = extractBearerToken(req);
|
|
249
|
-
if (!rawToken) {
|
|
250
|
-
log.warn(
|
|
251
|
-
{ reason: "missing_token", path: "/v1/host-browser-result" },
|
|
252
|
-
"Host browser result auth denied: missing Authorization header",
|
|
253
|
-
);
|
|
254
|
-
return {
|
|
255
|
-
ok: false,
|
|
256
|
-
response: Response.json(
|
|
257
|
-
{
|
|
258
|
-
error: {
|
|
259
|
-
code: "UNAUTHORIZED",
|
|
260
|
-
message: "Missing Authorization header",
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
{ status: 401 },
|
|
264
|
-
),
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// 1) Capability-token path (self-hosted default). The chrome
|
|
269
|
-
// extension presents the token it received from the native
|
|
270
|
-
// messaging pair flow. We derive `actorPrincipalId` from the
|
|
271
|
-
// capability claims directly — the claims are HMAC-signed by the
|
|
272
|
-
// same daemon so there is no cross-tenant risk.
|
|
273
|
-
const capabilityClaims = await verifyHostBrowserCapability(rawToken);
|
|
274
|
-
if (capabilityClaims) {
|
|
275
|
-
return {
|
|
276
|
-
ok: true,
|
|
277
|
-
context: buildCapabilityAuthContext(capabilityClaims.guardianId),
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// 2) JWT compatibility path. Fall back to the existing daemon/gateway
|
|
282
|
-
// JWT verification so cloud callers and any legacy self-hosted
|
|
283
|
-
// clients still holding a daemon JWT continue to work. Any 401
|
|
284
|
-
// emitted here already includes the JWT-specific reason.
|
|
285
|
-
return authenticateRequest(req);
|
|
286
|
-
}
|
|
@@ -151,8 +151,11 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
151
151
|
{ endpoint: "confirm", scopes: ["approval.write"] },
|
|
152
152
|
{ endpoint: "secret", scopes: ["approval.write"] },
|
|
153
153
|
{ endpoint: "trust-rules", scopes: ["approval.write"] },
|
|
154
|
+
{ endpoint: "host-app-control-result", scopes: ["approval.write"] },
|
|
154
155
|
{ endpoint: "host-bash-result", scopes: ["approval.write"] },
|
|
155
156
|
{ endpoint: "host-browser-result", scopes: ["approval.write"] },
|
|
157
|
+
{ endpoint: "host-browser-event", scopes: ["approval.write"] },
|
|
158
|
+
{ endpoint: "host-browser-session-invalidated", scopes: ["approval.write"] },
|
|
156
159
|
{ endpoint: "host-cu-result", scopes: ["approval.write"] },
|
|
157
160
|
{ endpoint: "host-file-result", scopes: ["approval.write"] },
|
|
158
161
|
{ endpoint: "host-transfer-result", scopes: ["approval.write"] },
|
|
@@ -204,6 +207,8 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
204
207
|
{ endpoint: "contacts/invites:POST", scopes: ["settings.write"] },
|
|
205
208
|
{ endpoint: "contacts/invites/redeem", scopes: ["settings.write"] },
|
|
206
209
|
{ endpoint: "contacts/invites:DELETE", scopes: ["settings.write"] },
|
|
210
|
+
{ endpoint: "contacts/prompt:POST", scopes: ["settings.write"] },
|
|
211
|
+
{ endpoint: "resolve_contact_prompt:POST", scopes: ["settings.write"] },
|
|
207
212
|
{ endpoint: "integrations/telegram/config", scopes: ["settings.read"] },
|
|
208
213
|
{ endpoint: "integrations/telegram/config:POST", scopes: ["settings.write"] },
|
|
209
214
|
{
|
|
@@ -422,7 +427,15 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
422
427
|
{ endpoint: "memory-items:DELETE", scopes: ["settings.write"] },
|
|
423
428
|
{ endpoint: "memory/v2/backfill:POST", scopes: ["settings.write"] },
|
|
424
429
|
{ endpoint: "memory/v2/validate:POST", scopes: ["settings.read"] },
|
|
430
|
+
{ endpoint: "memory/v2/concept-page:POST", scopes: ["settings.read"] },
|
|
425
431
|
{ endpoint: "memory/v2/reembed-skills:POST", scopes: ["settings.write"] },
|
|
432
|
+
{ endpoint: "memory/v2/explain-similarity:POST", scopes: ["settings.read"] },
|
|
433
|
+
{ endpoint: "memory/v2/fit-anisotropy:POST", scopes: ["settings.write"] },
|
|
434
|
+
{
|
|
435
|
+
endpoint: "memory/v2/rebuild-corpus-stats:POST",
|
|
436
|
+
scopes: ["settings.write"],
|
|
437
|
+
},
|
|
438
|
+
{ endpoint: "memory/v2/fit-anisotropy:POST", scopes: ["settings.write"] },
|
|
426
439
|
|
|
427
440
|
// Trust rule listing
|
|
428
441
|
{ endpoint: "trust-rules/manage:GET", scopes: ["settings.read"] },
|
|
@@ -490,6 +503,9 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
490
503
|
{ endpoint: "consolidation", scopes: ["settings.read"] },
|
|
491
504
|
{ endpoint: "consolidation:POST", scopes: ["settings.write"] },
|
|
492
505
|
|
|
506
|
+
// Gateway log proxy
|
|
507
|
+
{ endpoint: "gateway/logs/tail", scopes: ["settings.read"] },
|
|
508
|
+
|
|
493
509
|
// Heartbeat (config, runs, checklist — all share the "heartbeat" policyKey)
|
|
494
510
|
{ endpoint: "heartbeat:GET", scopes: ["settings.read"] },
|
|
495
511
|
{ endpoint: "heartbeat", scopes: ["settings.write"] },
|
|
@@ -563,6 +579,9 @@ const INTERNAL_ENDPOINTS = [
|
|
|
563
579
|
"internal/twilio/status",
|
|
564
580
|
"internal/twilio/connect-action",
|
|
565
581
|
"internal/oauth/callback",
|
|
582
|
+
"internal/mcp/auth/start",
|
|
583
|
+
"internal/mcp/auth/status",
|
|
584
|
+
"internal/mcp/reload", // ← new
|
|
566
585
|
];
|
|
567
586
|
for (const endpoint of INTERNAL_ENDPOINTS) {
|
|
568
587
|
registerPolicy(endpoint, {
|