@vellumai/assistant 0.6.3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +273 -10
- package/Dockerfile +2 -3
- package/bun.lock +5 -13
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/stt-provider-onboarding.md +120 -0
- package/knip.json +12 -2
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +3 -3
- package/openapi.yaml +982 -72
- package/package.json +4 -6
- package/scripts/generate-openapi.ts +0 -1
- package/scripts/test.sh +73 -18
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop.test.ts +123 -0
- package/src/__tests__/anthropic-provider.test.ts +263 -10
- package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
- package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
- package/src/__tests__/browser-fill-credential.test.ts +11 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/browser-skill-endstate.test.ts +31 -7
- package/src/__tests__/btw-routes.test.ts +7 -0
- package/src/__tests__/call-controller.test.ts +581 -20
- package/src/__tests__/catalog-files.test.ts +138 -0
- package/src/__tests__/channel-invite-transport.test.ts +2 -2
- package/src/__tests__/channel-readiness-routes.test.ts +16 -20
- package/src/__tests__/channel-readiness-service.test.ts +12 -7
- package/src/__tests__/checker.test.ts +157 -10
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/config-analysis.test.ts +100 -0
- package/src/__tests__/config-schema.test.ts +1013 -66
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +43 -8
- package/src/__tests__/contact-store-user-file.test.ts +512 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-window-manager.test.ts +88 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +98 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +135 -0
- package/src/__tests__/conversation-error.test.ts +70 -0
- package/src/__tests__/conversation-history-web-search.test.ts +11 -4
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +901 -60
- package/src/__tests__/conversation-routes-disk-view.test.ts +270 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +55 -0
- package/src/__tests__/conversation-skill-tools.test.ts +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +89 -18
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +5 -3
- package/src/__tests__/credential-vault-unit.test.ts +379 -3
- package/src/__tests__/credentials-cli.test.ts +40 -16
- package/src/__tests__/cross-provider-web-search.test.ts +146 -35
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +75 -8
- package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +64 -0
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
- package/src/__tests__/gmail-archive-gate.test.ts +246 -0
- package/src/__tests__/gmail-preferences.test.ts +117 -0
- package/src/__tests__/headless-browser-interactions.test.ts +43 -0
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +142 -5
- package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
- package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
- package/src/__tests__/heartbeat-service.test.ts +70 -17
- package/src/__tests__/home-state-routes.test.ts +162 -0
- package/src/__tests__/host-bash-proxy.test.ts +0 -5
- package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
- package/src/__tests__/host-cu-proxy.test.ts +0 -5
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/llm-context-normalization.test.ts +488 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/media-stream-output.test.ts +555 -0
- package/src/__tests__/media-stream-parser.test.ts +374 -0
- package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
- package/src/__tests__/media-stream-stt-session.test.ts +588 -0
- package/src/__tests__/media-turn-detector.test.ts +440 -0
- package/src/__tests__/message-queue.test.ts +125 -0
- package/src/__tests__/migration-export-http.test.ts +6 -6
- package/src/__tests__/migration-import-commit-http.test.ts +8 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +151 -0
- package/src/__tests__/model-intents.test.ts +2 -2
- package/src/__tests__/oauth-apps-routes.test.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +2 -0
- package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
- package/src/__tests__/oauth-providers-routes.test.ts +2 -0
- package/src/__tests__/oauth-store.test.ts +85 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +249 -6
- package/src/__tests__/onboarding-template-contract.test.ts +6 -13
- package/src/__tests__/openai-provider.test.ts +176 -0
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1105 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +31 -2
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +174 -0
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
- package/src/__tests__/relationship-state-contract.test.ts +175 -0
- package/src/__tests__/relay-server.test.ts +423 -5
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-scanner-executor.test.ts +4 -0
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +5 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +49 -0
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
- package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
- package/src/__tests__/skills.test.ts +5 -2
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +564 -1
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/system-prompt.test.ts +112 -26
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +18 -7
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +33 -24
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/trust-store.test.ts +7 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +345 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
- package/src/__tests__/twilio-routes.test.ts +376 -0
- package/src/__tests__/unicode.test.ts +293 -0
- package/src/__tests__/update-bulletin-format.test.ts +59 -0
- package/src/__tests__/update-bulletin.test.ts +206 -5
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
- package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
- package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
- package/src/__tests__/workspace-migration-meets.test.ts +244 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
- package/src/__tests__/workspace-policy.test.ts +2 -0
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +43 -3
- package/src/backup/__tests__/backup-key.test.ts +152 -0
- package/src/backup/__tests__/backup-worker.test.ts +767 -0
- package/src/backup/__tests__/list-snapshots.test.ts +87 -0
- package/src/backup/__tests__/local-writer.test.ts +218 -0
- package/src/backup/__tests__/offsite-writer.test.ts +641 -0
- package/src/backup/__tests__/paths.test.ts +300 -0
- package/src/backup/__tests__/restore.test.ts +498 -0
- package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
- package/src/backup/__tests__/stream-crypt.test.ts +228 -0
- package/src/backup/backup-key.ts +137 -0
- package/src/backup/backup-worker.ts +459 -0
- package/src/backup/list-snapshots.ts +147 -0
- package/src/backup/local-writer.ts +133 -0
- package/src/backup/offsite-writer.ts +222 -0
- package/src/backup/paths.ts +226 -0
- package/src/backup/restore.ts +322 -0
- package/src/backup/snapshot-lock.ts +431 -0
- package/src/backup/stream-crypt.ts +263 -0
- package/src/bundler/package-resolver.ts +4 -0
- package/src/calls/audio-store.ts +11 -5
- package/src/calls/call-controller.ts +226 -71
- package/src/calls/call-domain.ts +9 -0
- package/src/calls/call-speech-output.ts +190 -0
- package/src/calls/call-transport.ts +77 -0
- package/src/calls/media-stream-audio-transcode.ts +173 -0
- package/src/calls/media-stream-output.ts +660 -0
- package/src/calls/media-stream-parser.ts +300 -0
- package/src/calls/media-stream-protocol.ts +166 -0
- package/src/calls/media-stream-server.ts +592 -0
- package/src/calls/media-stream-stt-session.ts +460 -0
- package/src/calls/media-turn-detector.ts +230 -0
- package/src/calls/relay-server.ts +90 -75
- package/src/calls/resolve-call-tts-provider.ts +136 -0
- package/src/calls/telephony-stt-routing.ts +145 -0
- package/src/calls/tts-call-strategy.ts +161 -0
- package/src/calls/tts-text-sanitizer.ts +32 -16
- package/src/calls/twilio-routes.ts +281 -17
- package/src/calls/voice-quality.ts +78 -35
- package/src/calls/voice-session-bridge.ts +8 -1
- package/src/channels/types.ts +16 -0
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
- package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
- package/src/cli/commands/__tests__/email-download.test.ts +16 -1
- package/src/cli/commands/__tests__/email-list.test.ts +22 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +37 -4
- package/src/cli/commands/__tests__/email-status.test.ts +5 -1
- package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/conversations.ts +77 -0
- package/src/cli/commands/credentials.ts +0 -1
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +255 -3
- package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +15 -0
- package/src/cli/commands/oauth/shared.ts +2 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -9
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
- package/src/cli/program.ts +30 -4
- package/src/config/__tests__/backup-schema.test.ts +134 -0
- package/src/config/assistant-feature-flags.ts +61 -62
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +37 -1
- package/src/config/bundled-skills/browser/SKILL.md +30 -5
- package/src/config/bundled-skills/browser/TOOLS.json +123 -0
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
- package/src/config/bundled-skills/contacts/SKILL.md +2 -2
- package/src/config/bundled-skills/gmail/SKILL.md +53 -7
- package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
- package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
- package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/outlook/SKILL.md +2 -2
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
- package/src/config/bundled-skills/slack/SKILL.md +1 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
- package/src/config/bundled-tool-registry.ts +8 -0
- package/src/config/env-registry.ts +24 -0
- package/src/config/env.ts +34 -10
- package/src/config/feature-flag-registry.json +46 -14
- package/src/config/loader.ts +26 -12
- package/src/config/schema.ts +35 -10
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +51 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -26
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +47 -7
- package/src/config/schemas/heartbeat.ts +27 -5
- package/src/config/schemas/host-browser.ts +47 -1
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/services.ts +44 -0
- package/src/config/schemas/stt.ts +59 -0
- package/src/config/schemas/tts.ts +230 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/skills.ts +4 -0
- package/src/config/types.ts +4 -0
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/post-turn-tool-result-truncation.ts +3 -2
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +45 -12
- package/src/credential-execution/executable-discovery.ts +12 -2
- package/src/credential-execution/process-manager.ts +33 -2
- package/src/credential-health/credential-health-service.ts +366 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +17 -8
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/config-watcher.ts +99 -5
- package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
- package/src/daemon/conversation-agent-loop.ts +101 -24
- package/src/daemon/conversation-error.ts +11 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +59 -9
- package/src/daemon/conversation-messaging.ts +37 -3
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +581 -19
- package/src/daemon/conversation-queue-manager.ts +24 -0
- package/src/daemon/conversation-runtime-assembly.ts +11 -1
- package/src/daemon/conversation-slash.ts +36 -0
- package/src/daemon/conversation-surfaces.ts +94 -4
- package/src/daemon/conversation-tool-setup.ts +25 -0
- package/src/daemon/conversation-usage.ts +7 -4
- package/src/daemon/conversation.ts +86 -28
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +4 -1
- package/src/daemon/handlers/shared.ts +22 -0
- package/src/daemon/handlers/skills.ts +321 -77
- package/src/daemon/host-browser-proxy.ts +2 -1
- package/src/daemon/lifecycle.ts +122 -25
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/conversations.ts +34 -1
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +14 -0
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +16 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/server.ts +347 -2
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +9 -0
- package/src/email/html-renderer.ts +76 -0
- package/src/heartbeat/heartbeat-service.ts +93 -7
- package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
- package/src/home/__tests__/emit-feed-event.test.ts +169 -0
- package/src/home/__tests__/feed-scheduler.test.ts +194 -0
- package/src/home/__tests__/feed-types.test.ts +275 -0
- package/src/home/__tests__/feed-writer.test.ts +688 -0
- package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
- package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
- package/src/home/__tests__/progress-formula.test.ts +213 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
- package/src/home/__tests__/rollup-producer.test.ts +398 -0
- package/src/home/assistant-feed-authoring.ts +124 -0
- package/src/home/emit-feed-event.ts +158 -0
- package/src/home/feed-scheduler.ts +247 -0
- package/src/home/feed-types.ts +181 -0
- package/src/home/feed-writer.ts +469 -0
- package/src/home/platform-gmail-digest.ts +163 -0
- package/src/home/progress-formula.ts +86 -0
- package/src/home/relationship-state-writer.ts +824 -0
- package/src/home/relationship-state.ts +143 -0
- package/src/home/rollup-producer.ts +384 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +12 -3
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/cli-client.ts +151 -0
- package/src/ipc/cli-server.ts +234 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/index.ts +5 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
- package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/app-store.ts +1 -1
- package/src/memory/attachments-store.ts +70 -0
- package/src/memory/auto-analysis-enqueue.ts +127 -0
- package/src/memory/auto-analysis-guard.ts +27 -0
- package/src/memory/cleanup-schedule-state.ts +37 -0
- package/src/memory/conversation-analyze-job.ts +73 -0
- package/src/memory/conversation-crud.ts +99 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +34 -2
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/db-init.ts +6 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/graph/conversation-graph-memory.ts +15 -0
- package/src/memory/graph/extraction.test.ts +23 -0
- package/src/memory/graph/extraction.ts +8 -0
- package/src/memory/graph/retriever.ts +27 -18
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/group-crud.ts +6 -1
- package/src/memory/indexer.ts +95 -16
- package/src/memory/job-handlers/cleanup.ts +11 -8
- package/src/memory/job-handlers/conversation-starters.ts +16 -10
- package/src/memory/jobs-store.ts +64 -4
- package/src/memory/jobs-worker.ts +22 -9
- package/src/memory/llm-usage-store.ts +92 -56
- package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
- package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/oauth.ts +3 -0
- package/src/memory/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/client.ts +57 -6
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +143 -38
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/decision-engine.ts +3 -3
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +1 -0
- package/src/oauth/byo-connection.test.ts +18 -1
- package/src/oauth/byo-connection.ts +3 -1
- package/src/oauth/connect-orchestrator.ts +2 -0
- package/src/oauth/connection-resolver.ts +6 -2
- package/src/oauth/connection.ts +2 -0
- package/src/oauth/oauth-store.ts +9 -0
- package/src/oauth/platform-connection.test.ts +98 -0
- package/src/oauth/platform-connection.ts +52 -31
- package/src/oauth/seed-providers.ts +7 -0
- package/src/permissions/checker.ts +16 -6
- package/src/permissions/defaults.ts +49 -1
- package/src/permissions/trust-store.ts +3 -3
- package/src/permissions/workspace-policy.ts +3 -0
- package/src/platform/client.test.ts +10 -0
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +126 -2
- package/src/prompts/system-prompt.ts +59 -18
- package/src/prompts/templates/BOOTSTRAP.md +5 -5
- package/src/prompts/templates/SOUL.md +3 -1
- package/src/prompts/templates/UPDATES.md +12 -0
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-format.ts +26 -9
- package/src/prompts/update-bulletin.ts +34 -23
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/anthropic/client.ts +157 -61
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +9 -1
- package/src/providers/model-catalog.ts +6 -0
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +474 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +502 -0
- package/src/providers/openrouter/client.ts +101 -4
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +14 -3
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
- package/src/providers/speech-to-text/deepgram.test.ts +332 -0
- package/src/providers/speech-to-text/deepgram.ts +115 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
- package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
- package/src/providers/speech-to-text/google-gemini.ts +101 -0
- package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
- package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
- package/src/providers/speech-to-text/openai-whisper.ts +63 -33
- package/src/providers/speech-to-text/provider-catalog.ts +306 -0
- package/src/providers/speech-to-text/resolve.ts +386 -6
- package/src/providers/types.ts +9 -0
- package/src/runtime/AGENTS.md +43 -1
- package/src/runtime/__tests__/agent-wake.test.ts +831 -0
- package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
- package/src/runtime/agent-wake.ts +512 -0
- package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
- package/src/runtime/auth/route-policy.ts +30 -5
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/capability-tokens.ts +10 -10
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-invite-transports/email.ts +14 -6
- package/src/runtime/channel-readiness-service.ts +12 -22
- package/src/runtime/chrome-extension-registry.ts +38 -2
- package/src/runtime/http-server.ts +395 -10
- package/src/runtime/http-types.ts +6 -2
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/migration-transport.ts +1 -0
- package/src/runtime/migrations/migration-wizard.ts +1 -0
- package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
- package/src/runtime/migrations/vbundle-importer.ts +34 -0
- package/src/runtime/pending-interactions.ts +0 -11
- package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
- package/src/runtime/routes/app-management-routes.ts +12 -18
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
- package/src/runtime/routes/btw-routes.ts +8 -6
- package/src/runtime/routes/contact-routes.test.ts +298 -0
- package/src/runtime/routes/contact-routes.ts +132 -5
- package/src/runtime/routes/conversation-analysis-routes.ts +22 -142
- package/src/runtime/routes/conversation-management-routes.ts +115 -0
- package/src/runtime/routes/conversation-routes.ts +367 -146
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/home-feed-routes.ts +334 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +3 -14
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +3 -17
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
- package/src/runtime/routes/integrations/slack/channel.ts +11 -3
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +303 -0
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/migration-routes.ts +40 -5
- package/src/runtime/routes/settings-routes.ts +22 -5
- package/src/runtime/routes/skills-routes.ts +76 -7
- package/src/runtime/routes/stt-routes.ts +233 -0
- package/src/runtime/routes/surface-action-routes.ts +41 -2
- package/src/runtime/routes/tts-routes.ts +108 -24
- package/src/runtime/routes/usage-routes.ts +30 -2
- package/src/runtime/routes/user-route-dispatcher.ts +50 -5
- package/src/runtime/routes/user-routes.ts +13 -1
- package/src/runtime/routes/work-items-routes.ts +8 -1
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
- package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
- package/src/runtime/services/analyze-conversation.ts +344 -0
- package/src/runtime/services/analyze-deps-singleton.ts +32 -0
- package/src/runtime/services/auto-analysis-prompt.ts +55 -0
- package/src/runtime/skill-route-registry.ts +49 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +50 -0
- package/src/security/oauth2.ts +26 -4
- package/src/security/secure-keys.ts +25 -2
- package/src/security/token-manager.ts +8 -0
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-files.ts +64 -2
- package/src/skills/category-inference.ts +122 -0
- package/src/skills/clawhub-files.ts +213 -0
- package/src/skills/clawhub.ts +84 -23
- package/src/skills/skill-file-provider.ts +40 -0
- package/src/skills/skillssh-files.ts +395 -0
- package/src/skills/skillssh-registry.ts +4 -4
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +195 -0
- package/src/stt/stt-stream-session.ts +499 -0
- package/src/stt/types.ts +330 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +38 -14
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
- package/src/tools/browser/browser-execution.ts +1163 -23
- package/src/tools/browser/browser-manager.ts +45 -0
- package/src/tools/browser/browser-mode-constants.ts +12 -0
- package/src/tools/browser/browser-mode.ts +92 -0
- package/src/tools/browser/browser-status-constants.ts +33 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +393 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +183 -17
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
- package/src/tools/browser/cdp-client/errors.ts +15 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
- package/src/tools/browser/cdp-client/factory.ts +797 -87
- package/src/tools/browser/cdp-client/index.ts +16 -2
- package/src/tools/browser/cdp-client/types.ts +68 -0
- package/src/tools/credentials/vault.ts +35 -6
- package/src/tools/network/web-fetch.ts +5 -2
- package/src/tools/network/web-search.ts +5 -2
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +2 -0
- package/src/tools/skills/sandbox-runner.ts +3 -2
- package/src/tools/terminal/safe-env.ts +10 -2
- package/src/tools/terminal/shell.ts +15 -4
- package/src/tools/tool-manifest.ts +21 -0
- package/src/tools/types.ts +17 -0
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tts/__tests__/provider-adapters.test.ts +834 -0
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
- package/src/tts/__tests__/provider-catalog.test.ts +183 -0
- package/src/tts/__tests__/provider-registry.test.ts +90 -0
- package/src/tts/provider-catalog.ts +201 -0
- package/src/tts/provider-registry.ts +73 -0
- package/src/tts/providers/deepgram-provider.ts +219 -0
- package/src/tts/providers/elevenlabs-provider.ts +211 -0
- package/src/tts/providers/fish-audio-provider.ts +183 -0
- package/src/tts/providers/index.ts +42 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +153 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/util/abort-reasons.ts +58 -0
- package/src/util/device-id.ts +32 -16
- package/src/util/errors.ts +9 -1
- package/src/util/platform.ts +54 -10
- package/src/util/pricing.ts +66 -3
- package/src/util/spawn.ts +1 -1
- package/src/util/truncate.ts +4 -2
- package/src/util/unicode.ts +201 -0
- package/src/version.ts +19 -24
- package/src/watcher/engine.ts +23 -0
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/migrations/003-seed-device-id.ts +9 -3
- package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
- package/src/workspace/migrations/029-seed-pkb.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +317 -0
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
- package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
- package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
- package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/top-level-renderer.ts +13 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/cli/commands/browser-relay.ts +0 -466
- package/src/email/guardrails.ts +0 -221
- package/src/email/provider.ts +0 -117
- package/src/email/providers/agentmail.ts +0 -361
- package/src/email/providers/index.ts +0 -65
- package/src/email/service.ts +0 -384
- package/src/email/types.ts +0 -126
- package/src/prompts/templates/USER.md +0 -13
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/runtime/routes/browser-cdp-routes.ts +0 -229
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
+
import { SttServiceSchema } from "./stt.js";
|
|
4
|
+
import { TtsServiceSchema } from "./tts.js";
|
|
5
|
+
|
|
3
6
|
export const ServiceModeSchema = z.enum(["managed", "your-own"]);
|
|
4
7
|
export type ServiceMode = z.infer<typeof ServiceModeSchema>;
|
|
5
8
|
|
|
@@ -66,6 +69,16 @@ export const GitHubOAuthServiceSchema = BaseServiceSchema.extend({
|
|
|
66
69
|
});
|
|
67
70
|
export type GitHubOAuthService = z.infer<typeof GitHubOAuthServiceSchema>;
|
|
68
71
|
|
|
72
|
+
export const NotionOAuthServiceSchema = BaseServiceSchema.extend({
|
|
73
|
+
mode: ServiceModeSchema.default("your-own"),
|
|
74
|
+
});
|
|
75
|
+
export type NotionOAuthService = z.infer<typeof NotionOAuthServiceSchema>;
|
|
76
|
+
|
|
77
|
+
export const TwitterOAuthServiceSchema = BaseServiceSchema.extend({
|
|
78
|
+
mode: ServiceModeSchema.default("your-own"),
|
|
79
|
+
});
|
|
80
|
+
export type TwitterOAuthService = z.infer<typeof TwitterOAuthServiceSchema>;
|
|
81
|
+
|
|
69
82
|
export const ServicesSchema = z.object({
|
|
70
83
|
inference: InferenceServiceSchema.default(InferenceServiceSchema.parse({})),
|
|
71
84
|
"image-generation": ImageGenerationServiceSchema.default(
|
|
@@ -74,6 +87,12 @@ export const ServicesSchema = z.object({
|
|
|
74
87
|
"web-search": WebSearchServiceSchema.default(
|
|
75
88
|
WebSearchServiceSchema.parse({}),
|
|
76
89
|
),
|
|
90
|
+
stt: SttServiceSchema.default({
|
|
91
|
+
mode: "your-own" as const,
|
|
92
|
+
provider: "deepgram" as const,
|
|
93
|
+
providers: {},
|
|
94
|
+
}),
|
|
95
|
+
tts: TtsServiceSchema.default(TtsServiceSchema.parse({})),
|
|
77
96
|
"google-oauth": GoogleOAuthServiceSchema.default(
|
|
78
97
|
GoogleOAuthServiceSchema.parse({}),
|
|
79
98
|
),
|
|
@@ -86,5 +105,30 @@ export const ServicesSchema = z.object({
|
|
|
86
105
|
"github-oauth": GitHubOAuthServiceSchema.default(
|
|
87
106
|
GitHubOAuthServiceSchema.parse({}),
|
|
88
107
|
),
|
|
108
|
+
"notion-oauth": NotionOAuthServiceSchema.default(
|
|
109
|
+
NotionOAuthServiceSchema.parse({}),
|
|
110
|
+
),
|
|
111
|
+
"twitter-oauth": TwitterOAuthServiceSchema.default(
|
|
112
|
+
TwitterOAuthServiceSchema.parse({}),
|
|
113
|
+
),
|
|
89
114
|
});
|
|
90
115
|
export type Services = z.infer<typeof ServicesSchema>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Safely read the `mode` of a `services.*` entry.
|
|
119
|
+
*
|
|
120
|
+
* Most service entries (OAuth providers, inference, etc.) extend
|
|
121
|
+
* `BaseServiceSchema` and therefore carry a `mode: "managed" | "your-own"`
|
|
122
|
+
* field.
|
|
123
|
+
*
|
|
124
|
+
* Returns `undefined` when the requested service entry has no `mode` field,
|
|
125
|
+
* so callers can treat those entries as implicitly "your-own" without the
|
|
126
|
+
* compiler tripping on a union widened by non-BaseService members.
|
|
127
|
+
*/
|
|
128
|
+
export function getServiceMode(
|
|
129
|
+
services: Services,
|
|
130
|
+
key: keyof Services,
|
|
131
|
+
): ServiceMode | undefined {
|
|
132
|
+
const entry = services[key] as { mode?: ServiceMode };
|
|
133
|
+
return entry.mode;
|
|
134
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Valid STT provider identifiers. New providers append here and register
|
|
5
|
+
* an adapter.
|
|
6
|
+
*/
|
|
7
|
+
export const VALID_STT_PROVIDERS = [
|
|
8
|
+
"deepgram",
|
|
9
|
+
"google-gemini",
|
|
10
|
+
"openai-whisper",
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Sparse provider config map under `services.stt.providers`.
|
|
15
|
+
*
|
|
16
|
+
* This is a forward-compatible record that accepts any provider ID as key
|
|
17
|
+
* with an object value. All provider entries — known (`openai-whisper`,
|
|
18
|
+
* `deepgram`, `google-gemini`) and unknown — are accepted with generic object
|
|
19
|
+
* validation. Adding a new provider ID does not require a migration to seed
|
|
20
|
+
* `services.stt.providers.<id>`.
|
|
21
|
+
*
|
|
22
|
+
* The map only holds entries the user has explicitly configured — it is
|
|
23
|
+
* NOT required to enumerate every known provider.
|
|
24
|
+
*/
|
|
25
|
+
export const SttProvidersSchema = z.record(
|
|
26
|
+
z.string(),
|
|
27
|
+
z.record(z.string(), z.unknown()).default({}),
|
|
28
|
+
);
|
|
29
|
+
export type SttProviders = z.infer<typeof SttProvidersSchema>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Canonical STT service configuration.
|
|
33
|
+
*
|
|
34
|
+
* `mode` is locked to `"your-own"` -- managed STT is not supported.
|
|
35
|
+
* Attempting to set `mode: "managed"` will fail schema validation.
|
|
36
|
+
*/
|
|
37
|
+
export const SttServiceSchema = z
|
|
38
|
+
.object({
|
|
39
|
+
mode: z
|
|
40
|
+
.literal("your-own", {
|
|
41
|
+
error:
|
|
42
|
+
'services.stt.mode must be "your-own" -- managed STT is not supported',
|
|
43
|
+
})
|
|
44
|
+
.default("your-own" as const)
|
|
45
|
+
.describe(
|
|
46
|
+
'STT service mode -- only "your-own" is supported (managed STT is not available)',
|
|
47
|
+
),
|
|
48
|
+
provider: z
|
|
49
|
+
.enum(VALID_STT_PROVIDERS, {
|
|
50
|
+
error: `services.stt.provider must be one of: ${VALID_STT_PROVIDERS.join(", ")}`,
|
|
51
|
+
})
|
|
52
|
+
.describe("Active STT provider used for speech-to-text transcription"),
|
|
53
|
+
providers: SttProvidersSchema.default({}),
|
|
54
|
+
})
|
|
55
|
+
.describe(
|
|
56
|
+
"Speech-to-text service configuration -- provider selection and per-provider settings",
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export type SttService = z.infer<typeof SttServiceSchema>;
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { listCatalogProviderIds } from "../../tts/provider-catalog.js";
|
|
4
|
+
import type { TtsProviderId } from "../../tts/types.js";
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_ELEVENLABS_VOICE_ID,
|
|
7
|
+
VALID_CONVERSATION_TIMEOUTS,
|
|
8
|
+
} from "./elevenlabs.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Valid TTS provider identifiers derived from the canonical provider catalog.
|
|
12
|
+
*
|
|
13
|
+
* Adding a new TTS provider starts in `provider-catalog.ts` — the IDs flow
|
|
14
|
+
* here automatically.
|
|
15
|
+
*/
|
|
16
|
+
export const VALID_TTS_PROVIDERS: readonly [string, ...string[]] =
|
|
17
|
+
listCatalogProviderIds() as [TtsProviderId, ...TtsProviderId[]];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Per-provider config schemas nested under `services.tts.providers.<id>`.
|
|
21
|
+
*
|
|
22
|
+
* Each provider's schema is the full provider-specific config (voice ID,
|
|
23
|
+
* model overrides, tuning params, etc.). These are identical to the
|
|
24
|
+
* legacy top-level schemas (`elevenlabs.*`, `fishAudio.*`) so that
|
|
25
|
+
* migration can copy values 1:1.
|
|
26
|
+
*/
|
|
27
|
+
export const TtsElevenLabsProviderConfigSchema = z
|
|
28
|
+
.object({
|
|
29
|
+
voiceId: z
|
|
30
|
+
.string({
|
|
31
|
+
error: "services.tts.providers.elevenlabs.voiceId must be a string",
|
|
32
|
+
})
|
|
33
|
+
.transform((v) => v || DEFAULT_ELEVENLABS_VOICE_ID)
|
|
34
|
+
.default(DEFAULT_ELEVENLABS_VOICE_ID)
|
|
35
|
+
.describe("ElevenLabs voice ID for text-to-speech"),
|
|
36
|
+
voiceModelId: z
|
|
37
|
+
.string({
|
|
38
|
+
error:
|
|
39
|
+
"services.tts.providers.elevenlabs.voiceModelId must be a string",
|
|
40
|
+
})
|
|
41
|
+
.default("")
|
|
42
|
+
.describe(
|
|
43
|
+
"ElevenLabs model ID override (leave empty to use the default model)",
|
|
44
|
+
),
|
|
45
|
+
speed: z
|
|
46
|
+
.number({
|
|
47
|
+
error: "services.tts.providers.elevenlabs.speed must be a number",
|
|
48
|
+
})
|
|
49
|
+
.min(0.7, "services.tts.providers.elevenlabs.speed must be >= 0.7")
|
|
50
|
+
.max(1.2, "services.tts.providers.elevenlabs.speed must be <= 1.2")
|
|
51
|
+
.default(1.0)
|
|
52
|
+
.describe(
|
|
53
|
+
"Speech playback speed multiplier (0.7 = slower, 1.2 = faster)",
|
|
54
|
+
),
|
|
55
|
+
stability: z
|
|
56
|
+
.number({
|
|
57
|
+
error: "services.tts.providers.elevenlabs.stability must be a number",
|
|
58
|
+
})
|
|
59
|
+
.min(0, "services.tts.providers.elevenlabs.stability must be >= 0")
|
|
60
|
+
.max(1, "services.tts.providers.elevenlabs.stability must be <= 1")
|
|
61
|
+
.default(0.5)
|
|
62
|
+
.describe(
|
|
63
|
+
"Voice stability — higher values produce more consistent speech, lower values add expressiveness",
|
|
64
|
+
),
|
|
65
|
+
similarityBoost: z
|
|
66
|
+
.number({
|
|
67
|
+
error:
|
|
68
|
+
"services.tts.providers.elevenlabs.similarityBoost must be a number",
|
|
69
|
+
})
|
|
70
|
+
.min(0, "services.tts.providers.elevenlabs.similarityBoost must be >= 0")
|
|
71
|
+
.max(1, "services.tts.providers.elevenlabs.similarityBoost must be <= 1")
|
|
72
|
+
.default(0.75)
|
|
73
|
+
.describe(
|
|
74
|
+
"How closely the output matches the original voice — higher values increase similarity",
|
|
75
|
+
),
|
|
76
|
+
conversationTimeoutSeconds: z
|
|
77
|
+
.number({
|
|
78
|
+
error:
|
|
79
|
+
"services.tts.providers.elevenlabs.conversationTimeoutSeconds must be a number",
|
|
80
|
+
})
|
|
81
|
+
.refine(
|
|
82
|
+
(v) =>
|
|
83
|
+
VALID_CONVERSATION_TIMEOUTS.includes(
|
|
84
|
+
v as (typeof VALID_CONVERSATION_TIMEOUTS)[number],
|
|
85
|
+
),
|
|
86
|
+
{
|
|
87
|
+
message: `services.tts.providers.elevenlabs.conversationTimeoutSeconds must be one of: ${VALID_CONVERSATION_TIMEOUTS.join(", ")}`,
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
.default(30)
|
|
91
|
+
.describe("Seconds of silence before voice conversation auto-ends"),
|
|
92
|
+
})
|
|
93
|
+
.describe("ElevenLabs provider configuration under services.tts");
|
|
94
|
+
|
|
95
|
+
export type TtsElevenLabsProviderConfig = z.infer<
|
|
96
|
+
typeof TtsElevenLabsProviderConfigSchema
|
|
97
|
+
>;
|
|
98
|
+
|
|
99
|
+
export const TtsFishAudioProviderConfigSchema = z
|
|
100
|
+
.object({
|
|
101
|
+
referenceId: z
|
|
102
|
+
.string({
|
|
103
|
+
error: "services.tts.providers.fish-audio.referenceId must be a string",
|
|
104
|
+
})
|
|
105
|
+
.default("")
|
|
106
|
+
.describe("Fish Audio voice/clone reference ID"),
|
|
107
|
+
chunkLength: z
|
|
108
|
+
.number({
|
|
109
|
+
error: "services.tts.providers.fish-audio.chunkLength must be a number",
|
|
110
|
+
})
|
|
111
|
+
.int("services.tts.providers.fish-audio.chunkLength must be an integer")
|
|
112
|
+
.min(100, "services.tts.providers.fish-audio.chunkLength must be >= 100")
|
|
113
|
+
.max(300, "services.tts.providers.fish-audio.chunkLength must be <= 300")
|
|
114
|
+
.default(200)
|
|
115
|
+
.describe("Text chunk size for streaming synthesis"),
|
|
116
|
+
format: z
|
|
117
|
+
.enum(["mp3", "wav", "opus"], {
|
|
118
|
+
error:
|
|
119
|
+
"services.tts.providers.fish-audio.format must be one of: mp3, wav, opus",
|
|
120
|
+
})
|
|
121
|
+
.default("mp3")
|
|
122
|
+
.describe("Output audio format"),
|
|
123
|
+
latency: z
|
|
124
|
+
.enum(["normal", "balanced"], {
|
|
125
|
+
error:
|
|
126
|
+
"services.tts.providers.fish-audio.latency must be one of: normal, balanced",
|
|
127
|
+
})
|
|
128
|
+
.default("normal")
|
|
129
|
+
.describe(
|
|
130
|
+
"Latency/quality tradeoff for Fish Audio S2 synthesis. 'normal' prioritizes lower latency; 'balanced' trades latency for higher quality.",
|
|
131
|
+
),
|
|
132
|
+
speed: z
|
|
133
|
+
.number({
|
|
134
|
+
error: "services.tts.providers.fish-audio.speed must be a number",
|
|
135
|
+
})
|
|
136
|
+
.min(0.5, "services.tts.providers.fish-audio.speed must be >= 0.5")
|
|
137
|
+
.max(2.0, "services.tts.providers.fish-audio.speed must be <= 2.0")
|
|
138
|
+
.default(1.0)
|
|
139
|
+
.describe("Playback speed multiplier (0.5 = slower, 2.0 = faster)"),
|
|
140
|
+
})
|
|
141
|
+
.describe("Fish Audio provider configuration under services.tts");
|
|
142
|
+
|
|
143
|
+
export type TtsFishAudioProviderConfig = z.infer<
|
|
144
|
+
typeof TtsFishAudioProviderConfigSchema
|
|
145
|
+
>;
|
|
146
|
+
|
|
147
|
+
export const TtsDeepgramProviderConfigSchema = z
|
|
148
|
+
.object({
|
|
149
|
+
model: z
|
|
150
|
+
.string({
|
|
151
|
+
error: "services.tts.providers.deepgram.model must be a string",
|
|
152
|
+
})
|
|
153
|
+
.transform((v) => v || "aura-asteria-en")
|
|
154
|
+
.default("aura-asteria-en")
|
|
155
|
+
.describe("Deepgram TTS model identifier"),
|
|
156
|
+
format: z
|
|
157
|
+
.enum(["mp3", "wav", "opus"], {
|
|
158
|
+
error:
|
|
159
|
+
"services.tts.providers.deepgram.format must be one of: mp3, wav, opus",
|
|
160
|
+
})
|
|
161
|
+
.default("mp3")
|
|
162
|
+
.describe("Output audio format for call/runtime playback"),
|
|
163
|
+
})
|
|
164
|
+
.describe("Deepgram provider configuration under services.tts");
|
|
165
|
+
|
|
166
|
+
export type TtsDeepgramProviderConfig = z.infer<
|
|
167
|
+
typeof TtsDeepgramProviderConfigSchema
|
|
168
|
+
>;
|
|
169
|
+
|
|
170
|
+
export const TtsProvidersSchema = z.object({
|
|
171
|
+
elevenlabs: TtsElevenLabsProviderConfigSchema.default(
|
|
172
|
+
TtsElevenLabsProviderConfigSchema.parse({}),
|
|
173
|
+
),
|
|
174
|
+
"fish-audio": TtsFishAudioProviderConfigSchema.default(
|
|
175
|
+
TtsFishAudioProviderConfigSchema.parse({}),
|
|
176
|
+
),
|
|
177
|
+
deepgram: TtsDeepgramProviderConfigSchema.default(
|
|
178
|
+
TtsDeepgramProviderConfigSchema.parse({}),
|
|
179
|
+
),
|
|
180
|
+
});
|
|
181
|
+
export type TtsProviders = z.infer<typeof TtsProvidersSchema>;
|
|
182
|
+
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
// Catalog-completeness guard
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
// Ensures every provider in the catalog has a corresponding key in
|
|
187
|
+
// TtsProvidersSchema. If a new provider is added to the catalog without a
|
|
188
|
+
// schema entry, this fires at module-load time so the oversight is caught
|
|
189
|
+
// immediately rather than at runtime when a user selects the provider.
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
const schemaKeys = new Set(Object.keys(TtsProvidersSchema.shape));
|
|
192
|
+
for (const id of VALID_TTS_PROVIDERS) {
|
|
193
|
+
if (!schemaKeys.has(id)) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`TTS provider "${id}" exists in the catalog but has no schema entry ` +
|
|
196
|
+
`in TtsProvidersSchema. Add a "services.tts.providers.${id}" schema.`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Canonical TTS service configuration.
|
|
203
|
+
*
|
|
204
|
+
* `mode` is locked to `"your-own"` — managed TTS is not supported.
|
|
205
|
+
* Attempting to set `mode: "managed"` will fail schema validation.
|
|
206
|
+
*/
|
|
207
|
+
export const TtsServiceSchema = z
|
|
208
|
+
.object({
|
|
209
|
+
mode: z
|
|
210
|
+
.literal("your-own", {
|
|
211
|
+
error:
|
|
212
|
+
'services.tts.mode must be "your-own" — managed TTS is not supported',
|
|
213
|
+
})
|
|
214
|
+
.default("your-own" as const)
|
|
215
|
+
.describe(
|
|
216
|
+
'TTS service mode — only "your-own" is supported (managed TTS is not available)',
|
|
217
|
+
),
|
|
218
|
+
provider: z
|
|
219
|
+
.enum(VALID_TTS_PROVIDERS, {
|
|
220
|
+
error: `services.tts.provider must be one of: ${VALID_TTS_PROVIDERS.join(", ")}`,
|
|
221
|
+
})
|
|
222
|
+
.default("elevenlabs")
|
|
223
|
+
.describe("Active TTS provider used for speech synthesis"),
|
|
224
|
+
providers: TtsProvidersSchema.default(TtsProvidersSchema.parse({})),
|
|
225
|
+
})
|
|
226
|
+
.describe(
|
|
227
|
+
"Text-to-speech service configuration — provider selection and per-provider settings",
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
export type TtsService = z.infer<typeof TtsServiceSchema>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const UpdatesConfigSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
enabled: z
|
|
6
|
+
.boolean({ error: "updates.enabled must be a boolean" })
|
|
7
|
+
.default(true)
|
|
8
|
+
.describe(
|
|
9
|
+
"Whether the release update bulletin (UPDATES.md) is materialized into the workspace on daemon startup",
|
|
10
|
+
),
|
|
11
|
+
})
|
|
12
|
+
.describe("Release update bulletin configuration");
|
|
13
|
+
|
|
14
|
+
export type UpdatesConfig = z.infer<typeof UpdatesConfigSchema>;
|
package/src/config/skills.ts
CHANGED
|
@@ -784,6 +784,8 @@ export function loadSkillCatalog(
|
|
|
784
784
|
toolManifest: detectToolManifest(directory),
|
|
785
785
|
includes: parsed.includes,
|
|
786
786
|
featureFlag: parsed.featureFlag,
|
|
787
|
+
activationHints: parsed.activationHints,
|
|
788
|
+
avoidWhen: parsed.avoidWhen,
|
|
787
789
|
inlineCommandExpansions: parsed.inlineCommandExpansions,
|
|
788
790
|
});
|
|
789
791
|
} catch (err) {
|
|
@@ -879,6 +881,8 @@ export function loadSkillCatalog(
|
|
|
879
881
|
toolManifest: detectToolManifest(directory),
|
|
880
882
|
includes: parsed.includes,
|
|
881
883
|
featureFlag: parsed.featureFlag,
|
|
884
|
+
activationHints: parsed.activationHints,
|
|
885
|
+
avoidWhen: parsed.avoidWhen,
|
|
882
886
|
inlineCommandExpansions: parsed.inlineCommandExpansions,
|
|
883
887
|
};
|
|
884
888
|
|
package/src/config/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { and, asc, desc, eq, like, sql } from "drizzle-orm";
|
|
1
|
+
import { and, asc, desc, eq, isNotNull, like, sql } from "drizzle-orm";
|
|
2
2
|
import { v4 as uuid } from "uuid";
|
|
3
3
|
|
|
4
4
|
import { getDb } from "../memory/db.js";
|
|
@@ -29,16 +29,27 @@ function escapeLike(value: string): string {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* Pure slug transform applied to a display name. No DB lookup, no collision
|
|
33
|
+
* handling — callers that need a collision-free filename should use
|
|
34
|
+
* `generateUserFileSlug` instead. Exported so the migration classifier can
|
|
35
|
+
* recompute the expected base slug for a given display name.
|
|
34
36
|
*/
|
|
35
|
-
export function
|
|
36
|
-
|
|
37
|
+
export function computeUserFileBaseSlug(displayName: string): string {
|
|
38
|
+
return (
|
|
37
39
|
displayName
|
|
38
40
|
.toLowerCase()
|
|
39
41
|
.replace(/[^a-z0-9]+/g, "-")
|
|
40
42
|
.replace(/^-+|-+$/g, "")
|
|
41
|
-
.slice(0, 100) || "user"
|
|
43
|
+
.slice(0, 100) || "user"
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Generate a collision-free slugified filename for a contact's per-user persona file.
|
|
49
|
+
* Produces filenames like "alice.md", "alice-2.md", "alice-3.md", etc.
|
|
50
|
+
*/
|
|
51
|
+
export function generateUserFileSlug(displayName: string): string {
|
|
52
|
+
const slug = computeUserFileBaseSlug(displayName);
|
|
42
53
|
|
|
43
54
|
const db = getDb();
|
|
44
55
|
const rows = db
|
|
@@ -273,10 +284,27 @@ export function upsertContact(params: {
|
|
|
273
284
|
|
|
274
285
|
// Create new contact
|
|
275
286
|
contactId = contactId ?? uuid();
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
287
|
+
// Sibling contacts sharing a principal_id must share a user_file so every
|
|
288
|
+
// channel for one principal resolves to the same persona + journal slug.
|
|
289
|
+
let resolvedUserFile: string | null;
|
|
290
|
+
if (params.userFile !== undefined) {
|
|
291
|
+
resolvedUserFile = params.userFile;
|
|
292
|
+
} else if (params.principalId) {
|
|
293
|
+
const sibling = db
|
|
294
|
+
.select({ userFile: contacts.userFile })
|
|
295
|
+
.from(contacts)
|
|
296
|
+
.where(
|
|
297
|
+
and(
|
|
298
|
+
eq(contacts.principalId, params.principalId),
|
|
299
|
+
isNotNull(contacts.userFile),
|
|
300
|
+
),
|
|
301
|
+
)
|
|
302
|
+
.get();
|
|
303
|
+
resolvedUserFile =
|
|
304
|
+
sibling?.userFile ?? generateUserFileSlug(params.displayName);
|
|
305
|
+
} else {
|
|
306
|
+
resolvedUserFile = generateUserFileSlug(params.displayName);
|
|
307
|
+
}
|
|
280
308
|
db.insert(contacts)
|
|
281
309
|
.values({
|
|
282
310
|
id: contactId,
|
|
@@ -285,7 +313,7 @@ export function upsertContact(params: {
|
|
|
285
313
|
role: params.role ?? "contact",
|
|
286
314
|
contactType: params.contactType ?? "human",
|
|
287
315
|
principalId: params.principalId ?? null,
|
|
288
|
-
userFile:
|
|
316
|
+
userFile: resolvedUserFile,
|
|
289
317
|
createdAt: now,
|
|
290
318
|
updatedAt: now,
|
|
291
319
|
})
|
|
@@ -811,6 +839,23 @@ export function findContactChannel(params: {
|
|
|
811
839
|
return null;
|
|
812
840
|
}
|
|
813
841
|
|
|
842
|
+
/**
|
|
843
|
+
* Find the guardian contact regardless of channel.
|
|
844
|
+
* Returns the first contact with role='guardian', or null if none exists.
|
|
845
|
+
*/
|
|
846
|
+
export function findGuardianContact(): ContactWithChannels | null {
|
|
847
|
+
const db = getDb();
|
|
848
|
+
const row = db
|
|
849
|
+
.select()
|
|
850
|
+
.from(contacts)
|
|
851
|
+
.where(eq(contacts.role, "guardian"))
|
|
852
|
+
.orderBy(asc(contacts.createdAt))
|
|
853
|
+
.limit(1)
|
|
854
|
+
.get();
|
|
855
|
+
if (!row) return null;
|
|
856
|
+
return withChannels(parseContact(row));
|
|
857
|
+
}
|
|
858
|
+
|
|
814
859
|
/**
|
|
815
860
|
* Find the guardian contact and their specific channel entry for a given channel type.
|
|
816
861
|
* This is the contacts-based equivalent of getGuardianBinding(assistantId, channel).
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
import type { ChannelId } from "../channels/types.js";
|
|
10
10
|
import type { GuardianBinding } from "../memory/channel-verification-sessions.js";
|
|
11
|
+
import { clearCache as clearTrustCache } from "../permissions/trust-store.js";
|
|
12
|
+
import { ensureGuardianPersonaFile } from "../prompts/persona-resolver.js";
|
|
11
13
|
import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
|
|
12
14
|
import { getLogger } from "../util/logger.js";
|
|
13
15
|
import { emitContactChange } from "./contact-events.js";
|
|
@@ -76,7 +78,7 @@ export function createGuardianBinding(params: {
|
|
|
76
78
|
parseDisplayNameFromMetadata(params.metadataJson) ??
|
|
77
79
|
params.guardianExternalUserId;
|
|
78
80
|
|
|
79
|
-
upsertContact({
|
|
81
|
+
const contact = upsertContact({
|
|
80
82
|
displayName,
|
|
81
83
|
role: "guardian",
|
|
82
84
|
notes: "guardian",
|
|
@@ -94,6 +96,35 @@ export function createGuardianBinding(params: {
|
|
|
94
96
|
],
|
|
95
97
|
});
|
|
96
98
|
|
|
99
|
+
// Seed the per-user persona file so downstream readers (journaling,
|
|
100
|
+
// persona resolution) can rely on `users/<slug>.md` existing on disk.
|
|
101
|
+
// Idempotent: pre-existing customized files are preserved.
|
|
102
|
+
//
|
|
103
|
+
// Seeding is restricted to the guardian-creation path only — it must
|
|
104
|
+
// NOT run from inbound-message upsertContactChannel calls, since the
|
|
105
|
+
// `users/` directory watcher would fire on every new contact and
|
|
106
|
+
// evict live conversations.
|
|
107
|
+
if (contact.userFile) {
|
|
108
|
+
// Tolerate filesystem failures (read-only or full workspace) so a
|
|
109
|
+
// disk error doesn't leave the DB commit orphaned. The persona file
|
|
110
|
+
// can be reseeded later; failing the binding here would be worse.
|
|
111
|
+
try {
|
|
112
|
+
ensureGuardianPersonaFile(contact.userFile);
|
|
113
|
+
} catch (err) {
|
|
114
|
+
log.warn(
|
|
115
|
+
{ err, userFile: contact.userFile },
|
|
116
|
+
"failed to seed guardian persona file; continuing",
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
// Invalidate the trust rule cache so the dynamic guardian-persona
|
|
120
|
+
// auto-allow rules from `permissions/defaults.ts` are backfilled on
|
|
121
|
+
// the next `getRules()` call. Without this, guardians created at
|
|
122
|
+
// runtime (self-heal paths, first-message-seeds-guardian) wouldn't
|
|
123
|
+
// get their auto-allow rule until the daemon restarts, and the
|
|
124
|
+
// model would prompt on its first `file_edit users/<slug>.md`.
|
|
125
|
+
clearTrustCache();
|
|
126
|
+
}
|
|
127
|
+
|
|
97
128
|
const now = Date.now();
|
|
98
129
|
const result: GuardianBinding = {
|
|
99
130
|
id: `contact-binding-${params.channel}`,
|
|
@@ -210,6 +241,12 @@ export function upsertContactChannel(params: {
|
|
|
210
241
|
reassignConflictingChannels: !!params.contactId,
|
|
211
242
|
});
|
|
212
243
|
|
|
244
|
+
// NOTE: We intentionally do NOT seed `users/<slug>.md` here. This is the
|
|
245
|
+
// inbound-message hot path — every new contact (Slack, phone, email, etc)
|
|
246
|
+
// would otherwise fire the `users/` directory watcher in
|
|
247
|
+
// config-watcher.ts and evict live conversations. Persona-file seeding
|
|
248
|
+
// is the sole responsibility of `createGuardianBinding`.
|
|
249
|
+
|
|
213
250
|
const contactResult = findContactChannel({
|
|
214
251
|
channelType: params.sourceChannel,
|
|
215
252
|
externalUserId: canonicalId ?? undefined,
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
ToolResultContent,
|
|
9
9
|
ToolUseContent,
|
|
10
10
|
} from "../providers/types.js";
|
|
11
|
+
import { safeStringSlice } from "../util/unicode.js";
|
|
11
12
|
|
|
12
13
|
/** Minimum content length (chars) before a tool result is eligible for truncation. ~2000 tokens at 4 chars/token. */
|
|
13
14
|
export const THRESHOLD_CHARS = 8_000;
|
|
@@ -43,8 +44,8 @@ export function buildTruncatedContent(
|
|
|
43
44
|
filePath: string,
|
|
44
45
|
): string {
|
|
45
46
|
const half = Math.floor(TARGET_CHARS / 2);
|
|
46
|
-
const prefix = original
|
|
47
|
-
const suffix = original.
|
|
47
|
+
const prefix = safeStringSlice(original, 0, half);
|
|
48
|
+
const suffix = safeStringSlice(original, original.length - half, original.length);
|
|
48
49
|
const omittedChars = original.length - TARGET_CHARS;
|
|
49
50
|
const estimatedTokens = Math.round(omittedChars / 4);
|
|
50
51
|
return `${prefix}\n\n...(${estimatedTokens} tokens omitted ${TRUNCATION_MARKER} ${filePath})\n\n${suffix}`;
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
Message,
|
|
4
4
|
ToolResultContent,
|
|
5
5
|
} from "../providers/types.js";
|
|
6
|
+
import { safeStringSlice } from "../util/unicode.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Maximum share of the context window that a single tool result may occupy.
|
|
@@ -53,7 +54,7 @@ export function truncateToolResultText(text: string, maxChars: number): string {
|
|
|
53
54
|
return text;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
return text
|
|
57
|
+
return safeStringSlice(text, 0, sliceEnd) + TRUNCATION_SUFFIX;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/**
|