@vellumai/assistant 0.6.3 → 0.6.5
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/.prettierignore +5 -0
- package/ARCHITECTURE.md +298 -39
- package/Dockerfile +14 -3
- package/README.md +3 -4
- package/bun.lock +13 -16
- package/docs/architecture/integrations.md +1 -20
- package/docs/architecture/security.md +16 -16
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/error-handling.md +111 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +121 -0
- package/knip.json +20 -3
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +5 -4
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
- package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
- package/node_modules/@vellumai/credential-storage/package.json +2 -2
- package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
- package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
- package/node_modules/@vellumai/egress-proxy/package.json +2 -2
- package/openapi.yaml +1094 -72
- package/package.json +9 -8
- package/scripts/generate-openapi.ts +50 -12
- package/scripts/test.sh +73 -18
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
- package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
- package/src/__tests__/agent-loop.test.ts +235 -1
- package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
- package/src/__tests__/anthropic-provider.test.ts +434 -12
- package/src/__tests__/approval-cascade.test.ts +31 -10
- package/src/__tests__/approval-routes-http.test.ts +134 -10
- package/src/__tests__/assistant-attachments.test.ts +44 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
- 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 +12 -1
- package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
- package/src/__tests__/browser-skill-endstate.test.ts +52 -159
- package/src/__tests__/btw-routes.test.ts +54 -1
- package/src/__tests__/call-controller.test.ts +582 -22
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +27 -4
- package/src/__tests__/catalog-files.test.ts +138 -0
- package/src/__tests__/channel-approval-routes.test.ts +4 -4
- 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__/channel-reply-delivery.test.ts +300 -2
- package/src/__tests__/checker.test.ts +576 -502
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/config-analysis.test.ts +83 -0
- package/src/__tests__/config-loader-backfill.test.ts +174 -0
- package/src/__tests__/config-loader-corrupt.test.ts +183 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +1458 -198
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +45 -10
- package/src/__tests__/contact-store-user-file.test.ts +511 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +618 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +32 -16
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +62 -17
- package/src/__tests__/conversation-agent-loop.test.ts +510 -84
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +165 -9
- package/src/__tests__/conversation-error.test.ts +102 -1
- package/src/__tests__/conversation-history-web-search.test.ts +17 -4
- package/src/__tests__/conversation-init.benchmark.test.ts +42 -1
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +32 -16
- package/src/__tests__/conversation-process-callsite.test.ts +306 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +32 -16
- package/src/__tests__/conversation-queue.test.ts +932 -76
- package/src/__tests__/conversation-routes-disk-view.test.ts +299 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2790 -55
- package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
- package/src/__tests__/conversation-skill-tools.test.ts +12 -143
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +120 -34
- package/src/__tests__/conversation-slash-unknown.test.ts +32 -16
- package/src/__tests__/conversation-speed-override.test.ts +30 -11
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -2
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-unread-route.test.ts +2 -2
- package/src/__tests__/conversation-usage.test.ts +3 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
- package/src/__tests__/conversation-workspace-injection.test.ts +45 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +46 -16
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +8 -3
- package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
- package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
- package/src/__tests__/credential-vault-unit.test.ts +495 -3
- package/src/__tests__/credentials-cli.test.ts +32 -16
- package/src/__tests__/cross-provider-web-search.test.ts +230 -35
- package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
- package/src/__tests__/delete-propagation.test.ts +437 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/dm-backfill.test.ts +417 -0
- package/src/__tests__/dm-persistence.test.ts +227 -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__/edit-propagation.test.ts +280 -0
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/ephemeral-permissions.test.ts +93 -3
- package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
- package/src/__tests__/estimator-calibration.test.ts +213 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +101 -15
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +64 -3
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/guardian-grant-minting.test.ts +8 -0
- package/src/__tests__/headless-browser-interactions.test.ts +44 -1
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +142 -5
- package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
- package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
- package/src/__tests__/heartbeat-service.test.ts +166 -32
- package/src/__tests__/home-state-routes.test.ts +162 -0
- package/src/__tests__/host-bash-proxy.test.ts +0 -5
- package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
- package/src/__tests__/host-cu-proxy.test.ts +0 -5
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/intent-routing.test.ts +1 -40
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/llm-catalog-parity.test.ts +174 -0
- package/src/__tests__/llm-context-normalization.test.ts +609 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-resolver.test.ts +214 -0
- package/src/__tests__/llm-schema.test.ts +223 -0
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/managed-proxy-context.test.ts +6 -2
- 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__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-export-http.test.ts +6 -6
- package/src/__tests__/migration-import-commit-http.test.ts +8 -6
- package/src/__tests__/migration-import-from-url.test.ts +684 -0
- 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 +10 -84
- package/src/__tests__/notification-decision-fallback.test.ts +0 -10
- package/src/__tests__/notification-decision-identity.test.ts +0 -9
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
- package/src/__tests__/oauth-apps-routes.test.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +2 -0
- package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
- package/src/__tests__/oauth-providers-routes.test.ts +2 -0
- package/src/__tests__/oauth-store.test.ts +95 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +257 -9
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/onboarding-template-contract.test.ts +6 -13
- package/src/__tests__/openai-provider.test.ts +183 -0
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1501 -0
- package/src/__tests__/openrouter-provider-only.test.ts +135 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -1
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +224 -3
- package/src/__tests__/profiler-routes.test.ts +1 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
- package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
- package/src/__tests__/provider-error-scenarios.test.ts +135 -6
- package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
- package/src/__tests__/provider-registry-ollama.test.ts +1 -2
- package/src/__tests__/proxy-approval-callback.test.ts +0 -1
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/reaction-persistence.test.ts +560 -0
- 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 +424 -6
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
- package/src/__tests__/risk-classifier-parity.test.ts +230 -0
- package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-ingress-http.test.ts +28 -0
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
- package/src/__tests__/secret-scanner-executor.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +34 -2
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +80 -0
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/shell-parser-property.test.ts +13 -13
- package/src/__tests__/skill-cache-store.test.ts +182 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
- package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
- package/src/__tests__/skills.test.ts +19 -30
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +564 -1
- package/src/__tests__/slack-skill.test.ts +3 -8
- package/src/__tests__/starter-bundle.test.ts +35 -0
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
- package/src/__tests__/suggestion-routes.test.ts +160 -3
- package/src/__tests__/system-prompt.test.ts +126 -53
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +26 -7
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -49
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +10 -6
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +88 -113
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/trust-store.test.ts +442 -103
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- 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-job.test.ts +389 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/verification-control-plane-policy.test.ts +5 -22
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/voice-session-bridge.test.ts +39 -0
- package/src/__tests__/volume-security-guard.test.ts +3 -2
- package/src/__tests__/web-search-history.test.ts +337 -0
- 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-039-drop-legacy-llm-keys.test.ts +343 -0
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -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-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +1 -11
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +251 -19
- package/src/avatar/resvg-lazy.test.ts +136 -0
- package/src/avatar/resvg-lazy.ts +82 -9
- package/src/avatar/traits-png-sync.ts +21 -1
- 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/__tests__/operations.test.ts +163 -0
- package/src/browser/identifiers.ts +51 -0
- package/src/browser/operations.ts +660 -0
- package/src/browser/types.ts +81 -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/guardian-question-copy.ts +2 -2
- 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 +9 -1
- package/src/channels/types.ts +16 -0
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/browser.test.ts +554 -0
- package/src/cli/commands/__tests__/cache.test.ts +623 -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 +28 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +130 -5
- 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/__tests__/image-generation.test.ts +666 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
- package/src/cli/commands/__tests__/task.test.ts +913 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
- package/src/cli/commands/__tests__/ui.test.ts +1215 -0
- package/src/cli/commands/__tests__/watchers.test.ts +716 -0
- package/src/cli/commands/attachment.ts +182 -0
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +90 -0
- package/src/cli/commands/credentials.ts +0 -1
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +308 -16
- package/src/cli/commands/image-generation.ts +300 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +15 -0
- package/src/cli/commands/oauth/shared.ts +2 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -10
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -2
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -1
- package/src/cli/commands/stt.ts +339 -0
- package/src/cli/commands/task.ts +795 -0
- package/src/cli/commands/trust.ts +50 -19
- package/src/cli/commands/tts.ts +273 -0
- package/src/cli/commands/ui.ts +670 -0
- package/src/cli/commands/watchers.ts +509 -0
- package/src/cli/lib/daemon-credential-client.ts +0 -19
- package/src/cli/program.ts +53 -8
- package/src/cli.ts +0 -37
- 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/references/CUSTOM_ROUTES.md +37 -1
- package/src/config/bundled-skills/contacts/SKILL.md +2 -2
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
- 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/services/reduce.ts +1 -1
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -2
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +28 -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/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 +0 -167
- package/src/config/env-registry.ts +24 -0
- package/src/config/env.ts +39 -10
- package/src/config/feature-flag-registry.json +63 -15
- package/src/config/llm-resolver.ts +128 -0
- package/src/config/loader.ts +220 -22
- package/src/config/raw-config-utils.ts +30 -2
- package/src/config/sanitize-for-transfer.ts +35 -0
- package/src/config/schema.ts +65 -51
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +32 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -30
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +49 -14
- package/src/config/schemas/heartbeat.ts +27 -10
- package/src/config/schemas/host-browser.ts +47 -1
- package/src/config/schemas/inference.ts +3 -23
- package/src/config/schemas/llm.ts +318 -0
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/memory-processing.ts +1 -9
- package/src/config/schemas/notifications.ts +4 -11
- package/src/config/schemas/platform.ts +3 -9
- package/src/config/schemas/security.ts +33 -0
- package/src/config/schemas/services.ts +53 -4
- package/src/config/schemas/stt.ts +60 -0
- package/src/config/schemas/tts.ts +283 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skills.ts +6 -2
- package/src/config/types.ts +4 -0
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/__tests__/compact-prompt.test.ts +45 -0
- package/src/context/__tests__/microcompact.test.ts +805 -0
- package/src/context/estimator-calibration.ts +136 -0
- package/src/context/microcompact.ts +443 -0
- package/src/context/post-turn-tool-result-truncation.ts +3 -2
- package/src/context/prompts/compact.md +12 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +272 -35
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/executable-discovery.ts +23 -2
- package/src/credential-execution/process-manager.test.ts +109 -0
- package/src/credential-execution/process-manager.ts +96 -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 +17 -8
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/approval-generators.ts +29 -4
- package/src/daemon/assistant-attachments.ts +24 -13
- package/src/daemon/classifier.ts +2 -2
- package/src/daemon/config-watcher.ts +99 -6
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +85 -12
- package/src/daemon/conversation-agent-loop.ts +563 -104
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +46 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +85 -11
- package/src/daemon/conversation-messaging.ts +110 -7
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +591 -23
- package/src/daemon/conversation-queue-manager.ts +27 -0
- package/src/daemon/conversation-runtime-assembly.ts +769 -28
- package/src/daemon/conversation-slash.ts +38 -2
- package/src/daemon/conversation-surfaces.ts +483 -5
- package/src/daemon/conversation-tool-setup.ts +35 -5
- package/src/daemon/conversation-usage.ts +8 -5
- package/src/daemon/conversation.ts +193 -47
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/guardian-action-generators.ts +34 -14
- package/src/daemon/handlers/config-model.test.ts +86 -0
- package/src/daemon/handlers/config-model.ts +54 -12
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +13 -3
- package/src/daemon/handlers/shared.ts +51 -1
- package/src/daemon/handlers/skills.ts +323 -79
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/host-browser-proxy.ts +2 -1
- package/src/daemon/lifecycle.ts +185 -26
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/conversations.ts +48 -1
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +23 -1
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +16 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/trust.ts +0 -2
- package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
- package/src/daemon/pkb-context-tracker.test.ts +169 -0
- package/src/daemon/pkb-context-tracker.ts +125 -0
- package/src/daemon/pkb-reminder-builder.test.ts +70 -0
- package/src/daemon/pkb-reminder-builder.ts +31 -0
- package/src/daemon/providers-setup.ts +6 -0
- package/src/daemon/server.ts +463 -10
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +9 -9
- package/src/daemon/watch-handler.ts +4 -4
- package/src/daemon/web-search-history.ts +126 -0
- package/src/email/html-renderer.ts +76 -0
- package/src/events/domain-events.ts +0 -1
- package/src/filing/filing-service.ts +9 -10
- package/src/heartbeat/heartbeat-service.ts +156 -22
- 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 +222 -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 +442 -0
- package/src/home/assistant-feed-authoring.ts +128 -0
- package/src/home/emit-feed-event.ts +162 -0
- package/src/home/feed-scheduler.ts +263 -0
- package/src/home/feed-types.ts +235 -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 +413 -0
- package/src/home/suggested-prompts.ts +101 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +12 -3
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
- package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/__tests__/socket-path.test.ts +73 -0
- package/src/ipc/__tests__/task-ipc.test.ts +577 -0
- package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
- package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
- package/src/ipc/cli-client.ts +152 -0
- package/src/ipc/cli-server.ts +252 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +61 -0
- package/src/ipc/routes/browser.ts +96 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/index.ts +21 -0
- package/src/ipc/routes/task-queue.ts +226 -0
- package/src/ipc/routes/task.ts +173 -0
- package/src/ipc/routes/ui-request.ts +50 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +100 -0
- 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 +233 -0
- package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/admin.ts +18 -0
- package/src/memory/app-store.ts +1 -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 +74 -0
- package/src/memory/conversation-attention-store.ts +13 -6
- package/src/memory/conversation-crud.ts +199 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +65 -1
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/conversation-title-service.ts +7 -4
- package/src/memory/db-init.ts +8 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/graph/compaction.ts +299 -0
- package/src/memory/graph/consolidation.ts +4 -4
- package/src/memory/graph/conversation-graph-memory.ts +104 -29
- package/src/memory/graph/extraction.test.ts +295 -2
- package/src/memory/graph/extraction.ts +181 -51
- package/src/memory/graph/graph-search.test.ts +92 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.test.ts +459 -0
- package/src/memory/graph/retriever.ts +257 -66
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/store.ts +41 -0
- package/src/memory/graph/tool-handlers.ts +27 -0
- package/src/memory/graph/tools.ts +6 -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 +39 -30
- package/src/memory/job-handlers/summarization.ts +2 -2
- package/src/memory/job-utils.ts +7 -1
- package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
- package/src/memory/jobs/embed-pkb-file.ts +54 -0
- package/src/memory/jobs-store.ts +106 -5
- package/src/memory/jobs-worker.ts +26 -9
- package/src/memory/llm-usage-store.ts +92 -56
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- 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/222-strip-placeholder-sentinels-from-messages.ts +82 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-index.test.ts +368 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +438 -0
- package/src/memory/pkb/pkb-search.ts +137 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.ts +122 -1
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/oauth.ts +3 -0
- package/src/memory/slack-thread-store.ts +37 -0
- package/src/memory/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/adapter.ts +6 -16
- package/src/messaging/providers/gmail/client.ts +79 -6
- package/src/messaging/providers/gmail/types.ts +7 -0
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +155 -38
- package/src/messaging/providers/slack/backfill.test.ts +257 -0
- package/src/messaging/providers/slack/backfill.ts +101 -0
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
- package/src/messaging/providers/slack/message-metadata.ts +123 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
- package/src/messaging/providers/slack/render-transcript.ts +443 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/decision-engine.ts +6 -12
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +1 -0
- package/src/oauth/byo-connection.test.ts +18 -1
- package/src/oauth/byo-connection.ts +3 -1
- package/src/oauth/connect-orchestrator.ts +2 -0
- package/src/oauth/connection-resolver.ts +6 -2
- package/src/oauth/connection.ts +2 -0
- package/src/oauth/oauth-store.ts +10 -0
- package/src/oauth/platform-connection.test.ts +145 -0
- package/src/oauth/platform-connection.ts +62 -31
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/approval-policy.test.ts +948 -0
- package/src/permissions/approval-policy.ts +257 -0
- package/src/permissions/bash-risk-classifier.test.ts +1208 -0
- package/src/permissions/bash-risk-classifier.ts +707 -0
- package/src/permissions/checker.ts +218 -699
- package/src/permissions/command-registry.test.ts +535 -0
- package/src/permissions/command-registry.ts +825 -0
- package/src/permissions/defaults.ts +71 -75
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/risk-types.ts +205 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/skill-risk-classifier.test.ts +311 -0
- package/src/permissions/skill-risk-classifier.ts +214 -0
- package/src/permissions/trust-client.ts +52 -25
- package/src/permissions/trust-store-interface.ts +1 -6
- package/src/permissions/trust-store.ts +164 -65
- package/src/permissions/types.ts +23 -14
- package/src/permissions/web-risk-classifier.test.ts +170 -0
- package/src/permissions/web-risk-classifier.ts +89 -0
- package/src/permissions/workspace-policy.ts +1 -13
- package/src/platform/client.test.ts +10 -0
- package/src/platform/client.ts +19 -1
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +127 -3
- package/src/prompts/system-prompt.ts +78 -38
- package/src/prompts/templates/BOOTSTRAP.md +5 -5
- package/src/prompts/templates/SOUL.md +5 -3
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-job.ts +190 -0
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/__tests__/retry-callsite.test.ts +424 -0
- package/src/providers/anthropic/client.ts +335 -70
- package/src/providers/call-site-routing.ts +71 -0
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +74 -3
- package/src/providers/managed-proxy/constants.ts +2 -1
- package/src/providers/model-catalog.ts +502 -28
- package/src/providers/model-intents.ts +8 -8
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +530 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +579 -0
- package/src/providers/openrouter/client.ts +168 -4
- package/src/providers/provider-env-vars.ts +56 -0
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/provider-send-message.ts +22 -5
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/registry.ts +21 -10
- package/src/providers/retry.ts +185 -39
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +883 -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 +323 -0
- package/src/providers/speech-to-text/resolve.ts +393 -6
- package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
- package/src/providers/speech-to-text/xai-realtime.ts +796 -0
- package/src/providers/speech-to-text/xai.test.ts +155 -0
- package/src/providers/speech-to-text/xai.ts +97 -0
- package/src/providers/types.ts +102 -3
- package/src/runtime/AGENTS.md +45 -3
- package/src/runtime/__tests__/agent-wake.test.ts +872 -0
- package/src/runtime/__tests__/interactive-ui.test.ts +673 -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 +553 -0
- package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
- package/src/runtime/auth/route-policy.ts +34 -5
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +15 -3
- package/src/runtime/capability-tokens.ts +10 -10
- 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/channel-reply-delivery.ts +106 -2
- package/src/runtime/chrome-extension-registry.ts +38 -2
- package/src/runtime/decision-token.ts +116 -0
- package/src/runtime/gateway-client.ts +2 -2
- package/src/runtime/http-router.ts +32 -0
- package/src/runtime/http-server.ts +447 -11
- package/src/runtime/http-types.ts +29 -3
- package/src/runtime/interactive-ui.ts +362 -0
- package/src/runtime/invite-instruction-generator.ts +2 -2
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
- package/src/runtime/migrations/gcs-signed-url.ts +162 -0
- package/src/runtime/migrations/migration-transport.ts +1 -0
- package/src/runtime/migrations/migration-wizard.ts +1 -0
- package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
- package/src/runtime/migrations/vbundle-importer.ts +187 -8
- package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
- package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
- package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
- package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
- package/src/runtime/migrations/vbundle-validator.ts +15 -6
- package/src/runtime/pending-interactions.ts +0 -11
- package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +618 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +247 -0
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -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-prompt-ts-tracker.ts +58 -0
- package/src/runtime/routes/approval-routes.ts +12 -17
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/avatar-routes.ts +20 -4
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
- package/src/runtime/routes/btw-routes.ts +9 -10
- 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 -142
- package/src/runtime/routes/conversation-management-routes.ts +133 -0
- package/src/runtime/routes/conversation-routes.ts +487 -160
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +6 -4
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/guardian-approval-interception.ts +33 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
- package/src/runtime/routes/home-feed-routes.ts +452 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +3 -14
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +3 -17
- package/src/runtime/routes/inbound-message-handler.ts +912 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
- 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 +36 -6
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +325 -0
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/migration-routes.ts +722 -91
- package/src/runtime/routes/settings-routes.ts +26 -7
- package/src/runtime/routes/skills-routes.ts +76 -7
- package/src/runtime/routes/stt-routes.ts +233 -0
- package/src/runtime/routes/surface-action-routes.ts +41 -2
- package/src/runtime/routes/trust-rules-routes.ts +30 -14
- package/src/runtime/routes/tts-routes.ts +108 -24
- package/src/runtime/routes/usage-routes.ts +30 -2
- 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.test.ts +1 -1
- package/src/runtime/routes/work-items-routes.ts +11 -3
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +426 -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 +340 -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 +71 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +58 -0
- package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
- package/src/security/__tests__/untrusted-content.test.ts +109 -0
- package/src/security/oauth2.ts +122 -37
- package/src/security/secure-keys.ts +32 -10
- package/src/security/token-manager.ts +35 -13
- package/src/security/untrusted-content.ts +102 -0
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-cache.ts +26 -7
- package/src/skills/catalog-files.ts +64 -2
- package/src/skills/catalog-install.ts +31 -3
- 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-cache-store.ts +97 -0
- 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 +468 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +228 -0
- package/src/stt/stt-stream-session.ts +506 -0
- package/src/stt/types.ts +334 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +79 -27
- package/src/tasks/ephemeral-permissions.ts +9 -4
- package/src/telemetry/usage-telemetry-reporter.ts +27 -5
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +166 -0
- package/src/tools/browser/browser-execution.ts +1208 -41
- package/src/tools/browser/browser-manager.ts +45 -0
- 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__/cdp-inspect-client.test.ts +393 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +205 -17
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
- package/src/tools/browser/cdp-client/errors.ts +15 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
- package/src/tools/browser/cdp-client/factory.ts +797 -87
- package/src/tools/browser/cdp-client/index.ts +16 -2
- package/src/tools/browser/cdp-client/types.ts +68 -0
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +41 -7
- package/src/tools/executor.ts +4 -0
- package/src/tools/filesystem/write.ts +52 -0
- package/src/tools/host-terminal/host-shell.ts +45 -5
- package/src/tools/memory/register.test.ts +185 -0
- package/src/tools/memory/register.ts +3 -1
- package/src/tools/network/web-fetch.ts +25 -12
- package/src/tools/network/web-search.ts +20 -2
- package/src/tools/permission-checker.ts +36 -15
- package/src/tools/policy-context.ts +25 -8
- package/src/tools/registry.ts +55 -3
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +0 -9
- package/src/tools/skills/execute.ts +2 -2
- package/src/tools/skills/sandbox-runner.ts +6 -2
- package/src/tools/terminal/backends/native.ts +51 -2
- package/src/tools/terminal/safe-env.ts +11 -2
- package/src/tools/terminal/shell.ts +16 -4
- package/src/tools/tool-manifest.ts +6 -0
- package/src/tools/types.ts +29 -3
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tools/verification-control-plane-policy.ts +1 -1
- package/src/tts/__tests__/provider-adapters.test.ts +1061 -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 +219 -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 +44 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/providers/xai-provider.ts +224 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +199 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/types/tar-stream.d.ts +66 -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/json.ts +17 -0
- package/src/util/platform.ts +56 -12
- package/src/util/pricing.ts +78 -5
- 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 +24 -1
- package/src/watcher/providers/google-calendar.ts +134 -8
- package/src/watcher/providers/outlook-calendar.ts +42 -2
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/git-service.ts +23 -4
- 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/038-unify-llm-callsite-configs.ts +516 -0
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
- package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +32 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/src/workspace/top-level-renderer.ts +13 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/__tests__/outlook-attachments.test.ts +0 -301
- package/src/__tests__/outlook-automation-tools.test.ts +0 -425
- package/src/__tests__/outlook-categories.test.ts +0 -212
- package/src/__tests__/outlook-compose-tools.test.ts +0 -325
- package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
- package/src/__tests__/outlook-follow-up.test.ts +0 -196
- package/src/__tests__/outlook-trash.test.ts +0 -77
- package/src/__tests__/outlook-unsubscribe.test.ts +0 -250
- package/src/__tests__/update-bulletin-format.test.ts +0 -122
- package/src/__tests__/update-bulletin-state.test.ts +0 -135
- package/src/__tests__/update-bulletin.test.ts +0 -277
- package/src/__tests__/update-template-contract.test.ts +0 -29
- package/src/cli/commands/browser-relay.ts +0 -466
- package/src/cli/commands/doctor.ts +0 -341
- package/src/config/bundled-skills/browser/SKILL.md +0 -63
- package/src/config/bundled-skills/browser/TOOLS.json +0 -393
- package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -32
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
- package/src/config/bundled-skills/gmail/SKILL.md +0 -175
- package/src/config/bundled-skills/gmail/TOOLS.json +0 -558
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -149
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -220
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -251
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
- package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
- package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
- package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/google-calendar/types.ts +0 -97
- package/src/config/bundled-skills/outlook/SKILL.md +0 -196
- package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
- package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
- package/src/config/bundled-skills/slack/SKILL.md +0 -107
- package/src/config/bundled-skills/tasks/SKILL.md +0 -37
- package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
- package/src/config/bundled-skills/tasks/icon.svg +0 -34
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
- package/src/config/bundled-skills/watcher/SKILL.md +0 -31
- package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
- 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/prompts/templates/UPDATES.md +0 -38
- package/src/prompts/templates/USER.md +0 -13
- package/src/prompts/update-bulletin-format.ts +0 -68
- package/src/prompts/update-bulletin-state.ts +0 -58
- package/src/prompts/update-bulletin-template-path.ts +0 -13
- package/src/prompts/update-bulletin.ts +0 -128
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/runtime/routes/browser-cdp-routes.ts +0 -229
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/tools/watcher/create.ts +0 -86
- package/src/tools/watcher/delete.ts +0 -36
- package/src/tools/watcher/digest.ts +0 -54
- package/src/tools/watcher/list.ts +0 -83
- package/src/tools/watcher/update.ts +0 -71
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validator for Google Cloud Storage signed URLs.
|
|
3
|
+
*
|
|
4
|
+
* Used by the migrations import path to confirm that a URL the daemon is
|
|
5
|
+
* about to `fetch()` is, in fact, a signed GCS object URL (and not an
|
|
6
|
+
* attacker-chosen host, scheme, or path).
|
|
7
|
+
*
|
|
8
|
+
* This is a pure function — no I/O, no side effects. The caller decides
|
|
9
|
+
* what to do with the validation result.
|
|
10
|
+
*
|
|
11
|
+
* What we check:
|
|
12
|
+
* - The string parses as a URL.
|
|
13
|
+
* - The scheme is `https:` (no `http:`, `file:`, `data:`, etc.).
|
|
14
|
+
* - The hostname is exactly `storage.googleapis.com`.
|
|
15
|
+
* - No explicit port is present (the default HTTPS port is required;
|
|
16
|
+
* WHATWG URL normalizes `:443` to an empty port string for HTTPS).
|
|
17
|
+
* - The URL carries a signature query param — either `X-Goog-Signature`
|
|
18
|
+
* (V4 signing) or `Signature` (V2 signing). If neither is present
|
|
19
|
+
* the URL is not a signed URL and we refuse it.
|
|
20
|
+
* - The pathname does not contain `..` segments (traversal guard).
|
|
21
|
+
*
|
|
22
|
+
* On success we return the hostname and pathname for logging/telemetry.
|
|
23
|
+
* We deliberately do NOT return the full URL or the query string,
|
|
24
|
+
* because the signature is sensitive and should not end up in logs.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export type GcsUrlValidation =
|
|
28
|
+
| { ok: true; host: string; path: string }
|
|
29
|
+
| { ok: false; reason: string };
|
|
30
|
+
|
|
31
|
+
const EXPECTED_HOST = "storage.googleapis.com";
|
|
32
|
+
const DEFAULT_ALLOWED_HOSTS: readonly string[] = [EXPECTED_HOST];
|
|
33
|
+
|
|
34
|
+
export interface ValidateGcsSignedUrlOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Allowlisted hosts. Defaults to `["storage.googleapis.com"]` — the only
|
|
37
|
+
* production value. Test-only callers can widen this to point at a local
|
|
38
|
+
* HTTP fixture (the `scheme` check also relaxes to accept `http:` for
|
|
39
|
+
* non-default hosts). Production code MUST NOT pass a wider list.
|
|
40
|
+
*/
|
|
41
|
+
allowedHosts?: readonly string[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function validateGcsSignedUrl(
|
|
45
|
+
raw: string,
|
|
46
|
+
options?: ValidateGcsSignedUrlOptions,
|
|
47
|
+
): GcsUrlValidation {
|
|
48
|
+
let parsed: URL;
|
|
49
|
+
try {
|
|
50
|
+
parsed = new URL(raw);
|
|
51
|
+
} catch {
|
|
52
|
+
return { ok: false, reason: "invalid_url" };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const allowedHosts = options?.allowedHosts ?? DEFAULT_ALLOWED_HOSTS;
|
|
56
|
+
const isDefaultHostList =
|
|
57
|
+
allowedHosts.length === 1 && allowedHosts[0] === EXPECTED_HOST;
|
|
58
|
+
|
|
59
|
+
// When the allowlist is the production default (GCS only), require HTTPS.
|
|
60
|
+
// When a caller passes a non-default allowlist (tests pointing at a local
|
|
61
|
+
// HTTP server), allow http too — same-process tests cannot reasonably
|
|
62
|
+
// stand up HTTPS. We still refuse non-http(s) schemes (file:, data:, etc).
|
|
63
|
+
if (isDefaultHostList) {
|
|
64
|
+
if (parsed.protocol !== "https:") {
|
|
65
|
+
return { ok: false, reason: "scheme" };
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
69
|
+
return { ok: false, reason: "scheme" };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!allowedHosts.includes(parsed.hostname)) {
|
|
74
|
+
return { ok: false, reason: "host" };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Reject any explicit port. GCS signed URLs use the default HTTPS
|
|
78
|
+
// port (443), and WHATWG URL normalizes `:443` to an empty port
|
|
79
|
+
// string for HTTPS — so a correctly-issued signed URL always has
|
|
80
|
+
// `parsed.port === ""`. A non-empty port indicates an attacker is
|
|
81
|
+
// trying to redirect the fetch to a non-default port (SSRF vector).
|
|
82
|
+
//
|
|
83
|
+
// For the non-default (test) allowlist, an explicit port is expected
|
|
84
|
+
// (local servers bind to arbitrary ephemeral ports), so the check is
|
|
85
|
+
// skipped in that case.
|
|
86
|
+
if (isDefaultHostList && parsed.port !== "") {
|
|
87
|
+
return { ok: false, reason: "port" };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const hasV4 = parsed.searchParams.has("X-Goog-Signature");
|
|
91
|
+
const hasV2 = parsed.searchParams.has("Signature");
|
|
92
|
+
if (!hasV4 && !hasV2) {
|
|
93
|
+
return { ok: false, reason: "missing_signature" };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Defense-in-depth: reject any `..` path segment. The WHATWG URL
|
|
97
|
+
// parser silently normalizes `/bucket/../foo` to `/foo`, which would
|
|
98
|
+
// hide a traversal attempt — so inspect the *raw* input before
|
|
99
|
+
// normalization in addition to the parsed pathname.
|
|
100
|
+
if (hasTraversalSegment(parsed.pathname) || hasTraversalInRawPath(raw)) {
|
|
101
|
+
return { ok: false, reason: "path_traversal" };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return { ok: true, host: parsed.hostname, path: parsed.pathname };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function hasTraversalSegment(pathname: string): boolean {
|
|
108
|
+
for (const segment of pathname.split("/")) {
|
|
109
|
+
if (segment === "..") return true;
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Look for `..` path segments in the raw input before URL normalization.
|
|
116
|
+
* We slice off the scheme+authority and stop at the first `?` or `#`,
|
|
117
|
+
* then examine each segment split on both `/` and `\` (the WHATWG URL
|
|
118
|
+
* parser treats `\` as equivalent to `/` for special schemes like
|
|
119
|
+
* `https:`, so a backslash-delimited traversal would be normalized
|
|
120
|
+
* away by `new URL()`).
|
|
121
|
+
*
|
|
122
|
+
* Inside each segment we also handle percent-encoded separators
|
|
123
|
+
* (`%2F` = `/`, `%5C` = `\`): we pre-normalize those before the
|
|
124
|
+
* top-level split, and we also re-split each decoded segment on `/`
|
|
125
|
+
* and `\` to catch cases like `%2e%2e%2fother` where the encoded
|
|
126
|
+
* slash hides a traversal within a single raw segment.
|
|
127
|
+
*/
|
|
128
|
+
function hasTraversalInRawPath(raw: string): boolean {
|
|
129
|
+
const schemeEnd = raw.indexOf("://");
|
|
130
|
+
if (schemeEnd === -1) return false;
|
|
131
|
+
const afterScheme = raw.slice(schemeEnd + 3);
|
|
132
|
+
const pathStart = afterScheme.search(/[\/\\]/);
|
|
133
|
+
if (pathStart === -1) return false;
|
|
134
|
+
let path = afterScheme.slice(pathStart);
|
|
135
|
+
const queryIdx = path.indexOf("?");
|
|
136
|
+
if (queryIdx !== -1) path = path.slice(0, queryIdx);
|
|
137
|
+
const hashIdx = path.indexOf("#");
|
|
138
|
+
if (hashIdx !== -1) path = path.slice(0, hashIdx);
|
|
139
|
+
|
|
140
|
+
// Normalize percent-encoded forms of `/` and `\` so that encoded
|
|
141
|
+
// separators participate in the segment split.
|
|
142
|
+
const normalized = path.replace(/%2[fF]/g, "/").replace(/%5[cC]/g, "\\");
|
|
143
|
+
|
|
144
|
+
for (const segment of normalized.split(/[\/\\]/)) {
|
|
145
|
+
if (segment === "..") return true;
|
|
146
|
+
// Percent-decoded forms of ".." — e.g. "%2E%2E", ".%2e", "%2e.".
|
|
147
|
+
// Also re-split on `/` and `\` to catch encoded separators that
|
|
148
|
+
// weren't covered by the top-level normalization (e.g. a decoded
|
|
149
|
+
// segment `../other`).
|
|
150
|
+
let decoded: string;
|
|
151
|
+
try {
|
|
152
|
+
decoded = decodeURIComponent(segment);
|
|
153
|
+
} catch {
|
|
154
|
+
// Ignore malformed percent-encoding; URL parser would handle it.
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
for (const sub of decoded.split(/[\/\\]/)) {
|
|
158
|
+
if (sub === "..") return true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
@@ -17,9 +17,19 @@ import { createHash } from "node:crypto";
|
|
|
17
17
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
18
18
|
import { join, resolve } from "node:path";
|
|
19
19
|
|
|
20
|
+
import { resolveGuardianPersonaPath } from "../../prompts/persona-resolver.js";
|
|
21
|
+
import { getLogger } from "../../util/logger.js";
|
|
20
22
|
import type { ManifestType } from "./vbundle-validator.js";
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
const log = getLogger("vbundle-import-analyzer");
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Only these prompt filenames are accepted during import.
|
|
28
|
+
*
|
|
29
|
+
* `USER.md` is retained for backward compatibility with legacy bundles —
|
|
30
|
+
* on import, its content is translated to `users/<slug>.md` at the
|
|
31
|
+
* current guardian's location (see `DefaultPathResolver.resolve`).
|
|
32
|
+
*/
|
|
23
33
|
const ALLOWED_PROMPT_FILENAMES = new Set([
|
|
24
34
|
"IDENTITY.md",
|
|
25
35
|
"SOUL.md",
|
|
@@ -27,6 +37,9 @@ const ALLOWED_PROMPT_FILENAMES = new Set([
|
|
|
27
37
|
"UPDATES.md",
|
|
28
38
|
]);
|
|
29
39
|
|
|
40
|
+
/** Archive path for the legacy guardian user persona file. */
|
|
41
|
+
const LEGACY_USER_MD_ARCHIVE_PATH = "prompts/USER.md";
|
|
42
|
+
|
|
30
43
|
// ---------------------------------------------------------------------------
|
|
31
44
|
// Public types
|
|
32
45
|
// ---------------------------------------------------------------------------
|
|
@@ -87,9 +100,19 @@ export interface PathResolver {
|
|
|
87
100
|
}
|
|
88
101
|
|
|
89
102
|
export class DefaultPathResolver implements PathResolver {
|
|
103
|
+
/**
|
|
104
|
+
* @param workspaceDir absolute path to the workspace directory.
|
|
105
|
+
* @param hooksDir absolute path to the hooks directory.
|
|
106
|
+
* @param guardianPersonaPathResolver function that returns the
|
|
107
|
+
* current guardian's persona path (`users/<slug>.md`) or `null`
|
|
108
|
+
* when no guardian exists. Defaults to the production
|
|
109
|
+
* `resolveGuardianPersonaPath` helper; tests inject a stub so they
|
|
110
|
+
* don't need to mock the contact store.
|
|
111
|
+
*/
|
|
90
112
|
constructor(
|
|
91
113
|
private workspaceDir?: string,
|
|
92
114
|
private hooksDir?: string,
|
|
115
|
+
private guardianPersonaPathResolver: () => string | null = resolveGuardianPersonaPath,
|
|
93
116
|
) {}
|
|
94
117
|
|
|
95
118
|
resolve(archivePath: string): string | null {
|
|
@@ -139,6 +162,38 @@ export class DefaultPathResolver implements PathResolver {
|
|
|
139
162
|
if (!ALLOWED_PROMPT_FILENAMES.has(filename)) {
|
|
140
163
|
return null;
|
|
141
164
|
}
|
|
165
|
+
|
|
166
|
+
// Legacy USER.md translation: rewrite the destination to the
|
|
167
|
+
// current guardian's per-user persona file `users/<slug>.md`.
|
|
168
|
+
// Guardian-less workspaces return null → importer skips with a
|
|
169
|
+
// warning (see vbundle-importer.ts). This lookup runs against
|
|
170
|
+
// whatever DB state is live at the time of resolve — typically
|
|
171
|
+
// the pre-import workspace, which is the common upgrade case.
|
|
172
|
+
if (archivePath === LEGACY_USER_MD_ARCHIVE_PATH) {
|
|
173
|
+
const guardianPath = this.guardianPersonaPathResolver();
|
|
174
|
+
if (!guardianPath) {
|
|
175
|
+
log.warn(
|
|
176
|
+
{ path: archivePath },
|
|
177
|
+
"Legacy prompts/USER.md has no guardian target — will be skipped on import",
|
|
178
|
+
);
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
// Containment check: guardian path must live under the workspace.
|
|
182
|
+
const wsRoot = resolve(this.workspaceDir);
|
|
183
|
+
const guardianResolved = resolve(guardianPath);
|
|
184
|
+
if (
|
|
185
|
+
guardianResolved !== wsRoot &&
|
|
186
|
+
!guardianResolved.startsWith(wsRoot + "/")
|
|
187
|
+
) {
|
|
188
|
+
log.warn(
|
|
189
|
+
{ path: archivePath, guardianPath },
|
|
190
|
+
"Guardian persona path falls outside workspace — refusing to write",
|
|
191
|
+
);
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
return guardianResolved;
|
|
195
|
+
}
|
|
196
|
+
|
|
142
197
|
const resolved = resolve(this.workspaceDir, filename);
|
|
143
198
|
const wsRoot = resolve(this.workspaceDir);
|
|
144
199
|
if (resolved !== wsRoot && !resolved.startsWith(wsRoot + "/")) {
|
|
@@ -210,6 +265,27 @@ export function analyzeImport(
|
|
|
210
265
|
}
|
|
211
266
|
|
|
212
267
|
if (!diskPath) {
|
|
268
|
+
// Legacy `prompts/USER.md` in a guardian-less workspace has no
|
|
269
|
+
// destination to translate to. The commit-time path skips this
|
|
270
|
+
// entry with a warning rather than failing, so preflight mirrors
|
|
271
|
+
// that: emit a non-blocking skip so `can_import` stays true and
|
|
272
|
+
// upgrade paths proceed. No conflict is registered.
|
|
273
|
+
if (fileEntry.path === LEGACY_USER_MD_ARCHIVE_PATH) {
|
|
274
|
+
log.warn(
|
|
275
|
+
{ path: fileEntry.path },
|
|
276
|
+
"Legacy prompts/USER.md has no guardian target — will be skipped on import",
|
|
277
|
+
);
|
|
278
|
+
files.push({
|
|
279
|
+
path: fileEntry.path,
|
|
280
|
+
action: "skip",
|
|
281
|
+
bundle_size: fileEntry.size,
|
|
282
|
+
bundle_sha256: fileEntry.sha256,
|
|
283
|
+
current_size: null,
|
|
284
|
+
current_sha256: null,
|
|
285
|
+
});
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
|
|
213
289
|
// Unknown archive path — would have nowhere to write
|
|
214
290
|
conflicts.push({
|
|
215
291
|
code: "UNKNOWN_ARCHIVE_PATH",
|
|
@@ -25,10 +25,63 @@ import {
|
|
|
25
25
|
import { dirname, join } from "node:path";
|
|
26
26
|
|
|
27
27
|
import { sanitizeConfigForTransfer } from "../../config/sanitize-for-transfer.js";
|
|
28
|
+
import { isGuardianPersonaCustomized } from "../../prompts/persona-resolver.js";
|
|
29
|
+
import { getLogger } from "../../util/logger.js";
|
|
28
30
|
import type { PathResolver } from "./vbundle-import-analyzer.js";
|
|
31
|
+
import { mergeMetadataPreservingVellum } from "./vbundle-metadata-merge.js";
|
|
29
32
|
import type { ManifestType, VBundleTarEntry } from "./vbundle-validator.js";
|
|
30
33
|
import { validateVBundle } from "./vbundle-validator.js";
|
|
31
34
|
|
|
35
|
+
const log = getLogger("vbundle-importer");
|
|
36
|
+
|
|
37
|
+
/** Archive path for the legacy guardian user persona file. */
|
|
38
|
+
export const LEGACY_USER_MD_ARCHIVE_PATH = "prompts/USER.md";
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Archive paths recognized as JSON config files that must be run through
|
|
42
|
+
* `sanitizeConfigForTransfer` before writing to disk. Exported so the
|
|
43
|
+
* streaming importer can apply the same defense-in-depth treatment.
|
|
44
|
+
*/
|
|
45
|
+
export const CONFIG_ARCHIVE_PATHS: ReadonlySet<string> = new Set([
|
|
46
|
+
"workspace/config.json",
|
|
47
|
+
"config/settings.json",
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Archive path for the credential metadata file. On import, bundle contents
|
|
52
|
+
* must be merged with the target's live `vellum:*` entries so the gateway's
|
|
53
|
+
* `readServiceCredentials` can still locate the platform API key after a
|
|
54
|
+
* local→platform teleport. Both importers consult this constant.
|
|
55
|
+
*/
|
|
56
|
+
export const CREDENTIAL_METADATA_ARCHIVE_PATH =
|
|
57
|
+
"workspace/data/credentials/metadata.json";
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Paths inside the workspace directory that must be preserved across an
|
|
61
|
+
* import when the bundle does not carry entries for them.
|
|
62
|
+
*
|
|
63
|
+
* Each entry is a path RELATIVE to the workspace root. Two kinds of live
|
|
64
|
+
* data warrant carry-over:
|
|
65
|
+
*
|
|
66
|
+
* - `embedding-models` / `deprecated`: large local caches / quarantine
|
|
67
|
+
* directories that are never shipped inside bundles but are expensive
|
|
68
|
+
* or impossible to reconstruct from an import.
|
|
69
|
+
* - `data/db` / `data/qdrant`: user-critical state (SQLite assistant DB;
|
|
70
|
+
* Qdrant vector store). If the bundle omits them — e.g. a partial
|
|
71
|
+
* bundle covering only prompts/config — the live copies must survive.
|
|
72
|
+
*
|
|
73
|
+
* Both the buffer-based `commitImport` (which selectively clears the
|
|
74
|
+
* workspace in place) and the streaming importer (which swaps the
|
|
75
|
+
* workspace with a freshly-populated temp tree) consult this list so
|
|
76
|
+
* their behavior stays in sync.
|
|
77
|
+
*/
|
|
78
|
+
export const WORKSPACE_PRESERVE_PATHS: readonly string[] = [
|
|
79
|
+
"embedding-models",
|
|
80
|
+
"deprecated",
|
|
81
|
+
"data/db",
|
|
82
|
+
"data/qdrant",
|
|
83
|
+
];
|
|
84
|
+
|
|
32
85
|
// ---------------------------------------------------------------------------
|
|
33
86
|
// Public types
|
|
34
87
|
// ---------------------------------------------------------------------------
|
|
@@ -164,10 +217,19 @@ export function commitImport(options: ImportCommitOptions): ImportCommitResult {
|
|
|
164
217
|
entryMap = validation.entries;
|
|
165
218
|
}
|
|
166
219
|
|
|
167
|
-
// Directories to preserve when clearing the workspace.
|
|
168
|
-
|
|
169
|
-
//
|
|
170
|
-
const
|
|
220
|
+
// Directories to preserve when clearing the workspace. Derived from the
|
|
221
|
+
// shared WORKSPACE_PRESERVE_PATHS list so the streaming importer's
|
|
222
|
+
// carry-over logic and this in-place clear stay in sync.
|
|
223
|
+
const WORKSPACE_SKIP_DIRS = new Set<string>();
|
|
224
|
+
const DATA_SKIP_DIRS = new Set<string>();
|
|
225
|
+
for (const rel of WORKSPACE_PRESERVE_PATHS) {
|
|
226
|
+
const parts = rel.split("/");
|
|
227
|
+
if (parts.length === 1) {
|
|
228
|
+
WORKSPACE_SKIP_DIRS.add(parts[0]);
|
|
229
|
+
} else if (parts.length === 2 && parts[0] === "data") {
|
|
230
|
+
DATA_SKIP_DIRS.add(parts[1]);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
171
233
|
|
|
172
234
|
// Step 1b: Clear the workspace directory before restore if the bundle
|
|
173
235
|
// contains new-format workspace/ entries. This ensures an exact-match
|
|
@@ -188,6 +250,30 @@ export function commitImport(options: ImportCommitOptions): ImportCommitResult {
|
|
|
188
250
|
(f) => f.path.startsWith("workspace/") && !!pathResolver.resolve(f.path),
|
|
189
251
|
);
|
|
190
252
|
|
|
253
|
+
// Capture the target's credential metadata BEFORE the workspace clear
|
|
254
|
+
// runs. Step 1b wipes `data/credentials/`, so reading live metadata
|
|
255
|
+
// later (during the per-file write loop) would always miss. The merge
|
|
256
|
+
// helper needs this content to preserve the target's platform-identity
|
|
257
|
+
// (`vellum:*`) entries across the overwrite.
|
|
258
|
+
let liveCredentialMetadataJson: string | null = null;
|
|
259
|
+
const credentialMetadataDiskPath = pathResolver.resolve(
|
|
260
|
+
CREDENTIAL_METADATA_ARCHIVE_PATH,
|
|
261
|
+
);
|
|
262
|
+
if (credentialMetadataDiskPath && existsSync(credentialMetadataDiskPath)) {
|
|
263
|
+
try {
|
|
264
|
+
liveCredentialMetadataJson = readFileSync(
|
|
265
|
+
credentialMetadataDiskPath,
|
|
266
|
+
"utf-8",
|
|
267
|
+
);
|
|
268
|
+
} catch (err) {
|
|
269
|
+
log.warn(
|
|
270
|
+
{ err, path: credentialMetadataDiskPath },
|
|
271
|
+
"Failed to read live credential metadata before import; vellum:* entries may not be preserved",
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
let workspaceWasCleared = false;
|
|
191
277
|
if (hasWorkspaceEntries && workspaceDir && existsSync(workspaceDir)) {
|
|
192
278
|
try {
|
|
193
279
|
// Clear workspace contents selectively, preserving skip dirs
|
|
@@ -211,6 +297,7 @@ export function commitImport(options: ImportCommitOptions): ImportCommitResult {
|
|
|
211
297
|
rmSync(entryPath, { recursive: true, force: true });
|
|
212
298
|
}
|
|
213
299
|
}
|
|
300
|
+
workspaceWasCleared = true;
|
|
214
301
|
} catch (err) {
|
|
215
302
|
return {
|
|
216
303
|
ok: false,
|
|
@@ -270,6 +357,33 @@ export function commitImport(options: ImportCommitOptions): ImportCommitResult {
|
|
|
270
357
|
continue;
|
|
271
358
|
}
|
|
272
359
|
|
|
360
|
+
// Legacy guardian persona (prompts/USER.md) is translated to the
|
|
361
|
+
// current guardian's users/<slug>.md by DefaultPathResolver. If
|
|
362
|
+
// that target already holds user-authored content, skip rather
|
|
363
|
+
// than clobber — the user has curated their persona since the
|
|
364
|
+
// bundle was exported.
|
|
365
|
+
if (
|
|
366
|
+
fileEntry.path === LEGACY_USER_MD_ARCHIVE_PATH &&
|
|
367
|
+
isGuardianPersonaCustomized(diskPath)
|
|
368
|
+
) {
|
|
369
|
+
log.warn(
|
|
370
|
+
{ archivePath: fileEntry.path, diskPath },
|
|
371
|
+
"Skipping legacy prompts/USER.md import: guardian persona is already customized",
|
|
372
|
+
);
|
|
373
|
+
warnings.push(
|
|
374
|
+
`Skipped "${fileEntry.path}": guardian persona at "${diskPath}" is already customized`,
|
|
375
|
+
);
|
|
376
|
+
importedFiles.push({
|
|
377
|
+
path: fileEntry.path,
|
|
378
|
+
disk_path: diskPath,
|
|
379
|
+
action: "skipped",
|
|
380
|
+
size: fileEntry.size,
|
|
381
|
+
sha256: fileEntry.sha256,
|
|
382
|
+
backup_path: null,
|
|
383
|
+
});
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
|
|
273
387
|
// Determine action and create backup if needed
|
|
274
388
|
let backupPath: string | null = null;
|
|
275
389
|
let action: ImportFileAction;
|
|
@@ -324,15 +438,47 @@ export function commitImport(options: ImportCommitOptions): ImportCommitResult {
|
|
|
324
438
|
|
|
325
439
|
// Sanitize config files to strip environment-specific fields (defense-in-depth)
|
|
326
440
|
let dataToWrite: Uint8Array = archiveEntry.data;
|
|
327
|
-
if (
|
|
328
|
-
fileEntry.path === "workspace/config.json" ||
|
|
329
|
-
fileEntry.path === "config/settings.json"
|
|
330
|
-
) {
|
|
441
|
+
if (CONFIG_ARCHIVE_PATHS.has(fileEntry.path)) {
|
|
331
442
|
const configJson = new TextDecoder().decode(archiveEntry.data);
|
|
332
443
|
const sanitized = sanitizeConfigForTransfer(configJson);
|
|
333
444
|
dataToWrite = new TextEncoder().encode(sanitized);
|
|
334
445
|
}
|
|
335
446
|
|
|
447
|
+
// Preserve target's `vellum:*` metadata entries across the overwrite.
|
|
448
|
+
// Django's post-hatch provisioning writes these on the target via
|
|
449
|
+
// POST /v1/secrets; a naive overwrite of the bundle's metadata.json
|
|
450
|
+
// would wipe them and break the gateway's vellum credential read.
|
|
451
|
+
// We use the snapshot captured BEFORE the workspace clear because
|
|
452
|
+
// Step 1b may have already removed the live file.
|
|
453
|
+
if (fileEntry.path === CREDENTIAL_METADATA_ARCHIVE_PATH) {
|
|
454
|
+
const bundleJson = new TextDecoder().decode(archiveEntry.data);
|
|
455
|
+
const merged = mergeMetadataPreservingVellum(
|
|
456
|
+
bundleJson,
|
|
457
|
+
liveCredentialMetadataJson,
|
|
458
|
+
);
|
|
459
|
+
dataToWrite = new TextEncoder().encode(merged);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// If we're about to replace a SQLite main database file, remove any
|
|
463
|
+
// pre-existing `.db-wal`/`.db-shm`/`.db-journal` siblings at the
|
|
464
|
+
// target. Those auxiliary files are only valid as a pair with the
|
|
465
|
+
// exact `.db` that wrote them; leaving them alongside a replacement
|
|
466
|
+
// DB causes SQLite to replay incompatible WAL frames on the first
|
|
467
|
+
// open and report "database disk image is malformed". The exporter
|
|
468
|
+
// already checkpointed the source WAL into the main DB before the
|
|
469
|
+
// bundle was built, so dropping the sibling aux files doesn't lose
|
|
470
|
+
// data from the source workspace.
|
|
471
|
+
if (diskPath.endsWith(".db")) {
|
|
472
|
+
for (const suffix of [".db-wal", ".db-shm", ".db-journal"]) {
|
|
473
|
+
const auxPath = `${diskPath.slice(0, -".db".length)}${suffix}`;
|
|
474
|
+
try {
|
|
475
|
+
rmSync(auxPath, { force: true });
|
|
476
|
+
} catch {
|
|
477
|
+
/* best effort — if the aux file doesn't exist we're fine */
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
336
482
|
// Write the file
|
|
337
483
|
try {
|
|
338
484
|
writeFileSync(diskPath, dataToWrite);
|
|
@@ -382,6 +528,39 @@ export function commitImport(options: ImportCommitOptions): ImportCommitResult {
|
|
|
382
528
|
});
|
|
383
529
|
}
|
|
384
530
|
|
|
531
|
+
// If Step 1b actually cleared the workspace AND the bundle did not
|
|
532
|
+
// carry a metadata.json entry, the target's vellum:* entries were
|
|
533
|
+
// wiped along with the `data/credentials/` directory. Restore them by
|
|
534
|
+
// writing a minimal file containing just the preserved entries so the
|
|
535
|
+
// gateway can still locate the platform API key. When Step 1b did NOT
|
|
536
|
+
// run (e.g. workspaceDir unset) the live metadata.json is still on
|
|
537
|
+
// disk untouched — we must not rewrite it here or we would drop the
|
|
538
|
+
// non-vellum entries the caller chose to keep.
|
|
539
|
+
const bundleHadMetadata = manifest.files.some(
|
|
540
|
+
(f) => f.path === CREDENTIAL_METADATA_ARCHIVE_PATH,
|
|
541
|
+
);
|
|
542
|
+
if (
|
|
543
|
+
workspaceWasCleared &&
|
|
544
|
+
!bundleHadMetadata &&
|
|
545
|
+
liveCredentialMetadataJson &&
|
|
546
|
+
credentialMetadataDiskPath
|
|
547
|
+
) {
|
|
548
|
+
const merged = mergeMetadataPreservingVellum(
|
|
549
|
+
JSON.stringify({ version: 5, credentials: [] }),
|
|
550
|
+
liveCredentialMetadataJson,
|
|
551
|
+
);
|
|
552
|
+
try {
|
|
553
|
+
mkdirSync(dirname(credentialMetadataDiskPath), { recursive: true });
|
|
554
|
+
writeFileSync(credentialMetadataDiskPath, merged);
|
|
555
|
+
} catch (err) {
|
|
556
|
+
warnings.push(
|
|
557
|
+
`Failed to restore preserved vellum:* credential metadata: ${
|
|
558
|
+
err instanceof Error ? err.message : String(err)
|
|
559
|
+
}`,
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
385
564
|
// Build final report
|
|
386
565
|
const report: ImportCommitReport = {
|
|
387
566
|
success: true,
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge helper for `data/credentials/metadata.json` on bundle import.
|
|
3
|
+
*
|
|
4
|
+
* The credential metadata file lists the credentials known to the assistant
|
|
5
|
+
* (service, field, policy, timestamps) and is used by the gateway's
|
|
6
|
+
* `readServiceCredentials` to decide whether a service is "configured".
|
|
7
|
+
* The VELLUM spec requires all four `vellum:*` fields (`platform_base_url`,
|
|
8
|
+
* `assistant_api_key`, `platform_assistant_id`, `webhook_secret`) to be
|
|
9
|
+
* present in metadata before the gateway will even look up their values in
|
|
10
|
+
* CES.
|
|
11
|
+
*
|
|
12
|
+
* On a local→platform teleport, the bundle carries the SOURCE's metadata
|
|
13
|
+
* (no `vellum:*` entries, since the source is local), and a naive overwrite
|
|
14
|
+
* would wipe out the `vellum:*` entries that Django's post-hatch
|
|
15
|
+
* provisioning just wrote on the TARGET. This module merges bundle and live
|
|
16
|
+
* metadata with one rule:
|
|
17
|
+
*
|
|
18
|
+
* - Drop `service === "vellum"` entries the bundle tries to ship
|
|
19
|
+
* (defense-in-depth — they represent the source's identity, not the
|
|
20
|
+
* target's). This mirrors the CES-side filter in migration-routes.ts.
|
|
21
|
+
* - Preserve every `service === "vellum"` entry the target already has.
|
|
22
|
+
* - Import bundle entries for every other service normally (user OAuth,
|
|
23
|
+
* channel credentials).
|
|
24
|
+
*
|
|
25
|
+
* Malformed input (missing file, unparseable JSON, unrecognized schema) is
|
|
26
|
+
* handled by the callers: they should treat "no live metadata" as no
|
|
27
|
+
* preservation needed, and leave the bundle's file untouched if its schema
|
|
28
|
+
* can't be merged cleanly.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const VELLUM_SERVICE = "vellum";
|
|
32
|
+
|
|
33
|
+
interface MetadataRecord {
|
|
34
|
+
credentialId: string;
|
|
35
|
+
service: string;
|
|
36
|
+
field: string;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface MetadataFile {
|
|
41
|
+
version?: number;
|
|
42
|
+
credentials?: unknown[];
|
|
43
|
+
[key: string]: unknown;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isRecord(value: unknown): value is MetadataRecord {
|
|
47
|
+
if (typeof value !== "object" || value == null) return false;
|
|
48
|
+
const r = value as Record<string, unknown>;
|
|
49
|
+
return (
|
|
50
|
+
typeof r.credentialId === "string" &&
|
|
51
|
+
typeof r.service === "string" &&
|
|
52
|
+
typeof r.field === "string"
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function parseMetadata(json: string | null | undefined): MetadataFile | null {
|
|
57
|
+
if (!json) return null;
|
|
58
|
+
try {
|
|
59
|
+
const parsed: unknown = JSON.parse(json);
|
|
60
|
+
if (typeof parsed !== "object" || parsed == null || Array.isArray(parsed)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return parsed as MetadataFile;
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function extractVellumRecords(file: MetadataFile | null): MetadataRecord[] {
|
|
70
|
+
if (!file || !Array.isArray(file.credentials)) return [];
|
|
71
|
+
return file.credentials
|
|
72
|
+
.filter(isRecord)
|
|
73
|
+
.filter((r) => r.service === VELLUM_SERVICE);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Merge the bundle's metadata.json content with any `vellum:*` entries
|
|
78
|
+
* present in the target's live metadata.json.
|
|
79
|
+
*
|
|
80
|
+
* Returns the merged JSON string, preserving the bundle's schema version
|
|
81
|
+
* and formatting (2-space indent). If the bundle's JSON is unparseable the
|
|
82
|
+
* original input is returned unchanged — we never want to corrupt the
|
|
83
|
+
* bundle's file by emitting an empty or restructured payload.
|
|
84
|
+
*
|
|
85
|
+
* If the live JSON is unparseable or missing, the bundle's file is returned
|
|
86
|
+
* verbatim (no preservation possible — nothing to preserve).
|
|
87
|
+
*/
|
|
88
|
+
export function mergeMetadataPreservingVellum(
|
|
89
|
+
bundleJson: string,
|
|
90
|
+
liveJson: string | null,
|
|
91
|
+
): string {
|
|
92
|
+
const bundle = parseMetadata(bundleJson);
|
|
93
|
+
if (!bundle) return bundleJson;
|
|
94
|
+
|
|
95
|
+
const preservedVellum = extractVellumRecords(parseMetadata(liveJson));
|
|
96
|
+
|
|
97
|
+
const bundleCredentials = Array.isArray(bundle.credentials)
|
|
98
|
+
? bundle.credentials.filter(isRecord)
|
|
99
|
+
: [];
|
|
100
|
+
|
|
101
|
+
// Drop any `service === "vellum"` entries from the bundle (defense-in-depth).
|
|
102
|
+
const filteredBundle = bundleCredentials.filter(
|
|
103
|
+
(r) => r.service !== VELLUM_SERVICE,
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Union: bundle non-vellum entries + target vellum entries. If the
|
|
107
|
+
// preserved list happens to collide with a bundle entry on credentialId,
|
|
108
|
+
// the preserved version wins (it belongs to the target's live identity).
|
|
109
|
+
const merged = [...filteredBundle, ...preservedVellum];
|
|
110
|
+
|
|
111
|
+
const output: MetadataFile = {
|
|
112
|
+
...bundle,
|
|
113
|
+
credentials: merged,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return JSON.stringify(output, null, 2);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** @internal For direct use by tests. */
|
|
120
|
+
export const _internal = {
|
|
121
|
+
VELLUM_SERVICE,
|
|
122
|
+
parseMetadata,
|
|
123
|
+
extractVellumRecords,
|
|
124
|
+
};
|