@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
|
@@ -16,6 +16,63 @@ mock.module("../util/logger.js", () => ({
|
|
|
16
16
|
truncateForLog: (value: string) => value,
|
|
17
17
|
}));
|
|
18
18
|
|
|
19
|
+
// Mock the shared `runBackgroundJob` runner so the scheduler's fresh-bootstrap
|
|
20
|
+
// talk-mode path stays observable in unit tests. Each invocation creates a new
|
|
21
|
+
// conversation row (so `getLastScheduleConversationId` lookups reflect reality)
|
|
22
|
+
// and pushes onto a shared log mirrored by the per-test `processMessage`
|
|
23
|
+
// callback used for the reuse path — that way assertions don't have to know
|
|
24
|
+
// which path a given run took.
|
|
25
|
+
const processedMessages: { conversationId: string; message: string }[] = [];
|
|
26
|
+
const runBackgroundJobOptions: Array<{
|
|
27
|
+
conversationType?: string;
|
|
28
|
+
scheduleJobId?: string;
|
|
29
|
+
groupId?: string;
|
|
30
|
+
suppressFailureNotifications?: boolean;
|
|
31
|
+
onConversationCreated?: (id: string) => void;
|
|
32
|
+
}> = [];
|
|
33
|
+
let runBackgroundJobShouldFail = false;
|
|
34
|
+
mock.module("../runtime/background-job-runner.js", () => ({
|
|
35
|
+
runBackgroundJob: async (opts: {
|
|
36
|
+
prompt: string;
|
|
37
|
+
groupId?: string;
|
|
38
|
+
conversationType?: "background" | "scheduled";
|
|
39
|
+
scheduleJobId?: string;
|
|
40
|
+
suppressFailureNotifications?: boolean;
|
|
41
|
+
onConversationCreated?: (id: string) => void;
|
|
42
|
+
}) => {
|
|
43
|
+
const { createConversation } =
|
|
44
|
+
await import("../memory/conversation-crud.js");
|
|
45
|
+
const conv = createConversation({
|
|
46
|
+
title: "(test stub)",
|
|
47
|
+
conversationType: opts.conversationType ?? "background",
|
|
48
|
+
source: "schedule",
|
|
49
|
+
...(opts.groupId ? { groupId: opts.groupId } : {}),
|
|
50
|
+
...(opts.scheduleJobId ? { scheduleJobId: opts.scheduleJobId } : {}),
|
|
51
|
+
});
|
|
52
|
+
runBackgroundJobOptions.push({
|
|
53
|
+
conversationType: opts.conversationType,
|
|
54
|
+
scheduleJobId: opts.scheduleJobId,
|
|
55
|
+
groupId: opts.groupId,
|
|
56
|
+
suppressFailureNotifications: opts.suppressFailureNotifications,
|
|
57
|
+
onConversationCreated: opts.onConversationCreated,
|
|
58
|
+
});
|
|
59
|
+
// Mirror the real runner's contract: fire the SSE callback synchronously
|
|
60
|
+
// BEFORE the job's processMessage finishes, with the bootstrap-returned
|
|
61
|
+
// conversation id.
|
|
62
|
+
opts.onConversationCreated?.(conv.id);
|
|
63
|
+
processedMessages.push({ conversationId: conv.id, message: opts.prompt });
|
|
64
|
+
if (runBackgroundJobShouldFail) {
|
|
65
|
+
return {
|
|
66
|
+
conversationId: conv.id,
|
|
67
|
+
ok: false,
|
|
68
|
+
error: new Error("Simulated failure"),
|
|
69
|
+
errorKind: "exception" as const,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return { conversationId: conv.id, ok: true };
|
|
73
|
+
},
|
|
74
|
+
}));
|
|
75
|
+
|
|
19
76
|
import { deleteConversation } from "../memory/conversation-crud.js";
|
|
20
77
|
import { getDb } from "../memory/db-connection.js";
|
|
21
78
|
import { initializeDb } from "../memory/db-init.js";
|
|
@@ -77,6 +134,9 @@ describe("scheduler conversation reuse", () => {
|
|
|
77
134
|
db.run("DELETE FROM tasks");
|
|
78
135
|
db.run("DELETE FROM messages");
|
|
79
136
|
db.run("DELETE FROM conversations");
|
|
137
|
+
processedMessages.length = 0;
|
|
138
|
+
runBackgroundJobOptions.length = 0;
|
|
139
|
+
runBackgroundJobShouldFail = false;
|
|
80
140
|
});
|
|
81
141
|
|
|
82
142
|
test("recurring schedule with reuseConversation=true reuses conversation across runs", async () => {
|
|
@@ -99,7 +159,6 @@ describe("scheduler conversation reuse", () => {
|
|
|
99
159
|
// WHEN the schedule fires for the first time
|
|
100
160
|
forceScheduleDue(schedule.id);
|
|
101
161
|
|
|
102
|
-
const processedMessages: { conversationId: string; message: string }[] = [];
|
|
103
162
|
const processMessage = async (conversationId: string, message: string) => {
|
|
104
163
|
processedMessages.push({ conversationId, message });
|
|
105
164
|
};
|
|
@@ -156,7 +215,6 @@ describe("scheduler conversation reuse", () => {
|
|
|
156
215
|
// WHEN the schedule fires for the first time
|
|
157
216
|
forceScheduleDue(schedule.id);
|
|
158
217
|
|
|
159
|
-
const processedMessages: { conversationId: string; message: string }[] = [];
|
|
160
218
|
const processMessage = async (conversationId: string, message: string) => {
|
|
161
219
|
processedMessages.push({ conversationId, message });
|
|
162
220
|
};
|
|
@@ -200,7 +258,6 @@ describe("scheduler conversation reuse", () => {
|
|
|
200
258
|
|
|
201
259
|
forceScheduleDue(schedule.id);
|
|
202
260
|
|
|
203
|
-
const processedMessages: { conversationId: string; message: string }[] = [];
|
|
204
261
|
const processMessage = async (conversationId: string, message: string) => {
|
|
205
262
|
processedMessages.push({ conversationId, message });
|
|
206
263
|
};
|
|
@@ -245,7 +302,6 @@ describe("scheduler conversation reuse", () => {
|
|
|
245
302
|
});
|
|
246
303
|
|
|
247
304
|
// WHEN the schedule fires
|
|
248
|
-
const processedMessages: { conversationId: string; message: string }[] = [];
|
|
249
305
|
const processMessage = async (conversationId: string, message: string) => {
|
|
250
306
|
processedMessages.push({ conversationId, message });
|
|
251
307
|
};
|
|
@@ -285,7 +341,6 @@ describe("scheduler conversation reuse", () => {
|
|
|
285
341
|
forceScheduleDue(schedule.id);
|
|
286
342
|
|
|
287
343
|
let shouldFail = false;
|
|
288
|
-
const processedMessages: { conversationId: string; message: string }[] = [];
|
|
289
344
|
const processMessage = async (conversationId: string, message: string) => {
|
|
290
345
|
processedMessages.push({ conversationId, message });
|
|
291
346
|
if (shouldFail) throw new Error("Simulated failure");
|
|
@@ -327,3 +382,104 @@ describe("scheduler conversation reuse", () => {
|
|
|
327
382
|
expect(processedMessages[0].conversationId).toBe(successConversationId);
|
|
328
383
|
});
|
|
329
384
|
});
|
|
385
|
+
|
|
386
|
+
describe("scheduler talk-mode runner option propagation", () => {
|
|
387
|
+
beforeEach(() => {
|
|
388
|
+
const db = getDb();
|
|
389
|
+
db.run("DELETE FROM cron_runs");
|
|
390
|
+
db.run("DELETE FROM cron_jobs");
|
|
391
|
+
db.run("DELETE FROM messages");
|
|
392
|
+
db.run("DELETE FROM conversations");
|
|
393
|
+
processedMessages.length = 0;
|
|
394
|
+
runBackgroundJobOptions.length = 0;
|
|
395
|
+
runBackgroundJobShouldFail = false;
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
test("talk-mode propagates conversationType=scheduled, scheduleJobId, and quiet=>suppressFailureNotifications", async () => {
|
|
399
|
+
const rruleExpr = buildEveryMinuteRrule();
|
|
400
|
+
const schedule = createSchedule({
|
|
401
|
+
name: "Quiet Talk Mode",
|
|
402
|
+
cronExpression: rruleExpr,
|
|
403
|
+
message: "Background work",
|
|
404
|
+
syntax: "rrule",
|
|
405
|
+
expression: rruleExpr,
|
|
406
|
+
quiet: true,
|
|
407
|
+
});
|
|
408
|
+
forceScheduleDue(schedule.id);
|
|
409
|
+
|
|
410
|
+
const processMessage = async () => {};
|
|
411
|
+
const scheduler = startScheduler(processMessage, () => {});
|
|
412
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
413
|
+
scheduler.stop();
|
|
414
|
+
|
|
415
|
+
expect(runBackgroundJobOptions).toHaveLength(1);
|
|
416
|
+
const opts = runBackgroundJobOptions[0]!;
|
|
417
|
+
expect(opts.conversationType).toBe("scheduled");
|
|
418
|
+
expect(opts.scheduleJobId).toBe(schedule.id);
|
|
419
|
+
expect(opts.groupId).toBe("system:scheduled");
|
|
420
|
+
expect(opts.suppressFailureNotifications).toBe(true);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test("talk-mode without quiet leaves suppressFailureNotifications=false", async () => {
|
|
424
|
+
const rruleExpr = buildEveryMinuteRrule();
|
|
425
|
+
const schedule = createSchedule({
|
|
426
|
+
name: "Loud Talk Mode",
|
|
427
|
+
cronExpression: rruleExpr,
|
|
428
|
+
message: "Background work",
|
|
429
|
+
syntax: "rrule",
|
|
430
|
+
expression: rruleExpr,
|
|
431
|
+
// quiet defaults to false
|
|
432
|
+
});
|
|
433
|
+
forceScheduleDue(schedule.id);
|
|
434
|
+
|
|
435
|
+
const processMessage = async () => {};
|
|
436
|
+
const scheduler = startScheduler(processMessage, () => {});
|
|
437
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
438
|
+
scheduler.stop();
|
|
439
|
+
|
|
440
|
+
expect(runBackgroundJobOptions).toHaveLength(1);
|
|
441
|
+
expect(runBackgroundJobOptions[0]!.suppressFailureNotifications).toBe(
|
|
442
|
+
false,
|
|
443
|
+
);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
test("talk-mode fires onScheduleConversationCreated synchronously via runner callback (BEFORE the runner returns)", async () => {
|
|
447
|
+
const rruleExpr = buildEveryMinuteRrule();
|
|
448
|
+
const schedule = createSchedule({
|
|
449
|
+
name: "SSE timing",
|
|
450
|
+
cronExpression: rruleExpr,
|
|
451
|
+
message: "x",
|
|
452
|
+
syntax: "rrule",
|
|
453
|
+
expression: rruleExpr,
|
|
454
|
+
});
|
|
455
|
+
forceScheduleDue(schedule.id);
|
|
456
|
+
|
|
457
|
+
const sseCalls: Array<{
|
|
458
|
+
conversationId: string;
|
|
459
|
+
scheduleJobId: string;
|
|
460
|
+
title: string;
|
|
461
|
+
}> = [];
|
|
462
|
+
const processMessage = async () => {};
|
|
463
|
+
const scheduler = startScheduler(
|
|
464
|
+
processMessage,
|
|
465
|
+
() => {},
|
|
466
|
+
undefined,
|
|
467
|
+
(info) => sseCalls.push(info),
|
|
468
|
+
);
|
|
469
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
470
|
+
scheduler.stop();
|
|
471
|
+
|
|
472
|
+
expect(sseCalls).toHaveLength(1);
|
|
473
|
+
expect(sseCalls[0]).toMatchObject({
|
|
474
|
+
scheduleJobId: schedule.id,
|
|
475
|
+
title: "SSE timing",
|
|
476
|
+
});
|
|
477
|
+
// The mock runner fires the callback synchronously after creating the
|
|
478
|
+
// conversation row, so the conversationId must be the same id the runner
|
|
479
|
+
// ultimately reports.
|
|
480
|
+
expect(processedMessages).toHaveLength(1);
|
|
481
|
+
expect(sseCalls[0].conversationId).toBe(
|
|
482
|
+
processedMessages[0].conversationId,
|
|
483
|
+
);
|
|
484
|
+
});
|
|
485
|
+
});
|
|
@@ -27,11 +27,6 @@ mock.module("../runtime/agent-wake.js", () => ({
|
|
|
27
27
|
wakeAgentForOpportunity: mockWakeAgentForOpportunity,
|
|
28
28
|
}));
|
|
29
29
|
|
|
30
|
-
const mockEmitFeedEvent = mock(() => Promise.resolve());
|
|
31
|
-
mock.module("../home/emit-feed-event.js", () => ({
|
|
32
|
-
emitFeedEvent: mockEmitFeedEvent,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
30
|
import { getDb } from "../memory/db-connection.js";
|
|
36
31
|
import { initializeDb } from "../memory/db-init.js";
|
|
37
32
|
import { createSchedule } from "../schedule/schedule-store.js";
|
|
@@ -82,7 +77,6 @@ describe("scheduler wake mode", () => {
|
|
|
82
77
|
db.run("DELETE FROM messages");
|
|
83
78
|
db.run("DELETE FROM conversations");
|
|
84
79
|
mockWakeAgentForOpportunity.mockClear();
|
|
85
|
-
mockEmitFeedEvent.mockClear();
|
|
86
80
|
});
|
|
87
81
|
|
|
88
82
|
test("wake schedule calls wakeAgentForOpportunity with correct args", async () => {
|
|
@@ -208,63 +202,6 @@ describe("scheduler wake mode", () => {
|
|
|
208
202
|
expect(row?.status).toBe("active");
|
|
209
203
|
});
|
|
210
204
|
|
|
211
|
-
test("quiet: true suppresses feed event", async () => {
|
|
212
|
-
// GIVEN a one-shot wake schedule with quiet: true
|
|
213
|
-
const schedule = createSchedule({
|
|
214
|
-
name: "Wake Quiet",
|
|
215
|
-
message: "Quiet wake",
|
|
216
|
-
mode: "wake",
|
|
217
|
-
wakeConversationId: "conv-quiet",
|
|
218
|
-
quiet: true,
|
|
219
|
-
nextRunAt: Date.now() - 1000,
|
|
220
|
-
});
|
|
221
|
-
forceScheduleDue(schedule.id);
|
|
222
|
-
|
|
223
|
-
// WHEN the scheduler fires
|
|
224
|
-
const scheduler = startScheduler(
|
|
225
|
-
mock(() => Promise.resolve()),
|
|
226
|
-
() => {},
|
|
227
|
-
);
|
|
228
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
229
|
-
scheduler.stop();
|
|
230
|
-
|
|
231
|
-
// THEN wakeAgentForOpportunity is called
|
|
232
|
-
expect(mockWakeAgentForOpportunity).toHaveBeenCalledTimes(1);
|
|
233
|
-
|
|
234
|
-
// AND no feed event is emitted
|
|
235
|
-
expect(mockEmitFeedEvent).not.toHaveBeenCalled();
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
test("quiet: false emits feed event on success", async () => {
|
|
239
|
-
// GIVEN a one-shot wake schedule with quiet: false (default)
|
|
240
|
-
const schedule = createSchedule({
|
|
241
|
-
name: "Wake Loud",
|
|
242
|
-
message: "Loud wake",
|
|
243
|
-
mode: "wake",
|
|
244
|
-
wakeConversationId: "conv-loud",
|
|
245
|
-
nextRunAt: Date.now() - 1000,
|
|
246
|
-
});
|
|
247
|
-
forceScheduleDue(schedule.id);
|
|
248
|
-
|
|
249
|
-
// WHEN the scheduler fires
|
|
250
|
-
const scheduler = startScheduler(
|
|
251
|
-
mock(() => Promise.resolve()),
|
|
252
|
-
() => {},
|
|
253
|
-
);
|
|
254
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
255
|
-
scheduler.stop();
|
|
256
|
-
|
|
257
|
-
// THEN a feed event IS emitted
|
|
258
|
-
expect(mockEmitFeedEvent).toHaveBeenCalledTimes(1);
|
|
259
|
-
expect(mockEmitFeedEvent).toHaveBeenCalledWith(
|
|
260
|
-
expect.objectContaining({
|
|
261
|
-
source: "assistant",
|
|
262
|
-
title: "Wake Loud",
|
|
263
|
-
summary: "Deferred wake fired.",
|
|
264
|
-
}),
|
|
265
|
-
);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
205
|
test("retries wake when wakeAgentForOpportunity returns timeout", async () => {
|
|
269
206
|
// GIVEN wakeAgentForOpportunity returns timeout on first call, then succeeds
|
|
270
207
|
mockWakeAgentForOpportunity
|
|
@@ -135,6 +135,7 @@ describe("secret-allowlist", () => {
|
|
|
135
135
|
|
|
136
136
|
// -----------------------------------------------------------------------
|
|
137
137
|
// Integration with scanText
|
|
138
|
+
// AKIAIOSFODNN7* keys below are fake — based on the AWS docs example prefix, not real credentials.
|
|
138
139
|
// -----------------------------------------------------------------------
|
|
139
140
|
test("[experimental] allowlisted values are suppressed by scanText", () => {
|
|
140
141
|
const awsKey = "AKIAIOSFODNN7REALKEY";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import { LLMSchema } from "../config/schemas/llm.js";
|
|
3
4
|
import { credentialKey } from "../security/credential-key.js";
|
|
4
5
|
|
|
5
6
|
let lastGeminiConstructorOpts: Record<string, unknown> | null = null;
|
|
@@ -15,11 +16,11 @@ const MANAGED_PROVIDERS = ["anthropic", "openai", "gemini"] as const;
|
|
|
15
16
|
|
|
16
17
|
let platformBaseUrlOverride: string | undefined;
|
|
17
18
|
|
|
19
|
+
const baseLlm = LLMSchema.parse({});
|
|
20
|
+
|
|
18
21
|
const mockConfig = {
|
|
19
22
|
services: {
|
|
20
|
-
inference: {
|
|
21
|
-
mode: "your-own" as const,
|
|
22
|
-
},
|
|
23
|
+
inference: {},
|
|
23
24
|
"image-generation": {
|
|
24
25
|
mode: "your-own" as const,
|
|
25
26
|
provider: "gemini",
|
|
@@ -30,7 +31,14 @@ const mockConfig = {
|
|
|
30
31
|
provider: "inference-provider-native",
|
|
31
32
|
},
|
|
32
33
|
},
|
|
33
|
-
llm: {
|
|
34
|
+
llm: {
|
|
35
|
+
...baseLlm,
|
|
36
|
+
default: {
|
|
37
|
+
...baseLlm.default,
|
|
38
|
+
provider: "anthropic" as const,
|
|
39
|
+
model: "test-model",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
34
42
|
};
|
|
35
43
|
|
|
36
44
|
mock.module("@google/genai", () => ({
|
|
@@ -93,6 +93,7 @@ afterAll(() => {
|
|
|
93
93
|
describe("shell tool credential ref resolution", () => {
|
|
94
94
|
test("service/field ref resolves to UUID and reaches session creation", async () => {
|
|
95
95
|
const meta = upsertCredentialMetadata("fal", "api_key", {
|
|
96
|
+
allowedTools: ["bash"],
|
|
96
97
|
injectionTemplates: [
|
|
97
98
|
{
|
|
98
99
|
hostPattern: "*.fal.ai",
|
|
@@ -120,7 +121,9 @@ describe("shell tool credential ref resolution", () => {
|
|
|
120
121
|
});
|
|
121
122
|
|
|
122
123
|
test("UUID ref remains supported", async () => {
|
|
123
|
-
const meta = upsertCredentialMetadata("github", "token"
|
|
124
|
+
const meta = upsertCredentialMetadata("github", "token", {
|
|
125
|
+
allowedTools: ["bash"],
|
|
126
|
+
});
|
|
124
127
|
|
|
125
128
|
await shellTool.execute(
|
|
126
129
|
{
|
|
@@ -156,7 +159,9 @@ describe("shell tool credential ref resolution", () => {
|
|
|
156
159
|
});
|
|
157
160
|
|
|
158
161
|
test("mixed known+unknown refs fails fast (no partial execution)", async () => {
|
|
159
|
-
upsertCredentialMetadata("fal", "api_key"
|
|
162
|
+
upsertCredentialMetadata("fal", "api_key", {
|
|
163
|
+
allowedTools: ["bash"],
|
|
164
|
+
});
|
|
160
165
|
|
|
161
166
|
const result = await shellTool.execute(
|
|
162
167
|
{
|
|
@@ -175,7 +180,9 @@ describe("shell tool credential ref resolution", () => {
|
|
|
175
180
|
});
|
|
176
181
|
|
|
177
182
|
test("duplicate refs are deduped", async () => {
|
|
178
|
-
const meta = upsertCredentialMetadata("fal", "api_key"
|
|
183
|
+
const meta = upsertCredentialMetadata("fal", "api_key", {
|
|
184
|
+
allowedTools: ["bash"],
|
|
185
|
+
});
|
|
179
186
|
|
|
180
187
|
await shellTool.execute(
|
|
181
188
|
{
|
|
@@ -209,4 +216,89 @@ describe("shell tool credential ref resolution", () => {
|
|
|
209
216
|
expect(result.isError).toBeFalsy();
|
|
210
217
|
expect(mockGetOrStartSession).not.toHaveBeenCalled();
|
|
211
218
|
});
|
|
219
|
+
|
|
220
|
+
test("credential with allowedTools excluding bash is denied for proxied shell", async () => {
|
|
221
|
+
upsertCredentialMetadata("vercel", "api_token", {
|
|
222
|
+
allowedTools: ["publish_page"],
|
|
223
|
+
injectionTemplates: [
|
|
224
|
+
{
|
|
225
|
+
hostPattern: "api.vercel.com",
|
|
226
|
+
injectionType: "header",
|
|
227
|
+
headerName: "Authorization",
|
|
228
|
+
valuePrefix: "Bearer ",
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const result = await shellTool.execute(
|
|
234
|
+
{
|
|
235
|
+
command: "curl https://api.vercel.com/v1/projects",
|
|
236
|
+
activity: "test",
|
|
237
|
+
network_mode: "proxied",
|
|
238
|
+
credential_ids: ["vercel/api_token"],
|
|
239
|
+
},
|
|
240
|
+
ctx,
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
expect(result.isError).toBe(true);
|
|
244
|
+
expect(result.content).toContain("credential tool policy denied");
|
|
245
|
+
expect(result.content).toContain("not bash");
|
|
246
|
+
// Must not call getOrStartSession — policy denial happens before session creation
|
|
247
|
+
expect(mockGetOrStartSession).not.toHaveBeenCalled();
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test("credential with allowedTools including bash starts proxied session", async () => {
|
|
251
|
+
const meta = upsertCredentialMetadata("deploy_svc", "api_key", {
|
|
252
|
+
allowedTools: ["bash"],
|
|
253
|
+
injectionTemplates: [
|
|
254
|
+
{
|
|
255
|
+
hostPattern: "*.deploy-svc.io",
|
|
256
|
+
injectionType: "header",
|
|
257
|
+
headerName: "Authorization",
|
|
258
|
+
valuePrefix: "Bearer ",
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
await shellTool.execute(
|
|
264
|
+
{
|
|
265
|
+
command: "echo deploy",
|
|
266
|
+
activity: "test",
|
|
267
|
+
network_mode: "proxied",
|
|
268
|
+
credential_ids: ["deploy_svc/api_key"],
|
|
269
|
+
},
|
|
270
|
+
ctx,
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
// Session should be created with the resolved credential ID
|
|
274
|
+
expect(mockGetOrStartSession).toHaveBeenCalledTimes(1);
|
|
275
|
+
const callArgs = mockGetOrStartSession.mock.calls[0];
|
|
276
|
+
expect(callArgs[1]).toEqual([meta.credentialId]);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test("mixed allowed and denied credentials fail the whole command before session creation", async () => {
|
|
280
|
+
upsertCredentialMetadata("allowed_svc", "token", {
|
|
281
|
+
allowedTools: ["bash"],
|
|
282
|
+
});
|
|
283
|
+
upsertCredentialMetadata("denied_svc", "token", {
|
|
284
|
+
allowedTools: ["publish_page"],
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
const result = await shellTool.execute(
|
|
288
|
+
{
|
|
289
|
+
command: "echo mixed",
|
|
290
|
+
activity: "test",
|
|
291
|
+
network_mode: "proxied",
|
|
292
|
+
credential_ids: ["allowed_svc/token", "denied_svc/token"],
|
|
293
|
+
},
|
|
294
|
+
ctx,
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
expect(result.isError).toBe(true);
|
|
298
|
+
expect(result.content).toContain("credential tool policy denied");
|
|
299
|
+
expect(result.content).toContain("denied_svc/token");
|
|
300
|
+
expect(result.content).toContain("not bash");
|
|
301
|
+
// Must not call getOrStartSession — even one denied credential blocks the whole command
|
|
302
|
+
expect(mockGetOrStartSession).not.toHaveBeenCalled();
|
|
303
|
+
});
|
|
212
304
|
});
|
|
@@ -136,6 +136,20 @@ mock.module("../tools/credentials/resolve.js", () => ({
|
|
|
136
136
|
resolveCredentialRef: (ref: string) => ({ credentialId: ref }),
|
|
137
137
|
}));
|
|
138
138
|
|
|
139
|
+
mock.module("../tools/credentials/metadata-store.js", () => ({
|
|
140
|
+
getCredentialMetadataById: (id: string) => ({
|
|
141
|
+
service: "test",
|
|
142
|
+
field: id,
|
|
143
|
+
allowedTools: ["bash"],
|
|
144
|
+
allowedDomains: [],
|
|
145
|
+
}),
|
|
146
|
+
}));
|
|
147
|
+
|
|
148
|
+
mock.module("../tools/credentials/tool-policy.js", () => ({
|
|
149
|
+
isToolAllowed: (toolName: string, allowedTools: string[]) =>
|
|
150
|
+
Array.isArray(allowedTools) && allowedTools.includes(toolName),
|
|
151
|
+
}));
|
|
152
|
+
|
|
139
153
|
mock.module("../tools/network/script-proxy/logging.js", () => ({
|
|
140
154
|
buildCredentialRefTrace: (
|
|
141
155
|
rawRefs: string[],
|
|
@@ -371,15 +371,13 @@ describe("skill_load tool", () => {
|
|
|
371
371
|
expect(result.content).toContain("Skill: No Includes");
|
|
372
372
|
});
|
|
373
373
|
|
|
374
|
-
test("bundled app-builder loads
|
|
374
|
+
test("bundled app-builder loads without includes", async () => {
|
|
375
375
|
const result = await executeSkillLoad({ skill: "app-builder" });
|
|
376
376
|
|
|
377
377
|
expect(result.isError).toBe(false);
|
|
378
378
|
expect(result.content).toContain("Skill: App Builder");
|
|
379
|
-
expect(result.content).toContain("
|
|
380
|
-
expect(result.content).toContain("frontend-design");
|
|
379
|
+
expect(result.content).toContain("Included Skills (immediate): none");
|
|
381
380
|
expect(result.content).toContain('<loaded_skill id="app-builder"');
|
|
382
|
-
expect(result.content).not.toContain('<loaded_skill id="frontend-design"');
|
|
383
381
|
});
|
|
384
382
|
|
|
385
383
|
test("bundled phone-calls loads when setup includes are unavailable", async () => {
|
|
@@ -110,16 +110,39 @@ mock.module("../prompts/system-prompt.js", () => ({
|
|
|
110
110
|
buildSubagentSystemPrompt: () => "subagent system",
|
|
111
111
|
}));
|
|
112
112
|
|
|
113
|
-
// Provider registry
|
|
113
|
+
// Provider registry + connection resolver — routing goes through
|
|
114
|
+
// `provider_connection` exclusively. `getProvider` is kept here purely
|
|
115
|
+
// because the registry module still exports it; the production code under
|
|
116
|
+
// test does not call it.
|
|
114
117
|
const anthropicStub = { name: "anthropic" };
|
|
115
118
|
const openaiStub = { name: "openai" };
|
|
116
119
|
|
|
117
120
|
mock.module("../providers/registry.js", () => ({
|
|
118
121
|
getProvider: (name: string) => {
|
|
119
|
-
|
|
120
|
-
if (name === "openai") return openaiStub;
|
|
121
|
-
throw new Error(`unknown provider: ${name}`);
|
|
122
|
+
throw new Error(`legacy getProvider should not be called: ${name}`);
|
|
122
123
|
},
|
|
124
|
+
resolveProviderFromConnection: async (connection: { name: string }) => {
|
|
125
|
+
if (connection.name === "anthropic-conn") return anthropicStub;
|
|
126
|
+
if (connection.name === "openai-conn") return openaiStub;
|
|
127
|
+
return null;
|
|
128
|
+
},
|
|
129
|
+
clearConnectionProviderCache: () => {},
|
|
130
|
+
}));
|
|
131
|
+
|
|
132
|
+
// Connection lookup — feeds `resolveProviderFromConnection` above. The DB
|
|
133
|
+
// is stubbed; tests don't touch SQLite.
|
|
134
|
+
mock.module("../providers/inference/connections.js", () => ({
|
|
135
|
+
getConnection: (_db: unknown, name: string) => {
|
|
136
|
+
if (name === "anthropic-conn")
|
|
137
|
+
return { name: "anthropic-conn", provider: "anthropic", auth: { type: "platform" } };
|
|
138
|
+
if (name === "openai-conn")
|
|
139
|
+
return { name: "openai-conn", provider: "openai", auth: { type: "platform" } };
|
|
140
|
+
return null;
|
|
141
|
+
},
|
|
142
|
+
}));
|
|
143
|
+
|
|
144
|
+
mock.module("../memory/db-connection.js", () => ({
|
|
145
|
+
getDb: () => ({}),
|
|
123
146
|
}));
|
|
124
147
|
|
|
125
148
|
// Mutable LLM config — tests rewrite this per-case.
|
|
@@ -154,7 +177,11 @@ function setLlmConfig(raw: unknown): void {
|
|
|
154
177
|
describe("SubagentManager — provider call-site routing", () => {
|
|
155
178
|
test("wraps the default provider in CallSiteRoutingProvider", async () => {
|
|
156
179
|
setLlmConfig({
|
|
157
|
-
default: {
|
|
180
|
+
default: {
|
|
181
|
+
provider: "anthropic",
|
|
182
|
+
provider_connection: "anthropic-conn",
|
|
183
|
+
model: "claude-opus-4-7",
|
|
184
|
+
},
|
|
158
185
|
});
|
|
159
186
|
|
|
160
187
|
capturedProvider = undefined;
|
|
@@ -172,10 +199,27 @@ describe("SubagentManager — provider call-site routing", () => {
|
|
|
172
199
|
});
|
|
173
200
|
|
|
174
201
|
test("the wrapped provider exposes the default provider's name (stable identity for outer wrappers)", async () => {
|
|
202
|
+
// Note: `provider_connection` lives on `ProfileEntry` and `LLMConfigBase`,
|
|
203
|
+
// NOT on `LLMCallSiteConfig` (which is `LLMConfigFragment.extend({
|
|
204
|
+
// profile })`). Setting `provider_connection` directly on a `callSites.*`
|
|
205
|
+
// entry would be silently stripped by Zod. The correct shape for an
|
|
206
|
+
// alternate-provider call-site override is a profile reference, defined
|
|
207
|
+
// here as `altOpenai`.
|
|
175
208
|
setLlmConfig({
|
|
176
|
-
default: {
|
|
209
|
+
default: {
|
|
210
|
+
provider: "anthropic",
|
|
211
|
+
provider_connection: "anthropic-conn",
|
|
212
|
+
model: "claude-opus-4-7",
|
|
213
|
+
},
|
|
214
|
+
profiles: {
|
|
215
|
+
altOpenai: {
|
|
216
|
+
provider: "openai",
|
|
217
|
+
provider_connection: "openai-conn",
|
|
218
|
+
model: "gpt-5.4",
|
|
219
|
+
},
|
|
220
|
+
},
|
|
177
221
|
callSites: {
|
|
178
|
-
subagentSpawn: {
|
|
222
|
+
subagentSpawn: { profile: "altOpenai" },
|
|
179
223
|
},
|
|
180
224
|
});
|
|
181
225
|
|
|
@@ -202,7 +246,11 @@ describe("SubagentManager — provider call-site routing", () => {
|
|
|
202
246
|
|
|
203
247
|
test("falls back to default provider when subagentSpawn callSite is absent", async () => {
|
|
204
248
|
setLlmConfig({
|
|
205
|
-
default: {
|
|
249
|
+
default: {
|
|
250
|
+
provider: "anthropic",
|
|
251
|
+
provider_connection: "anthropic-conn",
|
|
252
|
+
model: "claude-opus-4-7",
|
|
253
|
+
},
|
|
206
254
|
// No subagentSpawn override.
|
|
207
255
|
});
|
|
208
256
|
|
|
@@ -224,7 +272,11 @@ describe("SubagentManager — provider call-site routing", () => {
|
|
|
224
272
|
|
|
225
273
|
test("copies parent guardian and auth context into spawned conversation", async () => {
|
|
226
274
|
setLlmConfig({
|
|
227
|
-
default: {
|
|
275
|
+
default: {
|
|
276
|
+
provider: "anthropic",
|
|
277
|
+
provider_connection: "anthropic-conn",
|
|
278
|
+
model: "claude-opus-4-7",
|
|
279
|
+
},
|
|
228
280
|
});
|
|
229
281
|
|
|
230
282
|
const parentTrustContext = {
|
|
@@ -273,11 +325,18 @@ describe("SubagentManager — provider call-site routing", () => {
|
|
|
273
325
|
// ── Direct unit test for CallSiteRoutingProvider's selection logic ─────────
|
|
274
326
|
|
|
275
327
|
describe("CallSiteRoutingProvider — selectProvider behavior", () => {
|
|
276
|
-
test("routes to the resolved provider when callSite
|
|
328
|
+
test("routes to the resolved provider when callSite resolves to a profile with provider_connection", async () => {
|
|
277
329
|
setLlmConfig({
|
|
278
330
|
default: { provider: "anthropic", model: "claude-opus-4-7" },
|
|
331
|
+
profiles: {
|
|
332
|
+
altOpenai: {
|
|
333
|
+
provider: "openai",
|
|
334
|
+
provider_connection: "openai-conn",
|
|
335
|
+
model: "gpt-5.4",
|
|
336
|
+
},
|
|
337
|
+
},
|
|
279
338
|
callSites: {
|
|
280
|
-
subagentSpawn: {
|
|
339
|
+
subagentSpawn: { profile: "altOpenai" },
|
|
281
340
|
},
|
|
282
341
|
});
|
|
283
342
|
|
|
@@ -309,10 +368,13 @@ describe("CallSiteRoutingProvider — selectProvider behavior", () => {
|
|
|
309
368
|
},
|
|
310
369
|
};
|
|
311
370
|
|
|
312
|
-
const wrapper = new CallSiteRoutingProvider(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
371
|
+
const wrapper = new CallSiteRoutingProvider(
|
|
372
|
+
defaultProvider,
|
|
373
|
+
async (connectionName) => {
|
|
374
|
+
if (connectionName === "openai-conn") return altProvider;
|
|
375
|
+
return null;
|
|
376
|
+
},
|
|
377
|
+
);
|
|
316
378
|
|
|
317
379
|
await wrapper.sendMessage([], undefined, undefined, {
|
|
318
380
|
config: { callSite: "subagentSpawn" },
|
|
@@ -347,7 +409,7 @@ describe("CallSiteRoutingProvider — selectProvider behavior", () => {
|
|
|
347
409
|
|
|
348
410
|
const wrapper = new CallSiteRoutingProvider(
|
|
349
411
|
defaultProvider,
|
|
350
|
-
() =>
|
|
412
|
+
async () => null,
|
|
351
413
|
);
|
|
352
414
|
|
|
353
415
|
await wrapper.sendMessage([], undefined, undefined, {
|