@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `vellum backup` — manage automated
|
|
2
|
+
* `vellum backup` — manage automated backup configuration and list snapshots.
|
|
3
3
|
*
|
|
4
4
|
* All subcommands run in-process (they do not call the daemon HTTP port).
|
|
5
5
|
* Config mutations go through `loadRawConfig` / `setNestedValue` / `saveRawConfig`
|
|
@@ -12,31 +12,22 @@ import { dirname } from "node:path";
|
|
|
12
12
|
|
|
13
13
|
import type { Command } from "commander";
|
|
14
14
|
|
|
15
|
-
import { readBackupKey } from "../../backup/backup-key.js";
|
|
16
|
-
import { createSnapshotNow } from "../../backup/backup-worker.js";
|
|
17
15
|
import {
|
|
18
16
|
listSnapshotsInDir,
|
|
19
17
|
type SnapshotEntry,
|
|
20
18
|
} from "../../backup/list-snapshots.js";
|
|
21
19
|
import {
|
|
22
|
-
getBackupKeyPath,
|
|
23
20
|
getLocalBackupsDir,
|
|
24
21
|
resolveOffsiteDestinations,
|
|
25
22
|
} from "../../backup/paths.js";
|
|
26
|
-
import { restoreFromSnapshot, verifySnapshot } from "../../backup/restore.js";
|
|
27
23
|
import {
|
|
28
24
|
getConfig,
|
|
29
|
-
invalidateConfigCache,
|
|
30
25
|
loadRawConfig,
|
|
31
26
|
saveRawConfig,
|
|
32
27
|
setNestedValue,
|
|
33
28
|
} from "../../config/loader.js";
|
|
34
29
|
import type { BackupDestination } from "../../config/schema.js";
|
|
35
|
-
import { isDaemonRunning } from "../../daemon/daemon-control.js";
|
|
36
30
|
import { getMemoryCheckpoint } from "../../memory/checkpoints.js";
|
|
37
|
-
import { resetDb } from "../../memory/db-connection.js";
|
|
38
|
-
import { DefaultPathResolver } from "../../runtime/migrations/vbundle-import-analyzer.js";
|
|
39
|
-
import { getWorkspaceDir, getWorkspaceHooksDir } from "../../util/platform.js";
|
|
40
31
|
import { log } from "../logger.js";
|
|
41
32
|
|
|
42
33
|
// ---------------------------------------------------------------------------
|
|
@@ -87,7 +78,7 @@ function formatDurationShort(ms: number): string {
|
|
|
87
78
|
|
|
88
79
|
/**
|
|
89
80
|
* Check whether an offsite destination's parent directory exists. Mirrors the
|
|
90
|
-
* reachability check in
|
|
81
|
+
* reachability check in the backup worker — if the parent is missing (e.g.
|
|
91
82
|
* iCloud Drive not enabled, external SSD unplugged) the destination is
|
|
92
83
|
* considered unreachable and we skip it at runtime.
|
|
93
84
|
*/
|
|
@@ -405,242 +396,9 @@ export async function handleList(): Promise<void> {
|
|
|
405
396
|
}
|
|
406
397
|
|
|
407
398
|
// ---------------------------------------------------------------------------
|
|
408
|
-
// create
|
|
409
399
|
// ---------------------------------------------------------------------------
|
|
410
400
|
|
|
411
|
-
export async function handleCreate(): Promise<void> {
|
|
412
|
-
const cfg = getConfig().backup;
|
|
413
|
-
try {
|
|
414
|
-
const result = await createSnapshotNow(cfg, new Date());
|
|
415
|
-
log.info(`Created snapshot: ${result.local.path}`);
|
|
416
|
-
log.info(` size: ${formatBytes(result.local.sizeBytes)}`);
|
|
417
|
-
log.info(` duration: ${result.durationMs}ms`);
|
|
418
|
-
if (result.offsite.length === 0) {
|
|
419
|
-
log.info(` offsite: (none)`);
|
|
420
|
-
} else {
|
|
421
|
-
log.info(` offsite:`);
|
|
422
|
-
for (const r of result.offsite) {
|
|
423
|
-
if (r.entry) {
|
|
424
|
-
log.info(
|
|
425
|
-
` ok ${r.destination.path} -> ${r.entry.filename}`,
|
|
426
|
-
);
|
|
427
|
-
} else if (r.skipped) {
|
|
428
|
-
log.info(` skipped ${r.destination.path} (${r.skipped})`);
|
|
429
|
-
} else {
|
|
430
|
-
log.info(
|
|
431
|
-
` error ${r.destination.path} (${r.error ?? "unknown"})`,
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
} catch (err) {
|
|
437
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
438
|
-
if (message.toLowerCase().includes("snapshot in progress")) {
|
|
439
|
-
log.error(
|
|
440
|
-
"Another snapshot is already running. Wait for it to finish, then retry.",
|
|
441
|
-
);
|
|
442
|
-
} else {
|
|
443
|
-
log.error(`Snapshot failed: ${message}`);
|
|
444
|
-
}
|
|
445
|
-
process.exitCode = 1;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// ---------------------------------------------------------------------------
|
|
450
|
-
// restore / verify helpers
|
|
451
|
-
// ---------------------------------------------------------------------------
|
|
452
401
|
|
|
453
|
-
/** True when a snapshot path ends in `.vbundle.enc`. */
|
|
454
|
-
function isEncryptedPath(path: string): boolean {
|
|
455
|
-
return path.endsWith(".vbundle.enc");
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* Load the backup key when the snapshot is encrypted. Throws a user-facing
|
|
460
|
-
* error when the key file is missing or corrupt.
|
|
461
|
-
*/
|
|
462
|
-
async function loadKeyForEncryptedSnapshot(
|
|
463
|
-
snapshotPath: string,
|
|
464
|
-
): Promise<Buffer | undefined> {
|
|
465
|
-
if (!isEncryptedPath(snapshotPath)) return undefined;
|
|
466
|
-
const keyPath = getBackupKeyPath();
|
|
467
|
-
const key = await readBackupKey(keyPath);
|
|
468
|
-
if (!key) {
|
|
469
|
-
throw new Error(
|
|
470
|
-
`Encrypted snapshot requires backup key at ${keyPath}, but none was found. ` +
|
|
471
|
-
`The key is generated the first time automatic backup runs against an encrypted ` +
|
|
472
|
-
`destination.`,
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
return key;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* Prompt for y/N confirmation. Defaults to `false` on empty input, EOF, or
|
|
480
|
-
* anything other than `y` / `yes` (case-insensitive).
|
|
481
|
-
*/
|
|
482
|
-
async function promptConfirm(question: string): Promise<boolean> {
|
|
483
|
-
const readline = await import("node:readline");
|
|
484
|
-
const rl = readline.createInterface({
|
|
485
|
-
input: process.stdin,
|
|
486
|
-
output: process.stdout,
|
|
487
|
-
});
|
|
488
|
-
const answer = await new Promise<string>((resolve) => {
|
|
489
|
-
rl.question(question, resolve);
|
|
490
|
-
});
|
|
491
|
-
rl.close();
|
|
492
|
-
const normalized = answer.trim().toLowerCase();
|
|
493
|
-
return normalized === "y" || normalized === "yes";
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
// ---------------------------------------------------------------------------
|
|
497
|
-
// restore
|
|
498
|
-
// ---------------------------------------------------------------------------
|
|
499
|
-
|
|
500
|
-
export interface RestoreOptions {
|
|
501
|
-
path?: string;
|
|
502
|
-
latest?: boolean;
|
|
503
|
-
yes?: boolean;
|
|
504
|
-
force?: boolean;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
export async function handleRestore(opts: RestoreOptions): Promise<void> {
|
|
508
|
-
if (!opts.path && !opts.latest) {
|
|
509
|
-
log.error(
|
|
510
|
-
"Must specify --path <snapshot> or --latest. " +
|
|
511
|
-
"Run 'vellum backup list' to see available snapshots.",
|
|
512
|
-
);
|
|
513
|
-
process.exitCode = 1;
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
if (opts.path && opts.latest) {
|
|
517
|
-
log.error("Cannot combine --path and --latest. Drop one.");
|
|
518
|
-
process.exitCode = 1;
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// Safety gate: a restore while the assistant is running is dangerous.
|
|
523
|
-
// The assistant holds an open SQLite handle (referencing the old inode on
|
|
524
|
-
// Unix), a cached config, and cached trust rules. Overwriting the files
|
|
525
|
-
// under a running process corrupts state. Refuse unless `--force` says the
|
|
526
|
-
// caller knows what they're doing.
|
|
527
|
-
if (!opts.force && isDaemonRunning()) {
|
|
528
|
-
log.error(
|
|
529
|
-
"Assistant is running — stop it first with 'vellum sleep' before restoring " +
|
|
530
|
-
"(safe restore requires an idle assistant). Pass --force to override.",
|
|
531
|
-
);
|
|
532
|
-
process.exitCode = 1;
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
let snapshotPath: string;
|
|
537
|
-
if (opts.path) {
|
|
538
|
-
snapshotPath = opts.path;
|
|
539
|
-
} else {
|
|
540
|
-
// `--latest` is explicitly scoped to local snapshots — offsite files may
|
|
541
|
-
// not exist after a machine swap (per the plan), so we keep the selection
|
|
542
|
-
// rule predictable.
|
|
543
|
-
const cfg = getConfig().backup;
|
|
544
|
-
const localDir = getLocalBackupsDir(cfg.localDirectory);
|
|
545
|
-
const entries = await listSnapshotsInDir(localDir);
|
|
546
|
-
if (entries.length === 0) {
|
|
547
|
-
log.error(
|
|
548
|
-
`No local snapshots found in ${localDir}. ` +
|
|
549
|
-
`Run 'vellum backup create' to make one, or pass --path with an explicit file.`,
|
|
550
|
-
);
|
|
551
|
-
process.exitCode = 1;
|
|
552
|
-
return;
|
|
553
|
-
}
|
|
554
|
-
snapshotPath = entries[0]!.path;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
if (!opts.yes) {
|
|
558
|
-
const confirmed = await promptConfirm(
|
|
559
|
-
`Restore from ${snapshotPath}? This will overwrite workspace files. (y/N) `,
|
|
560
|
-
);
|
|
561
|
-
if (!confirmed) {
|
|
562
|
-
log.info("Restore cancelled");
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
let key: Buffer | undefined;
|
|
568
|
-
try {
|
|
569
|
-
key = await loadKeyForEncryptedSnapshot(snapshotPath);
|
|
570
|
-
} catch (err) {
|
|
571
|
-
log.error(err instanceof Error ? err.message : String(err));
|
|
572
|
-
process.exitCode = 1;
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
try {
|
|
577
|
-
const workspaceDir = getWorkspaceDir();
|
|
578
|
-
const hooksDir = getWorkspaceHooksDir();
|
|
579
|
-
const pathResolver = new DefaultPathResolver(workspaceDir, hooksDir);
|
|
580
|
-
|
|
581
|
-
// Close the SQLite singleton before the bundle is written. If the
|
|
582
|
-
// assistant process was running in-process (tests, `--force`) the
|
|
583
|
-
// singleton may still reference the old file; resetting closes the
|
|
584
|
-
// handle so the restored DB file is picked up cleanly on the next
|
|
585
|
-
// getDb() call.
|
|
586
|
-
resetDb();
|
|
587
|
-
|
|
588
|
-
const result = await restoreFromSnapshot(snapshotPath, {
|
|
589
|
-
key,
|
|
590
|
-
pathResolver,
|
|
591
|
-
workspaceDir,
|
|
592
|
-
});
|
|
593
|
-
|
|
594
|
-
// Invalidate the in-process config cache so the restored settings.json
|
|
595
|
-
// takes effect without requiring a daemon restart.
|
|
596
|
-
invalidateConfigCache();
|
|
597
|
-
|
|
598
|
-
log.info(`Restored from ${snapshotPath}`);
|
|
599
|
-
log.info(` bundle_id: ${result.manifest.bundle_id}`);
|
|
600
|
-
log.info(` schema_version: ${result.manifest.schema_version}`);
|
|
601
|
-
log.info(` files restored: ${result.restoredFiles}`);
|
|
602
|
-
} catch (err) {
|
|
603
|
-
log.error(
|
|
604
|
-
`Restore failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
605
|
-
);
|
|
606
|
-
process.exitCode = 1;
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// ---------------------------------------------------------------------------
|
|
611
|
-
// verify
|
|
612
|
-
// ---------------------------------------------------------------------------
|
|
613
|
-
|
|
614
|
-
export async function handleVerify(path: string): Promise<void> {
|
|
615
|
-
let key: Buffer | undefined;
|
|
616
|
-
try {
|
|
617
|
-
key = await loadKeyForEncryptedSnapshot(path);
|
|
618
|
-
} catch (err) {
|
|
619
|
-
log.error(err instanceof Error ? err.message : String(err));
|
|
620
|
-
process.exitCode = 1;
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
try {
|
|
625
|
-
const result = await verifySnapshot(path, { key });
|
|
626
|
-
if (result.valid) {
|
|
627
|
-
log.info(`OK: ${path}`);
|
|
628
|
-
if (result.manifest) {
|
|
629
|
-
log.info(` schema_version: ${result.manifest.schema_version}`);
|
|
630
|
-
log.info(` bundle_id: ${result.manifest.bundle_id}`);
|
|
631
|
-
}
|
|
632
|
-
} else {
|
|
633
|
-
log.error(`Invalid: ${path}`);
|
|
634
|
-
if (result.error) log.error(` ${result.error}`);
|
|
635
|
-
process.exitCode = 1;
|
|
636
|
-
}
|
|
637
|
-
} catch (err) {
|
|
638
|
-
log.error(
|
|
639
|
-
`Verify failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
640
|
-
);
|
|
641
|
-
process.exitCode = 1;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
402
|
|
|
645
403
|
// ---------------------------------------------------------------------------
|
|
646
404
|
// Command wiring
|
|
@@ -650,7 +408,7 @@ export function registerBackupCommand(program: Command): void {
|
|
|
650
408
|
const backup = program
|
|
651
409
|
.command("backup")
|
|
652
410
|
.description(
|
|
653
|
-
"Manage automated
|
|
411
|
+
"Manage automated backup configuration and list snapshots",
|
|
654
412
|
);
|
|
655
413
|
|
|
656
414
|
backup.addHelpText(
|
|
@@ -659,7 +417,7 @@ export function registerBackupCommand(program: Command): void {
|
|
|
659
417
|
Backups capture a snapshot of the assistant workspace (config, conversations,
|
|
660
418
|
trust rules, hooks, the SQLite database) as a .vbundle file. Credentials are
|
|
661
419
|
NOT included — they live in the OS keychain / CES and users re-authenticate
|
|
662
|
-
integrations after a restore. The automated worker runs on a configurable
|
|
420
|
+
integrations after a restore (via the gateway). The automated worker runs on a configurable
|
|
663
421
|
interval and writes to a local pool under ~/.vellum/backups/local/, optionally
|
|
664
422
|
mirroring each snapshot to one or more offsite destinations (iCloud Drive by
|
|
665
423
|
default).
|
|
@@ -672,10 +430,7 @@ Examples:
|
|
|
672
430
|
$ vellum backup enable --interval 6 --retention 3
|
|
673
431
|
$ vellum backup destinations add /Volumes/BackupSSD/vellum --plaintext
|
|
674
432
|
$ vellum backup status
|
|
675
|
-
$ vellum backup list
|
|
676
|
-
$ vellum backup create
|
|
677
|
-
$ vellum backup restore --latest --yes
|
|
678
|
-
$ vellum backup verify ~/.vellum/backups/local/backup-20260411-093000.vbundle`,
|
|
433
|
+
$ vellum backup list`,
|
|
679
434
|
);
|
|
680
435
|
|
|
681
436
|
backup
|
|
@@ -841,7 +596,7 @@ Examples:
|
|
|
841
596
|
});
|
|
842
597
|
|
|
843
598
|
// ---------------------------------------------------------------------------
|
|
844
|
-
// status / list
|
|
599
|
+
// status / list
|
|
845
600
|
// ---------------------------------------------------------------------------
|
|
846
601
|
|
|
847
602
|
backup
|
|
@@ -880,84 +635,4 @@ Examples:
|
|
|
880
635
|
await handleList();
|
|
881
636
|
});
|
|
882
637
|
|
|
883
|
-
backup
|
|
884
|
-
.command("create")
|
|
885
|
-
.description("Create a backup snapshot immediately (ignores interval)")
|
|
886
|
-
.addHelpText(
|
|
887
|
-
"after",
|
|
888
|
-
`
|
|
889
|
-
Triggers an on-demand snapshot. Bypasses the interval gate so it will run even
|
|
890
|
-
if the automated worker just ran, but still honours the concurrency mutex --
|
|
891
|
-
a second concurrent caller errors with "snapshot in progress". Does NOT update
|
|
892
|
-
the last-run checkpoint (manual snapshots should not reset the cadence).
|
|
893
|
-
|
|
894
|
-
Examples:
|
|
895
|
-
$ vellum backup create`,
|
|
896
|
-
)
|
|
897
|
-
.action(async () => {
|
|
898
|
-
await handleCreate();
|
|
899
|
-
});
|
|
900
|
-
|
|
901
|
-
backup
|
|
902
|
-
.command("restore")
|
|
903
|
-
.description("Restore a backup snapshot into the workspace")
|
|
904
|
-
.option(
|
|
905
|
-
"--path <path>",
|
|
906
|
-
"Absolute path to the .vbundle or .vbundle.enc file to restore",
|
|
907
|
-
)
|
|
908
|
-
.option(
|
|
909
|
-
"--latest",
|
|
910
|
-
"Restore the newest local snapshot (offsite files are not considered)",
|
|
911
|
-
)
|
|
912
|
-
.option("--yes", "Skip the confirmation prompt")
|
|
913
|
-
.option(
|
|
914
|
-
"--force",
|
|
915
|
-
"Restore even when the assistant is running (unsafe — only use if you know what you're doing)",
|
|
916
|
-
)
|
|
917
|
-
.addHelpText(
|
|
918
|
-
"after",
|
|
919
|
-
`
|
|
920
|
-
Restores a snapshot by writing its contents back into the workspace.
|
|
921
|
-
Encryption is auto-detected from the file extension; encrypted snapshots
|
|
922
|
-
(.vbundle.enc) require the backup key at ~/.vellum/workspace/.backup.key.
|
|
923
|
-
|
|
924
|
-
Prompts for confirmation unless --yes is passed.
|
|
925
|
-
|
|
926
|
-
--latest selects the newest local snapshot only. Offsite files may not exist
|
|
927
|
-
on a new machine after a workspace migration, so --latest refuses to dig into
|
|
928
|
-
them on purpose.
|
|
929
|
-
|
|
930
|
-
Safety: refuses to run while the assistant is running, because the live
|
|
931
|
-
SQLite handle and cached config/trust rules can corrupt the restored state.
|
|
932
|
-
Stop the assistant first with 'vellum sleep'. Pass --force to override (only
|
|
933
|
-
use this if you understand the risk).
|
|
934
|
-
|
|
935
|
-
Examples:
|
|
936
|
-
$ vellum backup restore --latest --yes
|
|
937
|
-
$ vellum backup restore --path ~/.vellum/backups/local/backup-20260411-093000.vbundle`,
|
|
938
|
-
)
|
|
939
|
-
.action(async (opts: RestoreOptions) => {
|
|
940
|
-
await handleRestore(opts);
|
|
941
|
-
});
|
|
942
|
-
|
|
943
|
-
backup
|
|
944
|
-
.command("verify <path>")
|
|
945
|
-
.description("Verify a backup snapshot without restoring it")
|
|
946
|
-
.addHelpText(
|
|
947
|
-
"after",
|
|
948
|
-
`
|
|
949
|
-
Arguments:
|
|
950
|
-
path Absolute path to a .vbundle or .vbundle.enc snapshot file.
|
|
951
|
-
|
|
952
|
-
Runs the same validation the importer would run but never touches the
|
|
953
|
-
workspace. Encryption is auto-detected from the file extension; encrypted
|
|
954
|
-
snapshots require the backup key at ~/.vellum/workspace/.backup.key.
|
|
955
|
-
|
|
956
|
-
Examples:
|
|
957
|
-
$ vellum backup verify ~/.vellum/backups/local/backup-20260411-093000.vbundle
|
|
958
|
-
$ vellum backup verify /Volumes/BackupSSD/vellum/backup-20260411-093000.vbundle.enc`,
|
|
959
|
-
)
|
|
960
|
-
.action(async (path: string) => {
|
|
961
|
-
await handleVerify(path);
|
|
962
|
-
});
|
|
963
638
|
}
|
|
@@ -9,6 +9,7 @@ interface ClientEntryJSON {
|
|
|
9
9
|
clientId: string;
|
|
10
10
|
interfaceId: string;
|
|
11
11
|
capabilities: string[];
|
|
12
|
+
machineName?: string;
|
|
12
13
|
connectedAt: string;
|
|
13
14
|
lastActiveAt: string;
|
|
14
15
|
}
|
|
@@ -47,7 +48,7 @@ Examples:
|
|
|
47
48
|
.option("--json", "Machine-readable compact JSON output")
|
|
48
49
|
.option(
|
|
49
50
|
"--capability <name>",
|
|
50
|
-
"Filter to clients supporting this capability (e.g. host_bash, host_file, host_cu, host_browser)",
|
|
51
|
+
"Filter to clients supporting this capability (e.g. host_bash, host_file, host_cu, host_browser, host_app_control)",
|
|
51
52
|
)
|
|
52
53
|
.addHelpText(
|
|
53
54
|
"after",
|
|
@@ -55,7 +56,7 @@ Examples:
|
|
|
55
56
|
Options:
|
|
56
57
|
--json Output as compact JSON instead of a table.
|
|
57
58
|
--capability <name> Only show clients that support the named capability.
|
|
58
|
-
Valid values: host_bash, host_file, host_cu, host_browser.
|
|
59
|
+
Valid values: host_bash, host_file, host_cu, host_browser, host_app_control.
|
|
59
60
|
|
|
60
61
|
The table shows each client's ID, interface type, capabilities,
|
|
61
62
|
connection timestamps, and host environment (when available).
|
|
@@ -104,6 +105,7 @@ Examples:
|
|
|
104
105
|
"CLIENT ID",
|
|
105
106
|
"INTERFACE",
|
|
106
107
|
"CAPABILITIES",
|
|
108
|
+
"LABEL",
|
|
107
109
|
"CONNECTED",
|
|
108
110
|
"LAST ACTIVE",
|
|
109
111
|
];
|
|
@@ -111,6 +113,7 @@ Examples:
|
|
|
111
113
|
e.clientId,
|
|
112
114
|
e.interfaceId,
|
|
113
115
|
e.capabilities.length > 0 ? e.capabilities.join(", ") : "—",
|
|
116
|
+
e.machineName ?? "—",
|
|
114
117
|
formatRelativeTime(e.connectedAt),
|
|
115
118
|
formatRelativeTime(e.lastActiveAt),
|
|
116
119
|
]);
|
|
@@ -134,13 +137,13 @@ Examples:
|
|
|
134
137
|
},
|
|
135
138
|
);
|
|
136
139
|
|
|
137
|
-
clients
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
clients
|
|
141
|
+
.command("disconnect <clientId>")
|
|
142
|
+
.description("Force-disconnect a client by its ID")
|
|
143
|
+
.option("--json", "Machine-readable compact JSON output")
|
|
144
|
+
.addHelpText(
|
|
145
|
+
"after",
|
|
146
|
+
`
|
|
144
147
|
Arguments:
|
|
145
148
|
clientId The UUID of the client to disconnect (from \`clients list\`).
|
|
146
149
|
|
|
@@ -151,34 +154,30 @@ reconnect automatically depending on its implementation.
|
|
|
151
154
|
Examples:
|
|
152
155
|
$ assistant clients disconnect a1a30bde-6679-406c-bc32-d5a0d2a7a99e
|
|
153
156
|
$ assistant clients disconnect a1a30bde-6679-406c-bc32-d5a0d2a7a99e --json`,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
`Disconnected client ${clientId} (${result.result!.disconnected} subscriber${result.result!.disconnected === 1 ? "" : "s"} disposed)`,
|
|
179
|
-
);
|
|
180
|
-
},
|
|
181
|
-
);
|
|
157
|
+
)
|
|
158
|
+
.action(
|
|
159
|
+
async (clientId: string, opts: { json?: boolean }, cmd: Command) => {
|
|
160
|
+
const result = await cliIpcCall<DisconnectClientResponse>(
|
|
161
|
+
"disconnect_client",
|
|
162
|
+
{ body: { clientId } },
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
if (!result.ok) {
|
|
166
|
+
log.error(result.error ?? "Failed to disconnect client");
|
|
167
|
+
process.exitCode = 1;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (opts.json) {
|
|
172
|
+
writeOutput(cmd, result.result!);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
log.info(
|
|
177
|
+
`Disconnected client ${clientId} (${result.result!.disconnected} subscriber${result.result!.disconnected === 1 ? "" : "s"} disposed)`,
|
|
178
|
+
);
|
|
179
|
+
},
|
|
180
|
+
);
|
|
182
181
|
}
|
|
183
182
|
|
|
184
183
|
function formatRelativeTime(iso: string): string {
|
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
ContactType,
|
|
20
20
|
ContactWithChannels,
|
|
21
21
|
} from "../../contacts/types.js";
|
|
22
|
+
import { cliIpcCall } from "../../ipc/cli-client.js";
|
|
22
23
|
import { getDb } from "../../memory/db-connection.js";
|
|
23
24
|
import {
|
|
24
25
|
createIngressInvite,
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
redeemVoiceInviteCode,
|
|
28
29
|
revokeIngressInvite,
|
|
29
30
|
} from "../../runtime/invite-service.js";
|
|
31
|
+
import type { ContactPromptResult } from "../../runtime/routes/contact-prompt-routes.js";
|
|
30
32
|
import { shouldOutputJson, writeOutput } from "../output.js";
|
|
31
33
|
|
|
32
34
|
// ---------------------------------------------------------------------------
|
|
@@ -407,6 +409,77 @@ Examples:
|
|
|
407
409
|
},
|
|
408
410
|
);
|
|
409
411
|
|
|
412
|
+
contacts
|
|
413
|
+
.command("prompt")
|
|
414
|
+
.description("Prompt user to register a contact channel via the app UI")
|
|
415
|
+
.option("--channel <channel>", "Suggested channel type hint (e.g. phone, email, telegram)")
|
|
416
|
+
.option("--placeholder <placeholder>", "Placeholder text for the address input field")
|
|
417
|
+
.option("--role <role>", "Intended role: guardian, trusted-contact, or unknown (default: unknown)")
|
|
418
|
+
.option("--label <label>", "Display label shown in the prompt UI")
|
|
419
|
+
.option("--description <description>", "Longer description shown in the prompt UI")
|
|
420
|
+
.option("--timeout <ms>", "How long to wait for the user to submit (ms). Defaults to match the server-side prompt timeout.", String(310_000))
|
|
421
|
+
.addHelpText(
|
|
422
|
+
"after",
|
|
423
|
+
`
|
|
424
|
+
Opens a contact address prompt in the user's app. The user enters a channel
|
|
425
|
+
address (phone number, email, Telegram ID, etc.). The address is saved with
|
|
426
|
+
status "unverified". Verification is a separate step.
|
|
427
|
+
|
|
428
|
+
Run \`assistant contacts prompt --help\` for full option details.`,
|
|
429
|
+
)
|
|
430
|
+
.action(
|
|
431
|
+
async (
|
|
432
|
+
opts: {
|
|
433
|
+
channel?: string;
|
|
434
|
+
placeholder?: string;
|
|
435
|
+
role?: string;
|
|
436
|
+
label?: string;
|
|
437
|
+
description?: string;
|
|
438
|
+
timeout?: string;
|
|
439
|
+
},
|
|
440
|
+
cmd: Command,
|
|
441
|
+
) => {
|
|
442
|
+
try {
|
|
443
|
+
const timeoutMs = opts.timeout ? parseInt(opts.timeout, 10) : 310_000;
|
|
444
|
+
const ipc = await cliIpcCall<ContactPromptResult>(
|
|
445
|
+
"contacts_prompt",
|
|
446
|
+
{
|
|
447
|
+
body: {
|
|
448
|
+
channel: opts.channel,
|
|
449
|
+
placeholder: opts.placeholder,
|
|
450
|
+
role: opts.role ?? "unknown",
|
|
451
|
+
label: opts.label,
|
|
452
|
+
description: opts.description,
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
{ timeoutMs },
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
if (!ipc.ok || !ipc.result?.ok) {
|
|
459
|
+
writeError(cmd, ipc.error ?? ipc.result?.error ?? "Contact prompt failed");
|
|
460
|
+
process.exitCode = 1;
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const result = ipc.result;
|
|
465
|
+
if (shouldOutputJson(cmd)) {
|
|
466
|
+
writeOutput(cmd, result);
|
|
467
|
+
} else {
|
|
468
|
+
process.stdout.write(
|
|
469
|
+
`Registered ${result.channelType} channel: ${result.address}\n` +
|
|
470
|
+
` Channel ID: ${result.channelId}\n` +
|
|
471
|
+
` Contact ID: ${result.contactId}\n` +
|
|
472
|
+
` Status: unverified\n`,
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
} catch (err) {
|
|
476
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
477
|
+
writeError(cmd, message);
|
|
478
|
+
process.exitCode = 1;
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
);
|
|
482
|
+
|
|
410
483
|
const channelsCmds = contacts
|
|
411
484
|
.command("channels")
|
|
412
485
|
.description("Manage contact channels");
|
|
@@ -15,10 +15,7 @@ import {
|
|
|
15
15
|
} from "../../memory/conversation-crud.js";
|
|
16
16
|
import { listConversations } from "../../memory/conversation-queries.js";
|
|
17
17
|
import { getDb } from "../../memory/db-connection.js";
|
|
18
|
-
import {
|
|
19
|
-
selectEmbeddingBackend,
|
|
20
|
-
SPARSE_EMBEDDING_VERSION,
|
|
21
|
-
} from "../../memory/embedding-backend.js";
|
|
18
|
+
import { selectEmbeddingBackend } from "../../memory/embedding-backend.js";
|
|
22
19
|
import { enqueueMemoryJob } from "../../memory/jobs-store.js";
|
|
23
20
|
import {
|
|
24
21
|
initQdrantClient,
|
|
@@ -307,7 +304,7 @@ Examples:
|
|
|
307
304
|
const qdrantUrl = resolveQdrantUrl(config);
|
|
308
305
|
const embeddingSelection = await selectEmbeddingBackend(config);
|
|
309
306
|
const embeddingModel = embeddingSelection.backend
|
|
310
|
-
? `${embeddingSelection.backend.provider}:${embeddingSelection.backend.model}
|
|
307
|
+
? `${embeddingSelection.backend.provider}:${embeddingSelection.backend.model}`
|
|
311
308
|
: undefined;
|
|
312
309
|
const qdrant = initQdrantClient({
|
|
313
310
|
url: qdrantUrl,
|
|
@@ -439,13 +439,17 @@ Examples:
|
|
|
439
439
|
|
|
440
440
|
assertMetadataWritable();
|
|
441
441
|
|
|
442
|
-
const
|
|
442
|
+
const setResult = await setSecureKeyViaDaemon(
|
|
443
443
|
"credential",
|
|
444
444
|
`${service}:${field}`,
|
|
445
445
|
value,
|
|
446
446
|
);
|
|
447
|
-
if (!
|
|
448
|
-
|
|
447
|
+
if (!setResult.ok) {
|
|
448
|
+
const detail = setResult.error ? `: ${setResult.error}` : "";
|
|
449
|
+
writeError(
|
|
450
|
+
cmd,
|
|
451
|
+
`Failed to store credential ${service}:${field}${detail}`,
|
|
452
|
+
);
|
|
449
453
|
process.exitCode = 1;
|
|
450
454
|
return;
|
|
451
455
|
}
|
|
@@ -506,12 +510,16 @@ Examples:
|
|
|
506
510
|
|
|
507
511
|
assertMetadataWritable();
|
|
508
512
|
|
|
509
|
-
const
|
|
513
|
+
const deleteResult = await deleteSecureKeyViaDaemon(
|
|
510
514
|
"credential",
|
|
511
515
|
`${service}:${field}`,
|
|
512
516
|
);
|
|
513
|
-
if (
|
|
514
|
-
|
|
517
|
+
if (deleteResult.result === "error") {
|
|
518
|
+
const detail = deleteResult.error ? `: ${deleteResult.error}` : "";
|
|
519
|
+
writeError(
|
|
520
|
+
cmd,
|
|
521
|
+
`Failed to delete credential ${service}:${field}${detail}`,
|
|
522
|
+
);
|
|
515
523
|
process.exitCode = 1;
|
|
516
524
|
return;
|
|
517
525
|
}
|
|
@@ -537,7 +545,7 @@ Examples:
|
|
|
537
545
|
}
|
|
538
546
|
|
|
539
547
|
if (
|
|
540
|
-
|
|
548
|
+
deleteResult.result !== "deleted" &&
|
|
541
549
|
!metadataDeleted &&
|
|
542
550
|
oauthResult !== "disconnected"
|
|
543
551
|
) {
|