@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
|
@@ -3,6 +3,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
3
3
|
import {
|
|
4
4
|
appendReleaseBlock,
|
|
5
5
|
extractReleaseIds,
|
|
6
|
+
filterNewContentBlocks,
|
|
6
7
|
hasReleaseBlock,
|
|
7
8
|
releaseMarker,
|
|
8
9
|
} from "../prompts/update-bulletin-format.js";
|
|
@@ -83,6 +84,64 @@ describe("appendReleaseBlock", () => {
|
|
|
83
84
|
});
|
|
84
85
|
});
|
|
85
86
|
|
|
87
|
+
describe("filterNewContentBlocks", () => {
|
|
88
|
+
const blockA = [
|
|
89
|
+
"<!-- vellum-update-release:entry-a -->",
|
|
90
|
+
"## Entry A",
|
|
91
|
+
"Content for A.",
|
|
92
|
+
"<!-- /vellum-update-release:entry-a -->",
|
|
93
|
+
].join("\n");
|
|
94
|
+
|
|
95
|
+
const blockB = [
|
|
96
|
+
"<!-- vellum-update-release:entry-b -->",
|
|
97
|
+
"## Entry B",
|
|
98
|
+
"Content for B.",
|
|
99
|
+
"<!-- /vellum-update-release:entry-b -->",
|
|
100
|
+
].join("\n");
|
|
101
|
+
|
|
102
|
+
const blockC = [
|
|
103
|
+
"<!-- vellum-update-release:entry-c -->",
|
|
104
|
+
"## Entry C",
|
|
105
|
+
"Content for C.",
|
|
106
|
+
"<!-- /vellum-update-release:entry-c -->",
|
|
107
|
+
].join("\n");
|
|
108
|
+
|
|
109
|
+
test("returns body unchanged when no block structure exists", () => {
|
|
110
|
+
const body = "## What's New\n\nPlain text notes.\n";
|
|
111
|
+
expect(filterNewContentBlocks(body, "anything")).toBe(body);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("returns all blocks when none are present in existing content", () => {
|
|
115
|
+
const body = `${blockA}\n\n${blockB}`;
|
|
116
|
+
const result = filterNewContentBlocks(body, "no markers here");
|
|
117
|
+
expect(result).toContain("entry-a");
|
|
118
|
+
expect(result).toContain("entry-b");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("returns empty string when all blocks are already present", () => {
|
|
122
|
+
const body = `${blockA}\n\n${blockB}`;
|
|
123
|
+
const existing = `<!-- vellum-update-release:0.9.0 -->\n${blockA}\n\n${blockB}\n`;
|
|
124
|
+
expect(filterNewContentBlocks(body, existing)).toBe("");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("returns only new blocks when some are already present", () => {
|
|
128
|
+
const body = `${blockA}\n\n${blockB}\n\n${blockC}`;
|
|
129
|
+
const existing = `<!-- vellum-update-release:0.9.0 -->\n${blockA}\n\n${blockB}\n`;
|
|
130
|
+
|
|
131
|
+
const result = filterNewContentBlocks(body, existing);
|
|
132
|
+
expect(result).toContain("entry-c");
|
|
133
|
+
expect(result).toContain("Content for C.");
|
|
134
|
+
expect(result).not.toContain("entry-a");
|
|
135
|
+
expect(result).not.toContain("entry-b");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("handles single-block template", () => {
|
|
139
|
+
const result = filterNewContentBlocks(blockA, "no markers");
|
|
140
|
+
expect(result).toContain("entry-a");
|
|
141
|
+
expect(result).toContain("Content for A.");
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
86
145
|
describe("extractReleaseIds", () => {
|
|
87
146
|
test("returns all version strings from multiple markers", () => {
|
|
88
147
|
const content = [
|
|
@@ -31,6 +31,13 @@ mock.module("../memory/checkpoints.js", () => ({
|
|
|
31
31
|
),
|
|
32
32
|
}));
|
|
33
33
|
|
|
34
|
+
// --- Mutable config stub for updates.enabled tests ---
|
|
35
|
+
const updatesConfig = { enabled: true };
|
|
36
|
+
|
|
37
|
+
mock.module("../config/loader.js", () => ({
|
|
38
|
+
getConfig: () => ({ updates: updatesConfig }),
|
|
39
|
+
}));
|
|
40
|
+
|
|
34
41
|
// --- Temp directory for template files ---
|
|
35
42
|
// Avoids mutating the real source-controlled UPDATES.md template, preventing
|
|
36
43
|
// race conditions with parallel test execution and working tree corruption
|
|
@@ -60,6 +67,7 @@ const COMMENT_ONLY_TEMPLATE =
|
|
|
60
67
|
describe("syncUpdateBulletinOnStartup", () => {
|
|
61
68
|
beforeEach(() => {
|
|
62
69
|
store.clear();
|
|
70
|
+
updatesConfig.enabled = true;
|
|
63
71
|
// Remove any leftover workspace UPDATES.md from a previous test
|
|
64
72
|
if (existsSync(workspacePath)) {
|
|
65
73
|
rmSync(workspacePath);
|
|
@@ -92,6 +100,18 @@ describe("syncUpdateBulletinOnStartup", () => {
|
|
|
92
100
|
expect(content).toContain("What's New");
|
|
93
101
|
});
|
|
94
102
|
|
|
103
|
+
it("skips materialization entirely when updates.enabled is false", () => {
|
|
104
|
+
updatesConfig.enabled = false;
|
|
105
|
+
expect(existsSync(workspacePath)).toBe(false);
|
|
106
|
+
|
|
107
|
+
syncUpdateBulletinOnStartup();
|
|
108
|
+
|
|
109
|
+
expect(existsSync(workspacePath)).toBe(false);
|
|
110
|
+
// No checkpoint writes should have happened either.
|
|
111
|
+
expect(store.get("updates:active_releases")).toBeUndefined();
|
|
112
|
+
expect(store.get("updates:completed_releases")).toBeUndefined();
|
|
113
|
+
});
|
|
114
|
+
|
|
95
115
|
it("appends release block when workspace file exists without current marker", () => {
|
|
96
116
|
const preExisting =
|
|
97
117
|
"<!-- vellum-update-release:0.9.0 -->\nOld release notes.\n";
|
|
@@ -133,28 +153,34 @@ describe("syncUpdateBulletinOnStartup", () => {
|
|
|
133
153
|
});
|
|
134
154
|
|
|
135
155
|
it("marks active releases as completed when UPDATES.md is deleted", () => {
|
|
136
|
-
// Pre-populate active releases
|
|
137
|
-
|
|
156
|
+
// Pre-populate active releases including the current one — simulates
|
|
157
|
+
// a normal session where 1.0.0 was materialized alongside leftover
|
|
158
|
+
// entries from prior versions.
|
|
159
|
+
store.set(
|
|
160
|
+
"updates:active_releases",
|
|
161
|
+
JSON.stringify(["0.8.0", "0.9.0", "1.0.0"]),
|
|
162
|
+
);
|
|
138
163
|
|
|
139
164
|
// Workspace file does not exist — simulates the assistant having deleted it
|
|
140
165
|
expect(existsSync(workspacePath)).toBe(false);
|
|
141
166
|
|
|
142
167
|
syncUpdateBulletinOnStartup();
|
|
143
168
|
|
|
144
|
-
// Active set should be cleared
|
|
169
|
+
// Active set should be cleared
|
|
145
170
|
const activeRaw = store.get("updates:active_releases");
|
|
146
171
|
expect(activeRaw).toBeDefined();
|
|
147
172
|
const active: string[] = JSON.parse(activeRaw!);
|
|
148
|
-
// The old releases should not be in the active set
|
|
149
173
|
expect(active).not.toContain("0.8.0");
|
|
150
174
|
expect(active).not.toContain("0.9.0");
|
|
175
|
+
expect(active).not.toContain("1.0.0");
|
|
151
176
|
|
|
152
|
-
//
|
|
177
|
+
// All releases should now be completed
|
|
153
178
|
const completedRaw = store.get("updates:completed_releases");
|
|
154
179
|
expect(completedRaw).toBeDefined();
|
|
155
180
|
const completed: string[] = JSON.parse(completedRaw!);
|
|
156
181
|
expect(completed).toContain("0.8.0");
|
|
157
182
|
expect(completed).toContain("0.9.0");
|
|
183
|
+
expect(completed).toContain("1.0.0");
|
|
158
184
|
});
|
|
159
185
|
|
|
160
186
|
it("does not recreate completed release after deletion", () => {
|
|
@@ -173,6 +199,82 @@ describe("syncUpdateBulletinOnStartup", () => {
|
|
|
173
199
|
expect(existsSync(workspacePath)).toBe(false);
|
|
174
200
|
});
|
|
175
201
|
|
|
202
|
+
it("treats an empty UPDATES.md as dismissal of the current release", () => {
|
|
203
|
+
// Pre-populate active so we're past the fresh-install guard.
|
|
204
|
+
store.set("updates:active_releases", JSON.stringify(["1.0.0"]));
|
|
205
|
+
writeFileSync(workspacePath, "", "utf-8");
|
|
206
|
+
|
|
207
|
+
syncUpdateBulletinOnStartup();
|
|
208
|
+
|
|
209
|
+
// File should be left alone (still empty, not refilled).
|
|
210
|
+
expect(existsSync(workspacePath)).toBe(true);
|
|
211
|
+
expect(readFileSync(workspacePath, "utf-8")).toBe("");
|
|
212
|
+
|
|
213
|
+
const completed: string[] = JSON.parse(
|
|
214
|
+
store.get("updates:completed_releases")!,
|
|
215
|
+
);
|
|
216
|
+
expect(completed).toContain("1.0.0");
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("treats a whitespace-only UPDATES.md as dismissal of the current release", () => {
|
|
220
|
+
// Pre-populate active with the current release so the dismissal branch
|
|
221
|
+
// is scoped correctly to this version.
|
|
222
|
+
store.set("updates:active_releases", JSON.stringify(["1.0.0"]));
|
|
223
|
+
writeFileSync(workspacePath, " \n\n\t\n", "utf-8");
|
|
224
|
+
|
|
225
|
+
syncUpdateBulletinOnStartup();
|
|
226
|
+
|
|
227
|
+
// File should be left alone — content must not be re-appended.
|
|
228
|
+
const content = readFileSync(workspacePath, "utf-8");
|
|
229
|
+
expect(content).not.toContain("<!-- vellum-update-release:1.0.0 -->");
|
|
230
|
+
|
|
231
|
+
const completed: string[] = JSON.parse(
|
|
232
|
+
store.get("updates:completed_releases")!,
|
|
233
|
+
);
|
|
234
|
+
expect(completed).toContain("1.0.0");
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("materializes new version bulletin after a prior release was dismissed", () => {
|
|
238
|
+
// Verifies that a new version's bulletin is materialized even when a
|
|
239
|
+
// prior release exists in the completed set. Dismissal detection is
|
|
240
|
+
// scoped to the current release — only suppress if this version was
|
|
241
|
+
// already active or completed, not because an unrelated version was.
|
|
242
|
+
store.set("updates:completed_releases", JSON.stringify(["0.9.0"]));
|
|
243
|
+
expect(existsSync(workspacePath)).toBe(false);
|
|
244
|
+
|
|
245
|
+
syncUpdateBulletinOnStartup();
|
|
246
|
+
|
|
247
|
+
expect(existsSync(workspacePath)).toBe(true);
|
|
248
|
+
const content = readFileSync(workspacePath, "utf-8");
|
|
249
|
+
expect(content).toContain("<!-- vellum-update-release:1.0.0 -->");
|
|
250
|
+
expect(content).toContain("What's New");
|
|
251
|
+
|
|
252
|
+
// 1.0.0 must NOT have been auto-completed.
|
|
253
|
+
const completed: string[] = JSON.parse(
|
|
254
|
+
store.get("updates:completed_releases")!,
|
|
255
|
+
);
|
|
256
|
+
expect(completed).not.toContain("1.0.0");
|
|
257
|
+
|
|
258
|
+
// 1.0.0 should be in the active set.
|
|
259
|
+
const active: string[] = JSON.parse(store.get("updates:active_releases")!);
|
|
260
|
+
expect(active).toContain("1.0.0");
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("creates file on fresh install even though it is missing", () => {
|
|
264
|
+
// Both active and completed are empty — brand-new DB.
|
|
265
|
+
expect(store.get("updates:active_releases")).toBeUndefined();
|
|
266
|
+
expect(store.get("updates:completed_releases")).toBeUndefined();
|
|
267
|
+
expect(existsSync(workspacePath)).toBe(false);
|
|
268
|
+
|
|
269
|
+
syncUpdateBulletinOnStartup();
|
|
270
|
+
|
|
271
|
+
// Fresh install should materialize, not dismiss.
|
|
272
|
+
expect(existsSync(workspacePath)).toBe(true);
|
|
273
|
+
expect(readFileSync(workspacePath, "utf-8")).toContain(
|
|
274
|
+
"<!-- vellum-update-release:1.0.0 -->",
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
|
|
176
278
|
it("merges pending old block with new release block", () => {
|
|
177
279
|
// Pre-create workspace file with an old release block
|
|
178
280
|
const oldContent =
|
|
@@ -239,6 +341,105 @@ describe("syncUpdateBulletinOnStartup", () => {
|
|
|
239
341
|
expect(existsSync(workspacePath)).toBe(false);
|
|
240
342
|
});
|
|
241
343
|
|
|
344
|
+
it("only appends new content blocks on version bump with extended template", () => {
|
|
345
|
+
// Workspace already has entries A and B from a prior release
|
|
346
|
+
const oldContent = [
|
|
347
|
+
"<!-- vellum-update-release:0.9.0 -->",
|
|
348
|
+
"<!-- vellum-update-release:entry-a -->",
|
|
349
|
+
"## Entry A",
|
|
350
|
+
"Content for A.",
|
|
351
|
+
"<!-- /vellum-update-release:entry-a -->",
|
|
352
|
+
"",
|
|
353
|
+
"<!-- vellum-update-release:entry-b -->",
|
|
354
|
+
"## Entry B",
|
|
355
|
+
"Content for B.",
|
|
356
|
+
"<!-- /vellum-update-release:entry-b -->",
|
|
357
|
+
"",
|
|
358
|
+
].join("\n");
|
|
359
|
+
writeFileSync(workspacePath, oldContent, "utf-8");
|
|
360
|
+
|
|
361
|
+
// Template now has A, B, C — C is the only new entry
|
|
362
|
+
const extendedTemplate = [
|
|
363
|
+
"<!-- vellum-update-release:entry-a -->",
|
|
364
|
+
"## Entry A",
|
|
365
|
+
"Content for A.",
|
|
366
|
+
"<!-- /vellum-update-release:entry-a -->",
|
|
367
|
+
"",
|
|
368
|
+
"<!-- vellum-update-release:entry-b -->",
|
|
369
|
+
"## Entry B",
|
|
370
|
+
"Content for B.",
|
|
371
|
+
"<!-- /vellum-update-release:entry-b -->",
|
|
372
|
+
"",
|
|
373
|
+
"<!-- vellum-update-release:entry-c -->",
|
|
374
|
+
"## Entry C",
|
|
375
|
+
"New content for C.",
|
|
376
|
+
"<!-- /vellum-update-release:entry-c -->",
|
|
377
|
+
"",
|
|
378
|
+
].join("\n");
|
|
379
|
+
writeFileSync(
|
|
380
|
+
join(tempTemplateDir, "UPDATES.md"),
|
|
381
|
+
extendedTemplate,
|
|
382
|
+
"utf-8",
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
syncUpdateBulletinOnStartup();
|
|
386
|
+
|
|
387
|
+
const content = readFileSync(workspacePath, "utf-8");
|
|
388
|
+
|
|
389
|
+
// New release block should be present
|
|
390
|
+
expect(content).toContain("<!-- vellum-update-release:1.0.0 -->");
|
|
391
|
+
|
|
392
|
+
// Entry C should appear
|
|
393
|
+
expect(content).toContain("entry-c");
|
|
394
|
+
expect(content).toContain("New content for C.");
|
|
395
|
+
|
|
396
|
+
// Entries A and B should NOT be duplicated
|
|
397
|
+
const countA = (
|
|
398
|
+
content.match(/<!-- vellum-update-release:entry-a -->/g) || []
|
|
399
|
+
).length;
|
|
400
|
+
const countB = (
|
|
401
|
+
content.match(/<!-- vellum-update-release:entry-b -->/g) || []
|
|
402
|
+
).length;
|
|
403
|
+
expect(countA).toBe(1);
|
|
404
|
+
expect(countB).toBe(1);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it("skips append when all template content blocks already exist in workspace", () => {
|
|
408
|
+
// Workspace already has entries A and B from a prior release
|
|
409
|
+
const oldContent = [
|
|
410
|
+
"<!-- vellum-update-release:0.9.0 -->",
|
|
411
|
+
"<!-- vellum-update-release:entry-a -->",
|
|
412
|
+
"## Entry A",
|
|
413
|
+
"<!-- /vellum-update-release:entry-a -->",
|
|
414
|
+
"",
|
|
415
|
+
"<!-- vellum-update-release:entry-b -->",
|
|
416
|
+
"## Entry B",
|
|
417
|
+
"<!-- /vellum-update-release:entry-b -->",
|
|
418
|
+
"",
|
|
419
|
+
].join("\n");
|
|
420
|
+
writeFileSync(workspacePath, oldContent, "utf-8");
|
|
421
|
+
|
|
422
|
+
// Template has the same A and B — nothing new
|
|
423
|
+
const sameTemplate = [
|
|
424
|
+
"<!-- vellum-update-release:entry-a -->",
|
|
425
|
+
"## Entry A",
|
|
426
|
+
"<!-- /vellum-update-release:entry-a -->",
|
|
427
|
+
"",
|
|
428
|
+
"<!-- vellum-update-release:entry-b -->",
|
|
429
|
+
"## Entry B",
|
|
430
|
+
"<!-- /vellum-update-release:entry-b -->",
|
|
431
|
+
"",
|
|
432
|
+
].join("\n");
|
|
433
|
+
writeFileSync(join(tempTemplateDir, "UPDATES.md"), sameTemplate, "utf-8");
|
|
434
|
+
|
|
435
|
+
syncUpdateBulletinOnStartup();
|
|
436
|
+
|
|
437
|
+
const content = readFileSync(workspacePath, "utf-8");
|
|
438
|
+
|
|
439
|
+
// No 1.0.0 block should be added — all content already present
|
|
440
|
+
expect(content).not.toContain("<!-- vellum-update-release:1.0.0 -->");
|
|
441
|
+
});
|
|
442
|
+
|
|
242
443
|
it("preserves existing file when atomic write fails", () => {
|
|
243
444
|
const originalContent =
|
|
244
445
|
"<!-- vellum-update-release:0.9.0 -->\nOriginal content.\n";
|
|
@@ -202,11 +202,32 @@ describe("usage routes", () => {
|
|
|
202
202
|
// -- daily buckets --
|
|
203
203
|
|
|
204
204
|
describe("GET /v1/usage/daily", () => {
|
|
205
|
-
test("returns
|
|
206
|
-
const
|
|
205
|
+
test("returns zero-filled buckets when no events in range", async () => {
|
|
206
|
+
const from = new Date("2025-01-15T00:00:00Z").getTime();
|
|
207
|
+
const to = new Date("2025-01-17T23:59:59Z").getTime();
|
|
208
|
+
const res = await dispatch("GET", `usage/daily?from=${from}&to=${to}`);
|
|
207
209
|
expect(res.status).toBe(200);
|
|
208
|
-
const body = (await res.json()) as {
|
|
209
|
-
|
|
210
|
+
const body = (await res.json()) as {
|
|
211
|
+
buckets: Array<{
|
|
212
|
+
date: string;
|
|
213
|
+
eventCount: number;
|
|
214
|
+
totalInputTokens: number;
|
|
215
|
+
totalOutputTokens: number;
|
|
216
|
+
totalEstimatedCostUsd: number;
|
|
217
|
+
}>;
|
|
218
|
+
};
|
|
219
|
+
expect(body.buckets).toHaveLength(3);
|
|
220
|
+
expect(body.buckets.map((b) => b.date)).toEqual([
|
|
221
|
+
"2025-01-15",
|
|
222
|
+
"2025-01-16",
|
|
223
|
+
"2025-01-17",
|
|
224
|
+
]);
|
|
225
|
+
for (const bucket of body.buckets) {
|
|
226
|
+
expect(bucket.eventCount).toBe(0);
|
|
227
|
+
expect(bucket.totalInputTokens).toBe(0);
|
|
228
|
+
expect(bucket.totalOutputTokens).toBe(0);
|
|
229
|
+
expect(bucket.totalEstimatedCostUsd).toBe(0);
|
|
230
|
+
}
|
|
210
231
|
});
|
|
211
232
|
|
|
212
233
|
test("returns daily buckets for seeded data", async () => {
|
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Tests for user-reference resolvers. After the drop-user-md migration,
|
|
3
|
+
* `readPreferredNameFromUserMd` and `resolveUserPronouns` source their
|
|
4
|
+
* content from the guardian's per-user persona file via
|
|
5
|
+
* `resolveGuardianPersonaStrict()` (no `default.md` fallback). We mock
|
|
6
|
+
* the persona-resolver module directly so tests can drive the input
|
|
7
|
+
* content without touching disk.
|
|
8
|
+
*/
|
|
9
|
+
|
|
3
10
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
//
|
|
8
|
-
let
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
existsSync: (path: string) => {
|
|
14
|
-
if (path === join(TEST_DIR, "USER.md")) return mockFileExists;
|
|
15
|
-
return false;
|
|
16
|
-
},
|
|
17
|
-
readFileSync: (path: string, _encoding: string) => {
|
|
18
|
-
if (path === join(TEST_DIR, "USER.md") && mockFileExists)
|
|
19
|
-
return mockFileContent;
|
|
20
|
-
throw new Error(`ENOENT: no such file: ${path}`);
|
|
21
|
-
},
|
|
12
|
+
// Mutable state the tests control — represents the value returned by
|
|
13
|
+
// `resolveGuardianPersonaStrict()` (comment-stripped string, or null
|
|
14
|
+
// when no guardian / empty / missing guardian-specific file).
|
|
15
|
+
let mockGuardianPersona: string | null = null;
|
|
16
|
+
|
|
17
|
+
mock.module("../prompts/persona-resolver.js", () => ({
|
|
18
|
+
resolveGuardianPersona: () => mockGuardianPersona,
|
|
19
|
+
resolveGuardianPersonaStrict: () => mockGuardianPersona,
|
|
22
20
|
}));
|
|
23
21
|
|
|
24
|
-
// Import after mocks are in place
|
|
22
|
+
// Import after mocks are in place so the module under test binds to
|
|
23
|
+
// the stubbed implementation.
|
|
25
24
|
const {
|
|
26
25
|
resolveUserReference,
|
|
27
26
|
resolveUserPronouns,
|
|
@@ -31,18 +30,16 @@ const {
|
|
|
31
30
|
|
|
32
31
|
describe("resolveUserReference", () => {
|
|
33
32
|
beforeEach(() => {
|
|
34
|
-
|
|
35
|
-
mockFileContent = "";
|
|
33
|
+
mockGuardianPersona = null;
|
|
36
34
|
});
|
|
37
35
|
|
|
38
|
-
test('returns "my human" when
|
|
39
|
-
|
|
36
|
+
test('returns "my human" when no guardian persona exists', () => {
|
|
37
|
+
mockGuardianPersona = null;
|
|
40
38
|
expect(resolveUserReference()).toBe("my human");
|
|
41
39
|
});
|
|
42
40
|
|
|
43
41
|
test('returns "my human" when preferred name field is empty', () => {
|
|
44
|
-
|
|
45
|
-
mockFileContent = [
|
|
42
|
+
mockGuardianPersona = [
|
|
46
43
|
"## Onboarding Snapshot",
|
|
47
44
|
"",
|
|
48
45
|
"- Preferred name/reference:",
|
|
@@ -53,8 +50,7 @@ describe("resolveUserReference", () => {
|
|
|
53
50
|
});
|
|
54
51
|
|
|
55
52
|
test("returns the configured name when it is set", () => {
|
|
56
|
-
|
|
57
|
-
mockFileContent = [
|
|
53
|
+
mockGuardianPersona = [
|
|
58
54
|
"## Onboarding Snapshot",
|
|
59
55
|
"",
|
|
60
56
|
"- Preferred name/reference: John",
|
|
@@ -65,27 +61,24 @@ describe("resolveUserReference", () => {
|
|
|
65
61
|
});
|
|
66
62
|
|
|
67
63
|
test("trims whitespace around the configured name", () => {
|
|
68
|
-
|
|
69
|
-
mockFileContent = "- Preferred name/reference: Alice \n";
|
|
64
|
+
mockGuardianPersona = "- Preferred name/reference: Alice \n";
|
|
70
65
|
expect(resolveUserReference()).toBe("Alice");
|
|
71
66
|
});
|
|
72
67
|
});
|
|
73
68
|
|
|
74
69
|
describe("resolveUserPronouns", () => {
|
|
75
70
|
beforeEach(() => {
|
|
76
|
-
|
|
77
|
-
mockFileContent = "";
|
|
71
|
+
mockGuardianPersona = null;
|
|
78
72
|
});
|
|
79
73
|
|
|
80
|
-
test("returns null when
|
|
81
|
-
|
|
74
|
+
test("returns null when no guardian persona exists", () => {
|
|
75
|
+
mockGuardianPersona = null;
|
|
82
76
|
expect(resolveUserPronouns()).toBeNull();
|
|
83
77
|
});
|
|
84
78
|
|
|
85
|
-
test("returns pronouns from flat
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"# USER.md",
|
|
79
|
+
test("returns pronouns from flat persona file (no Onboarding Snapshot)", () => {
|
|
80
|
+
mockGuardianPersona = [
|
|
81
|
+
"# User Profile",
|
|
89
82
|
"",
|
|
90
83
|
"- Preferred name/reference: Alice",
|
|
91
84
|
"- Pronouns: she/her",
|
|
@@ -95,9 +88,8 @@ describe("resolveUserPronouns", () => {
|
|
|
95
88
|
});
|
|
96
89
|
|
|
97
90
|
test("returns null when pronouns field is empty in flat format", () => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"# USER.md",
|
|
91
|
+
mockGuardianPersona = [
|
|
92
|
+
"# User Profile",
|
|
101
93
|
"",
|
|
102
94
|
"- Preferred name/reference: Alice",
|
|
103
95
|
"- Pronouns:",
|
|
@@ -107,8 +99,7 @@ describe("resolveUserPronouns", () => {
|
|
|
107
99
|
});
|
|
108
100
|
|
|
109
101
|
test("returns pronouns from legacy Onboarding Snapshot section", () => {
|
|
110
|
-
|
|
111
|
-
mockFileContent = [
|
|
102
|
+
mockGuardianPersona = [
|
|
112
103
|
"## Onboarding Snapshot",
|
|
113
104
|
"",
|
|
114
105
|
"- Pronouns: they/them",
|
|
@@ -117,8 +108,7 @@ describe("resolveUserPronouns", () => {
|
|
|
117
108
|
});
|
|
118
109
|
|
|
119
110
|
test("prefers pronouns above Onboarding Snapshot over inside it", () => {
|
|
120
|
-
|
|
121
|
-
mockFileContent = [
|
|
111
|
+
mockGuardianPersona = [
|
|
122
112
|
"Pronouns: he/him",
|
|
123
113
|
"",
|
|
124
114
|
"## Onboarding Snapshot",
|
|
@@ -129,8 +119,7 @@ describe("resolveUserPronouns", () => {
|
|
|
129
119
|
});
|
|
130
120
|
|
|
131
121
|
test("returns null for declined_by_user", () => {
|
|
132
|
-
|
|
133
|
-
mockFileContent = [
|
|
122
|
+
mockGuardianPersona = [
|
|
134
123
|
"- Preferred name/reference: Alice",
|
|
135
124
|
"- Pronouns: declined_by_user",
|
|
136
125
|
].join("\n");
|
|
@@ -138,8 +127,7 @@ describe("resolveUserPronouns", () => {
|
|
|
138
127
|
});
|
|
139
128
|
|
|
140
129
|
test("strips inferred: prefix", () => {
|
|
141
|
-
|
|
142
|
-
mockFileContent = [
|
|
130
|
+
mockGuardianPersona = [
|
|
143
131
|
"- Preferred name/reference: Alice",
|
|
144
132
|
"- Pronouns: inferred: she/her",
|
|
145
133
|
].join("\n");
|
|
@@ -149,13 +137,11 @@ describe("resolveUserPronouns", () => {
|
|
|
149
137
|
|
|
150
138
|
describe("resolveGuardianName", () => {
|
|
151
139
|
beforeEach(() => {
|
|
152
|
-
|
|
153
|
-
mockFileContent = "";
|
|
140
|
+
mockGuardianPersona = null;
|
|
154
141
|
});
|
|
155
142
|
|
|
156
|
-
test("returns
|
|
157
|
-
|
|
158
|
-
mockFileContent = [
|
|
143
|
+
test("returns persona name when present, ignoring guardianDisplayName", () => {
|
|
144
|
+
mockGuardianPersona = [
|
|
159
145
|
"## Onboarding Snapshot",
|
|
160
146
|
"",
|
|
161
147
|
"- Preferred name/reference: John",
|
|
@@ -163,9 +149,8 @@ describe("resolveGuardianName", () => {
|
|
|
163
149
|
expect(resolveGuardianName("Jane")).toBe("John");
|
|
164
150
|
});
|
|
165
151
|
|
|
166
|
-
test('returns "my human" when
|
|
167
|
-
|
|
168
|
-
mockFileContent = [
|
|
152
|
+
test('returns "my human" when persona explicitly sets name to default value', () => {
|
|
153
|
+
mockGuardianPersona = [
|
|
169
154
|
"## Onboarding Snapshot",
|
|
170
155
|
"",
|
|
171
156
|
"- Preferred name/reference: my human",
|
|
@@ -174,20 +159,20 @@ describe("resolveGuardianName", () => {
|
|
|
174
159
|
expect(resolveGuardianName("Jane")).toBe("my human");
|
|
175
160
|
});
|
|
176
161
|
|
|
177
|
-
test("falls back to guardianDisplayName when
|
|
178
|
-
|
|
162
|
+
test("falls back to guardianDisplayName when persona is empty", () => {
|
|
163
|
+
mockGuardianPersona = null;
|
|
179
164
|
expect(resolveGuardianName("Jane")).toBe("Jane");
|
|
180
165
|
});
|
|
181
166
|
|
|
182
167
|
test("falls back to DEFAULT_USER_REFERENCE when both are empty", () => {
|
|
183
|
-
|
|
168
|
+
mockGuardianPersona = null;
|
|
184
169
|
expect(resolveGuardianName()).toBe(DEFAULT_USER_REFERENCE);
|
|
185
170
|
expect(resolveGuardianName(null)).toBe(DEFAULT_USER_REFERENCE);
|
|
186
171
|
expect(resolveGuardianName("")).toBe(DEFAULT_USER_REFERENCE);
|
|
187
172
|
});
|
|
188
173
|
|
|
189
174
|
test("trims whitespace on guardianDisplayName fallback", () => {
|
|
190
|
-
|
|
175
|
+
mockGuardianPersona = null;
|
|
191
176
|
expect(resolveGuardianName(" Jane ")).toBe("Jane");
|
|
192
177
|
});
|
|
193
178
|
});
|
|
@@ -73,8 +73,12 @@ mock.module("../permissions/checker.js", () => ({
|
|
|
73
73
|
generateScopeOptions: () => [],
|
|
74
74
|
}));
|
|
75
75
|
|
|
76
|
+
// Mock every export so downstream test files that dynamically import modules
|
|
77
|
+
// with a static `from "../memory/tool-usage-store.js"` still see all symbols.
|
|
76
78
|
mock.module("../memory/tool-usage-store.js", () => ({
|
|
77
79
|
recordToolInvocation: () => {},
|
|
80
|
+
getRecentInvocations: () => [],
|
|
81
|
+
rotateToolInvocations: () => 0,
|
|
78
82
|
}));
|
|
79
83
|
|
|
80
84
|
mock.module("../tools/registry.js", () => ({
|