@vellumai/assistant 0.6.3 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +5 -0
- package/ARCHITECTURE.md +298 -39
- package/Dockerfile +14 -3
- package/README.md +3 -4
- package/bun.lock +13 -16
- package/docs/architecture/integrations.md +1 -20
- package/docs/architecture/security.md +16 -16
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/error-handling.md +111 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +121 -0
- package/knip.json +20 -3
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +5 -4
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
- package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
- package/node_modules/@vellumai/credential-storage/package.json +2 -2
- package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
- package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
- package/node_modules/@vellumai/egress-proxy/package.json +2 -2
- package/openapi.yaml +1094 -72
- package/package.json +9 -8
- package/scripts/generate-openapi.ts +50 -12
- package/scripts/test.sh +73 -18
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
- package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
- package/src/__tests__/agent-loop.test.ts +235 -1
- package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
- package/src/__tests__/anthropic-provider.test.ts +434 -12
- package/src/__tests__/approval-cascade.test.ts +31 -10
- package/src/__tests__/approval-routes-http.test.ts +134 -10
- package/src/__tests__/assistant-attachments.test.ts +44 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
- package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
- package/src/__tests__/browser-fill-credential.test.ts +12 -1
- package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
- package/src/__tests__/browser-skill-endstate.test.ts +52 -159
- package/src/__tests__/btw-routes.test.ts +54 -1
- package/src/__tests__/call-controller.test.ts +582 -22
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +27 -4
- package/src/__tests__/catalog-files.test.ts +138 -0
- package/src/__tests__/channel-approval-routes.test.ts +4 -4
- package/src/__tests__/channel-invite-transport.test.ts +2 -2
- package/src/__tests__/channel-readiness-routes.test.ts +16 -20
- package/src/__tests__/channel-readiness-service.test.ts +12 -7
- package/src/__tests__/channel-reply-delivery.test.ts +300 -2
- package/src/__tests__/checker.test.ts +576 -502
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/config-analysis.test.ts +83 -0
- package/src/__tests__/config-loader-backfill.test.ts +174 -0
- package/src/__tests__/config-loader-corrupt.test.ts +183 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +1458 -198
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +45 -10
- package/src/__tests__/contact-store-user-file.test.ts +511 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +618 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +32 -16
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +62 -17
- package/src/__tests__/conversation-agent-loop.test.ts +510 -84
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +165 -9
- package/src/__tests__/conversation-error.test.ts +102 -1
- package/src/__tests__/conversation-history-web-search.test.ts +17 -4
- package/src/__tests__/conversation-init.benchmark.test.ts +42 -1
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +32 -16
- package/src/__tests__/conversation-process-callsite.test.ts +306 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +32 -16
- package/src/__tests__/conversation-queue.test.ts +932 -76
- package/src/__tests__/conversation-routes-disk-view.test.ts +299 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2790 -55
- package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
- package/src/__tests__/conversation-skill-tools.test.ts +12 -143
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +120 -34
- package/src/__tests__/conversation-slash-unknown.test.ts +32 -16
- package/src/__tests__/conversation-speed-override.test.ts +30 -11
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -2
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-unread-route.test.ts +2 -2
- package/src/__tests__/conversation-usage.test.ts +3 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
- package/src/__tests__/conversation-workspace-injection.test.ts +45 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +46 -16
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +8 -3
- package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
- package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
- package/src/__tests__/credential-vault-unit.test.ts +495 -3
- package/src/__tests__/credentials-cli.test.ts +32 -16
- package/src/__tests__/cross-provider-web-search.test.ts +230 -35
- package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
- package/src/__tests__/delete-propagation.test.ts +437 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/dm-backfill.test.ts +417 -0
- package/src/__tests__/dm-persistence.test.ts +227 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
- package/src/__tests__/edit-propagation.test.ts +280 -0
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/ephemeral-permissions.test.ts +93 -3
- package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
- package/src/__tests__/estimator-calibration.test.ts +213 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +101 -15
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +64 -3
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/guardian-grant-minting.test.ts +8 -0
- package/src/__tests__/headless-browser-interactions.test.ts +44 -1
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +142 -5
- package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
- package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
- package/src/__tests__/heartbeat-service.test.ts +166 -32
- package/src/__tests__/home-state-routes.test.ts +162 -0
- package/src/__tests__/host-bash-proxy.test.ts +0 -5
- package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
- package/src/__tests__/host-cu-proxy.test.ts +0 -5
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/intent-routing.test.ts +1 -40
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/llm-catalog-parity.test.ts +174 -0
- package/src/__tests__/llm-context-normalization.test.ts +609 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-resolver.test.ts +214 -0
- package/src/__tests__/llm-schema.test.ts +223 -0
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/managed-proxy-context.test.ts +6 -2
- package/src/__tests__/media-stream-output.test.ts +555 -0
- package/src/__tests__/media-stream-parser.test.ts +374 -0
- package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
- package/src/__tests__/media-stream-stt-session.test.ts +588 -0
- package/src/__tests__/media-turn-detector.test.ts +440 -0
- package/src/__tests__/message-queue.test.ts +125 -0
- package/src/__tests__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-export-http.test.ts +6 -6
- package/src/__tests__/migration-import-commit-http.test.ts +8 -6
- package/src/__tests__/migration-import-from-url.test.ts +684 -0
- package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +151 -0
- package/src/__tests__/model-intents.test.ts +10 -84
- package/src/__tests__/notification-decision-fallback.test.ts +0 -10
- package/src/__tests__/notification-decision-identity.test.ts +0 -9
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
- package/src/__tests__/oauth-apps-routes.test.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +2 -0
- package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
- package/src/__tests__/oauth-providers-routes.test.ts +2 -0
- package/src/__tests__/oauth-store.test.ts +95 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +257 -9
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/onboarding-template-contract.test.ts +6 -13
- package/src/__tests__/openai-provider.test.ts +183 -0
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1501 -0
- package/src/__tests__/openrouter-provider-only.test.ts +135 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -1
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +224 -3
- package/src/__tests__/profiler-routes.test.ts +1 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
- package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
- package/src/__tests__/provider-error-scenarios.test.ts +135 -6
- package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
- package/src/__tests__/provider-registry-ollama.test.ts +1 -2
- package/src/__tests__/proxy-approval-callback.test.ts +0 -1
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/reaction-persistence.test.ts +560 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
- package/src/__tests__/relationship-state-contract.test.ts +175 -0
- package/src/__tests__/relay-server.test.ts +424 -6
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
- package/src/__tests__/risk-classifier-parity.test.ts +230 -0
- package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-ingress-http.test.ts +28 -0
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
- package/src/__tests__/secret-scanner-executor.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +34 -2
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +80 -0
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/shell-parser-property.test.ts +13 -13
- package/src/__tests__/skill-cache-store.test.ts +182 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
- package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
- package/src/__tests__/skills.test.ts +19 -30
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +564 -1
- package/src/__tests__/slack-skill.test.ts +3 -8
- package/src/__tests__/starter-bundle.test.ts +35 -0
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
- package/src/__tests__/suggestion-routes.test.ts +160 -3
- package/src/__tests__/system-prompt.test.ts +126 -53
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +26 -7
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -49
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +10 -6
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +88 -113
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/trust-store.test.ts +442 -103
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +345 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
- package/src/__tests__/twilio-routes.test.ts +376 -0
- package/src/__tests__/unicode.test.ts +293 -0
- package/src/__tests__/update-bulletin-job.test.ts +389 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/verification-control-plane-policy.test.ts +5 -22
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/voice-session-bridge.test.ts +39 -0
- package/src/__tests__/volume-security-guard.test.ts +3 -2
- package/src/__tests__/web-search-history.test.ts +337 -0
- package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
- package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
- package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
- package/src/__tests__/workspace-migration-meets.test.ts +244 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +1 -11
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +251 -19
- package/src/avatar/resvg-lazy.test.ts +136 -0
- package/src/avatar/resvg-lazy.ts +82 -9
- package/src/avatar/traits-png-sync.ts +21 -1
- package/src/backup/__tests__/backup-key.test.ts +152 -0
- package/src/backup/__tests__/backup-worker.test.ts +767 -0
- package/src/backup/__tests__/list-snapshots.test.ts +87 -0
- package/src/backup/__tests__/local-writer.test.ts +218 -0
- package/src/backup/__tests__/offsite-writer.test.ts +641 -0
- package/src/backup/__tests__/paths.test.ts +300 -0
- package/src/backup/__tests__/restore.test.ts +498 -0
- package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
- package/src/backup/__tests__/stream-crypt.test.ts +228 -0
- package/src/backup/backup-key.ts +137 -0
- package/src/backup/backup-worker.ts +459 -0
- package/src/backup/list-snapshots.ts +147 -0
- package/src/backup/local-writer.ts +133 -0
- package/src/backup/offsite-writer.ts +222 -0
- package/src/backup/paths.ts +226 -0
- package/src/backup/restore.ts +322 -0
- package/src/backup/snapshot-lock.ts +431 -0
- package/src/backup/stream-crypt.ts +263 -0
- package/src/browser/__tests__/operations.test.ts +163 -0
- package/src/browser/identifiers.ts +51 -0
- package/src/browser/operations.ts +660 -0
- package/src/browser/types.ts +81 -0
- package/src/bundler/package-resolver.ts +4 -0
- package/src/calls/audio-store.ts +11 -5
- package/src/calls/call-controller.ts +226 -71
- package/src/calls/call-domain.ts +9 -0
- package/src/calls/call-speech-output.ts +190 -0
- package/src/calls/call-transport.ts +77 -0
- package/src/calls/guardian-question-copy.ts +2 -2
- package/src/calls/media-stream-audio-transcode.ts +173 -0
- package/src/calls/media-stream-output.ts +660 -0
- package/src/calls/media-stream-parser.ts +300 -0
- package/src/calls/media-stream-protocol.ts +166 -0
- package/src/calls/media-stream-server.ts +592 -0
- package/src/calls/media-stream-stt-session.ts +460 -0
- package/src/calls/media-turn-detector.ts +230 -0
- package/src/calls/relay-server.ts +90 -75
- package/src/calls/resolve-call-tts-provider.ts +136 -0
- package/src/calls/telephony-stt-routing.ts +145 -0
- package/src/calls/tts-call-strategy.ts +161 -0
- package/src/calls/tts-text-sanitizer.ts +32 -16
- package/src/calls/twilio-routes.ts +281 -17
- package/src/calls/voice-quality.ts +78 -35
- package/src/calls/voice-session-bridge.ts +9 -1
- package/src/channels/types.ts +16 -0
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/browser.test.ts +554 -0
- package/src/cli/commands/__tests__/cache.test.ts +623 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
- package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
- package/src/cli/commands/__tests__/email-download.test.ts +16 -1
- package/src/cli/commands/__tests__/email-list.test.ts +28 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +130 -5
- package/src/cli/commands/__tests__/email-status.test.ts +5 -1
- package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
- package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
- package/src/cli/commands/__tests__/task.test.ts +913 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
- package/src/cli/commands/__tests__/ui.test.ts +1215 -0
- package/src/cli/commands/__tests__/watchers.test.ts +716 -0
- package/src/cli/commands/attachment.ts +182 -0
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +90 -0
- package/src/cli/commands/credentials.ts +0 -1
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +308 -16
- package/src/cli/commands/image-generation.ts +300 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +15 -0
- package/src/cli/commands/oauth/shared.ts +2 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -10
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -2
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -1
- package/src/cli/commands/stt.ts +339 -0
- package/src/cli/commands/task.ts +795 -0
- package/src/cli/commands/trust.ts +50 -19
- package/src/cli/commands/tts.ts +273 -0
- package/src/cli/commands/ui.ts +670 -0
- package/src/cli/commands/watchers.ts +509 -0
- package/src/cli/lib/daemon-credential-client.ts +0 -19
- package/src/cli/program.ts +53 -8
- package/src/cli.ts +0 -37
- package/src/config/__tests__/backup-schema.test.ts +134 -0
- package/src/config/assistant-feature-flags.ts +61 -62
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +37 -1
- package/src/config/bundled-skills/contacts/SKILL.md +2 -2
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
- package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
- package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
- package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -2
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +28 -18
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
- package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
- package/src/config/bundled-tool-registry.ts +0 -167
- package/src/config/env-registry.ts +24 -0
- package/src/config/env.ts +39 -10
- package/src/config/feature-flag-registry.json +63 -15
- package/src/config/llm-resolver.ts +128 -0
- package/src/config/loader.ts +220 -22
- package/src/config/raw-config-utils.ts +30 -2
- package/src/config/sanitize-for-transfer.ts +35 -0
- package/src/config/schema.ts +65 -51
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +32 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -30
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +49 -14
- package/src/config/schemas/heartbeat.ts +27 -10
- package/src/config/schemas/host-browser.ts +47 -1
- package/src/config/schemas/inference.ts +3 -23
- package/src/config/schemas/llm.ts +318 -0
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/memory-processing.ts +1 -9
- package/src/config/schemas/notifications.ts +4 -11
- package/src/config/schemas/platform.ts +3 -9
- package/src/config/schemas/security.ts +33 -0
- package/src/config/schemas/services.ts +53 -4
- package/src/config/schemas/stt.ts +60 -0
- package/src/config/schemas/tts.ts +283 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skills.ts +6 -2
- package/src/config/types.ts +4 -0
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/__tests__/compact-prompt.test.ts +45 -0
- package/src/context/__tests__/microcompact.test.ts +805 -0
- package/src/context/estimator-calibration.ts +136 -0
- package/src/context/microcompact.ts +443 -0
- package/src/context/post-turn-tool-result-truncation.ts +3 -2
- package/src/context/prompts/compact.md +12 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +272 -35
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/executable-discovery.ts +23 -2
- package/src/credential-execution/process-manager.test.ts +109 -0
- package/src/credential-execution/process-manager.ts +96 -2
- package/src/credential-health/credential-health-service.ts +366 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +17 -8
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/approval-generators.ts +29 -4
- package/src/daemon/assistant-attachments.ts +24 -13
- package/src/daemon/classifier.ts +2 -2
- package/src/daemon/config-watcher.ts +99 -6
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +85 -12
- package/src/daemon/conversation-agent-loop.ts +563 -104
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +46 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +85 -11
- package/src/daemon/conversation-messaging.ts +110 -7
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +591 -23
- package/src/daemon/conversation-queue-manager.ts +27 -0
- package/src/daemon/conversation-runtime-assembly.ts +769 -28
- package/src/daemon/conversation-slash.ts +38 -2
- package/src/daemon/conversation-surfaces.ts +483 -5
- package/src/daemon/conversation-tool-setup.ts +35 -5
- package/src/daemon/conversation-usage.ts +8 -5
- package/src/daemon/conversation.ts +193 -47
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/guardian-action-generators.ts +34 -14
- package/src/daemon/handlers/config-model.test.ts +86 -0
- package/src/daemon/handlers/config-model.ts +54 -12
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +13 -3
- package/src/daemon/handlers/shared.ts +51 -1
- package/src/daemon/handlers/skills.ts +323 -79
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/host-browser-proxy.ts +2 -1
- package/src/daemon/lifecycle.ts +185 -26
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/conversations.ts +48 -1
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +23 -1
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +16 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/trust.ts +0 -2
- package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
- package/src/daemon/pkb-context-tracker.test.ts +169 -0
- package/src/daemon/pkb-context-tracker.ts +125 -0
- package/src/daemon/pkb-reminder-builder.test.ts +70 -0
- package/src/daemon/pkb-reminder-builder.ts +31 -0
- package/src/daemon/providers-setup.ts +6 -0
- package/src/daemon/server.ts +463 -10
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +9 -9
- package/src/daemon/watch-handler.ts +4 -4
- package/src/daemon/web-search-history.ts +126 -0
- package/src/email/html-renderer.ts +76 -0
- package/src/events/domain-events.ts +0 -1
- package/src/filing/filing-service.ts +9 -10
- package/src/heartbeat/heartbeat-service.ts +156 -22
- package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
- package/src/home/__tests__/emit-feed-event.test.ts +169 -0
- package/src/home/__tests__/feed-scheduler.test.ts +222 -0
- package/src/home/__tests__/feed-types.test.ts +275 -0
- package/src/home/__tests__/feed-writer.test.ts +688 -0
- package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
- package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
- package/src/home/__tests__/progress-formula.test.ts +213 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
- package/src/home/__tests__/rollup-producer.test.ts +442 -0
- package/src/home/assistant-feed-authoring.ts +128 -0
- package/src/home/emit-feed-event.ts +162 -0
- package/src/home/feed-scheduler.ts +263 -0
- package/src/home/feed-types.ts +235 -0
- package/src/home/feed-writer.ts +469 -0
- package/src/home/platform-gmail-digest.ts +163 -0
- package/src/home/progress-formula.ts +86 -0
- package/src/home/relationship-state-writer.ts +824 -0
- package/src/home/relationship-state.ts +143 -0
- package/src/home/rollup-producer.ts +413 -0
- package/src/home/suggested-prompts.ts +101 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +12 -3
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
- package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/__tests__/socket-path.test.ts +73 -0
- package/src/ipc/__tests__/task-ipc.test.ts +577 -0
- package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
- package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
- package/src/ipc/cli-client.ts +152 -0
- package/src/ipc/cli-server.ts +252 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +61 -0
- package/src/ipc/routes/browser.ts +96 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/index.ts +21 -0
- package/src/ipc/routes/task-queue.ts +226 -0
- package/src/ipc/routes/task.ts +173 -0
- package/src/ipc/routes/ui-request.ts +50 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +100 -0
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
- package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +233 -0
- package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/admin.ts +18 -0
- package/src/memory/app-store.ts +1 -1
- package/src/memory/attachments-store.ts +70 -0
- package/src/memory/auto-analysis-enqueue.ts +127 -0
- package/src/memory/auto-analysis-guard.ts +27 -0
- package/src/memory/cleanup-schedule-state.ts +37 -0
- package/src/memory/conversation-analyze-job.ts +74 -0
- package/src/memory/conversation-attention-store.ts +13 -6
- package/src/memory/conversation-crud.ts +199 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +65 -1
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/conversation-title-service.ts +7 -4
- package/src/memory/db-init.ts +8 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/graph/compaction.ts +299 -0
- package/src/memory/graph/consolidation.ts +4 -4
- package/src/memory/graph/conversation-graph-memory.ts +104 -29
- package/src/memory/graph/extraction.test.ts +295 -2
- package/src/memory/graph/extraction.ts +181 -51
- package/src/memory/graph/graph-search.test.ts +92 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.test.ts +459 -0
- package/src/memory/graph/retriever.ts +257 -66
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/store.ts +41 -0
- package/src/memory/graph/tool-handlers.ts +27 -0
- package/src/memory/graph/tools.ts +6 -1
- package/src/memory/group-crud.ts +6 -1
- package/src/memory/indexer.ts +95 -16
- package/src/memory/job-handlers/cleanup.ts +11 -8
- package/src/memory/job-handlers/conversation-starters.ts +39 -30
- package/src/memory/job-handlers/summarization.ts +2 -2
- package/src/memory/job-utils.ts +7 -1
- package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
- package/src/memory/jobs/embed-pkb-file.ts +54 -0
- package/src/memory/jobs-store.ts +106 -5
- package/src/memory/jobs-worker.ts +26 -9
- package/src/memory/llm-usage-store.ts +92 -56
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
- package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-index.test.ts +368 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +438 -0
- package/src/memory/pkb/pkb-search.ts +137 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.ts +122 -1
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/oauth.ts +3 -0
- package/src/memory/slack-thread-store.ts +37 -0
- package/src/memory/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/adapter.ts +6 -16
- package/src/messaging/providers/gmail/client.ts +79 -6
- package/src/messaging/providers/gmail/types.ts +7 -0
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +155 -38
- package/src/messaging/providers/slack/backfill.test.ts +257 -0
- package/src/messaging/providers/slack/backfill.ts +101 -0
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
- package/src/messaging/providers/slack/message-metadata.ts +123 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
- package/src/messaging/providers/slack/render-transcript.ts +443 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/decision-engine.ts +6 -12
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +1 -0
- package/src/oauth/byo-connection.test.ts +18 -1
- package/src/oauth/byo-connection.ts +3 -1
- package/src/oauth/connect-orchestrator.ts +2 -0
- package/src/oauth/connection-resolver.ts +6 -2
- package/src/oauth/connection.ts +2 -0
- package/src/oauth/oauth-store.ts +10 -0
- package/src/oauth/platform-connection.test.ts +145 -0
- package/src/oauth/platform-connection.ts +62 -31
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/approval-policy.test.ts +948 -0
- package/src/permissions/approval-policy.ts +257 -0
- package/src/permissions/bash-risk-classifier.test.ts +1208 -0
- package/src/permissions/bash-risk-classifier.ts +707 -0
- package/src/permissions/checker.ts +218 -699
- package/src/permissions/command-registry.test.ts +535 -0
- package/src/permissions/command-registry.ts +825 -0
- package/src/permissions/defaults.ts +71 -75
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/risk-types.ts +205 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/skill-risk-classifier.test.ts +311 -0
- package/src/permissions/skill-risk-classifier.ts +214 -0
- package/src/permissions/trust-client.ts +52 -25
- package/src/permissions/trust-store-interface.ts +1 -6
- package/src/permissions/trust-store.ts +164 -65
- package/src/permissions/types.ts +23 -14
- package/src/permissions/web-risk-classifier.test.ts +170 -0
- package/src/permissions/web-risk-classifier.ts +89 -0
- package/src/permissions/workspace-policy.ts +1 -13
- package/src/platform/client.test.ts +10 -0
- package/src/platform/client.ts +19 -1
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +127 -3
- package/src/prompts/system-prompt.ts +78 -38
- package/src/prompts/templates/BOOTSTRAP.md +5 -5
- package/src/prompts/templates/SOUL.md +5 -3
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-job.ts +190 -0
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/__tests__/retry-callsite.test.ts +424 -0
- package/src/providers/anthropic/client.ts +335 -70
- package/src/providers/call-site-routing.ts +71 -0
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +74 -3
- package/src/providers/managed-proxy/constants.ts +2 -1
- package/src/providers/model-catalog.ts +502 -28
- package/src/providers/model-intents.ts +8 -8
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +530 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +579 -0
- package/src/providers/openrouter/client.ts +168 -4
- package/src/providers/provider-env-vars.ts +56 -0
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/provider-send-message.ts +22 -5
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/registry.ts +21 -10
- package/src/providers/retry.ts +185 -39
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +883 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
- package/src/providers/speech-to-text/deepgram.test.ts +332 -0
- package/src/providers/speech-to-text/deepgram.ts +115 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
- package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
- package/src/providers/speech-to-text/google-gemini.ts +101 -0
- package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
- package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
- package/src/providers/speech-to-text/openai-whisper.ts +63 -33
- package/src/providers/speech-to-text/provider-catalog.ts +323 -0
- package/src/providers/speech-to-text/resolve.ts +393 -6
- package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
- package/src/providers/speech-to-text/xai-realtime.ts +796 -0
- package/src/providers/speech-to-text/xai.test.ts +155 -0
- package/src/providers/speech-to-text/xai.ts +97 -0
- package/src/providers/types.ts +102 -3
- package/src/runtime/AGENTS.md +45 -3
- package/src/runtime/__tests__/agent-wake.test.ts +872 -0
- package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
- package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
- package/src/runtime/agent-wake.ts +553 -0
- package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
- package/src/runtime/auth/route-policy.ts +34 -5
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +15 -3
- package/src/runtime/capability-tokens.ts +10 -10
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-invite-transports/email.ts +14 -6
- package/src/runtime/channel-readiness-service.ts +12 -22
- package/src/runtime/channel-reply-delivery.ts +106 -2
- package/src/runtime/chrome-extension-registry.ts +38 -2
- package/src/runtime/decision-token.ts +116 -0
- package/src/runtime/gateway-client.ts +2 -2
- package/src/runtime/http-router.ts +32 -0
- package/src/runtime/http-server.ts +447 -11
- package/src/runtime/http-types.ts +29 -3
- package/src/runtime/interactive-ui.ts +362 -0
- package/src/runtime/invite-instruction-generator.ts +2 -2
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
- package/src/runtime/migrations/gcs-signed-url.ts +162 -0
- package/src/runtime/migrations/migration-transport.ts +1 -0
- package/src/runtime/migrations/migration-wizard.ts +1 -0
- package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
- package/src/runtime/migrations/vbundle-importer.ts +187 -8
- package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
- package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
- package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
- package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
- package/src/runtime/migrations/vbundle-validator.ts +15 -6
- package/src/runtime/pending-interactions.ts +0 -11
- package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +618 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +247 -0
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
- package/src/runtime/routes/app-management-routes.ts +12 -18
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
- package/src/runtime/routes/approval-routes.ts +12 -17
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/avatar-routes.ts +20 -4
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
- package/src/runtime/routes/btw-routes.ts +9 -10
- package/src/runtime/routes/contact-routes.test.ts +298 -0
- package/src/runtime/routes/contact-routes.ts +132 -5
- package/src/runtime/routes/conversation-analysis-routes.ts +22 -142
- package/src/runtime/routes/conversation-management-routes.ts +133 -0
- package/src/runtime/routes/conversation-routes.ts +487 -160
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +6 -4
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/guardian-approval-interception.ts +33 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
- package/src/runtime/routes/home-feed-routes.ts +452 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +3 -14
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +3 -17
- package/src/runtime/routes/inbound-message-handler.ts +912 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
- package/src/runtime/routes/integrations/slack/channel.ts +36 -6
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +325 -0
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/migration-routes.ts +722 -91
- package/src/runtime/routes/settings-routes.ts +26 -7
- package/src/runtime/routes/skills-routes.ts +76 -7
- package/src/runtime/routes/stt-routes.ts +233 -0
- package/src/runtime/routes/surface-action-routes.ts +41 -2
- package/src/runtime/routes/trust-rules-routes.ts +30 -14
- package/src/runtime/routes/tts-routes.ts +108 -24
- package/src/runtime/routes/usage-routes.ts +30 -2
- package/src/runtime/routes/user-route-dispatcher.ts +50 -5
- package/src/runtime/routes/user-routes.ts +13 -1
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/routes/work-items-routes.ts +11 -3
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +426 -0
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
- package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
- package/src/runtime/services/analyze-conversation.ts +340 -0
- package/src/runtime/services/analyze-deps-singleton.ts +32 -0
- package/src/runtime/services/auto-analysis-prompt.ts +55 -0
- package/src/runtime/skill-route-registry.ts +71 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +58 -0
- package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
- package/src/security/__tests__/untrusted-content.test.ts +109 -0
- package/src/security/oauth2.ts +122 -37
- package/src/security/secure-keys.ts +32 -10
- package/src/security/token-manager.ts +35 -13
- package/src/security/untrusted-content.ts +102 -0
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-cache.ts +26 -7
- package/src/skills/catalog-files.ts +64 -2
- package/src/skills/catalog-install.ts +31 -3
- package/src/skills/category-inference.ts +122 -0
- package/src/skills/clawhub-files.ts +213 -0
- package/src/skills/clawhub.ts +84 -23
- package/src/skills/skill-cache-store.ts +97 -0
- package/src/skills/skill-file-provider.ts +40 -0
- package/src/skills/skillssh-files.ts +395 -0
- package/src/skills/skillssh-registry.ts +4 -4
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +468 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +228 -0
- package/src/stt/stt-stream-session.ts +506 -0
- package/src/stt/types.ts +334 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +79 -27
- package/src/tasks/ephemeral-permissions.ts +9 -4
- package/src/telemetry/usage-telemetry-reporter.ts +27 -5
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +166 -0
- package/src/tools/browser/browser-execution.ts +1208 -41
- package/src/tools/browser/browser-manager.ts +45 -0
- package/src/tools/browser/browser-mode-constants.ts +12 -0
- package/src/tools/browser/browser-mode.ts +92 -0
- package/src/tools/browser/browser-status-constants.ts +33 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +393 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +205 -17
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
- package/src/tools/browser/cdp-client/errors.ts +15 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
- package/src/tools/browser/cdp-client/factory.ts +797 -87
- package/src/tools/browser/cdp-client/index.ts +16 -2
- package/src/tools/browser/cdp-client/types.ts +68 -0
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +41 -7
- package/src/tools/executor.ts +4 -0
- package/src/tools/filesystem/write.ts +52 -0
- package/src/tools/host-terminal/host-shell.ts +45 -5
- package/src/tools/memory/register.test.ts +185 -0
- package/src/tools/memory/register.ts +3 -1
- package/src/tools/network/web-fetch.ts +25 -12
- package/src/tools/network/web-search.ts +20 -2
- package/src/tools/permission-checker.ts +36 -15
- package/src/tools/policy-context.ts +25 -8
- package/src/tools/registry.ts +55 -3
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +0 -9
- package/src/tools/skills/execute.ts +2 -2
- package/src/tools/skills/sandbox-runner.ts +6 -2
- package/src/tools/terminal/backends/native.ts +51 -2
- package/src/tools/terminal/safe-env.ts +11 -2
- package/src/tools/terminal/shell.ts +16 -4
- package/src/tools/tool-manifest.ts +6 -0
- package/src/tools/types.ts +29 -3
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tools/verification-control-plane-policy.ts +1 -1
- package/src/tts/__tests__/provider-adapters.test.ts +1061 -0
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
- package/src/tts/__tests__/provider-catalog.test.ts +183 -0
- package/src/tts/__tests__/provider-registry.test.ts +90 -0
- package/src/tts/provider-catalog.ts +219 -0
- package/src/tts/provider-registry.ts +73 -0
- package/src/tts/providers/deepgram-provider.ts +219 -0
- package/src/tts/providers/elevenlabs-provider.ts +211 -0
- package/src/tts/providers/fish-audio-provider.ts +183 -0
- package/src/tts/providers/index.ts +44 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/providers/xai-provider.ts +224 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +199 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/types/tar-stream.d.ts +66 -0
- package/src/util/abort-reasons.ts +58 -0
- package/src/util/device-id.ts +32 -16
- package/src/util/errors.ts +9 -1
- package/src/util/json.ts +17 -0
- package/src/util/platform.ts +56 -12
- package/src/util/pricing.ts +78 -5
- package/src/util/spawn.ts +1 -1
- package/src/util/truncate.ts +4 -2
- package/src/util/unicode.ts +201 -0
- package/src/version.ts +19 -24
- package/src/watcher/engine.ts +24 -1
- package/src/watcher/providers/google-calendar.ts +134 -8
- package/src/watcher/providers/outlook-calendar.ts +42 -2
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/git-service.ts +23 -4
- package/src/workspace/migrations/003-seed-device-id.ts +9 -3
- package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
- package/src/workspace/migrations/029-seed-pkb.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +317 -0
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
- package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
- package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
- package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
- package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
- package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +32 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/src/workspace/top-level-renderer.ts +13 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/__tests__/outlook-attachments.test.ts +0 -301
- package/src/__tests__/outlook-automation-tools.test.ts +0 -425
- package/src/__tests__/outlook-categories.test.ts +0 -212
- package/src/__tests__/outlook-compose-tools.test.ts +0 -325
- package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
- package/src/__tests__/outlook-follow-up.test.ts +0 -196
- package/src/__tests__/outlook-trash.test.ts +0 -77
- package/src/__tests__/outlook-unsubscribe.test.ts +0 -250
- package/src/__tests__/update-bulletin-format.test.ts +0 -122
- package/src/__tests__/update-bulletin-state.test.ts +0 -135
- package/src/__tests__/update-bulletin.test.ts +0 -277
- package/src/__tests__/update-template-contract.test.ts +0 -29
- package/src/cli/commands/browser-relay.ts +0 -466
- package/src/cli/commands/doctor.ts +0 -341
- package/src/config/bundled-skills/browser/SKILL.md +0 -63
- package/src/config/bundled-skills/browser/TOOLS.json +0 -393
- package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -32
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
- package/src/config/bundled-skills/gmail/SKILL.md +0 -175
- package/src/config/bundled-skills/gmail/TOOLS.json +0 -558
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -149
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -220
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -251
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
- package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
- package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
- package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/google-calendar/types.ts +0 -97
- package/src/config/bundled-skills/outlook/SKILL.md +0 -196
- package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
- package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
- package/src/config/bundled-skills/slack/SKILL.md +0 -107
- package/src/config/bundled-skills/tasks/SKILL.md +0 -37
- package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
- package/src/config/bundled-skills/tasks/icon.svg +0 -34
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
- package/src/config/bundled-skills/watcher/SKILL.md +0 -31
- package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
- package/src/email/guardrails.ts +0 -221
- package/src/email/provider.ts +0 -117
- package/src/email/providers/agentmail.ts +0 -361
- package/src/email/providers/index.ts +0 -65
- package/src/email/service.ts +0 -384
- package/src/email/types.ts +0 -126
- package/src/prompts/templates/UPDATES.md +0 -38
- package/src/prompts/templates/USER.md +0 -13
- package/src/prompts/update-bulletin-format.ts +0 -68
- package/src/prompts/update-bulletin-state.ts +0 -58
- package/src/prompts/update-bulletin-template-path.ts +0 -13
- package/src/prompts/update-bulletin.ts +0 -128
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/runtime/routes/browser-cdp-routes.ts +0 -229
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/tools/watcher/create.ts +0 -86
- package/src/tools/watcher/delete.ts +0 -36
- package/src/tools/watcher/digest.ts +0 -54
- package/src/tools/watcher/list.ts +0 -83
- package/src/tools/watcher/update.ts +0 -71
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Route handlers for conversation messages and suggestions.
|
|
3
3
|
*/
|
|
4
|
-
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
4
|
+
import { existsSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join, relative } from "node:path";
|
|
6
6
|
|
|
7
7
|
import { z } from "zod";
|
|
@@ -12,8 +12,10 @@ import {
|
|
|
12
12
|
createUserMessage,
|
|
13
13
|
} from "../../agent/message-types.js";
|
|
14
14
|
import {
|
|
15
|
+
canServiceRegistryBrowser,
|
|
15
16
|
CHANNEL_IDS,
|
|
16
17
|
INTERFACE_IDS,
|
|
18
|
+
type InterfaceId,
|
|
17
19
|
isInteractiveInterface,
|
|
18
20
|
parseChannelId,
|
|
19
21
|
parseInterfaceId,
|
|
@@ -21,6 +23,7 @@ import {
|
|
|
21
23
|
} from "../../channels/types.js";
|
|
22
24
|
import { isHttpAuthDisabled } from "../../config/env.js";
|
|
23
25
|
import { getConfig } from "../../config/loader.js";
|
|
26
|
+
import type { Conversation } from "../../daemon/conversation.js";
|
|
24
27
|
import {
|
|
25
28
|
buildModelInfoEvent,
|
|
26
29
|
formatCompactResult,
|
|
@@ -45,6 +48,10 @@ import type {
|
|
|
45
48
|
NonHostProxyTransportMetadata,
|
|
46
49
|
} from "../../daemon/message-types/conversations.js";
|
|
47
50
|
import type { HeartbeatService } from "../../heartbeat/heartbeat-service.js";
|
|
51
|
+
import {
|
|
52
|
+
writeOnboardingSidecar,
|
|
53
|
+
writeRelationshipState,
|
|
54
|
+
} from "../../home/relationship-state-writer.js";
|
|
48
55
|
import * as attachmentsStore from "../../memory/attachments-store.js";
|
|
49
56
|
import {
|
|
50
57
|
createCanonicalGuardianRequest,
|
|
@@ -58,6 +65,7 @@ import {
|
|
|
58
65
|
getLastAssistantTimestampBefore,
|
|
59
66
|
getMessages,
|
|
60
67
|
getMessagesPaginated,
|
|
68
|
+
hasMessages,
|
|
61
69
|
type MessageRow,
|
|
62
70
|
provenanceFromTrustContext,
|
|
63
71
|
setConversationOriginChannelIfUnset,
|
|
@@ -74,6 +82,7 @@ import { checkIngressForSecrets } from "../../security/secret-ingress.js";
|
|
|
74
82
|
import { redactSecrets } from "../../security/secret-scanner.js";
|
|
75
83
|
import { summarizeToolInput } from "../../tools/tool-input-summary.js";
|
|
76
84
|
import { getLogger } from "../../util/logger.js";
|
|
85
|
+
import { getWorkspacePromptPath } from "../../util/platform.js";
|
|
77
86
|
import { silentlyWithLog } from "../../util/silently.js";
|
|
78
87
|
import { buildAssistantEvent } from "../assistant-event.js";
|
|
79
88
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
@@ -107,7 +116,7 @@ const SUGGESTION_CACHE_MAX = 100;
|
|
|
107
116
|
function collectCanonicalGuardianRequestHintIds(
|
|
108
117
|
conversationId: string,
|
|
109
118
|
sourceChannel: string,
|
|
110
|
-
conversation:
|
|
119
|
+
conversation: Conversation,
|
|
111
120
|
): string[] {
|
|
112
121
|
const requests = listPendingRequestsByConversationScope(
|
|
113
122
|
conversationId,
|
|
@@ -172,7 +181,7 @@ async function tryConsumeCanonicalGuardianReply(params: {
|
|
|
172
181
|
data: string;
|
|
173
182
|
filePath?: string;
|
|
174
183
|
}>;
|
|
175
|
-
conversation:
|
|
184
|
+
conversation: Conversation;
|
|
176
185
|
onEvent: (msg: ServerMessage) => void;
|
|
177
186
|
approvalConversationGenerator?: ApprovalConversationGenerator;
|
|
178
187
|
/** Verified actor identity from actor-token middleware. */
|
|
@@ -967,7 +976,7 @@ function mergeConsecutiveAssistantMessages(messages: MessageRow[]): {
|
|
|
967
976
|
function makeHubPublisher(
|
|
968
977
|
deps: SendMessageDeps,
|
|
969
978
|
conversationId: string,
|
|
970
|
-
conversation:
|
|
979
|
+
conversation: Conversation,
|
|
971
980
|
): (msg: ServerMessage) => void {
|
|
972
981
|
let hubChain: Promise<void> = Promise.resolve();
|
|
973
982
|
return (msg: ServerMessage) => {
|
|
@@ -1048,30 +1057,8 @@ function makeHubPublisher(
|
|
|
1048
1057
|
conversationId,
|
|
1049
1058
|
kind: "secret",
|
|
1050
1059
|
});
|
|
1051
|
-
} else
|
|
1052
|
-
|
|
1053
|
-
conversation,
|
|
1054
|
-
conversationId,
|
|
1055
|
-
kind: "host_bash",
|
|
1056
|
-
});
|
|
1057
|
-
} else if (msg.type === "host_browser_request") {
|
|
1058
|
-
pendingInteractions.register(msg.requestId, {
|
|
1059
|
-
conversation,
|
|
1060
|
-
conversationId,
|
|
1061
|
-
kind: "host_browser",
|
|
1062
|
-
});
|
|
1063
|
-
} else if (msg.type === "host_file_request") {
|
|
1064
|
-
pendingInteractions.register(msg.requestId, {
|
|
1065
|
-
conversation,
|
|
1066
|
-
conversationId,
|
|
1067
|
-
kind: "host_file",
|
|
1068
|
-
});
|
|
1069
|
-
} else if (msg.type === "host_cu_request") {
|
|
1070
|
-
pendingInteractions.register(msg.requestId, {
|
|
1071
|
-
conversation,
|
|
1072
|
-
conversationId,
|
|
1073
|
-
kind: "host_cu",
|
|
1074
|
-
});
|
|
1060
|
+
} else {
|
|
1061
|
+
registerHostProxyPendingInteraction(msg, conversation, conversationId);
|
|
1075
1062
|
}
|
|
1076
1063
|
|
|
1077
1064
|
// ServerMessage is a large union; conversationId exists on most but not all variants.
|
|
@@ -1080,7 +1067,20 @@ function makeHubPublisher(
|
|
|
1080
1067
|
typeof (msg as { conversationId?: unknown }).conversationId === "string"
|
|
1081
1068
|
? (msg as { conversationId: string }).conversationId
|
|
1082
1069
|
: undefined;
|
|
1083
|
-
|
|
1070
|
+
// `conversation_list_invalidated` is a list-level system event: it
|
|
1071
|
+
// describes no particular conversation and every connected client
|
|
1072
|
+
// should refresh its sidebar. Publish it unscoped so the SSE hub does
|
|
1073
|
+
// not filter it out by the subscriber's `filter.conversationId`.
|
|
1074
|
+
// Other events (including `conversation_title_updated`) stay scoped to
|
|
1075
|
+
// their conversation — unscoped scoped-events would leak foreign
|
|
1076
|
+
// `conversationId` values to native clients' speculative ID-resolution
|
|
1077
|
+
// path. For `conversation_title_updated` we instead enqueue a matching
|
|
1078
|
+
// unscoped `conversation_list_invalidated` below so other clients'
|
|
1079
|
+
// sidebars can refresh and pick up the new title.
|
|
1080
|
+
const resolvedConversationId =
|
|
1081
|
+
msg.type === "conversation_list_invalidated"
|
|
1082
|
+
? undefined
|
|
1083
|
+
: (msgConversationId ?? conversationId);
|
|
1084
1084
|
const event = buildAssistantEvent(
|
|
1085
1085
|
DAEMON_INTERNAL_ASSISTANT_ID,
|
|
1086
1086
|
msg,
|
|
@@ -1096,10 +1096,229 @@ function makeHubPublisher(
|
|
|
1096
1096
|
"assistant-events hub subscriber threw during POST /messages",
|
|
1097
1097
|
);
|
|
1098
1098
|
}
|
|
1099
|
+
|
|
1100
|
+
// When the agent loop auto-generates a conversation title, also
|
|
1101
|
+
// broadcast an unscoped `conversation_list_invalidated` so every
|
|
1102
|
+
// connected client's sidebar can refresh and pick up the new title.
|
|
1103
|
+
// Without this, clients viewing other conversations (or a draft)
|
|
1104
|
+
// would never learn that the title for this conversation changed.
|
|
1105
|
+
// The scoped `conversation_title_updated` above still handles the
|
|
1106
|
+
// in-place update for the client currently viewing this conversation.
|
|
1107
|
+
if (msg.type === "conversation_title_updated") {
|
|
1108
|
+
try {
|
|
1109
|
+
await deps.assistantEventHub.publish(
|
|
1110
|
+
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
1111
|
+
type: "conversation_list_invalidated",
|
|
1112
|
+
reason: "renamed",
|
|
1113
|
+
}),
|
|
1114
|
+
);
|
|
1115
|
+
} catch (err) {
|
|
1116
|
+
log.warn(
|
|
1117
|
+
{ err },
|
|
1118
|
+
"Failed to publish conversation_list_invalidated after title update",
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1099
1122
|
})();
|
|
1100
1123
|
};
|
|
1101
1124
|
}
|
|
1102
1125
|
|
|
1126
|
+
/**
|
|
1127
|
+
* Register pending interactions for host proxy request envelopes so
|
|
1128
|
+
* standalone result endpoints can resolve by requestId.
|
|
1129
|
+
*
|
|
1130
|
+
* Returns the registered requestId when a host proxy request was registered.
|
|
1131
|
+
* Callers that route through non-hub transports (e.g. registry-routed
|
|
1132
|
+
* host_browser sends) can use this to clean up the registration if send fails.
|
|
1133
|
+
*/
|
|
1134
|
+
function registerHostProxyPendingInteraction(
|
|
1135
|
+
msg: ServerMessage,
|
|
1136
|
+
conversation: Conversation,
|
|
1137
|
+
conversationId: string,
|
|
1138
|
+
): string | undefined {
|
|
1139
|
+
if (msg.type === "host_bash_request") {
|
|
1140
|
+
pendingInteractions.register(msg.requestId, {
|
|
1141
|
+
conversation,
|
|
1142
|
+
conversationId,
|
|
1143
|
+
kind: "host_bash",
|
|
1144
|
+
});
|
|
1145
|
+
return msg.requestId;
|
|
1146
|
+
}
|
|
1147
|
+
if (msg.type === "host_browser_request") {
|
|
1148
|
+
pendingInteractions.register(msg.requestId, {
|
|
1149
|
+
conversation,
|
|
1150
|
+
conversationId,
|
|
1151
|
+
kind: "host_browser",
|
|
1152
|
+
});
|
|
1153
|
+
return msg.requestId;
|
|
1154
|
+
}
|
|
1155
|
+
if (msg.type === "host_file_request") {
|
|
1156
|
+
pendingInteractions.register(msg.requestId, {
|
|
1157
|
+
conversation,
|
|
1158
|
+
conversationId,
|
|
1159
|
+
kind: "host_file",
|
|
1160
|
+
});
|
|
1161
|
+
return msg.requestId;
|
|
1162
|
+
}
|
|
1163
|
+
if (msg.type === "host_cu_request") {
|
|
1164
|
+
pendingInteractions.register(msg.requestId, {
|
|
1165
|
+
conversation,
|
|
1166
|
+
conversationId,
|
|
1167
|
+
kind: "host_cu",
|
|
1168
|
+
});
|
|
1169
|
+
return msg.requestId;
|
|
1170
|
+
}
|
|
1171
|
+
return undefined;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* Resolve the host_browser sender function for a conversation turn.
|
|
1176
|
+
*
|
|
1177
|
+
* When the guardian has an active extension connection in the
|
|
1178
|
+
* ChromeExtensionRegistry, returns a registry-routed sender that forwards
|
|
1179
|
+
* `host_browser_request` / `host_browser_cancel` frames through the
|
|
1180
|
+
* WebSocket to the connected extension. Otherwise returns the SSE hub
|
|
1181
|
+
* emitter (`onEvent`).
|
|
1182
|
+
*
|
|
1183
|
+
* For `chrome-extension` turns the registry sender is **always** returned
|
|
1184
|
+
* regardless of the POST-time connection check. The chrome-extension
|
|
1185
|
+
* interface has no SSE consumer for `host_browser_request` frames, so
|
|
1186
|
+
* falling back to `onEvent` would cause CDP calls to stall until the proxy
|
|
1187
|
+
* timeout (30 s) instead of failing immediately at send time when the
|
|
1188
|
+
* registry throws on a missing connection.
|
|
1189
|
+
*
|
|
1190
|
+
* This helper is interface-agnostic: both chrome-extension and macOS turns
|
|
1191
|
+
* can obtain a registry-routed sender when extension connectivity exists.
|
|
1192
|
+
* The `isRegistryRouted` flag lets the caller decide whether to set
|
|
1193
|
+
* `hostBrowserSenderOverride` and whether to provision a `HostBrowserProxy`
|
|
1194
|
+
* for interfaces that don't statically support host_browser (e.g. macOS).
|
|
1195
|
+
*/
|
|
1196
|
+
function resolveHostBrowserSender(
|
|
1197
|
+
conversation: Conversation,
|
|
1198
|
+
conversationId: string,
|
|
1199
|
+
authContext: AuthContext,
|
|
1200
|
+
onEvent: (msg: ServerMessage) => void,
|
|
1201
|
+
sourceInterface: InterfaceId,
|
|
1202
|
+
): { sender: (msg: ServerMessage) => void; isRegistryRouted: boolean } {
|
|
1203
|
+
// Check whether the guardian has any active extension connection.
|
|
1204
|
+
const guardianId =
|
|
1205
|
+
conversation.trustContext?.guardianPrincipalId ??
|
|
1206
|
+
authContext.actorPrincipalId;
|
|
1207
|
+
const hasExtensionConnection =
|
|
1208
|
+
!!guardianId && !!getChromeExtensionRegistry().get(guardianId);
|
|
1209
|
+
|
|
1210
|
+
// For chrome-extension, always use the registry sender so that send-time
|
|
1211
|
+
// failures produce immediate errors rather than 30-second proxy timeouts.
|
|
1212
|
+
// The SSE hub has no extension consumer, so falling back to onEvent is
|
|
1213
|
+
// never correct for this interface.
|
|
1214
|
+
if (!hasExtensionConnection && sourceInterface !== "chrome-extension") {
|
|
1215
|
+
return { sender: onEvent, isRegistryRouted: false };
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// Build a registry-routed sender. The guardian principal ID is resolved
|
|
1219
|
+
// at send time rather than captured here so that queue-drain restores
|
|
1220
|
+
// (which re-fire this closure outside the original POST context) follow
|
|
1221
|
+
// the conversation's bound guardian identity rather than a stale
|
|
1222
|
+
// authContext.actorPrincipalId.
|
|
1223
|
+
const registrySender = (msg: ServerMessage): void => {
|
|
1224
|
+
const requestId = registerHostProxyPendingInteraction(
|
|
1225
|
+
msg,
|
|
1226
|
+
conversation,
|
|
1227
|
+
conversationId,
|
|
1228
|
+
);
|
|
1229
|
+
const gid =
|
|
1230
|
+
conversation.trustContext?.guardianPrincipalId ??
|
|
1231
|
+
authContext.actorPrincipalId;
|
|
1232
|
+
if (!gid) {
|
|
1233
|
+
if (requestId) pendingInteractions.resolve(requestId);
|
|
1234
|
+
throw new Error(
|
|
1235
|
+
"host_browser send skipped: no guardianId on AuthContext",
|
|
1236
|
+
);
|
|
1237
|
+
}
|
|
1238
|
+
const ok = getChromeExtensionRegistry().send(gid, msg);
|
|
1239
|
+
if (!ok) {
|
|
1240
|
+
if (requestId) pendingInteractions.resolve(requestId);
|
|
1241
|
+
throw new Error(
|
|
1242
|
+
`host_browser send failed: no active connection for guardian ${gid}`,
|
|
1243
|
+
);
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1246
|
+
|
|
1247
|
+
return { sender: registrySender, isRegistryRouted: true };
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
/**
|
|
1251
|
+
* Persist the pre-chat onboarding payload to disk.
|
|
1252
|
+
*
|
|
1253
|
+
* Runs only on the very first message of a fresh conversation. Three
|
|
1254
|
+
* artifacts are produced:
|
|
1255
|
+
*
|
|
1256
|
+
* 1. `data/onboarding-context.json` — sidecar read by the
|
|
1257
|
+
* relationship-state writer so onboarding-sourced facts survive
|
|
1258
|
+
* the pure-recomputation write cycle (every turn boundary rebuilds
|
|
1259
|
+
* facts from markdown; the sidecar is the durable source for the
|
|
1260
|
+
* tool/task/tone chips).
|
|
1261
|
+
* 2. `IDENTITY.md` / `USER.md` — persona seed files, only written
|
|
1262
|
+
* when missing so we never clobber existing content. These feed
|
|
1263
|
+
* the system prompt and the relationship-state writer's
|
|
1264
|
+
* `parseIdentity` / `parseUserName` helpers after a daemon
|
|
1265
|
+
* restart when the in-memory onboarding context is gone.
|
|
1266
|
+
* 3. `data/relationship-state.json` — kicked off fire-and-forget so
|
|
1267
|
+
* the Home page can populate immediately on first visit instead
|
|
1268
|
+
* of waiting for the first agent-turn boundary.
|
|
1269
|
+
*
|
|
1270
|
+
* Never throws: every write is guarded and logged as a warning on
|
|
1271
|
+
* failure. The route handler path must never reject because of a
|
|
1272
|
+
* best-effort persistence step.
|
|
1273
|
+
*/
|
|
1274
|
+
function persistOnboardingArtifacts(onboarding: {
|
|
1275
|
+
tools: string[];
|
|
1276
|
+
tasks: string[];
|
|
1277
|
+
tone: string;
|
|
1278
|
+
userName?: string;
|
|
1279
|
+
assistantName?: string;
|
|
1280
|
+
}): void {
|
|
1281
|
+
writeOnboardingSidecar(onboarding);
|
|
1282
|
+
|
|
1283
|
+
const assistantName = onboarding.assistantName?.trim();
|
|
1284
|
+
if (assistantName) {
|
|
1285
|
+
const identityPath = getWorkspacePromptPath("IDENTITY.md");
|
|
1286
|
+
if (!existsSync(identityPath)) {
|
|
1287
|
+
try {
|
|
1288
|
+
writeFileSync(
|
|
1289
|
+
identityPath,
|
|
1290
|
+
`# Identity\n\n- Name: ${assistantName}\n`,
|
|
1291
|
+
"utf-8",
|
|
1292
|
+
);
|
|
1293
|
+
} catch (err) {
|
|
1294
|
+
log.warn(
|
|
1295
|
+
{ err, identityPath },
|
|
1296
|
+
"Failed to seed IDENTITY.md from onboarding",
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
const userName = onboarding.userName?.trim();
|
|
1303
|
+
if (userName) {
|
|
1304
|
+
const userPath = getWorkspacePromptPath("USER.md");
|
|
1305
|
+
if (!existsSync(userPath)) {
|
|
1306
|
+
try {
|
|
1307
|
+
writeFileSync(userPath, `# User\n\n- Name: ${userName}\n`, "utf-8");
|
|
1308
|
+
} catch (err) {
|
|
1309
|
+
log.warn({ err, userPath }, "Failed to seed USER.md from onboarding");
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
void writeRelationshipState().catch((err) => {
|
|
1315
|
+
log.warn(
|
|
1316
|
+
{ err },
|
|
1317
|
+
"Failed to kick off relationship-state write after onboarding",
|
|
1318
|
+
);
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1103
1322
|
export async function handleSendMessage(
|
|
1104
1323
|
req: Request,
|
|
1105
1324
|
deps: {
|
|
@@ -1120,9 +1339,19 @@ export async function handleSendMessage(
|
|
|
1120
1339
|
bypassSecretCheck?: boolean;
|
|
1121
1340
|
hostHomeDir?: string;
|
|
1122
1341
|
hostUsername?: string;
|
|
1342
|
+
clientMessageId?: string;
|
|
1343
|
+
onboarding?: {
|
|
1344
|
+
tools: string[];
|
|
1345
|
+
tasks: string[];
|
|
1346
|
+
tone: string;
|
|
1347
|
+
userName?: string;
|
|
1348
|
+
assistantName?: string;
|
|
1349
|
+
};
|
|
1123
1350
|
};
|
|
1124
1351
|
|
|
1125
1352
|
const { conversationKey, content, attachmentIds } = body;
|
|
1353
|
+
const clientMessageId =
|
|
1354
|
+
typeof body.clientMessageId === "string" ? body.clientMessageId : undefined;
|
|
1126
1355
|
if (!body.sourceChannel || typeof body.sourceChannel !== "string") {
|
|
1127
1356
|
return httpError("BAD_REQUEST", "sourceChannel is required", 400);
|
|
1128
1357
|
}
|
|
@@ -1222,8 +1451,32 @@ export async function handleSendMessage(
|
|
|
1222
1451
|
const mapping = getOrCreateConversation(resolvedConversationKey, {
|
|
1223
1452
|
conversationType,
|
|
1224
1453
|
});
|
|
1454
|
+
|
|
1225
1455
|
const smDeps = deps.sendMessageDeps;
|
|
1226
1456
|
|
|
1457
|
+
// Notify all connected clients that the conversation list changed when
|
|
1458
|
+
// this is the first message in a standard conversation, so sidebars on
|
|
1459
|
+
// other devices can refresh. We check for first-message rather than
|
|
1460
|
+
// first-create because the SSE subscribe handler (events-routes.ts) may
|
|
1461
|
+
// have already materialised the conversation from a draft key before any
|
|
1462
|
+
// message was sent — in that case `mapping.created` is `false` even
|
|
1463
|
+
// though, from the user's perspective, this is a brand-new conversation
|
|
1464
|
+
// that other clients don't yet know about.
|
|
1465
|
+
if (mapping.conversationType === "standard") {
|
|
1466
|
+
if (!hasMessages(mapping.conversationId)) {
|
|
1467
|
+
smDeps.assistantEventHub
|
|
1468
|
+
.publish(
|
|
1469
|
+
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
1470
|
+
type: "conversation_list_invalidated",
|
|
1471
|
+
reason: "created",
|
|
1472
|
+
}),
|
|
1473
|
+
)
|
|
1474
|
+
.catch((err) => {
|
|
1475
|
+
log.warn({ err }, "Failed to publish conversation_list_invalidated");
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1227
1480
|
// Build transport metadata from the request so the daemon can inject
|
|
1228
1481
|
// host environment hints (home directory, username) into the LLM context.
|
|
1229
1482
|
// The `supportsHostProxy` type predicate narrows `sourceInterface` to
|
|
@@ -1247,6 +1500,17 @@ export async function handleSendMessage(
|
|
|
1247
1500
|
{ transport },
|
|
1248
1501
|
);
|
|
1249
1502
|
|
|
1503
|
+
// Store pre-chat onboarding context on the conversation when this is the
|
|
1504
|
+
// very first message (no prior messages loaded). Also persist the
|
|
1505
|
+
// onboarding selections so the Home page shows onboarding-sourced
|
|
1506
|
+
// chips immediately, and seed IDENTITY.md / USER.md so subsequent
|
|
1507
|
+
// turn-boundary recomputes of relationship-state have a stable
|
|
1508
|
+
// persona source beyond the in-memory conversation object.
|
|
1509
|
+
if (body.onboarding && conversation.messages.length === 0) {
|
|
1510
|
+
conversation.setOnboardingContext(body.onboarding);
|
|
1511
|
+
persistOnboardingArtifacts(body.onboarding);
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1250
1514
|
// Resolve guardian context from the AuthContext's actorPrincipalId.
|
|
1251
1515
|
// The JWT-verified principal is used as the sender identity through
|
|
1252
1516
|
// the same trust resolution pipeline that channel ingress uses.
|
|
@@ -1328,66 +1592,44 @@ export async function handleSendMessage(
|
|
|
1328
1592
|
} else if (!conversation.isProcessing()) {
|
|
1329
1593
|
conversation.setHostBashProxy(undefined);
|
|
1330
1594
|
}
|
|
1331
|
-
//
|
|
1332
|
-
//
|
|
1333
|
-
//
|
|
1334
|
-
//
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
// `sendToInstance` if a caller ever needs it.
|
|
1345
|
-
//
|
|
1346
|
-
// macOS (and any other interface that supports host_browser in the
|
|
1347
|
-
// future via the SSE hub) keeps using `onEvent` — see the else branch.
|
|
1348
|
-
const browserProxySendToClient: (msg: ServerMessage) => void =
|
|
1349
|
-
sourceInterface === "chrome-extension"
|
|
1350
|
-
? (msg) => {
|
|
1351
|
-
// Resolve the guardian principal id at send time rather than
|
|
1352
|
-
// capturing it from the POST-time authContext. This closure can be
|
|
1353
|
-
// re-fired on queue drain — if a different actor's POST lands while
|
|
1354
|
-
// the queue is still draining an earlier turn, a captured
|
|
1355
|
-
// authContext.actorPrincipalId would mis-route the earlier turn's
|
|
1356
|
-
// host_browser frames to the *new* actor. Preferring
|
|
1357
|
-
// conversation.trustContext?.guardianPrincipalId makes the routing
|
|
1358
|
-
// follow the conversation's bound guardian, which is stable across
|
|
1359
|
-
// subsequent POSTs. Falls back to the per-POST authContext for
|
|
1360
|
-
// turns that haven't been bound to a trust context yet.
|
|
1361
|
-
const gid =
|
|
1362
|
-
conversation.trustContext?.guardianPrincipalId ??
|
|
1363
|
-
authContext.actorPrincipalId;
|
|
1364
|
-
if (!gid) {
|
|
1365
|
-
// No guardian identity on this turn — nothing to route to.
|
|
1366
|
-
// The proxy will observe this via its try/catch and surface a
|
|
1367
|
-
// transport error back to the caller.
|
|
1368
|
-
throw new Error(
|
|
1369
|
-
"chrome-extension host_browser send skipped: no guardianId on AuthContext",
|
|
1370
|
-
);
|
|
1371
|
-
}
|
|
1372
|
-
const ok = getChromeExtensionRegistry().send(gid, msg);
|
|
1373
|
-
if (!ok) {
|
|
1374
|
-
throw new Error(
|
|
1375
|
-
`chrome-extension host_browser send failed: no active connection for guardian ${gid}`,
|
|
1376
|
-
);
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
: onEvent;
|
|
1595
|
+
// Resolve the host_browser sender — registry-routed when the guardian has
|
|
1596
|
+
// an active extension connection, SSE hub otherwise. This applies to both
|
|
1597
|
+
// chrome-extension and macOS interfaces so that macOS turns can route
|
|
1598
|
+
// browser automation through the user's real Chrome session when available.
|
|
1599
|
+
const { sender: browserProxySendToClient, isRegistryRouted } =
|
|
1600
|
+
resolveHostBrowserSender(
|
|
1601
|
+
conversation,
|
|
1602
|
+
mapping.conversationId,
|
|
1603
|
+
authContext,
|
|
1604
|
+
onEvent,
|
|
1605
|
+
sourceInterface,
|
|
1606
|
+
);
|
|
1607
|
+
|
|
1380
1608
|
// Stash the registry-routed sender on the conversation so queue-drain
|
|
1381
1609
|
// restores (which run outside of conversation-routes.ts and only have
|
|
1382
1610
|
// access to `sendToClient`) can preserve it when calling
|
|
1383
|
-
// `restoreBrowserProxyAvailability()`.
|
|
1384
|
-
//
|
|
1385
|
-
|
|
1611
|
+
// `restoreBrowserProxyAvailability()`. The override is set when the
|
|
1612
|
+
// sender is registry-routed (regardless of interface) and cleared when
|
|
1613
|
+
// the SSE hub sender is used, so the drain path always restores the
|
|
1614
|
+
// correct transport.
|
|
1615
|
+
if (isRegistryRouted) {
|
|
1386
1616
|
conversation.hostBrowserSenderOverride = browserProxySendToClient;
|
|
1387
1617
|
} else {
|
|
1388
1618
|
conversation.hostBrowserSenderOverride = undefined;
|
|
1389
1619
|
}
|
|
1390
|
-
|
|
1620
|
+
|
|
1621
|
+
// Provision the host browser proxy. For interfaces that natively support
|
|
1622
|
+
// host_browser (chrome-extension), always provision it. For macOS, the
|
|
1623
|
+
// static capability check returns false (supportsHostProxy("macos",
|
|
1624
|
+
// "host_browser") === false) because the extension isn't guaranteed to be
|
|
1625
|
+
// attached — but when the registry confirms an active extension
|
|
1626
|
+
// connection, we provision the proxy anyway so macOS turns can drive the
|
|
1627
|
+
// user's real Chrome session. When no extension is connected, macOS skips
|
|
1628
|
+
// provisioning and browser tools fall through to cdp-inspect/local.
|
|
1629
|
+
const shouldProvisionBrowserProxy =
|
|
1630
|
+
supportsHostProxy(sourceInterface, "host_browser") ||
|
|
1631
|
+
(canServiceRegistryBrowser(sourceInterface) && isRegistryRouted);
|
|
1632
|
+
if (shouldProvisionBrowserProxy) {
|
|
1391
1633
|
if (!conversation.isProcessing() || !conversation.hostBrowserProxy) {
|
|
1392
1634
|
const browserProxy = new HostBrowserProxy(
|
|
1393
1635
|
browserProxySendToClient,
|
|
@@ -1445,18 +1687,17 @@ export async function handleSendMessage(
|
|
|
1445
1687
|
conversation.updateClient(onEvent, !isInteractive, {
|
|
1446
1688
|
skipProxySenderUpdate: preservingProxies,
|
|
1447
1689
|
});
|
|
1448
|
-
//
|
|
1449
|
-
//
|
|
1450
|
-
//
|
|
1451
|
-
//
|
|
1452
|
-
// host_bash/host_file tool availability into tool gating.
|
|
1690
|
+
// Re-enable the browser proxy for turns that provisioned one. This covers:
|
|
1691
|
+
// - chrome-extension: natively supports host_browser (non-interactive but
|
|
1692
|
+
// has a connected client for host_browser_request events)
|
|
1693
|
+
// - macOS with extension: provisioned above when isRegistryRouted is true
|
|
1453
1694
|
//
|
|
1454
|
-
// `
|
|
1455
|
-
//
|
|
1456
|
-
//
|
|
1457
|
-
//
|
|
1458
|
-
//
|
|
1459
|
-
if (
|
|
1695
|
+
// The helper bypasses the `hasNoClient` gate so chrome-extension turns can
|
|
1696
|
+
// drive the browser via CDP without leaking host_bash/host_file tool
|
|
1697
|
+
// availability. It reads `hostBrowserSenderOverride` (set above when
|
|
1698
|
+
// registry-routed) and applies the correct sender — including after
|
|
1699
|
+
// queue-drain restores run from conversation-process.ts.
|
|
1700
|
+
if (shouldProvisionBrowserProxy) {
|
|
1460
1701
|
conversation.restoreBrowserProxyAvailability?.();
|
|
1461
1702
|
}
|
|
1462
1703
|
|
|
@@ -1522,6 +1763,13 @@ export async function handleSendMessage(
|
|
|
1522
1763
|
// fast path) so the HTTP response reaches the client before SSE
|
|
1523
1764
|
// events arrive.
|
|
1524
1765
|
setTimeout(() => {
|
|
1766
|
+
onEvent({
|
|
1767
|
+
type: "user_message_echo",
|
|
1768
|
+
text: rawContent,
|
|
1769
|
+
conversationId,
|
|
1770
|
+
messageId: persisted.id,
|
|
1771
|
+
clientMessageId,
|
|
1772
|
+
});
|
|
1525
1773
|
onEvent({ type: "assistant_text_delta", text: cannedGreeting });
|
|
1526
1774
|
onEvent({ type: "message_complete", conversationId });
|
|
1527
1775
|
conversation.processing = false;
|
|
@@ -1618,6 +1866,7 @@ export async function handleSendMessage(
|
|
|
1618
1866
|
{ isInteractive },
|
|
1619
1867
|
undefined, // displayContent
|
|
1620
1868
|
transport,
|
|
1869
|
+
clientMessageId,
|
|
1621
1870
|
);
|
|
1622
1871
|
if (enqueueResult.rejected) {
|
|
1623
1872
|
return Response.json(
|
|
@@ -1730,9 +1979,9 @@ export async function handleSendMessage(
|
|
|
1730
1979
|
messageCount: conversation.getMessages().length,
|
|
1731
1980
|
inputTokens: conversation.usageStats.inputTokens,
|
|
1732
1981
|
outputTokens: conversation.usageStats.outputTokens,
|
|
1733
|
-
maxInputTokens: config.contextWindow.maxInputTokens,
|
|
1734
|
-
model: config.
|
|
1735
|
-
provider: config.
|
|
1982
|
+
maxInputTokens: config.llm.default.contextWindow.maxInputTokens,
|
|
1983
|
+
model: config.llm.default.model,
|
|
1984
|
+
provider: config.llm.default.provider,
|
|
1736
1985
|
estimatedCost: conversation.usageStats.estimatedCost,
|
|
1737
1986
|
userMessageInterface: sourceInterface,
|
|
1738
1987
|
};
|
|
@@ -1815,6 +2064,13 @@ export async function handleSendMessage(
|
|
|
1815
2064
|
const conversationId = mapping.conversationId;
|
|
1816
2065
|
const message = slashResult.message;
|
|
1817
2066
|
setTimeout(() => {
|
|
2067
|
+
onEvent({
|
|
2068
|
+
type: "user_message_echo",
|
|
2069
|
+
text: rawContent,
|
|
2070
|
+
conversationId,
|
|
2071
|
+
messageId: persisted.id,
|
|
2072
|
+
clientMessageId,
|
|
2073
|
+
});
|
|
1818
2074
|
if (modelInfoEvent) {
|
|
1819
2075
|
onEvent(modelInfoEvent);
|
|
1820
2076
|
}
|
|
@@ -1841,80 +2097,89 @@ export async function handleSendMessage(
|
|
|
1841
2097
|
|
|
1842
2098
|
if (slashResult.kind === "compact") {
|
|
1843
2099
|
conversation.processing = true;
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
);
|
|
1861
|
-
conversation.getMessages().push(cleanMsg);
|
|
1862
|
-
|
|
1863
|
-
conversation.emitActivityState(
|
|
1864
|
-
"thinking",
|
|
1865
|
-
"context_compacting",
|
|
1866
|
-
"assistant_turn",
|
|
1867
|
-
);
|
|
1868
|
-
const result = await conversation.forceCompact();
|
|
1869
|
-
const responseText = formatCompactResult(result);
|
|
2100
|
+
const provenance = provenanceFromTrustContext(conversation.trustContext);
|
|
2101
|
+
const channelMeta = {
|
|
2102
|
+
...provenance,
|
|
2103
|
+
userMessageChannel: sourceChannel,
|
|
2104
|
+
assistantMessageChannel: sourceChannel,
|
|
2105
|
+
userMessageInterface: sourceInterface,
|
|
2106
|
+
assistantMessageInterface: sourceInterface,
|
|
2107
|
+
};
|
|
2108
|
+
const cleanMsg = createUserMessage(rawContent, attachments);
|
|
2109
|
+
const persisted = await addMessage(
|
|
2110
|
+
mapping.conversationId,
|
|
2111
|
+
"user",
|
|
2112
|
+
JSON.stringify(cleanMsg.content),
|
|
2113
|
+
channelMeta,
|
|
2114
|
+
);
|
|
2115
|
+
conversation.getMessages().push(cleanMsg);
|
|
1870
2116
|
|
|
1871
|
-
|
|
1872
|
-
await addMessage(
|
|
1873
|
-
mapping.conversationId,
|
|
1874
|
-
"assistant",
|
|
1875
|
-
JSON.stringify(assistantMsg.content),
|
|
1876
|
-
channelMeta,
|
|
1877
|
-
);
|
|
1878
|
-
conversation.getMessages().push(assistantMsg);
|
|
2117
|
+
const conversationId = mapping.conversationId;
|
|
1879
2118
|
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
2119
|
+
// Fire-and-forget: return 202 immediately, run compaction async.
|
|
2120
|
+
// forceCompact() makes an LLM call that can exceed the client's
|
|
2121
|
+
// HTTP timeout on large contexts, causing a false "Failed to send".
|
|
2122
|
+
(async () => {
|
|
2123
|
+
try {
|
|
2124
|
+
onEvent({
|
|
2125
|
+
type: "user_message_echo",
|
|
2126
|
+
text: rawContent,
|
|
2127
|
+
conversationId,
|
|
1883
2128
|
messageId: persisted.id,
|
|
1884
|
-
|
|
1885
|
-
}
|
|
1886
|
-
|
|
1887
|
-
|
|
2129
|
+
clientMessageId,
|
|
2130
|
+
});
|
|
2131
|
+
conversation.emitActivityState(
|
|
2132
|
+
"thinking",
|
|
2133
|
+
"context_compacting",
|
|
2134
|
+
"assistant_turn",
|
|
2135
|
+
);
|
|
2136
|
+
const result = await conversation.forceCompact();
|
|
2137
|
+
const responseText = formatCompactResult(result);
|
|
2138
|
+
|
|
2139
|
+
const assistantMsg = createAssistantMessage(responseText);
|
|
2140
|
+
await addMessage(
|
|
2141
|
+
conversationId,
|
|
2142
|
+
"assistant",
|
|
2143
|
+
JSON.stringify(assistantMsg.content),
|
|
2144
|
+
channelMeta,
|
|
2145
|
+
);
|
|
2146
|
+
conversation.getMessages().push(assistantMsg);
|
|
1888
2147
|
|
|
1889
|
-
const conversationId = mapping.conversationId;
|
|
1890
|
-
setTimeout(() => {
|
|
1891
2148
|
onEvent({ type: "assistant_text_delta", text: responseText });
|
|
2149
|
+
onEvent({ type: "message_complete", conversationId });
|
|
2150
|
+
} catch (err) {
|
|
2151
|
+
log.error({ err, conversationId }, "Compact command failed");
|
|
1892
2152
|
onEvent({
|
|
1893
|
-
type: "
|
|
2153
|
+
type: "conversation_error",
|
|
1894
2154
|
conversationId,
|
|
2155
|
+
code: "UNKNOWN",
|
|
2156
|
+
userMessage: `Compaction failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
2157
|
+
retryable: true,
|
|
1895
2158
|
});
|
|
2159
|
+
} finally {
|
|
1896
2160
|
conversation.processing = false;
|
|
1897
2161
|
silentlyWithLog(
|
|
1898
2162
|
conversation.drainQueue(),
|
|
1899
2163
|
"compact-command queue drain",
|
|
1900
2164
|
);
|
|
1901
|
-
}, 0);
|
|
1902
|
-
|
|
1903
|
-
cleanupDeferred = true;
|
|
1904
|
-
return response;
|
|
1905
|
-
} finally {
|
|
1906
|
-
if (!cleanupDeferred && conversation.processing) {
|
|
1907
|
-
conversation.processing = false;
|
|
1908
|
-
silentlyWithLog(conversation.drainQueue(), "error-path queue drain");
|
|
1909
2165
|
}
|
|
1910
|
-
}
|
|
2166
|
+
})();
|
|
2167
|
+
|
|
2168
|
+
return Response.json(
|
|
2169
|
+
{
|
|
2170
|
+
accepted: true,
|
|
2171
|
+
messageId: persisted.id,
|
|
2172
|
+
conversationId,
|
|
2173
|
+
},
|
|
2174
|
+
{ status: 202 },
|
|
2175
|
+
);
|
|
1911
2176
|
}
|
|
1912
2177
|
|
|
1913
2178
|
const resolvedContent = slashResult.content;
|
|
1914
2179
|
|
|
2180
|
+
const requestId = crypto.randomUUID();
|
|
1915
2181
|
let messageId: string;
|
|
1916
2182
|
try {
|
|
1917
|
-
const requestId = crypto.randomUUID();
|
|
1918
2183
|
messageId = await conversation.persistUserMessage(
|
|
1919
2184
|
resolvedContent,
|
|
1920
2185
|
attachments,
|
|
@@ -1925,6 +2190,15 @@ export async function handleSendMessage(
|
|
|
1925
2190
|
throw err;
|
|
1926
2191
|
}
|
|
1927
2192
|
|
|
2193
|
+
onEvent({
|
|
2194
|
+
type: "user_message_echo",
|
|
2195
|
+
text: resolvedContent,
|
|
2196
|
+
conversationId: mapping.conversationId,
|
|
2197
|
+
messageId,
|
|
2198
|
+
requestId,
|
|
2199
|
+
clientMessageId,
|
|
2200
|
+
});
|
|
2201
|
+
|
|
1928
2202
|
// Fire-and-forget the agent loop; events flow to the hub via onEvent.
|
|
1929
2203
|
conversation
|
|
1930
2204
|
.runAgentLoop(resolvedContent, messageId, onEvent, {
|
|
@@ -1944,28 +2218,62 @@ export async function handleSendMessage(
|
|
|
1944
2218
|
);
|
|
1945
2219
|
}
|
|
1946
2220
|
|
|
2221
|
+
function escapeXmlContent(text: string): string {
|
|
2222
|
+
return text
|
|
2223
|
+
.replace(/&/g, "&")
|
|
2224
|
+
.replace(/</g, "<")
|
|
2225
|
+
.replace(/>/g, ">");
|
|
2226
|
+
}
|
|
2227
|
+
|
|
1947
2228
|
async function generateLlmSuggestion(
|
|
1948
2229
|
provider: Provider,
|
|
1949
2230
|
assistantText: string,
|
|
2231
|
+
priorUserText: string | null,
|
|
1950
2232
|
): Promise<string | null> {
|
|
1951
2233
|
const log = (await import("../../util/logger.js")).getLogger("runtime-http");
|
|
1952
|
-
const
|
|
1953
|
-
assistantText.length > 2000 ? assistantText.slice(-2000) : assistantText
|
|
2234
|
+
const truncatedAssistant = escapeXmlContent(
|
|
2235
|
+
assistantText.length > 2000 ? assistantText.slice(-2000) : assistantText,
|
|
2236
|
+
);
|
|
2237
|
+
const truncatedUser =
|
|
2238
|
+
priorUserText && priorUserText.length > 500
|
|
2239
|
+
? escapeXmlContent(priorUserText.slice(-500))
|
|
2240
|
+
: priorUserText
|
|
2241
|
+
? escapeXmlContent(priorUserText)
|
|
2242
|
+
: priorUserText;
|
|
1954
2243
|
|
|
1955
|
-
const prompt = `Given this assistant message, write a very short tab-complete suggestion the user could send next. Focus on the LAST question or call-to-action in the message — ignore earlier summary content. Be casual, curious, or actionable — like a quick reply, not a formal request. Reply with ONLY the suggestion text.\n\nAssistant's message:\n${truncated}`;
|
|
1956
2244
|
const systemPrompt =
|
|
1957
|
-
"You
|
|
2245
|
+
"You generate short, casual reply suggestions a user might type next in a chat. Match the tone and register of the preceding conversation. Output only the reply text inside the requested tags — no preamble, no commentary.";
|
|
2246
|
+
|
|
2247
|
+
const userPrompt =
|
|
2248
|
+
`Here is the end of a conversation:\n\n` +
|
|
2249
|
+
`<user_message>${truncatedUser ?? "(no prior user message)"}</user_message>\n` +
|
|
2250
|
+
`<assistant_message>${truncatedAssistant}</assistant_message>\n\n` +
|
|
2251
|
+
`Write the user's next reply, focusing on the LAST question or call-to-action in the assistant message. Keep it short (under 15 words), casual, and in the user's voice. Respond in this exact format:\n\n` +
|
|
2252
|
+
`<reply>YOUR_REPLY_HERE</reply>`;
|
|
1958
2253
|
|
|
1959
2254
|
const response = await provider.sendMessage(
|
|
1960
|
-
[
|
|
2255
|
+
[
|
|
2256
|
+
{ role: "user", content: [{ type: "text", text: userPrompt }] },
|
|
2257
|
+
{ role: "assistant", content: [{ type: "text", text: "<reply>" }] },
|
|
2258
|
+
],
|
|
1961
2259
|
[], // no tools
|
|
1962
2260
|
systemPrompt,
|
|
1963
|
-
{
|
|
2261
|
+
{
|
|
2262
|
+
config: {
|
|
2263
|
+
callSite: "conversationStarters",
|
|
2264
|
+
max_tokens: 60,
|
|
2265
|
+
stop_sequences: ["</reply>"],
|
|
2266
|
+
temperature: 0.7,
|
|
2267
|
+
},
|
|
2268
|
+
},
|
|
1964
2269
|
);
|
|
1965
2270
|
|
|
1966
2271
|
const textBlock = response.content.find((b) => b.type === "text");
|
|
1967
|
-
const raw = textBlock && "text" in textBlock ? textBlock.text
|
|
1968
|
-
const stripped = raw
|
|
2272
|
+
const raw = textBlock && "text" in textBlock ? textBlock.text : "";
|
|
2273
|
+
const stripped = raw
|
|
2274
|
+
.replace(/<\/?reply>/gi, "")
|
|
2275
|
+
.replace(/^["'`]+|["'`]+$/g, "")
|
|
2276
|
+
.trim();
|
|
1969
2277
|
|
|
1970
2278
|
if (!stripped) {
|
|
1971
2279
|
log.debug("Suggestion rejected: empty LLM response");
|
|
@@ -2078,14 +2386,33 @@ export async function handleGetSuggestion(
|
|
|
2078
2386
|
});
|
|
2079
2387
|
}
|
|
2080
2388
|
|
|
2389
|
+
// Find the most recent user message preceding this assistant turn so the
|
|
2390
|
+
// suggestion model can see both sides of the conversation and doesn't have
|
|
2391
|
+
// to guess which role it's generating for.
|
|
2392
|
+
let priorUserText: string | null = null;
|
|
2393
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
2394
|
+
if (rawMessages[j].role !== "user") continue;
|
|
2395
|
+
let userContent: unknown;
|
|
2396
|
+
try {
|
|
2397
|
+
userContent = JSON.parse(rawMessages[j].content);
|
|
2398
|
+
} catch {
|
|
2399
|
+
userContent = rawMessages[j].content;
|
|
2400
|
+
}
|
|
2401
|
+
const userText = renderHistoryContent(userContent).text.trim();
|
|
2402
|
+
if (userText) {
|
|
2403
|
+
priorUserText = userText;
|
|
2404
|
+
break;
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2081
2408
|
// Try LLM suggestion using the configured provider
|
|
2082
|
-
const provider = await getConfiguredProvider();
|
|
2409
|
+
const provider = await getConfiguredProvider("conversationStarters");
|
|
2083
2410
|
if (provider) {
|
|
2084
2411
|
try {
|
|
2085
2412
|
// Deduplicate concurrent requests
|
|
2086
2413
|
let promise = suggestionInFlight.get(msg.id);
|
|
2087
2414
|
if (!promise) {
|
|
2088
|
-
promise = generateLlmSuggestion(provider, text);
|
|
2415
|
+
promise = generateLlmSuggestion(provider, text, priorUserText);
|
|
2089
2416
|
suggestionInFlight.set(msg.id, promise);
|
|
2090
2417
|
}
|
|
2091
2418
|
|