@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
|
@@ -3,6 +3,7 @@ import type { DeleteResult } from "../../security/credential-backend.js";
|
|
|
3
3
|
import { credentialKey } from "../../security/credential-key.js";
|
|
4
4
|
import {
|
|
5
5
|
deleteSecureKeyAsync,
|
|
6
|
+
getActiveBackendName,
|
|
6
7
|
setSecureKeyAsync,
|
|
7
8
|
} from "../../security/secure-keys.js";
|
|
8
9
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -16,6 +17,26 @@ function isDaemonUnreachable(error: string): boolean {
|
|
|
16
17
|
return error === DAEMON_UNREACHABLE;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Result types — include error context so the CLI can surface it
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
export interface SetSecureKeyResult {
|
|
25
|
+
ok: boolean;
|
|
26
|
+
/** Human-readable error reason when ok=false. */
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DeleteSecureKeyResult {
|
|
31
|
+
result: DeleteResult;
|
|
32
|
+
/** Human-readable error reason when result="error". */
|
|
33
|
+
error?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Set
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
19
40
|
/**
|
|
20
41
|
* Store a secret via the daemon IPC socket (so daemon-side singletons
|
|
21
42
|
* stay in sync). Falls back to direct `setSecureKeyAsync()` when the
|
|
@@ -25,37 +46,61 @@ export async function setSecureKeyViaDaemon(
|
|
|
25
46
|
type: string,
|
|
26
47
|
name: string,
|
|
27
48
|
value: string,
|
|
28
|
-
): Promise<
|
|
29
|
-
const ipc = await cliIpcCall<{ success: boolean }>(
|
|
30
|
-
|
|
31
|
-
name,
|
|
32
|
-
|
|
33
|
-
});
|
|
49
|
+
): Promise<SetSecureKeyResult> {
|
|
50
|
+
const ipc = await cliIpcCall<{ success: boolean; error?: string }>(
|
|
51
|
+
"secrets/write",
|
|
52
|
+
{ type, name, value },
|
|
53
|
+
);
|
|
34
54
|
|
|
35
|
-
if (ipc.ok && ipc.result) {
|
|
36
|
-
return
|
|
55
|
+
if (ipc.ok && ipc.result?.success) {
|
|
56
|
+
return { ok: true };
|
|
37
57
|
}
|
|
38
58
|
|
|
59
|
+
// Daemon returned an IPC-level error (thrown InternalError, etc.)
|
|
39
60
|
if (ipc.error && !isDaemonUnreachable(ipc.error)) {
|
|
40
61
|
log.warn({ type, name, error: ipc.error }, "Daemon secret write failed");
|
|
41
|
-
return false;
|
|
62
|
+
return { ok: false, error: ipc.error };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Daemon returned success=false (e.g. validation error, backend failure)
|
|
66
|
+
if (ipc.ok && ipc.result && !ipc.result.success) {
|
|
67
|
+
return {
|
|
68
|
+
ok: false,
|
|
69
|
+
error: ipc.result.error || "Credential write rejected by assistant",
|
|
70
|
+
};
|
|
42
71
|
}
|
|
43
72
|
|
|
44
73
|
// Daemon unreachable — fall back to direct write.
|
|
74
|
+
let account: string;
|
|
45
75
|
if (type === "api_key") {
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
if (type === "credential" && !name.startsWith("credential/")) {
|
|
76
|
+
account = credentialKey(name, "api_key");
|
|
77
|
+
} else if (type === "credential" && !name.startsWith("credential/")) {
|
|
49
78
|
const colonIdx = name.lastIndexOf(":");
|
|
50
79
|
if (colonIdx > 0 && colonIdx < name.length - 1) {
|
|
51
80
|
const service = name.slice(0, colonIdx);
|
|
52
81
|
const field = name.slice(colonIdx + 1);
|
|
53
|
-
|
|
82
|
+
account = credentialKey(service, field);
|
|
83
|
+
} else {
|
|
84
|
+
account = name;
|
|
54
85
|
}
|
|
86
|
+
} else {
|
|
87
|
+
account = name;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const ok = await setSecureKeyAsync(account, value);
|
|
91
|
+
if (!ok) {
|
|
92
|
+
return {
|
|
93
|
+
ok: false,
|
|
94
|
+
error: `Failed to store credential (backend: ${getActiveBackendName()})`,
|
|
95
|
+
};
|
|
55
96
|
}
|
|
56
|
-
return
|
|
97
|
+
return { ok: true };
|
|
57
98
|
}
|
|
58
99
|
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// Delete
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
|
|
59
104
|
/**
|
|
60
105
|
* Delete a secret via the daemon IPC socket. Falls back to direct
|
|
61
106
|
* `deleteSecureKeyAsync()` when the daemon is not running.
|
|
@@ -63,42 +108,79 @@ export async function setSecureKeyViaDaemon(
|
|
|
63
108
|
export async function deleteSecureKeyViaDaemon(
|
|
64
109
|
type: string,
|
|
65
110
|
name: string,
|
|
66
|
-
): Promise<
|
|
111
|
+
): Promise<DeleteSecureKeyResult> {
|
|
67
112
|
const ipc = await cliIpcCall<{ success: boolean }>("secrets/delete", {
|
|
68
113
|
type,
|
|
69
114
|
name,
|
|
70
115
|
});
|
|
71
116
|
|
|
72
|
-
if (ipc.ok && ipc.result) {
|
|
73
|
-
return
|
|
117
|
+
if (ipc.ok && ipc.result?.success) {
|
|
118
|
+
return { result: "deleted" };
|
|
74
119
|
}
|
|
75
120
|
|
|
121
|
+
// Daemon returned an IPC-level error
|
|
76
122
|
if (ipc.error && !isDaemonUnreachable(ipc.error)) {
|
|
77
123
|
if (ipc.error.includes("not found") || ipc.error.includes("404")) {
|
|
78
|
-
return "not-found";
|
|
124
|
+
return { result: "not-found" };
|
|
79
125
|
}
|
|
80
|
-
return "error";
|
|
126
|
+
return { result: "error", error: ipc.error };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Daemon returned success=false
|
|
130
|
+
if (ipc.ok && ipc.result && !ipc.result.success) {
|
|
131
|
+
return {
|
|
132
|
+
result: "error",
|
|
133
|
+
error: "Credential delete rejected by assistant",
|
|
134
|
+
};
|
|
81
135
|
}
|
|
82
136
|
|
|
83
137
|
// Daemon unreachable — fall back to direct delete.
|
|
84
138
|
if (type === "api_key") {
|
|
85
139
|
// Delete from both locations; during migration overlap both may exist.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
140
|
+
const credResult = await deleteSecureKeyAsync(
|
|
141
|
+
credentialKey(name, "api_key"),
|
|
142
|
+
);
|
|
143
|
+
if (credResult === "error") {
|
|
144
|
+
return {
|
|
145
|
+
result: "error",
|
|
146
|
+
error: `Failed to delete credential (backend: ${getActiveBackendName()})`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
89
149
|
const bareResult = await deleteSecureKeyAsync(name);
|
|
90
|
-
if (bareResult === "error")
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
150
|
+
if (bareResult === "error") {
|
|
151
|
+
return {
|
|
152
|
+
result: "error",
|
|
153
|
+
error: `Failed to delete credential (backend: ${getActiveBackendName()})`,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
result:
|
|
158
|
+
credResult === "deleted" || bareResult === "deleted"
|
|
159
|
+
? "deleted"
|
|
160
|
+
: "not-found",
|
|
161
|
+
};
|
|
94
162
|
}
|
|
163
|
+
|
|
164
|
+
let account: string;
|
|
95
165
|
if (type === "credential" && !name.startsWith("credential/")) {
|
|
96
166
|
const colonIdx = name.lastIndexOf(":");
|
|
97
167
|
if (colonIdx > 0 && colonIdx < name.length - 1) {
|
|
98
168
|
const service = name.slice(0, colonIdx);
|
|
99
169
|
const field = name.slice(colonIdx + 1);
|
|
100
|
-
|
|
170
|
+
account = credentialKey(service, field);
|
|
171
|
+
} else {
|
|
172
|
+
account = name;
|
|
101
173
|
}
|
|
174
|
+
} else {
|
|
175
|
+
account = name;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const result = await deleteSecureKeyAsync(account);
|
|
179
|
+
if (result === "error") {
|
|
180
|
+
return {
|
|
181
|
+
result: "error",
|
|
182
|
+
error: `Failed to delete credential (backend: ${getActiveBackendName()})`,
|
|
183
|
+
};
|
|
102
184
|
}
|
|
103
|
-
return
|
|
185
|
+
return { result };
|
|
104
186
|
}
|
package/src/cli/program.ts
CHANGED
|
@@ -27,6 +27,7 @@ import { registerCredentialsCommand } from "./commands/credentials.js";
|
|
|
27
27
|
import { registerDefaultAction } from "./commands/default-action.js";
|
|
28
28
|
import { registerDomainCommand } from "./commands/domain.js";
|
|
29
29
|
import { registerEmailCommand } from "./commands/email.js";
|
|
30
|
+
import { registerGatewayCommand } from "./commands/gateway.js";
|
|
30
31
|
import { registerImageGenerationCommand } from "./commands/image-generation.js";
|
|
31
32
|
import { registerInferenceCommand } from "./commands/inference.js";
|
|
32
33
|
import { registerKeysCommand } from "./commands/keys.js";
|
|
@@ -96,6 +97,7 @@ Examples:
|
|
|
96
97
|
registerDomainCommand(program);
|
|
97
98
|
registerEmailCommand(program);
|
|
98
99
|
}
|
|
100
|
+
registerGatewayCommand(program);
|
|
99
101
|
registerImageGenerationCommand(program);
|
|
100
102
|
registerInferenceCommand(program);
|
|
101
103
|
registerKeysCommand(program);
|
|
@@ -17,8 +17,11 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
17
17
|
import { dirname, join } from "node:path";
|
|
18
18
|
|
|
19
19
|
import { ipcGetFeatureFlags } from "../ipc/gateway-client.js";
|
|
20
|
+
import { getLogger } from "../util/logger.js";
|
|
20
21
|
import type { AssistantConfig } from "./schema.js";
|
|
21
22
|
|
|
23
|
+
const log = getLogger("assistant-feature-flags");
|
|
24
|
+
|
|
22
25
|
// ---------------------------------------------------------------------------
|
|
23
26
|
// Types
|
|
24
27
|
// ---------------------------------------------------------------------------
|
|
@@ -140,6 +143,20 @@ async function fetchOverridesFromGateway(): Promise<Record<string, boolean>> {
|
|
|
140
143
|
}
|
|
141
144
|
}
|
|
142
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Default backoff schedule (ms) between `initFeatureFlagOverrides` retries
|
|
148
|
+
* when the gateway IPC fetch returns empty. The daemon and gateway start
|
|
149
|
+
* as sibling child processes of the macOS app, so the daemon can race
|
|
150
|
+
* ahead of the gateway binding `gateway.sock`. Each delay is the
|
|
151
|
+
* *additional* wait before the next attempt, so total worst-case latency
|
|
152
|
+
* is the sum: 250 + 500 + 1000 + 2000 + 4000 = 7.75s. All retries run in
|
|
153
|
+
* the background (lifecycle.ts fires `initFeatureFlagOverrides`
|
|
154
|
+
* non-blocking), so this never delays startup.
|
|
155
|
+
*/
|
|
156
|
+
const DEFAULT_INIT_RETRY_BACKOFFS_MS: readonly number[] = [
|
|
157
|
+
250, 500, 1000, 2000, 4000,
|
|
158
|
+
];
|
|
159
|
+
|
|
143
160
|
/**
|
|
144
161
|
* Pre-populate the override cache from the gateway (async).
|
|
145
162
|
*
|
|
@@ -148,26 +165,66 @@ async function fetchOverridesFromGateway(): Promise<Record<string, boolean>> {
|
|
|
148
165
|
* uses the gateway. In local mode, falls back to the local file when
|
|
149
166
|
* the gateway is unreachable.
|
|
150
167
|
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
168
|
+
* Retries the gateway IPC fetch on empty/failed results — the gateway
|
|
169
|
+
* may not have bound its IPC socket yet when the daemon races ahead at
|
|
170
|
+
* startup. After exhausting retries, the cache is left unset so
|
|
171
|
+
* subsequent sync calls return an empty override map (registry defaults
|
|
172
|
+
* only).
|
|
173
|
+
*
|
|
174
|
+
* Pass `retryBackoffsMs: []` to disable retries (used by unit tests that
|
|
175
|
+
* intentionally simulate an unreachable gateway and want immediate
|
|
176
|
+
* fallback without waiting through the production schedule).
|
|
153
177
|
*
|
|
154
178
|
* No-ops when the cache is already populated — callers that want to
|
|
155
179
|
* refresh must call `clearFeatureFlagOverridesCache()` first. This lets
|
|
156
180
|
* tests preseed flag state via `_setOverridesForTesting()` without the
|
|
157
181
|
* gateway IPC call clobbering their setup.
|
|
158
182
|
*/
|
|
159
|
-
export async function initFeatureFlagOverrides(
|
|
183
|
+
export async function initFeatureFlagOverrides(options?: {
|
|
184
|
+
retryBackoffsMs?: readonly number[];
|
|
185
|
+
}): Promise<void> {
|
|
160
186
|
if (cachedOverridesFromGateway) return;
|
|
161
187
|
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
188
|
+
const backoffs = options?.retryBackoffsMs ?? DEFAULT_INIT_RETRY_BACKOFFS_MS;
|
|
189
|
+
|
|
190
|
+
// First attempt has no preceding delay; subsequent attempts wait per the
|
|
191
|
+
// backoff schedule. An empty result is treated as a transient miss
|
|
192
|
+
// (gateway not yet bound) and triggers a retry — a healthy gateway
|
|
193
|
+
// always returns at least the registry-merged flags.
|
|
194
|
+
for (let attempt = 0; attempt <= backoffs.length; attempt++) {
|
|
195
|
+
if (attempt > 0) {
|
|
196
|
+
const delay = backoffs[attempt - 1]!;
|
|
197
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
198
|
+
// Re-check after the wait: a concurrent caller (e.g. a test using
|
|
199
|
+
// `_setOverridesForTesting`) may have populated the cache while we
|
|
200
|
+
// were sleeping. Bail out so we don't clobber their setup.
|
|
201
|
+
if (cachedOverridesFromGateway) return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const gatewayOverrides = await fetchOverridesFromGateway();
|
|
205
|
+
if (Object.keys(gatewayOverrides).length > 0) {
|
|
206
|
+
cachedOverrides = gatewayOverrides;
|
|
207
|
+
cachedOverridesFromGateway = true;
|
|
208
|
+
if (attempt > 0) {
|
|
209
|
+
log.info(
|
|
210
|
+
{ attempt: attempt + 1 },
|
|
211
|
+
"Feature flag overrides loaded from gateway after retry",
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
167
216
|
}
|
|
168
217
|
|
|
169
|
-
//
|
|
170
|
-
//
|
|
218
|
+
// Exhausted retries — leave cache unset so loadOverrides() returns an
|
|
219
|
+
// empty map on subsequent sync reads. Flag checks fall through to the
|
|
220
|
+
// registry default (`defaultEnabled`), which biases toward off for
|
|
221
|
+
// newer assistant-scope flags.
|
|
222
|
+
if (backoffs.length > 0) {
|
|
223
|
+
log.warn(
|
|
224
|
+
{ attempts: backoffs.length + 1 },
|
|
225
|
+
"Feature flag overrides empty after all retries; falling back to registry defaults",
|
|
226
|
+
);
|
|
227
|
+
}
|
|
171
228
|
}
|
|
172
229
|
|
|
173
230
|
/**
|
|
@@ -6,6 +6,12 @@ metadata:
|
|
|
6
6
|
emoji: "🔗"
|
|
7
7
|
vellum:
|
|
8
8
|
display-name: "ACP"
|
|
9
|
+
activation-hints:
|
|
10
|
+
- "User wants to delegate a coding task to Claude Code, Codex, or another ACP agent"
|
|
11
|
+
- "User wants to spawn an external coding agent that runs autonomously and streams results back"
|
|
12
|
+
- "User mentions ACP, claude-agent-acp, codex-acp, or running multiple coding agents in parallel"
|
|
13
|
+
avoid-when:
|
|
14
|
+
- "Task is small enough to do inline with the assistant's own tools — no need for an external agent"
|
|
9
15
|
---
|
|
10
16
|
|
|
11
17
|
ACP agent orchestration - spawn external coding agents (Claude Code, Codex, etc.) to work on tasks via the Agent Client Protocol. Each agent runs as its own subprocess speaking ACP over stdio and streams results back into the conversation.
|
|
@@ -20,10 +20,6 @@
|
|
|
20
20
|
"cwd": {
|
|
21
21
|
"type": "string",
|
|
22
22
|
"description": "Working directory for the agent. This determines where the agent runs and where its session is stored. Set this to the project/repo root the user wants the agent to work in. Defaults to current conversation's working directory."
|
|
23
|
-
},
|
|
24
|
-
"activity": {
|
|
25
|
-
"type": "string",
|
|
26
|
-
"description": "Brief explanation of why this tool is being called"
|
|
27
23
|
}
|
|
28
24
|
},
|
|
29
25
|
"required": ["task"]
|
|
@@ -42,10 +38,6 @@
|
|
|
42
38
|
"acp_session_id": {
|
|
43
39
|
"type": "string",
|
|
44
40
|
"description": "Optional ACP session ID to query. If omitted, returns all ACP sessions."
|
|
45
|
-
},
|
|
46
|
-
"activity": {
|
|
47
|
-
"type": "string",
|
|
48
|
-
"description": "Brief explanation of why this tool is being called"
|
|
49
41
|
}
|
|
50
42
|
},
|
|
51
43
|
"required": []
|
|
@@ -64,10 +56,6 @@
|
|
|
64
56
|
"acp_session_id": {
|
|
65
57
|
"type": "string",
|
|
66
58
|
"description": "The ID of the ACP session to abort."
|
|
67
|
-
},
|
|
68
|
-
"activity": {
|
|
69
|
-
"type": "string",
|
|
70
|
-
"description": "Brief explanation of why this tool is being called"
|
|
71
59
|
}
|
|
72
60
|
},
|
|
73
61
|
"required": ["acp_session_id"]
|
|
@@ -90,10 +78,6 @@
|
|
|
90
78
|
"instruction": {
|
|
91
79
|
"type": "string",
|
|
92
80
|
"description": "The new instruction that replaces the in-flight prompt."
|
|
93
|
-
},
|
|
94
|
-
"activity": {
|
|
95
|
-
"type": "string",
|
|
96
|
-
"description": "Brief explanation of why this tool is being called"
|
|
97
81
|
}
|
|
98
82
|
},
|
|
99
83
|
"required": ["acp_session_id", "instruction"]
|
|
@@ -108,12 +92,7 @@
|
|
|
108
92
|
"risk": "low",
|
|
109
93
|
"input_schema": {
|
|
110
94
|
"type": "object",
|
|
111
|
-
"properties": {
|
|
112
|
-
"activity": {
|
|
113
|
-
"type": "string",
|
|
114
|
-
"description": "Brief explanation of why this tool is being called"
|
|
115
|
-
}
|
|
116
|
-
},
|
|
95
|
+
"properties": {},
|
|
117
96
|
"required": []
|
|
118
97
|
},
|
|
119
98
|
"executor": "tools/acp-list-agents.ts",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: app-builder
|
|
3
|
-
description: Build interactive apps, dashboards, calculators, games, trackers, tools, landing pages, and data visualizations with
|
|
3
|
+
description: Build interactive apps, dashboards, calculators, games, trackers, tools, landing pages, and data visualizations with Preact/TypeScript/CSS
|
|
4
4
|
compatibility: "Designed for Vellum personal assistants"
|
|
5
5
|
metadata:
|
|
6
6
|
emoji: "🏗️"
|
|
@@ -30,11 +30,11 @@ Apps live under `{workspaceDir}/data/apps/`. Each app has a slug-based layout:
|
|
|
30
30
|
{workspaceDir}/data/apps/
|
|
31
31
|
<slug>.json # App metadata
|
|
32
32
|
<slug>/ # App directory (contains all app files)
|
|
33
|
-
index.html #
|
|
34
|
-
pages/ #
|
|
33
|
+
index.html # Legacy single-file entry point (do not create for new apps)
|
|
34
|
+
pages/ # Legacy additional pages (do not create for new apps)
|
|
35
35
|
records/ # Data records (one JSON file per record)
|
|
36
|
-
src/ # Source files (
|
|
37
|
-
dist/ # Compiled output (
|
|
36
|
+
src/ # Source files (multi-file TSX apps, formatVersion: 2)
|
|
37
|
+
dist/ # Compiled output (multi-file TSX apps)
|
|
38
38
|
<slug>.preview # Preview image (auto-generated)
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -42,7 +42,7 @@ Apps live under `{workspaceDir}/data/apps/`. Each app has a slug-based layout:
|
|
|
42
42
|
|
|
43
43
|
Fields: `id`, `name`, `description`, `icon`, `schemaJson`, `createdAt`, `updatedAt`, `formatVersion`, `dirName`.
|
|
44
44
|
|
|
45
|
-
**Important:** `htmlDefinition` and `pages`
|
|
45
|
+
**Important:** Legacy `htmlDefinition` and `pages` content is NOT stored in the metadata JSON — it lives as separate files inside the app directory (`index.html` and `pages/`). Do not create new single-file apps or new `pages/` directories.
|
|
46
46
|
|
|
47
47
|
### Records
|
|
48
48
|
|
|
@@ -52,9 +52,9 @@ Each record is a JSON file at `<slug>/records/<uuid>.json` with shape:
|
|
|
52
52
|
{ "id": "<uuid>", "appId": "<app-id>", "data": { ... }, "createdAt": "...", "updatedAt": "..." }
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
###
|
|
55
|
+
### Multi-file TSX Apps
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
All new apps use `formatVersion: 2`: source files live under `src/` and compiled output lives under `dist/`. The build system compiles TSX to JS automatically when `app_refresh` is called.
|
|
58
58
|
|
|
59
59
|
## Workflow
|
|
60
60
|
|
|
@@ -69,16 +69,7 @@ For `formatVersion: 2` apps, source files live under `src/` and compiled output
|
|
|
69
69
|
|
|
70
70
|
**Make creative decisions on behalf of the user.** They want to be delighted, not consulted. Pick the accent color. Choose between a dark moody aesthetic or a light airy one. Decide if cards should have glassmorphism or layered shadows. Add a background pattern or gradient. These are YOUR decisions as the designer.
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
**Prefer multi-file TSX projects** for any non-trivial app. They give you component reuse, TypeScript safety, and cleaner organization. Fall back to single-file HTML only for the simplest one-off pages.
|
|
75
|
-
|
|
76
|
-
<!-- feature:app-builder-multifile:end -->
|
|
77
|
-
<!-- feature:app-builder-multifile:alt -->
|
|
78
|
-
|
|
79
|
-
**Always build single-file HTML apps.** Write a complete, self-contained HTML document with all CSS in `<style>` and all JavaScript in `<script>`. Do not use multi-file projects or TSX.
|
|
80
|
-
|
|
81
|
-
<!-- feature:app-builder-multifile:alt:end -->
|
|
72
|
+
**Build all new apps as multi-file TSX projects.** They give you component reuse, TypeScript safety, and cleaner organization.
|
|
82
73
|
|
|
83
74
|
**Only ask questions when the request is genuinely ambiguous** - e.g., "build me an app" with no indication of what kind. Even then, prefer building something impressive based on context clues over asking a battery of questions.
|
|
84
75
|
|
|
@@ -124,11 +115,9 @@ Example schema for a project tracker:
|
|
|
124
115
|
|
|
125
116
|
Apps are rendered inside a sandboxed WebView on macOS.
|
|
126
117
|
|
|
127
|
-
<!-- feature:app-builder-multifile:start -->
|
|
128
|
-
|
|
129
118
|
#### Multi-file TSX projects
|
|
130
119
|
|
|
131
|
-
Build apps as multi-file TSX projects. You get component reuse, TypeScript type-checking, and clean file organization. The build system uses esbuild to bundle everything automatically.
|
|
120
|
+
Build apps as multi-file TSX projects. You get component reuse, TypeScript type-checking, and clean file organization. The build system uses esbuild to bundle everything automatically. Do not create root-level `index.html` files or `pages/` directories for new apps.
|
|
132
121
|
|
|
133
122
|
**Project structure:**
|
|
134
123
|
|
|
@@ -190,7 +179,7 @@ useEffect(() => {
|
|
|
190
179
|
}, []);
|
|
191
180
|
```
|
|
192
181
|
|
|
193
|
-
**File workflow:**
|
|
182
|
+
**File workflow:** Call `app_create` first to create the app record and scaffold, use `file_write` for each source file under `src/`, then call `app_refresh` once to compile and refresh the UI.
|
|
194
183
|
|
|
195
184
|
**Allowed third-party packages:** `date-fns`, `chart.js`, `lodash-es`, `zod`, `clsx`, `lucide`. Import them directly - esbuild resolves them at build time. No CDN imports. Note: `lucide` is the vanilla JS icon library (not `lucide-react`). Use its `createElement` or `createIcons` API, or manually inline SVG - do not import JSX icon components.
|
|
196
185
|
|
|
@@ -262,23 +251,6 @@ app_refresh(app_id)
|
|
|
262
251
|
- No external fonts, images, or resources - use system fonts and CSS/SVG for visuals
|
|
263
252
|
- Design responsively. Apps render at fluid, user-resizable widths — avoid fixed-pixel layouts
|
|
264
253
|
- The WebView blocks all navigation - links and form `action` attributes won't work
|
|
265
|
-
<!-- feature:app-builder-multifile:end -->
|
|
266
|
-
|
|
267
|
-
<!-- feature:app-builder-multifile:alt -->
|
|
268
|
-
|
|
269
|
-
#### Single HTML file
|
|
270
|
-
|
|
271
|
-
Write a complete, self-contained HTML document.
|
|
272
|
-
|
|
273
|
-
**Technical constraints (single-file):**
|
|
274
|
-
|
|
275
|
-
- Single HTML string - no external files, CDNs, or imports
|
|
276
|
-
- All CSS in `<style>` in `<head>`, all JavaScript in `<script>` before `</body>`
|
|
277
|
-
- No external fonts, images, or resources - use system fonts and CSS/SVG for visuals
|
|
278
|
-
- Design responsively. Apps render at fluid, user-resizable widths — avoid fixed-pixel layouts
|
|
279
|
-
- The WebView blocks all navigation - links and form `action` attributes won't work
|
|
280
|
-
|
|
281
|
-
<!-- feature:app-builder-multifile:alt:end -->
|
|
282
254
|
|
|
283
255
|
#### Injected design system
|
|
284
256
|
|
|
@@ -352,88 +324,21 @@ For handler conventions, examples, key rules, and frontend usage patterns, see *
|
|
|
352
324
|
|
|
353
325
|
`localStorage` and `sessionStorage` are available for ephemeral UI state (filters, view modes, collapsed state, preferences, form drafts). Use custom routes for persistent app records, `localStorage` for UI preferences.
|
|
354
326
|
|
|
355
|
-
<!-- feature:app-builder-multifile:alt -->
|
|
356
|
-
|
|
357
|
-
#### JavaScript patterns
|
|
358
|
-
|
|
359
|
-
Initialize apps with clean state management:
|
|
360
|
-
|
|
361
|
-
```javascript
|
|
362
|
-
document.addEventListener("DOMContentLoaded", async () => {
|
|
363
|
-
await loadRecords();
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
let allRecords = [];
|
|
367
|
-
|
|
368
|
-
async function loadRecords() {
|
|
369
|
-
try {
|
|
370
|
-
const res = await window.vellum.fetch("/v1/x/records");
|
|
371
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
372
|
-
allRecords = await res.json();
|
|
373
|
-
render();
|
|
374
|
-
} catch (err) {
|
|
375
|
-
console.error("Failed to load:", err);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
function render() {
|
|
380
|
-
// Re-render UI from allRecords
|
|
381
|
-
}
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
**HTML escaping:** Always escape user-controlled data before inserting into the DOM via `innerHTML`:
|
|
385
|
-
|
|
386
|
-
```javascript
|
|
387
|
-
function esc(s) {
|
|
388
|
-
const d = document.createElement("div");
|
|
389
|
-
d.textContent = String(s);
|
|
390
|
-
return d.innerHTML;
|
|
391
|
-
}
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### 4. Single-Page App Views
|
|
395
|
-
|
|
396
|
-
Apps run inside a sandboxed WebView that blocks all navigation. All apps are effectively single-page. When an app needs multiple views, use JavaScript to swap content:
|
|
397
|
-
|
|
398
|
-
```javascript
|
|
399
|
-
function showView(name) {
|
|
400
|
-
document.querySelectorAll(".view").forEach((v) => (v.hidden = true));
|
|
401
|
-
document.getElementById("view-" + name).hidden = false;
|
|
402
|
-
document
|
|
403
|
-
.querySelectorAll(".nav-link")
|
|
404
|
-
.forEach((btn) => btn.classList.remove("active"));
|
|
405
|
-
document
|
|
406
|
-
.querySelector(`[onclick="showView('${name}')"]`)
|
|
407
|
-
?.classList.add("active");
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
<!-- feature:app-builder-multifile:alt:end -->
|
|
412
|
-
|
|
413
|
-
<!-- feature:app-builder-multifile:start -->
|
|
414
327
|
### 4. Create and Open the App
|
|
415
|
-
<!-- feature:app-builder-multifile:end -->
|
|
416
|
-
<!-- feature:app-builder-multifile:alt -->
|
|
417
|
-
### 5. Create and Open the App
|
|
418
|
-
<!-- feature:app-builder-multifile:alt:end -->
|
|
419
328
|
|
|
420
329
|
Call `app_create` with:
|
|
421
330
|
|
|
422
331
|
- `name`: Short descriptive name
|
|
423
332
|
- `description`: One-sentence summary
|
|
424
333
|
- `schema_json`: JSON schema as string
|
|
425
|
-
- `html`: (optional) Complete HTML document as string for `index.html`. If omitted, a minimal scaffold is created - you can then write `index.html` and other files via `file_write`.
|
|
426
334
|
- `auto_open`: (optional, defaults to `true`) Shows an inline preview card in chat
|
|
427
335
|
- `preview`: Always include - `title` (required), `subtitle`, `description`, `icon` (image URL preferred, emoji fallback), `metrics` (up to 3 key-value pills)
|
|
428
336
|
|
|
337
|
+
Do not pass `html` or `pages` to `app_create`; those single-file shortcuts are retired. After `app_create` returns the app ID, write the real app source under `src/` and call `app_refresh`.
|
|
338
|
+
|
|
429
339
|
The app is NOT opened in a workspace panel automatically - users open it via the 'Open App' button on the inline card.
|
|
430
340
|
|
|
431
|
-
<!-- feature:app-builder-multifile:start -->
|
|
432
341
|
### 5. Handle Iteration
|
|
433
|
-
<!-- feature:app-builder-multifile:end -->
|
|
434
|
-
<!-- feature:app-builder-multifile:alt -->
|
|
435
|
-
### 6. Handle Iteration
|
|
436
|
-
<!-- feature:app-builder-multifile:alt:end -->
|
|
437
342
|
|
|
438
343
|
When the user requests changes, prefer **`file_edit`** over rewriting the entire file.
|
|
439
344
|
|
|
@@ -444,7 +349,7 @@ When the user requests changes, prefer **`file_edit`** over rewriting the entire
|
|
|
444
349
|
|
|
445
350
|
After making all file changes, call `app_refresh(app_id)` once to compile and refresh the UI. Do NOT call it after every individual file edit — batch your changes first.
|
|
446
351
|
|
|
447
|
-
Apps
|
|
352
|
+
Apps should have multiple source files under `src/` (`styles.css`, components, helpers, etc.). Import CSS and modules from TSX so esbuild includes them in the compiled output.
|
|
448
353
|
|
|
449
354
|
## Interaction Standards
|
|
450
355
|
|