@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
|
@@ -1,28 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* User plugin loader — discovers plugins under `<workspaceDir>/plugins/*`
|
|
3
|
-
*
|
|
2
|
+
* User plugin loader — discovers plugins under `<workspaceDir>/plugins/*` via
|
|
3
|
+
* one of two paths, gated by the contents of each candidate directory.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* `register.ts
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* **External plugin framework path** (`package.json` present **and** no
|
|
6
|
+
* `register.{ts,js}`): the harness delegates to {@link loadExternalPlugin},
|
|
7
|
+
* which builds a `Plugin` from the directory's interface dirs (`hooks/`,
|
|
8
|
+
* `tools/`) and registers it directly. This path is opt-in by the plugin
|
|
9
|
+
* author and currently experimental — see
|
|
10
|
+
* `assistant/src/plugins/external-plugin-loader.ts` for the full
|
|
11
|
+
* convention.
|
|
12
|
+
*
|
|
13
|
+
* **Legacy path** (`register.{ts,js}` present): the file is dynamic-imported
|
|
14
|
+
* and expected to call {@link registerPlugin} at import time as a side
|
|
15
|
+
* effect, populating the registry before {@link bootstrapPlugins} runs.
|
|
16
|
+
*
|
|
17
|
+
* The legacy path takes precedence when a directory contains both
|
|
18
|
+
* `package.json` and `register.{ts,js}` — a migration-friendly default
|
|
19
|
+
* that keeps existing plugins (including the in-repo `examples/plugins/echo`
|
|
20
|
+
* reference) working unchanged while we iterate the external-plugin
|
|
21
|
+
* convention. A directory matching neither path is skipped silently.
|
|
9
22
|
*
|
|
10
23
|
* The loader deliberately:
|
|
11
24
|
*
|
|
12
25
|
* - Uses `getWorkspaceDir()` so each instance loads its own plugin set
|
|
13
26
|
* when `VELLUM_WORKSPACE_DIR` is set.
|
|
14
|
-
* - Prefers
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - Treats any error from
|
|
18
|
-
* boundary
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* - Bounds each
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* daemon startup. Timed-out plugins are logged and skipped just like
|
|
25
|
-
* thrown-error plugins.
|
|
27
|
+
* - Prefers `.js` over `.ts` per surface file (compiled-binary semantics).
|
|
28
|
+
* The external loader applies the same rule per surface file; the
|
|
29
|
+
* legacy path picks between `register.js` and `register.ts`.
|
|
30
|
+
* - Treats any error from a plugin load as a per-plugin isolation
|
|
31
|
+
* boundary. {@link loadExternalPlugin} owns its own try/catch/timeout;
|
|
32
|
+
* the legacy path is wrapped here. One bad user plugin must not crash
|
|
33
|
+
* the daemon.
|
|
34
|
+
* - Bounds each plugin load with {@link USER_PLUGIN_IMPORT_TIMEOUT_MS}
|
|
35
|
+
* so a plugin whose top-level `await` hangs or whose module evaluation
|
|
36
|
+
* never resolves cannot stall daemon startup.
|
|
26
37
|
*
|
|
27
38
|
* Call order relative to the rest of the plugin system:
|
|
28
39
|
*
|
|
@@ -39,6 +50,7 @@ import { pathToFileURL } from "node:url";
|
|
|
39
50
|
|
|
40
51
|
import { getLogger } from "../util/logger.js";
|
|
41
52
|
import { getWorkspaceDir } from "../util/platform.js";
|
|
53
|
+
import { loadExternalPlugin } from "./external-plugin-loader.js";
|
|
42
54
|
import { closeRegistration } from "./registry.js";
|
|
43
55
|
|
|
44
56
|
const log = getLogger("user-plugin-loader");
|
|
@@ -55,9 +67,10 @@ const log = getLogger("user-plugin-loader");
|
|
|
55
67
|
const USER_PLUGIN_IMPORT_TIMEOUT_MS = 10_000;
|
|
56
68
|
|
|
57
69
|
/**
|
|
58
|
-
* Scan `getWorkspaceDir()/plugins/` for subdirectories
|
|
59
|
-
* `
|
|
60
|
-
*
|
|
70
|
+
* Scan `getWorkspaceDir()/plugins/` for subdirectories, then dispatch each
|
|
71
|
+
* one to the external loader (if `package.json` is present and there is no
|
|
72
|
+
* `register.{ts,js}`) or the legacy side-effect importer (if
|
|
73
|
+
* `register.{ts,js}` is present).
|
|
61
74
|
*
|
|
62
75
|
* Invariants:
|
|
63
76
|
*
|
|
@@ -68,24 +81,24 @@ const USER_PLUGIN_IMPORT_TIMEOUT_MS = 10_000;
|
|
|
68
81
|
* - Does not return plugin instances. The registry is the single source of
|
|
69
82
|
* truth for who got registered, and the caller inspects it directly.
|
|
70
83
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
84
|
+
* Caller responsibilities:
|
|
85
|
+
*
|
|
86
|
+
* - Must be invoked exactly once during daemon startup, before
|
|
87
|
+
* `bootstrapPlugins()` walks the registry.
|
|
88
|
+
* - Holds no locks during the import — bun's dynamic `import()` resolution
|
|
89
|
+
* is concurrency-safe.
|
|
74
90
|
*/
|
|
75
91
|
export async function loadUserPlugins(
|
|
76
92
|
options: { importTimeoutMs?: number } = {},
|
|
77
93
|
): Promise<void> {
|
|
78
|
-
const importTimeoutMs =
|
|
79
|
-
|
|
94
|
+
const importTimeoutMs = options.importTimeoutMs ?? USER_PLUGIN_IMPORT_TIMEOUT_MS;
|
|
95
|
+
|
|
80
96
|
const pluginsDir = join(getWorkspaceDir(), "plugins");
|
|
97
|
+
|
|
81
98
|
if (!existsSync(pluginsDir)) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
);
|
|
86
|
-
// Close the registration window even on the fast path so a late arrival
|
|
87
|
-
// from an unrelated source (e.g. a mis-ordered static import) still can't
|
|
88
|
-
// slip in after bootstrap walks the registry.
|
|
99
|
+
// The clean-install case. Closing the registration window keeps the
|
|
100
|
+
// post-loader invariant uniform: `bootstrapPlugins()` may rely on the
|
|
101
|
+
// registry being final by the time `loadUserPlugins()` resolves.
|
|
89
102
|
closeRegistration();
|
|
90
103
|
return;
|
|
91
104
|
}
|
|
@@ -118,10 +131,12 @@ export async function loadUserPlugins(
|
|
|
118
131
|
}
|
|
119
132
|
if (!stats.isDirectory()) continue;
|
|
120
133
|
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
//
|
|
134
|
+
// Path selection: the legacy side-effect path takes precedence when
|
|
135
|
+
// both a `register.{ts,js}` and a `package.json` are present.
|
|
136
|
+
// Migration-friendly: any plugin in the wild today that happens to
|
|
137
|
+
// ship a `package.json` keeps loading via its existing register entry.
|
|
138
|
+
// The external-plugin path only fires when the directory is
|
|
139
|
+
// unambiguously the new convention.
|
|
125
140
|
const jsPath = join(pluginDir, "register.js");
|
|
126
141
|
const tsPath = join(pluginDir, "register.ts");
|
|
127
142
|
let registerPath: string | undefined;
|
|
@@ -130,16 +145,24 @@ export async function loadUserPlugins(
|
|
|
130
145
|
} else if (existsSync(tsPath)) {
|
|
131
146
|
registerPath = tsPath;
|
|
132
147
|
}
|
|
133
|
-
|
|
148
|
+
|
|
149
|
+
if (registerPath === undefined) {
|
|
150
|
+
// External plugin framework path. `loadExternalPlugin` owns its own
|
|
151
|
+
// try/catch + timeout, so a `continue` is the entire branch here.
|
|
152
|
+
if (existsSync(join(pluginDir, "package.json"))) {
|
|
153
|
+
await loadExternalPlugin(pluginDir, { importTimeoutMs });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
134
156
|
log.debug(
|
|
135
157
|
{ pluginDir },
|
|
136
|
-
"loadUserPlugins: no register.{ts,js} — skipping",
|
|
158
|
+
"loadUserPlugins: no register.{ts,js} or package.json — skipping",
|
|
137
159
|
);
|
|
138
160
|
continue;
|
|
139
161
|
}
|
|
140
162
|
|
|
141
|
-
// `import()` with a `file://` URL
|
|
142
|
-
// and sidesteps platform-specific
|
|
163
|
+
// Legacy side-effect import path. `import()` with a `file://` URL
|
|
164
|
+
// works identically under Node and bun and sidesteps platform-specific
|
|
165
|
+
// absolute-path quirks on Windows.
|
|
143
166
|
const moduleUrl = pathToFileURL(registerPath).href;
|
|
144
167
|
let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
|
|
145
168
|
try {
|
|
@@ -51,9 +51,15 @@ mock.module("../providers/provider-send-message.js", () => ({
|
|
|
51
51
|
|
|
52
52
|
// rawAll mock
|
|
53
53
|
let rawAllRows: Array<{ role: string; content: string }> = [];
|
|
54
|
+
let rawAllLastSql = "";
|
|
55
|
+
let rawAllLastArgs: unknown[] = [];
|
|
54
56
|
|
|
55
57
|
mock.module("../memory/raw-query.js", () => ({
|
|
56
|
-
rawAll: () =>
|
|
58
|
+
rawAll: (sql: string, ...args: unknown[]) => {
|
|
59
|
+
rawAllLastSql = sql;
|
|
60
|
+
rawAllLastArgs = args;
|
|
61
|
+
return rawAllRows;
|
|
62
|
+
},
|
|
57
63
|
rawRun: () => 0,
|
|
58
64
|
}));
|
|
59
65
|
|
|
@@ -279,6 +285,8 @@ function resetState() {
|
|
|
279
285
|
copyResponse = "";
|
|
280
286
|
providerSendCalls = [];
|
|
281
287
|
rawAllRows = [];
|
|
288
|
+
rawAllLastSql = "";
|
|
289
|
+
rawAllLastArgs = [];
|
|
282
290
|
bootstrapCalls = [];
|
|
283
291
|
processMessageCalls = [];
|
|
284
292
|
processMessageShouldThrow = false;
|
|
@@ -645,7 +653,7 @@ describe("runProactiveArtifactJob", () => {
|
|
|
645
653
|
});
|
|
646
654
|
|
|
647
655
|
describe("Transcript collection", () => {
|
|
648
|
-
test("
|
|
656
|
+
test("transcript query is scoped to the triggering conversation", async () => {
|
|
649
657
|
rawAllRows = defaultTranscript;
|
|
650
658
|
decisionResponse = decisionNo;
|
|
651
659
|
|
|
@@ -656,8 +664,8 @@ describe("runProactiveArtifactJob", () => {
|
|
|
656
664
|
broadcastMessage: mockBroadcast,
|
|
657
665
|
});
|
|
658
666
|
|
|
659
|
-
|
|
660
|
-
|
|
667
|
+
expect(rawAllLastSql).toContain("AND m.conversation_id = ?");
|
|
668
|
+
expect(rawAllLastArgs).toEqual(["conv-1", 5000, "asst-msg-99"]);
|
|
661
669
|
expect(
|
|
662
670
|
providerSendCalls.some(
|
|
663
671
|
(c) => c.callSite === "proactiveArtifactDecision",
|
|
@@ -57,12 +57,16 @@ export async function runProactiveArtifactJob(params: {
|
|
|
57
57
|
let buildSucceeded = false;
|
|
58
58
|
try {
|
|
59
59
|
// ── Collect transcript (bounded) ────────────────────────────────
|
|
60
|
+
// The trigger window is workspace-wide, but raw transcript context sent to
|
|
61
|
+
// the LLM must stay scoped to the conversation that fired the job.
|
|
60
62
|
const rows = rawAll<{ role: string; content: string }>(
|
|
61
63
|
`SELECT m.role, m.content FROM messages m
|
|
62
64
|
JOIN conversations c ON m.conversation_id = c.id
|
|
63
65
|
WHERE c.conversation_type = 'standard'
|
|
66
|
+
AND m.conversation_id = ?
|
|
64
67
|
AND (m.created_at <= ? OR m.id = ?)
|
|
65
68
|
ORDER BY m.created_at ASC`,
|
|
69
|
+
params.conversationId,
|
|
66
70
|
params.userMessageCutoff,
|
|
67
71
|
params.assistantMessageId ?? "",
|
|
68
72
|
);
|
|
@@ -123,6 +123,15 @@ describe("trigger-state", () => {
|
|
|
123
123
|
expect(getUserMessageCountUpTo(350)).toBe(3);
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
+
test("counts user messages across standard conversations", () => {
|
|
127
|
+
seedUserMessage(100);
|
|
128
|
+
seedUserMessage(200);
|
|
129
|
+
seedUserMessage(300);
|
|
130
|
+
seedUserMessage(400);
|
|
131
|
+
|
|
132
|
+
expect(getUserMessageCountUpTo(400)).toBe(4);
|
|
133
|
+
});
|
|
134
|
+
|
|
126
135
|
test("caps at 11 due to LIMIT", () => {
|
|
127
136
|
for (let i = 1; i <= 15; i++) {
|
|
128
137
|
seedUserMessage(i * 100);
|
|
@@ -16,6 +16,10 @@ function guardPath(): string {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Count user messages in standard conversations with created_at <= beforeOrAt.
|
|
19
|
+
* This is intentionally cross-conversation: a user who starts a new thread
|
|
20
|
+
* early should still enter the proactive artifact trigger window. The job
|
|
21
|
+
* separately scopes raw transcript context to the triggering conversation.
|
|
22
|
+
*
|
|
19
23
|
* LIMIT caps scan cost since we only care about thresholds up to TRIGGER_MAX.
|
|
20
24
|
*/
|
|
21
25
|
export function getUserMessageCountUpTo(beforeOrAt: number): number {
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the Background Conversation gating in buildSystemPrompt.
|
|
3
|
+
*
|
|
4
|
+
* The Background Conversation guidance is gated on
|
|
5
|
+
* `options.isBackgroundConversation === true`. Interactive (default)
|
|
6
|
+
* conversations must pay zero token cost — the section must be entirely
|
|
7
|
+
* absent unless the flag is explicitly true.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { mkdirSync } from "node:fs";
|
|
11
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
|
+
|
|
13
|
+
const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
14
|
+
|
|
15
|
+
const noopLogger: Record<string, unknown> = new Proxy(
|
|
16
|
+
{} as Record<string, unknown>,
|
|
17
|
+
{
|
|
18
|
+
get: (_target, prop) => (prop === "child" ? () => noopLogger : () => {}),
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
23
|
+
const realLogger = require("../../util/logger.js");
|
|
24
|
+
mock.module("../../util/logger.js", () => ({
|
|
25
|
+
...realLogger,
|
|
26
|
+
getLogger: () => noopLogger,
|
|
27
|
+
getCliLogger: () => noopLogger,
|
|
28
|
+
truncateForLog: (v: string) => v,
|
|
29
|
+
initLogger: () => {},
|
|
30
|
+
pruneOldLogFiles: () => 0,
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
const mockLoadedConfig: Record<string, unknown> = {};
|
|
34
|
+
|
|
35
|
+
mock.module("../../config/loader.js", () => ({
|
|
36
|
+
getConfig: () => ({
|
|
37
|
+
ui: {},
|
|
38
|
+
services: {
|
|
39
|
+
inference: {
|
|
40
|
+
mode: "your-own",
|
|
41
|
+
provider: "anthropic",
|
|
42
|
+
model: "claude-opus-4-6",
|
|
43
|
+
},
|
|
44
|
+
"image-generation": {
|
|
45
|
+
mode: "your-own",
|
|
46
|
+
provider: "gemini",
|
|
47
|
+
model: "gemini-3.1-flash-image-preview",
|
|
48
|
+
},
|
|
49
|
+
"web-search": { mode: "your-own", provider: "inference-provider-native" },
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
loadConfig: () => mockLoadedConfig,
|
|
53
|
+
loadRawConfig: () => ({}),
|
|
54
|
+
saveConfig: () => {},
|
|
55
|
+
saveRawConfig: () => {},
|
|
56
|
+
invalidateConfigCache: () => {},
|
|
57
|
+
getNestedValue: () => undefined,
|
|
58
|
+
setNestedValue: () => {},
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
const { buildSystemPrompt, SYSTEM_PROMPT_CACHE_BOUNDARY } =
|
|
62
|
+
await import("../system-prompt.js");
|
|
63
|
+
|
|
64
|
+
describe("buildSystemPrompt — Background Conversation gating", () => {
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("isBackgroundConversation: true — appends the Background Conversation section", () => {
|
|
70
|
+
const result = buildSystemPrompt({ isBackgroundConversation: true });
|
|
71
|
+
expect(result).toContain("## Background Conversation");
|
|
72
|
+
expect(result).toContain("`notifications` skill");
|
|
73
|
+
expect(result).toContain("assistant notifications send");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("isBackgroundConversation: false — section is omitted", () => {
|
|
77
|
+
const result = buildSystemPrompt({ isBackgroundConversation: false });
|
|
78
|
+
expect(result).not.toContain("## Background Conversation");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("options undefined — section is omitted (interactive default)", () => {
|
|
82
|
+
const result = buildSystemPrompt(undefined);
|
|
83
|
+
expect(result).not.toContain("## Background Conversation");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("options provided without the flag — section is omitted", () => {
|
|
87
|
+
const result = buildSystemPrompt({});
|
|
88
|
+
expect(result).not.toContain("## Background Conversation");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("section lives in the static (cached) block, not the dynamic suffix", () => {
|
|
92
|
+
// The section is deterministic for a given conversationType, so it
|
|
93
|
+
// belongs in staticParts to share the cache block with other
|
|
94
|
+
// call-time-stable instructions.
|
|
95
|
+
const result = buildSystemPrompt({ isBackgroundConversation: true });
|
|
96
|
+
const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
|
|
97
|
+
expect(boundaryIdx).toBeGreaterThan(-1);
|
|
98
|
+
const staticBlock = result.slice(0, boundaryIdx);
|
|
99
|
+
const dynamicBlock = result.slice(
|
|
100
|
+
boundaryIdx + SYSTEM_PROMPT_CACHE_BOUNDARY.length,
|
|
101
|
+
);
|
|
102
|
+
expect(staticBlock).toContain("## Background Conversation");
|
|
103
|
+
expect(dynamicBlock).not.toContain("## Background Conversation");
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -219,10 +219,19 @@ export function ensurePromptFiles(): void {
|
|
|
219
219
|
export interface BuildSystemPromptOptions {
|
|
220
220
|
hasNoClient?: boolean;
|
|
221
221
|
excludeBootstrap?: boolean;
|
|
222
|
+
excludeCustomPrefix?: boolean;
|
|
222
223
|
userPersona?: string | null;
|
|
223
224
|
channelPersona?: string | null;
|
|
224
225
|
userSlug?: string | null;
|
|
225
226
|
onboardingContext?: OnboardingContext;
|
|
227
|
+
/**
|
|
228
|
+
* When true, append the Background Conversation guidance instructing the
|
|
229
|
+
* model to invoke the `notifications` skill for progress, blockers, and
|
|
230
|
+
* completion. Set by callers when running a non-interactive
|
|
231
|
+
* background/scheduled conversation. Interactive conversations leave this
|
|
232
|
+
* unset so they pay zero token cost.
|
|
233
|
+
*/
|
|
234
|
+
isBackgroundConversation?: boolean;
|
|
226
235
|
}
|
|
227
236
|
|
|
228
237
|
/**
|
|
@@ -242,7 +251,8 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
242
251
|
// (IDENTITY.md, SOUL.md, users/<slug>.md, etc.) are edited between turns.
|
|
243
252
|
const staticParts: string[] = [];
|
|
244
253
|
const customPrefix = readCustomSystemPromptPrefix();
|
|
245
|
-
if (customPrefix
|
|
254
|
+
if (customPrefix && !options?.excludeCustomPrefix)
|
|
255
|
+
staticParts.push(customPrefix);
|
|
246
256
|
staticParts.push(buildParallelToolCallsSection());
|
|
247
257
|
if (getIsContainerized()) staticParts.push(buildContainerizedSection());
|
|
248
258
|
staticParts.push(buildCliReferenceSection());
|
|
@@ -254,6 +264,9 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
254
264
|
staticParts.push(buildAccessPreferenceSection(hasNoClient));
|
|
255
265
|
staticParts.push(buildCredentialSecuritySection());
|
|
256
266
|
staticParts.push(buildExternalContentSection());
|
|
267
|
+
if (options?.isBackgroundConversation) {
|
|
268
|
+
staticParts.push(buildBackgroundConversationSection());
|
|
269
|
+
}
|
|
257
270
|
// Memory Persistence, Memory Recall, Workspace Reflection, Learning from Mistakes
|
|
258
271
|
// sections removed — guidance lives in memory_manage/memory_recall tool descriptions
|
|
259
272
|
// and the Proactive Workspace Editing subsection in Configuration.
|
|
@@ -407,6 +420,14 @@ function buildExternalContentSection(): string {
|
|
|
407
420
|
].join("\n");
|
|
408
421
|
}
|
|
409
422
|
|
|
423
|
+
function buildBackgroundConversationSection(): string {
|
|
424
|
+
return [
|
|
425
|
+
"## Background Conversation",
|
|
426
|
+
"",
|
|
427
|
+
'You are running as a non-interactive background job — the user is not watching this conversation. To surface progress, blockers, or completion to the user, invoke the `notifications` skill (`assistant notifications send --message "..." --source-channel assistant_tool --is-async-background`). Finishing silently means the user sees nothing.',
|
|
428
|
+
].join("\n");
|
|
429
|
+
}
|
|
430
|
+
|
|
410
431
|
function buildIntegrationSection(): string {
|
|
411
432
|
let connections: { provider: string; accountInfo?: string | null }[];
|
|
412
433
|
try {
|
|
@@ -2,14 +2,12 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
|
|
4
4
|
import { getConfig } from "../config/loader.js";
|
|
5
|
-
import { INTERNAL_GUARDIAN_TRUST_CONTEXT } from "../daemon/trust-context.js";
|
|
6
5
|
import {
|
|
7
6
|
getMemoryCheckpoint,
|
|
8
7
|
setMemoryCheckpoint,
|
|
9
8
|
} from "../memory/checkpoints.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { wakeAgentForOpportunity } from "../runtime/agent-wake.js";
|
|
9
|
+
import { runBackgroundJob } from "../runtime/background-job-runner.js";
|
|
10
|
+
import { hasReceivedUserMessage } from "../runtime/pre-first-message-gate.js";
|
|
13
11
|
import { getLogger } from "../util/logger.js";
|
|
14
12
|
import {
|
|
15
13
|
getWorkspaceDirDisplay,
|
|
@@ -20,6 +18,12 @@ const log = getLogger("update-bulletin-job");
|
|
|
20
18
|
|
|
21
19
|
const HASH_CHECKPOINT_KEY = "updates:last_processed_hash";
|
|
22
20
|
const EMPTY_HASH = "empty";
|
|
21
|
+
/**
|
|
22
|
+
* Hard timeout for the update-bulletin agent turn. The agent reads a small
|
|
23
|
+
* markdown file and (usually) deletes it; 10 minutes is generous headroom for
|
|
24
|
+
* a slow model + any tool calls (e.g. memory writes).
|
|
25
|
+
*/
|
|
26
|
+
const UPDATE_BULLETIN_TIMEOUT_MS = 10 * 60 * 1000;
|
|
23
27
|
|
|
24
28
|
function updateBulletinHint(): string {
|
|
25
29
|
const workspace = getWorkspaceDirDisplay();
|
|
@@ -47,31 +51,48 @@ function readTrimmedContent(path: string): ReadResult {
|
|
|
47
51
|
/**
|
|
48
52
|
* Fire-and-forget background processor for the release-notes bulletin.
|
|
49
53
|
*
|
|
50
|
-
* If `<workspace>/UPDATES.md` has new (unprocessed) content, this
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
+
* If `<workspace>/UPDATES.md` has new (unprocessed) content, this drives a
|
|
55
|
+
* background conversation through `runBackgroundJob` with a hint pointing at
|
|
56
|
+
* the file. De-duplication uses a sha256 content hash stored in the
|
|
57
|
+
* `updates:last_processed_hash` memory checkpoint — an `"empty"` sentinel
|
|
54
58
|
* represents a missing/blank file so the job skips the common no-op case.
|
|
55
59
|
*
|
|
56
|
-
* The function never throws: any error inside
|
|
57
|
-
*
|
|
58
|
-
*
|
|
60
|
+
* The function never throws: any error inside `runBackgroundJob` is captured
|
|
61
|
+
* in its structured result (which already emits an `activity.failed`
|
|
62
|
+
* notification) and surrounding errors are logged at `warn` and swallowed,
|
|
63
|
+
* so callers can safely invoke it in a non-awaited context.
|
|
59
64
|
*
|
|
60
65
|
* Checkpoint write rules (intentionally conservative — prefer retry over
|
|
61
66
|
* poisoning the checkpoint when state is ambiguous):
|
|
62
67
|
* - File missing → checkpoint = `EMPTY_HASH`.
|
|
63
68
|
* - File present but unreadable → checkpoint UNCHANGED, warn logged.
|
|
64
|
-
* -
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* -
|
|
68
|
-
*
|
|
69
|
+
* - `runBackgroundJob` returned `ok: false` → checkpoint UNCHANGED so the
|
|
70
|
+
* next startup retries. The runner has already emitted an
|
|
71
|
+
* `activity.failed` notification.
|
|
72
|
+
* - Job ran successfully + file deleted/empty → checkpoint = `EMPTY_HASH`.
|
|
73
|
+
* - Job ran successfully + file unchanged → checkpoint = current hash
|
|
74
|
+
* (agent intentionally left the file).
|
|
69
75
|
*/
|
|
70
76
|
export async function runUpdateBulletinJobIfNeeded(): Promise<void> {
|
|
71
77
|
if (getConfig().updates.enabled === false) {
|
|
72
78
|
return;
|
|
73
79
|
}
|
|
74
80
|
|
|
81
|
+
// Warm-pool guard: don't process release notes before a real user has
|
|
82
|
+
// interacted with the assistant. Provider credentials are typically not
|
|
83
|
+
// registered until the user hatches the image, so this job would fail
|
|
84
|
+
// and leave a "Background job failed: update-bulletin" row in the
|
|
85
|
+
// sidebar the user inherits at hatch time. The checkpoint is left
|
|
86
|
+
// untouched on purpose — once the user sends their first message, the
|
|
87
|
+
// job runs on the next daemon start (or after the next UPDATES.md
|
|
88
|
+
// change) with normal semantics.
|
|
89
|
+
if (!hasReceivedUserMessage()) {
|
|
90
|
+
log.info(
|
|
91
|
+
"update-bulletin-job: skipped — daemon has not received a first user message yet",
|
|
92
|
+
);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
75
96
|
try {
|
|
76
97
|
const updatesPath = getWorkspacePromptPath("UPDATES.md");
|
|
77
98
|
const initial = readTrimmedContent(updatesPath);
|
|
@@ -98,60 +119,39 @@ export async function runUpdateBulletinJobIfNeeded(): Promise<void> {
|
|
|
98
119
|
return;
|
|
99
120
|
}
|
|
100
121
|
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
source: "
|
|
122
|
+
const result = await runBackgroundJob({
|
|
123
|
+
jobName: "update-bulletin",
|
|
124
|
+
source: "update-bulletin",
|
|
104
125
|
origin: "updates_bulletin",
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
trustContext: INTERNAL_GUARDIAN_TRUST_CONTEXT,
|
|
126
|
+
prompt: updateBulletinHint(),
|
|
127
|
+
trustContext: {
|
|
128
|
+
sourceChannel: "vellum",
|
|
129
|
+
trustClass: "guardian",
|
|
130
|
+
},
|
|
131
|
+
callSite: "mainAgent",
|
|
132
|
+
timeoutMs: UPDATE_BULLETIN_TIMEOUT_MS,
|
|
113
133
|
});
|
|
114
134
|
|
|
115
|
-
if (!
|
|
135
|
+
if (!result.ok) {
|
|
116
136
|
log.warn(
|
|
117
|
-
{
|
|
118
|
-
|
|
137
|
+
{
|
|
138
|
+
conversationId: result.conversationId,
|
|
139
|
+
errorKind: result.errorKind,
|
|
140
|
+
err: result.error?.message,
|
|
141
|
+
},
|
|
142
|
+
"update-bulletin-job: runBackgroundJob returned ok=false; leaving checkpoint unchanged so next startup retries (failure notification already emitted by runner)",
|
|
119
143
|
);
|
|
120
|
-
// Belt-and-suspenders cleanup: `wakeAgentForOpportunity()` can return
|
|
121
|
-
// `{invoked: false}` for reasons unrelated to the wake-resolver
|
|
122
|
-
// registration order (resolver returns null because the conversation
|
|
123
|
-
// cannot be hydrated, etc.). Without this cleanup each such occurrence
|
|
124
|
-
// leaks a conversation DB row.
|
|
125
|
-
//
|
|
126
|
-
// Wrapped in its own try/catch so a cleanup failure never propagates
|
|
127
|
-
// out of this fire-and-forget task.
|
|
128
|
-
//
|
|
129
|
-
// TODO: the `queueGenerateConversationTitle()` call that
|
|
130
|
-
// `bootstrapConversation()` fires is already in flight by the time we
|
|
131
|
-
// reach here. The title service checks `isReplaceableTitle()` before
|
|
132
|
-
// writing, but the LLM sidechain call itself still runs against the
|
|
133
|
-
// now-deleted conversation id. Adding a cancellation/existence hook
|
|
134
|
-
// in `conversation-title-service.ts` would plug this one-call waste,
|
|
135
|
-
// but this code path is rare, so we accept the one-time cost.
|
|
136
|
-
try {
|
|
137
|
-
deleteConversation(conv.id);
|
|
138
|
-
} catch (err) {
|
|
139
|
-
log.warn(
|
|
140
|
-
{ err, conversationId: conv.id },
|
|
141
|
-
"update-bulletin-job: failed to delete orphan background conversation; continuing",
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
// Re-read after the
|
|
148
|
-
// or modified to decide whether to advance the checkpoint.
|
|
147
|
+
// Re-read after the job completed. We need to know whether the file was
|
|
148
|
+
// deleted or modified to decide whether to advance the checkpoint.
|
|
149
149
|
const after = readTrimmedContent(updatesPath);
|
|
150
150
|
|
|
151
151
|
if (after.kind === "error") {
|
|
152
152
|
log.warn(
|
|
153
153
|
{ err: after.err, path: updatesPath },
|
|
154
|
-
"update-bulletin-job: failed to re-read UPDATES.md after
|
|
154
|
+
"update-bulletin-job: failed to re-read UPDATES.md after job; leaving checkpoint unchanged so next startup retries",
|
|
155
155
|
);
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
@@ -166,26 +166,14 @@ export async function runUpdateBulletinJobIfNeeded(): Promise<void> {
|
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
// to no-op" from "silent failure", so leave the checkpoint alone and
|
|
173
|
-
// let the next startup retry.
|
|
174
|
-
log.warn(
|
|
175
|
-
{ conversationId: conv.id },
|
|
176
|
-
"update-bulletin-job: wake produced no tool calls and file is unchanged; leaving checkpoint unchanged so next startup retries",
|
|
177
|
-
);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Wake produced tool calls and the file is still present — the agent
|
|
182
|
-
// intentionally left it (or modified it). Record the current hash so we
|
|
183
|
-
// don't re-wake on the same content.
|
|
169
|
+
// Job succeeded and the file is still present — the agent intentionally
|
|
170
|
+
// left it (or modified it). Record the current hash so we don't re-process
|
|
171
|
+
// the same content on next startup.
|
|
184
172
|
setMemoryCheckpoint(HASH_CHECKPOINT_KEY, computeHash(after.content));
|
|
185
173
|
} catch (err) {
|
|
186
174
|
log.warn(
|
|
187
175
|
{ err },
|
|
188
|
-
"update-bulletin-job:
|
|
176
|
+
"update-bulletin-job: outer flow threw; swallowing so callers can fire-and-forget",
|
|
189
177
|
);
|
|
190
178
|
return;
|
|
191
179
|
}
|