@vellumai/assistant 0.7.3 → 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/ARCHITECTURE.md +29 -28
- package/Dockerfile +6 -4
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
- package/bun.lock +3 -0
- 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 +3 -1
- package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
- package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
- package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/openapi.yaml +4126 -959
- package/package.json +5 -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__/annotate-risk-options.test.ts +291 -0
- package/src/__tests__/anthropic-provider.test.ts +92 -2
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/approval-cascade.test.ts +8 -16
- package/src/__tests__/approval-routes-http.test.ts +6 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
- 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-constants.test.ts +10 -1
- package/src/__tests__/call-controller.test.ts +127 -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 +88 -30
- 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 +345 -8
- 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-source.test.ts +3 -26
- 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-abort-tool-results.test.ts +1 -6
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +3 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
- 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 +2 -1
- 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 +22 -7
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
- package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
- 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 +25 -22
- 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 +10 -34
- 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__/injector-chain.test.ts +24 -16
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
- 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 +169 -67
- 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-decision-fallback.test.ts +91 -0
- package/src/__tests__/notification-decision-strategy.test.ts +22 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -1888
- 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 +164 -2
- 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-prompt-log-hygiene.test.ts +7 -5
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
- package/src/__tests__/secret-response-routing.test.ts +7 -5
- package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
- package/src/__tests__/server-history-render.test.ts +82 -0
- 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-include-graph.test.ts +31 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skill-load-tool.test.ts +42 -16
- package/src/__tests__/skills.test.ts +39 -0
- 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__/tool-execution-pipeline.benchmark.test.ts +0 -42
- package/src/__tests__/tool-executor.test.ts +155 -0
- 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__/voice-session-bridge.test.ts +3 -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 +153 -0
- package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
- 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-safe-storage-limits-release.test.ts +15 -27
- 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/agent/loop.ts +11 -0
- package/src/approvals/guardian-decision-primitive.ts +0 -13
- package/src/approvals/guardian-request-resolvers.ts +19 -102
- package/src/calls/call-constants.ts +5 -8
- package/src/calls/call-controller.ts +130 -67
- package/src/calls/relay-server.ts +42 -1
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +24 -5
- 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 +163 -517
- package/src/cli/commands/notifications.ts +33 -7
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +182 -345
- 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-builder/SKILL.md +1 -3
- 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 +17 -17
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +148 -33
- 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 +33 -2
- 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 +111 -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 +56 -0
- package/src/daemon/conversation-agent-loop.ts +140 -107
- package/src/daemon/conversation-error.ts +21 -0
- package/src/daemon/conversation-lifecycle.ts +68 -13
- 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 +92 -26
- package/src/daemon/conversation-tool-setup.ts +33 -19
- package/src/daemon/conversation.ts +49 -10
- 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/shared.ts +26 -0
- 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 +97 -36
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/host-transfer-proxy.ts +2 -2
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +128 -114
- package/src/daemon/meet-host-supervisor.ts +15 -15
- package/src/daemon/memory-v2-startup.ts +62 -14
- 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 +28 -2
- 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/documents/document-store.ts +35 -1
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +42 -56
- 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 +149 -128
- 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 +148 -42
- 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/ipc/skill-server.ts +99 -42
- 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__/jobs-worker-v2-schedule.test.ts +10 -57
- 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 +40 -31
- package/src/memory/context-search/sources/memory.ts +9 -2
- 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__/conversation-graph-memory-v2-routing.test.ts +104 -61
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +108 -14
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/graph-search.test.ts +6 -5
- package/src/memory/graph/graph-search.ts +3 -4
- package/src/memory/graph/retriever.test.ts +12 -7
- package/src/memory/graph/retriever.ts +4 -5
- package/src/memory/graph/tool-handlers.ts +20 -11
- package/src/memory/graph/tools.ts +48 -9
- package/src/memory/indexer.ts +18 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
- package/src/memory/jobs/embed-concept-page.ts +261 -89
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +60 -7
- 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/pkb/pkb-search.test.ts +6 -5
- package/src/memory/pkb/pkb-search.ts +4 -5
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/qdrant-client.ts +3 -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 +5 -9
- 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 +46 -9
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
- 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 +768 -33
- 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 +382 -9
- 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 +163 -8
- package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
- package/src/memory/v2/__tests__/static-context.test.ts +8 -35
- package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
- 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 +92 -86
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +466 -115
- package/src/memory/v2/migration.ts +117 -20
- package/src/memory/v2/page-index.ts +191 -0
- package/src/memory/v2/page-store.ts +42 -0
- package/src/memory/v2/prompts/consolidation.ts +14 -7
- package/src/memory/v2/prompts/router.ts +192 -0
- package/src/memory/v2/qdrant.ts +307 -133
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +322 -0
- package/src/memory/v2/sim.ts +88 -34
- package/src/memory/v2/skill-store.ts +118 -29
- package/src/memory/v2/static-context.ts +20 -17
- package/src/memory/v2/sweep-job.ts +127 -102
- package/src/memory/v2/types.ts +16 -5
- 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 +61 -12
- package/src/notifications/decision-engine.ts +46 -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/gateway-threshold-reader.ts +116 -8
- package/src/permissions/ipc-risk-types.ts +2 -0
- package/src/permissions/prompter.ts +86 -96
- package/src/permissions/secret-prompter.ts +31 -31
- 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 +20 -5
- 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 +63 -8
- package/src/proactive-artifact/job.ts +20 -2
- package/src/proactive-artifact/message-copy.ts +18 -1
- 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/templates/SOUL.md +13 -28
- 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 +304 -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/channel-approvals.ts +3 -2
- package/src/runtime/guardian-reply-router.ts +0 -10
- 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/pending-interactions.ts +19 -15
- 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 +147 -0
- 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 +7 -21
- 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/consolidation-routes.ts +8 -9
- 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 +373 -82
- 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-bash-routes.ts +2 -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/filing-routes.ts +2 -3
- 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 -7
- 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-item-routes.test.ts +3 -9
- package/src/runtime/routes/memory-item-routes.ts +5 -6
- package/src/runtime/routes/memory-v2-routes.ts +105 -404
- 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/skills/include-graph.ts +35 -13
- 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/document/document-tool.ts +20 -0
- package/src/tools/executor.ts +18 -2
- package/src/tools/memory/register.test.ts +10 -8
- 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 +28 -5
- package/src/tools/skills/load.ts +24 -20
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/terminal/shell.ts +44 -0
- package/src/tools/tool-name-aliases.ts +19 -0
- package/src/tools/types.ts +19 -1
- 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/067-release-notes-safe-storage-limits.ts +4 -62
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
- package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
- 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 +28 -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 -492
- 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 -1201
- 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 -477
- package/src/memory/graph/compaction.ts +0 -299
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
|
@@ -146,6 +146,42 @@ describe("loadConfig corrupt-file recovery", () => {
|
|
|
146
146
|
/^config\.json\.corrupt-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}\.\d{3}Z\.json$/,
|
|
147
147
|
);
|
|
148
148
|
});
|
|
149
|
+
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Shape-mismatch quarantine — same JSON.parse caveat as `loadRawConfig`.
|
|
152
|
+
// Without an `isPlainObject` check, downstream code (e.g. the managed-Gemini
|
|
153
|
+
// `setNestedValue` block in `loadConfig`) would TypeError on `null` or
|
|
154
|
+
// primitive `fileConfig`, and only the broad try/catch around the migration
|
|
155
|
+
// saved startup. Treating the wrong-shape case as a parse error here moves
|
|
156
|
+
// the boundary check to the loader so callers don't have to defend.
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
test.each([
|
|
160
|
+
["null at the top level", "null"],
|
|
161
|
+
["a JSON number", "42"],
|
|
162
|
+
["a JSON string", '"hello"'],
|
|
163
|
+
["a JSON boolean", "true"],
|
|
164
|
+
["a JSON array", '["provider", "anthropic"]'],
|
|
165
|
+
])(
|
|
166
|
+
"quarantines when config.json contains %s and returns defaults",
|
|
167
|
+
(_label, jsonText) => {
|
|
168
|
+
writeFileSync(CONFIG_PATH, jsonText);
|
|
169
|
+
|
|
170
|
+
// Must not throw — daemon startup contract.
|
|
171
|
+
const config = loadConfig();
|
|
172
|
+
|
|
173
|
+
// Defaults loaded — config is populated through the Zod schema.
|
|
174
|
+
expect(config).toBeDefined();
|
|
175
|
+
expect(config.memory).toBeDefined();
|
|
176
|
+
|
|
177
|
+
const quarantined = listQuarantinedFiles();
|
|
178
|
+
expect(quarantined).toHaveLength(1);
|
|
179
|
+
// Original wrong-shape content preserved for debugging.
|
|
180
|
+
expect(readFileSync(join(WORKSPACE_DIR, quarantined[0]), "utf-8")).toBe(
|
|
181
|
+
jsonText,
|
|
182
|
+
);
|
|
183
|
+
},
|
|
184
|
+
);
|
|
149
185
|
});
|
|
150
186
|
|
|
151
187
|
describe("loadRawConfig corrupt-file recovery", () => {
|
|
@@ -180,4 +216,36 @@ describe("loadRawConfig corrupt-file recovery", () => {
|
|
|
180
216
|
expect(raw).toEqual({ foo: "bar", nested: { k: 1 } });
|
|
181
217
|
expect(listQuarantinedFiles()).toHaveLength(0);
|
|
182
218
|
});
|
|
219
|
+
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
// Shape-mismatch quarantine — JSON.parse can succeed on `null`, primitives,
|
|
222
|
+
// and arrays, all of which violate the function's `Record<string, unknown>`
|
|
223
|
+
// return-type contract. These cases must be quarantined the same way as a
|
|
224
|
+
// syntax error so callers (e.g. /v1/config handlers) can iterate the result
|
|
225
|
+
// safely without runtime shape checks.
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
|
|
228
|
+
test.each([
|
|
229
|
+
["null at the top level", "null"],
|
|
230
|
+
["a JSON number", "42"],
|
|
231
|
+
["a JSON string", '"hello"'],
|
|
232
|
+
["a JSON boolean", "true"],
|
|
233
|
+
["a JSON array", '["provider", "anthropic"]'],
|
|
234
|
+
])(
|
|
235
|
+
"quarantines when config.json contains %s and returns {}",
|
|
236
|
+
(_label, jsonText) => {
|
|
237
|
+
writeFileSync(CONFIG_PATH, jsonText);
|
|
238
|
+
|
|
239
|
+
// Must not throw — same contract as the syntax-error path.
|
|
240
|
+
const raw = loadRawConfig();
|
|
241
|
+
|
|
242
|
+
expect(raw).toEqual({});
|
|
243
|
+
const quarantined = listQuarantinedFiles();
|
|
244
|
+
expect(quarantined).toHaveLength(1);
|
|
245
|
+
// Original wrong-shape content is preserved for debugging.
|
|
246
|
+
expect(readFileSync(join(WORKSPACE_DIR, quarantined[0]), "utf-8")).toBe(
|
|
247
|
+
jsonText,
|
|
248
|
+
);
|
|
249
|
+
},
|
|
250
|
+
);
|
|
183
251
|
});
|
|
@@ -58,6 +58,7 @@ afterAll(() => {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
import { invalidateConfigCache, loadConfig } from "../config/loader.js";
|
|
61
|
+
import { applyContextDefaultsToRawConfig } from "../runtime/routes/conversation-query-routes.js";
|
|
61
62
|
import { _setStorePath } from "../security/encrypted-store.js";
|
|
62
63
|
|
|
63
64
|
// ---------------------------------------------------------------------------
|
|
@@ -91,7 +92,6 @@ function readConfig(): Record<string, unknown> {
|
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
const MANAGED_SERVICES = [
|
|
94
|
-
"inference",
|
|
95
95
|
"image-generation",
|
|
96
96
|
"web-search",
|
|
97
97
|
"google-oauth",
|
|
@@ -125,7 +125,7 @@ describe("platform-managed config defaults", () => {
|
|
|
125
125
|
}
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
test("IS_PLATFORM=true, no config file → all
|
|
128
|
+
test("IS_PLATFORM=true, no config file → all 7 managed service modes written as 'managed'", () => {
|
|
129
129
|
process.env.IS_PLATFORM = "true";
|
|
130
130
|
|
|
131
131
|
loadConfig();
|
|
@@ -139,7 +139,7 @@ describe("platform-managed config defaults", () => {
|
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
-
test("IS_PLATFORM=false, no config file → service modes default to 'your-own'", () => {
|
|
142
|
+
test("IS_PLATFORM=false, no config file → managed service modes default to 'your-own'", () => {
|
|
143
143
|
process.env.IS_PLATFORM = "false";
|
|
144
144
|
|
|
145
145
|
loadConfig();
|
|
@@ -153,7 +153,7 @@ describe("platform-managed config defaults", () => {
|
|
|
153
153
|
}
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
-
test("IS_PLATFORM unset, no config file → service modes default to 'your-own'", () => {
|
|
156
|
+
test("IS_PLATFORM unset, no config file → managed service modes default to 'your-own'", () => {
|
|
157
157
|
delete process.env.IS_PLATFORM;
|
|
158
158
|
|
|
159
159
|
loadConfig();
|
|
@@ -170,13 +170,13 @@ describe("platform-managed config defaults", () => {
|
|
|
170
170
|
test("IS_PLATFORM=true, config file already exists → existing service mode values are preserved", () => {
|
|
171
171
|
process.env.IS_PLATFORM = "true";
|
|
172
172
|
|
|
173
|
-
// Write an existing config with
|
|
173
|
+
// Write an existing config with image-generation mode explicitly set to "your-own"
|
|
174
174
|
writeFileSync(
|
|
175
175
|
CONFIG_PATH,
|
|
176
176
|
JSON.stringify(
|
|
177
177
|
{
|
|
178
178
|
services: {
|
|
179
|
-
|
|
179
|
+
"image-generation": { mode: "your-own" },
|
|
180
180
|
},
|
|
181
181
|
},
|
|
182
182
|
null,
|
|
@@ -184,13 +184,350 @@ describe("platform-managed config defaults", () => {
|
|
|
184
184
|
) + "\n",
|
|
185
185
|
);
|
|
186
186
|
|
|
187
|
-
loadConfig();
|
|
187
|
+
const config = loadConfig();
|
|
188
188
|
|
|
189
189
|
const written = readConfig() as { services?: Record<string, unknown> };
|
|
190
190
|
expect(written.services).toBeDefined();
|
|
191
191
|
// The existing value must be preserved — backfill path, not fresh-write path
|
|
192
192
|
expect(
|
|
193
|
-
(written.services!["
|
|
193
|
+
(written.services!["image-generation"] as { mode?: string })?.mode,
|
|
194
194
|
).toBe("your-own");
|
|
195
|
+
// ...and the in-memory config must mirror the explicit user choice (the
|
|
196
|
+
// fill-defaults pass must not override an explicit "your-own").
|
|
197
|
+
expect(config.services["image-generation"].mode).toBe("your-own");
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("IS_PLATFORM=true, config file exists without a services key → in-memory config has all managed modes", () => {
|
|
201
|
+
// Regression guard for the platform-managed boot order: by the time
|
|
202
|
+
// `loadConfig()` runs, lifecycle steps such as `seedInferenceProfiles`
|
|
203
|
+
// have already written `config.json` (with `llm.profiles` etc.), so
|
|
204
|
+
// `configFileExisted` is true even on a brand-new platform-managed
|
|
205
|
+
// assistant. Deployment-context defaults must still be applied to the
|
|
206
|
+
// in-memory config for any leaf keys that are absent from disk.
|
|
207
|
+
process.env.IS_PLATFORM = "true";
|
|
208
|
+
|
|
209
|
+
writeFileSync(
|
|
210
|
+
CONFIG_PATH,
|
|
211
|
+
JSON.stringify(
|
|
212
|
+
{
|
|
213
|
+
llm: {
|
|
214
|
+
profiles: {
|
|
215
|
+
balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
|
|
216
|
+
},
|
|
217
|
+
activeProfile: "balanced",
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
null,
|
|
221
|
+
2,
|
|
222
|
+
) + "\n",
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
const config = loadConfig();
|
|
226
|
+
|
|
227
|
+
// In-memory config has the deployment-context defaults applied for the
|
|
228
|
+
// missing service-mode fields.
|
|
229
|
+
for (const svc of MANAGED_SERVICES) {
|
|
230
|
+
expect(
|
|
231
|
+
(
|
|
232
|
+
config.services as unknown as Record<
|
|
233
|
+
string,
|
|
234
|
+
{ mode: string }
|
|
235
|
+
>
|
|
236
|
+
)[svc]!.mode,
|
|
237
|
+
).toBe("managed");
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// The on-disk file is NOT modified by the fill pass — disk reflects only
|
|
241
|
+
// what was already there. Existing-file branch never re-writes config.json.
|
|
242
|
+
const onDisk = readConfig() as Record<string, unknown>;
|
|
243
|
+
expect(onDisk["services"]).toBeUndefined();
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("IS_PLATFORM=true, config file exists with a partial service subtree → preserves user fields, fills missing mode", () => {
|
|
247
|
+
process.env.IS_PLATFORM = "true";
|
|
248
|
+
|
|
249
|
+
// User has an image-generation provider configured but never explicitly
|
|
250
|
+
// chose a mode for that service. The fill pass must apply
|
|
251
|
+
// `mode: "managed"` without clobbering the user-supplied provider.
|
|
252
|
+
// (The inference schema dropped per-service model/provider in
|
|
253
|
+
// migration 039 — image-generation still carries them, so it's the
|
|
254
|
+
// right schema to exercise the partial-subtree case.)
|
|
255
|
+
writeFileSync(
|
|
256
|
+
CONFIG_PATH,
|
|
257
|
+
JSON.stringify(
|
|
258
|
+
{
|
|
259
|
+
services: {
|
|
260
|
+
"image-generation": { provider: "openai" },
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
null,
|
|
264
|
+
2,
|
|
265
|
+
) + "\n",
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
const config = loadConfig();
|
|
269
|
+
|
|
270
|
+
const imageGen = (
|
|
271
|
+
config.services as unknown as Record<
|
|
272
|
+
string,
|
|
273
|
+
{ mode: string; provider?: string }
|
|
274
|
+
>
|
|
275
|
+
)["image-generation"]!;
|
|
276
|
+
expect(imageGen.mode).toBe("managed");
|
|
277
|
+
expect(imageGen.provider).toBe("openai");
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test("IS_PLATFORM=false, config file exists without services key → in-memory config keeps schema your-own defaults", () => {
|
|
281
|
+
// Sanity guard: deployment-context defaults are a no-op when IS_PLATFORM
|
|
282
|
+
// is not enabled, regardless of whether config.json existed.
|
|
283
|
+
process.env.IS_PLATFORM = "false";
|
|
284
|
+
|
|
285
|
+
writeFileSync(
|
|
286
|
+
CONFIG_PATH,
|
|
287
|
+
JSON.stringify(
|
|
288
|
+
{
|
|
289
|
+
llm: {
|
|
290
|
+
profiles: {
|
|
291
|
+
balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
|
|
292
|
+
},
|
|
293
|
+
activeProfile: "balanced",
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
null,
|
|
297
|
+
2,
|
|
298
|
+
) + "\n",
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
const config = loadConfig();
|
|
302
|
+
|
|
303
|
+
for (const svc of MANAGED_SERVICES) {
|
|
304
|
+
expect(
|
|
305
|
+
(
|
|
306
|
+
config.services as unknown as Record<
|
|
307
|
+
string,
|
|
308
|
+
{ mode: string }
|
|
309
|
+
>
|
|
310
|
+
)[svc]!.mode,
|
|
311
|
+
).toBe("your-own");
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Regression guard for the `handleGetConfig` route handler in
|
|
318
|
+
* `assistant/src/runtime/routes/conversation-query-routes.ts`. That handler
|
|
319
|
+
* returns the raw on-disk JSON to clients (macOS, web, CLI) via
|
|
320
|
+
* `GET /v1/config`, but first layers deployment-context defaults on top
|
|
321
|
+
* via the `applyContextDefaultsToRawConfig` helper.
|
|
322
|
+
*
|
|
323
|
+
* macOS's `loadServiceModes(config:)` only updates `inferenceMode` when
|
|
324
|
+
* `services.inference.mode` is present in the response — without the fill
|
|
325
|
+
* pass, freshly-hatched platform-managed assistants would have no `services`
|
|
326
|
+
* key on disk (only `llm.profiles` from `seedInferenceProfiles`) and macOS
|
|
327
|
+
* would fall back to its `@Published` default of "your-own". The helper is
|
|
328
|
+
* also responsible for guarding against `loadRawConfig()` returning a
|
|
329
|
+
* non-object payload from a malformed-but-parseable `config.json`.
|
|
330
|
+
*/
|
|
331
|
+
describe("GET /v1/config handler — context-default fill on raw response", () => {
|
|
332
|
+
const originalIsPlatform = process.env.IS_PLATFORM;
|
|
333
|
+
|
|
334
|
+
afterEach(() => {
|
|
335
|
+
if (originalIsPlatform === undefined) {
|
|
336
|
+
delete process.env.IS_PLATFORM;
|
|
337
|
+
} else {
|
|
338
|
+
process.env.IS_PLATFORM = originalIsPlatform;
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
test("IS_PLATFORM=true, raw config has no services key → response includes managed defaults", () => {
|
|
343
|
+
process.env.IS_PLATFORM = "true";
|
|
344
|
+
|
|
345
|
+
// Mirrors the real-world fresh-hatch state: lifecycle wrote
|
|
346
|
+
// `llm.profiles` to disk, but never persisted any service modes.
|
|
347
|
+
const raw: Record<string, unknown> = {
|
|
348
|
+
llm: {
|
|
349
|
+
profiles: {
|
|
350
|
+
balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
|
|
351
|
+
},
|
|
352
|
+
activeProfile: "balanced",
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const result = applyContextDefaultsToRawConfig(raw) as Record<
|
|
357
|
+
string,
|
|
358
|
+
unknown
|
|
359
|
+
>;
|
|
360
|
+
const services = result["services"] as Record<string, { mode: string }>;
|
|
361
|
+
expect(services).toBeDefined();
|
|
362
|
+
for (const svc of MANAGED_SERVICES) {
|
|
363
|
+
expect(services[svc]!.mode).toBe("managed");
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test("IS_PLATFORM=true, raw config has explicit services.image-generation.mode='your-own' → preserved", () => {
|
|
368
|
+
process.env.IS_PLATFORM = "true";
|
|
369
|
+
|
|
370
|
+
// User has explicitly chosen "your-own" for image-generation via the macOS
|
|
371
|
+
// Save flow. The patch handler persisted that to disk; the fill pass must
|
|
372
|
+
// not override an explicit user choice.
|
|
373
|
+
const raw: Record<string, unknown> = {
|
|
374
|
+
services: {
|
|
375
|
+
"image-generation": { mode: "your-own" },
|
|
376
|
+
},
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
const result = applyContextDefaultsToRawConfig(raw) as Record<
|
|
380
|
+
string,
|
|
381
|
+
unknown
|
|
382
|
+
>;
|
|
383
|
+
const services = result["services"] as Record<string, { mode: string }>;
|
|
384
|
+
expect(services["image-generation"]!.mode).toBe("your-own");
|
|
385
|
+
// web-search was missing → fill.
|
|
386
|
+
expect(services["web-search"]!.mode).toBe("managed");
|
|
387
|
+
// inference.mode is a legacy backwards-compat wire field — synthesized
|
|
388
|
+
// here for old macOS clients (SettingsStore.swift) that still read it.
|
|
389
|
+
expect(services["inference"]!.mode).toBe("managed");
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
test("IS_PLATFORM=false, raw config has no services key → response is unchanged", () => {
|
|
393
|
+
process.env.IS_PLATFORM = "false";
|
|
394
|
+
|
|
395
|
+
const raw: Record<string, unknown> = {
|
|
396
|
+
llm: {
|
|
397
|
+
profiles: {
|
|
398
|
+
balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const result = applyContextDefaultsToRawConfig(raw) as Record<
|
|
404
|
+
string,
|
|
405
|
+
unknown
|
|
406
|
+
>;
|
|
407
|
+
expect(result["services"]).toBeUndefined();
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
test("IS_PLATFORM=true, raw config has partial services subtree → preserves user fields, fills missing mode", () => {
|
|
411
|
+
process.env.IS_PLATFORM = "true";
|
|
412
|
+
|
|
413
|
+
// User set image-generation.provider but never chose a mode.
|
|
414
|
+
// The fill pass adds the missing mode without clobbering the user-supplied
|
|
415
|
+
// provider.
|
|
416
|
+
const raw: Record<string, unknown> = {
|
|
417
|
+
services: {
|
|
418
|
+
"image-generation": { provider: "openai" },
|
|
419
|
+
},
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const result = applyContextDefaultsToRawConfig(raw) as Record<
|
|
423
|
+
string,
|
|
424
|
+
unknown
|
|
425
|
+
>;
|
|
426
|
+
const services = result["services"] as Record<
|
|
427
|
+
string,
|
|
428
|
+
{ mode: string; provider?: string }
|
|
429
|
+
>;
|
|
430
|
+
expect(services["image-generation"]!.mode).toBe("managed");
|
|
431
|
+
expect(services["image-generation"]!.provider).toBe("openai");
|
|
432
|
+
// services.inference.mode is synthesized as a legacy wire-only field for
|
|
433
|
+
// older macOS clients during the rollout window (Phase 1.2 schema removal
|
|
434
|
+
// landed before the macOS Providers UI ships).
|
|
435
|
+
expect(services["inference"]!.mode).toBe("managed");
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
test("IS_PLATFORM=true, raw config has no inference subtree → synthesizes legacy mode='managed'", () => {
|
|
439
|
+
process.env.IS_PLATFORM = "true";
|
|
440
|
+
|
|
441
|
+
const raw: Record<string, unknown> = {
|
|
442
|
+
llm: {
|
|
443
|
+
profiles: {
|
|
444
|
+
balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
const result = applyContextDefaultsToRawConfig(raw) as Record<
|
|
450
|
+
string,
|
|
451
|
+
unknown
|
|
452
|
+
>;
|
|
453
|
+
const services = result["services"] as Record<string, { mode: string }>;
|
|
454
|
+
expect(services["inference"]!.mode).toBe("managed");
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
test("IS_PLATFORM=true, raw config has explicit services.inference.mode='your-own' → preserved (legacy override)", () => {
|
|
458
|
+
process.env.IS_PLATFORM = "true";
|
|
459
|
+
|
|
460
|
+
// Pre-migration upgrade: workspace config still carries the legacy
|
|
461
|
+
// mode value. The synthesis only fills when absent, so an explicit
|
|
462
|
+
// disk value wins until migration 076 strips it.
|
|
463
|
+
const raw: Record<string, unknown> = {
|
|
464
|
+
services: {
|
|
465
|
+
inference: { mode: "your-own" },
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
const result = applyContextDefaultsToRawConfig(raw) as Record<
|
|
470
|
+
string,
|
|
471
|
+
unknown
|
|
472
|
+
>;
|
|
473
|
+
const services = result["services"] as Record<string, { mode: string }>;
|
|
474
|
+
expect(services["inference"]!.mode).toBe("your-own");
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
test("IS_PLATFORM=false, raw config has no inference subtree → no synthesis", () => {
|
|
478
|
+
process.env.IS_PLATFORM = "false";
|
|
479
|
+
|
|
480
|
+
const raw: Record<string, unknown> = {
|
|
481
|
+
llm: {},
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
const result = applyContextDefaultsToRawConfig(raw) as Record<
|
|
485
|
+
string,
|
|
486
|
+
unknown
|
|
487
|
+
>;
|
|
488
|
+
expect(result["services"]).toBeUndefined();
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// -------------------------------------------------------------------------
|
|
492
|
+
// Malformed-but-parseable config.json — must not 500 the GET endpoint.
|
|
493
|
+
//
|
|
494
|
+
// `loadRawConfig()` is typed `Record<string, unknown>` but `JSON.parse`
|
|
495
|
+
// will happily return `null`, primitives, or arrays for a syntactically
|
|
496
|
+
// valid file like `null` / `42` / `[]`. The helper must return those
|
|
497
|
+
// payloads unchanged rather than throwing inside
|
|
498
|
+
// `fillContextDefaultsForMissingKeys`.
|
|
499
|
+
// -------------------------------------------------------------------------
|
|
500
|
+
|
|
501
|
+
test("IS_PLATFORM=true, raw config is null → returned unchanged (no throw)", () => {
|
|
502
|
+
process.env.IS_PLATFORM = "true";
|
|
503
|
+
expect(applyContextDefaultsToRawConfig(null)).toBe(null);
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
test("IS_PLATFORM=true, raw config is a primitive number → returned unchanged (no throw)", () => {
|
|
507
|
+
process.env.IS_PLATFORM = "true";
|
|
508
|
+
expect(applyContextDefaultsToRawConfig(42)).toBe(42);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
test("IS_PLATFORM=true, raw config is an array → returned unchanged (no throw)", () => {
|
|
512
|
+
process.env.IS_PLATFORM = "true";
|
|
513
|
+
const raw: unknown[] = [{ foo: "bar" }];
|
|
514
|
+
const result = applyContextDefaultsToRawConfig(raw);
|
|
515
|
+
expect(result).toBe(raw);
|
|
516
|
+
// No `services` key was synthesized onto the array.
|
|
517
|
+
expect((result as { services?: unknown }).services).toBeUndefined();
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
test("IS_PLATFORM=true, raw config is a string → returned unchanged (no throw)", () => {
|
|
521
|
+
process.env.IS_PLATFORM = "true";
|
|
522
|
+
expect(applyContextDefaultsToRawConfig("not-an-object")).toBe(
|
|
523
|
+
"not-an-object",
|
|
524
|
+
);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
test("IS_PLATFORM=false, raw config is null → returned unchanged (no throw)", () => {
|
|
528
|
+
// Sanity check: when there are no context defaults to apply, the helper
|
|
529
|
+
// also short-circuits cleanly on non-object payloads.
|
|
530
|
+
process.env.IS_PLATFORM = "false";
|
|
531
|
+
expect(applyContextDefaultsToRawConfig(null)).toBe(null);
|
|
195
532
|
});
|
|
196
533
|
});
|
|
@@ -3,7 +3,7 @@ import { join } from "node:path";
|
|
|
3
3
|
import { describe, expect, mock, test } from "bun:test";
|
|
4
4
|
|
|
5
5
|
// ---------------------------------------------------------------------------
|
|
6
|
-
// Mocks
|
|
6
|
+
// Mocks - declared before imports that depend on platform/logger/ipc
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
|
|
9
9
|
const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
@@ -45,28 +45,38 @@ mock.module("../util/logger.js", () => ({
|
|
|
45
45
|
getCliLogger: () => makeLoggerStub(),
|
|
46
46
|
}));
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Mocks - ipc/cli-client
|
|
50
|
+
//
|
|
51
|
+
// The `config` CLI is IPC-tagged, so all schema lookups go through the
|
|
52
|
+
// daemon. Mock cliIpcCall so we can drive the response in each test and
|
|
53
|
+
// assert on exit behavior without spinning up a daemon socket.
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
let mockIpcResult: {
|
|
57
|
+
ok: boolean;
|
|
58
|
+
result?: unknown;
|
|
59
|
+
error?: string;
|
|
60
|
+
statusCode?: number;
|
|
61
|
+
} = { ok: true, result: { schema: {} } };
|
|
62
|
+
|
|
63
|
+
mock.module("../ipc/cli-client.js", () => ({
|
|
64
|
+
cliIpcCall: async () => mockIpcResult,
|
|
65
|
+
exitFromIpcResult: (r: {
|
|
66
|
+
error?: string;
|
|
67
|
+
statusCode?: number;
|
|
68
|
+
}) => {
|
|
69
|
+
process.stderr.write((r.error ?? "Unknown error") + "\n");
|
|
70
|
+
if (r.statusCode === undefined) {
|
|
71
|
+
process.exit(10);
|
|
72
|
+
} else if (r.statusCode >= 500) {
|
|
73
|
+
process.exit(3);
|
|
74
|
+
} else if (r.statusCode >= 400) {
|
|
75
|
+
process.exit(2);
|
|
76
|
+
} else {
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
70
80
|
}));
|
|
71
81
|
|
|
72
82
|
import { Command } from "commander";
|
|
@@ -259,30 +269,54 @@ describe("z.toJSONSchema integration", () => {
|
|
|
259
269
|
|
|
260
270
|
// ---------------------------------------------------------------------------
|
|
261
271
|
// Tests: CLI schema command error path
|
|
272
|
+
//
|
|
273
|
+
// The CLI now routes `config schema <path>` through the daemon. When the
|
|
274
|
+
// daemon throws a BadRequestError for an unknown path, the IPC layer
|
|
275
|
+
// returns statusCode=400, and exitFromIpcResult maps that to process exit
|
|
276
|
+
// code 2 (per the matrix in cli-client.ts:exitFromIpcResult).
|
|
262
277
|
// ---------------------------------------------------------------------------
|
|
263
278
|
|
|
264
279
|
describe("CLI schema command", () => {
|
|
265
|
-
test("
|
|
280
|
+
test("daemon error for nonexistent path surfaces via exitFromIpcResult", async () => {
|
|
281
|
+
// Drive the IPC mock to return a BadRequest as the daemon would
|
|
282
|
+
mockIpcResult = {
|
|
283
|
+
ok: false,
|
|
284
|
+
error: "No schema found at path: nonexistent",
|
|
285
|
+
statusCode: 400,
|
|
286
|
+
};
|
|
287
|
+
|
|
266
288
|
const program = new Command();
|
|
267
|
-
program.exitOverride();
|
|
289
|
+
program.exitOverride();
|
|
268
290
|
registerConfigCommand(program);
|
|
269
291
|
|
|
270
292
|
const origExit = process.exit;
|
|
271
|
-
|
|
293
|
+
const origStderrWrite = process.stderr.write.bind(process.stderr);
|
|
272
294
|
let exitCode: number | undefined;
|
|
273
295
|
process.exit = ((code?: number) => {
|
|
274
296
|
exitCode = code;
|
|
275
297
|
throw new Error(`process.exit(${code})`);
|
|
276
298
|
}) as never;
|
|
299
|
+
process.stderr.write = (() => true) as typeof process.stderr.write;
|
|
277
300
|
|
|
278
301
|
try {
|
|
279
|
-
program.
|
|
302
|
+
await program.parseAsync([
|
|
303
|
+
"node",
|
|
304
|
+
"test",
|
|
305
|
+
"config",
|
|
306
|
+
"schema",
|
|
307
|
+
"nonexistent",
|
|
308
|
+
]);
|
|
280
309
|
} catch {
|
|
281
|
-
// Expected:
|
|
310
|
+
// Expected: process.exit stub throws
|
|
282
311
|
} finally {
|
|
283
312
|
process.exit = origExit;
|
|
313
|
+
process.stderr.write = origStderrWrite;
|
|
284
314
|
}
|
|
285
315
|
|
|
286
|
-
|
|
316
|
+
// 400 → exit 2 (per exitFromIpcResult matrix)
|
|
317
|
+
expect(exitCode).toBe(2);
|
|
318
|
+
|
|
319
|
+
// Restore default
|
|
320
|
+
mockIpcResult = { ok: true, result: { schema: {} } };
|
|
287
321
|
});
|
|
288
322
|
});
|
|
@@ -83,9 +83,9 @@ function writeConfig(obj: unknown): void {
|
|
|
83
83
|
describe("AssistantConfigSchema", () => {
|
|
84
84
|
test("parses empty object with full defaults", () => {
|
|
85
85
|
const result = AssistantConfigSchema.parse({});
|
|
86
|
-
// services.inference now
|
|
87
|
-
// llm.default.{provider,model}
|
|
88
|
-
expect(result.services.inference
|
|
86
|
+
// services.inference is now an empty object; provider/model live under
|
|
87
|
+
// llm.default.{provider,model}, auth routing via provider_connections.
|
|
88
|
+
expect(result.services.inference).toEqual({});
|
|
89
89
|
expect(result.llm.default.provider).toBe("anthropic");
|
|
90
90
|
expect(result.llm.default.model).toBe("claude-opus-4-7");
|
|
91
91
|
expect(result.services["image-generation"].provider).toBe("gemini");
|
|
@@ -134,6 +134,17 @@ describe("AssistantConfigSchema", () => {
|
|
|
134
134
|
expect(result.auditLog).toEqual({ retentionDays: 0 });
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
+
test("accepts Tavily as a web search provider", () => {
|
|
138
|
+
const result = AssistantConfigSchema.parse({
|
|
139
|
+
services: {
|
|
140
|
+
"web-search": { mode: "your-own", provider: "tavily" },
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
expect(result.services["web-search"].provider).toBe("tavily");
|
|
145
|
+
expect(result.services["web-search"].mode).toBe("your-own");
|
|
146
|
+
});
|
|
147
|
+
|
|
137
148
|
test("accepts valid complete config", () => {
|
|
138
149
|
const input = {
|
|
139
150
|
llm: {
|