@vellumai/assistant 0.8.0 → 0.8.1
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/AGENTS.md +11 -0
- package/Dockerfile +5 -4
- package/README.md +2 -2
- package/docker-entrypoint.sh +16 -0
- package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
- package/eslint-rules/cli-no-daemon-internals.js +283 -0
- package/eslint.config.mjs +12 -0
- package/knip.json +2 -1
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/openapi.yaml +4847 -1698
- package/package.json +3 -1
- package/scripts/generate-openapi.ts +52 -4
- package/scripts/sync-llm-catalog.ts +165 -0
- package/scripts/sync-web-search-catalog.ts +107 -0
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
- package/src/__tests__/anthropic-provider.test.ts +92 -2
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/avatar-identity-sync.test.ts +87 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/call-site-routing-provider.test.ts +172 -45
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
- package/src/__tests__/channel-policy.test.ts +12 -0
- package/src/__tests__/checker.test.ts +89 -0
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
- package/src/__tests__/config-loader-backfill.test.ts +526 -102
- package/src/__tests__/config-loader-corrupt.test.ts +68 -0
- package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
- package/src/__tests__/config-schema-cmd.test.ts +63 -29
- package/src/__tests__/config-schema.test.ts +14 -3
- package/src/__tests__/config-set-platform-guard.test.ts +75 -152
- package/src/__tests__/config-set-route.test.ts +198 -0
- package/src/__tests__/config-watcher.test.ts +6 -0
- package/src/__tests__/contacts-tools.test.ts +51 -199
- package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
- package/src/__tests__/context-search-agent-runner.test.ts +22 -138
- package/src/__tests__/context-search-conversations-source.test.ts +42 -16
- package/src/__tests__/context-search-fanout.test.ts +20 -157
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
- package/src/__tests__/context-search-types.test.ts +7 -2
- package/src/__tests__/context-window-manager.test.ts +389 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
- package/src/__tests__/conversation-error.test.ts +38 -0
- package/src/__tests__/conversation-fork-crud.test.ts +241 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
- package/src/__tests__/conversation-lifecycle.test.ts +124 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
- package/src/__tests__/conversation-process-callsite.test.ts +21 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +4 -4
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -6
- package/src/__tests__/daemon-credential-client.test.ts +56 -1
- package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
- package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
- package/src/__tests__/db-proxy-transaction.test.ts +206 -0
- package/src/__tests__/external-plugin-loader.test.ts +458 -0
- package/src/__tests__/filing-service.test.ts +23 -3
- package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -8
- package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
- package/src/__tests__/heartbeat-service.test.ts +50 -233
- package/src/__tests__/history-repair.test.ts +89 -0
- package/src/__tests__/host-app-control-proxy.test.ts +109 -1
- package/src/__tests__/host-app-control-routes.test.ts +247 -1
- package/src/__tests__/host-browser-proxy.test.ts +416 -20
- package/src/__tests__/host-browser-routes.test.ts +325 -33
- package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
- package/src/__tests__/inference-profile-reaper.test.ts +154 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
- package/src/__tests__/install-skill-routing.test.ts +2 -2
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +15 -0
- package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
- package/src/__tests__/llm-catalog-parity.test.ts +146 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
- package/src/__tests__/llm-resolver.test.ts +46 -0
- package/src/__tests__/managed-profile-guard.test.ts +131 -2
- package/src/__tests__/mcp-auth-routes.test.ts +1 -0
- package/src/__tests__/mcp-cli.test.ts +182 -220
- package/src/__tests__/mcp-health-check.test.ts +56 -27
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
- package/src/__tests__/message-complete-display-id.test.ts +175 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -2009
- package/src/__tests__/oauth-commands-routes.test.ts +711 -0
- package/src/__tests__/oauth-connect-routes.test.ts +174 -11
- package/src/__tests__/oauth-providers-routes.test.ts +14 -10
- package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
- package/src/__tests__/openai-responses-provider.test.ts +17 -0
- package/src/__tests__/plugin-bootstrap.test.ts +31 -2
- package/src/__tests__/plugin-route-contribution.test.ts +31 -3
- package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
- package/src/__tests__/plugin-types.test.ts +13 -11
- package/src/__tests__/process-message-background-slack.test.ts +46 -0
- package/src/__tests__/profile-entry-status.test.ts +43 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
- package/src/__tests__/provider-registry-ollama.test.ts +12 -4
- package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
- package/src/__tests__/relay-server.test.ts +118 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
- package/src/__tests__/schedule-retry.test.ts +56 -4
- package/src/__tests__/schedule-routes.test.ts +104 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
- package/src/__tests__/scheduler-recurrence.test.ts +87 -34
- package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
- package/src/__tests__/scheduler-wake.test.ts +0 -63
- package/src/__tests__/secret-allowlist.test.ts +1 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
- package/src/__tests__/shell-credential-ref.test.ts +95 -3
- package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skill-load-tool.test.ts +2 -4
- package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +63 -0
- package/src/__tests__/task-scheduler.test.ts +88 -23
- package/src/__tests__/update-bulletin-job.test.ts +96 -193
- package/src/__tests__/usage-cli.test.ts +11 -73
- package/src/__tests__/user-plugin-loader.test.ts +145 -0
- package/src/__tests__/vercel-config.test.ts +168 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
- package/src/__tests__/web-search.test.ts +303 -2
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
- package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
- package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
- package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
- package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
- package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
- package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
- package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
- package/src/acp/__tests__/helpers/which-stub.ts +4 -2
- package/src/acp/resolve-agent.test.ts +25 -0
- package/src/acp/resolve-agent.ts +13 -2
- package/src/acp/session-manager.ts +14 -0
- package/src/approvals/guardian-request-resolvers.ts +32 -87
- package/src/calls/relay-server.ts +35 -0
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +23 -4
- package/src/channels/config.ts +14 -1
- package/src/channels/types.ts +1 -0
- package/src/cli/AGENTS.md +164 -4
- package/src/cli/__tests__/notifications.test.ts +54 -0
- package/src/cli/commands/__tests__/avatar.test.ts +540 -0
- package/src/cli/commands/__tests__/backup.test.ts +236 -776
- package/src/cli/commands/__tests__/cache.test.ts +1 -1
- package/src/cli/commands/__tests__/changelog.test.ts +593 -0
- package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
- package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
- package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
- package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
- package/src/cli/commands/__tests__/email-core.test.ts +579 -0
- package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
- package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
- package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
- package/src/cli/commands/__tests__/skills.test.ts +563 -0
- package/src/cli/commands/__tests__/status.test.ts +249 -0
- package/src/cli/commands/__tests__/stt.test.ts +320 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
- package/src/cli/commands/__tests__/tts.test.ts +321 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
- package/src/cli/commands/attachment.ts +8 -3
- package/src/cli/commands/audit.ts +95 -64
- package/src/cli/commands/auth.ts +61 -58
- package/src/cli/commands/avatar.ts +276 -390
- package/src/cli/commands/backup.ts +409 -505
- package/src/cli/commands/bash.ts +9 -5
- package/src/cli/commands/browser.ts +28 -9
- package/src/cli/commands/cache.ts +9 -4
- package/src/cli/commands/changelog.ts +414 -0
- package/src/cli/commands/channel-verification-sessions.ts +238 -317
- package/src/cli/commands/clients.ts +8 -3
- package/src/cli/commands/completions.ts +9 -9
- package/src/cli/commands/config.ts +102 -72
- package/src/cli/commands/contacts.ts +575 -696
- package/src/cli/commands/conversations-defer.ts +17 -69
- package/src/cli/commands/conversations-import.ts +90 -253
- package/src/cli/commands/conversations.ts +346 -436
- package/src/cli/commands/credential-execution.ts +9 -6
- package/src/cli/commands/credentials.ts +456 -736
- package/src/cli/commands/domain.ts +128 -206
- package/src/cli/commands/email.ts +606 -794
- package/src/cli/commands/gateway.ts +8 -1
- package/src/cli/commands/image-generation.ts +157 -205
- package/src/cli/commands/inference-providers.ts +352 -0
- package/src/cli/commands/inference-session.ts +415 -0
- package/src/cli/commands/inference.ts +87 -65
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.ts +103 -287
- package/src/cli/commands/memory-v2.ts +162 -516
- package/src/cli/commands/notifications.ts +33 -7
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +176 -297
- package/src/cli/commands/oauth/disconnect.ts +16 -215
- package/src/cli/commands/oauth/index.ts +49 -45
- package/src/cli/commands/oauth/mode.ts +43 -199
- package/src/cli/commands/oauth/ping.ts +17 -125
- package/src/cli/commands/oauth/providers.ts +732 -921
- package/src/cli/commands/oauth/request.ts +60 -350
- package/src/cli/commands/oauth/shared.ts +11 -121
- package/src/cli/commands/oauth/status.ts +31 -121
- package/src/cli/commands/oauth/token.ts +13 -55
- package/src/cli/commands/pending.ts +19 -10
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
- package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
- package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
- package/src/cli/commands/platform/connect.ts +16 -80
- package/src/cli/commands/platform/disconnect.ts +14 -112
- package/src/cli/commands/platform/index.ts +177 -246
- package/src/cli/commands/routes.ts +153 -336
- package/src/cli/commands/sequence.ts +316 -360
- package/src/cli/commands/skills.ts +449 -671
- package/src/cli/commands/status.ts +58 -37
- package/src/cli/commands/stt.ts +94 -262
- package/src/cli/commands/task.ts +14 -40
- package/src/cli/commands/trust.ts +8 -3
- package/src/cli/commands/tts.ts +162 -167
- package/src/cli/commands/ui.ts +35 -42
- package/src/cli/commands/usage.ts +188 -126
- package/src/cli/commands/watchers.ts +8 -3
- package/src/cli/commands/webhooks.ts +99 -193
- package/src/cli/lib/__tests__/register-command.test.ts +85 -0
- package/src/cli/lib/daemon-credential-client.ts +4 -5
- package/src/cli/lib/nested-value.ts +44 -0
- package/src/cli/lib/open-browser.ts +36 -0
- package/src/cli/lib/register-command.ts +19 -0
- package/src/cli/lib/time-ago.ts +34 -0
- package/src/cli/program.ts +2 -4
- package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
- package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
- package/src/cli/utils/conversation-id.ts +30 -0
- package/src/cli/utils/parse-duration.ts +41 -0
- package/src/config/acp-defaults.test.ts +5 -1
- package/src/config/acp-defaults.ts +11 -4
- package/src/config/bundled-skills/acp/TOOLS.json +2 -2
- package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
- package/src/config/bundled-skills/contacts/SKILL.md +12 -45
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
- package/src/config/bundled-tool-registry.ts +0 -2
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +76 -14
- package/src/config/raw-config-utils.ts +2 -30
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
- package/src/config/schemas/call-site-catalog.ts +29 -7
- package/src/config/schemas/llm-request-logs.ts +57 -0
- package/src/config/schemas/llm.ts +52 -2
- package/src/config/schemas/memory-retrospective.ts +48 -0
- package/src/config/schemas/memory-v2.ts +32 -1
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +15 -12
- package/src/config/seed-inference-profiles.ts +195 -134
- package/src/contacts/contact-store.ts +0 -61
- package/src/context/window-manager.ts +191 -5
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +79 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
- package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
- package/src/daemon/approval-generators.ts +23 -29
- package/src/daemon/config-watcher.ts +2 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
- package/src/daemon/conversation-agent-loop.ts +127 -97
- package/src/daemon/conversation-error.ts +21 -0
- package/src/daemon/conversation-lifecycle.ts +46 -5
- package/src/daemon/conversation-process.ts +36 -19
- package/src/daemon/conversation-runtime-assembly.ts +14 -5
- package/src/daemon/conversation-slash.ts +175 -23
- package/src/daemon/conversation-store.ts +17 -10
- package/src/daemon/conversation-surfaces.ts +76 -12
- package/src/daemon/conversation-tool-setup.ts +24 -14
- package/src/daemon/conversation.ts +48 -9
- package/src/daemon/external-plugins-bootstrap.ts +18 -8
- package/src/daemon/guardian-action-generators.ts +7 -22
- package/src/daemon/handlers/config-model.ts +8 -126
- package/src/daemon/handlers/config-slack-channel.ts +10 -7
- package/src/daemon/handlers/config-vercel.ts +3 -1
- package/src/daemon/handlers/skills.ts +84 -5
- package/src/daemon/history-repair.ts +33 -6
- package/src/daemon/host-app-control-proxy.ts +44 -19
- package/src/daemon/host-bash-proxy.ts +85 -158
- package/src/daemon/host-browser-proxy.ts +96 -35
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +42 -43
- package/src/daemon/meet-host-supervisor.ts +15 -15
- package/src/daemon/memory-v2-startup.ts +9 -2
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/bookmarks.ts +18 -0
- package/src/daemon/message-types/conversations.ts +12 -9
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/sync.ts +60 -0
- package/src/daemon/pkb-reminder-builder.test.ts +54 -13
- package/src/daemon/pkb-reminder-builder.ts +21 -7
- package/src/daemon/process-message.ts +56 -23
- package/src/daemon/server.ts +23 -18
- package/src/daemon/shutdown-handlers.ts +0 -2
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/daemon/tool-side-effects.ts +6 -4
- package/src/daemon/wake-target-adapter.ts +11 -0
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +40 -53
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +148 -127
- package/src/home/__tests__/feed-types.test.ts +63 -131
- package/src/home/__tests__/feed-writer.test.ts +77 -278
- package/src/home/__tests__/post-connect-feed.test.ts +9 -12
- package/src/home/feed-types.ts +19 -73
- package/src/home/feed-writer.ts +25 -156
- package/src/home/post-connect-feed.ts +1 -3
- package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
- package/src/ipc/__tests__/email-ipc.test.ts +506 -0
- package/src/ipc/__tests__/exit-helper.test.ts +104 -0
- package/src/ipc/__tests__/streaming-client.test.ts +237 -0
- package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
- package/src/ipc/assistant-server.ts +55 -6
- package/src/ipc/cli-client.ts +370 -50
- package/src/ipc/routes/db-proxy-transaction.ts +151 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
- package/src/ipc/skill-routes/events.ts +30 -3
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
- package/src/live-voice/live-voice-session-manager.ts +11 -4
- package/src/live-voice/live-voice-session.ts +14 -6
- package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
- package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
- package/src/memory/__tests__/conversation-types.test.ts +36 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
- package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
- package/src/memory/bookmark-crud.ts +179 -0
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
- package/src/memory/context-search/agent-protocol.ts +5 -1
- package/src/memory/context-search/agent-runner.ts +60 -85
- package/src/memory/context-search/limits.ts +1 -4
- package/src/memory/context-search/search.ts +23 -113
- package/src/memory/context-search/sources/conversations.ts +18 -6
- package/src/memory/context-search/sources/memory-v2.ts +39 -14
- package/src/memory/context-search/sources/memory.ts +7 -0
- package/src/memory/context-search/sources/workspace.ts +13 -10
- package/src/memory/context-search/types.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +11 -0
- package/src/memory/conversation-crud.ts +312 -10
- package/src/memory/conversation-queries.ts +9 -5
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/conversation-types.ts +16 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +2 -1
- package/src/memory/embedding-runtime-manager.ts +1 -2
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +76 -5
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/tool-handlers.ts +17 -7
- package/src/memory/graph/tools.ts +44 -5
- package/src/memory/indexer.ts +17 -0
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +13 -15
- package/src/memory/jobs/embed-concept-page.ts +45 -9
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +52 -3
- package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
- package/src/memory/llm-request-log-source-local.ts +26 -0
- package/src/memory/llm-request-log-source.ts +97 -0
- package/src/memory/llm-request-log-store.ts +1 -1
- package/src/memory/memory-retrospective-constants.ts +13 -0
- package/src/memory/memory-retrospective-enqueue.ts +114 -0
- package/src/memory/memory-retrospective-job.ts +351 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
- package/src/memory/memory-retrospective-state.ts +162 -0
- package/src/memory/memory-retrospective-trigger-check.ts +91 -0
- package/src/memory/memory-v2-activation-log-store.ts +49 -5
- package/src/memory/memory-v2-concept-frequency.ts +4 -0
- package/src/memory/message-content.ts +38 -1
- package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
- package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
- package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
- package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
- package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
- package/src/memory/migrations/242-message-bookmarks.ts +38 -0
- package/src/memory/migrations/243-provider-connections.ts +68 -0
- package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
- package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
- package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
- package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
- package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
- package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/schema/bookmarks.ts +38 -0
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/inference.ts +29 -0
- package/src/memory/schema/memory-core.ts +9 -0
- package/src/memory/search/semantic.ts +1 -4
- package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
- package/src/memory/v2/__tests__/activation.test.ts +11 -4
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
- package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
- package/src/memory/v2/__tests__/injection.test.ts +628 -10
- package/src/memory/v2/__tests__/migration.test.ts +7 -3
- package/src/memory/v2/__tests__/page-index.test.ts +277 -0
- package/src/memory/v2/__tests__/page-store.test.ts +14 -1
- package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +72 -0
- package/src/memory/v2/__tests__/reranker.test.ts +4 -4
- package/src/memory/v2/__tests__/router.test.ts +516 -0
- package/src/memory/v2/__tests__/sim.test.ts +45 -1
- package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
- package/src/memory/v2/__tests__/static-context.test.ts +7 -22
- package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
- package/src/memory/v2/activation-store.ts +34 -5
- package/src/memory/v2/activation.ts +40 -27
- package/src/memory/v2/backfill-jobs.ts +17 -84
- package/src/memory/v2/consolidation-job.ts +85 -78
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +440 -109
- package/src/memory/v2/migration.ts +117 -20
- package/src/memory/v2/page-index.ts +191 -0
- package/src/memory/v2/page-store.ts +3 -0
- package/src/memory/v2/prompts/consolidation.ts +9 -7
- package/src/memory/v2/prompts/router.ts +192 -0
- package/src/memory/v2/qdrant.ts +100 -87
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +322 -0
- package/src/memory/v2/sim.ts +25 -12
- package/src/memory/v2/skill-store.ts +118 -29
- package/src/memory/v2/static-context.ts +16 -9
- package/src/memory/v2/sweep-job.ts +122 -96
- package/src/memory/v2/types.ts +10 -6
- package/src/memory/validation.ts +13 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
- package/src/notifications/__tests__/signal-registry.test.ts +17 -0
- package/src/notifications/adapters/platform.ts +171 -0
- package/src/notifications/conversation-pairing.ts +2 -2
- package/src/notifications/copy-composer.ts +15 -0
- package/src/notifications/destination-resolver.ts +21 -0
- package/src/notifications/emit-signal.ts +28 -1
- package/src/notifications/home-feed-side-effect.ts +111 -0
- package/src/notifications/signal.ts +5 -0
- package/src/permissions/checker.ts +12 -0
- package/src/permissions/ipc-risk-types.ts +2 -0
- package/src/plugin-api/index.ts +13 -0
- package/src/plugin-api/package.json +12 -0
- package/src/plugin-api/types.ts +62 -0
- package/src/plugins/defaults/injectors.ts +19 -3
- package/src/plugins/external-plugin-loader.ts +294 -0
- package/src/plugins/types.ts +46 -30
- package/src/plugins/user-loader.ts +64 -41
- package/src/proactive-artifact/job.test.ts +12 -4
- package/src/proactive-artifact/job.ts +4 -0
- package/src/proactive-artifact/trigger-state.test.ts +9 -0
- package/src/proactive-artifact/trigger-state.ts +4 -0
- package/src/prompts/__tests__/system-prompt.test.ts +105 -0
- package/src/prompts/system-prompt.ts +22 -1
- package/src/prompts/update-bulletin-job.ts +61 -73
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
- package/src/providers/__tests__/inference.test.ts +288 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +14 -32
- package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
- package/src/providers/anthropic/client.ts +95 -26
- package/src/providers/call-site-routing.ts +94 -16
- package/src/providers/connection-resolution.ts +163 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
- package/src/providers/inference/adapter-factory.ts +173 -0
- package/src/providers/inference/auth.ts +112 -0
- package/src/providers/inference/backfill.ts +196 -0
- package/src/providers/inference/connections.ts +356 -0
- package/src/providers/inference/resolve-auth.ts +65 -0
- package/src/providers/model-catalog.ts +104 -6
- package/src/providers/openai/responses-provider.ts +4 -2
- package/src/providers/provider-env-vars.ts +17 -7
- package/src/providers/provider-secret-catalog.ts +49 -30
- package/src/providers/provider-send-message.ts +41 -20
- package/src/providers/registry.ts +143 -159
- package/src/providers/retry.ts +18 -10
- package/src/providers/search-provider-catalog.ts +121 -0
- package/src/runtime/AGENTS.md +18 -5
- package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
- package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
- package/src/runtime/actor-trust-resolver.ts +32 -10
- package/src/runtime/agent-wake.ts +35 -6
- package/src/runtime/assistant-event-hub.ts +3 -85
- package/src/runtime/auth/route-policy.ts +303 -8
- package/src/runtime/auth/same-actor.ts +2 -0
- package/src/runtime/background-job-runner.ts +339 -0
- package/src/runtime/btw-sidechain.ts +1 -0
- package/src/runtime/http-router.ts +36 -1
- package/src/runtime/http-server.ts +31 -5
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
- package/src/runtime/middleware/request-logger.ts +62 -1
- package/src/runtime/pre-first-message-gate.ts +83 -0
- package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/acp-routes.ts +10 -8
- package/src/runtime/routes/app-management-routes.ts +228 -3
- package/src/runtime/routes/approval-routes.ts +0 -18
- package/src/runtime/routes/audit-routes.ts +43 -0
- package/src/runtime/routes/auth-routes.ts +72 -0
- package/src/runtime/routes/avatar-routes.ts +273 -20
- package/src/runtime/routes/backup-routes.ts +406 -2
- package/src/runtime/routes/bookmark-routes.ts +154 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/contact-routes.ts +0 -160
- package/src/runtime/routes/conversation-cli-routes.ts +192 -0
- package/src/runtime/routes/conversation-management-routes.ts +30 -43
- package/src/runtime/routes/conversation-query-routes.ts +334 -86
- package/src/runtime/routes/conversation-routes.ts +31 -10
- package/src/runtime/routes/conversations-import-routes.ts +229 -0
- package/src/runtime/routes/credential-routes.ts +540 -0
- package/src/runtime/routes/debug-routes.ts +2 -2
- package/src/runtime/routes/document-pdf-renderer.ts +5 -1
- package/src/runtime/routes/domain-routes.ts +167 -0
- package/src/runtime/routes/email-routes.ts +603 -0
- package/src/runtime/routes/errors.ts +2 -2
- package/src/runtime/routes/events-routes.ts +192 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -78
- package/src/runtime/routes/host-app-control-routes.ts +44 -2
- package/src/runtime/routes/host-browser-routes.ts +103 -22
- package/src/runtime/routes/http-adapter.ts +2 -0
- package/src/runtime/routes/identity-routes.ts +5 -0
- package/src/runtime/routes/image-generation-routes.ts +99 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
- package/src/runtime/routes/index.ts +36 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
- package/src/runtime/routes/inference-send-routes.ts +115 -0
- package/src/runtime/routes/integrations/twilio.ts +1 -0
- package/src/runtime/routes/mcp-auth-routes.ts +283 -9
- package/src/runtime/routes/memory-v2-routes.ts +13 -398
- package/src/runtime/routes/notification-routes.ts +2 -0
- package/src/runtime/routes/oauth-apps.ts +112 -7
- package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
- package/src/runtime/routes/oauth-connect-routes.ts +67 -5
- package/src/runtime/routes/oauth-providers.ts +298 -8
- package/src/runtime/routes/platform-routes.ts +336 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -1
- package/src/runtime/routes/playground/reset-circuit.ts +2 -1
- package/src/runtime/routes/playground/state.ts +2 -1
- package/src/runtime/routes/publish-routes.ts +221 -0
- package/src/runtime/routes/schedule-routes.ts +82 -0
- package/src/runtime/routes/sequence-routes.ts +291 -0
- package/src/runtime/routes/settings-routes.ts +2 -10
- package/src/runtime/routes/skills-routes.ts +31 -1
- package/src/runtime/routes/stt-routes.ts +240 -3
- package/src/runtime/routes/surface-action-routes.ts +43 -7
- package/src/runtime/routes/tts-routes.ts +67 -0
- package/src/runtime/routes/types.ts +32 -0
- package/src/runtime/routes/user-routes-cli.ts +243 -0
- package/src/runtime/routes/webhook-routes.ts +165 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/sync/sync-publisher.test.ts +105 -0
- package/src/runtime/sync/sync-publisher.ts +21 -0
- package/src/schedule/scheduler.ts +200 -123
- package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
- package/src/security/secret-patterns.ts +3 -0
- package/src/sequence/engine.ts +38 -40
- package/src/subagent/manager.ts +20 -15
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
- package/src/tools/browser/browser-execution.ts +15 -4
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
- package/src/tools/browser/cdp-client/factory.ts +66 -5
- package/src/tools/browser/runtime-check.ts +77 -0
- package/src/tools/memory/register.test.ts +3 -3
- package/src/tools/memory/register.ts +9 -1
- package/src/tools/network/__tests__/web-search.test.ts +156 -0
- package/src/tools/network/web-search.ts +280 -37
- package/src/tools/permission-checker.ts +13 -5
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/terminal/shell.ts +44 -0
- package/src/usage/attribution.ts +3 -2
- package/src/util/pricing.ts +86 -160
- package/src/watcher/__tests__/engine.test.ts +301 -0
- package/src/watcher/constants.ts +7 -0
- package/src/watcher/engine.ts +90 -90
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
- package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
- package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
- package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
- package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
- package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
- package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
- package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
- package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
- package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
- package/src/workspace/migrations/registry.ts +22 -0
- package/src/workspace/migrations/runner.ts +13 -2
- package/src/workspace/migrations/types.ts +13 -3
- package/src/workspace/provider-commit-message-generator.ts +3 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -498
- package/src/__tests__/credentials-cli.test.ts +0 -1225
- package/src/__tests__/memory-admin-recall.test.ts +0 -213
- package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
- package/src/cli/commands/__tests__/email-download.test.ts +0 -260
- package/src/cli/commands/__tests__/email-list.test.ts +0 -216
- package/src/cli/commands/__tests__/email-register.test.ts +0 -186
- package/src/cli/commands/__tests__/email-send.test.ts +0 -416
- package/src/cli/commands/__tests__/email-status.test.ts +0 -185
- package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
- package/src/cli/commands/__tests__/routes.test.ts +0 -562
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
- package/src/cli/commands/autonomy.ts +0 -365
- package/src/cli/commands/memory.ts +0 -424
- package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
- package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
- package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
- package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
- package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
- package/src/cli/lib/daemon-avatar-client.ts +0 -37
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
- package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
- package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
- package/src/home/__tests__/emit-feed-event.test.ts +0 -169
- package/src/home/__tests__/feed-population-integration.test.ts +0 -312
- package/src/home/__tests__/feed-scheduler.test.ts +0 -222
- package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
- package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
- package/src/home/__tests__/rollup-producer.test.ts +0 -507
- package/src/home/assistant-feed-authoring.ts +0 -135
- package/src/home/emit-feed-event.ts +0 -169
- package/src/home/feed-scheduler.ts +0 -281
- package/src/home/platform-gmail-digest.ts +0 -163
- package/src/home/rewrite-command-preview.ts +0 -66
- package/src/home/rewrite-feed-title.ts +0 -58
- package/src/home/rollup-producer.ts +0 -426
- package/src/memory/admin.ts +0 -326
- package/src/memory/context-search/sources/pkb.ts +0 -476
- package/src/memory/graph/compaction.ts +0 -299
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
|
@@ -532,7 +532,7 @@ describe("GET /v1/suggestion", () => {
|
|
|
532
532
|
);
|
|
533
533
|
});
|
|
534
534
|
|
|
535
|
-
test("uses
|
|
535
|
+
test("uses replySuggestion call site", async () => {
|
|
536
536
|
const provider = makeMockProvider("Quick reply");
|
|
537
537
|
mockGetConfiguredProvider.mockImplementation(async () => provider);
|
|
538
538
|
mockGetConversationByKey.mockImplementation(() => ({
|
|
@@ -558,7 +558,7 @@ describe("GET /v1/suggestion", () => {
|
|
|
558
558
|
const options = callArgs[3] as
|
|
559
559
|
| { config?: { callSite?: string } }
|
|
560
560
|
| undefined;
|
|
561
|
-
expect(options?.config?.callSite).toBe("
|
|
561
|
+
expect(options?.config?.callSite).toBe("replySuggestion");
|
|
562
562
|
});
|
|
563
563
|
|
|
564
564
|
test("disables thinking and zeros effort to avoid Anthropic temp/thinking 400", async () => {
|
|
@@ -612,7 +612,7 @@ describe("GET /v1/suggestion", () => {
|
|
|
612
612
|
// whenever the request triggers extended thinking (e.g. Opus 4.x at
|
|
613
613
|
// `effort: "xhigh"`). The suggestion generator must only send a
|
|
614
614
|
// single user-role message so it stays compatible with every
|
|
615
|
-
// possible `
|
|
615
|
+
// possible `replySuggestion` call-site config.
|
|
616
616
|
const provider = makeMockProvider("<reply>Sure, works for me</reply>");
|
|
617
617
|
mockGetConfiguredProvider.mockImplementation(async () => provider);
|
|
618
618
|
mockGetConversationByKey.mockImplementation(() => ({
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
buildSyncChangedMessage,
|
|
5
|
+
conversationMessagesSyncTag,
|
|
6
|
+
type ServerMessage,
|
|
7
|
+
SYNC_TAGS,
|
|
8
|
+
SyncChangedMessageSchema,
|
|
9
|
+
} from "../daemon/message-protocol.js";
|
|
10
|
+
|
|
11
|
+
describe("sync message contract", () => {
|
|
12
|
+
test("sync_changed is assignable to ServerMessage", () => {
|
|
13
|
+
const message: ServerMessage = {
|
|
14
|
+
type: "sync_changed",
|
|
15
|
+
tags: [SYNC_TAGS.assistantAvatar],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
expect(message).toEqual({
|
|
19
|
+
type: "sync_changed",
|
|
20
|
+
tags: [SYNC_TAGS.assistantAvatar],
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("buildSyncChangedMessage dedupes tags", () => {
|
|
25
|
+
const message = buildSyncChangedMessage([
|
|
26
|
+
SYNC_TAGS.assistantAvatar,
|
|
27
|
+
SYNC_TAGS.assistantAvatar,
|
|
28
|
+
conversationMessagesSyncTag("conversation-123"),
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
expect(message).toEqual({
|
|
32
|
+
type: "sync_changed",
|
|
33
|
+
tags: [
|
|
34
|
+
SYNC_TAGS.assistantAvatar,
|
|
35
|
+
"conversation:conversation-123:messages",
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("schema rejects malformed sync_changed payloads", () => {
|
|
41
|
+
expect(() =>
|
|
42
|
+
SyncChangedMessageSchema.parse({
|
|
43
|
+
type: "sync_changed",
|
|
44
|
+
tags: [],
|
|
45
|
+
}),
|
|
46
|
+
).toThrow();
|
|
47
|
+
|
|
48
|
+
expect(() =>
|
|
49
|
+
SyncChangedMessageSchema.parse({
|
|
50
|
+
type: "sync_changed",
|
|
51
|
+
tags: [""],
|
|
52
|
+
}),
|
|
53
|
+
).toThrow();
|
|
54
|
+
|
|
55
|
+
expect(() =>
|
|
56
|
+
SyncChangedMessageSchema.parse({
|
|
57
|
+
type: "sync_changed",
|
|
58
|
+
tags: [SYNC_TAGS.assistantAvatar],
|
|
59
|
+
cursor: 1,
|
|
60
|
+
}),
|
|
61
|
+
).toThrow();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -7,6 +7,57 @@ mock.module("../util/logger.js", () => ({
|
|
|
7
7
|
}),
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
|
+
// Mock the shared `runBackgroundJob` runner so the scheduler's fresh-bootstrap
|
|
11
|
+
// talk-mode path stays observable. Each invocation creates a new conversation
|
|
12
|
+
// row and pushes the prompt onto the per-test handler set via
|
|
13
|
+
// `onRunBackgroundJobCall`. `run_task:` schedules use a different code path
|
|
14
|
+
// and do not invoke this runner.
|
|
15
|
+
let onRunBackgroundJobCall:
|
|
16
|
+
| ((info: {
|
|
17
|
+
conversationId: string;
|
|
18
|
+
prompt: string;
|
|
19
|
+
trustContext: { sourceChannel: string; trustClass: string };
|
|
20
|
+
}) => void)
|
|
21
|
+
| null = null;
|
|
22
|
+
mock.module("../runtime/background-job-runner.js", () => ({
|
|
23
|
+
runBackgroundJob: async (opts: {
|
|
24
|
+
prompt: string;
|
|
25
|
+
groupId?: string;
|
|
26
|
+
trustContext: { sourceChannel: string; trustClass: string };
|
|
27
|
+
}) => {
|
|
28
|
+
const { createConversation } =
|
|
29
|
+
await import("../memory/conversation-crud.js");
|
|
30
|
+
const conv = createConversation({
|
|
31
|
+
title: "(test stub)",
|
|
32
|
+
conversationType: "background",
|
|
33
|
+
source: "schedule",
|
|
34
|
+
...(opts.groupId ? { groupId: opts.groupId } : {}),
|
|
35
|
+
});
|
|
36
|
+
onRunBackgroundJobCall?.({
|
|
37
|
+
conversationId: conv.id,
|
|
38
|
+
prompt: opts.prompt,
|
|
39
|
+
trustContext: opts.trustContext,
|
|
40
|
+
});
|
|
41
|
+
return { conversationId: conv.id, ok: true };
|
|
42
|
+
},
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
// Capture `emitNotificationSignal` calls so tests can assert that scheduled
|
|
46
|
+
// task failures surface via the notification pipeline (home feed + native).
|
|
47
|
+
const emitNotificationCalls: Array<Record<string, unknown>> = [];
|
|
48
|
+
mock.module("../notifications/emit-signal.js", () => ({
|
|
49
|
+
emitNotificationSignal: async (params: Record<string, unknown>) => {
|
|
50
|
+
emitNotificationCalls.push(params);
|
|
51
|
+
return {
|
|
52
|
+
signalId: "stub-signal",
|
|
53
|
+
deduplicated: false,
|
|
54
|
+
dispatched: true,
|
|
55
|
+
reason: "ok",
|
|
56
|
+
deliveryResults: [],
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
}));
|
|
60
|
+
|
|
10
61
|
import { getDb } from "../memory/db-connection.js";
|
|
11
62
|
import { initializeDb } from "../memory/db-init.js";
|
|
12
63
|
import {
|
|
@@ -111,6 +162,8 @@ describe("scheduler run_task detection", () => {
|
|
|
111
162
|
db.run("DELETE FROM tasks");
|
|
112
163
|
db.run("DELETE FROM messages");
|
|
113
164
|
db.run("DELETE FROM conversations");
|
|
165
|
+
onRunBackgroundJobCall = null;
|
|
166
|
+
emitNotificationCalls.length = 0;
|
|
114
167
|
});
|
|
115
168
|
|
|
116
169
|
test("run_task:<id> messages trigger runTask instead of processMessage", async () => {
|
|
@@ -163,7 +216,7 @@ describe("scheduler run_task detection", () => {
|
|
|
163
216
|
expect(typeof runTaskCalls[0].options?.taskRunId).toBe("string");
|
|
164
217
|
});
|
|
165
218
|
|
|
166
|
-
test("regular messages
|
|
219
|
+
test("regular messages route through the runBackgroundJob runner", async () => {
|
|
167
220
|
// Create a regular schedule (no run_task: prefix)
|
|
168
221
|
const schedule = createSchedule({
|
|
169
222
|
name: "Regular Schedule",
|
|
@@ -174,36 +227,32 @@ describe("scheduler run_task detection", () => {
|
|
|
174
227
|
|
|
175
228
|
forceScheduleDue(schedule.id);
|
|
176
229
|
|
|
177
|
-
const
|
|
230
|
+
const runnerCalls: Array<{
|
|
178
231
|
conversationId: string;
|
|
179
|
-
|
|
180
|
-
|
|
232
|
+
prompt: string;
|
|
233
|
+
trustContext: { sourceChannel: string; trustClass: string };
|
|
181
234
|
}> = [];
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
message: string,
|
|
185
|
-
options?: { trustClass?: string; taskRunId?: string },
|
|
186
|
-
) => {
|
|
187
|
-
processedMessages.push({ conversationId, message, options });
|
|
235
|
+
onRunBackgroundJobCall = (info) => {
|
|
236
|
+
runnerCalls.push(info);
|
|
188
237
|
};
|
|
189
238
|
|
|
190
|
-
const scheduler = startScheduler(
|
|
239
|
+
const scheduler = startScheduler(
|
|
240
|
+
async () => {},
|
|
241
|
+
() => {},
|
|
242
|
+
);
|
|
191
243
|
|
|
192
244
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
193
245
|
scheduler.stop();
|
|
194
246
|
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
).toBe(
|
|
199
|
-
expect(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
m.options?.taskRunId === undefined,
|
|
205
|
-
),
|
|
206
|
-
).toBe(true);
|
|
247
|
+
// The runner should have been invoked with the schedule message and a
|
|
248
|
+
// guardian trust context, mirroring the historical inline `processMessage`
|
|
249
|
+
// call that the migration replaced.
|
|
250
|
+
expect(runnerCalls.length).toBe(1);
|
|
251
|
+
expect(runnerCalls[0].prompt).toBe("Do something normal");
|
|
252
|
+
expect(runnerCalls[0].trustContext).toEqual({
|
|
253
|
+
sourceChannel: "vellum",
|
|
254
|
+
trustClass: "guardian",
|
|
255
|
+
});
|
|
207
256
|
});
|
|
208
257
|
|
|
209
258
|
test("handles task not found gracefully", async () => {
|
|
@@ -232,5 +281,21 @@ describe("scheduler run_task detection", () => {
|
|
|
232
281
|
expect(runs.length).toBeGreaterThanOrEqual(1);
|
|
233
282
|
expect(runs[0].status).toBe("error");
|
|
234
283
|
expect(runs[0].error).toContain("Task not found");
|
|
284
|
+
|
|
285
|
+
// Failed scheduled tasks must surface via the notification pipeline so
|
|
286
|
+
// they reach the home feed and native macOS notifications. The shape
|
|
287
|
+
// mirrors what `runBackgroundJob` emits for its own failures.
|
|
288
|
+
const failureSignal = emitNotificationCalls.find(
|
|
289
|
+
(p) => p.sourceEventName === "activity.failed",
|
|
290
|
+
);
|
|
291
|
+
expect(failureSignal).toBeDefined();
|
|
292
|
+
expect(failureSignal?.sourceChannel).toBe("scheduler");
|
|
293
|
+
const payload = failureSignal?.contextPayload as Record<string, unknown>;
|
|
294
|
+
expect(payload.jobName).toBe("task:nonexistent-task-id");
|
|
295
|
+
expect(payload.errorKind).toBe("exception");
|
|
296
|
+
expect(typeof payload.errorMessage).toBe("string");
|
|
297
|
+
expect(failureSignal?.dedupeKey).toMatch(
|
|
298
|
+
/^activity-failed:task:nonexistent-task-id:\d{4}-\d{2}-\d{2}$/,
|
|
299
|
+
);
|
|
235
300
|
});
|
|
236
301
|
});
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import {
|
|
4
|
-
afterEach,
|
|
5
|
-
beforeEach,
|
|
6
|
-
describe,
|
|
7
|
-
expect,
|
|
8
|
-
mock,
|
|
9
|
-
test,
|
|
10
|
-
} from "bun:test";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
11
4
|
|
|
12
5
|
import { getWorkspacePromptPath } from "../util/platform.js";
|
|
13
6
|
|
|
14
|
-
// ── fs.readFileSync override (for
|
|
7
|
+
// ── fs.readFileSync override (for read-failure test) ─────────────────
|
|
15
8
|
// We mock node:fs so we can inject a readFileSync that throws for the
|
|
16
9
|
// workspace path. All other call sites fall through to the real fs.
|
|
17
10
|
const realReadFileSync = readFileSync;
|
|
@@ -54,62 +47,58 @@ mock.module("../config/loader.js", () => ({
|
|
|
54
47
|
getConfig: () => ({ updates: updatesConfig }),
|
|
55
48
|
}));
|
|
56
49
|
|
|
57
|
-
// ──
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
let
|
|
62
|
-
let wakeShouldThrow = false;
|
|
63
|
-
let wakeInvoked = true;
|
|
64
|
-
let wakeProducedToolCalls = false;
|
|
65
|
-
// A side-effect function invoked during wake. Lets tests simulate the
|
|
66
|
-
// agent deleting UPDATES.md while the wake is in flight.
|
|
67
|
-
let wakeSideEffect: (() => void) | null = null;
|
|
68
|
-
|
|
69
|
-
mock.module("../memory/conversation-bootstrap.js", () => ({
|
|
70
|
-
bootstrapConversation: (opts: Record<string, unknown>) => {
|
|
71
|
-
bootstrapCalls += 1;
|
|
72
|
-
bootstrapLastArgs = opts;
|
|
73
|
-
return { id: `conv-${bootstrapCalls}` };
|
|
74
|
-
},
|
|
75
|
-
}));
|
|
50
|
+
// ── pre-first-message gate stub ──────────────────────────────────────
|
|
51
|
+
// Default: gate open (user has interacted) so the existing happy/sad
|
|
52
|
+
// paths exercise the bulletin logic. A dedicated test below flips this
|
|
53
|
+
// to false to assert the gate trips.
|
|
54
|
+
let preFirstMessageGateOpen = true;
|
|
76
55
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const deletedIds: string[] = [];
|
|
80
|
-
let deleteShouldThrow = false;
|
|
81
|
-
|
|
82
|
-
mock.module("../memory/conversation-crud.js", () => ({
|
|
83
|
-
deleteConversation: (id: string) => {
|
|
84
|
-
deleteCalls += 1;
|
|
85
|
-
deletedIds.push(id);
|
|
86
|
-
if (deleteShouldThrow) {
|
|
87
|
-
throw new Error("simulated delete failure");
|
|
88
|
-
}
|
|
89
|
-
return { segmentIds: [], deletedSummaryIds: [] };
|
|
90
|
-
},
|
|
56
|
+
mock.module("../runtime/pre-first-message-gate.js", () => ({
|
|
57
|
+
hasReceivedUserMessage: () => preFirstMessageGateOpen,
|
|
91
58
|
}));
|
|
92
59
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
60
|
+
// ── runBackgroundJob mock ────────────────────────────────────────────
|
|
61
|
+
let runBackgroundJobCalls = 0;
|
|
62
|
+
let runBackgroundJobLastArgs: Record<string, unknown> | null = null;
|
|
63
|
+
let runBackgroundJobShouldThrow = false;
|
|
64
|
+
let runBackgroundJobOk = true;
|
|
65
|
+
let runBackgroundJobErrorKind:
|
|
66
|
+
| "timeout"
|
|
67
|
+
| "model_provider"
|
|
68
|
+
| "exception"
|
|
69
|
+
| undefined = undefined;
|
|
70
|
+
let runBackgroundJobErrorMessage: string | undefined = undefined;
|
|
71
|
+
// A side-effect function invoked during the job. Lets tests simulate the
|
|
72
|
+
// agent deleting UPDATES.md while the job is running.
|
|
73
|
+
let runBackgroundJobSideEffect: (() => void) | null = null;
|
|
74
|
+
|
|
75
|
+
mock.module("../runtime/background-job-runner.js", () => ({
|
|
76
|
+
runBackgroundJob: async (opts: Record<string, unknown>) => {
|
|
77
|
+
runBackgroundJobCalls += 1;
|
|
78
|
+
runBackgroundJobLastArgs = opts;
|
|
79
|
+
if (runBackgroundJobSideEffect) {
|
|
80
|
+
runBackgroundJobSideEffect();
|
|
99
81
|
}
|
|
100
|
-
if (
|
|
101
|
-
throw new Error("simulated
|
|
82
|
+
if (runBackgroundJobShouldThrow) {
|
|
83
|
+
throw new Error("simulated runner failure");
|
|
84
|
+
}
|
|
85
|
+
if (runBackgroundJobOk) {
|
|
86
|
+
return {
|
|
87
|
+
conversationId: `conv-${runBackgroundJobCalls}`,
|
|
88
|
+
ok: true,
|
|
89
|
+
};
|
|
102
90
|
}
|
|
103
91
|
return {
|
|
104
|
-
|
|
105
|
-
|
|
92
|
+
conversationId: `conv-${runBackgroundJobCalls}`,
|
|
93
|
+
ok: false,
|
|
94
|
+
error: new Error(runBackgroundJobErrorMessage ?? "simulated failure"),
|
|
95
|
+
errorKind: runBackgroundJobErrorKind ?? "exception",
|
|
106
96
|
};
|
|
107
97
|
},
|
|
108
98
|
}));
|
|
109
99
|
|
|
110
|
-
const { runUpdateBulletinJobIfNeeded } =
|
|
111
|
-
"../prompts/update-bulletin-job.js"
|
|
112
|
-
);
|
|
100
|
+
const { runUpdateBulletinJobIfNeeded } =
|
|
101
|
+
await import("../prompts/update-bulletin-job.js");
|
|
113
102
|
|
|
114
103
|
const HASH_CHECKPOINT_KEY = "updates:last_processed_hash";
|
|
115
104
|
const EMPTY_HASH = "empty";
|
|
@@ -124,19 +113,16 @@ describe("runUpdateBulletinJobIfNeeded", () => {
|
|
|
124
113
|
beforeEach(() => {
|
|
125
114
|
store.clear();
|
|
126
115
|
setCheckpointCallCount = 0;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
wakeSideEffect = null;
|
|
116
|
+
runBackgroundJobCalls = 0;
|
|
117
|
+
runBackgroundJobLastArgs = null;
|
|
118
|
+
runBackgroundJobShouldThrow = false;
|
|
119
|
+
runBackgroundJobOk = true;
|
|
120
|
+
runBackgroundJobErrorKind = undefined;
|
|
121
|
+
runBackgroundJobErrorMessage = undefined;
|
|
122
|
+
runBackgroundJobSideEffect = null;
|
|
135
123
|
readFileSyncOverride = null;
|
|
136
124
|
updatesConfig.enabled = true;
|
|
137
|
-
|
|
138
|
-
deletedIds.length = 0;
|
|
139
|
-
deleteShouldThrow = false;
|
|
125
|
+
preFirstMessageGateOpen = true;
|
|
140
126
|
if (existsSync(workspacePath)) {
|
|
141
127
|
rmSync(workspacePath);
|
|
142
128
|
}
|
|
@@ -148,38 +134,45 @@ describe("runUpdateBulletinJobIfNeeded", () => {
|
|
|
148
134
|
}
|
|
149
135
|
});
|
|
150
136
|
|
|
151
|
-
test("config disabled — no
|
|
137
|
+
test("config disabled — no job, no checkpoint change", async () => {
|
|
152
138
|
updatesConfig.enabled = false;
|
|
153
139
|
writeFileSync(workspacePath, "## Real content", "utf-8");
|
|
154
140
|
|
|
155
141
|
await runUpdateBulletinJobIfNeeded();
|
|
156
142
|
|
|
157
|
-
expect(
|
|
158
|
-
expect(
|
|
143
|
+
expect(runBackgroundJobCalls).toBe(0);
|
|
144
|
+
expect(setCheckpointCallCount).toBe(0);
|
|
145
|
+
expect(store.has(HASH_CHECKPOINT_KEY)).toBe(false);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("pre-first-message gate closed — no job, checkpoint left UNCHANGED so the job retries after the user interacts", async () => {
|
|
149
|
+
preFirstMessageGateOpen = false;
|
|
150
|
+
writeFileSync(workspacePath, "## Real content", "utf-8");
|
|
151
|
+
|
|
152
|
+
await runUpdateBulletinJobIfNeeded();
|
|
153
|
+
|
|
154
|
+
expect(runBackgroundJobCalls).toBe(0);
|
|
159
155
|
expect(setCheckpointCallCount).toBe(0);
|
|
160
156
|
expect(store.has(HASH_CHECKPOINT_KEY)).toBe(false);
|
|
161
157
|
});
|
|
162
158
|
|
|
163
|
-
test("file missing, stored hash absent — no
|
|
159
|
+
test("file missing, stored hash absent — no job; stored becomes 'empty'", async () => {
|
|
164
160
|
expect(existsSync(workspacePath)).toBe(false);
|
|
165
161
|
expect(store.has(HASH_CHECKPOINT_KEY)).toBe(false);
|
|
166
162
|
|
|
167
163
|
await runUpdateBulletinJobIfNeeded();
|
|
168
164
|
|
|
169
|
-
expect(
|
|
170
|
-
expect(wakeCalls).toBe(0);
|
|
165
|
+
expect(runBackgroundJobCalls).toBe(0);
|
|
171
166
|
expect(store.get(HASH_CHECKPOINT_KEY)).toBe(EMPTY_HASH);
|
|
172
167
|
});
|
|
173
168
|
|
|
174
|
-
test("file missing, stored hash already 'empty' — no
|
|
169
|
+
test("file missing, stored hash already 'empty' — no job; no checkpoint write", async () => {
|
|
175
170
|
store.set(HASH_CHECKPOINT_KEY, EMPTY_HASH);
|
|
176
|
-
// Reset the counter to ignore the priming write above.
|
|
177
171
|
setCheckpointCallCount = 0;
|
|
178
172
|
|
|
179
173
|
await runUpdateBulletinJobIfNeeded();
|
|
180
174
|
|
|
181
|
-
expect(
|
|
182
|
-
expect(wakeCalls).toBe(0);
|
|
175
|
+
expect(runBackgroundJobCalls).toBe(0);
|
|
183
176
|
expect(setCheckpointCallCount).toBe(0);
|
|
184
177
|
expect(store.get(HASH_CHECKPOINT_KEY)).toBe(EMPTY_HASH);
|
|
185
178
|
});
|
|
@@ -189,28 +182,25 @@ describe("runUpdateBulletinJobIfNeeded", () => {
|
|
|
189
182
|
|
|
190
183
|
await runUpdateBulletinJobIfNeeded();
|
|
191
184
|
|
|
192
|
-
expect(
|
|
193
|
-
expect(wakeCalls).toBe(0);
|
|
185
|
+
expect(runBackgroundJobCalls).toBe(0);
|
|
194
186
|
expect(store.get(HASH_CHECKPOINT_KEY)).toBe(EMPTY_HASH);
|
|
195
187
|
});
|
|
196
188
|
|
|
197
|
-
test("file present
|
|
189
|
+
test("file present, job ok=true, file unchanged — stored hash is sha256(trimmed); jobName/source are kebab-case", async () => {
|
|
198
190
|
const content = "## Release 1.2.3\n\nNew thing.\n";
|
|
199
191
|
writeFileSync(workspacePath, content, "utf-8");
|
|
200
|
-
wakeProducedToolCalls = true;
|
|
201
192
|
|
|
202
193
|
await runUpdateBulletinJobIfNeeded();
|
|
203
194
|
|
|
204
|
-
expect(
|
|
205
|
-
expect(wakeCalls).toBe(1);
|
|
195
|
+
expect(runBackgroundJobCalls).toBe(1);
|
|
206
196
|
expect(store.get(HASH_CHECKPOINT_KEY)).toBe(sha256(content.trim()));
|
|
207
|
-
|
|
208
|
-
expect(
|
|
209
|
-
expect(
|
|
210
|
-
expect(
|
|
197
|
+
expect(runBackgroundJobLastArgs?.jobName).toBe("update-bulletin");
|
|
198
|
+
expect(runBackgroundJobLastArgs?.source).toBe("update-bulletin");
|
|
199
|
+
expect(runBackgroundJobLastArgs?.origin).toBe("updates_bulletin");
|
|
200
|
+
expect(runBackgroundJobLastArgs?.callSite).toBe("mainAgent");
|
|
211
201
|
});
|
|
212
202
|
|
|
213
|
-
test("file present, stored hash matches current — no
|
|
203
|
+
test("file present, stored hash matches current — no job", async () => {
|
|
214
204
|
const content = "## Release 1.2.3\n\nSame content.\n";
|
|
215
205
|
writeFileSync(workspacePath, content, "utf-8");
|
|
216
206
|
store.set(HASH_CHECKPOINT_KEY, sha256(content.trim()));
|
|
@@ -218,138 +208,53 @@ describe("runUpdateBulletinJobIfNeeded", () => {
|
|
|
218
208
|
|
|
219
209
|
await runUpdateBulletinJobIfNeeded();
|
|
220
210
|
|
|
221
|
-
expect(
|
|
222
|
-
expect(wakeCalls).toBe(0);
|
|
223
|
-
expect(setCheckpointCallCount).toBe(0);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
test("wake returns invoked:false — checkpoint UNCHANGED + orphan conversation is cleaned up", async () => {
|
|
227
|
-
const content = "## Release Q\n\nResolver-missing scenario.\n";
|
|
228
|
-
writeFileSync(workspacePath, content, "utf-8");
|
|
229
|
-
wakeInvoked = false;
|
|
230
|
-
wakeProducedToolCalls = false;
|
|
231
|
-
|
|
232
|
-
await runUpdateBulletinJobIfNeeded();
|
|
233
|
-
|
|
234
|
-
expect(bootstrapCalls).toBe(1);
|
|
235
|
-
expect(wakeCalls).toBe(1);
|
|
236
|
-
// Critical: do NOT poison the checkpoint (round-1 behavior preserved).
|
|
237
|
-
expect(store.has(HASH_CHECKPOINT_KEY)).toBe(false);
|
|
238
|
-
expect(setCheckpointCallCount).toBe(0);
|
|
239
|
-
// Belt-and-suspenders: the orphan background conversation bootstrapped
|
|
240
|
-
// before the wake must be deleted so we don't leak DB rows on every
|
|
241
|
-
// silent no-op.
|
|
242
|
-
expect(deleteCalls).toBe(1);
|
|
243
|
-
expect(deletedIds).toEqual(["conv-1"]);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
test("wake returns invoked:false AND deleteConversation throws — function still returns (cleanup error is swallowed)", async () => {
|
|
247
|
-
const content = "## Release Q2\n\nDelete-throws scenario.\n";
|
|
248
|
-
writeFileSync(workspacePath, content, "utf-8");
|
|
249
|
-
wakeInvoked = false;
|
|
250
|
-
wakeProducedToolCalls = false;
|
|
251
|
-
deleteShouldThrow = true;
|
|
252
|
-
|
|
253
|
-
await expect(runUpdateBulletinJobIfNeeded()).resolves.toBeUndefined();
|
|
254
|
-
|
|
255
|
-
expect(bootstrapCalls).toBe(1);
|
|
256
|
-
expect(wakeCalls).toBe(1);
|
|
257
|
-
expect(deleteCalls).toBe(1);
|
|
258
|
-
// Checkpoint still untouched.
|
|
259
|
-
expect(store.has(HASH_CHECKPOINT_KEY)).toBe(false);
|
|
211
|
+
expect(runBackgroundJobCalls).toBe(0);
|
|
260
212
|
expect(setCheckpointCallCount).toBe(0);
|
|
261
213
|
});
|
|
262
214
|
|
|
263
|
-
test("
|
|
264
|
-
const content = "## Release
|
|
265
|
-
writeFileSync(workspacePath, content, "utf-8");
|
|
266
|
-
wakeInvoked = true;
|
|
267
|
-
wakeProducedToolCalls = true;
|
|
268
|
-
|
|
269
|
-
await runUpdateBulletinJobIfNeeded();
|
|
270
|
-
|
|
271
|
-
expect(bootstrapCalls).toBe(1);
|
|
272
|
-
expect(wakeCalls).toBe(1);
|
|
273
|
-
expect(deleteCalls).toBe(0);
|
|
274
|
-
expect(deletedIds).toEqual([]);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
test("wake invoked but no tool calls AND file unchanged — checkpoint UNCHANGED (retry next startup)", async () => {
|
|
278
|
-
const content = "## Release R\n\nSilent no-op scenario.\n";
|
|
215
|
+
test("runBackgroundJob returns ok=false — checkpoint UNCHANGED so next startup retries", async () => {
|
|
216
|
+
const content = "## Release Q\n\nFailure scenario.\n";
|
|
279
217
|
writeFileSync(workspacePath, content, "utf-8");
|
|
280
|
-
|
|
281
|
-
|
|
218
|
+
runBackgroundJobOk = false;
|
|
219
|
+
runBackgroundJobErrorKind = "exception";
|
|
220
|
+
runBackgroundJobErrorMessage = "boom";
|
|
282
221
|
|
|
283
222
|
await runUpdateBulletinJobIfNeeded();
|
|
284
223
|
|
|
285
|
-
expect(
|
|
286
|
-
|
|
224
|
+
expect(runBackgroundJobCalls).toBe(1);
|
|
225
|
+
// Critical: do NOT poison the checkpoint when the job fails.
|
|
287
226
|
expect(store.has(HASH_CHECKPOINT_KEY)).toBe(false);
|
|
288
227
|
expect(setCheckpointCallCount).toBe(0);
|
|
289
228
|
});
|
|
290
229
|
|
|
291
|
-
test("
|
|
292
|
-
const content = "## Release
|
|
230
|
+
test("runBackgroundJob ok=true + agent deletes file mid-run — stored hash becomes 'empty'", async () => {
|
|
231
|
+
const content = "## Release X\n\nStuff to process.\n";
|
|
293
232
|
writeFileSync(workspacePath, content, "utf-8");
|
|
294
|
-
|
|
295
|
-
wakeProducedToolCalls = false;
|
|
296
|
-
wakeSideEffect = () => {
|
|
233
|
+
runBackgroundJobSideEffect = () => {
|
|
297
234
|
rmSync(workspacePath);
|
|
298
235
|
};
|
|
299
236
|
|
|
300
237
|
await runUpdateBulletinJobIfNeeded();
|
|
301
238
|
|
|
302
|
-
expect(
|
|
303
|
-
expect(wakeCalls).toBe(1);
|
|
239
|
+
expect(runBackgroundJobCalls).toBe(1);
|
|
304
240
|
expect(existsSync(workspacePath)).toBe(false);
|
|
305
241
|
expect(store.get(HASH_CHECKPOINT_KEY)).toBe(EMPTY_HASH);
|
|
306
242
|
});
|
|
307
243
|
|
|
308
|
-
test("
|
|
309
|
-
const content = "## Release T\n\nAgent processed, chose to leave file.\n";
|
|
310
|
-
writeFileSync(workspacePath, content, "utf-8");
|
|
311
|
-
wakeInvoked = true;
|
|
312
|
-
wakeProducedToolCalls = true;
|
|
313
|
-
|
|
314
|
-
await runUpdateBulletinJobIfNeeded();
|
|
315
|
-
|
|
316
|
-
expect(bootstrapCalls).toBe(1);
|
|
317
|
-
expect(wakeCalls).toBe(1);
|
|
318
|
-
expect(store.get(HASH_CHECKPOINT_KEY)).toBe(sha256(content.trim()));
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
test("file present, stored hash differs — wake invoked; stored hash updates", async () => {
|
|
244
|
+
test("file present, stored hash differs — job invoked; stored hash updates", async () => {
|
|
322
245
|
const oldContent = "## Old";
|
|
323
246
|
const newContent = "## New content v2";
|
|
324
247
|
writeFileSync(workspacePath, newContent, "utf-8");
|
|
325
248
|
store.set(HASH_CHECKPOINT_KEY, sha256(oldContent));
|
|
326
|
-
wakeProducedToolCalls = true;
|
|
327
249
|
|
|
328
250
|
await runUpdateBulletinJobIfNeeded();
|
|
329
251
|
|
|
330
|
-
expect(
|
|
331
|
-
expect(wakeCalls).toBe(1);
|
|
252
|
+
expect(runBackgroundJobCalls).toBe(1);
|
|
332
253
|
expect(store.get(HASH_CHECKPOINT_KEY)).toBe(sha256(newContent.trim()));
|
|
333
254
|
expect(store.get(HASH_CHECKPOINT_KEY)).not.toBe(sha256(oldContent));
|
|
334
255
|
});
|
|
335
256
|
|
|
336
|
-
test("
|
|
337
|
-
const content = "## Release X\n\nStuff to process.\n";
|
|
338
|
-
writeFileSync(workspacePath, content, "utf-8");
|
|
339
|
-
wakeProducedToolCalls = true;
|
|
340
|
-
wakeSideEffect = () => {
|
|
341
|
-
rmSync(workspacePath);
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
await runUpdateBulletinJobIfNeeded();
|
|
345
|
-
|
|
346
|
-
expect(bootstrapCalls).toBe(1);
|
|
347
|
-
expect(wakeCalls).toBe(1);
|
|
348
|
-
expect(existsSync(workspacePath)).toBe(false);
|
|
349
|
-
expect(store.get(HASH_CHECKPOINT_KEY)).toBe(EMPTY_HASH);
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
test("file present but readFileSync throws — checkpoint UNCHANGED; warn logged (gap 3)", async () => {
|
|
257
|
+
test("file present but readFileSync throws — checkpoint UNCHANGED; warn logged", async () => {
|
|
353
258
|
const content = "## Release U\n\nSimulated read failure.\n";
|
|
354
259
|
writeFileSync(workspacePath, content, "utf-8");
|
|
355
260
|
|
|
@@ -366,22 +271,20 @@ describe("runUpdateBulletinJobIfNeeded", () => {
|
|
|
366
271
|
readFileSyncOverride = null;
|
|
367
272
|
}
|
|
368
273
|
|
|
369
|
-
expect(
|
|
370
|
-
expect(wakeCalls).toBe(0);
|
|
274
|
+
expect(runBackgroundJobCalls).toBe(0);
|
|
371
275
|
expect(store.has(HASH_CHECKPOINT_KEY)).toBe(false);
|
|
372
276
|
expect(setCheckpointCallCount).toBe(0);
|
|
373
277
|
});
|
|
374
278
|
|
|
375
|
-
test("
|
|
279
|
+
test("runBackgroundJob throws — function does not reject; warning logged", async () => {
|
|
376
280
|
const content = "## Release Z";
|
|
377
281
|
writeFileSync(workspacePath, content, "utf-8");
|
|
378
|
-
|
|
282
|
+
runBackgroundJobShouldThrow = true;
|
|
379
283
|
|
|
380
284
|
// Must not throw.
|
|
381
285
|
await expect(runUpdateBulletinJobIfNeeded()).resolves.toBeUndefined();
|
|
382
286
|
|
|
383
|
-
expect(
|
|
384
|
-
expect(wakeCalls).toBe(1);
|
|
287
|
+
expect(runBackgroundJobCalls).toBe(1);
|
|
385
288
|
// Hash was never updated because the try/catch returned before the
|
|
386
289
|
// self-healing step.
|
|
387
290
|
expect(store.has(HASH_CHECKPOINT_KEY)).toBe(false);
|