@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
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the external plugin loader.
|
|
3
|
+
*
|
|
4
|
+
* The loader now owns the timeout / try-catch / `registerPlugin` triple
|
|
5
|
+
* directly, so tests exercise observable behavior: after
|
|
6
|
+
* `await loadExternalPlugin(dir)`, what does the registry hold?
|
|
7
|
+
*
|
|
8
|
+
* Each test materializes a synthetic plugin directory under a per-file
|
|
9
|
+
* tempdir. Surface files use plain TypeScript with default exports so
|
|
10
|
+
* bun can dynamic-import them at runtime without a build step.
|
|
11
|
+
*/
|
|
12
|
+
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { tmpdir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { afterAll, beforeEach, describe, expect, test } from "bun:test";
|
|
16
|
+
|
|
17
|
+
import { loadExternalPlugin } from "../plugins/external-plugin-loader.js";
|
|
18
|
+
import {
|
|
19
|
+
getRegisteredPlugins,
|
|
20
|
+
resetPluginRegistryForTests,
|
|
21
|
+
} from "../plugins/registry.js";
|
|
22
|
+
|
|
23
|
+
const ROOT = join(
|
|
24
|
+
tmpdir(),
|
|
25
|
+
`vellum-external-plugin-loader-test-${process.pid}-${Date.now()}`,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
function freshPluginDir(name: string): string {
|
|
29
|
+
const dir = join(ROOT, name);
|
|
30
|
+
rmSync(dir, { recursive: true, force: true });
|
|
31
|
+
mkdirSync(dir, { recursive: true });
|
|
32
|
+
return dir;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function writePackageJson(dir: string, pkg: Record<string, unknown>): void {
|
|
36
|
+
writeFileSync(join(dir, "package.json"), JSON.stringify(pkg, null, 2));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function writeSurfaceFile(dir: string, relPath: string, body: string): void {
|
|
40
|
+
const parts = relPath.split("/");
|
|
41
|
+
parts.pop();
|
|
42
|
+
if (parts.length > 0) {
|
|
43
|
+
mkdirSync(join(dir, ...parts), { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
writeFileSync(join(dir, relPath), body);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function registeredNames(): string[] {
|
|
49
|
+
return getRegisteredPlugins().map((p) => p.manifest.name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
resetPluginRegistryForTests();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
afterAll(() => {
|
|
57
|
+
rmSync(ROOT, { recursive: true, force: true });
|
|
58
|
+
resetPluginRegistryForTests();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("loadExternalPlugin — manifest", () => {
|
|
62
|
+
test("uses package.json name and version", async () => {
|
|
63
|
+
const dir = freshPluginDir("minimal");
|
|
64
|
+
writePackageJson(dir, { name: "minimal-plugin", version: "1.2.3" });
|
|
65
|
+
|
|
66
|
+
await loadExternalPlugin(dir);
|
|
67
|
+
|
|
68
|
+
const registered = getRegisteredPlugins().find(
|
|
69
|
+
(p) => p.manifest.name === "minimal-plugin",
|
|
70
|
+
);
|
|
71
|
+
expect(registered).toBeDefined();
|
|
72
|
+
expect(registered?.manifest.version).toBe("1.2.3");
|
|
73
|
+
// Defaults to pluginRuntime v1 when no `vellum.requires` is set.
|
|
74
|
+
expect(registered?.manifest.requires).toEqual({ pluginRuntime: "v1" });
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("strips npm scope from name", async () => {
|
|
78
|
+
const dir = freshPluginDir("scoped");
|
|
79
|
+
writePackageJson(dir, {
|
|
80
|
+
name: "@vellumai/simple-memory",
|
|
81
|
+
version: "0.1.0",
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await loadExternalPlugin(dir);
|
|
85
|
+
|
|
86
|
+
expect(registeredNames()).toContain("simple-memory");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("defaults version to 0.0.0 when package.json omits it", async () => {
|
|
90
|
+
const dir = freshPluginDir("no-version");
|
|
91
|
+
writePackageJson(dir, { name: "no-version-plugin" });
|
|
92
|
+
|
|
93
|
+
await loadExternalPlugin(dir);
|
|
94
|
+
|
|
95
|
+
const registered = getRegisteredPlugins().find(
|
|
96
|
+
(p) => p.manifest.name === "no-version-plugin",
|
|
97
|
+
);
|
|
98
|
+
expect(registered?.manifest.version).toBe("0.0.0");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("reads vellum.requires from package.json when present", async () => {
|
|
102
|
+
// Future direction (out of scope this PR): `requires` may carry
|
|
103
|
+
// `assistantVersion` alongside `pluginRuntime`. For today the registry
|
|
104
|
+
// validates against `ASSISTANT_API_VERSIONS` and only `pluginRuntime`
|
|
105
|
+
// is a known capability — so the loader's pass-through behavior is
|
|
106
|
+
// exercised with the keys the registry already accepts. The loader is
|
|
107
|
+
// opaque to the shape; additional keys propagate identically.
|
|
108
|
+
const dir = freshPluginDir("custom-requires");
|
|
109
|
+
writePackageJson(dir, {
|
|
110
|
+
name: "custom-requires",
|
|
111
|
+
version: "0.1.0",
|
|
112
|
+
vellum: { requires: { pluginRuntime: "v1" } },
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
await loadExternalPlugin(dir);
|
|
116
|
+
|
|
117
|
+
const registered = getRegisteredPlugins().find(
|
|
118
|
+
(p) => p.manifest.name === "custom-requires",
|
|
119
|
+
);
|
|
120
|
+
expect(registered?.manifest.requires).toEqual({ pluginRuntime: "v1" });
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("vellum.requires overrides the default — empty requires fails registration", async () => {
|
|
124
|
+
// Belt-and-suspenders proof that the loader reads `vellum.requires`
|
|
125
|
+
// rather than always defaulting: an empty `vellum.requires` propagates
|
|
126
|
+
// through, the registry rejects the plugin (missing pluginRuntime),
|
|
127
|
+
// and the registry stays empty.
|
|
128
|
+
const dir = freshPluginDir("empty-requires");
|
|
129
|
+
writePackageJson(dir, {
|
|
130
|
+
name: "empty-requires",
|
|
131
|
+
version: "0.1.0",
|
|
132
|
+
vellum: { requires: {} },
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
await loadExternalPlugin(dir);
|
|
136
|
+
|
|
137
|
+
expect(registeredNames()).not.toContain("empty-requires");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("does not synthesize a provides field", async () => {
|
|
141
|
+
const dir = freshPluginDir("no-provides");
|
|
142
|
+
writePackageJson(dir, { name: "no-provides", version: "0.1.0" });
|
|
143
|
+
|
|
144
|
+
await loadExternalPlugin(dir);
|
|
145
|
+
|
|
146
|
+
const registered = getRegisteredPlugins().find(
|
|
147
|
+
(p) => p.manifest.name === "no-provides",
|
|
148
|
+
);
|
|
149
|
+
expect(registered?.manifest.provides).toBeUndefined();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("malformed package.json is logged and skipped (registry untouched)", async () => {
|
|
153
|
+
const dir = freshPluginDir("malformed-pkg");
|
|
154
|
+
writeFileSync(join(dir, "package.json"), "{ this is not json");
|
|
155
|
+
|
|
156
|
+
await loadExternalPlugin(dir);
|
|
157
|
+
|
|
158
|
+
expect(registeredNames()).toHaveLength(0);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("package.json missing name is logged and skipped", async () => {
|
|
162
|
+
const dir = freshPluginDir("no-name");
|
|
163
|
+
writePackageJson(dir, { version: "1.0.0" });
|
|
164
|
+
|
|
165
|
+
await loadExternalPlugin(dir);
|
|
166
|
+
|
|
167
|
+
expect(registeredNames()).toHaveLength(0);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("empty string name is logged and skipped", async () => {
|
|
171
|
+
const dir = freshPluginDir("empty-name");
|
|
172
|
+
writePackageJson(dir, { name: "", version: "1.0.0" });
|
|
173
|
+
|
|
174
|
+
await loadExternalPlugin(dir);
|
|
175
|
+
|
|
176
|
+
expect(registeredNames()).toHaveLength(0);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe("loadExternalPlugin — hooks", () => {
|
|
181
|
+
test("wires hooks/init.ts default export to plugin.hooks.init", async () => {
|
|
182
|
+
const dir = freshPluginDir("with-init");
|
|
183
|
+
writePackageJson(dir, { name: "with-init", version: "0.1.0" });
|
|
184
|
+
writeSurfaceFile(
|
|
185
|
+
dir,
|
|
186
|
+
"hooks/init.ts",
|
|
187
|
+
`export default async function init(_ctx: unknown): Promise<void> {
|
|
188
|
+
(globalThis as Record<string, unknown>).__externalInitCalled = true;
|
|
189
|
+
}
|
|
190
|
+
`,
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
await loadExternalPlugin(dir);
|
|
194
|
+
|
|
195
|
+
const registered = getRegisteredPlugins().find(
|
|
196
|
+
(p) => p.manifest.name === "with-init",
|
|
197
|
+
);
|
|
198
|
+
expect(typeof registered?.hooks?.init).toBe("function");
|
|
199
|
+
await registered?.hooks?.init?.({} as never);
|
|
200
|
+
expect(
|
|
201
|
+
(globalThis as Record<string, unknown>).__externalInitCalled,
|
|
202
|
+
).toBe(true);
|
|
203
|
+
delete (globalThis as Record<string, unknown>).__externalInitCalled;
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("wires hooks/shutdown.ts default export to plugin.hooks.shutdown", async () => {
|
|
207
|
+
const dir = freshPluginDir("with-shutdown");
|
|
208
|
+
writePackageJson(dir, { name: "with-shutdown", version: "0.1.0" });
|
|
209
|
+
writeSurfaceFile(
|
|
210
|
+
dir,
|
|
211
|
+
"hooks/shutdown.ts",
|
|
212
|
+
`export default async function shutdown(ctx: { assistantVersion: string }): Promise<void> {
|
|
213
|
+
(globalThis as Record<string, unknown>).__externalShutdownCalled = true;
|
|
214
|
+
(globalThis as Record<string, unknown>).__externalShutdownVersion =
|
|
215
|
+
ctx.assistantVersion;
|
|
216
|
+
}
|
|
217
|
+
`,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
await loadExternalPlugin(dir);
|
|
221
|
+
|
|
222
|
+
const registered = getRegisteredPlugins().find(
|
|
223
|
+
(p) => p.manifest.name === "with-shutdown",
|
|
224
|
+
);
|
|
225
|
+
expect(typeof registered?.hooks?.shutdown).toBe("function");
|
|
226
|
+
await registered?.hooks?.shutdown?.({ assistantVersion: "9.9.9-test" });
|
|
227
|
+
expect(
|
|
228
|
+
(globalThis as Record<string, unknown>).__externalShutdownCalled,
|
|
229
|
+
).toBe(true);
|
|
230
|
+
expect(
|
|
231
|
+
(globalThis as Record<string, unknown>).__externalShutdownVersion,
|
|
232
|
+
).toBe("9.9.9-test");
|
|
233
|
+
delete (globalThis as Record<string, unknown>).__externalShutdownCalled;
|
|
234
|
+
delete (globalThis as Record<string, unknown>).__externalShutdownVersion;
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
test("ignores hooks/*.d.ts declaration files alongside hooks/*.js", async () => {
|
|
238
|
+
// Compiled plugins ship `init.js` + `init.d.ts` side-by-side. The walker
|
|
239
|
+
// must filter the declaration files out — they have no default-exported
|
|
240
|
+
// runtime function, and crashing `importDefault` would skip the plugin
|
|
241
|
+
// wholesale. Regression guard for the .d.ts ingest bug fixed in this PR.
|
|
242
|
+
const dir = freshPluginDir("with-dts");
|
|
243
|
+
writePackageJson(dir, { name: "with-dts", version: "0.1.0" });
|
|
244
|
+
writeSurfaceFile(
|
|
245
|
+
dir,
|
|
246
|
+
"hooks/init.js",
|
|
247
|
+
`export default async function init(_ctx) {
|
|
248
|
+
(globalThis).__externalDtsInitCalled = true;
|
|
249
|
+
}
|
|
250
|
+
`,
|
|
251
|
+
);
|
|
252
|
+
writeSurfaceFile(
|
|
253
|
+
dir,
|
|
254
|
+
"hooks/init.d.ts",
|
|
255
|
+
`export default function init(ctx: unknown): Promise<void>;\n`,
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
await loadExternalPlugin(dir);
|
|
259
|
+
|
|
260
|
+
const registered = getRegisteredPlugins().find(
|
|
261
|
+
(p) => p.manifest.name === "with-dts",
|
|
262
|
+
);
|
|
263
|
+
expect(registered).toBeDefined();
|
|
264
|
+
expect(Object.keys(registered?.hooks ?? {})).toEqual(["init"]);
|
|
265
|
+
expect(typeof registered?.hooks?.init).toBe("function");
|
|
266
|
+
await registered?.hooks?.init?.({} as never);
|
|
267
|
+
expect((globalThis as Record<string, unknown>).__externalDtsInitCalled).toBe(
|
|
268
|
+
true,
|
|
269
|
+
);
|
|
270
|
+
delete (globalThis as Record<string, unknown>).__externalDtsInitCalled;
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("plugin.hooks is undefined when neither hook file is present", async () => {
|
|
274
|
+
const dir = freshPluginDir("no-hooks");
|
|
275
|
+
writePackageJson(dir, { name: "no-hooks", version: "0.1.0" });
|
|
276
|
+
|
|
277
|
+
await loadExternalPlugin(dir);
|
|
278
|
+
|
|
279
|
+
const registered = getRegisteredPlugins().find(
|
|
280
|
+
(p) => p.manifest.name === "no-hooks",
|
|
281
|
+
);
|
|
282
|
+
expect(registered?.hooks).toBeUndefined();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test("hooks/init.ts with no default export is logged and skipped", async () => {
|
|
286
|
+
const dir = freshPluginDir("init-no-default");
|
|
287
|
+
writePackageJson(dir, { name: "init-no-default", version: "0.1.0" });
|
|
288
|
+
writeSurfaceFile(
|
|
289
|
+
dir,
|
|
290
|
+
"hooks/init.ts",
|
|
291
|
+
`export const init = async () => undefined;\n`,
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
await loadExternalPlugin(dir);
|
|
295
|
+
|
|
296
|
+
expect(registeredNames()).toHaveLength(0);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test("hooks/init.ts default export not a function is logged and skipped", async () => {
|
|
300
|
+
const dir = freshPluginDir("init-not-fn");
|
|
301
|
+
writePackageJson(dir, { name: "init-not-fn", version: "0.1.0" });
|
|
302
|
+
writeSurfaceFile(
|
|
303
|
+
dir,
|
|
304
|
+
"hooks/init.ts",
|
|
305
|
+
`export default { not: "a function" };\n`,
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
await loadExternalPlugin(dir);
|
|
309
|
+
|
|
310
|
+
expect(registeredNames()).toHaveLength(0);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
describe("loadExternalPlugin — tools", () => {
|
|
315
|
+
test("collects every default-exported tool under tools/", async () => {
|
|
316
|
+
const dir = freshPluginDir("two-tools");
|
|
317
|
+
writePackageJson(dir, { name: "two-tools", version: "0.1.0" });
|
|
318
|
+
writeSurfaceFile(
|
|
319
|
+
dir,
|
|
320
|
+
"tools/alpha.ts",
|
|
321
|
+
`export default {
|
|
322
|
+
name: "two_tools_alpha",
|
|
323
|
+
description: "alpha",
|
|
324
|
+
category: "plugin",
|
|
325
|
+
defaultRiskLevel: "low" as const,
|
|
326
|
+
getDefinition() { return { name: "two_tools_alpha", description: "alpha", input_schema: { type: "object", properties: {}, required: [] } }; },
|
|
327
|
+
async execute() { return { content: "a", isError: false }; },
|
|
328
|
+
};
|
|
329
|
+
`,
|
|
330
|
+
);
|
|
331
|
+
writeSurfaceFile(
|
|
332
|
+
dir,
|
|
333
|
+
"tools/beta.ts",
|
|
334
|
+
`export default {
|
|
335
|
+
name: "two_tools_beta",
|
|
336
|
+
description: "beta",
|
|
337
|
+
category: "plugin",
|
|
338
|
+
defaultRiskLevel: "low" as const,
|
|
339
|
+
getDefinition() { return { name: "two_tools_beta", description: "beta", input_schema: { type: "object", properties: {}, required: [] } }; },
|
|
340
|
+
async execute() { return { content: "b", isError: false }; },
|
|
341
|
+
};
|
|
342
|
+
`,
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
await loadExternalPlugin(dir);
|
|
346
|
+
|
|
347
|
+
const registered = getRegisteredPlugins().find(
|
|
348
|
+
(p) => p.manifest.name === "two-tools",
|
|
349
|
+
);
|
|
350
|
+
const names = (registered?.tools ?? []).map(
|
|
351
|
+
(t) => (t as { name: string }).name,
|
|
352
|
+
);
|
|
353
|
+
expect(names).toEqual(["two_tools_alpha", "two_tools_beta"]);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test("plugin.tools is undefined when tools/ is absent", async () => {
|
|
357
|
+
const dir = freshPluginDir("no-tools");
|
|
358
|
+
writePackageJson(dir, { name: "no-tools", version: "0.1.0" });
|
|
359
|
+
|
|
360
|
+
await loadExternalPlugin(dir);
|
|
361
|
+
|
|
362
|
+
const registered = getRegisteredPlugins().find(
|
|
363
|
+
(p) => p.manifest.name === "no-tools",
|
|
364
|
+
);
|
|
365
|
+
expect(registered?.tools).toBeUndefined();
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
test("a tool file with no default export is logged and skipped", async () => {
|
|
369
|
+
const dir = freshPluginDir("tool-no-default");
|
|
370
|
+
writePackageJson(dir, { name: "tool-no-default", version: "0.1.0" });
|
|
371
|
+
writeSurfaceFile(
|
|
372
|
+
dir,
|
|
373
|
+
"tools/broken.ts",
|
|
374
|
+
`export const broken = { name: "broken" };\n`,
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
await loadExternalPlugin(dir);
|
|
378
|
+
|
|
379
|
+
expect(registeredNames()).toHaveLength(0);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
test("a tool default export missing string name is logged and skipped", async () => {
|
|
383
|
+
const dir = freshPluginDir("tool-no-name");
|
|
384
|
+
writePackageJson(dir, { name: "tool-no-name", version: "0.1.0" });
|
|
385
|
+
writeSurfaceFile(
|
|
386
|
+
dir,
|
|
387
|
+
"tools/nameless.ts",
|
|
388
|
+
`export default { description: "missing name" };\n`,
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
await loadExternalPlugin(dir);
|
|
392
|
+
|
|
393
|
+
expect(registeredNames()).toHaveLength(0);
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
describe("loadExternalPlugin — isolation", () => {
|
|
398
|
+
test("never throws when a load fails — error is logged and skipped", async () => {
|
|
399
|
+
const dir = freshPluginDir("definitely-broken");
|
|
400
|
+
writeFileSync(join(dir, "package.json"), "{ broken");
|
|
401
|
+
|
|
402
|
+
await expect(loadExternalPlugin(dir)).resolves.toBeUndefined();
|
|
403
|
+
expect(registeredNames()).toHaveLength(0);
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
test("times out and skips when build exceeds the timeout", async () => {
|
|
407
|
+
// hooks/init.ts has a top-level await that never resolves. The build
|
|
408
|
+
// hangs on dynamic-importing this surface file; the loader's timeout
|
|
409
|
+
// must rescue the daemon boot.
|
|
410
|
+
const dir = freshPluginDir("hanging-init");
|
|
411
|
+
writePackageJson(dir, { name: "hanging-init", version: "0.1.0" });
|
|
412
|
+
writeSurfaceFile(
|
|
413
|
+
dir,
|
|
414
|
+
"hooks/init.ts",
|
|
415
|
+
`await new Promise(() => {});
|
|
416
|
+
export default async function init(_ctx: unknown): Promise<void> {}
|
|
417
|
+
`,
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
await loadExternalPlugin(dir, { importTimeoutMs: 50 });
|
|
421
|
+
|
|
422
|
+
expect(registeredNames()).not.toContain("hanging-init");
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
describe("loadExternalPlugin — end-to-end @vellumai/simple-memory", () => {
|
|
427
|
+
test("loads the in-tree simple-memory plugin", async () => {
|
|
428
|
+
// Resolve the real on-disk plugin from the worktree. This double-acts
|
|
429
|
+
// as the loader's contract test against the canonical Phase 0 plugin
|
|
430
|
+
// and exercises the relative `../src/state.js` imports inside the
|
|
431
|
+
// plugin's surface files.
|
|
432
|
+
const pluginDir = join(
|
|
433
|
+
import.meta.dir,
|
|
434
|
+
"..",
|
|
435
|
+
"..",
|
|
436
|
+
"..",
|
|
437
|
+
"experimental",
|
|
438
|
+
"plugins",
|
|
439
|
+
"simple-memory",
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
await loadExternalPlugin(pluginDir);
|
|
443
|
+
|
|
444
|
+
const registered = getRegisteredPlugins().find(
|
|
445
|
+
(p) => p.manifest.name === "simple-memory",
|
|
446
|
+
);
|
|
447
|
+
expect(registered).toBeDefined();
|
|
448
|
+
expect(typeof registered?.hooks?.init).toBe("function");
|
|
449
|
+
expect(typeof registered?.hooks?.shutdown).toBe("function");
|
|
450
|
+
const toolNames = (registered?.tools ?? [])
|
|
451
|
+
.map((t) => (t as { name: string }).name)
|
|
452
|
+
.sort();
|
|
453
|
+
expect(toolNames).toEqual([
|
|
454
|
+
"simple_memory_recall",
|
|
455
|
+
"simple_memory_remember",
|
|
456
|
+
]);
|
|
457
|
+
});
|
|
458
|
+
});
|
|
@@ -7,6 +7,13 @@ import { LLMSchema } from "../config/schemas/llm.js";
|
|
|
7
7
|
|
|
8
8
|
const testWorkspaceDir = process.env.VELLUM_WORKSPACE_DIR!;
|
|
9
9
|
|
|
10
|
+
// Default the warm-pool gate to OPEN for existing tests — they predate
|
|
11
|
+
// the gate and expect filing's runOnce() to fire on every tick.
|
|
12
|
+
mock.module("../runtime/pre-first-message-gate.js", () => ({
|
|
13
|
+
hasReceivedUserMessage: () => true,
|
|
14
|
+
_resetPreFirstMessageGateCacheForTests: () => {},
|
|
15
|
+
}));
|
|
16
|
+
|
|
10
17
|
// Mock config loader. Filing's `runOnce()` reads `getConfig().filing`, and
|
|
11
18
|
// `executeRun()` no longer reads `config.speed` (PR 8) — the call site is
|
|
12
19
|
// hardcoded to 'filingAgent' and the resolver picks up `llm.callSites.filingAgent`
|
|
@@ -35,8 +42,12 @@ mock.module("../config/loader.js", () => ({
|
|
|
35
42
|
}));
|
|
36
43
|
|
|
37
44
|
// Mock conversation store
|
|
38
|
-
const createdConversations: Array<{
|
|
39
|
-
|
|
45
|
+
const createdConversations: Array<{
|
|
46
|
+
title: string;
|
|
47
|
+
conversationType: string;
|
|
48
|
+
source?: string;
|
|
49
|
+
groupId?: string;
|
|
50
|
+
}> = [];
|
|
40
51
|
let conversationIdCounter = 0;
|
|
41
52
|
|
|
42
53
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
@@ -63,7 +74,12 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
63
74
|
}),
|
|
64
75
|
getConversationOriginInterface: () => null,
|
|
65
76
|
getConversationOriginChannel: () => null,
|
|
66
|
-
createConversation: (opts: {
|
|
77
|
+
createConversation: (opts: {
|
|
78
|
+
title: string;
|
|
79
|
+
conversationType: string;
|
|
80
|
+
source?: string;
|
|
81
|
+
groupId?: string;
|
|
82
|
+
}) => {
|
|
67
83
|
createdConversations.push(opts);
|
|
68
84
|
return { id: `conv-${++conversationIdCounter}`, ...opts };
|
|
69
85
|
},
|
|
@@ -220,6 +236,10 @@ describe("FilingService", () => {
|
|
|
220
236
|
expect(createdConversations).toHaveLength(1);
|
|
221
237
|
expect(createdConversations[0].title).toBe("Generating title...");
|
|
222
238
|
expect(createdConversations[0].conversationType).toBe("background");
|
|
239
|
+
// Confirms FilingService routes through runBackgroundJob:
|
|
240
|
+
// source="filing" + runner-default groupId="system:background".
|
|
241
|
+
expect(createdConversations[0].source).toBe("filing");
|
|
242
|
+
expect(createdConversations[0].groupId).toBe("system:background");
|
|
223
243
|
});
|
|
224
244
|
|
|
225
245
|
describe("runCompactionOnce()", () => {
|
|
@@ -224,6 +224,11 @@ export function createMockChromeExtension(
|
|
|
224
224
|
headers: {
|
|
225
225
|
"Content-Type": "application/json",
|
|
226
226
|
Authorization: `Bearer ${options.token}`,
|
|
227
|
+
// Same-actor binding: identifies this fixture to the daemon's
|
|
228
|
+
// result-route check. The daemon will reject targeted host_browser
|
|
229
|
+
// results without this header (or where it doesn't match the
|
|
230
|
+
// captured target client).
|
|
231
|
+
"X-Vellum-Client-Id": clientId,
|
|
227
232
|
},
|
|
228
233
|
body: JSON.stringify(body),
|
|
229
234
|
});
|
|
@@ -34,7 +34,6 @@ const ALLOWLIST = new Set([
|
|
|
34
34
|
|
|
35
35
|
// --- Chrome extension (local relay communication, not gateway API consumption) ---
|
|
36
36
|
"clients/chrome-extension/background/worker.ts",
|
|
37
|
-
"clients/chrome-extension/popup/popup.ts",
|
|
38
37
|
// --- Documentation and comments that mention the port for explanatory purposes ---
|
|
39
38
|
"AGENTS.md", // documents the gateway-only rule itself
|
|
40
39
|
"ARCHITECTURE.md", // architecture overview with port references
|
|
@@ -191,6 +191,40 @@ describe("parseExtractionResponse event_date coercion", () => {
|
|
|
191
191
|
expect(diff.updateNodes[0].changes.eventDate).toBe(1712534400000);
|
|
192
192
|
});
|
|
193
193
|
|
|
194
|
+
test("auto-creates an event trigger for future event_date", () => {
|
|
195
|
+
const conversationTs = Date.UTC(2026, 3, 26, 0, 0, 0);
|
|
196
|
+
const futureEventDate = Date.UTC(2026, 5, 1, 0, 0, 0);
|
|
197
|
+
const input = makeInput({ event_date: futureEventDate });
|
|
198
|
+
const { deferredTriggers } = parseExtractionResponse(
|
|
199
|
+
input,
|
|
200
|
+
conversationId,
|
|
201
|
+
scopeId,
|
|
202
|
+
candidateNodeIds,
|
|
203
|
+
conversationTs,
|
|
204
|
+
);
|
|
205
|
+
const auto = deferredTriggers.find(
|
|
206
|
+
(t) =>
|
|
207
|
+
t.trigger.type === "event" && t.trigger.eventDate === futureEventDate,
|
|
208
|
+
);
|
|
209
|
+
expect(auto).toBeTruthy();
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("does not auto-create an event trigger for past event_date", () => {
|
|
213
|
+
const conversationTs = Date.UTC(2026, 3, 26, 0, 0, 0);
|
|
214
|
+
const pastEventDate = Date.UTC(2025, 0, 15, 0, 0, 0);
|
|
215
|
+
const input = makeInput({ event_date: pastEventDate });
|
|
216
|
+
const { deferredTriggers } = parseExtractionResponse(
|
|
217
|
+
input,
|
|
218
|
+
conversationId,
|
|
219
|
+
scopeId,
|
|
220
|
+
candidateNodeIds,
|
|
221
|
+
conversationTs,
|
|
222
|
+
);
|
|
223
|
+
expect(deferredTriggers.some((t) => t.trigger.type === "event")).toBe(
|
|
224
|
+
false,
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
194
228
|
test("null-clears event_date on update_nodes when explicitly null", () => {
|
|
195
229
|
const existingNodeId = "existing-node-1";
|
|
196
230
|
const candidates = new Set([existingNodeId]);
|
|
@@ -245,12 +245,4 @@ describe("v2 skill re-seed gating in skill handlers", () => {
|
|
|
245
245
|
expect(mockMaybeSeedMemoryV2Skills).toHaveBeenCalledTimes(1);
|
|
246
246
|
expect(callOrder).toEqual(["v1"]);
|
|
247
247
|
});
|
|
248
|
-
|
|
249
|
-
// Note: "seed rejection swallowed" is now an internal concern of
|
|
250
|
-
// `maybeSeedMemoryV2Skills` — it dispatches the seed call as a
|
|
251
|
-
// fire-and-forget promise with `.catch(log.warn)`. That behavior is
|
|
252
|
-
// covered by `lifecycle-memory-v2-seed.test.ts`. From the handler's
|
|
253
|
-
// perspective, we only need to verify the helper is invoked
|
|
254
|
-
// synchronously with the correct config — which the cases above already
|
|
255
|
-
// exercise.
|
|
256
248
|
});
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
// Default the warm-pool gate to OPEN — these tests probe disk-pressure
|
|
4
|
+
// behavior, not the pre-first-message guard.
|
|
5
|
+
mock.module("../runtime/pre-first-message-gate.js", () => ({
|
|
6
|
+
hasReceivedUserMessage: () => true,
|
|
7
|
+
_resetPreFirstMessageGateCacheForTests: () => {},
|
|
8
|
+
}));
|
|
9
|
+
|
|
3
10
|
mock.module("../util/logger.js", () => ({
|
|
4
11
|
getLogger: () => ({
|
|
5
12
|
info: () => {},
|
|
@@ -63,6 +70,10 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
63
70
|
createdConversations.push(opts);
|
|
64
71
|
return { id: "conv-1", ...opts };
|
|
65
72
|
},
|
|
73
|
+
// runBackgroundJob (loaded transitively via heartbeat-service) imports
|
|
74
|
+
// addMessage. Disk-pressure short-circuits before addMessage ever runs,
|
|
75
|
+
// but the mock module must still expose every name the real module does.
|
|
76
|
+
addMessage: () => Promise.resolve({ id: "mock-msg-id" }),
|
|
66
77
|
}));
|
|
67
78
|
|
|
68
79
|
const mockProcessMessage = mock(() => Promise.resolve({ messageId: "msg-1" }));
|
|
@@ -70,9 +81,11 @@ mock.module("../daemon/process-message.js", () => ({
|
|
|
70
81
|
processMessage: mockProcessMessage,
|
|
71
82
|
}));
|
|
72
83
|
|
|
73
|
-
const
|
|
74
|
-
mock.module("../
|
|
75
|
-
|
|
84
|
+
const emittedNotificationSignals: Array<{ sourceEventName?: string }> = [];
|
|
85
|
+
mock.module("../notifications/emit-signal.js", () => ({
|
|
86
|
+
emitNotificationSignal: async (opts: { sourceEventName?: string }) => {
|
|
87
|
+
emittedNotificationSignals.push({ sourceEventName: opts.sourceEventName });
|
|
88
|
+
},
|
|
76
89
|
}));
|
|
77
90
|
|
|
78
91
|
mock.module("../prompts/persona-resolver.js", () => ({
|
|
@@ -131,10 +144,10 @@ describe("HeartbeatService disk pressure gate", () => {
|
|
|
131
144
|
mockMarkStaleRunningAsError.mockClear();
|
|
132
145
|
mockMarkStaleRunningAsError.mockImplementation(() => 0);
|
|
133
146
|
mockProcessMessage.mockClear();
|
|
134
|
-
|
|
147
|
+
emittedNotificationSignals.length = 0;
|
|
135
148
|
});
|
|
136
149
|
|
|
137
|
-
test("skips without creating heartbeat rows, conversations, or
|
|
150
|
+
test("skips without creating heartbeat rows, conversations, or notifications", async () => {
|
|
138
151
|
const service = new HeartbeatService({
|
|
139
152
|
alerter: () => {},
|
|
140
153
|
});
|
|
@@ -148,7 +161,7 @@ describe("HeartbeatService disk pressure gate", () => {
|
|
|
148
161
|
expect(mockSkipHeartbeatRun).not.toHaveBeenCalled();
|
|
149
162
|
expect(createdConversations).toHaveLength(0);
|
|
150
163
|
expect(mockProcessMessage).not.toHaveBeenCalled();
|
|
151
|
-
expect(
|
|
164
|
+
expect(emittedNotificationSignals).toHaveLength(0);
|
|
152
165
|
});
|
|
153
166
|
|
|
154
167
|
test("allows forced user-initiated heartbeat runs while locked", async () => {
|
|
@@ -168,7 +181,7 @@ describe("HeartbeatService disk pressure gate", () => {
|
|
|
168
181
|
expect(mockProcessMessage).toHaveBeenCalledTimes(1);
|
|
169
182
|
});
|
|
170
183
|
|
|
171
|
-
test("start recovery skips missed-run
|
|
184
|
+
test("start recovery skips missed-run notifications while locked", async () => {
|
|
172
185
|
mockMarkStaleRunsAsMissed.mockImplementationOnce(() => 1);
|
|
173
186
|
const service = new HeartbeatService({
|
|
174
187
|
alerter: () => {},
|
|
@@ -178,6 +191,6 @@ describe("HeartbeatService disk pressure gate", () => {
|
|
|
178
191
|
await service.stop();
|
|
179
192
|
|
|
180
193
|
expect(mockMarkStaleRunsAsMissed).toHaveBeenCalledTimes(1);
|
|
181
|
-
expect(
|
|
194
|
+
expect(emittedNotificationSignals).toHaveLength(0);
|
|
182
195
|
});
|
|
183
196
|
});
|