@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
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
* exports named functions for HTTP methods (GET, POST, PUT, etc.) using
|
|
7
7
|
* the standard Web API Request/Response signature.
|
|
8
8
|
*
|
|
9
|
+
* Handlers receive a second `context` argument with runtime singletons
|
|
10
|
+
* (event hub, assistant ID, etc.) that would otherwise be unreachable
|
|
11
|
+
* from dynamically imported modules because Bun's cache-busting import
|
|
12
|
+
* creates separate module instances.
|
|
13
|
+
*
|
|
9
14
|
* Modules are lazily loaded on first request and cached by file path +
|
|
10
15
|
* mtime. When a file changes on disk, the next request reloads it via
|
|
11
16
|
* Bun's dynamic `import()` with a cache-busting query parameter.
|
|
@@ -16,10 +21,35 @@ import { join, resolve } from "node:path";
|
|
|
16
21
|
|
|
17
22
|
import { getLogger } from "../../util/logger.js";
|
|
18
23
|
import { getWorkspaceRoutesDir } from "../../util/platform.js";
|
|
24
|
+
import type { AssistantEventHub } from "../assistant-event-hub.js";
|
|
19
25
|
import { httpError } from "../http-errors.js";
|
|
20
26
|
|
|
21
27
|
const log = getLogger("user-routes");
|
|
22
28
|
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// User route context — injected into every handler as the second argument
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Runtime context passed to user-defined route handlers.
|
|
35
|
+
*
|
|
36
|
+
* Because user route modules are loaded via dynamic `import()` with
|
|
37
|
+
* cache-busting query parameters, they get isolated module instances
|
|
38
|
+
* and cannot import process-level singletons like the event hub
|
|
39
|
+
* directly. This context bridges the gap by carrying references to
|
|
40
|
+
* the daemon's real singletons.
|
|
41
|
+
*/
|
|
42
|
+
export interface UserRouteContext {
|
|
43
|
+
/** The daemon's event hub singleton — use this to publish events to connected SSE clients. */
|
|
44
|
+
readonly assistantEventHub: AssistantEventHub;
|
|
45
|
+
/** The logical assistant ID used by the daemon (typically "self"). */
|
|
46
|
+
readonly assistantId: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Route handler types
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
|
|
23
53
|
/** HTTP methods that can be exported from a handler module. */
|
|
24
54
|
const HTTP_METHODS = [
|
|
25
55
|
"GET",
|
|
@@ -33,8 +63,18 @@ const HTTP_METHODS = [
|
|
|
33
63
|
|
|
34
64
|
type HttpMethod = (typeof HTTP_METHODS)[number];
|
|
35
65
|
|
|
36
|
-
/**
|
|
37
|
-
|
|
66
|
+
/**
|
|
67
|
+
* The function signature that user-defined route handlers must follow.
|
|
68
|
+
*
|
|
69
|
+
* Handlers may accept an optional second `context` argument with runtime
|
|
70
|
+
* singletons (event hub, assistant ID). Legacy handlers that only accept
|
|
71
|
+
* `request` continue to work — the context is passed positionally but
|
|
72
|
+
* ignored if the handler doesn't declare the parameter.
|
|
73
|
+
*/
|
|
74
|
+
type RouteHandler = (
|
|
75
|
+
request: Request,
|
|
76
|
+
context: UserRouteContext,
|
|
77
|
+
) => Response | Promise<Response>;
|
|
38
78
|
|
|
39
79
|
/** A loaded handler module with its cached metadata. */
|
|
40
80
|
interface CachedModule {
|
|
@@ -55,10 +95,15 @@ const HANDLER_EXTENSIONS = [".ts", ".js"] as const;
|
|
|
55
95
|
export class UserRouteDispatcher {
|
|
56
96
|
private moduleCache = new Map<string, CachedModule>();
|
|
57
97
|
private handlerTimeoutMs: number;
|
|
98
|
+
private context: UserRouteContext;
|
|
58
99
|
|
|
59
|
-
constructor(options
|
|
100
|
+
constructor(options: {
|
|
101
|
+
handlerTimeoutMs?: number;
|
|
102
|
+
context: UserRouteContext;
|
|
103
|
+
}) {
|
|
60
104
|
this.handlerTimeoutMs =
|
|
61
|
-
options
|
|
105
|
+
options.handlerTimeoutMs ?? DEFAULT_HANDLER_TIMEOUT_MS;
|
|
106
|
+
this.context = Object.freeze({ ...options.context });
|
|
62
107
|
}
|
|
63
108
|
|
|
64
109
|
/**
|
|
@@ -192,7 +237,7 @@ export class UserRouteDispatcher {
|
|
|
192
237
|
): Promise<Response> {
|
|
193
238
|
try {
|
|
194
239
|
const result = await Promise.race([
|
|
195
|
-
Promise.resolve(handler(request)),
|
|
240
|
+
Promise.resolve(handler(request, this.context)),
|
|
196
241
|
new Promise<never>((_, reject) =>
|
|
197
242
|
setTimeout(
|
|
198
243
|
() => reject(new Error("Handler timed out")),
|
|
@@ -4,12 +4,24 @@
|
|
|
4
4
|
* Registers a single catch-all route that delegates to the
|
|
5
5
|
* UserRouteDispatcher for file-based dispatch from
|
|
6
6
|
* `$VELLUM_WORKSPACE_DIR/routes/`.
|
|
7
|
+
*
|
|
8
|
+
* The dispatcher injects a `UserRouteContext` into every handler so
|
|
9
|
+
* that dynamically imported route modules can access daemon singletons
|
|
10
|
+
* (event hub, assistant ID) without relying on module-level imports
|
|
11
|
+
* that would resolve to separate instances due to cache-busting.
|
|
7
12
|
*/
|
|
8
13
|
|
|
14
|
+
import { assistantEventHub } from "../assistant-event-hub.js";
|
|
15
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
9
16
|
import type { RouteDefinition } from "../http-router.js";
|
|
10
17
|
import { UserRouteDispatcher } from "./user-route-dispatcher.js";
|
|
11
18
|
|
|
12
|
-
const dispatcher = new UserRouteDispatcher(
|
|
19
|
+
const dispatcher = new UserRouteDispatcher({
|
|
20
|
+
context: {
|
|
21
|
+
assistantEventHub,
|
|
22
|
+
assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
13
25
|
|
|
14
26
|
/**
|
|
15
27
|
* HTTP methods supported by user-defined route handlers.
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
getToolDescription,
|
|
20
20
|
sanitizeToolList,
|
|
21
21
|
} from "../../tasks/tool-sanitizer.js";
|
|
22
|
+
import { createAbortReason } from "../../util/abort-reasons.js";
|
|
22
23
|
import { getLogger } from "../../util/logger.js";
|
|
23
24
|
import { truncate } from "../../util/truncate.js";
|
|
24
25
|
import { resolveRequiredTools } from "../../work-items/resolve-required-tools.js";
|
|
@@ -587,7 +588,13 @@ export function workItemRouteDefinitions(
|
|
|
587
588
|
const conversation = deps.findConversation(conversationId);
|
|
588
589
|
if (conversation) {
|
|
589
590
|
conversation.headlessLock = false;
|
|
590
|
-
conversation.abort(
|
|
591
|
+
conversation.abort(
|
|
592
|
+
createAbortReason(
|
|
593
|
+
"work_item_aborted",
|
|
594
|
+
"work-items-routes.cancel",
|
|
595
|
+
conversationId,
|
|
596
|
+
),
|
|
597
|
+
);
|
|
591
598
|
getSubagentManager().abortAllForParent(conversationId);
|
|
592
599
|
}
|
|
593
600
|
}
|
|
@@ -190,6 +190,28 @@ describe("isTextMimeType", () => {
|
|
|
190
190
|
// A binary plist has a specific MIME type — extension should not override it
|
|
191
191
|
expect(isTextMimeType("application/x-plist", "Info.plist")).toBe(false);
|
|
192
192
|
});
|
|
193
|
+
|
|
194
|
+
test("application/octet-stream with .jsonl filename is text", () => {
|
|
195
|
+
expect(isTextMimeType("application/octet-stream", "messages.jsonl")).toBe(
|
|
196
|
+
true,
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("application/octet-stream with .ndjson filename is text", () => {
|
|
201
|
+
expect(isTextMimeType("application/octet-stream", "events.ndjson")).toBe(
|
|
202
|
+
true,
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("application/octet-stream with .JSONL uppercase is text", () => {
|
|
207
|
+
expect(isTextMimeType("application/octet-stream", "DATA.JSONL")).toBe(true);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("application/octet-stream with .NDJSON uppercase is text", () => {
|
|
211
|
+
expect(isTextMimeType("application/octet-stream", "DATA.NDJSON")).toBe(
|
|
212
|
+
true,
|
|
213
|
+
);
|
|
214
|
+
});
|
|
193
215
|
});
|
|
194
216
|
|
|
195
217
|
// ===========================================================================
|
|
@@ -120,7 +120,14 @@ function handleWorkspaceFile(ctx: RouteContext): Response {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
const mimeType = Bun.file(resolved).type;
|
|
123
|
-
|
|
123
|
+
// Empty files with unknown MIME type default to text — there is no binary
|
|
124
|
+
// content to protect, and files created via the UI "New File" action are
|
|
125
|
+
// always 0 bytes. Without this override, extensionless files (e.g. "Test")
|
|
126
|
+
// would be classified as binary and rendered in a non-editable fallback view.
|
|
127
|
+
const isText =
|
|
128
|
+
stat.size === 0 && mimeType === "application/octet-stream"
|
|
129
|
+
? true
|
|
130
|
+
: isTextMimeType(mimeType, basename(resolved));
|
|
124
131
|
const isBinary = !isText;
|
|
125
132
|
|
|
126
133
|
let content: string | undefined = undefined;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon runtime-mode detection.
|
|
3
|
+
*
|
|
4
|
+
* Exposes a single well-named helper `getDaemonRuntimeMode()` that returns
|
|
5
|
+
* `"docker"` when the daemon is running inside a container and
|
|
6
|
+
* `"bare-metal"` otherwise.
|
|
7
|
+
*
|
|
8
|
+
* Under the hood this delegates to `getIsContainerized()` from the env
|
|
9
|
+
* registry, which accepts the standard truthy values for `IS_CONTAINERIZED`
|
|
10
|
+
* (`"true"` or `"1"`). Keeping the check in the registry avoids duplicating
|
|
11
|
+
* the env-parsing semantics across modules.
|
|
12
|
+
*
|
|
13
|
+
* The mode-named API (rather than a boolean) exists to make downstream
|
|
14
|
+
* switch/branch code read naturally — e.g. `if (mode === "docker") { ... }`
|
|
15
|
+
* is clearer than `if (isContainerized) { ... }` when the behavior depends
|
|
16
|
+
* on the specific deployment shape, and it leaves room for additional
|
|
17
|
+
* runtime modes in the future without renaming every callsite.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { getIsContainerized } from "../config/env-registry.js";
|
|
21
|
+
|
|
22
|
+
export type DaemonRuntimeMode = "bare-metal" | "docker";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returns the deployment mode the daemon is currently running under.
|
|
26
|
+
*
|
|
27
|
+
* - `"docker"` when `IS_CONTAINERIZED` is set to a truthy value
|
|
28
|
+
* (`"true"` or `"1"`).
|
|
29
|
+
* - `"bare-metal"` otherwise.
|
|
30
|
+
*/
|
|
31
|
+
export function getDaemonRuntimeMode(): DaemonRuntimeMode {
|
|
32
|
+
return getIsContainerized() ? "docker" : "bare-metal";
|
|
33
|
+
}
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the analyzeConversation service.
|
|
3
|
+
*
|
|
4
|
+
* The service is driven directly (no HTTP routing) so tests exercise the
|
|
5
|
+
* validation + setup logic against mocked memory/CRUD + transcript helpers.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
9
|
+
|
|
10
|
+
mock.module("../../../util/logger.js", () => ({
|
|
11
|
+
getLogger: () =>
|
|
12
|
+
new Proxy({} as Record<string, unknown>, {
|
|
13
|
+
get: () => () => {},
|
|
14
|
+
}),
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
const mockResolveConversationId = mock((id: string) => id as string | null);
|
|
18
|
+
const mockGetConversation = mock(
|
|
19
|
+
() =>
|
|
20
|
+
({
|
|
21
|
+
id: "conv-1",
|
|
22
|
+
title: "Source",
|
|
23
|
+
conversationType: "normal",
|
|
24
|
+
}) as Record<string, unknown> | null,
|
|
25
|
+
);
|
|
26
|
+
const mockGetMessages = mock(() => [{ id: "m-source" }] as Array<{ id: string }>);
|
|
27
|
+
const mockCreateConversation = mock(
|
|
28
|
+
(_opts?: Record<string, unknown>) => ({ id: "analysis-new" }),
|
|
29
|
+
);
|
|
30
|
+
const mockAddMessage = mock(async () => ({ id: "msg-1" }));
|
|
31
|
+
const mockFindAnalysisConversationFor = mock(
|
|
32
|
+
(_parent: string) => null as { id: string } | null,
|
|
33
|
+
);
|
|
34
|
+
const mockGetConversationSource = mock((_id: string) => null as string | null);
|
|
35
|
+
|
|
36
|
+
mock.module("../../../memory/conversation-key-store.js", () => ({
|
|
37
|
+
resolveConversationId: mockResolveConversationId,
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
mock.module("../../../memory/conversation-crud.js", () => ({
|
|
41
|
+
getConversation: mockGetConversation,
|
|
42
|
+
getMessages: mockGetMessages,
|
|
43
|
+
createConversation: mockCreateConversation,
|
|
44
|
+
addMessage: mockAddMessage,
|
|
45
|
+
findAnalysisConversationFor: mockFindAnalysisConversationFor,
|
|
46
|
+
getConversationSource: mockGetConversationSource,
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
mock.module("../../../export/transcript-formatter.js", () => ({
|
|
50
|
+
buildAnalysisTranscript: () => "user: hi",
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
// Default config stub — individual tests can override via mockGetConfig.
|
|
54
|
+
interface AnalysisConfigStub {
|
|
55
|
+
analysis: {
|
|
56
|
+
modelIntent?: string;
|
|
57
|
+
modelOverride?: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const mockGetConfig = mock(
|
|
61
|
+
(): AnalysisConfigStub => ({
|
|
62
|
+
analysis: {},
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
mock.module("../../../config/loader.js", () => ({
|
|
67
|
+
getConfig: mockGetConfig,
|
|
68
|
+
}));
|
|
69
|
+
|
|
70
|
+
import { AssistantEventHub } from "../../assistant-event-hub.js";
|
|
71
|
+
import type { SendMessageDeps } from "../../http-types.js";
|
|
72
|
+
import { analyzeConversation } from "../analyze-conversation.js";
|
|
73
|
+
|
|
74
|
+
beforeEach(() => {
|
|
75
|
+
mockResolveConversationId.mockReset();
|
|
76
|
+
mockResolveConversationId.mockImplementation((id: string) => id);
|
|
77
|
+
mockGetConversation.mockReset();
|
|
78
|
+
mockGetConversation.mockImplementation(() => ({
|
|
79
|
+
id: "conv-1",
|
|
80
|
+
title: "Source",
|
|
81
|
+
conversationType: "normal",
|
|
82
|
+
}));
|
|
83
|
+
mockGetMessages.mockReset();
|
|
84
|
+
mockGetMessages.mockImplementation(() => [{ id: "m-source" }]);
|
|
85
|
+
mockCreateConversation.mockReset();
|
|
86
|
+
mockCreateConversation.mockImplementation(() => ({ id: "analysis-new" }));
|
|
87
|
+
mockAddMessage.mockReset();
|
|
88
|
+
mockAddMessage.mockImplementation(async () => ({ id: "msg-1" }));
|
|
89
|
+
mockFindAnalysisConversationFor.mockReset();
|
|
90
|
+
mockFindAnalysisConversationFor.mockImplementation(() => null);
|
|
91
|
+
mockGetConversationSource.mockReset();
|
|
92
|
+
mockGetConversationSource.mockImplementation(() => null);
|
|
93
|
+
mockGetConfig.mockReset();
|
|
94
|
+
mockGetConfig.mockImplementation(() => ({ analysis: {} }));
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
function makeConversation() {
|
|
98
|
+
return {
|
|
99
|
+
setTrustContext: mock(() => {}),
|
|
100
|
+
ensureActorScopedHistory: mock(() => Promise.resolve()),
|
|
101
|
+
setSubagentAllowedTools: mock(() => {}),
|
|
102
|
+
updateClient: mock(() => {}),
|
|
103
|
+
processing: false,
|
|
104
|
+
abortController: null as AbortController | null,
|
|
105
|
+
currentRequestId: null as string | null,
|
|
106
|
+
loadedHistoryTrustClass: undefined as string | undefined,
|
|
107
|
+
runAgentLoop: mock(() => Promise.resolve()),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function makeDeps(conversation: ReturnType<typeof makeConversation>) {
|
|
112
|
+
const assistantEventHub = new AssistantEventHub();
|
|
113
|
+
const getOrCreateConversation = mock(async () => conversation);
|
|
114
|
+
const sendMessageDeps = {
|
|
115
|
+
getOrCreateConversation,
|
|
116
|
+
assistantEventHub,
|
|
117
|
+
resolveAttachments: () => [],
|
|
118
|
+
} as unknown as SendMessageDeps;
|
|
119
|
+
return {
|
|
120
|
+
sendMessageDeps,
|
|
121
|
+
buildConversationDetailResponse: (id: string) => ({ id }),
|
|
122
|
+
getOrCreateConversation,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
describe("analyzeConversation", () => {
|
|
127
|
+
test("returns NOT_FOUND when the source ID does not resolve", async () => {
|
|
128
|
+
mockResolveConversationId.mockImplementation(() => null);
|
|
129
|
+
const deps = makeDeps(makeConversation());
|
|
130
|
+
|
|
131
|
+
const result = await analyzeConversation("missing", deps, {
|
|
132
|
+
trigger: "manual",
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
expect("error" in result).toBe(true);
|
|
136
|
+
if (!("error" in result)) throw new Error("expected error");
|
|
137
|
+
expect(result.error.kind).toBe("NOT_FOUND");
|
|
138
|
+
expect(result.error.status).toBe(404);
|
|
139
|
+
expect(mockGetConversation).not.toHaveBeenCalled();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("returns NOT_FOUND when the conversation record is missing", async () => {
|
|
143
|
+
mockGetConversation.mockImplementation(() => null);
|
|
144
|
+
const deps = makeDeps(makeConversation());
|
|
145
|
+
|
|
146
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
147
|
+
trigger: "manual",
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
expect("error" in result).toBe(true);
|
|
151
|
+
if (!("error" in result)) throw new Error("expected error");
|
|
152
|
+
expect(result.error.kind).toBe("NOT_FOUND");
|
|
153
|
+
expect(result.error.status).toBe(404);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("returns FORBIDDEN when the source conversation is private", async () => {
|
|
157
|
+
mockGetConversation.mockImplementation(() => ({
|
|
158
|
+
id: "conv-1",
|
|
159
|
+
title: "Private",
|
|
160
|
+
conversationType: "private",
|
|
161
|
+
}));
|
|
162
|
+
const deps = makeDeps(makeConversation());
|
|
163
|
+
|
|
164
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
165
|
+
trigger: "manual",
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
expect("error" in result).toBe(true);
|
|
169
|
+
if (!("error" in result)) throw new Error("expected error");
|
|
170
|
+
expect(result.error.kind).toBe("FORBIDDEN");
|
|
171
|
+
expect(result.error.status).toBe(403);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("returns BAD_REQUEST when the source conversation has no messages", async () => {
|
|
175
|
+
mockGetMessages.mockImplementation(() => []);
|
|
176
|
+
const deps = makeDeps(makeConversation());
|
|
177
|
+
|
|
178
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
179
|
+
trigger: "manual",
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
expect("error" in result).toBe(true);
|
|
183
|
+
if (!("error" in result)) throw new Error("expected error");
|
|
184
|
+
expect(result.error.kind).toBe("BAD_REQUEST");
|
|
185
|
+
expect(result.error.status).toBe(400);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("creates an analysis conversation with unknown trust, no tools, and returns the new ID", async () => {
|
|
189
|
+
const conversation = makeConversation();
|
|
190
|
+
const deps = makeDeps(conversation);
|
|
191
|
+
|
|
192
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
193
|
+
trigger: "manual",
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
expect("error" in result).toBe(false);
|
|
197
|
+
if ("error" in result) throw new Error("expected success");
|
|
198
|
+
expect(result.analysisConversationId).toBe("analysis-new");
|
|
199
|
+
|
|
200
|
+
// Persists the prompt as a user message with unknown trust.
|
|
201
|
+
expect(mockAddMessage).toHaveBeenCalledWith(
|
|
202
|
+
"analysis-new",
|
|
203
|
+
"user",
|
|
204
|
+
expect.any(String),
|
|
205
|
+
{ provenanceTrustClass: "unknown" },
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// Sets trust context to unknown.
|
|
209
|
+
expect(conversation.setTrustContext).toHaveBeenCalledWith({
|
|
210
|
+
trustClass: "unknown",
|
|
211
|
+
sourceChannel: "vellum",
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Strips all tools.
|
|
215
|
+
expect(conversation.setSubagentAllowedTools).toHaveBeenCalledTimes(1);
|
|
216
|
+
const allowedTools = (
|
|
217
|
+
conversation.setSubagentAllowedTools.mock.calls as unknown as Array<
|
|
218
|
+
[Set<string> | undefined]
|
|
219
|
+
>
|
|
220
|
+
)[0]?.[0];
|
|
221
|
+
expect(allowedTools).toBeInstanceOf(Set);
|
|
222
|
+
expect(allowedTools?.size).toBe(0);
|
|
223
|
+
|
|
224
|
+
// Fires the agent loop.
|
|
225
|
+
expect(conversation.runAgentLoop).toHaveBeenCalledWith(
|
|
226
|
+
expect.any(String),
|
|
227
|
+
"msg-1",
|
|
228
|
+
expect.any(Function),
|
|
229
|
+
expect.objectContaining({ isInteractive: false, isUserMessage: true }),
|
|
230
|
+
);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// ── Auto trigger ──────────────────────────────────────────────────
|
|
234
|
+
|
|
235
|
+
test("auto: creates a new analysis conversation when none exists, with source=auto-analysis, dedicated groupId, and forkParentConversationId", async () => {
|
|
236
|
+
mockFindAnalysisConversationFor.mockImplementation(() => null);
|
|
237
|
+
const conversation = makeConversation();
|
|
238
|
+
const deps = makeDeps(conversation);
|
|
239
|
+
|
|
240
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
241
|
+
trigger: "auto",
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
expect("error" in result).toBe(false);
|
|
245
|
+
if ("error" in result) throw new Error("expected success");
|
|
246
|
+
expect(result.analysisConversationId).toBe("analysis-new");
|
|
247
|
+
|
|
248
|
+
// Verifies the rolling-analysis lookup was consulted against the source ID.
|
|
249
|
+
expect(mockFindAnalysisConversationFor).toHaveBeenCalledWith("conv-1");
|
|
250
|
+
|
|
251
|
+
expect(mockCreateConversation).toHaveBeenCalledTimes(1);
|
|
252
|
+
expect(mockCreateConversation).toHaveBeenCalledWith(
|
|
253
|
+
expect.objectContaining({
|
|
254
|
+
title: "Analysis: Source",
|
|
255
|
+
source: "auto-analysis",
|
|
256
|
+
groupId: "system:background",
|
|
257
|
+
forkParentConversationId: "conv-1",
|
|
258
|
+
}),
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test("auto: skips the run (no agent loop, no message persisted) when the rolling analysis conversation is already processing", async () => {
|
|
263
|
+
const conversation = makeConversation();
|
|
264
|
+
conversation.processing = true;
|
|
265
|
+
const deps = makeDeps(conversation);
|
|
266
|
+
|
|
267
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
268
|
+
trigger: "auto",
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Returns a successful no-op result tagged with `skipped: true`.
|
|
272
|
+
expect("error" in result).toBe(false);
|
|
273
|
+
if ("error" in result) throw new Error("expected success");
|
|
274
|
+
expect(result.analysisConversationId).toBe("analysis-new");
|
|
275
|
+
expect(result.skipped).toBe(true);
|
|
276
|
+
|
|
277
|
+
// Critically, none of the mutating side effects should have run: no
|
|
278
|
+
// message persisted, no trust context overwritten, no agent loop fired.
|
|
279
|
+
expect(mockAddMessage).not.toHaveBeenCalled();
|
|
280
|
+
expect(conversation.setTrustContext).not.toHaveBeenCalled();
|
|
281
|
+
expect(conversation.runAgentLoop).not.toHaveBeenCalled();
|
|
282
|
+
expect(conversation.abortController).toBeNull();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test("manual: does NOT skip when the conversation reports processing (guard is auto-only)", async () => {
|
|
286
|
+
const conversation = makeConversation();
|
|
287
|
+
conversation.processing = true;
|
|
288
|
+
const deps = makeDeps(conversation);
|
|
289
|
+
|
|
290
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
291
|
+
trigger: "manual",
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
expect("error" in result).toBe(false);
|
|
295
|
+
if ("error" in result) throw new Error("expected success");
|
|
296
|
+
expect(result.skipped).toBeUndefined();
|
|
297
|
+
|
|
298
|
+
// Manual trigger always proceeds — it creates a fresh conversation per
|
|
299
|
+
// invocation, so there is no shared-state concurrency hazard.
|
|
300
|
+
expect(mockAddMessage).toHaveBeenCalled();
|
|
301
|
+
expect(conversation.runAgentLoop).toHaveBeenCalled();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
test("auto: reuses an existing rolling analysis conversation (no new row)", async () => {
|
|
305
|
+
mockFindAnalysisConversationFor.mockImplementation(() => ({
|
|
306
|
+
id: "analysis-existing",
|
|
307
|
+
}));
|
|
308
|
+
const conversation = makeConversation();
|
|
309
|
+
const deps = makeDeps(conversation);
|
|
310
|
+
|
|
311
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
312
|
+
trigger: "auto",
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
expect("error" in result).toBe(false);
|
|
316
|
+
if ("error" in result) throw new Error("expected success");
|
|
317
|
+
expect(result.analysisConversationId).toBe("analysis-existing");
|
|
318
|
+
|
|
319
|
+
// No new conversation row is created on reuse.
|
|
320
|
+
expect(mockCreateConversation).not.toHaveBeenCalled();
|
|
321
|
+
|
|
322
|
+
// The new user message is appended to the existing analysis conversation.
|
|
323
|
+
expect(mockAddMessage).toHaveBeenCalledWith(
|
|
324
|
+
"analysis-existing",
|
|
325
|
+
"user",
|
|
326
|
+
expect.any(String),
|
|
327
|
+
{ provenanceTrustClass: "guardian" },
|
|
328
|
+
);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
test("auto: invalidates loadedHistoryTrustClass before ensureActorScopedHistory on reuse so stale ctx.messages is reloaded", async () => {
|
|
332
|
+
// Simulate a reused rolling conversation whose prior run already cached
|
|
333
|
+
// a guardian-class history load. Without explicit invalidation,
|
|
334
|
+
// ensureActorScopedHistory would short-circuit and runAgentLoopImpl
|
|
335
|
+
// would execute against ctx.messages missing the newly-enqueued prompt.
|
|
336
|
+
mockFindAnalysisConversationFor.mockImplementation(() => ({
|
|
337
|
+
id: "analysis-existing",
|
|
338
|
+
}));
|
|
339
|
+
const conversation = makeConversation();
|
|
340
|
+
conversation.loadedHistoryTrustClass = "guardian";
|
|
341
|
+
let trustClassWhenEnsured: string | undefined = "sentinel";
|
|
342
|
+
conversation.ensureActorScopedHistory.mockImplementation(() => {
|
|
343
|
+
trustClassWhenEnsured = conversation.loadedHistoryTrustClass;
|
|
344
|
+
return Promise.resolve();
|
|
345
|
+
});
|
|
346
|
+
const deps = makeDeps(conversation);
|
|
347
|
+
|
|
348
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
349
|
+
trigger: "auto",
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
expect("error" in result).toBe(false);
|
|
353
|
+
// The invalidation must land before ensureActorScopedHistory runs so
|
|
354
|
+
// the reload inside it pulls the freshly-persisted user prompt.
|
|
355
|
+
expect(trustClassWhenEnsured).toBeUndefined();
|
|
356
|
+
expect(conversation.ensureActorScopedHistory).toHaveBeenCalledTimes(1);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
test("auto: sets trustClass to guardian", async () => {
|
|
360
|
+
const conversation = makeConversation();
|
|
361
|
+
const deps = makeDeps(conversation);
|
|
362
|
+
|
|
363
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
364
|
+
trigger: "auto",
|
|
365
|
+
});
|
|
366
|
+
expect("error" in result).toBe(false);
|
|
367
|
+
|
|
368
|
+
expect(conversation.setTrustContext).toHaveBeenCalledWith({
|
|
369
|
+
trustClass: "guardian",
|
|
370
|
+
sourceChannel: "vellum",
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
test("auto: does NOT strip the tool surface", async () => {
|
|
375
|
+
const conversation = makeConversation();
|
|
376
|
+
const deps = makeDeps(conversation);
|
|
377
|
+
|
|
378
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
379
|
+
trigger: "auto",
|
|
380
|
+
});
|
|
381
|
+
expect("error" in result).toBe(false);
|
|
382
|
+
|
|
383
|
+
// Manual mode calls this with an empty Set; auto mode must leave the
|
|
384
|
+
// conversation's default tool surface intact.
|
|
385
|
+
expect(conversation.setSubagentAllowedTools).not.toHaveBeenCalled();
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
test("auto: rejects when the source conversation is itself an auto-analysis conversation", async () => {
|
|
389
|
+
mockGetConversationSource.mockImplementation(() => "auto-analysis");
|
|
390
|
+
const conversation = makeConversation();
|
|
391
|
+
const deps = makeDeps(conversation);
|
|
392
|
+
|
|
393
|
+
const result = await analyzeConversation("conv-1", deps, {
|
|
394
|
+
trigger: "auto",
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
expect("error" in result).toBe(true);
|
|
398
|
+
if (!("error" in result)) throw new Error("expected error");
|
|
399
|
+
expect(result.error.kind).toBe("BAD_REQUEST");
|
|
400
|
+
expect(result.error.status).toBe(400);
|
|
401
|
+
|
|
402
|
+
// Nothing downstream of the guard should have fired.
|
|
403
|
+
expect(mockFindAnalysisConversationFor).not.toHaveBeenCalled();
|
|
404
|
+
expect(mockCreateConversation).not.toHaveBeenCalled();
|
|
405
|
+
expect(mockAddMessage).not.toHaveBeenCalled();
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
test("auto: passes modelOverride through to getOrCreateConversation when set in config", async () => {
|
|
409
|
+
mockGetConfig.mockImplementation(() => ({
|
|
410
|
+
analysis: {
|
|
411
|
+
modelIntent: "quality-optimized",
|
|
412
|
+
modelOverride: "claude-opus-4-6",
|
|
413
|
+
},
|
|
414
|
+
}));
|
|
415
|
+
const conversation = makeConversation();
|
|
416
|
+
const deps = makeDeps(conversation);
|
|
417
|
+
|
|
418
|
+
await analyzeConversation("conv-1", deps, { trigger: "auto" });
|
|
419
|
+
|
|
420
|
+
expect(deps.getOrCreateConversation).toHaveBeenCalledWith(
|
|
421
|
+
"analysis-new",
|
|
422
|
+
expect.objectContaining({
|
|
423
|
+
modelIntent: "quality-optimized",
|
|
424
|
+
modelOverride: "claude-opus-4-6",
|
|
425
|
+
}),
|
|
426
|
+
);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
test("auto: does not pass modelOverride/modelIntent keys when config leaves them unset", async () => {
|
|
430
|
+
const conversation = makeConversation();
|
|
431
|
+
const deps = makeDeps(conversation);
|
|
432
|
+
|
|
433
|
+
await analyzeConversation("conv-1", deps, { trigger: "auto" });
|
|
434
|
+
|
|
435
|
+
const [, passedOpts] = (
|
|
436
|
+
deps.getOrCreateConversation.mock.calls as unknown as Array<
|
|
437
|
+
[string, Record<string, unknown>]
|
|
438
|
+
>
|
|
439
|
+
)[0] ?? ["", {}];
|
|
440
|
+
expect(passedOpts).toBeDefined();
|
|
441
|
+
expect("modelIntent" in (passedOpts ?? {})).toBe(false);
|
|
442
|
+
expect("modelOverride" in (passedOpts ?? {})).toBe(false);
|
|
443
|
+
});
|
|
444
|
+
});
|