@vellumai/assistant 0.6.2 → 0.6.4
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 +273 -10
- package/Dockerfile +2 -3
- package/bun.lock +41 -49
- package/bunfig.toml +3 -0
- package/docs/architecture/memory.md +1 -1
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/stt-provider-onboarding.md +120 -0
- package/knip.json +12 -2
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +3 -3
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +1111 -86
- package/package.json +40 -42
- package/scripts/generate-openapi.ts +0 -2
- package/scripts/test.sh +73 -18
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop.test.ts +123 -0
- package/src/__tests__/anthropic-provider.test.ts +263 -10
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
- package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
- package/src/__tests__/browser-fill-credential.test.ts +240 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/browser-skill-endstate.test.ts +31 -7
- package/src/__tests__/btw-routes.test.ts +7 -0
- package/src/__tests__/call-controller.test.ts +581 -20
- package/src/__tests__/catalog-files.test.ts +1000 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/channel-invite-transport.test.ts +2 -2
- package/src/__tests__/channel-readiness-routes.test.ts +16 -20
- package/src/__tests__/channel-readiness-service.test.ts +12 -7
- package/src/__tests__/checker.test.ts +157 -10
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/config-analysis.test.ts +100 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +1248 -224
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +43 -8
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/contact-store-user-file.test.ts +512 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-overflow-approval.test.ts +16 -1
- package/src/__tests__/context-window-manager.test.ts +88 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +99 -3
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +290 -0
- package/src/__tests__/conversation-error.test.ts +70 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +12 -4
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +946 -62
- package/src/__tests__/conversation-routes-disk-view.test.ts +275 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +324 -46
- package/src/__tests__/conversation-skill-tools.test.ts +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +89 -18
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +6 -3
- package/src/__tests__/credential-vault-unit.test.ts +383 -7
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +42 -18
- package/src/__tests__/cross-provider-web-search.test.ts +146 -35
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +222 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +386 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +2 -0
- package/src/__tests__/gemini-provider.test.ts +66 -2
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
- package/src/__tests__/gmail-archive-gate.test.ts +246 -0
- package/src/__tests__/gmail-preferences.test.ts +117 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +738 -359
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +528 -49
- package/src/__tests__/headless-browser-read-tools.test.ts +274 -100
- package/src/__tests__/headless-browser-snapshot.test.ts +250 -77
- package/src/__tests__/heartbeat-service.test.ts +70 -17
- package/src/__tests__/home-state-routes.test.ts +162 -0
- package/src/__tests__/host-bash-proxy.test.ts +145 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +596 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +423 -0
- package/src/__tests__/host-cu-proxy.test.ts +166 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/llm-context-normalization.test.ts +488 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/media-stream-output.test.ts +555 -0
- package/src/__tests__/media-stream-parser.test.ts +374 -0
- package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
- package/src/__tests__/media-stream-stt-session.test.ts +588 -0
- package/src/__tests__/media-turn-detector.test.ts +440 -0
- package/src/__tests__/message-queue.test.ts +125 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +67 -8
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +109 -7
- package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +151 -0
- package/src/__tests__/model-intents.test.ts +2 -2
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/oauth-apps-routes.test.ts +18 -12
- package/src/__tests__/oauth-cli.test.ts +709 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +118 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +147 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +52 -14
- package/src/__tests__/oauth-store.test.ts +1465 -176
- package/src/__tests__/oauth2-gateway-transport.test.ts +460 -26
- package/src/__tests__/onboarding-template-contract.test.ts +81 -70
- package/src/__tests__/openai-provider.test.ts +178 -2
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1105 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +32 -3
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +343 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +174 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
- package/src/__tests__/relationship-state-contract.test.ts +175 -0
- package/src/__tests__/relay-server.test.ts +423 -5
- package/src/__tests__/require-fresh-approval.test.ts +40 -1
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/secret-scanner-executor.test.ts +4 -0
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +8 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +49 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +801 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +738 -0
- package/src/__tests__/skills.test.ts +5 -2
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +576 -16
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +184 -27
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +25 -5
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +33 -24
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +14 -29
- package/src/__tests__/trust-store.test.ts +7 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/tts-catalog-parity.test.ts +345 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
- package/src/__tests__/twilio-routes.test.ts +376 -0
- package/src/__tests__/unicode.test.ts +293 -0
- package/src/__tests__/update-bulletin-format.test.ts +59 -0
- package/src/__tests__/update-bulletin.test.ts +206 -5
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
- package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
- package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
- package/src/__tests__/workspace-migration-meets.test.ts +244 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
- package/src/__tests__/workspace-policy.test.ts +2 -0
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +55 -9
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/backup/__tests__/backup-key.test.ts +152 -0
- package/src/backup/__tests__/backup-worker.test.ts +767 -0
- package/src/backup/__tests__/list-snapshots.test.ts +87 -0
- package/src/backup/__tests__/local-writer.test.ts +218 -0
- package/src/backup/__tests__/offsite-writer.test.ts +641 -0
- package/src/backup/__tests__/paths.test.ts +300 -0
- package/src/backup/__tests__/restore.test.ts +498 -0
- package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
- package/src/backup/__tests__/stream-crypt.test.ts +228 -0
- package/src/backup/backup-key.ts +137 -0
- package/src/backup/backup-worker.ts +459 -0
- package/src/backup/list-snapshots.ts +147 -0
- package/src/backup/local-writer.ts +133 -0
- package/src/backup/offsite-writer.ts +222 -0
- package/src/backup/paths.ts +226 -0
- package/src/backup/restore.ts +322 -0
- package/src/backup/snapshot-lock.ts +431 -0
- package/src/backup/stream-crypt.ts +263 -0
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/bundler/package-resolver.ts +4 -0
- package/src/calls/audio-store.ts +11 -5
- package/src/calls/call-controller.ts +226 -71
- package/src/calls/call-domain.ts +9 -0
- package/src/calls/call-speech-output.ts +190 -0
- package/src/calls/call-transport.ts +77 -0
- package/src/calls/media-stream-audio-transcode.ts +173 -0
- package/src/calls/media-stream-output.ts +660 -0
- package/src/calls/media-stream-parser.ts +300 -0
- package/src/calls/media-stream-protocol.ts +166 -0
- package/src/calls/media-stream-server.ts +592 -0
- package/src/calls/media-stream-stt-session.ts +460 -0
- package/src/calls/media-turn-detector.ts +230 -0
- package/src/calls/relay-server.ts +90 -75
- package/src/calls/resolve-call-tts-provider.ts +136 -0
- package/src/calls/telephony-stt-routing.ts +145 -0
- package/src/calls/tts-call-strategy.ts +161 -0
- package/src/calls/tts-text-sanitizer.ts +32 -16
- package/src/calls/twilio-routes.ts +281 -17
- package/src/calls/voice-quality.ts +78 -35
- package/src/calls/voice-session-bridge.ts +8 -1
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +69 -3
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
- package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
- package/src/cli/commands/__tests__/email-download.test.ts +16 -1
- package/src/cli/commands/__tests__/email-list.test.ts +22 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +37 -4
- package/src/cli/commands/__tests__/email-status.test.ts +5 -1
- package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/conversations.ts +77 -0
- package/src/cli/commands/credentials.ts +3 -4
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +273 -16
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +56 -44
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +32 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +330 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +117 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +6 -3
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +215 -36
- package/src/cli/commands/oauth/shared.ts +7 -6
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +254 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +30 -4
- package/src/config/__tests__/backup-schema.test.ts +134 -0
- package/src/config/assistant-feature-flags.ts +61 -62
- package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +141 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/browser/SKILL.md +30 -5
- package/src/config/bundled-skills/browser/TOOLS.json +123 -0
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
- package/src/config/bundled-skills/contacts/SKILL.md +5 -2
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +54 -8
- package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
- package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
- package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/outlook/SKILL.md +9 -2
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
- package/src/config/bundled-skills/slack/SKILL.md +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
- package/src/config/bundled-tool-registry.ts +8 -0
- package/src/config/env-registry.ts +38 -0
- package/src/config/env.ts +49 -4
- package/src/config/feature-flag-registry.json +85 -14
- package/src/config/loader.ts +82 -13
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +81 -15
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +51 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -26
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +47 -7
- package/src/config/schemas/heartbeat.ts +27 -5
- package/src/config/schemas/host-browser.ts +112 -0
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +52 -0
- package/src/config/schemas/stt.ts +59 -0
- package/src/config/schemas/tts.ts +230 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/skills.ts +4 -0
- package/src/config/types.ts +4 -1
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/post-turn-tool-result-truncation.ts +177 -0
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +61 -10
- package/src/credential-execution/approval-bridge.ts +49 -15
- package/src/credential-execution/executable-discovery.ts +12 -2
- package/src/credential-execution/process-manager.ts +33 -2
- package/src/credential-health/credential-health-service.ts +366 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +195 -0
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +99 -5
- package/src/daemon/context-overflow-approval.ts +5 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +23 -2
- package/src/daemon/conversation-agent-loop.ts +153 -42
- package/src/daemon/conversation-attachments.ts +40 -0
- package/src/daemon/conversation-error.ts +11 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +59 -9
- package/src/daemon/conversation-messaging.ts +37 -3
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +622 -13
- package/src/daemon/conversation-queue-manager.ts +24 -0
- package/src/daemon/conversation-runtime-assembly.ts +128 -36
- package/src/daemon/conversation-slash.ts +36 -0
- package/src/daemon/conversation-surfaces.ts +131 -40
- package/src/daemon/conversation-tool-setup.ts +99 -8
- package/src/daemon/conversation-usage.ts +7 -4
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +292 -16
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +13 -141
- package/src/daemon/handlers/shared.ts +80 -0
- package/src/daemon/handlers/skills.ts +483 -44
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +192 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +179 -28
- package/src/daemon/message-protocol.ts +13 -0
- package/src/daemon/message-types/conversations.ts +89 -14
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +19 -5
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +26 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/server.ts +439 -14
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +15 -0
- package/src/daemon/transport-hints.ts +5 -24
- package/src/email/html-renderer.ts +76 -0
- package/src/heartbeat/heartbeat-service.ts +93 -7
- package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
- package/src/home/__tests__/emit-feed-event.test.ts +169 -0
- package/src/home/__tests__/feed-scheduler.test.ts +194 -0
- package/src/home/__tests__/feed-types.test.ts +275 -0
- package/src/home/__tests__/feed-writer.test.ts +688 -0
- package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
- package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
- package/src/home/__tests__/progress-formula.test.ts +213 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
- package/src/home/__tests__/rollup-producer.test.ts +398 -0
- package/src/home/assistant-feed-authoring.ts +124 -0
- package/src/home/emit-feed-event.ts +158 -0
- package/src/home/feed-scheduler.ts +247 -0
- package/src/home/feed-types.ts +181 -0
- package/src/home/feed-writer.ts +469 -0
- package/src/home/platform-gmail-digest.ts +163 -0
- package/src/home/progress-formula.ts +86 -0
- package/src/home/relationship-state-writer.ts +824 -0
- package/src/home/relationship-state.ts +143 -0
- package/src/home/rollup-producer.ts +384 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +30 -20
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/cli-client.ts +151 -0
- package/src/ipc/cli-server.ts +234 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/index.ts +5 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/mcp/client.ts +59 -24
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
- package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/app-store.ts +31 -1
- package/src/memory/attachments-store.ts +70 -0
- package/src/memory/auto-analysis-enqueue.ts +127 -0
- package/src/memory/auto-analysis-guard.ts +27 -0
- package/src/memory/cleanup-schedule-state.ts +37 -0
- package/src/memory/conversation-analyze-job.ts +73 -0
- package/src/memory/conversation-crud.ts +122 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +34 -2
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +18 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +176 -17
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/conversation-graph-memory.ts +15 -0
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/extraction.test.ts +23 -0
- package/src/memory/graph/extraction.ts +8 -0
- package/src/memory/graph/retriever.ts +67 -40
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/group-crud.ts +6 -1
- package/src/memory/indexer.ts +95 -16
- package/src/memory/job-handlers/cleanup.ts +11 -8
- package/src/memory/job-handlers/conversation-starters.ts +16 -10
- package/src/memory/jobs-store.ts +64 -4
- package/src/memory/jobs-worker.ts +22 -9
- package/src/memory/llm-usage-store.ts +137 -60
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
- package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/oauth.ts +21 -13
- package/src/memory/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/client.ts +57 -6
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +143 -38
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/decision-engine.ts +3 -3
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +25 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +26 -9
- package/src/oauth/byo-connection.ts +10 -8
- package/src/oauth/connect-orchestrator.ts +25 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +22 -18
- package/src/oauth/connection.ts +3 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +223 -100
- package/src/oauth/platform-connection.test.ts +101 -3
- package/src/oauth/platform-connection.ts +56 -35
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +133 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +16 -6
- package/src/permissions/defaults.ts +49 -1
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -1
- package/src/permissions/trust-store.ts +3 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/permissions/workspace-policy.ts +3 -0
- package/src/platform/client.test.ts +10 -0
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +126 -2
- package/src/prompts/system-prompt.ts +76 -38
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -105
- package/src/prompts/templates/SOUL.md +3 -1
- package/src/prompts/templates/UPDATES.md +12 -0
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-format.ts +26 -9
- package/src/prompts/update-bulletin.ts +34 -23
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/anthropic/client.ts +157 -60
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +9 -1
- package/src/providers/model-catalog.ts +6 -0
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +474 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +502 -0
- package/src/providers/openrouter/client.ts +101 -4
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +14 -3
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
- package/src/providers/speech-to-text/deepgram.test.ts +332 -0
- package/src/providers/speech-to-text/deepgram.ts +115 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
- package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
- package/src/providers/speech-to-text/google-gemini.ts +101 -0
- package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
- package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
- package/src/providers/speech-to-text/openai-whisper.ts +63 -33
- package/src/providers/speech-to-text/provider-catalog.ts +306 -0
- package/src/providers/speech-to-text/resolve.ts +386 -6
- package/src/providers/types.ts +10 -1
- package/src/runtime/AGENTS.md +65 -0
- package/src/runtime/__tests__/agent-wake.test.ts +831 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
- package/src/runtime/agent-wake.ts +512 -0
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +48 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +33 -9
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-invite-transports/email.ts +14 -6
- package/src/runtime/channel-readiness-service.ts +12 -22
- package/src/runtime/chrome-extension-registry.ts +368 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +815 -75
- package/src/runtime/http-types.ts +6 -2
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +198 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/migration-transport.ts +7 -0
- package/src/runtime/migrations/migration-wizard.ts +23 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +96 -1
- package/src/runtime/migrations/vbundle-importer.ts +89 -5
- package/src/runtime/pending-interactions.ts +18 -13
- package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
- package/src/runtime/routes/app-management-routes.ts +12 -18
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +556 -0
- package/src/runtime/routes/btw-routes.ts +8 -6
- package/src/runtime/routes/contact-routes.test.ts +298 -0
- package/src/runtime/routes/contact-routes.ts +132 -5
- package/src/runtime/routes/conversation-analysis-routes.ts +22 -141
- package/src/runtime/routes/conversation-management-routes.ts +223 -0
- package/src/runtime/routes/conversation-routes.ts +598 -103
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/home-feed-routes.ts +334 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +268 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +262 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
- package/src/runtime/routes/integrations/slack/channel.ts +11 -3
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +303 -0
- package/src/runtime/routes/log-export-routes.ts +42 -22
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +122 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +31 -102
- package/src/runtime/routes/skills-routes.ts +128 -9
- package/src/runtime/routes/stt-routes.ts +233 -0
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/surface-action-routes.ts +41 -2
- package/src/runtime/routes/tts-routes.ts +108 -24
- package/src/runtime/routes/usage-routes.ts +38 -9
- package/src/runtime/routes/user-route-dispatcher.ts +50 -5
- package/src/runtime/routes/user-routes.ts +13 -1
- package/src/runtime/routes/work-items-routes.ts +8 -1
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
- package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
- package/src/runtime/services/analyze-conversation.ts +344 -0
- package/src/runtime/services/analyze-deps-singleton.ts +32 -0
- package/src/runtime/services/auto-analysis-prompt.ts +55 -0
- package/src/runtime/skill-route-registry.ts +49 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +57 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +68 -29
- package/src/security/secure-keys.ts +143 -27
- package/src/security/token-manager.ts +31 -10
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-files.ts +554 -0
- package/src/skills/category-inference.ts +122 -0
- package/src/skills/clawhub-files.ts +213 -0
- package/src/skills/clawhub.ts +84 -23
- package/src/skills/skill-file-provider.ts +40 -0
- package/src/skills/skillssh-files.ts +395 -0
- package/src/skills/skillssh-registry.ts +4 -4
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +195 -0
- package/src/stt/stt-stream-session.ts +499 -0
- package/src/stt/types.ts +330 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +169 -40
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +1787 -342
- package/src/tools/browser/browser-manager.ts +81 -12
- package/src/tools/browser/browser-mode-constants.ts +12 -0
- package/src/tools/browser/browser-mode.ts +92 -0
- package/src/tools/browser/browser-status-constants.ts +33 -0
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1263 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +359 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1993 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +1007 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +744 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +868 -0
- package/src/tools/browser/cdp-client/errors.ts +49 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +148 -0
- package/src/tools/browser/cdp-client/factory.ts +914 -0
- package/src/tools/browser/cdp-client/index.ts +28 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +120 -0
- package/src/tools/credentials/vault.ts +35 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/network/web-fetch.ts +5 -2
- package/src/tools/network/web-search.ts +5 -2
- package/src/tools/permission-checker.ts +77 -82
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -0
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +2 -0
- package/src/tools/skills/sandbox-runner.ts +3 -2
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +15 -0
- package/src/tools/terminal/shell.ts +36 -20
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/tool-manifest.ts +21 -0
- package/src/tools/types.ts +19 -0
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tts/__tests__/provider-adapters.test.ts +834 -0
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
- package/src/tts/__tests__/provider-catalog.test.ts +183 -0
- package/src/tts/__tests__/provider-registry.test.ts +90 -0
- package/src/tts/provider-catalog.ts +201 -0
- package/src/tts/provider-registry.ts +73 -0
- package/src/tts/providers/deepgram-provider.ts +219 -0
- package/src/tts/providers/elevenlabs-provider.ts +211 -0
- package/src/tts/providers/fish-audio-provider.ts +183 -0
- package/src/tts/providers/index.ts +42 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +153 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/util/abort-reasons.ts +58 -0
- package/src/util/device-id.ts +32 -16
- package/src/util/errors.ts +9 -1
- package/src/util/platform.ts +63 -24
- package/src/util/pricing.ts +66 -3
- package/src/util/spawn.ts +1 -1
- package/src/util/truncate.ts +4 -2
- package/src/util/unicode.ts +201 -0
- package/src/version.ts +19 -24
- package/src/watcher/engine.ts +23 -0
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/migrations/003-seed-device-id.ts +9 -3
- package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
- package/src/workspace/migrations/029-seed-pkb.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +317 -0
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
- package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
- package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
- package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/top-level-renderer.ts +31 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/cli/commands/browser-relay.ts +0 -536
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/email/guardrails.ts +0 -221
- package/src/email/provider.ts +0 -117
- package/src/email/providers/agentmail.ts +0 -361
- package/src/email/providers/index.ts +0 -65
- package/src/email/service.ts +0 -384
- package/src/email/types.ts +0 -126
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/prompts/templates/USER.md +0 -13
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability token minting and verification for scoped, short-lived tokens
|
|
3
|
+
* issued to the chrome extension (and other thin clients) so they can submit
|
|
4
|
+
* results back to the runtime without a full guardian-bound JWT.
|
|
5
|
+
*
|
|
6
|
+
* Design:
|
|
7
|
+
* - Tokens are HMAC-SHA256 signed over a JSON claims payload.
|
|
8
|
+
* - Claims include a bound capability, guardian id, nonce, and expiry.
|
|
9
|
+
* - Signing uses a long-lived random secret persisted to
|
|
10
|
+
* `~/.vellum/protected/` with 0600 permissions. The protected
|
|
11
|
+
* directory sits outside the workspace per AGENTS.md: workspace
|
|
12
|
+
* directories must not hold security-sensitive material.
|
|
13
|
+
* - The secret is generated once on first launch and reused across
|
|
14
|
+
* subsequent daemon restarts so previously-minted tokens still verify.
|
|
15
|
+
* - Tests inject their own secret via `setCapabilityTokenSecretForTests`.
|
|
16
|
+
*
|
|
17
|
+
* The encoded token format is `<base64url(payload)>.<base64url(sig)>`.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
21
|
+
import {
|
|
22
|
+
chmodSync,
|
|
23
|
+
existsSync,
|
|
24
|
+
mkdirSync,
|
|
25
|
+
readFileSync,
|
|
26
|
+
renameSync,
|
|
27
|
+
unlinkSync,
|
|
28
|
+
writeFileSync,
|
|
29
|
+
} from "node:fs";
|
|
30
|
+
import { dirname, join } from "node:path";
|
|
31
|
+
|
|
32
|
+
import { getLogger } from "../util/logger.js";
|
|
33
|
+
import { getDataDir, getProtectedDir } from "../util/platform.js";
|
|
34
|
+
|
|
35
|
+
const log = getLogger("capability-tokens");
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Types
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
/** Capability identifiers that can be bound to a capability token. */
|
|
42
|
+
export type Capability = "host_browser_command";
|
|
43
|
+
|
|
44
|
+
/** Claims encoded in the signed payload. */
|
|
45
|
+
export interface CapabilityClaims {
|
|
46
|
+
capability: Capability;
|
|
47
|
+
guardianId: string;
|
|
48
|
+
/** 16-byte random nonce, hex-encoded. Prevents replay across fresh mints. */
|
|
49
|
+
nonce: string;
|
|
50
|
+
/** ms-since-epoch expiry. */
|
|
51
|
+
expiresAt: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** A freshly-minted capability token and its absolute expiry. */
|
|
55
|
+
export interface CapabilityToken {
|
|
56
|
+
token: string;
|
|
57
|
+
expiresAt: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Secret lifecycle
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
let _secret: Buffer | undefined;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns the canonical path where the capability-token secret is
|
|
68
|
+
* persisted: `~/.vellum/protected/capability-token-secret`. The protected
|
|
69
|
+
* directory is the canonical location for security-sensitive material
|
|
70
|
+
* and sits outside the workspace (which AGENTS.md forbids for secrets).
|
|
71
|
+
*/
|
|
72
|
+
function getSecretPath(): string {
|
|
73
|
+
return join(getProtectedDir(), "capability-token-secret");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Legacy path under `workspace/data/` where earlier builds persisted the
|
|
78
|
+
* capability-token secret. We keep this as a read-only migration source
|
|
79
|
+
* so existing deployments don't regenerate their secret (and invalidate
|
|
80
|
+
* every outstanding token) on upgrade — the first launch after the
|
|
81
|
+
* upgrade copies the legacy file into `getProtectedDir()` and removes it
|
|
82
|
+
* from the workspace.
|
|
83
|
+
*/
|
|
84
|
+
function getLegacySecretPath(): string {
|
|
85
|
+
return join(getDataDir(), "capability-token-secret");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Path overrides used by unit tests to drive the secret lifecycle
|
|
90
|
+
* without touching the real `~/.vellum/` tree. Production callers must
|
|
91
|
+
* omit this argument so the canonical paths (`getProtectedDir()` +
|
|
92
|
+
* `getDataDir()`) are used.
|
|
93
|
+
*/
|
|
94
|
+
export interface CapabilityTokenSecretPaths {
|
|
95
|
+
/** Protected-directory secret path (authoritative). */
|
|
96
|
+
secretPath: string;
|
|
97
|
+
/** Legacy workspace-directory secret path (migration source). */
|
|
98
|
+
legacySecretPath: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Load the capability-token secret from disk or generate and persist a new
|
|
103
|
+
* one. Atomically writes with mode 0o600 so the secret is not readable by
|
|
104
|
+
* other users on the same host.
|
|
105
|
+
*
|
|
106
|
+
* Migration: if the secret exists only at the legacy workspace path, copy
|
|
107
|
+
* it into the protected directory and delete the workspace copy so we do
|
|
108
|
+
* not leave security-sensitive material inside `workspace/`.
|
|
109
|
+
*
|
|
110
|
+
* The optional `paths` argument is for unit tests only — production
|
|
111
|
+
* callers must omit it and use the canonical `~/.vellum/protected/` /
|
|
112
|
+
* `~/.vellum/workspace/data/` paths.
|
|
113
|
+
*/
|
|
114
|
+
export function loadOrCreateCapabilityTokenSecret(
|
|
115
|
+
paths?: CapabilityTokenSecretPaths,
|
|
116
|
+
): Buffer {
|
|
117
|
+
const keyPath = paths?.secretPath ?? getSecretPath();
|
|
118
|
+
const legacyPath = paths?.legacySecretPath ?? getLegacySecretPath();
|
|
119
|
+
if (existsSync(keyPath)) {
|
|
120
|
+
try {
|
|
121
|
+
const raw = readFileSync(keyPath);
|
|
122
|
+
if (raw.length === 32) {
|
|
123
|
+
return raw;
|
|
124
|
+
}
|
|
125
|
+
log.warn(
|
|
126
|
+
{ keyPath, length: raw.length },
|
|
127
|
+
"capability token secret has unexpected length — regenerating",
|
|
128
|
+
);
|
|
129
|
+
} catch (err) {
|
|
130
|
+
log.warn(
|
|
131
|
+
{ err, keyPath },
|
|
132
|
+
"Failed to read capability token secret — regenerating",
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Attempt to migrate a legacy workspace-directory secret before we
|
|
138
|
+
// generate a fresh one. If this succeeds we end up with the legacy
|
|
139
|
+
// secret persisted at the protected path and the workspace copy
|
|
140
|
+
// removed, preserving every outstanding token across the upgrade.
|
|
141
|
+
const migrated = migrateLegacyCapabilityTokenSecret(keyPath, legacyPath);
|
|
142
|
+
if (migrated) {
|
|
143
|
+
return migrated;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const fresh = randomBytes(32);
|
|
147
|
+
writeSecretAtomic(keyPath, fresh);
|
|
148
|
+
log.info("Capability token secret generated and persisted");
|
|
149
|
+
return fresh;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Write `secret` to `keyPath` atomically with mode 0o600. Ensures the
|
|
154
|
+
* parent directory exists.
|
|
155
|
+
*/
|
|
156
|
+
function writeSecretAtomic(keyPath: string, secret: Buffer): void {
|
|
157
|
+
const dir = dirname(keyPath);
|
|
158
|
+
if (!existsSync(dir)) {
|
|
159
|
+
mkdirSync(dir, { recursive: true });
|
|
160
|
+
}
|
|
161
|
+
const tmpPath = `${keyPath}.tmp.${process.pid}`;
|
|
162
|
+
writeFileSync(tmpPath, secret, { mode: 0o600 });
|
|
163
|
+
renameSync(tmpPath, keyPath);
|
|
164
|
+
try {
|
|
165
|
+
chmodSync(keyPath, 0o600);
|
|
166
|
+
} catch (err) {
|
|
167
|
+
log.warn(
|
|
168
|
+
{ err, keyPath },
|
|
169
|
+
"Failed to chmod capability token secret after write",
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* If a pre-migration capability token secret exists under the workspace
|
|
176
|
+
* data directory, copy it into the protected directory and remove the
|
|
177
|
+
* workspace copy. Returns the migrated secret if migration ran
|
|
178
|
+
* successfully, or `undefined` if there was nothing to migrate or the
|
|
179
|
+
* migration failed.
|
|
180
|
+
*/
|
|
181
|
+
function migrateLegacyCapabilityTokenSecret(
|
|
182
|
+
secretPath: string,
|
|
183
|
+
legacyPath: string,
|
|
184
|
+
): Buffer | undefined {
|
|
185
|
+
if (!existsSync(legacyPath)) {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
const raw = readFileSync(legacyPath);
|
|
190
|
+
if (raw.length !== 32) {
|
|
191
|
+
log.warn(
|
|
192
|
+
{ legacyPath, length: raw.length },
|
|
193
|
+
"legacy capability token secret has unexpected length — ignoring",
|
|
194
|
+
);
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
writeSecretAtomic(secretPath, raw);
|
|
198
|
+
try {
|
|
199
|
+
unlinkSync(legacyPath);
|
|
200
|
+
} catch (err) {
|
|
201
|
+
log.warn(
|
|
202
|
+
{ err, legacyPath },
|
|
203
|
+
"Failed to remove legacy workspace capability token secret after migration",
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
log.info(
|
|
207
|
+
{ from: legacyPath, to: secretPath },
|
|
208
|
+
"Migrated capability token secret out of workspace into protected directory",
|
|
209
|
+
);
|
|
210
|
+
return raw;
|
|
211
|
+
} catch (err) {
|
|
212
|
+
log.warn(
|
|
213
|
+
{ err, legacyPath },
|
|
214
|
+
"Failed to migrate legacy capability token secret — regenerating",
|
|
215
|
+
);
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Initialize the module-level secret. Called once at daemon startup. Safe
|
|
222
|
+
* to call multiple times — subsequent calls overwrite the cached value
|
|
223
|
+
* (useful in tests that reset state).
|
|
224
|
+
*/
|
|
225
|
+
export function initCapabilityTokenSecret(secret: Buffer): void {
|
|
226
|
+
if (secret.length !== 32) {
|
|
227
|
+
throw new Error(
|
|
228
|
+
`capability token secret must be 32 bytes, got ${secret.length}`,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
_secret = secret;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Test-only helper to inject a deterministic secret.
|
|
236
|
+
*/
|
|
237
|
+
export function setCapabilityTokenSecretForTests(secret: Buffer): void {
|
|
238
|
+
_secret = secret;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Reset the cached secret. Test-only — exposed so test isolation can
|
|
243
|
+
* force a reload from disk.
|
|
244
|
+
*/
|
|
245
|
+
export function resetCapabilityTokenSecretForTests(): void {
|
|
246
|
+
_secret = undefined;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function getSecret(): Buffer {
|
|
250
|
+
if (_secret) return _secret;
|
|
251
|
+
if (process.env.NODE_ENV === "test") {
|
|
252
|
+
_secret = randomBytes(32);
|
|
253
|
+
return _secret;
|
|
254
|
+
}
|
|
255
|
+
// Lazy load — daemon startup is expected to call
|
|
256
|
+
// `initCapabilityTokenSecret(loadOrCreateCapabilityTokenSecret())` but
|
|
257
|
+
// we fall back to a disk load here so unit tests and early call sites
|
|
258
|
+
// don't have to depend on startup ordering.
|
|
259
|
+
_secret = loadOrCreateCapabilityTokenSecret();
|
|
260
|
+
return _secret;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ---------------------------------------------------------------------------
|
|
264
|
+
// Mint / verify
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
266
|
+
|
|
267
|
+
const DEFAULT_TTL_MS = 30 * 60 * 1000; // 30 minutes
|
|
268
|
+
|
|
269
|
+
function base64urlEncode(buf: Buffer): string {
|
|
270
|
+
return buf
|
|
271
|
+
.toString("base64")
|
|
272
|
+
.replace(/\+/g, "-")
|
|
273
|
+
.replace(/\//g, "_")
|
|
274
|
+
.replace(/=+$/, "");
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function base64urlDecode(s: string): Buffer {
|
|
278
|
+
const pad = s.length % 4 === 0 ? 0 : 4 - (s.length % 4);
|
|
279
|
+
const b64 = s.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat(pad);
|
|
280
|
+
return Buffer.from(b64, "base64");
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function sign(payload: string, secret: Buffer): string {
|
|
284
|
+
return base64urlEncode(createHmac("sha256", secret).update(payload).digest());
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Mint a capability token bound to the `host_browser_command` capability
|
|
289
|
+
* for the given guardian id. Default TTL is 30 minutes.
|
|
290
|
+
*/
|
|
291
|
+
export function mintHostBrowserCapability(
|
|
292
|
+
guardianId: string,
|
|
293
|
+
ttlMs: number = DEFAULT_TTL_MS,
|
|
294
|
+
): CapabilityToken {
|
|
295
|
+
const expiresAt = Date.now() + ttlMs;
|
|
296
|
+
const nonce = randomBytes(16).toString("hex");
|
|
297
|
+
const claims: CapabilityClaims = {
|
|
298
|
+
capability: "host_browser_command",
|
|
299
|
+
guardianId,
|
|
300
|
+
nonce,
|
|
301
|
+
expiresAt,
|
|
302
|
+
};
|
|
303
|
+
const payload = base64urlEncode(Buffer.from(JSON.stringify(claims), "utf8"));
|
|
304
|
+
const sig = sign(payload, getSecret());
|
|
305
|
+
return { token: `${payload}.${sig}`, expiresAt };
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Verify a capability token minted by `mintHostBrowserCapability`.
|
|
310
|
+
*
|
|
311
|
+
* Returns the decoded claims on success or null if the signature is
|
|
312
|
+
* invalid, the payload is malformed, the token has expired, or the bound
|
|
313
|
+
* capability is not `host_browser_command`.
|
|
314
|
+
*
|
|
315
|
+
* Signature comparison uses `timingSafeEqual` to avoid leaking the secret
|
|
316
|
+
* through timing side channels.
|
|
317
|
+
*
|
|
318
|
+
* The `/v1/browser-relay` WebSocket upgrade handler in `http-server.ts`
|
|
319
|
+
* (`handleBrowserRelayUpgrade`) calls this to authenticate self-hosted
|
|
320
|
+
* chrome extensions on the capability-token branch before falling
|
|
321
|
+
* through to the JWT compatibility path. The `/v1/host-browser-result`
|
|
322
|
+
* POST route may also call it (see that route's auth handling) when a
|
|
323
|
+
* result is posted back with a capability-token bearer instead of a
|
|
324
|
+
* guardian-bound JWT.
|
|
325
|
+
*/
|
|
326
|
+
export function verifyHostBrowserCapability(
|
|
327
|
+
token: string,
|
|
328
|
+
): CapabilityClaims | null {
|
|
329
|
+
if (typeof token !== "string") return null;
|
|
330
|
+
const dot = token.indexOf(".");
|
|
331
|
+
if (dot < 0) return null;
|
|
332
|
+
const payload = token.slice(0, dot);
|
|
333
|
+
const sig = token.slice(dot + 1);
|
|
334
|
+
if (!payload || !sig) return null;
|
|
335
|
+
|
|
336
|
+
const expected = sign(payload, getSecret());
|
|
337
|
+
const a = Buffer.from(sig, "utf8");
|
|
338
|
+
const b = Buffer.from(expected, "utf8");
|
|
339
|
+
if (a.length !== b.length) return null;
|
|
340
|
+
if (!timingSafeEqual(a, b)) return null;
|
|
341
|
+
|
|
342
|
+
let claims: CapabilityClaims;
|
|
343
|
+
try {
|
|
344
|
+
claims = JSON.parse(
|
|
345
|
+
base64urlDecode(payload).toString("utf8"),
|
|
346
|
+
) as CapabilityClaims;
|
|
347
|
+
} catch {
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (!claims || typeof claims !== "object") return null;
|
|
352
|
+
if (claims.capability !== "host_browser_command") return null;
|
|
353
|
+
if (typeof claims.guardianId !== "string" || claims.guardianId.length === 0) {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
if (typeof claims.nonce !== "string" || claims.nonce.length === 0) {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
if (typeof claims.expiresAt !== "number" || claims.expiresAt <= Date.now()) {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
return claims;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// ---------------------------------------------------------------------------
|
|
366
|
+
// Dev-only fallback token file
|
|
367
|
+
// ---------------------------------------------------------------------------
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Path to the dev-pairing fallback token file. The runtime writes a freshly
|
|
371
|
+
* minted capability token to this location on daemon startup so developers
|
|
372
|
+
* can manually pair the chrome extension without wiring the native
|
|
373
|
+
* messaging helper. Production users should pair via the native helper
|
|
374
|
+
* (PRs 7/12/13).
|
|
375
|
+
*/
|
|
376
|
+
export function getDaemonTokenFilePath(): string {
|
|
377
|
+
// Stored under the per-instance protected directory. Both writer and
|
|
378
|
+
// reader run in the same daemon process, so they resolve the same
|
|
379
|
+
// per-instance path (honoring BASE_DATA_DIR for multi-instance setups).
|
|
380
|
+
// This is a dev-only convenience path — production pairing goes through
|
|
381
|
+
// the native messaging flow.
|
|
382
|
+
return join(getProtectedDir(), "daemon-token");
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Write a freshly-minted capability token to the per-instance dev token
|
|
387
|
+
* file (see `getDaemonTokenFilePath`) with 0600 permissions. Swallows
|
|
388
|
+
* errors so a failure here never blocks daemon startup — this is a
|
|
389
|
+
* dev-convenience path, not a production auth requirement.
|
|
390
|
+
*/
|
|
391
|
+
export function writeDaemonTokenFallback(guardianId: string): void {
|
|
392
|
+
try {
|
|
393
|
+
const { token } = mintHostBrowserCapability(guardianId);
|
|
394
|
+
const filePath = getDaemonTokenFilePath();
|
|
395
|
+
const dir = dirname(filePath);
|
|
396
|
+
if (!existsSync(dir)) {
|
|
397
|
+
mkdirSync(dir, { recursive: true });
|
|
398
|
+
}
|
|
399
|
+
const tmpPath = `${filePath}.tmp.${process.pid}`;
|
|
400
|
+
writeFileSync(tmpPath, token, { mode: 0o600 });
|
|
401
|
+
renameSync(tmpPath, filePath);
|
|
402
|
+
try {
|
|
403
|
+
chmodSync(filePath, 0o600);
|
|
404
|
+
} catch {
|
|
405
|
+
// best-effort
|
|
406
|
+
}
|
|
407
|
+
log.info({ filePath }, "Dev capability token written to daemon-token file");
|
|
408
|
+
} catch (err) {
|
|
409
|
+
log.warn(
|
|
410
|
+
{ err },
|
|
411
|
+
"Failed to write dev capability token file; manual pairing still available via /v1/browser-extension-pair",
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import { addRule } from "../permissions/trust-store.js";
|
|
13
13
|
import type { UserDecision } from "../permissions/types.js";
|
|
14
|
+
import { isPermissionControlsV2Enabled } from "../permissions/v2-consent-policy.js";
|
|
14
15
|
import { getTool } from "../tools/registry.js";
|
|
15
16
|
import { composeApprovalMessage } from "./approval-message-composer.js";
|
|
16
17
|
import type {
|
|
@@ -22,6 +23,7 @@ import type {
|
|
|
22
23
|
import { toApprovalActionOptions } from "./channel-approval-types.js";
|
|
23
24
|
import {
|
|
24
25
|
buildDecisionActions,
|
|
26
|
+
buildOneTimeDecisionActions,
|
|
25
27
|
buildPlainTextFallback,
|
|
26
28
|
} from "./guardian-decision-types.js";
|
|
27
29
|
import * as pendingInteractions from "./pending-interactions.js";
|
|
@@ -92,9 +94,11 @@ function buildPromptFromApprovalInfo(
|
|
|
92
94
|
toolName: info.toolName,
|
|
93
95
|
});
|
|
94
96
|
|
|
95
|
-
const decisionActions =
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
const decisionActions = isPermissionControlsV2Enabled()
|
|
98
|
+
? buildOneTimeDecisionActions()
|
|
99
|
+
: buildDecisionActions({
|
|
100
|
+
persistentDecisionsAllowed: info.persistentDecisionsAllowed,
|
|
101
|
+
});
|
|
98
102
|
const actions = toApprovalActionOptions(decisionActions);
|
|
99
103
|
const plainTextFallback = buildPlainTextFallback(promptText, decisionActions);
|
|
100
104
|
|
|
@@ -138,6 +142,10 @@ export function buildApprovalUIMetadata(
|
|
|
138
142
|
* the permission pipeline can activate the appropriate override.
|
|
139
143
|
*/
|
|
140
144
|
function mapApprovalActionToUserDecision(action: ApprovalAction): UserDecision {
|
|
145
|
+
if (isPermissionControlsV2Enabled()) {
|
|
146
|
+
return action === "reject" ? "deny" : "allow";
|
|
147
|
+
}
|
|
148
|
+
|
|
141
149
|
switch (action) {
|
|
142
150
|
case "reject":
|
|
143
151
|
return "deny";
|
|
@@ -182,7 +190,10 @@ export function handleChannelDecision(
|
|
|
182
190
|
: pending[0];
|
|
183
191
|
if (!info) return { applied: false };
|
|
184
192
|
|
|
185
|
-
if (
|
|
193
|
+
if (
|
|
194
|
+
!isPermissionControlsV2Enabled() &&
|
|
195
|
+
decision.action === "approve_always"
|
|
196
|
+
) {
|
|
186
197
|
// Only persist a trust rule when the confirmation explicitly allows persistence
|
|
187
198
|
// AND provides explicit allowlist/scope options. Without explicit options we
|
|
188
199
|
// would create a blanket "**"/"everywhere" rule, which is a security risk.
|
|
@@ -264,7 +275,9 @@ export function buildGuardianApprovalPrompt(
|
|
|
264
275
|
requesterIdentifier,
|
|
265
276
|
});
|
|
266
277
|
|
|
267
|
-
const decisionActions =
|
|
278
|
+
const decisionActions = isPermissionControlsV2Enabled()
|
|
279
|
+
? buildOneTimeDecisionActions()
|
|
280
|
+
: buildDecisionActions({ forGuardianOnBehalf: true });
|
|
268
281
|
const actions = toApprovalActionOptions(decisionActions);
|
|
269
282
|
const plainTextFallback = buildPlainTextFallback(promptText, decisionActions);
|
|
270
283
|
|
|
@@ -58,7 +58,7 @@ export interface ChannelInviteAdapter {
|
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* Resolve the channel-specific handle to reach the assistant (e.g.
|
|
61
|
-
* "@botName", "+15551234567", "hello@
|
|
61
|
+
* "@botName", "+15551234567", "hello@vellum.me").
|
|
62
62
|
* Returns `undefined` when the handle cannot be resolved (e.g.
|
|
63
63
|
* credentials not yet configured).
|
|
64
64
|
*/
|
|
@@ -2,17 +2,16 @@
|
|
|
2
2
|
* Email channel invite adapter.
|
|
3
3
|
*
|
|
4
4
|
* Resolves the assistant's email address for use in invite instructions.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* generic "on Email" wording instead of a misleading stub address.
|
|
5
|
+
* Reads the address from workspace config (`email.address`). Returns
|
|
6
|
+
* `undefined` when no address is configured, which causes the invite
|
|
7
|
+
* instruction generator to emit generic "on Email" wording.
|
|
9
8
|
*
|
|
10
9
|
* Email invites use the universal 6-digit code path for redemption, so
|
|
11
10
|
* this adapter only implements `resolveChannelHandleAsync` — no
|
|
12
11
|
* `buildShareLink` or `extractInboundToken` needed.
|
|
13
12
|
*/
|
|
14
13
|
|
|
15
|
-
import {
|
|
14
|
+
import { getNestedValue, loadRawConfig } from "../../config/loader.js";
|
|
16
15
|
import type { ChannelInviteAdapter } from "../channel-invite-transport.js";
|
|
17
16
|
|
|
18
17
|
// ---------------------------------------------------------------------------
|
|
@@ -23,6 +22,15 @@ export const emailInviteAdapter: ChannelInviteAdapter = {
|
|
|
23
22
|
channel: "email",
|
|
24
23
|
|
|
25
24
|
async resolveChannelHandleAsync(): Promise<string | undefined> {
|
|
26
|
-
|
|
25
|
+
try {
|
|
26
|
+
const raw = loadRawConfig();
|
|
27
|
+
const address = getNestedValue(raw, "email.address");
|
|
28
|
+
if (typeof address === "string" && address.length > 0) {
|
|
29
|
+
return address;
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
// Config unavailable
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
27
35
|
},
|
|
28
36
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { resolveTwilioPhoneNumber } from "../calls/twilio-config.js";
|
|
2
2
|
import { hasTwilioCredentials } from "../calls/twilio-rest.js";
|
|
3
3
|
import { getChannelInvitePolicy } from "../channels/config.js";
|
|
4
|
-
import { getConfig, loadRawConfig } from "../config/loader.js";
|
|
4
|
+
import { getConfig, getNestedValue, loadRawConfig } from "../config/loader.js";
|
|
5
5
|
import { isEmailEnabled } from "../email/feature-gate.js";
|
|
6
|
-
import { getEmailService } from "../email/service.js";
|
|
7
6
|
import { shouldUsePlatformCallbacks } from "../inbound/platform-callback-registration.js";
|
|
8
7
|
import { credentialKey } from "../security/credential-key.js";
|
|
9
8
|
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
@@ -81,8 +80,9 @@ async function checkCredential(
|
|
|
81
80
|
|
|
82
81
|
/** Check that public ingress is configured and enabled. */
|
|
83
82
|
function checkIngress(allowManagedCallbacks = false): ReadinessCheckResult {
|
|
84
|
-
const { configured, usesManagedCallbacks } =
|
|
85
|
-
|
|
83
|
+
const { configured, usesManagedCallbacks } = hasWebhookRoutingConfigured(
|
|
84
|
+
allowManagedCallbacks,
|
|
85
|
+
);
|
|
86
86
|
return check(
|
|
87
87
|
"ingress",
|
|
88
88
|
configured,
|
|
@@ -150,17 +150,13 @@ const telegramProbe: ChannelProbe = {
|
|
|
150
150
|
const emailProbe: ChannelProbe = {
|
|
151
151
|
channel: "email",
|
|
152
152
|
async runLocalChecks(): Promise<ReadinessCheckResult[]> {
|
|
153
|
-
const hasApiKey = !!(
|
|
154
|
-
(await getSecureKeyAsync("agentmail")) ||
|
|
155
|
-
(await getSecureKeyAsync(credentialKey("agentmail", "api_key")))
|
|
156
|
-
);
|
|
157
153
|
const invitePolicy = getChannelInvitePolicy("email");
|
|
158
154
|
return [
|
|
159
155
|
check(
|
|
160
|
-
"
|
|
161
|
-
|
|
162
|
-
"
|
|
163
|
-
"
|
|
156
|
+
"platform_email",
|
|
157
|
+
true,
|
|
158
|
+
"Email is handled through the platform (Mailgun)",
|
|
159
|
+
"Email requires platform registration",
|
|
164
160
|
),
|
|
165
161
|
check(
|
|
166
162
|
"invite_policy",
|
|
@@ -172,23 +168,17 @@ const emailProbe: ChannelProbe = {
|
|
|
172
168
|
];
|
|
173
169
|
},
|
|
174
170
|
async runRemoteChecks(): Promise<ReadinessCheckResult[]> {
|
|
175
|
-
// Only worth checking if the API key is present
|
|
176
|
-
const hasApiKey = !!(
|
|
177
|
-
(await getSecureKeyAsync("agentmail")) ||
|
|
178
|
-
(await getSecureKeyAsync(credentialKey("agentmail", "api_key")))
|
|
179
|
-
);
|
|
180
|
-
if (!hasApiKey) return [];
|
|
181
|
-
|
|
182
171
|
try {
|
|
183
|
-
const
|
|
184
|
-
const
|
|
172
|
+
const raw = loadRawConfig();
|
|
173
|
+
const address = getNestedValue(raw, "email.address");
|
|
174
|
+
const hasInbox = typeof address === "string" && address.length > 0;
|
|
185
175
|
return [
|
|
186
176
|
{
|
|
187
177
|
name: "inbox_configured",
|
|
188
178
|
passed: hasInbox,
|
|
189
179
|
message: hasInbox
|
|
190
180
|
? `Inbox address is configured (${address})`
|
|
191
|
-
: "No inbox address configured —
|
|
181
|
+
: "No inbox address configured — register one with: assistant email register <username>",
|
|
192
182
|
},
|
|
193
183
|
];
|
|
194
184
|
} catch (err) {
|