@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
|
@@ -213,6 +213,7 @@ function makeSendMessageDeps() {
|
|
|
213
213
|
hasPendingConfirmation: () => false,
|
|
214
214
|
setHostBrowserProxy: () => {},
|
|
215
215
|
setHostCuProxy: () => {},
|
|
216
|
+
setHostAppControlProxy: () => {},
|
|
216
217
|
addPreactivatedSkillId: () => {},
|
|
217
218
|
} as unknown as import("../daemon/conversation.js").Conversation;
|
|
218
219
|
|
|
@@ -160,6 +160,7 @@ function makeCompletingConversation(): Conversation {
|
|
|
160
160
|
updateClient: () => {},
|
|
161
161
|
setHostBrowserProxy: () => {},
|
|
162
162
|
setHostCuProxy: () => {},
|
|
163
|
+
setHostAppControlProxy: () => {},
|
|
163
164
|
addPreactivatedSkillId: () => {},
|
|
164
165
|
hasAnyPendingConfirmation: () => false,
|
|
165
166
|
hasPendingConfirmation: () => false,
|
|
@@ -216,6 +217,7 @@ function makeHangingConversation(): Conversation {
|
|
|
216
217
|
updateClient: () => {},
|
|
217
218
|
setHostBrowserProxy: () => {},
|
|
218
219
|
setHostCuProxy: () => {},
|
|
220
|
+
setHostAppControlProxy: () => {},
|
|
219
221
|
addPreactivatedSkillId: () => {},
|
|
220
222
|
hasAnyPendingConfirmation: () => false,
|
|
221
223
|
hasPendingConfirmation: () => false,
|
|
@@ -300,6 +302,7 @@ function makePendingApprovalConversation(
|
|
|
300
302
|
updateClient: () => {},
|
|
301
303
|
setHostBrowserProxy: () => {},
|
|
302
304
|
setHostCuProxy: () => {},
|
|
305
|
+
setHostAppControlProxy: () => {},
|
|
303
306
|
addPreactivatedSkillId: () => {},
|
|
304
307
|
hasAnyPendingConfirmation: () => pending.size > 0,
|
|
305
308
|
hasPendingConfirmation: (candidateRequestId: string) =>
|
|
@@ -45,7 +45,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
45
45
|
getConfig: () => mockConfig,
|
|
46
46
|
loadConfig: () => mockConfig,
|
|
47
47
|
invalidateConfigCache: () => {},
|
|
48
|
-
saveConfig: () => {},
|
|
49
48
|
loadRawConfig: () => ({}),
|
|
50
49
|
saveRawConfig: () => {},
|
|
51
50
|
getNestedValue: () => undefined,
|
|
@@ -16,10 +16,11 @@ afterEach(() => {
|
|
|
16
16
|
_setOverridesForTesting({});
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
const DECLARED_FLAG_ID = "
|
|
19
|
+
const DECLARED_FLAG_ID = "email-channel";
|
|
20
20
|
const DECLARED_FLAG_KEY = DECLARED_FLAG_ID;
|
|
21
|
-
const DECLARED_SKILL_ID = "
|
|
22
|
-
const
|
|
21
|
+
const DECLARED_SKILL_ID = "email-channel";
|
|
22
|
+
const ENABLED_UNDECLARED_FLAG_KEY = "enabled-undeclared-flag";
|
|
23
|
+
const ENABLED_UNDECLARED_SKILL_ID = "enabled-undeclared-skill";
|
|
23
24
|
// ---------------------------------------------------------------------------
|
|
24
25
|
// Helpers
|
|
25
26
|
// ---------------------------------------------------------------------------
|
|
@@ -91,14 +92,14 @@ describe("skillFlagKey", () => {
|
|
|
91
92
|
// ---------------------------------------------------------------------------
|
|
92
93
|
|
|
93
94
|
describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
|
|
94
|
-
test("returns
|
|
95
|
+
test("returns false when no flag overrides (registry default is false)", () => {
|
|
95
96
|
const config = makeConfig();
|
|
96
97
|
expect(
|
|
97
98
|
isAssistantFeatureFlagEnabled(
|
|
98
99
|
skillFlagKey({ featureFlag: DECLARED_FLAG_ID })!,
|
|
99
100
|
config,
|
|
100
101
|
),
|
|
101
|
-
).toBe(
|
|
102
|
+
).toBe(false);
|
|
102
103
|
});
|
|
103
104
|
|
|
104
105
|
test("returns true when skill key is explicitly true", () => {
|
|
@@ -144,27 +145,18 @@ describe("isAssistantFeatureFlagEnabled", () => {
|
|
|
144
145
|
|
|
145
146
|
test("falls back to registry default when no override", () => {
|
|
146
147
|
const config = makeConfig();
|
|
147
|
-
//
|
|
148
|
-
expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(
|
|
148
|
+
// email-channel defaults to false in the registry
|
|
149
|
+
expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(
|
|
150
|
+
false,
|
|
151
|
+
);
|
|
149
152
|
});
|
|
150
153
|
|
|
151
154
|
test("respects persisted overrides for undeclared keys", () => {
|
|
152
|
-
_setOverridesForTesting({
|
|
153
|
-
const config = makeConfig();
|
|
154
|
-
expect(isAssistantFeatureFlagEnabled("browser", config)).toBe(false);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
test("declared keys with no persisted override use registry default", () => {
|
|
158
|
-
const config = makeConfig();
|
|
159
|
-
// browser is declared in the registry with defaultEnabled: true
|
|
160
|
-
expect(isAssistantFeatureFlagEnabled("browser", config)).toBe(true);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
test("app-builder-multifile defaults to enabled when no override is set", () => {
|
|
155
|
+
_setOverridesForTesting({ "some-undeclared-flag": false });
|
|
164
156
|
const config = makeConfig();
|
|
165
|
-
expect(
|
|
166
|
-
|
|
167
|
-
)
|
|
157
|
+
expect(isAssistantFeatureFlagEnabled("some-undeclared-flag", config)).toBe(
|
|
158
|
+
false,
|
|
159
|
+
);
|
|
168
160
|
});
|
|
169
161
|
});
|
|
170
162
|
|
|
@@ -176,11 +168,15 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
176
168
|
test("flag OFF skill does not appear in resolved list", () => {
|
|
177
169
|
_setOverridesForTesting({
|
|
178
170
|
[DECLARED_FLAG_KEY]: false,
|
|
179
|
-
|
|
171
|
+
[ENABLED_UNDECLARED_FLAG_KEY]: true,
|
|
180
172
|
});
|
|
181
173
|
const catalog = [
|
|
182
174
|
makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID),
|
|
183
|
-
makeSkill(
|
|
175
|
+
makeSkill(
|
|
176
|
+
ENABLED_UNDECLARED_SKILL_ID,
|
|
177
|
+
"bundled",
|
|
178
|
+
ENABLED_UNDECLARED_FLAG_KEY,
|
|
179
|
+
),
|
|
184
180
|
];
|
|
185
181
|
const config = makeConfig();
|
|
186
182
|
|
|
@@ -188,17 +184,21 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
188
184
|
const ids = resolved.map((r) => r.summary.id);
|
|
189
185
|
|
|
190
186
|
expect(ids).not.toContain(DECLARED_SKILL_ID);
|
|
191
|
-
expect(ids).toContain(
|
|
187
|
+
expect(ids).toContain(ENABLED_UNDECLARED_SKILL_ID);
|
|
192
188
|
});
|
|
193
189
|
|
|
194
190
|
test("flag ON skill appears normally", () => {
|
|
195
191
|
_setOverridesForTesting({
|
|
196
192
|
[DECLARED_FLAG_KEY]: true,
|
|
197
|
-
|
|
193
|
+
[ENABLED_UNDECLARED_FLAG_KEY]: true,
|
|
198
194
|
});
|
|
199
195
|
const catalog = [
|
|
200
196
|
makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID),
|
|
201
|
-
makeSkill(
|
|
197
|
+
makeSkill(
|
|
198
|
+
ENABLED_UNDECLARED_SKILL_ID,
|
|
199
|
+
"bundled",
|
|
200
|
+
ENABLED_UNDECLARED_FLAG_KEY,
|
|
201
|
+
),
|
|
202
202
|
];
|
|
203
203
|
const config = makeConfig();
|
|
204
204
|
|
|
@@ -206,17 +206,16 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
206
206
|
const ids = resolved.map((r) => r.summary.id);
|
|
207
207
|
|
|
208
208
|
expect(ids).toContain(DECLARED_SKILL_ID);
|
|
209
|
-
expect(ids).toContain(
|
|
209
|
+
expect(ids).toContain(ENABLED_UNDECLARED_SKILL_ID);
|
|
210
210
|
});
|
|
211
211
|
|
|
212
|
-
test("declared flag key defaults to registry value (
|
|
212
|
+
test("declared flag key defaults to registry value (false)", () => {
|
|
213
213
|
const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
|
|
214
214
|
const config = makeConfig();
|
|
215
215
|
|
|
216
216
|
const resolved = resolveSkillStates(catalog, config);
|
|
217
|
-
//
|
|
218
|
-
expect(resolved.length).toBe(
|
|
219
|
-
expect(resolved[0].summary.id).toBe(DECLARED_SKILL_ID);
|
|
217
|
+
// email-channel registry default is false, so it is filtered out
|
|
218
|
+
expect(resolved.length).toBe(0);
|
|
220
219
|
});
|
|
221
220
|
|
|
222
221
|
test("skill without featureFlag is never flag-gated", () => {
|
|
@@ -259,12 +258,16 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
259
258
|
test("multiple skills with mixed flags — persisted overrides respected", () => {
|
|
260
259
|
_setOverridesForTesting({
|
|
261
260
|
[DECLARED_FLAG_KEY]: false,
|
|
262
|
-
|
|
261
|
+
[ENABLED_UNDECLARED_FLAG_KEY]: true,
|
|
263
262
|
deploy: false,
|
|
264
263
|
});
|
|
265
264
|
const catalog = [
|
|
266
265
|
makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID),
|
|
267
|
-
makeSkill(
|
|
266
|
+
makeSkill(
|
|
267
|
+
ENABLED_UNDECLARED_SKILL_ID,
|
|
268
|
+
"bundled",
|
|
269
|
+
ENABLED_UNDECLARED_FLAG_KEY,
|
|
270
|
+
),
|
|
268
271
|
makeSkill("deploy", "bundled", "deploy"),
|
|
269
272
|
];
|
|
270
273
|
const config = makeConfig();
|
|
@@ -272,8 +275,8 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
272
275
|
const resolved = resolveSkillStates(catalog, config);
|
|
273
276
|
const ids = resolved.map((r) => r.summary.id);
|
|
274
277
|
|
|
275
|
-
//
|
|
276
|
-
expect(ids).toEqual([
|
|
278
|
+
// email-channel and deploy explicitly false; one unrelated skill explicitly true
|
|
279
|
+
expect(ids).toEqual([ENABLED_UNDECLARED_SKILL_ID]);
|
|
277
280
|
});
|
|
278
281
|
});
|
|
279
282
|
|
|
@@ -282,15 +285,14 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
282
285
|
// ---------------------------------------------------------------------------
|
|
283
286
|
|
|
284
287
|
describe("resolveSkillStates with frontmatter featureFlag", () => {
|
|
285
|
-
test("skill with featureFlag (defaultEnabled:
|
|
286
|
-
//
|
|
288
|
+
test("skill with featureFlag (defaultEnabled: false) is excluded when no config override", () => {
|
|
289
|
+
// email-channel has defaultEnabled: false in the registry
|
|
287
290
|
const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
|
|
288
291
|
const config = makeConfig();
|
|
289
292
|
|
|
290
293
|
const resolved = resolveSkillStates(catalog, config);
|
|
291
|
-
// No override, registry default is
|
|
292
|
-
expect(resolved.length).toBe(
|
|
293
|
-
expect(resolved[0].summary.id).toBe(DECLARED_SKILL_ID);
|
|
294
|
+
// No override, registry default is false → filtered out
|
|
295
|
+
expect(resolved.length).toBe(0);
|
|
294
296
|
});
|
|
295
297
|
|
|
296
298
|
test("skill with featureFlag is included when override enables it", () => {
|
|
@@ -12,8 +12,8 @@ const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
|
12
12
|
|
|
13
13
|
let currentConfig: Record<string, unknown> = {};
|
|
14
14
|
|
|
15
|
-
const DECLARED_SKILL_ID = "
|
|
16
|
-
const DECLARED_FLAG_KEY = "
|
|
15
|
+
const DECLARED_SKILL_ID = "email-channel";
|
|
16
|
+
const DECLARED_FLAG_KEY = "email-channel";
|
|
17
17
|
|
|
18
18
|
const noopLogger = new Proxy({} as Record<string, unknown>, {
|
|
19
19
|
get: (_target, prop) => (prop === "child" ? () => noopLogger : () => {}),
|
|
@@ -35,7 +35,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
35
35
|
getConfigReadOnly: () => currentConfig,
|
|
36
36
|
loadConfig: () => currentConfig,
|
|
37
37
|
loadRawConfig: () => ({}),
|
|
38
|
-
saveConfig: () => {},
|
|
39
38
|
saveRawConfig: () => {},
|
|
40
39
|
invalidateConfigCache: () => {},
|
|
41
40
|
getNestedValue: () => undefined,
|
|
@@ -99,8 +98,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
99
98
|
test("returns deterministic error for flag OFF skill", async () => {
|
|
100
99
|
writeSkill(
|
|
101
100
|
DECLARED_SKILL_ID,
|
|
102
|
-
"
|
|
103
|
-
"Toggle
|
|
101
|
+
"Email Channel",
|
|
102
|
+
"Toggle email channel behavior",
|
|
104
103
|
"Use the feature.",
|
|
105
104
|
);
|
|
106
105
|
writeFileSync(
|
|
@@ -120,8 +119,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
120
119
|
test("loads skill normally when flag is ON", async () => {
|
|
121
120
|
writeSkill(
|
|
122
121
|
DECLARED_SKILL_ID,
|
|
123
|
-
"
|
|
124
|
-
"Toggle
|
|
122
|
+
"Email Channel",
|
|
123
|
+
"Toggle email channel behavior",
|
|
125
124
|
"Use the feature.",
|
|
126
125
|
);
|
|
127
126
|
writeFileSync(
|
|
@@ -134,14 +133,14 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
134
133
|
const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
|
|
135
134
|
|
|
136
135
|
expect(result.isError).toBe(false);
|
|
137
|
-
expect(result.content).toContain("Skill:
|
|
136
|
+
expect(result.content).toContain("Skill: Email Channel");
|
|
138
137
|
});
|
|
139
138
|
|
|
140
|
-
test("
|
|
139
|
+
test("returns error when flag key is absent (registry defaults to disabled)", async () => {
|
|
141
140
|
writeSkill(
|
|
142
141
|
DECLARED_SKILL_ID,
|
|
143
|
-
"
|
|
144
|
-
"Toggle
|
|
142
|
+
"Email Channel",
|
|
143
|
+
"Toggle email channel behavior",
|
|
145
144
|
"Use the feature.",
|
|
146
145
|
);
|
|
147
146
|
writeFileSync(
|
|
@@ -153,8 +152,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
153
152
|
|
|
154
153
|
const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
|
|
155
154
|
|
|
156
|
-
//
|
|
157
|
-
expect(result.isError).toBe(
|
|
158
|
-
expect(result.content).toContain("
|
|
155
|
+
// email-channel is declared in the registry with defaultEnabled: false
|
|
156
|
+
expect(result.isError).toBe(true);
|
|
157
|
+
expect(result.content).toContain("disabled by feature flag");
|
|
159
158
|
});
|
|
160
159
|
});
|
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
* Validates that:
|
|
5
5
|
* - Root skills with `!\`command\`` tokens get those tokens expanded exactly
|
|
6
6
|
* once at skill_load time, wrapped in <inline_skill_command> XML tags.
|
|
7
|
-
* - When the feature flag is off, skill_load returns an error instead of
|
|
8
|
-
* leaving unresolved live tokens in the prompt.
|
|
9
7
|
* - When the skill source is "extra", skill_load rejects with a specific error.
|
|
10
8
|
* - Render failures produce stable inline stubs rather than raw stderr.
|
|
11
9
|
*/
|
|
@@ -14,8 +12,6 @@ import { mkdirSync, writeFileSync } from "node:fs";
|
|
|
14
12
|
import { join } from "node:path";
|
|
15
13
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
16
14
|
|
|
17
|
-
import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
|
|
18
|
-
|
|
19
15
|
// ── Test directory ────────────────────────────────────────────────────────────
|
|
20
16
|
|
|
21
17
|
const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
@@ -93,7 +89,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
93
89
|
getConfig: () => testConfig,
|
|
94
90
|
loadConfig: () => testConfig,
|
|
95
91
|
invalidateConfigCache: () => {},
|
|
96
|
-
saveConfig: () => {},
|
|
97
92
|
loadRawConfig: () => ({}),
|
|
98
93
|
saveRawConfig: () => {},
|
|
99
94
|
getNestedValue: () => undefined,
|
|
@@ -163,10 +158,6 @@ describe("skill_load inline command expansion", () => {
|
|
|
163
158
|
) => mockRunInlineCommand(command, workingDir),
|
|
164
159
|
}));
|
|
165
160
|
|
|
166
|
-
// Enable the feature flag
|
|
167
|
-
_setOverridesForTesting({
|
|
168
|
-
"inline-skill-commands": true,
|
|
169
|
-
});
|
|
170
161
|
testConfig.skills = { load: { extraDirs: [] } };
|
|
171
162
|
});
|
|
172
163
|
|
|
@@ -255,48 +246,6 @@ describe("skill_load inline command expansion", () => {
|
|
|
255
246
|
});
|
|
256
247
|
});
|
|
257
248
|
|
|
258
|
-
// ── Feature flag off ─────────────────────────────────────────────────
|
|
259
|
-
|
|
260
|
-
describe("feature flag disabled", () => {
|
|
261
|
-
test("returns error when flag is off and skill has inline commands", async () => {
|
|
262
|
-
_setOverridesForTesting({
|
|
263
|
-
"inline-skill-commands": false,
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
writeSkill(
|
|
267
|
-
"flagged-off-skill",
|
|
268
|
-
"Flagged Off Skill",
|
|
269
|
-
"Has inline commands",
|
|
270
|
-
"Data: !`echo hello`",
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
const result = await executeSkillLoad({ skill: "flagged-off-skill" });
|
|
274
|
-
expect(result.isError).toBe(true);
|
|
275
|
-
expect(result.content).toContain(
|
|
276
|
-
"inline-skill-commands feature flag is disabled",
|
|
277
|
-
);
|
|
278
|
-
// Runner should not be called when flag is off
|
|
279
|
-
expect(runInlineCommandCalls).toHaveLength(0);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
test("plain skill still loads when flag is off", async () => {
|
|
283
|
-
_setOverridesForTesting({
|
|
284
|
-
"inline-skill-commands": false,
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
writeSkill(
|
|
288
|
-
"plain-flag-off",
|
|
289
|
-
"Plain Flag Off",
|
|
290
|
-
"No inline commands",
|
|
291
|
-
"Regular content.",
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
const result = await executeSkillLoad({ skill: "plain-flag-off" });
|
|
295
|
-
expect(result.isError).toBe(false);
|
|
296
|
-
expect(result.content).toContain("Regular content.");
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
249
|
// ── Extra source rejection ───────────────────────────────────────────
|
|
301
250
|
//
|
|
302
251
|
// The SkillLoadTool checks `skill.source === "extra"` and rejects inline
|
|
@@ -16,8 +16,6 @@ import { mkdirSync, writeFileSync } from "node:fs";
|
|
|
16
16
|
import { join } from "node:path";
|
|
17
17
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
18
18
|
|
|
19
|
-
import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
|
|
20
|
-
|
|
21
19
|
// ── Test directory ────────────────────────────────────────────────────────────
|
|
22
20
|
|
|
23
21
|
const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
@@ -95,7 +93,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
95
93
|
getConfig: () => testConfig,
|
|
96
94
|
loadConfig: () => testConfig,
|
|
97
95
|
invalidateConfigCache: () => {},
|
|
98
|
-
saveConfig: () => {},
|
|
99
96
|
loadRawConfig: () => ({}),
|
|
100
97
|
saveRawConfig: () => {},
|
|
101
98
|
getNestedValue: () => undefined,
|
|
@@ -173,10 +170,6 @@ describe("skill_load inline command expansion for included skills", () => {
|
|
|
173
170
|
) => mockRunInlineCommand(command, workingDir),
|
|
174
171
|
}));
|
|
175
172
|
|
|
176
|
-
// Enable the feature flag
|
|
177
|
-
_setOverridesForTesting({
|
|
178
|
-
"inline-skill-commands": true,
|
|
179
|
-
});
|
|
180
173
|
testConfig.skills = { load: { extraDirs: [] } };
|
|
181
174
|
});
|
|
182
175
|
|
|
@@ -514,42 +507,6 @@ describe("skill_load inline command expansion for included skills", () => {
|
|
|
514
507
|
});
|
|
515
508
|
});
|
|
516
509
|
|
|
517
|
-
// ── Feature flag off for child inline commands ────────────────────────
|
|
518
|
-
|
|
519
|
-
describe("feature flag disabled for included skills", () => {
|
|
520
|
-
test("skill_load returns error when child has inline commands and flag is off", async () => {
|
|
521
|
-
_setOverridesForTesting({
|
|
522
|
-
"inline-skill-commands": false,
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
writeSkill(
|
|
526
|
-
"child-flag-off",
|
|
527
|
-
"Flag Off Child",
|
|
528
|
-
"Child with inline cmds",
|
|
529
|
-
"Data: !`echo hello`",
|
|
530
|
-
);
|
|
531
|
-
writeSkill(
|
|
532
|
-
"parent-flag-off",
|
|
533
|
-
"Parent Flag Off",
|
|
534
|
-
"Parent for flag-off test",
|
|
535
|
-
"Root content.",
|
|
536
|
-
{ includes: ["child-flag-off"] },
|
|
537
|
-
);
|
|
538
|
-
|
|
539
|
-
const result = await executeSkillLoad({ skill: "parent-flag-off" });
|
|
540
|
-
// Fail closed: the entire skill_load must error when any included child
|
|
541
|
-
// has inline commands and the feature flag is off, matching the root
|
|
542
|
-
// skill behavior and the documented fail-closed contract.
|
|
543
|
-
expect(result.isError).toBe(true);
|
|
544
|
-
expect(result.content).toContain("child-flag-off");
|
|
545
|
-
expect(result.content).toContain(
|
|
546
|
-
"inline-skill-commands feature flag is disabled",
|
|
547
|
-
);
|
|
548
|
-
// Runner should not be called
|
|
549
|
-
expect(runInlineCommandCalls).toHaveLength(0);
|
|
550
|
-
});
|
|
551
|
-
});
|
|
552
|
-
|
|
553
510
|
// ── Root with inline + child with inline ──────────────────────────────
|
|
554
511
|
|
|
555
512
|
describe("root and child both have inline commands", () => {
|
|
@@ -28,7 +28,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
28
28
|
getConfig: () => mockConfig,
|
|
29
29
|
loadConfig: () => mockConfig,
|
|
30
30
|
invalidateConfigCache: () => {},
|
|
31
|
-
saveConfig: () => {},
|
|
32
31
|
loadRawConfig: () => ({}),
|
|
33
32
|
saveRawConfig: () => {},
|
|
34
33
|
getNestedValue: () => undefined,
|
|
@@ -61,7 +61,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
61
61
|
saveRawConfig: (raw: Record<string, unknown>) => {
|
|
62
62
|
configStore = structuredClone(raw);
|
|
63
63
|
},
|
|
64
|
-
saveConfig: () => {},
|
|
65
64
|
invalidateConfigCache: () => {},
|
|
66
65
|
setNestedValue,
|
|
67
66
|
}));
|
|
@@ -438,11 +437,7 @@ describe("Slack channel config handler", () => {
|
|
|
438
437
|
});
|
|
439
438
|
|
|
440
439
|
test("POST rejects user token with invalid prefix", async () => {
|
|
441
|
-
const result = await setSlackChannelConfig(
|
|
442
|
-
undefined,
|
|
443
|
-
undefined,
|
|
444
|
-
"abc-123",
|
|
445
|
-
);
|
|
440
|
+
const result = await setSlackChannelConfig(undefined, undefined, "abc-123");
|
|
446
441
|
expect(result.success).toBe(false);
|
|
447
442
|
expect(result.error).toContain("xoxp-");
|
|
448
443
|
// Nothing was stored.
|
|
@@ -660,9 +655,7 @@ describe("Slack channel config handler", () => {
|
|
|
660
655
|
expect(
|
|
661
656
|
await getSecureKeyAsync(credentialKey("slack_channel", "user_token")),
|
|
662
657
|
).toBe("xoxp-still-valid");
|
|
663
|
-
expect(
|
|
664
|
-
getCredentialMetadata("slack_channel", "user_token"),
|
|
665
|
-
).toBeDefined();
|
|
658
|
+
expect(getCredentialMetadata("slack_channel", "user_token")).toBeDefined();
|
|
666
659
|
|
|
667
660
|
// No warning about user_token removal — nothing was removed.
|
|
668
661
|
expect(result.warning ?? "").not.toContain("User token");
|
|
@@ -697,10 +690,10 @@ describe("Slack channel config handler", () => {
|
|
|
697
690
|
}
|
|
698
691
|
if (auth === "Bearer xoxp-workspace-a") {
|
|
699
692
|
// Workspace mismatch — handler will try to clear the user_token.
|
|
700
|
-
return new Response(
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
);
|
|
693
|
+
return new Response(JSON.stringify({ ok: true, team_id: "T_A" }), {
|
|
694
|
+
status: 200,
|
|
695
|
+
headers: { "content-type": "application/json" },
|
|
696
|
+
});
|
|
704
697
|
}
|
|
705
698
|
throw new Error(`Unexpected auth header: ${auth}`);
|
|
706
699
|
}) as unknown as typeof globalThis.fetch;
|
|
@@ -808,7 +801,9 @@ describe("Slack channel config handler", () => {
|
|
|
808
801
|
expect(
|
|
809
802
|
await getSecureKeyAsync(credentialKey("slack_channel", "user_token")),
|
|
810
803
|
).toBeUndefined();
|
|
811
|
-
expect(
|
|
804
|
+
expect(
|
|
805
|
+
getCredentialMetadata("slack_channel", "user_token"),
|
|
806
|
+
).toBeUndefined();
|
|
812
807
|
});
|
|
813
808
|
|
|
814
809
|
test("clearSlackUserToken leaves bot+app tokens and oauth_connection intact", async () => {
|
|
@@ -17,6 +17,7 @@ import { join } from "node:path";
|
|
|
17
17
|
import { afterAll } from "bun:test";
|
|
18
18
|
|
|
19
19
|
import { installGatewayIpcMock } from "../__tests__/mock-gateway-ipc.js";
|
|
20
|
+
import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
|
|
20
21
|
import { resetDb } from "../memory/db-connection.js";
|
|
21
22
|
import { _setStorePath } from "../security/encrypted-store.js";
|
|
22
23
|
|
|
@@ -36,6 +37,13 @@ _setStorePath(join(testDir, "keys.enc"));
|
|
|
36
37
|
// Tests that need to control IPC responses use mockGatewayIpc() / resetMockGatewayIpc().
|
|
37
38
|
installGatewayIpcMock();
|
|
38
39
|
|
|
40
|
+
// Pre-populate the feature-flag override cache so `initFeatureFlagOverrides()`
|
|
41
|
+
// short-circuits its retry loop — there is no real gateway in tests, and the
|
|
42
|
+
// retry backoff would otherwise exceed the per-test timeout for any test that
|
|
43
|
+
// builds the CLI program. Tests exercising the retry behavior call
|
|
44
|
+
// `clearFeatureFlagOverridesCache()` first.
|
|
45
|
+
_setOverridesForTesting({});
|
|
46
|
+
|
|
39
47
|
// Force-close any DB connection inherited from the parent process (e.g. when
|
|
40
48
|
// the test runner is spawned by the running assistant via a pre-push hook).
|
|
41
49
|
// Without this, the db singleton in db-connection.ts may still point at the
|
|
@@ -518,7 +518,7 @@ describe("ToolApprovalHandler / pre-exec gate grant check", () => {
|
|
|
518
518
|
}
|
|
519
519
|
});
|
|
520
520
|
|
|
521
|
-
test("trusted contact
|
|
521
|
+
test("trusted contact requires grant for sandboxed side-effect tools", async () => {
|
|
522
522
|
const result = await handler.checkPreExecutionGates(
|
|
523
523
|
"bash",
|
|
524
524
|
{ command: "echo hello" },
|
|
@@ -529,12 +529,11 @@ describe("ToolApprovalHandler / pre-exec gate grant check", () => {
|
|
|
529
529
|
emitLifecycleEvent,
|
|
530
530
|
);
|
|
531
531
|
|
|
532
|
-
expect(result.allowed).toBe(
|
|
532
|
+
expect(result.allowed).toBe(false);
|
|
533
533
|
expect(events.filter((e) => e.type === "permission_denied")).toHaveLength(
|
|
534
|
-
|
|
534
|
+
1,
|
|
535
535
|
);
|
|
536
536
|
});
|
|
537
|
-
|
|
538
537
|
});
|
|
539
538
|
|
|
540
539
|
afterAll(() => {
|
|
@@ -64,6 +64,54 @@ describe("tool audit listener", () => {
|
|
|
64
64
|
expect(records[1].decision).toBe("denied");
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
+
test("redacts known-pattern secrets in tool result content before recording", () => {
|
|
68
|
+
const records: ToolInvocationRecord[] = [];
|
|
69
|
+
const listener = createToolAuditListener((record) => records.push(record));
|
|
70
|
+
|
|
71
|
+
// Anthropic key pattern requires 80+ chars after "sk-ant-"
|
|
72
|
+
const anthropicKey =
|
|
73
|
+
"sk-ant-api03-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
|
|
74
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
75
|
+
listener({
|
|
76
|
+
type: "executed",
|
|
77
|
+
toolName: "bash",
|
|
78
|
+
input: { command: "echo $ANTHROPIC_API_KEY" },
|
|
79
|
+
workingDir: "/tmp",
|
|
80
|
+
conversationId: "conv-redact",
|
|
81
|
+
riskLevel: "low",
|
|
82
|
+
decision: "allow",
|
|
83
|
+
durationMs: 5,
|
|
84
|
+
result: { content: `key=${anthropicKey}`, isError: false },
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
expect(records).toHaveLength(1);
|
|
88
|
+
expect(records[0].result).not.toContain("sk-ant-api03-");
|
|
89
|
+
expect(records[0].result).toContain("<redacted");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("does not redact non-secret content like UUIDs or hashes", () => {
|
|
93
|
+
const records: ToolInvocationRecord[] = [];
|
|
94
|
+
const listener = createToolAuditListener((record) => records.push(record));
|
|
95
|
+
|
|
96
|
+
const safeContent =
|
|
97
|
+
"file id: 550e8400-e29b-41d4-a716-446655440000, sha: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2";
|
|
98
|
+
|
|
99
|
+
listener({
|
|
100
|
+
type: "executed",
|
|
101
|
+
toolName: "file_read",
|
|
102
|
+
input: { path: "/tmp/data" },
|
|
103
|
+
workingDir: "/tmp",
|
|
104
|
+
conversationId: "conv-safe",
|
|
105
|
+
riskLevel: "low",
|
|
106
|
+
decision: "allow",
|
|
107
|
+
durationMs: 3,
|
|
108
|
+
result: { content: safeContent, isError: false },
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
expect(records).toHaveLength(1);
|
|
112
|
+
expect(records[0].result).toBe(safeContent);
|
|
113
|
+
});
|
|
114
|
+
|
|
67
115
|
test("records error events and ignores non-terminal events", () => {
|
|
68
116
|
const records: ToolInvocationRecord[] = [];
|
|
69
117
|
const listener = createToolAuditListener((record) => records.push(record));
|