@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
|
@@ -214,6 +214,8 @@ mock.module("../memory/canonical-guardian-store.js", () => ({
|
|
|
214
214
|
// ---------------------------------------------------------------------------
|
|
215
215
|
|
|
216
216
|
import { Conversation } from "../daemon/conversation.js";
|
|
217
|
+
import { HostBashProxy } from "../daemon/host-bash-proxy.js";
|
|
218
|
+
import { HostBrowserProxy } from "../daemon/host-browser-proxy.js";
|
|
217
219
|
|
|
218
220
|
// ---------------------------------------------------------------------------
|
|
219
221
|
// Helpers
|
|
@@ -558,3 +560,291 @@ describe("sendToClient receives state signals", () => {
|
|
|
558
560
|
});
|
|
559
561
|
});
|
|
560
562
|
});
|
|
563
|
+
|
|
564
|
+
describe("restoreBrowserProxyAvailability", () => {
|
|
565
|
+
test("re-enables only the host browser proxy after clearProxyAvailability", () => {
|
|
566
|
+
const conversation = makeConversation();
|
|
567
|
+
const browserProxy = new HostBrowserProxy(() => {});
|
|
568
|
+
const bashProxy = new HostBashProxy(() => {});
|
|
569
|
+
conversation.setHostBrowserProxy(browserProxy);
|
|
570
|
+
conversation.setHostBashProxy(bashProxy);
|
|
571
|
+
|
|
572
|
+
// Mark as having a connected client (interactive desktop path).
|
|
573
|
+
conversation.updateClient(() => {}, false);
|
|
574
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
575
|
+
expect(bashProxy.isAvailable()).toBe(true);
|
|
576
|
+
|
|
577
|
+
// The drain queue clears all proxies for non-interactive turns.
|
|
578
|
+
conversation.clearProxyAvailability();
|
|
579
|
+
expect(browserProxy.isAvailable()).toBe(false);
|
|
580
|
+
expect(bashProxy.isAvailable()).toBe(false);
|
|
581
|
+
|
|
582
|
+
// restoreBrowserProxyAvailability should bring back ONLY the browser proxy.
|
|
583
|
+
conversation.restoreBrowserProxyAvailability();
|
|
584
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
585
|
+
expect(bashProxy.isAvailable()).toBe(false);
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
test("re-enables the browser proxy even when hasNoClient is true (chrome-extension)", () => {
|
|
589
|
+
// Regression: chrome-extension is non-interactive (hasNoClient stays
|
|
590
|
+
// true so host_bash/host_file tools remain gated), but we still need
|
|
591
|
+
// to provision the hostBrowserProxy so it can service CDP commands.
|
|
592
|
+
// The helper must NOT gate on hasNoClient.
|
|
593
|
+
const conversation = makeConversation();
|
|
594
|
+
const browserProxy = new HostBrowserProxy(() => {});
|
|
595
|
+
conversation.setHostBrowserProxy(browserProxy);
|
|
596
|
+
|
|
597
|
+
// updateClient with hasNoClient=true emulates the non-interactive
|
|
598
|
+
// chrome-extension turn. Host proxies start disabled because
|
|
599
|
+
// updateClient propagates hasNoClient through to updateSender.
|
|
600
|
+
conversation.updateClient(() => {}, true);
|
|
601
|
+
expect(browserProxy.isAvailable()).toBe(false);
|
|
602
|
+
expect(conversation["hasNoClient"]).toBe(true);
|
|
603
|
+
|
|
604
|
+
// The targeted helper bypasses the hasNoClient gate so the
|
|
605
|
+
// single-capability chrome-extension turn can drive the browser
|
|
606
|
+
// via CDP without flipping hasNoClient (which would also enable
|
|
607
|
+
// host_bash/host_file gating downstream).
|
|
608
|
+
conversation.restoreBrowserProxyAvailability();
|
|
609
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
610
|
+
// hasNoClient itself MUST remain true so that
|
|
611
|
+
// isToolActiveForContext keeps host_bash/host_file/host_cu gated.
|
|
612
|
+
expect(conversation["hasNoClient"]).toBe(true);
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
test("leaves bash/file/cu proxies disabled when called for chrome-extension", () => {
|
|
616
|
+
// Regression: the targeted helper must not accidentally re-enable
|
|
617
|
+
// proxies other than host_browser, even when called from a path that
|
|
618
|
+
// owns multiple proxies (e.g. macOS holdover state with hasNoClient
|
|
619
|
+
// forced true for an explicit non-interactive run).
|
|
620
|
+
const conversation = makeConversation();
|
|
621
|
+
const browserProxy = new HostBrowserProxy(() => {});
|
|
622
|
+
const bashProxy = new HostBashProxy(() => {});
|
|
623
|
+
conversation.setHostBrowserProxy(browserProxy);
|
|
624
|
+
conversation.setHostBashProxy(bashProxy);
|
|
625
|
+
|
|
626
|
+
conversation.updateClient(() => {}, true);
|
|
627
|
+
expect(browserProxy.isAvailable()).toBe(false);
|
|
628
|
+
expect(bashProxy.isAvailable()).toBe(false);
|
|
629
|
+
|
|
630
|
+
conversation.restoreBrowserProxyAvailability();
|
|
631
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
632
|
+
// Crucial: bash proxy stays disabled. The helper must touch ONLY the
|
|
633
|
+
// browser proxy.
|
|
634
|
+
expect(bashProxy.isAvailable()).toBe(false);
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
test("uses hostBrowserSenderOverride when set so drain-queue restores preserve the registry-routed sender", () => {
|
|
638
|
+
// Regression (PR #24129 cycle 2): the queue-drain path calls
|
|
639
|
+
// `restoreBrowserProxyAvailability()` on dequeue, which used to pass
|
|
640
|
+
// `this.sendToClient` (the SSE hub emitter) to the proxy, clobbering the
|
|
641
|
+
// chrome-extension registry-routed sender established by the POST
|
|
642
|
+
// /messages handler. The override field lets the HTTP handler pin the
|
|
643
|
+
// registry-routed sender so the drain path preserves it.
|
|
644
|
+
const sseHub: ServerMessage[] = [];
|
|
645
|
+
const registry: ServerMessage[] = [];
|
|
646
|
+
const conversation = makeConversation((msg) => sseHub.push(msg));
|
|
647
|
+
const browserProxy = new HostBrowserProxy(() => {});
|
|
648
|
+
conversation.setHostBrowserProxy(browserProxy);
|
|
649
|
+
|
|
650
|
+
// Simulate updateClient setting sendToClient to the SSE hub and
|
|
651
|
+
// marking the conversation as client-less (chrome-extension is
|
|
652
|
+
// non-interactive).
|
|
653
|
+
conversation.updateClient((msg) => sseHub.push(msg), true);
|
|
654
|
+
expect(browserProxy.isAvailable()).toBe(false);
|
|
655
|
+
|
|
656
|
+
// The HTTP handler stashes the registry-routed sender as the override.
|
|
657
|
+
const registrySender = (msg: ServerMessage) => registry.push(msg);
|
|
658
|
+
conversation.hostBrowserSenderOverride = registrySender;
|
|
659
|
+
|
|
660
|
+
// Drain-queue path calls restoreBrowserProxyAvailability — it must now
|
|
661
|
+
// prefer the override over sendToClient.
|
|
662
|
+
conversation.restoreBrowserProxyAvailability();
|
|
663
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
664
|
+
|
|
665
|
+
// Send a frame through the proxy and verify it flows through the
|
|
666
|
+
// registry sender, not the SSE hub.
|
|
667
|
+
const internalSend = (
|
|
668
|
+
browserProxy as unknown as {
|
|
669
|
+
sendToClient: (msg: ServerMessage) => void;
|
|
670
|
+
}
|
|
671
|
+
).sendToClient;
|
|
672
|
+
const probe: ServerMessage = {
|
|
673
|
+
type: "host_browser_cancel",
|
|
674
|
+
requestId: "probe-1",
|
|
675
|
+
} as ServerMessage;
|
|
676
|
+
internalSend(probe);
|
|
677
|
+
expect(registry).toHaveLength(1);
|
|
678
|
+
expect(sseHub.some((m) => m === probe)).toBe(false);
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
test("falls back to sendToClient when hostBrowserSenderOverride is cleared", () => {
|
|
682
|
+
// When a non-chrome-extension turn takes over, the HTTP handler clears
|
|
683
|
+
// the override and restoreBrowserProxyAvailability must fall back to
|
|
684
|
+
// sendToClient (the SSE hub), otherwise macOS turns would route their
|
|
685
|
+
// host_browser frames through the stale chrome-extension registry.
|
|
686
|
+
const sseHub: ServerMessage[] = [];
|
|
687
|
+
const conversation = makeConversation((msg) => sseHub.push(msg));
|
|
688
|
+
const browserProxy = new HostBrowserProxy(() => {});
|
|
689
|
+
conversation.setHostBrowserProxy(browserProxy);
|
|
690
|
+
|
|
691
|
+
// First the chrome-extension path pins the override.
|
|
692
|
+
const registry: ServerMessage[] = [];
|
|
693
|
+
conversation.hostBrowserSenderOverride = (msg) => registry.push(msg);
|
|
694
|
+
conversation.updateClient((msg) => sseHub.push(msg), true);
|
|
695
|
+
conversation.restoreBrowserProxyAvailability();
|
|
696
|
+
|
|
697
|
+
// Then a macOS handoff clears the override.
|
|
698
|
+
conversation.hostBrowserSenderOverride = undefined;
|
|
699
|
+
conversation.updateClient((msg) => sseHub.push(msg), false);
|
|
700
|
+
conversation.restoreBrowserProxyAvailability();
|
|
701
|
+
|
|
702
|
+
const internalSend = (
|
|
703
|
+
browserProxy as unknown as {
|
|
704
|
+
sendToClient: (msg: ServerMessage) => void;
|
|
705
|
+
}
|
|
706
|
+
).sendToClient;
|
|
707
|
+
const probe: ServerMessage = {
|
|
708
|
+
type: "host_browser_cancel",
|
|
709
|
+
requestId: "probe-2",
|
|
710
|
+
} as ServerMessage;
|
|
711
|
+
internalSend(probe);
|
|
712
|
+
expect(sseHub).toContain(probe);
|
|
713
|
+
expect(registry).not.toContain(probe);
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
describe("hostBrowserSenderOverride is sender-mode based, not interface-string based", () => {
|
|
718
|
+
test("macOS turn with registry override routes browser frames through the registry sender", () => {
|
|
719
|
+
// When a macOS turn sets hostBrowserSenderOverride (because the
|
|
720
|
+
// guardian has an active extension connection), the browser proxy
|
|
721
|
+
// must route through the registry sender, not the SSE hub — the
|
|
722
|
+
// same behavior chrome-extension turns have always used.
|
|
723
|
+
const sseHub: ServerMessage[] = [];
|
|
724
|
+
const registry: ServerMessage[] = [];
|
|
725
|
+
const conversation = makeConversation((msg) => sseHub.push(msg));
|
|
726
|
+
const browserProxy = new HostBrowserProxy(() => {});
|
|
727
|
+
conversation.setHostBrowserProxy(browserProxy);
|
|
728
|
+
|
|
729
|
+
// macOS is interactive — hasNoClient is false.
|
|
730
|
+
conversation.updateClient((msg) => sseHub.push(msg), false);
|
|
731
|
+
|
|
732
|
+
// The POST /messages handler detected an active extension connection
|
|
733
|
+
// and set the registry-routed sender override.
|
|
734
|
+
const registrySender = (msg: ServerMessage) => registry.push(msg);
|
|
735
|
+
conversation.hostBrowserSenderOverride = registrySender;
|
|
736
|
+
|
|
737
|
+
// restoreBrowserProxyAvailability (called after updateClient in the
|
|
738
|
+
// POST handler) must prefer the override.
|
|
739
|
+
conversation.restoreBrowserProxyAvailability();
|
|
740
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
741
|
+
|
|
742
|
+
// Verify frames flow through the registry, not the SSE hub.
|
|
743
|
+
const internalSend = (
|
|
744
|
+
browserProxy as unknown as {
|
|
745
|
+
sendToClient: (msg: ServerMessage) => void;
|
|
746
|
+
}
|
|
747
|
+
).sendToClient;
|
|
748
|
+
const probe: ServerMessage = {
|
|
749
|
+
type: "host_browser_cancel",
|
|
750
|
+
requestId: "probe-macos-registry",
|
|
751
|
+
} as ServerMessage;
|
|
752
|
+
internalSend(probe);
|
|
753
|
+
expect(registry).toHaveLength(1);
|
|
754
|
+
expect(sseHub.some((m) => m === probe)).toBe(false);
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
test("macOS turn without registry override clears the browser proxy on restore", () => {
|
|
758
|
+
// When a macOS turn has no active extension connection, the override
|
|
759
|
+
// is cleared and restoreBrowserProxyAvailability falls back to the
|
|
760
|
+
// SSE hub sender. The proxy should not be stuck on an unavailable
|
|
761
|
+
// registry-routed sender from a prior chrome-extension turn.
|
|
762
|
+
const sseHub: ServerMessage[] = [];
|
|
763
|
+
const conversation = makeConversation((msg) => sseHub.push(msg));
|
|
764
|
+
const browserProxy = new HostBrowserProxy(() => {});
|
|
765
|
+
conversation.setHostBrowserProxy(browserProxy);
|
|
766
|
+
|
|
767
|
+
// Interactive macOS turn without extension connectivity.
|
|
768
|
+
conversation.updateClient((msg) => sseHub.push(msg), false);
|
|
769
|
+
conversation.hostBrowserSenderOverride = undefined;
|
|
770
|
+
conversation.restoreBrowserProxyAvailability();
|
|
771
|
+
|
|
772
|
+
// The proxy should be available and routed through SSE.
|
|
773
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
774
|
+
const internalSend = (
|
|
775
|
+
browserProxy as unknown as {
|
|
776
|
+
sendToClient: (msg: ServerMessage) => void;
|
|
777
|
+
}
|
|
778
|
+
).sendToClient;
|
|
779
|
+
const probe: ServerMessage = {
|
|
780
|
+
type: "host_browser_cancel",
|
|
781
|
+
requestId: "probe-macos-sse",
|
|
782
|
+
} as ServerMessage;
|
|
783
|
+
internalSend(probe);
|
|
784
|
+
expect(sseHub).toContain(probe);
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
test("override semantics are symmetric: chrome-extension and macOS both set override when registry-routed", () => {
|
|
788
|
+
// The override field must be set for ANY interface that uses a
|
|
789
|
+
// registry-routed sender, and cleared for any that does not.
|
|
790
|
+
// This test verifies the field is not gated on interface strings.
|
|
791
|
+
const conversation = makeConversation();
|
|
792
|
+
const registrySender = () => {};
|
|
793
|
+
|
|
794
|
+
// Simulate chrome-extension setting the override.
|
|
795
|
+
conversation.hostBrowserSenderOverride = registrySender;
|
|
796
|
+
expect(conversation.hostBrowserSenderOverride).toBe(registrySender);
|
|
797
|
+
|
|
798
|
+
// Simulate macOS-with-extension setting the same override.
|
|
799
|
+
// The field value is the same registry sender, not gated by interface.
|
|
800
|
+
const macosRegistrySender = () => {};
|
|
801
|
+
conversation.hostBrowserSenderOverride = macosRegistrySender;
|
|
802
|
+
expect(conversation.hostBrowserSenderOverride).toBe(macosRegistrySender);
|
|
803
|
+
|
|
804
|
+
// Simulate macOS-without-extension clearing the override.
|
|
805
|
+
conversation.hostBrowserSenderOverride = undefined;
|
|
806
|
+
expect(conversation.hostBrowserSenderOverride).toBeUndefined();
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
test("queue-drain restore path preserves registry-routed sender for macOS turns", () => {
|
|
810
|
+
// When a macOS turn with an active extension connection has its
|
|
811
|
+
// messages queued and later drained, the drain-queue path calls
|
|
812
|
+
// restoreBrowserProxyAvailability(). With the override set, the
|
|
813
|
+
// proxy must be restored with the registry sender, not the SSE hub.
|
|
814
|
+
const sseHub: ServerMessage[] = [];
|
|
815
|
+
const registry: ServerMessage[] = [];
|
|
816
|
+
const conversation = makeConversation((msg) => sseHub.push(msg));
|
|
817
|
+
const browserProxy = new HostBrowserProxy(() => {});
|
|
818
|
+
conversation.setHostBrowserProxy(browserProxy);
|
|
819
|
+
|
|
820
|
+
// macOS interactive turn with extension connectivity.
|
|
821
|
+
conversation.updateClient((msg) => sseHub.push(msg), false);
|
|
822
|
+
const registrySender = (msg: ServerMessage) => registry.push(msg);
|
|
823
|
+
conversation.hostBrowserSenderOverride = registrySender;
|
|
824
|
+
conversation.restoreBrowserProxyAvailability();
|
|
825
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
826
|
+
|
|
827
|
+
// Simulate drain-queue clearing all proxies for a non-interactive
|
|
828
|
+
// queued message, then restoring for the next macOS turn.
|
|
829
|
+
conversation.clearProxyAvailability();
|
|
830
|
+
expect(browserProxy.isAvailable()).toBe(false);
|
|
831
|
+
|
|
832
|
+
// Drain restore — override is still set from the POST handler.
|
|
833
|
+
conversation.restoreBrowserProxyAvailability();
|
|
834
|
+
expect(browserProxy.isAvailable()).toBe(true);
|
|
835
|
+
|
|
836
|
+
// Verify the registry sender was preserved, not the SSE hub.
|
|
837
|
+
const internalSend = (
|
|
838
|
+
browserProxy as unknown as {
|
|
839
|
+
sendToClient: (msg: ServerMessage) => void;
|
|
840
|
+
}
|
|
841
|
+
).sendToClient;
|
|
842
|
+
const probe: ServerMessage = {
|
|
843
|
+
type: "host_browser_cancel",
|
|
844
|
+
requestId: "probe-drain-macos",
|
|
845
|
+
} as ServerMessage;
|
|
846
|
+
internalSend(probe);
|
|
847
|
+
expect(registry).toHaveLength(1);
|
|
848
|
+
expect(sseHub.some((m) => m === probe)).toBe(false);
|
|
849
|
+
});
|
|
850
|
+
});
|
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
classifyConversationError,
|
|
7
7
|
isUserCancellation,
|
|
8
8
|
} from "../daemon/conversation-error.js";
|
|
9
|
+
import {
|
|
10
|
+
type AbortReasonKind,
|
|
11
|
+
createAbortReason,
|
|
12
|
+
} from "../util/abort-reasons.js";
|
|
9
13
|
import { ProviderError, ProviderNotConfiguredError } from "../util/errors.js";
|
|
10
14
|
|
|
11
15
|
describe("isUserCancellation", () => {
|
|
@@ -563,6 +567,72 @@ describe("classifyConversationError", () => {
|
|
|
563
567
|
expect(isUserCancellation(err, aborted)).toBe(true);
|
|
564
568
|
});
|
|
565
569
|
});
|
|
570
|
+
|
|
571
|
+
describe("wrapped ProviderError carrying tagged abort reason", () => {
|
|
572
|
+
const abortedCtx: ErrorContext = { phase: "agent_loop", aborted: true };
|
|
573
|
+
const taggedKinds: AbortReasonKind[] = [
|
|
574
|
+
"user_cancel",
|
|
575
|
+
"preempted_by_new_message",
|
|
576
|
+
"conversation_disposed",
|
|
577
|
+
"subagent_aborted",
|
|
578
|
+
"signal_cancel",
|
|
579
|
+
"voice_session_aborted",
|
|
580
|
+
"work_item_aborted",
|
|
581
|
+
];
|
|
582
|
+
|
|
583
|
+
for (const kind of taggedKinds) {
|
|
584
|
+
it(`treats ProviderError with abortReason kind="${kind}" as user cancellation`, () => {
|
|
585
|
+
const wrapped = new ProviderError(
|
|
586
|
+
"Anthropic API error (undefined): Request was aborted.",
|
|
587
|
+
"anthropic",
|
|
588
|
+
undefined,
|
|
589
|
+
{ abortReason: createAbortReason(kind, `test:${kind}`) },
|
|
590
|
+
);
|
|
591
|
+
expect(isUserCancellation(wrapped, abortedCtx)).toBe(true);
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
it("does NOT treat tagged ProviderError as cancellation when ctx.aborted is false", () => {
|
|
596
|
+
const wrapped = new ProviderError(
|
|
597
|
+
"Anthropic API error (undefined): Request was aborted.",
|
|
598
|
+
"anthropic",
|
|
599
|
+
undefined,
|
|
600
|
+
{ abortReason: createAbortReason("user_cancel", "test") },
|
|
601
|
+
);
|
|
602
|
+
const notAborted: ErrorContext = { phase: "agent_loop", aborted: false };
|
|
603
|
+
expect(isUserCancellation(wrapped, notAborted)).toBe(false);
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
it("does NOT treat ProviderError without abortReason as cancellation", () => {
|
|
607
|
+
const wrapped = new ProviderError(
|
|
608
|
+
"Anthropic API error (undefined): Request was aborted.",
|
|
609
|
+
"anthropic",
|
|
610
|
+
undefined,
|
|
611
|
+
);
|
|
612
|
+
expect(isUserCancellation(wrapped, abortedCtx)).toBe(false);
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
it("does NOT treat ProviderError with foreign reason as cancellation", () => {
|
|
616
|
+
const wrapped = new ProviderError(
|
|
617
|
+
"Anthropic API error (undefined): Request was aborted.",
|
|
618
|
+
"anthropic",
|
|
619
|
+
undefined,
|
|
620
|
+
{ abortReason: { kind: "user_cancel", source: "spoofed" } },
|
|
621
|
+
);
|
|
622
|
+
expect(isUserCancellation(wrapped, abortedCtx)).toBe(false);
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
it("falls through to CONVERSATION_ABORTED when wrapped ProviderError has no tagged reason", () => {
|
|
626
|
+
const wrapped = new ProviderError(
|
|
627
|
+
"Anthropic API error (undefined): Request was aborted.",
|
|
628
|
+
"anthropic",
|
|
629
|
+
undefined,
|
|
630
|
+
);
|
|
631
|
+
const result = classifyConversationError(wrapped, abortedCtx);
|
|
632
|
+
expect(result.code).toBe("CONVERSATION_ABORTED");
|
|
633
|
+
expect(result.errorCategory).toBe("session_aborted");
|
|
634
|
+
});
|
|
635
|
+
});
|
|
566
636
|
});
|
|
567
637
|
|
|
568
638
|
describe("buildConversationErrorMessage", () => {
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
addMessage,
|
|
36
36
|
createConversation,
|
|
37
37
|
forkConversation,
|
|
38
|
+
getConversationHostAccess,
|
|
38
39
|
getMessages,
|
|
39
40
|
PRIVATE_CONVERSATION_FORK_ERROR,
|
|
40
41
|
} from "../memory/conversation-crud.js";
|
|
@@ -138,6 +139,22 @@ describe("forkConversation", () => {
|
|
|
138
139
|
).toBe(true);
|
|
139
140
|
});
|
|
140
141
|
|
|
142
|
+
test("forked conversations start with host access disabled", async () => {
|
|
143
|
+
const source = createConversation({
|
|
144
|
+
title: "Computer-enabled thread",
|
|
145
|
+
hostAccess: true,
|
|
146
|
+
});
|
|
147
|
+
await addMessage(source.id, "user", "Use the computer", undefined, {
|
|
148
|
+
skipIndexing: true,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const fork = forkConversation({ conversationId: source.id });
|
|
152
|
+
|
|
153
|
+
expect(getConversationHostAccess(source.id)).toBe(true);
|
|
154
|
+
expect(getConversationHostAccess(fork.id)).toBe(false);
|
|
155
|
+
expect(fork.hostAccess).toBe(0);
|
|
156
|
+
});
|
|
157
|
+
|
|
141
158
|
test("preserves source order when source messages share a timestamp", () => {
|
|
142
159
|
const source = createConversation("Equal timestamp thread");
|
|
143
160
|
const db = getDb();
|
|
@@ -747,15 +747,23 @@ describe("web_search_tool_result structural guard", () => {
|
|
|
747
747
|
// web_search_tool_result has a structurally different content format
|
|
748
748
|
// (array of web_search_result objects) and is not truncated this way.
|
|
749
749
|
"context/tool-result-truncation.ts",
|
|
750
|
+
"context/post-turn-tool-result-truncation.ts",
|
|
750
751
|
|
|
751
752
|
// Anthropic provider type guards define API-specific discriminants.
|
|
752
753
|
// It has a separate isWebSearchToolResultBlock for the other type.
|
|
753
754
|
"providers/anthropic/client.ts",
|
|
754
755
|
|
|
755
|
-
//
|
|
756
|
-
//
|
|
757
|
-
// blocks are handled upstream
|
|
758
|
-
|
|
756
|
+
// Chat-completions transport used by OpenAI-compatible providers
|
|
757
|
+
// (OpenRouter, Fireworks, Ollama). These APIs do not support
|
|
758
|
+
// web_search_tool_result natively; those blocks are handled upstream
|
|
759
|
+
// before reaching the chat-completions provider.
|
|
760
|
+
"providers/openai/chat-completions-provider.ts",
|
|
761
|
+
|
|
762
|
+
// OpenAI Responses API transport (used for direct OpenAI inference).
|
|
763
|
+
// Converts Anthropic-style messages to Responses API input format.
|
|
764
|
+
// web_search_tool_result blocks are handled upstream before reaching
|
|
765
|
+
// the responses provider.
|
|
766
|
+
"providers/openai/responses-provider.ts",
|
|
759
767
|
|
|
760
768
|
// Renders tool_result blocks for client display. web_search_tool_result
|
|
761
769
|
// blocks are rendered by the client via their own display path.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
let authDisabled = true;
|
|
4
|
+
let boundGuardianPrincipalId: string | null = null;
|
|
5
|
+
|
|
6
|
+
mock.module("../util/logger.js", () => ({
|
|
7
|
+
getLogger: () =>
|
|
8
|
+
new Proxy({} as Record<string, unknown>, {
|
|
9
|
+
get: () => () => {},
|
|
10
|
+
}),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
mock.module("../config/env.js", () => ({
|
|
14
|
+
isHttpAuthDisabled: () => authDisabled,
|
|
15
|
+
hasUngatedHttpAuthDisabled: () => false,
|
|
16
|
+
getGatewayInternalBaseUrl: () => "http://127.0.0.1:7830",
|
|
17
|
+
getGatewayPort: () => 7830,
|
|
18
|
+
getRuntimeHttpPort: () => 7821,
|
|
19
|
+
getRuntimeHttpHost: () => "127.0.0.1",
|
|
20
|
+
getRuntimeGatewayOriginSecret: () => undefined,
|
|
21
|
+
getIngressPublicBaseUrl: () => undefined,
|
|
22
|
+
setIngressPublicBaseUrl: () => {},
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
mock.module("../contacts/contact-store.js", () => ({
|
|
26
|
+
findGuardianForChannel: () =>
|
|
27
|
+
boundGuardianPrincipalId
|
|
28
|
+
? {
|
|
29
|
+
channel: { externalUserId: undefined },
|
|
30
|
+
contact: { principalId: boundGuardianPrincipalId },
|
|
31
|
+
}
|
|
32
|
+
: null,
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
mock.module("../config/loader.js", () => ({
|
|
36
|
+
getConfig: () => ({
|
|
37
|
+
ui: {},
|
|
38
|
+
model: "test",
|
|
39
|
+
provider: "test",
|
|
40
|
+
memory: { enabled: false },
|
|
41
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
42
|
+
secretDetection: { enabled: false },
|
|
43
|
+
}),
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
import {
|
|
47
|
+
createConversation,
|
|
48
|
+
updateConversationHostAccess,
|
|
49
|
+
} from "../memory/conversation-crud.js";
|
|
50
|
+
import { getDb, initializeDb, resetDb } from "../memory/db.js";
|
|
51
|
+
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
52
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
53
|
+
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
54
|
+
import { conversationManagementRouteDefinitions } from "../runtime/routes/conversation-management-routes.js";
|
|
55
|
+
|
|
56
|
+
initializeDb();
|
|
57
|
+
|
|
58
|
+
const routes = conversationManagementRouteDefinitions({
|
|
59
|
+
switchConversation: async (conversationId) => {
|
|
60
|
+
const conversation = {
|
|
61
|
+
conversationId,
|
|
62
|
+
title: "Switched conversation",
|
|
63
|
+
conversationType: "standard",
|
|
64
|
+
hostAccess: false,
|
|
65
|
+
};
|
|
66
|
+
return conversation;
|
|
67
|
+
},
|
|
68
|
+
renameConversation: () => true,
|
|
69
|
+
clearAllConversations: () => 0,
|
|
70
|
+
cancelGeneration: () => true,
|
|
71
|
+
destroyConversation: () => {},
|
|
72
|
+
undoLastMessage: async () => null,
|
|
73
|
+
regenerateResponse: async () => null,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
function findRoute(method: string, endpoint: string) {
|
|
77
|
+
const route = routes.find(
|
|
78
|
+
(routeDef) => routeDef.method === method && routeDef.endpoint === endpoint,
|
|
79
|
+
);
|
|
80
|
+
if (!route) {
|
|
81
|
+
throw new Error(`Route not found: ${method} ${endpoint}`);
|
|
82
|
+
}
|
|
83
|
+
return route;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function clearTables(): void {
|
|
87
|
+
const db = getDb();
|
|
88
|
+
db.run("DELETE FROM conversation_assistant_attention_state");
|
|
89
|
+
db.run("DELETE FROM external_conversation_bindings");
|
|
90
|
+
db.run("DELETE FROM conversation_keys");
|
|
91
|
+
db.run("DELETE FROM messages");
|
|
92
|
+
db.run("DELETE FROM conversations");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
describe("conversation host-access transport", () => {
|
|
96
|
+
let server: RuntimeHttpServer | null = null;
|
|
97
|
+
|
|
98
|
+
beforeEach(async () => {
|
|
99
|
+
await server?.stop();
|
|
100
|
+
server = null;
|
|
101
|
+
authDisabled = true;
|
|
102
|
+
boundGuardianPrincipalId = null;
|
|
103
|
+
clearTables();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
afterAll(async () => {
|
|
107
|
+
await server?.stop();
|
|
108
|
+
resetDb();
|
|
109
|
+
mock.restore();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("GET and PATCH /v1/conversations/:id/host-access use the conversation store", async () => {
|
|
113
|
+
const conversation = createConversation("Host access test");
|
|
114
|
+
|
|
115
|
+
const getRoute = findRoute("GET", "conversations/:id/host-access");
|
|
116
|
+
const getResponse = await getRoute.handler({
|
|
117
|
+
req: new Request("http://localhost/v1/conversations/test/host-access"),
|
|
118
|
+
url: new URL("http://localhost/v1/conversations/test/host-access"),
|
|
119
|
+
server: null as never,
|
|
120
|
+
authContext: {} as never,
|
|
121
|
+
params: { id: conversation.id },
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(getResponse.status).toBe(200);
|
|
125
|
+
expect(await getResponse.json()).toEqual({
|
|
126
|
+
conversationId: conversation.id,
|
|
127
|
+
hostAccess: false,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const received: Array<{
|
|
131
|
+
assistantId: string;
|
|
132
|
+
type: string;
|
|
133
|
+
conversationId?: string;
|
|
134
|
+
hostAccess?: boolean;
|
|
135
|
+
}> = [];
|
|
136
|
+
const subscription = assistantEventHub.subscribe(
|
|
137
|
+
{ assistantId: DAEMON_INTERNAL_ASSISTANT_ID },
|
|
138
|
+
(event) => {
|
|
139
|
+
received.push({
|
|
140
|
+
assistantId: event.assistantId,
|
|
141
|
+
type: event.message.type,
|
|
142
|
+
conversationId: event.conversationId,
|
|
143
|
+
hostAccess:
|
|
144
|
+
event.message.type === "conversation_host_access_updated"
|
|
145
|
+
? event.message.hostAccess
|
|
146
|
+
: undefined,
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
const patchRoute = findRoute("PATCH", "conversations/:id/host-access");
|
|
152
|
+
const patchResponse = await patchRoute.handler({
|
|
153
|
+
req: new Request("http://localhost/v1/conversations/test/host-access", {
|
|
154
|
+
method: "PATCH",
|
|
155
|
+
headers: { "Content-Type": "application/json" },
|
|
156
|
+
body: JSON.stringify({ hostAccess: true }),
|
|
157
|
+
}),
|
|
158
|
+
url: new URL("http://localhost/v1/conversations/test/host-access"),
|
|
159
|
+
server: null as never,
|
|
160
|
+
authContext: {} as never,
|
|
161
|
+
params: { id: conversation.id },
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
await Promise.resolve();
|
|
165
|
+
|
|
166
|
+
expect(patchResponse.status).toBe(200);
|
|
167
|
+
expect(await patchResponse.json()).toEqual({
|
|
168
|
+
conversationId: conversation.id,
|
|
169
|
+
hostAccess: true,
|
|
170
|
+
});
|
|
171
|
+
expect(received).toHaveLength(1);
|
|
172
|
+
expect(received[0]).toEqual({
|
|
173
|
+
assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
174
|
+
type: "conversation_host_access_updated",
|
|
175
|
+
conversationId: conversation.id,
|
|
176
|
+
hostAccess: true,
|
|
177
|
+
});
|
|
178
|
+
subscription.dispose();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("conversation summaries include hostAccess", async () => {
|
|
182
|
+
const conversation = createConversation("Summary host access");
|
|
183
|
+
updateConversationHostAccess(conversation.id, true);
|
|
184
|
+
|
|
185
|
+
server = new RuntimeHttpServer({
|
|
186
|
+
port: 0,
|
|
187
|
+
bearerToken: "test-bearer-token",
|
|
188
|
+
});
|
|
189
|
+
await server.start();
|
|
190
|
+
|
|
191
|
+
const response = await fetch(
|
|
192
|
+
`http://127.0.0.1:${server.actualPort}/v1/conversations/${conversation.id}`,
|
|
193
|
+
);
|
|
194
|
+
expect(response.status).toBe(200);
|
|
195
|
+
|
|
196
|
+
const body = (await response.json()) as {
|
|
197
|
+
conversation: {
|
|
198
|
+
id: string;
|
|
199
|
+
hostAccess: boolean;
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
expect(body.conversation.id).toBe(conversation.id);
|
|
204
|
+
expect(body.conversation.hostAccess).toBe(true);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("PATCH /v1/conversations/:id/host-access rejects non-guardian actors when auth is enforced", async () => {
|
|
208
|
+
authDisabled = false;
|
|
209
|
+
boundGuardianPrincipalId = "guardian-principal";
|
|
210
|
+
const conversation = createConversation("Guarded host access");
|
|
211
|
+
|
|
212
|
+
const patchRoute = findRoute("PATCH", "conversations/:id/host-access");
|
|
213
|
+
const patchResponse = await patchRoute.handler({
|
|
214
|
+
req: new Request("http://localhost/v1/conversations/test/host-access", {
|
|
215
|
+
method: "PATCH",
|
|
216
|
+
headers: { "Content-Type": "application/json" },
|
|
217
|
+
body: JSON.stringify({ hostAccess: true }),
|
|
218
|
+
}),
|
|
219
|
+
url: new URL("http://localhost/v1/conversations/test/host-access"),
|
|
220
|
+
server: null as never,
|
|
221
|
+
authContext: {
|
|
222
|
+
actorPrincipalId: "trusted-contact-principal",
|
|
223
|
+
} as never,
|
|
224
|
+
params: { id: conversation.id },
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
expect(patchResponse.status).toBe(403);
|
|
228
|
+
});
|
|
229
|
+
});
|