@vellumai/assistant 0.6.3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +273 -10
- package/Dockerfile +2 -3
- package/bun.lock +5 -13
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/stt-provider-onboarding.md +120 -0
- package/knip.json +12 -2
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +3 -3
- package/openapi.yaml +982 -72
- package/package.json +4 -6
- package/scripts/generate-openapi.ts +0 -1
- package/scripts/test.sh +73 -18
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop.test.ts +123 -0
- package/src/__tests__/anthropic-provider.test.ts +263 -10
- package/src/__tests__/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 +11 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/browser-skill-endstate.test.ts +31 -7
- package/src/__tests__/btw-routes.test.ts +7 -0
- package/src/__tests__/call-controller.test.ts +581 -20
- package/src/__tests__/catalog-files.test.ts +138 -0
- package/src/__tests__/channel-invite-transport.test.ts +2 -2
- package/src/__tests__/channel-readiness-routes.test.ts +16 -20
- package/src/__tests__/channel-readiness-service.test.ts +12 -7
- package/src/__tests__/checker.test.ts +157 -10
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/config-analysis.test.ts +100 -0
- package/src/__tests__/config-schema.test.ts +1013 -66
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +43 -8
- package/src/__tests__/contact-store-user-file.test.ts +512 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-window-manager.test.ts +88 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +98 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +135 -0
- package/src/__tests__/conversation-error.test.ts +70 -0
- package/src/__tests__/conversation-history-web-search.test.ts +11 -4
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +901 -60
- package/src/__tests__/conversation-routes-disk-view.test.ts +270 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +55 -0
- package/src/__tests__/conversation-skill-tools.test.ts +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +89 -18
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +5 -3
- package/src/__tests__/credential-vault-unit.test.ts +379 -3
- package/src/__tests__/credentials-cli.test.ts +40 -16
- package/src/__tests__/cross-provider-web-search.test.ts +146 -35
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +75 -8
- 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 -0
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
- package/src/__tests__/gmail-archive-gate.test.ts +246 -0
- package/src/__tests__/gmail-preferences.test.ts +117 -0
- package/src/__tests__/headless-browser-interactions.test.ts +43 -0
- 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 +70 -17
- 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__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/llm-context-normalization.test.ts +488 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/media-stream-output.test.ts +555 -0
- package/src/__tests__/media-stream-parser.test.ts +374 -0
- package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
- package/src/__tests__/media-stream-stt-session.test.ts +588 -0
- package/src/__tests__/media-turn-detector.test.ts +440 -0
- package/src/__tests__/message-queue.test.ts +125 -0
- package/src/__tests__/migration-export-http.test.ts +6 -6
- package/src/__tests__/migration-import-commit-http.test.ts +8 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +151 -0
- package/src/__tests__/model-intents.test.ts +2 -2
- package/src/__tests__/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 +85 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +249 -6
- package/src/__tests__/onboarding-template-contract.test.ts +6 -13
- package/src/__tests__/openai-provider.test.ts +176 -0
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1105 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +31 -2
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
- 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 +174 -0
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
- package/src/__tests__/relationship-state-contract.test.ts +175 -0
- package/src/__tests__/relay-server.test.ts +423 -5
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-scanner-executor.test.ts +4 -0
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +5 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +49 -0
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
- package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
- package/src/__tests__/skills.test.ts +5 -2
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +564 -1
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/system-prompt.test.ts +112 -26
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +18 -7
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +33 -24
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/trust-store.test.ts +7 -1
- 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-format.test.ts +59 -0
- package/src/__tests__/update-bulletin.test.ts +206 -5
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
- package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
- package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
- package/src/__tests__/workspace-migration-meets.test.ts +244 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
- package/src/__tests__/workspace-policy.test.ts +2 -0
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +43 -3
- 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/bundler/package-resolver.ts +4 -0
- package/src/calls/audio-store.ts +11 -5
- package/src/calls/call-controller.ts +226 -71
- package/src/calls/call-domain.ts +9 -0
- package/src/calls/call-speech-output.ts +190 -0
- package/src/calls/call-transport.ts +77 -0
- package/src/calls/media-stream-audio-transcode.ts +173 -0
- package/src/calls/media-stream-output.ts +660 -0
- package/src/calls/media-stream-parser.ts +300 -0
- package/src/calls/media-stream-protocol.ts +166 -0
- package/src/calls/media-stream-server.ts +592 -0
- package/src/calls/media-stream-stt-session.ts +460 -0
- package/src/calls/media-turn-detector.ts +230 -0
- package/src/calls/relay-server.ts +90 -75
- package/src/calls/resolve-call-tts-provider.ts +136 -0
- package/src/calls/telephony-stt-routing.ts +145 -0
- package/src/calls/tts-call-strategy.ts +161 -0
- package/src/calls/tts-text-sanitizer.ts +32 -16
- package/src/calls/twilio-routes.ts +281 -17
- package/src/calls/voice-quality.ts +78 -35
- package/src/calls/voice-session-bridge.ts +8 -1
- package/src/channels/types.ts +16 -0
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
- package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
- package/src/cli/commands/__tests__/email-download.test.ts +16 -1
- package/src/cli/commands/__tests__/email-list.test.ts +22 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +37 -4
- package/src/cli/commands/__tests__/email-status.test.ts +5 -1
- package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/conversations.ts +77 -0
- package/src/cli/commands/credentials.ts +0 -1
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +255 -3
- 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 -9
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
- package/src/cli/program.ts +30 -4
- package/src/config/__tests__/backup-schema.test.ts +134 -0
- package/src/config/assistant-feature-flags.ts +61 -62
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +37 -1
- package/src/config/bundled-skills/browser/SKILL.md +30 -5
- package/src/config/bundled-skills/browser/TOOLS.json +123 -0
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
- package/src/config/bundled-skills/contacts/SKILL.md +2 -2
- package/src/config/bundled-skills/gmail/SKILL.md +53 -7
- package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
- package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
- package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/outlook/SKILL.md +2 -2
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
- package/src/config/bundled-skills/slack/SKILL.md +1 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
- package/src/config/bundled-tool-registry.ts +8 -0
- package/src/config/env-registry.ts +24 -0
- package/src/config/env.ts +34 -10
- package/src/config/feature-flag-registry.json +46 -14
- package/src/config/loader.ts +26 -12
- package/src/config/schema.ts +35 -10
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +51 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -26
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +47 -7
- package/src/config/schemas/heartbeat.ts +27 -5
- package/src/config/schemas/host-browser.ts +47 -1
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/services.ts +44 -0
- package/src/config/schemas/stt.ts +59 -0
- package/src/config/schemas/tts.ts +230 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/skills.ts +4 -0
- package/src/config/types.ts +4 -0
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/post-turn-tool-result-truncation.ts +3 -2
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +45 -12
- package/src/credential-execution/executable-discovery.ts +12 -2
- package/src/credential-execution/process-manager.ts +33 -2
- package/src/credential-health/credential-health-service.ts +366 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +17 -8
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/config-watcher.ts +99 -5
- package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
- package/src/daemon/conversation-agent-loop.ts +101 -24
- package/src/daemon/conversation-error.ts +11 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +59 -9
- package/src/daemon/conversation-messaging.ts +37 -3
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +581 -19
- package/src/daemon/conversation-queue-manager.ts +24 -0
- package/src/daemon/conversation-runtime-assembly.ts +11 -1
- package/src/daemon/conversation-slash.ts +36 -0
- package/src/daemon/conversation-surfaces.ts +94 -4
- package/src/daemon/conversation-tool-setup.ts +25 -0
- package/src/daemon/conversation-usage.ts +7 -4
- package/src/daemon/conversation.ts +86 -28
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +4 -1
- package/src/daemon/handlers/shared.ts +22 -0
- package/src/daemon/handlers/skills.ts +321 -77
- package/src/daemon/host-browser-proxy.ts +2 -1
- package/src/daemon/lifecycle.ts +122 -25
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/conversations.ts +34 -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 +14 -0
- 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/server.ts +347 -2
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +9 -0
- package/src/email/html-renderer.ts +76 -0
- package/src/heartbeat/heartbeat-service.ts +93 -7
- package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
- package/src/home/__tests__/emit-feed-event.test.ts +169 -0
- package/src/home/__tests__/feed-scheduler.test.ts +194 -0
- package/src/home/__tests__/feed-types.test.ts +275 -0
- package/src/home/__tests__/feed-writer.test.ts +688 -0
- package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
- package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
- package/src/home/__tests__/progress-formula.test.ts +213 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
- package/src/home/__tests__/rollup-producer.test.ts +398 -0
- package/src/home/assistant-feed-authoring.ts +124 -0
- package/src/home/emit-feed-event.ts +158 -0
- package/src/home/feed-scheduler.ts +247 -0
- package/src/home/feed-types.ts +181 -0
- package/src/home/feed-writer.ts +469 -0
- package/src/home/platform-gmail-digest.ts +163 -0
- package/src/home/progress-formula.ts +86 -0
- package/src/home/relationship-state-writer.ts +824 -0
- package/src/home/relationship-state.ts +143 -0
- package/src/home/rollup-producer.ts +384 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +12 -3
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/cli-client.ts +151 -0
- package/src/ipc/cli-server.ts +234 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/index.ts +5 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
- package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/app-store.ts +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 +73 -0
- package/src/memory/conversation-crud.ts +99 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +34 -2
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/db-init.ts +6 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/graph/conversation-graph-memory.ts +15 -0
- package/src/memory/graph/extraction.test.ts +23 -0
- package/src/memory/graph/extraction.ts +8 -0
- package/src/memory/graph/retriever.ts +27 -18
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/group-crud.ts +6 -1
- package/src/memory/indexer.ts +95 -16
- package/src/memory/job-handlers/cleanup.ts +11 -8
- package/src/memory/job-handlers/conversation-starters.ts +16 -10
- package/src/memory/jobs-store.ts +64 -4
- package/src/memory/jobs-worker.ts +22 -9
- package/src/memory/llm-usage-store.ts +92 -56
- package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
- package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- 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/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/client.ts +57 -6
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +143 -38
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/decision-engine.ts +3 -3
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/__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 +9 -0
- package/src/oauth/platform-connection.test.ts +98 -0
- package/src/oauth/platform-connection.ts +52 -31
- package/src/oauth/seed-providers.ts +7 -0
- package/src/permissions/checker.ts +16 -6
- package/src/permissions/defaults.ts +49 -1
- package/src/permissions/trust-store.ts +3 -3
- package/src/permissions/workspace-policy.ts +3 -0
- package/src/platform/client.test.ts +10 -0
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +126 -2
- package/src/prompts/system-prompt.ts +59 -18
- package/src/prompts/templates/BOOTSTRAP.md +5 -5
- package/src/prompts/templates/SOUL.md +3 -1
- package/src/prompts/templates/UPDATES.md +12 -0
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-format.ts +26 -9
- package/src/prompts/update-bulletin.ts +34 -23
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/anthropic/client.ts +157 -61
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +9 -1
- package/src/providers/model-catalog.ts +6 -0
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +474 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +502 -0
- package/src/providers/openrouter/client.ts +101 -4
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +14 -3
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
- package/src/providers/speech-to-text/deepgram.test.ts +332 -0
- package/src/providers/speech-to-text/deepgram.ts +115 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
- package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
- package/src/providers/speech-to-text/google-gemini.ts +101 -0
- package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
- package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
- package/src/providers/speech-to-text/openai-whisper.ts +63 -33
- package/src/providers/speech-to-text/provider-catalog.ts +306 -0
- package/src/providers/speech-to-text/resolve.ts +386 -6
- package/src/providers/types.ts +9 -0
- package/src/runtime/AGENTS.md +43 -1
- package/src/runtime/__tests__/agent-wake.test.ts +831 -0
- package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
- package/src/runtime/agent-wake.ts +512 -0
- package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
- package/src/runtime/auth/route-policy.ts +30 -5
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- 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/chrome-extension-registry.ts +38 -2
- package/src/runtime/http-server.ts +395 -10
- package/src/runtime/http-types.ts +6 -2
- 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/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 +34 -0
- 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 +507 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
- package/src/runtime/routes/app-management-routes.ts +12 -18
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
- package/src/runtime/routes/btw-routes.ts +8 -6
- package/src/runtime/routes/contact-routes.test.ts +298 -0
- package/src/runtime/routes/contact-routes.ts +132 -5
- package/src/runtime/routes/conversation-analysis-routes.ts +22 -142
- package/src/runtime/routes/conversation-management-routes.ts +115 -0
- package/src/runtime/routes/conversation-routes.ts +367 -146
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/home-feed-routes.ts +334 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +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-stages/transcribe-audio.test.ts +46 -39
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
- package/src/runtime/routes/integrations/slack/channel.ts +11 -3
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +303 -0
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/migration-routes.ts +40 -5
- package/src/runtime/routes/settings-routes.ts +22 -5
- 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/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.ts +8 -1
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
- package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
- package/src/runtime/services/analyze-conversation.ts +344 -0
- package/src/runtime/services/analyze-deps-singleton.ts +32 -0
- package/src/runtime/services/auto-analysis-prompt.ts +55 -0
- package/src/runtime/skill-route-registry.ts +49 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +50 -0
- package/src/security/oauth2.ts +26 -4
- package/src/security/secure-keys.ts +25 -2
- package/src/security/token-manager.ts +8 -0
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-files.ts +64 -2
- package/src/skills/category-inference.ts +122 -0
- package/src/skills/clawhub-files.ts +213 -0
- package/src/skills/clawhub.ts +84 -23
- package/src/skills/skill-file-provider.ts +40 -0
- package/src/skills/skillssh-files.ts +395 -0
- package/src/skills/skillssh-registry.ts +4 -4
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +195 -0
- package/src/stt/stt-stream-session.ts +499 -0
- package/src/stt/types.ts +330 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +38 -14
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
- package/src/tools/browser/browser-execution.ts +1163 -23
- 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 +183 -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/vault.ts +35 -6
- package/src/tools/network/web-fetch.ts +5 -2
- package/src/tools/network/web-search.ts +5 -2
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +2 -0
- package/src/tools/skills/sandbox-runner.ts +3 -2
- package/src/tools/terminal/safe-env.ts +10 -2
- package/src/tools/terminal/shell.ts +15 -4
- package/src/tools/tool-manifest.ts +21 -0
- package/src/tools/types.ts +17 -0
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tts/__tests__/provider-adapters.test.ts +834 -0
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
- package/src/tts/__tests__/provider-catalog.test.ts +183 -0
- package/src/tts/__tests__/provider-registry.test.ts +90 -0
- package/src/tts/provider-catalog.ts +201 -0
- package/src/tts/provider-registry.ts +73 -0
- package/src/tts/providers/deepgram-provider.ts +219 -0
- package/src/tts/providers/elevenlabs-provider.ts +211 -0
- package/src/tts/providers/fish-audio-provider.ts +183 -0
- package/src/tts/providers/index.ts +42 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +153 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/util/abort-reasons.ts +58 -0
- package/src/util/device-id.ts +32 -16
- package/src/util/errors.ts +9 -1
- package/src/util/platform.ts +54 -10
- package/src/util/pricing.ts +66 -3
- package/src/util/spawn.ts +1 -1
- package/src/util/truncate.ts +4 -2
- package/src/util/unicode.ts +201 -0
- package/src/version.ts +19 -24
- package/src/watcher/engine.ts +23 -0
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/migrations/003-seed-device-id.ts +9 -3
- package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
- package/src/workspace/migrations/029-seed-pkb.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +317 -0
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
- package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
- package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
- package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/top-level-renderer.ts +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/cli/commands/browser-relay.ts +0 -466
- 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/USER.md +0 -13
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/runtime/routes/browser-cdp-routes.ts +0 -229
|
@@ -77,6 +77,7 @@ const mockConnections = new Map<
|
|
|
77
77
|
expiresAt: number | null;
|
|
78
78
|
grantedScopes?: string;
|
|
79
79
|
accountInfo?: string | null;
|
|
80
|
+
status?: string;
|
|
80
81
|
}
|
|
81
82
|
>();
|
|
82
83
|
const mockApps = new Map<
|
|
@@ -92,14 +93,26 @@ const mockProviders = new Map<
|
|
|
92
93
|
string,
|
|
93
94
|
{
|
|
94
95
|
key: string;
|
|
96
|
+
provider: string;
|
|
95
97
|
tokenExchangeUrl: string;
|
|
96
98
|
tokenEndpointAuthMethod?: string;
|
|
99
|
+
tokenExchangeBodyFormat?: string;
|
|
97
100
|
baseUrl?: string;
|
|
101
|
+
managedServiceConfigKey?: string | null;
|
|
98
102
|
}
|
|
99
103
|
>();
|
|
100
104
|
|
|
101
105
|
mock.module("./oauth-store.js", () => ({
|
|
102
106
|
getConnectionByProvider: (service: string) => mockConnections.get(service),
|
|
107
|
+
getActiveConnection: (
|
|
108
|
+
service: string,
|
|
109
|
+
opts?: { clientId?: string; account?: string },
|
|
110
|
+
) => {
|
|
111
|
+
const conn = mockConnections.get(service);
|
|
112
|
+
if (!conn) return undefined;
|
|
113
|
+
if (opts?.account && conn.accountInfo !== opts.account) return undefined;
|
|
114
|
+
return conn;
|
|
115
|
+
},
|
|
103
116
|
getConnection: (id: string) => {
|
|
104
117
|
for (const conn of mockConnections.values()) {
|
|
105
118
|
if (conn.id === id) return conn;
|
|
@@ -192,12 +205,15 @@ async function setupCredential(
|
|
|
192
205
|
const connId = `conn-${service}`;
|
|
193
206
|
mockProviders.set(service, {
|
|
194
207
|
key: service,
|
|
208
|
+
provider: service,
|
|
195
209
|
tokenExchangeUrl: "https://oauth2.googleapis.com/token",
|
|
210
|
+
tokenExchangeBodyFormat: "form",
|
|
196
211
|
// Only well-known providers (gmail) have a baseUrl; custom services don't
|
|
197
212
|
baseUrl:
|
|
198
213
|
service === "google"
|
|
199
214
|
? "https://gmail.googleapis.com/gmail/v1/users/me"
|
|
200
215
|
: undefined,
|
|
216
|
+
managedServiceConfigKey: null,
|
|
201
217
|
});
|
|
202
218
|
mockApps.set(appId, {
|
|
203
219
|
id: appId,
|
|
@@ -212,6 +228,7 @@ async function setupCredential(
|
|
|
212
228
|
expiresAt: opts?.expiresAt ?? Date.now() + 3600 * 1000,
|
|
213
229
|
grantedScopes: JSON.stringify(opts?.grantedScopes ?? ["read", "write"]),
|
|
214
230
|
accountInfo: null,
|
|
231
|
+
status: "active",
|
|
215
232
|
});
|
|
216
233
|
// Store access token in oauth-store key format
|
|
217
234
|
await setSecureKeyAsync(
|
|
@@ -509,7 +526,7 @@ describe("resolveOAuthConnection", () => {
|
|
|
509
526
|
test("throws when no base URL configured", async () => {
|
|
510
527
|
await setupCredential("custom-service");
|
|
511
528
|
await expect(resolveOAuthConnection("custom-service")).rejects.toThrow(
|
|
512
|
-
/
|
|
529
|
+
/OAuth provider "custom-service" has no base URL configured/,
|
|
513
530
|
);
|
|
514
531
|
});
|
|
515
532
|
});
|
|
@@ -82,7 +82,9 @@ export class BYOOAuthConnection implements OAuthConnection {
|
|
|
82
82
|
method: req.method,
|
|
83
83
|
headers,
|
|
84
84
|
body: req.body ? JSON.stringify(req.body) : undefined,
|
|
85
|
-
signal:
|
|
85
|
+
signal: req.signal
|
|
86
|
+
? AbortSignal.any([req.signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)])
|
|
87
|
+
: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
86
88
|
});
|
|
87
89
|
|
|
88
90
|
if (resp.status === 401) {
|
|
@@ -209,6 +209,8 @@ export async function orchestrateOAuthConnect(
|
|
|
209
209
|
authorizeParams,
|
|
210
210
|
userinfoUrl,
|
|
211
211
|
tokenEndpointAuthMethod,
|
|
212
|
+
tokenExchangeBodyFormat:
|
|
213
|
+
(providerRow.tokenExchangeBodyFormat as "form" | "json") ?? "form",
|
|
212
214
|
};
|
|
213
215
|
|
|
214
216
|
const storageParams = {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { getConfig } from "../config/loader.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getServiceMode,
|
|
4
|
+
type Services,
|
|
5
|
+
ServicesSchema,
|
|
6
|
+
} from "../config/schemas/services.js";
|
|
3
7
|
import { VellumPlatformClient } from "../platform/client.js";
|
|
4
8
|
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
5
9
|
import { getLogger } from "../util/logger.js";
|
|
@@ -47,7 +51,7 @@ export async function resolveOAuthConnection(
|
|
|
47
51
|
|
|
48
52
|
if (managedKey && managedKey in ServicesSchema.shape) {
|
|
49
53
|
const services: Services = getConfig().services;
|
|
50
|
-
if (services
|
|
54
|
+
if (getServiceMode(services, managedKey as keyof Services) === "managed") {
|
|
51
55
|
const client = await VellumPlatformClient.create();
|
|
52
56
|
if (!client || !client.platformAssistantId) {
|
|
53
57
|
const detail = !client
|
package/src/oauth/connection.ts
CHANGED
package/src/oauth/oauth-store.ts
CHANGED
|
@@ -72,6 +72,7 @@ export function seedProviders(
|
|
|
72
72
|
tokenExchangeUrl: string;
|
|
73
73
|
refreshUrl?: string;
|
|
74
74
|
tokenEndpointAuthMethod?: string;
|
|
75
|
+
tokenExchangeBodyFormat?: string;
|
|
75
76
|
userinfoUrl?: string;
|
|
76
77
|
pingUrl?: string;
|
|
77
78
|
pingMethod?: string;
|
|
@@ -122,6 +123,7 @@ export function seedProviders(
|
|
|
122
123
|
// token endpoint auth method.
|
|
123
124
|
const tokenEndpointAuthMethod =
|
|
124
125
|
p.tokenEndpointAuthMethod || "client_secret_post";
|
|
126
|
+
const tokenExchangeBodyFormat = p.tokenExchangeBodyFormat || "form";
|
|
125
127
|
const userinfoUrl = p.userinfoUrl ?? null;
|
|
126
128
|
const pingUrl = p.pingUrl ?? null;
|
|
127
129
|
const pingMethod = p.pingMethod ?? null;
|
|
@@ -176,6 +178,7 @@ export function seedProviders(
|
|
|
176
178
|
tokenExchangeUrl,
|
|
177
179
|
refreshUrl,
|
|
178
180
|
tokenEndpointAuthMethod,
|
|
181
|
+
tokenExchangeBodyFormat,
|
|
179
182
|
userinfoUrl,
|
|
180
183
|
baseUrl,
|
|
181
184
|
defaultScopes,
|
|
@@ -217,6 +220,7 @@ export function seedProviders(
|
|
|
217
220
|
tokenExchangeUrl,
|
|
218
221
|
refreshUrl,
|
|
219
222
|
tokenEndpointAuthMethod,
|
|
223
|
+
tokenExchangeBodyFormat,
|
|
220
224
|
userinfoUrl,
|
|
221
225
|
baseUrl: sql`COALESCE(${oauthProviders.baseUrl}, ${baseUrl})`,
|
|
222
226
|
scopeSeparator,
|
|
@@ -279,6 +283,7 @@ export function registerProvider(params: {
|
|
|
279
283
|
tokenExchangeUrl: string;
|
|
280
284
|
refreshUrl?: string;
|
|
281
285
|
tokenEndpointAuthMethod?: string;
|
|
286
|
+
tokenExchangeBodyFormat?: string;
|
|
282
287
|
userinfoUrl?: string;
|
|
283
288
|
pingUrl?: string;
|
|
284
289
|
pingMethod?: string;
|
|
@@ -331,6 +336,7 @@ export function registerProvider(params: {
|
|
|
331
336
|
refreshUrl: params.refreshUrl ?? null,
|
|
332
337
|
tokenEndpointAuthMethod:
|
|
333
338
|
params.tokenEndpointAuthMethod || "client_secret_post",
|
|
339
|
+
tokenExchangeBodyFormat: params.tokenExchangeBodyFormat || "form",
|
|
334
340
|
userinfoUrl: params.userinfoUrl ?? null,
|
|
335
341
|
baseUrl: params.baseUrl ?? null,
|
|
336
342
|
defaultScopes: JSON.stringify(params.defaultScopes),
|
|
@@ -402,6 +408,7 @@ export function updateProvider(
|
|
|
402
408
|
tokenExchangeUrl: string;
|
|
403
409
|
refreshUrl: string;
|
|
404
410
|
tokenEndpointAuthMethod: string;
|
|
411
|
+
tokenExchangeBodyFormat: string;
|
|
405
412
|
userinfoUrl: string;
|
|
406
413
|
pingUrl: string;
|
|
407
414
|
pingMethod: string;
|
|
@@ -452,6 +459,8 @@ export function updateProvider(
|
|
|
452
459
|
if (params.tokenEndpointAuthMethod !== undefined)
|
|
453
460
|
set.tokenEndpointAuthMethod =
|
|
454
461
|
params.tokenEndpointAuthMethod || "client_secret_post";
|
|
462
|
+
if (params.tokenExchangeBodyFormat !== undefined)
|
|
463
|
+
set.tokenExchangeBodyFormat = params.tokenExchangeBodyFormat || "form";
|
|
455
464
|
if (params.userinfoUrl !== undefined) set.userinfoUrl = params.userinfoUrl;
|
|
456
465
|
if (params.pingUrl !== undefined) set.pingUrl = params.pingUrl;
|
|
457
466
|
if (params.pingMethod !== undefined) set.pingMethod = params.pingMethod;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import * as actualRetry from "../util/retry.js";
|
|
4
|
+
|
|
5
|
+
// Stub out sleep so retry tests don't wait for real delays.
|
|
6
|
+
mock.module("../util/retry.js", () => ({
|
|
7
|
+
...actualRetry,
|
|
8
|
+
sleep: () => Promise.resolve(),
|
|
9
|
+
}));
|
|
10
|
+
|
|
3
11
|
import type { VellumPlatformClient } from "../platform/client.js";
|
|
4
12
|
import { BackendError, VellumError } from "../util/errors.js";
|
|
5
13
|
import {
|
|
@@ -226,6 +234,96 @@ describe("PlatformOAuthConnection", () => {
|
|
|
226
234
|
);
|
|
227
235
|
});
|
|
228
236
|
|
|
237
|
+
test("retries on 429 and succeeds", async () => {
|
|
238
|
+
let callCount = 0;
|
|
239
|
+
const client = makeMockClient(
|
|
240
|
+
mock(async () => {
|
|
241
|
+
callCount++;
|
|
242
|
+
if (callCount <= 2) {
|
|
243
|
+
return new Response("", { status: 429 });
|
|
244
|
+
}
|
|
245
|
+
return new Response(
|
|
246
|
+
JSON.stringify({ status: 200, headers: {}, body: { ok: true } }),
|
|
247
|
+
{ status: 200 },
|
|
248
|
+
);
|
|
249
|
+
}) as unknown as typeof globalThis.fetch,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
const conn = new PlatformOAuthConnection({ ...DEFAULT_OPTIONS, client });
|
|
253
|
+
const result = await conn.request({ method: "GET", path: "/test" });
|
|
254
|
+
|
|
255
|
+
expect(result.status).toBe(200);
|
|
256
|
+
expect(result.body).toEqual({ ok: true });
|
|
257
|
+
expect(callCount).toBe(3);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
test("throws after exhausting retries on 429", async () => {
|
|
261
|
+
const client = makeMockClient(
|
|
262
|
+
mock(
|
|
263
|
+
async () => new Response("", { status: 429 }),
|
|
264
|
+
) as unknown as typeof globalThis.fetch,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
const conn = new PlatformOAuthConnection({ ...DEFAULT_OPTIONS, client });
|
|
268
|
+
await expect(
|
|
269
|
+
conn.request({ method: "GET", path: "/test" }),
|
|
270
|
+
).rejects.toThrow("Platform proxy returned unexpected status 429");
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("retries on 500 and succeeds", async () => {
|
|
274
|
+
let callCount = 0;
|
|
275
|
+
const client = makeMockClient(
|
|
276
|
+
mock(async () => {
|
|
277
|
+
callCount++;
|
|
278
|
+
if (callCount === 1) {
|
|
279
|
+
return new Response("", { status: 500 });
|
|
280
|
+
}
|
|
281
|
+
return new Response(
|
|
282
|
+
JSON.stringify({ status: 200, headers: {}, body: null }),
|
|
283
|
+
{ status: 200 },
|
|
284
|
+
);
|
|
285
|
+
}) as unknown as typeof globalThis.fetch,
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const conn = new PlatformOAuthConnection({ ...DEFAULT_OPTIONS, client });
|
|
289
|
+
const result = await conn.request({ method: "GET", path: "/test" });
|
|
290
|
+
|
|
291
|
+
expect(result.status).toBe(200);
|
|
292
|
+
expect(callCount).toBe(2);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test("does not retry on 424", async () => {
|
|
296
|
+
let callCount = 0;
|
|
297
|
+
const client = makeMockClient(
|
|
298
|
+
mock(async () => {
|
|
299
|
+
callCount++;
|
|
300
|
+
return new Response("", { status: 424 });
|
|
301
|
+
}) as unknown as typeof globalThis.fetch,
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
const conn = new PlatformOAuthConnection({ ...DEFAULT_OPTIONS, client });
|
|
305
|
+
await expect(
|
|
306
|
+
conn.request({ method: "GET", path: "/test" }),
|
|
307
|
+
).rejects.toThrow(CredentialRequiredError);
|
|
308
|
+
expect(callCount).toBe(1);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("does not retry on 403", async () => {
|
|
312
|
+
let callCount = 0;
|
|
313
|
+
const client = makeMockClient(
|
|
314
|
+
mock(async () => {
|
|
315
|
+
callCount++;
|
|
316
|
+
return new Response("", { status: 403 });
|
|
317
|
+
}) as unknown as typeof globalThis.fetch,
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
const conn = new PlatformOAuthConnection({ ...DEFAULT_OPTIONS, client });
|
|
321
|
+
await expect(
|
|
322
|
+
conn.request({ method: "GET", path: "/test" }),
|
|
323
|
+
).rejects.toThrow("Platform proxy returned unexpected status 403");
|
|
324
|
+
expect(callCount).toBe(1);
|
|
325
|
+
});
|
|
326
|
+
|
|
229
327
|
test("uses connectionId in proxy URL regardless of provider format", async () => {
|
|
230
328
|
const client = makeMockClient(
|
|
231
329
|
mock(async (url: string | URL | Request) => {
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type { VellumPlatformClient } from "../platform/client.js";
|
|
2
2
|
import { BackendError } from "../util/errors.js";
|
|
3
|
+
import {
|
|
4
|
+
getHttpRetryDelay,
|
|
5
|
+
isRetryableStatus,
|
|
6
|
+
sleep,
|
|
7
|
+
} from "../util/retry.js";
|
|
3
8
|
import type {
|
|
4
9
|
OAuthConnection,
|
|
5
10
|
OAuthConnectionRequest,
|
|
6
11
|
OAuthConnectionResponse,
|
|
7
12
|
} from "./connection.js";
|
|
8
13
|
|
|
14
|
+
const MAX_RETRIES = 3;
|
|
15
|
+
|
|
9
16
|
export class CredentialRequiredError extends BackendError {
|
|
10
17
|
constructor(message = "Connection not set up on platform") {
|
|
11
18
|
super(message);
|
|
@@ -76,39 +83,53 @@ export class PlatformOAuthConnection implements OAuthConnection {
|
|
|
76
83
|
},
|
|
77
84
|
};
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
86
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
87
|
+
const response = await this.client.fetch(proxyPath, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: {
|
|
90
|
+
"Content-Type": "application/json",
|
|
91
|
+
},
|
|
92
|
+
body: JSON.stringify(body),
|
|
93
|
+
signal: req.signal,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (response.status === 424) {
|
|
97
|
+
throw new CredentialRequiredError();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (response.status === 502) {
|
|
101
|
+
throw new ProviderUnreachableError();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (
|
|
105
|
+
!response.ok &&
|
|
106
|
+
isRetryableStatus(response.status) &&
|
|
107
|
+
attempt < MAX_RETRIES
|
|
108
|
+
) {
|
|
109
|
+
await sleep(getHttpRetryDelay(response, attempt));
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!response.ok) {
|
|
114
|
+
throw new BackendError(
|
|
115
|
+
`Platform proxy returned unexpected status ${response.status}`,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const json = (await response.json()) as {
|
|
120
|
+
status: number;
|
|
121
|
+
headers: Record<string, string>;
|
|
122
|
+
body: unknown;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
status: json.status,
|
|
127
|
+
headers: json.headers,
|
|
128
|
+
body: json.body,
|
|
129
|
+
};
|
|
99
130
|
}
|
|
100
131
|
|
|
101
|
-
|
|
102
|
-
status: number;
|
|
103
|
-
headers: Record<string, string>;
|
|
104
|
-
body: unknown;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
status: json.status,
|
|
109
|
-
headers: json.headers,
|
|
110
|
-
body: json.body,
|
|
111
|
-
};
|
|
132
|
+
throw new BackendError("Platform proxy request failed after retries");
|
|
112
133
|
}
|
|
113
134
|
|
|
114
135
|
async withToken<T>(_fn: (token: string) => Promise<T>): Promise<T> {
|
|
@@ -27,6 +27,7 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
27
27
|
tokenExchangeUrl: string;
|
|
28
28
|
refreshUrl?: string;
|
|
29
29
|
tokenEndpointAuthMethod?: string;
|
|
30
|
+
tokenExchangeBodyFormat?: string;
|
|
30
31
|
userinfoUrl?: string;
|
|
31
32
|
pingUrl?: string;
|
|
32
33
|
pingMethod?: string;
|
|
@@ -85,6 +86,7 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
85
86
|
"https://www.googleapis.com/auth/gmail.readonly",
|
|
86
87
|
"https://www.googleapis.com/auth/gmail.modify",
|
|
87
88
|
"https://www.googleapis.com/auth/gmail.send",
|
|
89
|
+
"https://www.googleapis.com/auth/gmail.settings.basic",
|
|
88
90
|
"https://www.googleapis.com/auth/calendar.readonly",
|
|
89
91
|
"https://www.googleapis.com/auth/calendar.events",
|
|
90
92
|
"https://www.googleapis.com/auth/userinfo.email",
|
|
@@ -140,6 +142,7 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
140
142
|
clientIdPlaceholder: null,
|
|
141
143
|
logoUrl: "https://cdn.simpleicons.org/slack",
|
|
142
144
|
defaultScopes: [
|
|
145
|
+
"channels:join",
|
|
143
146
|
"channels:read",
|
|
144
147
|
"channels:history",
|
|
145
148
|
"groups:read",
|
|
@@ -199,6 +202,8 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
199
202
|
},
|
|
200
203
|
authorizeParams: { owner: "user" },
|
|
201
204
|
tokenEndpointAuthMethod: "client_secret_basic",
|
|
205
|
+
tokenExchangeBodyFormat: "json",
|
|
206
|
+
managedServiceConfigKey: "notion-oauth",
|
|
202
207
|
loopbackPort: 17323,
|
|
203
208
|
injectionTemplates: [
|
|
204
209
|
{
|
|
@@ -238,6 +243,8 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
238
243
|
},
|
|
239
244
|
tokenEndpointAuthMethod: "client_secret_basic",
|
|
240
245
|
loopbackPort: 17335,
|
|
246
|
+
managedServiceConfigKey: "twitter-oauth",
|
|
247
|
+
featureFlag: "managed-x-oauth-integration",
|
|
241
248
|
injectionTemplates: [
|
|
242
249
|
{
|
|
243
250
|
hostPattern: "api.x.com",
|
|
@@ -20,7 +20,11 @@ import {
|
|
|
20
20
|
looksLikePathOnlyInput,
|
|
21
21
|
} from "../tools/network/url-safety.js";
|
|
22
22
|
import { getTool } from "../tools/registry.js";
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
getDeprecatedDir,
|
|
25
|
+
getProtectedDir,
|
|
26
|
+
getWorkspaceHooksDir,
|
|
27
|
+
} from "../util/platform.js";
|
|
24
28
|
import {
|
|
25
29
|
buildShellAllowlistOptions,
|
|
26
30
|
buildShellCommandCandidates,
|
|
@@ -962,11 +966,17 @@ function isActorTokenSigningKeyPath(
|
|
|
962
966
|
if (!filePath) return false;
|
|
963
967
|
const cwd = workingDir ?? process.cwd();
|
|
964
968
|
const resolvedPath = resolve(cwd, filePath);
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
969
|
+
// Include both the per-instance protected dir AND the legacy global
|
|
970
|
+
// ~/.vellum/protected path so upgraded machines with a host-wide signing
|
|
971
|
+
// key still classify reads as High risk.
|
|
972
|
+
const signingKeyPaths = Array.from(
|
|
973
|
+
new Set([
|
|
974
|
+
join(homedir(), ".vellum", "protected", "actor-token-signing-key"),
|
|
975
|
+
join(getProtectedDir(), "actor-token-signing-key"),
|
|
976
|
+
join(getDeprecatedDir(), "actor-token-signing-key"),
|
|
977
|
+
resolve(cwd, "deprecated", "actor-token-signing-key"),
|
|
978
|
+
]),
|
|
979
|
+
);
|
|
970
980
|
return signingKeyPaths.includes(resolvedPath);
|
|
971
981
|
}
|
|
972
982
|
|
|
@@ -3,6 +3,7 @@ import { join } from "node:path";
|
|
|
3
3
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
4
4
|
import { getConfig } from "../config/loader.js";
|
|
5
5
|
import { getBundledSkillsDir } from "../config/skills.js";
|
|
6
|
+
import { resolveGuardianPersonaPath } from "../prompts/persona-resolver.js";
|
|
6
7
|
import { getWorkspaceDir } from "../util/platform.js";
|
|
7
8
|
|
|
8
9
|
export interface DefaultRuleTemplate {
|
|
@@ -15,6 +16,16 @@ export interface DefaultRuleTemplate {
|
|
|
15
16
|
allowHighRisk?: boolean;
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Escape minimatch metacharacters so a literal path is matched literally when
|
|
21
|
+
* interpolated into a rule pattern. Without this, characters like `*`, `?`,
|
|
22
|
+
* `[`, `]`, `{`, `}` in a filename would be treated as wildcards and broaden
|
|
23
|
+
* the resulting allow rule beyond the intended file.
|
|
24
|
+
*/
|
|
25
|
+
function escapeMinimatchPath(p: string): string {
|
|
26
|
+
return p.replace(/[?*[\]{}()!|\\]/g, "\\$&");
|
|
27
|
+
}
|
|
28
|
+
|
|
18
29
|
const HOST_FILE_TOOLS = [
|
|
19
30
|
"host_file_read",
|
|
20
31
|
"host_file_write",
|
|
@@ -118,7 +129,6 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
118
129
|
const workspaceDir = getWorkspaceDir().replaceAll("\\", "/");
|
|
119
130
|
const WORKSPACE_PROMPT_FILES = [
|
|
120
131
|
"IDENTITY.md",
|
|
121
|
-
"USER.md",
|
|
122
132
|
"SOUL.md",
|
|
123
133
|
"BOOTSTRAP.md",
|
|
124
134
|
"UPDATES.md",
|
|
@@ -139,6 +149,40 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
139
149
|
})),
|
|
140
150
|
);
|
|
141
151
|
|
|
152
|
+
// Guardian persona file — the contact-store-resolved `users/<slug>.md`
|
|
153
|
+
// for the current guardian. Once the workspace has a guardian contact,
|
|
154
|
+
// their per-user persona file should be readable/editable without a
|
|
155
|
+
// prompt.
|
|
156
|
+
//
|
|
157
|
+
// Resolved dynamically at template-build time (rather than hardcoded
|
|
158
|
+
// like WORKSPACE_PROMPT_FILES) because the slug depends on the
|
|
159
|
+
// installed guardian. The try/catch protects against early-boot paths
|
|
160
|
+
// where the DB may not yet be initialized — in that case no guardian
|
|
161
|
+
// persona rules are emitted and the agent will be prompted on first
|
|
162
|
+
// edit until the guardian contact is created.
|
|
163
|
+
let guardianPersonaRules: DefaultRuleTemplate[] = [];
|
|
164
|
+
try {
|
|
165
|
+
const guardianPath = resolveGuardianPersonaPath();
|
|
166
|
+
if (guardianPath) {
|
|
167
|
+
const posixPath = guardianPath.replaceAll("\\", "/");
|
|
168
|
+
const escapedPath = escapeMinimatchPath(posixPath);
|
|
169
|
+
guardianPersonaRules = WORKSPACE_FILE_TOOLS.map((tool) => ({
|
|
170
|
+
id: `default:allow-${tool}-guardian-persona`,
|
|
171
|
+
tool,
|
|
172
|
+
pattern: `${tool}:${escapedPath}`,
|
|
173
|
+
scope: "everywhere",
|
|
174
|
+
decision: "allow" as const,
|
|
175
|
+
priority: 100,
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
// If guardian resolution fails at default-rule computation, the rule
|
|
180
|
+
// will be missing until the trust cache is invalidated and rebuilt.
|
|
181
|
+
// Runtime guardian-creation paths invalidate the cache via
|
|
182
|
+
// `clearTrustCache()` in `contacts-write.createGuardianBinding` so
|
|
183
|
+
// that the next `getRules()` call picks up the new auto-allow rule.
|
|
184
|
+
}
|
|
185
|
+
|
|
142
186
|
const bootstrapDeleteRule: DefaultRuleTemplate = {
|
|
143
187
|
id: "default:allow-bash-rm-bootstrap",
|
|
144
188
|
tool: "bash",
|
|
@@ -248,6 +292,8 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
248
292
|
"browser_snapshot",
|
|
249
293
|
"browser_screenshot",
|
|
250
294
|
"browser_close",
|
|
295
|
+
"browser_attach",
|
|
296
|
+
"browser_detach",
|
|
251
297
|
"browser_click",
|
|
252
298
|
"browser_type",
|
|
253
299
|
"browser_press_key",
|
|
@@ -258,6 +304,7 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
258
304
|
"browser_extract",
|
|
259
305
|
"browser_wait_for_download",
|
|
260
306
|
"browser_fill_credential",
|
|
307
|
+
"browser_status",
|
|
261
308
|
] as const;
|
|
262
309
|
|
|
263
310
|
const browserToolRules: DefaultRuleTemplate[] = BROWSER_TOOLS_NO_SLASH.map(
|
|
@@ -303,6 +350,7 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
303
350
|
...computerUseRules,
|
|
304
351
|
...managedSkillRules,
|
|
305
352
|
...workspacePromptRules,
|
|
353
|
+
...guardianPersonaRules,
|
|
306
354
|
bootstrapDeleteRule,
|
|
307
355
|
updatesDeleteRule,
|
|
308
356
|
...skillSourceMutationRules,
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
renameSync,
|
|
7
7
|
writeFileSync,
|
|
8
8
|
} from "node:fs";
|
|
9
|
-
import { homedir } from "node:os";
|
|
10
9
|
import { dirname, join } from "node:path";
|
|
11
10
|
|
|
12
11
|
import { Minimatch } from "minimatch";
|
|
@@ -14,6 +13,7 @@ import { v4 as uuid } from "uuid";
|
|
|
14
13
|
|
|
15
14
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
16
15
|
import { getLogger } from "../util/logger.js";
|
|
16
|
+
import { getProtectedDir } from "../util/platform.js";
|
|
17
17
|
import { getDefaultRuleTemplates } from "./defaults.js";
|
|
18
18
|
import * as trustClient from "./trust-client.js";
|
|
19
19
|
import type {
|
|
@@ -135,12 +135,12 @@ function getTrustPath(): string {
|
|
|
135
135
|
* Resolve the gateway security directory.
|
|
136
136
|
*
|
|
137
137
|
* Docker: `GATEWAY_SECURITY_DIR` env var.
|
|
138
|
-
* Local:
|
|
138
|
+
* Local: the per-instance protected directory resolved by `getProtectedDir()`.
|
|
139
139
|
*/
|
|
140
140
|
function getGatewaySecurityDir(): string {
|
|
141
141
|
const securityDir = process.env.GATEWAY_SECURITY_DIR;
|
|
142
142
|
if (securityDir) return securityDir;
|
|
143
|
-
return
|
|
143
|
+
return getProtectedDir();
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
/**
|
|
@@ -23,6 +23,16 @@ mock.module("../config/env.js", () => ({
|
|
|
23
23
|
getPlatformAssistantId: () => mockAssistantId,
|
|
24
24
|
}));
|
|
25
25
|
|
|
26
|
+
// Stub the credential-store fallback so tests stay hermetic and do not
|
|
27
|
+
// read real values from the host credential backend.
|
|
28
|
+
mock.module("../security/secure-keys.js", () => ({
|
|
29
|
+
getSecureKeyAsync: async () => null,
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
mock.module("../security/credential-key.js", () => ({
|
|
33
|
+
credentialKey: (namespace: string, key: string) => `${namespace}:${key}`,
|
|
34
|
+
}));
|
|
35
|
+
|
|
26
36
|
// ---------------------------------------------------------------------------
|
|
27
37
|
// Import under test (after mocks)
|
|
28
38
|
// ---------------------------------------------------------------------------
|