@vellumai/assistant 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +273 -10
- package/Dockerfile +2 -3
- package/bun.lock +41 -49
- package/bunfig.toml +3 -0
- package/docs/architecture/memory.md +1 -1
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/stt-provider-onboarding.md +120 -0
- package/knip.json +12 -2
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +3 -3
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +1111 -86
- package/package.json +40 -42
- package/scripts/generate-openapi.ts +0 -2
- package/scripts/test.sh +73 -18
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop.test.ts +123 -0
- package/src/__tests__/anthropic-provider.test.ts +263 -10
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
- package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
- package/src/__tests__/browser-fill-credential.test.ts +240 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/browser-skill-endstate.test.ts +31 -7
- package/src/__tests__/btw-routes.test.ts +7 -0
- package/src/__tests__/call-controller.test.ts +581 -20
- package/src/__tests__/catalog-files.test.ts +1000 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/channel-invite-transport.test.ts +2 -2
- package/src/__tests__/channel-readiness-routes.test.ts +16 -20
- package/src/__tests__/channel-readiness-service.test.ts +12 -7
- package/src/__tests__/checker.test.ts +157 -10
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/config-analysis.test.ts +100 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +1248 -224
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +43 -8
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/contact-store-user-file.test.ts +512 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-overflow-approval.test.ts +16 -1
- package/src/__tests__/context-window-manager.test.ts +88 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +99 -3
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +290 -0
- package/src/__tests__/conversation-error.test.ts +70 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +12 -4
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +946 -62
- package/src/__tests__/conversation-routes-disk-view.test.ts +275 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +324 -46
- package/src/__tests__/conversation-skill-tools.test.ts +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +89 -18
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +6 -3
- package/src/__tests__/credential-vault-unit.test.ts +383 -7
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +42 -18
- package/src/__tests__/cross-provider-web-search.test.ts +146 -35
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +222 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +386 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +2 -0
- package/src/__tests__/gemini-provider.test.ts +66 -2
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
- package/src/__tests__/gmail-archive-gate.test.ts +246 -0
- package/src/__tests__/gmail-preferences.test.ts +117 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +738 -359
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +528 -49
- package/src/__tests__/headless-browser-read-tools.test.ts +274 -100
- package/src/__tests__/headless-browser-snapshot.test.ts +250 -77
- package/src/__tests__/heartbeat-service.test.ts +70 -17
- package/src/__tests__/home-state-routes.test.ts +162 -0
- package/src/__tests__/host-bash-proxy.test.ts +145 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +596 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +423 -0
- package/src/__tests__/host-cu-proxy.test.ts +166 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/llm-context-normalization.test.ts +488 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/media-stream-output.test.ts +555 -0
- package/src/__tests__/media-stream-parser.test.ts +374 -0
- package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
- package/src/__tests__/media-stream-stt-session.test.ts +588 -0
- package/src/__tests__/media-turn-detector.test.ts +440 -0
- package/src/__tests__/message-queue.test.ts +125 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +67 -8
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +109 -7
- package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +151 -0
- package/src/__tests__/model-intents.test.ts +2 -2
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/oauth-apps-routes.test.ts +18 -12
- package/src/__tests__/oauth-cli.test.ts +709 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +118 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +147 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +52 -14
- package/src/__tests__/oauth-store.test.ts +1465 -176
- package/src/__tests__/oauth2-gateway-transport.test.ts +460 -26
- package/src/__tests__/onboarding-template-contract.test.ts +81 -70
- package/src/__tests__/openai-provider.test.ts +178 -2
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1105 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +32 -3
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +343 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +174 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
- package/src/__tests__/relationship-state-contract.test.ts +175 -0
- package/src/__tests__/relay-server.test.ts +423 -5
- package/src/__tests__/require-fresh-approval.test.ts +40 -1
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/secret-scanner-executor.test.ts +4 -0
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +8 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +49 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +801 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +738 -0
- package/src/__tests__/skills.test.ts +5 -2
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +576 -16
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +184 -27
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +25 -5
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +33 -24
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +14 -29
- package/src/__tests__/trust-store.test.ts +7 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/tts-catalog-parity.test.ts +345 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
- package/src/__tests__/twilio-routes.test.ts +376 -0
- package/src/__tests__/unicode.test.ts +293 -0
- package/src/__tests__/update-bulletin-format.test.ts +59 -0
- package/src/__tests__/update-bulletin.test.ts +206 -5
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
- package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
- package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
- package/src/__tests__/workspace-migration-meets.test.ts +244 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
- package/src/__tests__/workspace-policy.test.ts +2 -0
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +55 -9
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/backup/__tests__/backup-key.test.ts +152 -0
- package/src/backup/__tests__/backup-worker.test.ts +767 -0
- package/src/backup/__tests__/list-snapshots.test.ts +87 -0
- package/src/backup/__tests__/local-writer.test.ts +218 -0
- package/src/backup/__tests__/offsite-writer.test.ts +641 -0
- package/src/backup/__tests__/paths.test.ts +300 -0
- package/src/backup/__tests__/restore.test.ts +498 -0
- package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
- package/src/backup/__tests__/stream-crypt.test.ts +228 -0
- package/src/backup/backup-key.ts +137 -0
- package/src/backup/backup-worker.ts +459 -0
- package/src/backup/list-snapshots.ts +147 -0
- package/src/backup/local-writer.ts +133 -0
- package/src/backup/offsite-writer.ts +222 -0
- package/src/backup/paths.ts +226 -0
- package/src/backup/restore.ts +322 -0
- package/src/backup/snapshot-lock.ts +431 -0
- package/src/backup/stream-crypt.ts +263 -0
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/bundler/package-resolver.ts +4 -0
- package/src/calls/audio-store.ts +11 -5
- package/src/calls/call-controller.ts +226 -71
- package/src/calls/call-domain.ts +9 -0
- package/src/calls/call-speech-output.ts +190 -0
- package/src/calls/call-transport.ts +77 -0
- package/src/calls/media-stream-audio-transcode.ts +173 -0
- package/src/calls/media-stream-output.ts +660 -0
- package/src/calls/media-stream-parser.ts +300 -0
- package/src/calls/media-stream-protocol.ts +166 -0
- package/src/calls/media-stream-server.ts +592 -0
- package/src/calls/media-stream-stt-session.ts +460 -0
- package/src/calls/media-turn-detector.ts +230 -0
- package/src/calls/relay-server.ts +90 -75
- package/src/calls/resolve-call-tts-provider.ts +136 -0
- package/src/calls/telephony-stt-routing.ts +145 -0
- package/src/calls/tts-call-strategy.ts +161 -0
- package/src/calls/tts-text-sanitizer.ts +32 -16
- package/src/calls/twilio-routes.ts +281 -17
- package/src/calls/voice-quality.ts +78 -35
- package/src/calls/voice-session-bridge.ts +8 -1
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +69 -3
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
- package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
- package/src/cli/commands/__tests__/email-download.test.ts +16 -1
- package/src/cli/commands/__tests__/email-list.test.ts +22 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +37 -4
- package/src/cli/commands/__tests__/email-status.test.ts +5 -1
- package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/conversations.ts +77 -0
- package/src/cli/commands/credentials.ts +3 -4
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +273 -16
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +56 -44
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +32 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +330 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +117 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +6 -3
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +215 -36
- package/src/cli/commands/oauth/shared.ts +7 -6
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +254 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +30 -4
- package/src/config/__tests__/backup-schema.test.ts +134 -0
- package/src/config/assistant-feature-flags.ts +61 -62
- package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +141 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/browser/SKILL.md +30 -5
- package/src/config/bundled-skills/browser/TOOLS.json +123 -0
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
- package/src/config/bundled-skills/contacts/SKILL.md +5 -2
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +54 -8
- package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
- package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
- package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/outlook/SKILL.md +9 -2
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
- package/src/config/bundled-skills/slack/SKILL.md +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
- package/src/config/bundled-tool-registry.ts +8 -0
- package/src/config/env-registry.ts +38 -0
- package/src/config/env.ts +49 -4
- package/src/config/feature-flag-registry.json +85 -14
- package/src/config/loader.ts +82 -13
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +81 -15
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +51 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -26
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +47 -7
- package/src/config/schemas/heartbeat.ts +27 -5
- package/src/config/schemas/host-browser.ts +112 -0
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +52 -0
- package/src/config/schemas/stt.ts +59 -0
- package/src/config/schemas/tts.ts +230 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/skills.ts +4 -0
- package/src/config/types.ts +4 -1
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/post-turn-tool-result-truncation.ts +177 -0
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +61 -10
- package/src/credential-execution/approval-bridge.ts +49 -15
- package/src/credential-execution/executable-discovery.ts +12 -2
- package/src/credential-execution/process-manager.ts +33 -2
- package/src/credential-health/credential-health-service.ts +366 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +195 -0
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +99 -5
- package/src/daemon/context-overflow-approval.ts +5 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +23 -2
- package/src/daemon/conversation-agent-loop.ts +153 -42
- package/src/daemon/conversation-attachments.ts +40 -0
- package/src/daemon/conversation-error.ts +11 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +59 -9
- package/src/daemon/conversation-messaging.ts +37 -3
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +622 -13
- package/src/daemon/conversation-queue-manager.ts +24 -0
- package/src/daemon/conversation-runtime-assembly.ts +128 -36
- package/src/daemon/conversation-slash.ts +36 -0
- package/src/daemon/conversation-surfaces.ts +131 -40
- package/src/daemon/conversation-tool-setup.ts +99 -8
- package/src/daemon/conversation-usage.ts +7 -4
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +292 -16
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +13 -141
- package/src/daemon/handlers/shared.ts +80 -0
- package/src/daemon/handlers/skills.ts +483 -44
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +192 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +179 -28
- package/src/daemon/message-protocol.ts +13 -0
- package/src/daemon/message-types/conversations.ts +89 -14
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +19 -5
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +26 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/server.ts +439 -14
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +15 -0
- package/src/daemon/transport-hints.ts +5 -24
- package/src/email/html-renderer.ts +76 -0
- package/src/heartbeat/heartbeat-service.ts +93 -7
- package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
- package/src/home/__tests__/emit-feed-event.test.ts +169 -0
- package/src/home/__tests__/feed-scheduler.test.ts +194 -0
- package/src/home/__tests__/feed-types.test.ts +275 -0
- package/src/home/__tests__/feed-writer.test.ts +688 -0
- package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
- package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
- package/src/home/__tests__/progress-formula.test.ts +213 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
- package/src/home/__tests__/rollup-producer.test.ts +398 -0
- package/src/home/assistant-feed-authoring.ts +124 -0
- package/src/home/emit-feed-event.ts +158 -0
- package/src/home/feed-scheduler.ts +247 -0
- package/src/home/feed-types.ts +181 -0
- package/src/home/feed-writer.ts +469 -0
- package/src/home/platform-gmail-digest.ts +163 -0
- package/src/home/progress-formula.ts +86 -0
- package/src/home/relationship-state-writer.ts +824 -0
- package/src/home/relationship-state.ts +143 -0
- package/src/home/rollup-producer.ts +384 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +30 -20
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/cli-client.ts +151 -0
- package/src/ipc/cli-server.ts +234 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/index.ts +5 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/mcp/client.ts +59 -24
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
- package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/app-store.ts +31 -1
- package/src/memory/attachments-store.ts +70 -0
- package/src/memory/auto-analysis-enqueue.ts +127 -0
- package/src/memory/auto-analysis-guard.ts +27 -0
- package/src/memory/cleanup-schedule-state.ts +37 -0
- package/src/memory/conversation-analyze-job.ts +73 -0
- package/src/memory/conversation-crud.ts +122 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +34 -2
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +18 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +176 -17
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/conversation-graph-memory.ts +15 -0
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/extraction.test.ts +23 -0
- package/src/memory/graph/extraction.ts +8 -0
- package/src/memory/graph/retriever.ts +67 -40
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/group-crud.ts +6 -1
- package/src/memory/indexer.ts +95 -16
- package/src/memory/job-handlers/cleanup.ts +11 -8
- package/src/memory/job-handlers/conversation-starters.ts +16 -10
- package/src/memory/jobs-store.ts +64 -4
- package/src/memory/jobs-worker.ts +22 -9
- package/src/memory/llm-usage-store.ts +137 -60
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
- package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/oauth.ts +21 -13
- package/src/memory/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/client.ts +57 -6
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +143 -38
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/decision-engine.ts +3 -3
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +25 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +26 -9
- package/src/oauth/byo-connection.ts +10 -8
- package/src/oauth/connect-orchestrator.ts +25 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +22 -18
- package/src/oauth/connection.ts +3 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +223 -100
- package/src/oauth/platform-connection.test.ts +101 -3
- package/src/oauth/platform-connection.ts +56 -35
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +133 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +16 -6
- package/src/permissions/defaults.ts +49 -1
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -1
- package/src/permissions/trust-store.ts +3 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/permissions/workspace-policy.ts +3 -0
- package/src/platform/client.test.ts +10 -0
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +126 -2
- package/src/prompts/system-prompt.ts +76 -38
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -105
- package/src/prompts/templates/SOUL.md +3 -1
- package/src/prompts/templates/UPDATES.md +12 -0
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-format.ts +26 -9
- package/src/prompts/update-bulletin.ts +34 -23
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/anthropic/client.ts +157 -60
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +9 -1
- package/src/providers/model-catalog.ts +6 -0
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +474 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +502 -0
- package/src/providers/openrouter/client.ts +101 -4
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +14 -3
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
- package/src/providers/speech-to-text/deepgram.test.ts +332 -0
- package/src/providers/speech-to-text/deepgram.ts +115 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
- package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
- package/src/providers/speech-to-text/google-gemini.ts +101 -0
- package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
- package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
- package/src/providers/speech-to-text/openai-whisper.ts +63 -33
- package/src/providers/speech-to-text/provider-catalog.ts +306 -0
- package/src/providers/speech-to-text/resolve.ts +386 -6
- package/src/providers/types.ts +10 -1
- package/src/runtime/AGENTS.md +65 -0
- package/src/runtime/__tests__/agent-wake.test.ts +831 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
- package/src/runtime/agent-wake.ts +512 -0
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +48 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +33 -9
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-invite-transports/email.ts +14 -6
- package/src/runtime/channel-readiness-service.ts +12 -22
- package/src/runtime/chrome-extension-registry.ts +368 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +815 -75
- package/src/runtime/http-types.ts +6 -2
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +198 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/migration-transport.ts +7 -0
- package/src/runtime/migrations/migration-wizard.ts +23 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +96 -1
- package/src/runtime/migrations/vbundle-importer.ts +89 -5
- package/src/runtime/pending-interactions.ts +18 -13
- package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
- package/src/runtime/routes/app-management-routes.ts +12 -18
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +556 -0
- package/src/runtime/routes/btw-routes.ts +8 -6
- package/src/runtime/routes/contact-routes.test.ts +298 -0
- package/src/runtime/routes/contact-routes.ts +132 -5
- package/src/runtime/routes/conversation-analysis-routes.ts +22 -141
- package/src/runtime/routes/conversation-management-routes.ts +223 -0
- package/src/runtime/routes/conversation-routes.ts +598 -103
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/home-feed-routes.ts +334 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +268 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +262 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
- package/src/runtime/routes/integrations/slack/channel.ts +11 -3
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +303 -0
- package/src/runtime/routes/log-export-routes.ts +42 -22
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +122 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +31 -102
- package/src/runtime/routes/skills-routes.ts +128 -9
- package/src/runtime/routes/stt-routes.ts +233 -0
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/surface-action-routes.ts +41 -2
- package/src/runtime/routes/tts-routes.ts +108 -24
- package/src/runtime/routes/usage-routes.ts +38 -9
- package/src/runtime/routes/user-route-dispatcher.ts +50 -5
- package/src/runtime/routes/user-routes.ts +13 -1
- package/src/runtime/routes/work-items-routes.ts +8 -1
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
- package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
- package/src/runtime/services/analyze-conversation.ts +344 -0
- package/src/runtime/services/analyze-deps-singleton.ts +32 -0
- package/src/runtime/services/auto-analysis-prompt.ts +55 -0
- package/src/runtime/skill-route-registry.ts +49 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +57 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +68 -29
- package/src/security/secure-keys.ts +143 -27
- package/src/security/token-manager.ts +31 -10
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-files.ts +554 -0
- package/src/skills/category-inference.ts +122 -0
- package/src/skills/clawhub-files.ts +213 -0
- package/src/skills/clawhub.ts +84 -23
- package/src/skills/skill-file-provider.ts +40 -0
- package/src/skills/skillssh-files.ts +395 -0
- package/src/skills/skillssh-registry.ts +4 -4
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +195 -0
- package/src/stt/stt-stream-session.ts +499 -0
- package/src/stt/types.ts +330 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +169 -40
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +1787 -342
- package/src/tools/browser/browser-manager.ts +81 -12
- package/src/tools/browser/browser-mode-constants.ts +12 -0
- package/src/tools/browser/browser-mode.ts +92 -0
- package/src/tools/browser/browser-status-constants.ts +33 -0
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1263 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +359 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1993 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +1007 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +744 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +868 -0
- package/src/tools/browser/cdp-client/errors.ts +49 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +148 -0
- package/src/tools/browser/cdp-client/factory.ts +914 -0
- package/src/tools/browser/cdp-client/index.ts +28 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +120 -0
- package/src/tools/credentials/vault.ts +35 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/network/web-fetch.ts +5 -2
- package/src/tools/network/web-search.ts +5 -2
- package/src/tools/permission-checker.ts +77 -82
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -0
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +2 -0
- package/src/tools/skills/sandbox-runner.ts +3 -2
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +15 -0
- package/src/tools/terminal/shell.ts +36 -20
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/tool-manifest.ts +21 -0
- package/src/tools/types.ts +19 -0
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tts/__tests__/provider-adapters.test.ts +834 -0
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
- package/src/tts/__tests__/provider-catalog.test.ts +183 -0
- package/src/tts/__tests__/provider-registry.test.ts +90 -0
- package/src/tts/provider-catalog.ts +201 -0
- package/src/tts/provider-registry.ts +73 -0
- package/src/tts/providers/deepgram-provider.ts +219 -0
- package/src/tts/providers/elevenlabs-provider.ts +211 -0
- package/src/tts/providers/fish-audio-provider.ts +183 -0
- package/src/tts/providers/index.ts +42 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +153 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/util/abort-reasons.ts +58 -0
- package/src/util/device-id.ts +32 -16
- package/src/util/errors.ts +9 -1
- package/src/util/platform.ts +63 -24
- package/src/util/pricing.ts +66 -3
- package/src/util/spawn.ts +1 -1
- package/src/util/truncate.ts +4 -2
- package/src/util/unicode.ts +201 -0
- package/src/version.ts +19 -24
- package/src/watcher/engine.ts +23 -0
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/migrations/003-seed-device-id.ts +9 -3
- package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
- package/src/workspace/migrations/029-seed-pkb.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +317 -0
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
- package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
- package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
- package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/top-level-renderer.ts +31 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/cli/commands/browser-relay.ts +0 -536
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/email/guardrails.ts +0 -221
- package/src/email/provider.ts +0 -117
- package/src/email/providers/agentmail.ts +0 -361
- package/src/email/providers/index.ts +0 -65
- package/src/email/service.ts +0 -384
- package/src/email/types.ts +0 -126
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/prompts/templates/USER.md +0 -13
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
package/src/security/oauth2.ts
CHANGED
|
@@ -33,13 +33,13 @@ export type TokenEndpointAuthMethod =
|
|
|
33
33
|
| "client_secret_post";
|
|
34
34
|
|
|
35
35
|
export interface OAuth2Config {
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
authorizeUrl: string;
|
|
37
|
+
tokenExchangeUrl: string;
|
|
38
38
|
scopes: string[];
|
|
39
39
|
clientId: string;
|
|
40
40
|
/** Client secret for providers that require it (e.g. Slack). PKCE is always used regardless. */
|
|
41
41
|
clientSecret?: string;
|
|
42
|
-
|
|
42
|
+
authorizeParams?: Record<string, string>;
|
|
43
43
|
/** URL to fetch user identity info after OAuth. If omitted, account info is not fetched. */
|
|
44
44
|
userinfoUrl?: string;
|
|
45
45
|
/**
|
|
@@ -49,6 +49,20 @@ export interface OAuth2Config {
|
|
|
49
49
|
* Defaults to `client_secret_post`.
|
|
50
50
|
*/
|
|
51
51
|
tokenEndpointAuthMethod?: TokenEndpointAuthMethod;
|
|
52
|
+
/**
|
|
53
|
+
* Separator used to join scopes in the authorize URL and split the
|
|
54
|
+
* granted-scope string returned by the token endpoint. Defaults to
|
|
55
|
+
* `" "` (space) per the OAuth 2.0 spec, but providers like Linear
|
|
56
|
+
* use `","` (comma).
|
|
57
|
+
*/
|
|
58
|
+
scopeSeparator: string;
|
|
59
|
+
/**
|
|
60
|
+
* Body encoding format for the token exchange and refresh requests.
|
|
61
|
+
* - `"form"` (default): `application/x-www-form-urlencoded` with `URLSearchParams`.
|
|
62
|
+
* - `"json"`: `application/json` with `JSON.stringify`.
|
|
63
|
+
* Providers like Notion require JSON-encoded bodies at their token endpoint.
|
|
64
|
+
*/
|
|
65
|
+
tokenExchangeBodyFormat?: "form" | "json";
|
|
52
66
|
}
|
|
53
67
|
|
|
54
68
|
export interface OAuth2TokenResult {
|
|
@@ -106,6 +120,7 @@ async function exchangeCodeForTokens(
|
|
|
106
120
|
codeVerifier: string,
|
|
107
121
|
): Promise<OAuth2FlowResult> {
|
|
108
122
|
const authMethod = config.tokenEndpointAuthMethod ?? "client_secret_post";
|
|
123
|
+
const bodyFormat = config.tokenExchangeBodyFormat ?? "form";
|
|
109
124
|
|
|
110
125
|
const tokenBody: Record<string, string> = {
|
|
111
126
|
grant_type: "authorization_code",
|
|
@@ -115,7 +130,11 @@ async function exchangeCodeForTokens(
|
|
|
115
130
|
};
|
|
116
131
|
|
|
117
132
|
const headers: Record<string, string> = {
|
|
118
|
-
"Content-Type":
|
|
133
|
+
"Content-Type":
|
|
134
|
+
bodyFormat === "json"
|
|
135
|
+
? "application/json"
|
|
136
|
+
: "application/x-www-form-urlencoded",
|
|
137
|
+
Accept: "application/json",
|
|
119
138
|
};
|
|
120
139
|
|
|
121
140
|
if (config.clientSecret && authMethod === "client_secret_basic") {
|
|
@@ -130,10 +149,13 @@ async function exchangeCodeForTokens(
|
|
|
130
149
|
}
|
|
131
150
|
}
|
|
132
151
|
|
|
133
|
-
const tokenResp = await fetch(config.
|
|
152
|
+
const tokenResp = await fetch(config.tokenExchangeUrl, {
|
|
134
153
|
method: "POST",
|
|
135
154
|
headers,
|
|
136
|
-
body:
|
|
155
|
+
body:
|
|
156
|
+
bodyFormat === "json"
|
|
157
|
+
? JSON.stringify(tokenBody)
|
|
158
|
+
: new URLSearchParams(tokenBody),
|
|
137
159
|
});
|
|
138
160
|
|
|
139
161
|
if (!tokenResp.ok) {
|
|
@@ -187,9 +209,19 @@ async function exchangeCodeForTokens(
|
|
|
187
209
|
(tokenData.token_type as string | undefined),
|
|
188
210
|
};
|
|
189
211
|
|
|
212
|
+
// Defensive split: providers (e.g. GitHub, Slack) may return comma-separated
|
|
213
|
+
// scopes in token responses regardless of the scope_separator used to join
|
|
214
|
+
// outbound authorize URLs, so we tolerate both spaces and commas here. When
|
|
215
|
+
// a provider explicitly configures a non-default separator (e.g. Linear uses
|
|
216
|
+
// ","), we honor that to keep symmetric round-tripping of configured scopes.
|
|
217
|
+
const splitPattern =
|
|
218
|
+
config.scopeSeparator === " " ? /[ ,]/ : config.scopeSeparator;
|
|
190
219
|
const grantedScopes =
|
|
191
220
|
typeof tokens.scope === "string"
|
|
192
|
-
? tokens.scope
|
|
221
|
+
? tokens.scope
|
|
222
|
+
.split(splitPattern)
|
|
223
|
+
.map((s) => s.trim())
|
|
224
|
+
.filter(Boolean)
|
|
193
225
|
: [...config.scopes];
|
|
194
226
|
|
|
195
227
|
return { tokens, grantedScopes, rawTokenResponse: tokenData };
|
|
@@ -228,18 +260,18 @@ async function runGatewayFlow(
|
|
|
228
260
|
});
|
|
229
261
|
|
|
230
262
|
const authParams = new URLSearchParams({
|
|
231
|
-
...config.
|
|
263
|
+
...config.authorizeParams,
|
|
232
264
|
client_id: config.clientId,
|
|
233
265
|
redirect_uri: redirectUri,
|
|
234
266
|
response_type: "code",
|
|
235
|
-
scope: config.scopes.join(
|
|
267
|
+
scope: config.scopes.join(config.scopeSeparator),
|
|
236
268
|
state,
|
|
237
269
|
code_challenge: codeChallenge,
|
|
238
270
|
code_challenge_method: "S256",
|
|
239
271
|
});
|
|
240
272
|
|
|
241
|
-
const
|
|
242
|
-
callbacks.openUrl(
|
|
273
|
+
const authorizeUrl = `${config.authorizeUrl}?${authParams}`;
|
|
274
|
+
callbacks.openUrl(authorizeUrl);
|
|
243
275
|
|
|
244
276
|
const code = await codePromise;
|
|
245
277
|
|
|
@@ -401,22 +433,22 @@ function startLoopbackServerAndWaitForCode(
|
|
|
401
433
|
);
|
|
402
434
|
|
|
403
435
|
const authParams = new URLSearchParams({
|
|
404
|
-
...config.
|
|
436
|
+
...config.authorizeParams,
|
|
405
437
|
client_id: config.clientId,
|
|
406
438
|
redirect_uri: boundRedirectUri,
|
|
407
439
|
response_type: "code",
|
|
408
|
-
scope: config.scopes.join(
|
|
440
|
+
scope: config.scopes.join(config.scopeSeparator),
|
|
409
441
|
state,
|
|
410
442
|
code_challenge: codeChallenge,
|
|
411
443
|
code_challenge_method: "S256",
|
|
412
444
|
});
|
|
413
445
|
|
|
414
|
-
const
|
|
446
|
+
const authorizeUrl = `${config.authorizeUrl}?${authParams}`;
|
|
415
447
|
log.info(
|
|
416
|
-
{
|
|
448
|
+
{ authorizeUrlLength: authorizeUrl.length, state },
|
|
417
449
|
"oauth2 loopback: built auth URL, calling openUrl callback",
|
|
418
450
|
);
|
|
419
|
-
callbacks.openUrl(
|
|
451
|
+
callbacks.openUrl(authorizeUrl);
|
|
420
452
|
log.info("oauth2 loopback: openUrl callback returned");
|
|
421
453
|
});
|
|
422
454
|
|
|
@@ -439,7 +471,7 @@ function startLoopbackServerAndWaitForCode(
|
|
|
439
471
|
// ---------------------------------------------------------------------------
|
|
440
472
|
|
|
441
473
|
export interface OAuth2PreparedFlow {
|
|
442
|
-
|
|
474
|
+
authorizeUrl: string;
|
|
443
475
|
state: string;
|
|
444
476
|
/** Resolves when the user completes authorization and tokens are exchanged. */
|
|
445
477
|
completion: Promise<OAuth2FlowResult>;
|
|
@@ -493,17 +525,17 @@ export async function prepareOAuth2Flow(
|
|
|
493
525
|
});
|
|
494
526
|
|
|
495
527
|
const authParams = new URLSearchParams({
|
|
496
|
-
...config.
|
|
528
|
+
...config.authorizeParams,
|
|
497
529
|
client_id: config.clientId,
|
|
498
530
|
redirect_uri: redirectUri,
|
|
499
531
|
response_type: "code",
|
|
500
|
-
scope: config.scopes.join(
|
|
532
|
+
scope: config.scopes.join(config.scopeSeparator),
|
|
501
533
|
state,
|
|
502
534
|
code_challenge: codeChallenge,
|
|
503
535
|
code_challenge_method: "S256",
|
|
504
536
|
});
|
|
505
537
|
|
|
506
|
-
const
|
|
538
|
+
const authorizeUrl = `${config.authorizeUrl}?${authParams}`;
|
|
507
539
|
|
|
508
540
|
const completion = codePromise.then(async (code) => {
|
|
509
541
|
return await exchangeCodeForTokens(config, code, redirectUri, codeVerifier);
|
|
@@ -511,7 +543,7 @@ export async function prepareOAuth2Flow(
|
|
|
511
543
|
|
|
512
544
|
log.debug({ transport: "gateway", state }, "Prepared deferred OAuth2 flow");
|
|
513
545
|
|
|
514
|
-
return {
|
|
546
|
+
return { authorizeUrl, state, completion };
|
|
515
547
|
}
|
|
516
548
|
|
|
517
549
|
/**
|
|
@@ -533,17 +565,17 @@ async function prepareLoopbackFlow(
|
|
|
533
565
|
);
|
|
534
566
|
|
|
535
567
|
const authParams = new URLSearchParams({
|
|
536
|
-
...config.
|
|
568
|
+
...config.authorizeParams,
|
|
537
569
|
client_id: config.clientId,
|
|
538
570
|
redirect_uri: redirectUri,
|
|
539
571
|
response_type: "code",
|
|
540
|
-
scope: config.scopes.join(
|
|
572
|
+
scope: config.scopes.join(config.scopeSeparator),
|
|
541
573
|
state,
|
|
542
574
|
code_challenge: codeChallenge,
|
|
543
575
|
code_challenge_method: "S256",
|
|
544
576
|
});
|
|
545
577
|
|
|
546
|
-
const
|
|
578
|
+
const authorizeUrl = `${config.authorizeUrl}?${authParams}`;
|
|
547
579
|
|
|
548
580
|
const completion = codePromise.then(async (code) => {
|
|
549
581
|
return await exchangeCodeForTokens(config, code, redirectUri, codeVerifier);
|
|
@@ -554,7 +586,7 @@ async function prepareLoopbackFlow(
|
|
|
554
586
|
"Prepared deferred OAuth2 flow (loopback)",
|
|
555
587
|
);
|
|
556
588
|
|
|
557
|
-
return {
|
|
589
|
+
return { authorizeUrl, state, completion };
|
|
558
590
|
}
|
|
559
591
|
|
|
560
592
|
/**
|
|
@@ -763,13 +795,15 @@ export async function startOAuth2Flow(
|
|
|
763
795
|
* Supports both PKCE (no secret) and client_secret flows.
|
|
764
796
|
*/
|
|
765
797
|
export async function refreshOAuth2Token(
|
|
766
|
-
|
|
798
|
+
tokenExchangeUrl: string,
|
|
767
799
|
clientId: string,
|
|
768
800
|
refreshToken: string,
|
|
769
801
|
clientSecret?: string,
|
|
770
802
|
tokenEndpointAuthMethod?: TokenEndpointAuthMethod,
|
|
803
|
+
tokenExchangeBodyFormat?: "form" | "json",
|
|
771
804
|
): Promise<OAuth2TokenResult> {
|
|
772
805
|
const authMethod = tokenEndpointAuthMethod ?? "client_secret_post";
|
|
806
|
+
const bodyFormat = tokenExchangeBodyFormat ?? "form";
|
|
773
807
|
|
|
774
808
|
const body: Record<string, string> = {
|
|
775
809
|
grant_type: "refresh_token",
|
|
@@ -777,7 +811,11 @@ export async function refreshOAuth2Token(
|
|
|
777
811
|
};
|
|
778
812
|
|
|
779
813
|
const headers: Record<string, string> = {
|
|
780
|
-
"Content-Type":
|
|
814
|
+
"Content-Type":
|
|
815
|
+
bodyFormat === "json"
|
|
816
|
+
? "application/json"
|
|
817
|
+
: "application/x-www-form-urlencoded",
|
|
818
|
+
Accept: "application/json",
|
|
781
819
|
};
|
|
782
820
|
|
|
783
821
|
if (clientSecret && authMethod === "client_secret_basic") {
|
|
@@ -792,10 +830,11 @@ export async function refreshOAuth2Token(
|
|
|
792
830
|
}
|
|
793
831
|
}
|
|
794
832
|
|
|
795
|
-
const resp = await fetch(
|
|
833
|
+
const resp = await fetch(tokenExchangeUrl, {
|
|
796
834
|
method: "POST",
|
|
797
835
|
headers,
|
|
798
|
-
body:
|
|
836
|
+
body:
|
|
837
|
+
bodyFormat === "json" ? JSON.stringify(body) : new URLSearchParams(body),
|
|
799
838
|
});
|
|
800
839
|
|
|
801
840
|
if (!resp.ok) {
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* sidecar and credential data.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
21
|
+
|
|
20
22
|
import type {
|
|
21
23
|
SecureKeyBackend,
|
|
22
24
|
SecureKeyDeleteResult,
|
|
@@ -75,6 +77,18 @@ let _lastReconnectAttempt = 0;
|
|
|
75
77
|
/** In-flight reconnection promise — concurrent callers share the same attempt. */
|
|
76
78
|
let _reconnectInFlight: Promise<boolean> | undefined;
|
|
77
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Per-async-context flag set while we are running the user-registered
|
|
82
|
+
* `_cesReconnect` callback. Reentrant credential reads from within the
|
|
83
|
+
* callback (on the same async call chain) must not `await`
|
|
84
|
+
* `_reconnectInFlight` — that would await the caller's own reconnect and
|
|
85
|
+
* deadlock until `CREDENTIAL_OP_TIMEOUT_MS` (45s) fires. Using
|
|
86
|
+
* AsyncLocalStorage (rather than a module-level boolean) scopes the guard
|
|
87
|
+
* to the actual reentrant stack, so unrelated concurrent callers keep
|
|
88
|
+
* sharing the in-flight reconnect promise normally.
|
|
89
|
+
*/
|
|
90
|
+
const _reconnectContext = new AsyncLocalStorage<true>();
|
|
91
|
+
|
|
78
92
|
/**
|
|
79
93
|
* Set to true when a ces-http operation returns an unreachable result.
|
|
80
94
|
* Triggers CES RPC reconnection on the next resolveBackendAsync() call so
|
|
@@ -86,6 +100,15 @@ let _cesHttpUnreachable = false;
|
|
|
86
100
|
/** Minimum interval between CES reconnection attempts. */
|
|
87
101
|
const RECONNECT_COOLDOWN_MS = 3_000;
|
|
88
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Hard timeout for each public credential operation (resolve + backend call).
|
|
105
|
+
* Prevents indefinite blocking when CES reconnection or backend operations hang.
|
|
106
|
+
*
|
|
107
|
+
* Set to 45s to comfortably cover the CES HTTP set worst case (~34s:
|
|
108
|
+
* 3 fetch attempts × 10s REQUEST_TIMEOUT_MS + 2 × 2s SET_RETRY_DELAY_MS).
|
|
109
|
+
*/
|
|
110
|
+
const CREDENTIAL_OP_TIMEOUT_MS = 45_000;
|
|
111
|
+
|
|
89
112
|
/** Inject a CES RPC client for credential routing. Resets the resolved backend. */
|
|
90
113
|
export function setCesClient(client: CesClient | undefined): void {
|
|
91
114
|
_cesClient = client;
|
|
@@ -231,6 +254,15 @@ function tryFailoverToCesHttpBackend(
|
|
|
231
254
|
async function attemptCesReconnection(): Promise<boolean> {
|
|
232
255
|
if (!_cesReconnect) return false;
|
|
233
256
|
|
|
257
|
+
// Reentrancy guard. A nested credential read from inside the reconnect
|
|
258
|
+
// callback must not `await` our own in-flight promise — that would
|
|
259
|
+
// deadlock on the 45-second credential-op timeout. Report the reconnect
|
|
260
|
+
// as failed so the caller sees "unreachable" and falls back (env vars,
|
|
261
|
+
// dead-backend response) without blocking. Concurrent callers on other
|
|
262
|
+
// async chains don't see the ALS store, so they still share the
|
|
263
|
+
// in-flight promise normally.
|
|
264
|
+
if (_reconnectContext.getStore()) return false;
|
|
265
|
+
|
|
234
266
|
// If a reconnection is already in flight, share it.
|
|
235
267
|
if (_reconnectInFlight) return _reconnectInFlight;
|
|
236
268
|
|
|
@@ -240,7 +272,7 @@ async function attemptCesReconnection(): Promise<boolean> {
|
|
|
240
272
|
_lastReconnectAttempt = Date.now();
|
|
241
273
|
log.warn("Credential backend unavailable — attempting CES reconnection");
|
|
242
274
|
|
|
243
|
-
_reconnectInFlight = (async () => {
|
|
275
|
+
_reconnectInFlight = _reconnectContext.run(true, async () => {
|
|
244
276
|
try {
|
|
245
277
|
const newClient = await _cesReconnect!();
|
|
246
278
|
if (newClient) {
|
|
@@ -253,7 +285,7 @@ async function attemptCesReconnection(): Promise<boolean> {
|
|
|
253
285
|
log.warn({ err }, "CES reconnection failed");
|
|
254
286
|
}
|
|
255
287
|
return false;
|
|
256
|
-
})
|
|
288
|
+
});
|
|
257
289
|
|
|
258
290
|
try {
|
|
259
291
|
return await _reconnectInFlight;
|
|
@@ -308,16 +340,58 @@ function updateCesHttpReachability(
|
|
|
308
340
|
}
|
|
309
341
|
}
|
|
310
342
|
|
|
343
|
+
// ---------------------------------------------------------------------------
|
|
344
|
+
// Timeout helper
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
|
|
347
|
+
const CREDENTIAL_TIMEOUT_MSG = "Credential operation timed out";
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Race a credential operation against a hard deadline. If the operation
|
|
351
|
+
* does not settle within `CREDENTIAL_OP_TIMEOUT_MS`, return the supplied
|
|
352
|
+
* fallback value so callers degrade gracefully instead of hanging.
|
|
353
|
+
*
|
|
354
|
+
* Non-timeout errors from `op()` are propagated to callers rather than
|
|
355
|
+
* silently swallowed — only genuine timeouts return the fallback.
|
|
356
|
+
*/
|
|
357
|
+
async function withCredentialTimeout<T>(
|
|
358
|
+
op: () => Promise<T>,
|
|
359
|
+
fallback: T,
|
|
360
|
+
): Promise<T> {
|
|
361
|
+
return new Promise<T>((resolve, reject) => {
|
|
362
|
+
const timer = setTimeout(() => {
|
|
363
|
+
log.warn(CREDENTIAL_TIMEOUT_MSG + " — returning fallback");
|
|
364
|
+
resolve(fallback);
|
|
365
|
+
}, CREDENTIAL_OP_TIMEOUT_MS);
|
|
366
|
+
|
|
367
|
+
op().then(
|
|
368
|
+
(val) => {
|
|
369
|
+
clearTimeout(timer);
|
|
370
|
+
resolve(val);
|
|
371
|
+
},
|
|
372
|
+
(err) => {
|
|
373
|
+
clearTimeout(timer);
|
|
374
|
+
reject(err);
|
|
375
|
+
},
|
|
376
|
+
);
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
311
380
|
/**
|
|
312
381
|
* List all account names from the resolved backend (async).
|
|
313
382
|
*
|
|
314
383
|
* Queries exactly one backend — no cross-store merge.
|
|
315
384
|
*/
|
|
316
385
|
export async function listSecureKeysAsync(): Promise<CredentialListResult> {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
386
|
+
return withCredentialTimeout(
|
|
387
|
+
async () => {
|
|
388
|
+
const backend = await resolveBackendAsync();
|
|
389
|
+
const result = await backend.list();
|
|
390
|
+
updateCesHttpReachability(backend, result.unreachable);
|
|
391
|
+
return result;
|
|
392
|
+
},
|
|
393
|
+
{ accounts: [], unreachable: true },
|
|
394
|
+
);
|
|
321
395
|
}
|
|
322
396
|
|
|
323
397
|
// ---------------------------------------------------------------------------
|
|
@@ -336,13 +410,18 @@ export async function listSecureKeysAsync(): Promise<CredentialListResult> {
|
|
|
336
410
|
export async function getSecureKeyResultAsync(
|
|
337
411
|
account: string,
|
|
338
412
|
): Promise<SecureKeyResult> {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
413
|
+
return withCredentialTimeout(
|
|
414
|
+
async () => {
|
|
415
|
+
const backend = await resolveBackendAsync();
|
|
416
|
+
const result = await backend.get(account);
|
|
417
|
+
updateCesHttpReachability(backend, result.unreachable);
|
|
418
|
+
if (result.value != null) {
|
|
419
|
+
return { value: result.value, unreachable: false };
|
|
420
|
+
}
|
|
421
|
+
return { value: undefined, unreachable: result.unreachable };
|
|
422
|
+
},
|
|
423
|
+
{ value: undefined, unreachable: true },
|
|
424
|
+
);
|
|
346
425
|
}
|
|
347
426
|
|
|
348
427
|
/**
|
|
@@ -364,16 +443,18 @@ export async function setSecureKeyAsync(
|
|
|
364
443
|
account: string,
|
|
365
444
|
value: string,
|
|
366
445
|
): Promise<boolean> {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
446
|
+
return withCredentialTimeout(async () => {
|
|
447
|
+
const backend = await resolveBackendAsync();
|
|
448
|
+
const ok = await backend.set(account, value);
|
|
449
|
+
if (!ok) {
|
|
450
|
+
log.warn(
|
|
451
|
+
{ account, backend: backend.name },
|
|
452
|
+
"Credential backend set failed",
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
updateCesHttpReachability(backend, !ok);
|
|
456
|
+
return ok;
|
|
457
|
+
}, false);
|
|
377
458
|
}
|
|
378
459
|
|
|
379
460
|
/**
|
|
@@ -384,10 +465,45 @@ export async function setSecureKeyAsync(
|
|
|
384
465
|
export async function deleteSecureKeyAsync(
|
|
385
466
|
account: string,
|
|
386
467
|
): Promise<DeleteResult> {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
468
|
+
return withCredentialTimeout(async () => {
|
|
469
|
+
const backend = await resolveBackendAsync();
|
|
470
|
+
const result = await backend.delete(account);
|
|
471
|
+
updateCesHttpReachability(backend, result === "error");
|
|
472
|
+
return result;
|
|
473
|
+
}, "error");
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Bulk-set multiple credentials in a single operation.
|
|
478
|
+
*
|
|
479
|
+
* Uses the backend's native `bulkSet` when available (CES RPC / HTTP),
|
|
480
|
+
* otherwise falls back to individual `set` calls.
|
|
481
|
+
*/
|
|
482
|
+
export async function bulkSetSecureKeysAsync(
|
|
483
|
+
credentials: Array<{ account: string; value: string }>,
|
|
484
|
+
): Promise<Array<{ account: string; ok: boolean }>> {
|
|
485
|
+
return withCredentialTimeout(
|
|
486
|
+
async () => {
|
|
487
|
+
const backend = await resolveBackendAsync();
|
|
488
|
+
if (backend.bulkSet) {
|
|
489
|
+
const results = await backend.bulkSet(credentials);
|
|
490
|
+
const anyFailed = results.some((r) => !r.ok);
|
|
491
|
+
updateCesHttpReachability(backend, anyFailed);
|
|
492
|
+
return results;
|
|
493
|
+
}
|
|
494
|
+
// Fallback: loop individual sets
|
|
495
|
+
const results = [];
|
|
496
|
+
let anyFailed = false;
|
|
497
|
+
for (const { account, value } of credentials) {
|
|
498
|
+
const ok = await backend.set(account, value);
|
|
499
|
+
if (!ok) anyFailed = true;
|
|
500
|
+
results.push({ account, ok });
|
|
501
|
+
}
|
|
502
|
+
updateCesHttpReachability(backend, anyFailed);
|
|
503
|
+
return results;
|
|
504
|
+
},
|
|
505
|
+
credentials.map((c) => ({ account: c.account, ok: false })),
|
|
506
|
+
);
|
|
391
507
|
}
|
|
392
508
|
|
|
393
509
|
// ---------------------------------------------------------------------------
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Token manager for OAuth2 credentials.
|
|
3
3
|
*
|
|
4
|
-
* Reads refresh configuration (
|
|
4
|
+
* Reads refresh configuration (refreshUrl with fallback to tokenExchangeUrl, clientId, authMethod) exclusively
|
|
5
5
|
* from the SQLite oauth-store (provider + app + connection rows). After a
|
|
6
6
|
* successful refresh, writes tokens to new-format secure key paths and
|
|
7
7
|
* updates the oauth_connection row.
|
|
@@ -90,20 +90,27 @@ const secureKeyBackend: SecureKeyBackend = {
|
|
|
90
90
|
|
|
91
91
|
/** Shared shape for resolved refresh configuration. */
|
|
92
92
|
interface RefreshConfig {
|
|
93
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Token endpoint used for the refresh grant. Resolved from
|
|
95
|
+
* `provider.refreshUrl` when set to a non-empty string, otherwise
|
|
96
|
+
* `provider.tokenExchangeUrl` (matching platform's Python `or` semantics).
|
|
97
|
+
*/
|
|
98
|
+
tokenExchangeUrl: string;
|
|
94
99
|
clientId: string;
|
|
95
100
|
/** OAuth client secret (optional — PKCE flows may omit it). */
|
|
96
101
|
secret?: string;
|
|
97
102
|
refreshToken?: string;
|
|
98
103
|
authMethod?: TokenEndpointAuthMethod;
|
|
104
|
+
tokenExchangeBodyFormat?: "form" | "json";
|
|
99
105
|
connId: string;
|
|
100
106
|
}
|
|
101
107
|
|
|
102
108
|
/**
|
|
103
109
|
* Resolve refresh configuration from the SQLite oauth-store.
|
|
104
110
|
*
|
|
105
|
-
* Looks up connection -> app -> provider to read
|
|
106
|
-
*
|
|
111
|
+
* Looks up connection -> app -> provider to read the refresh endpoint (preferring
|
|
112
|
+
* `provider.refreshUrl`, falling back to `provider.tokenExchangeUrl`), clientId,
|
|
113
|
+
* and authMethod. Throws `TokenExpiredError` if the connection is not found
|
|
107
114
|
* or incomplete.
|
|
108
115
|
*/
|
|
109
116
|
async function resolveRefreshConfig(
|
|
@@ -126,7 +133,7 @@ async function resolveRefreshConfig(
|
|
|
126
133
|
);
|
|
127
134
|
}
|
|
128
135
|
|
|
129
|
-
const provider = getProvider(conn.
|
|
136
|
+
const provider = getProvider(conn.provider);
|
|
130
137
|
if (!provider) {
|
|
131
138
|
throw new TokenExpiredError(
|
|
132
139
|
service,
|
|
@@ -134,9 +141,16 @@ async function resolveRefreshConfig(
|
|
|
134
141
|
);
|
|
135
142
|
}
|
|
136
143
|
|
|
137
|
-
|
|
144
|
+
// Prefer provider.refreshUrl when set; fall back to tokenExchangeUrl.
|
|
145
|
+
// This mirrors platform's `oauth_app.refresh_url or oauth_app.token_exchange_url`
|
|
146
|
+
// in `token_service.py:112`, so both repos resolve the refresh endpoint
|
|
147
|
+
// identically for managed and BYO flows. We use `||` (not `??`) so empty
|
|
148
|
+
// strings fall back to tokenExchangeUrl — matching Python's `or` semantics
|
|
149
|
+
// and preventing a malformed provider row with `refreshUrl: ""` from
|
|
150
|
+
// resolving to an empty endpoint.
|
|
151
|
+
const tokenExchangeUrl = provider.refreshUrl || provider.tokenExchangeUrl;
|
|
138
152
|
const resolvedClientId = app.clientId;
|
|
139
|
-
if (!
|
|
153
|
+
if (!tokenExchangeUrl || !resolvedClientId) {
|
|
140
154
|
throw new TokenExpiredError(
|
|
141
155
|
service,
|
|
142
156
|
`Missing OAuth2 refresh config for "${service}".${recoveryHint(service)}`,
|
|
@@ -153,13 +167,18 @@ async function resolveRefreshConfig(
|
|
|
153
167
|
| TokenEndpointAuthMethod
|
|
154
168
|
| undefined;
|
|
155
169
|
|
|
170
|
+
const tokenExchangeBodyFormat =
|
|
171
|
+
(provider.tokenExchangeBodyFormat as "form" | "json" | undefined) ??
|
|
172
|
+
undefined;
|
|
173
|
+
|
|
156
174
|
return {
|
|
157
175
|
connId: conn.id,
|
|
158
|
-
|
|
176
|
+
tokenExchangeUrl,
|
|
159
177
|
clientId: resolvedClientId,
|
|
160
178
|
secret,
|
|
161
179
|
refreshToken,
|
|
162
180
|
authMethod,
|
|
181
|
+
tokenExchangeBodyFormat,
|
|
163
182
|
};
|
|
164
183
|
}
|
|
165
184
|
|
|
@@ -175,10 +194,11 @@ async function resolveRefreshConfig(
|
|
|
175
194
|
async function doRefresh(service: string, connId: string): Promise<string> {
|
|
176
195
|
const refreshConfig = await resolveRefreshConfig(service, connId);
|
|
177
196
|
const {
|
|
178
|
-
|
|
197
|
+
tokenExchangeUrl,
|
|
179
198
|
clientId: resolvedClientId,
|
|
180
199
|
secret,
|
|
181
200
|
authMethod,
|
|
201
|
+
tokenExchangeBodyFormat,
|
|
182
202
|
refreshToken,
|
|
183
203
|
} = refreshConfig;
|
|
184
204
|
|
|
@@ -204,11 +224,12 @@ async function doRefresh(service: string, connId: string): Promise<string> {
|
|
|
204
224
|
let result;
|
|
205
225
|
try {
|
|
206
226
|
result = await refreshOAuth2Token(
|
|
207
|
-
|
|
227
|
+
tokenExchangeUrl,
|
|
208
228
|
resolvedClientId,
|
|
209
229
|
refreshToken,
|
|
210
230
|
secret,
|
|
211
231
|
authMethod,
|
|
232
|
+
tokenExchangeBodyFormat,
|
|
212
233
|
);
|
|
213
234
|
} catch (err) {
|
|
214
235
|
circuitBreaker.recordFailure(connId);
|
package/src/sequence/engine.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* sends through the messaging layer.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { emitFeedEvent } from "../home/emit-feed-event.js";
|
|
9
10
|
import { bootstrapConversation } from "../memory/conversation-bootstrap.js";
|
|
10
11
|
import { getMessages } from "../memory/conversation-crud.js";
|
|
11
12
|
import type { ScheduleMessageProcessor } from "../schedule/scheduler.js";
|
|
@@ -200,6 +201,28 @@ async function processEnrollment(
|
|
|
200
201
|
recordSend(sequence.id);
|
|
201
202
|
recordEvent(sequence.id, enrollment.id, "send", step.index);
|
|
202
203
|
|
|
204
|
+
// Fire-and-forget home-feed activity log entry. Each (enrollment,
|
|
205
|
+
// step) pair is a distinct real signal (an email actually went
|
|
206
|
+
// out), so the dedupKey embeds both — repeat emits for the same
|
|
207
|
+
// step are impossible because the enrollment advances after this
|
|
208
|
+
// line, but if they did occur they'd land on the same entry.
|
|
209
|
+
void emitFeedEvent({
|
|
210
|
+
source: "assistant",
|
|
211
|
+
title: sequence.name,
|
|
212
|
+
summary: `Sent step ${step.index + 1} of ${sequence.steps.length} to ${enrollment.contactEmail}.`,
|
|
213
|
+
dedupKey: `sequence-step:${enrollment.id}:${step.index}`,
|
|
214
|
+
}).catch((err) => {
|
|
215
|
+
log.warn(
|
|
216
|
+
{
|
|
217
|
+
err,
|
|
218
|
+
sequenceId: sequence.id,
|
|
219
|
+
enrollmentId: enrollment.id,
|
|
220
|
+
step: step.index,
|
|
221
|
+
},
|
|
222
|
+
"Failed to emit sequence step feed event",
|
|
223
|
+
);
|
|
224
|
+
});
|
|
225
|
+
|
|
203
226
|
// Advance to the next step
|
|
204
227
|
const nextStepIndex = enrollment.currentStep + 1;
|
|
205
228
|
if (nextStepIndex >= sequence.steps.length) {
|
package/src/sequence/types.ts
CHANGED
|
@@ -26,7 +26,7 @@ export interface Sequence {
|
|
|
26
26
|
id: string;
|
|
27
27
|
name: string;
|
|
28
28
|
description: string | null;
|
|
29
|
-
channel: string; // messaging channel (gmail,
|
|
29
|
+
channel: string; // messaging channel (gmail, email, slack)
|
|
30
30
|
steps: SequenceStep[];
|
|
31
31
|
exitOnReply: boolean;
|
|
32
32
|
status: SequenceStatus;
|