@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
|
@@ -3,14 +3,73 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Logs method, path, status, and latency for every request to aid
|
|
5
5
|
* debugging client issues. Uses structured Pino logging.
|
|
6
|
+
*
|
|
7
|
+
* Routes can opt in to suppress the per-request INFO line after a confirmed
|
|
8
|
+
* run of N successful responses by declaring `logging.silenceSuccessAfter`
|
|
9
|
+
* on the route definition. Warning (4xx) and error (5xx) lines are always
|
|
10
|
+
* emitted regardless of this setting.
|
|
6
11
|
*/
|
|
7
12
|
|
|
8
13
|
import { getLogger } from "../../util/logger.js";
|
|
14
|
+
import type { RouteLoggingConfig } from "../routes/types.js";
|
|
9
15
|
|
|
10
16
|
const log = getLogger("http-request");
|
|
11
17
|
|
|
12
18
|
const UNKNOWN = "unknown" as const;
|
|
13
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Optional metadata supplied by the caller (typically resolved from the
|
|
22
|
+
* matched route) that lets the middleware adjust its per-request log
|
|
23
|
+
* behavior — e.g. suppressing success logs after a threshold for noisy
|
|
24
|
+
* polling endpoints like `/v1/health`.
|
|
25
|
+
*/
|
|
26
|
+
export interface RequestLogMetadata {
|
|
27
|
+
/**
|
|
28
|
+
* Stable identifier used as the success-suppression counter key. Two
|
|
29
|
+
* requests with the same counterKey share a single counter (so all
|
|
30
|
+
* variants of a parameterized route share suppression state).
|
|
31
|
+
*/
|
|
32
|
+
counterKey: string;
|
|
33
|
+
config: RouteLoggingConfig;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Module-level counter map. Tracks the cumulative number of successful
|
|
37
|
+
// (status < 400) responses logged per `counterKey`. Once the count passes
|
|
38
|
+
// the route's `silenceSuccessAfter` threshold, further successful responses
|
|
39
|
+
// skip the per-request INFO log line. Counters never reset within a
|
|
40
|
+
// process — the behavior is "the route worked, stop spamming".
|
|
41
|
+
const successCounters = new Map<string, number>();
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Test-only: reset the per-route success counters. Production code never
|
|
45
|
+
* calls this; tests use it to isolate suppression state between cases.
|
|
46
|
+
*/
|
|
47
|
+
export function _resetRequestLoggingCountersForTests(): void {
|
|
48
|
+
successCounters.clear();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Decide whether the success log line should be suppressed for this
|
|
53
|
+
* request. Returns true when the counter has already reached the
|
|
54
|
+
* configured threshold. Pure read — the counter is only mutated when
|
|
55
|
+
* the log line is actually emitted.
|
|
56
|
+
*/
|
|
57
|
+
function shouldSuppressSuccess(meta: RequestLogMetadata | undefined): boolean {
|
|
58
|
+
if (!meta) return false;
|
|
59
|
+
const threshold = meta.config.silenceSuccessAfter;
|
|
60
|
+
if (threshold === undefined || threshold <= 0) return false;
|
|
61
|
+
const current = successCounters.get(meta.counterKey) ?? 0;
|
|
62
|
+
return current >= threshold;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Record that we just emitted a success log line for this route. */
|
|
66
|
+
function bumpSuccessCounter(meta: RequestLogMetadata | undefined): void {
|
|
67
|
+
if (!meta) return;
|
|
68
|
+
if (meta.config.silenceSuccessAfter === undefined) return;
|
|
69
|
+
const current = successCounters.get(meta.counterKey) ?? 0;
|
|
70
|
+
successCounters.set(meta.counterKey, current + 1);
|
|
71
|
+
}
|
|
72
|
+
|
|
14
73
|
/**
|
|
15
74
|
* Wrap a request handler to log request metadata and response timing.
|
|
16
75
|
*
|
|
@@ -20,6 +79,7 @@ const UNKNOWN = "unknown" as const;
|
|
|
20
79
|
export async function withRequestLogging(
|
|
21
80
|
req: Request,
|
|
22
81
|
handler: () => Promise<Response>,
|
|
82
|
+
meta?: RequestLogMetadata,
|
|
23
83
|
): Promise<Response> {
|
|
24
84
|
const start = performance.now();
|
|
25
85
|
const url = new URL(req.url);
|
|
@@ -66,8 +126,9 @@ export async function withRequestLogging(
|
|
|
66
126
|
log.error(logData, `${method} ${path} -> ${status} (${latencyMs}ms)`);
|
|
67
127
|
} else if (status >= 400) {
|
|
68
128
|
log.warn(logData, `${method} ${path} -> ${status} (${latencyMs}ms)`);
|
|
69
|
-
} else {
|
|
129
|
+
} else if (!shouldSuppressSuccess(meta)) {
|
|
70
130
|
log.info(logData, `${method} ${path} -> ${status} (${latencyMs}ms)`);
|
|
131
|
+
bumpSuccessCounter(meta);
|
|
71
132
|
}
|
|
72
133
|
|
|
73
134
|
return response;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate for LLM-touching background work that runs between daemon start and
|
|
3
|
+
* the user's first interaction.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* Cloud-hosted assistants are served from a warm pool: the daemon boots,
|
|
8
|
+
* background services initialize, and the image waits to be claimed by a
|
|
9
|
+
* real user. Before the user claims an image, no provider credentials are
|
|
10
|
+
* registered, so any background job that tries to call the LLM fails — and
|
|
11
|
+
* those failure rows persist in the local SQLite database, becoming visible
|
|
12
|
+
* in the conversation sidebar the moment the user hatches.
|
|
13
|
+
*
|
|
14
|
+
* ## The probe
|
|
15
|
+
*
|
|
16
|
+
* `hasReceivedUserMessage()` returns `true` once at least one
|
|
17
|
+
* `role='user'` message exists in a `conversation_type='standard'`
|
|
18
|
+
* conversation. Background / scheduled conversations don't count — they're
|
|
19
|
+
* exactly the noise we're trying to suppress.
|
|
20
|
+
*
|
|
21
|
+
* The result is cached in-process after the first `true` because the flag
|
|
22
|
+
* is monotonic: a user message, once present, is never deleted in a way
|
|
23
|
+
* that should re-open the gate. (Even a destructive sweep that wipes all
|
|
24
|
+
* messages would still want background jobs paused until a real user
|
|
25
|
+
* interaction resumes, so re-querying on miss is the correct behavior.)
|
|
26
|
+
*
|
|
27
|
+
* Callers should treat the gate as advisory + defense-in-depth: prefer to
|
|
28
|
+
* skip at the service level (heartbeat, update-bulletin, etc.) so no run
|
|
29
|
+
* row / conversation row is created at all, and rely on the gate inside
|
|
30
|
+
* `runBackgroundJob` as the universal backstop.
|
|
31
|
+
*/
|
|
32
|
+
import { rawGet } from "../memory/raw-query.js";
|
|
33
|
+
import { getLogger } from "../util/logger.js";
|
|
34
|
+
|
|
35
|
+
const log = getLogger("pre-first-message-gate");
|
|
36
|
+
|
|
37
|
+
let cachedHasUserMessage = false;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Returns `true` if the local store has ever recorded a user-authored
|
|
41
|
+
* message in a standard conversation.
|
|
42
|
+
*
|
|
43
|
+
* Cheap: indexed lookup with `LIMIT 1`. After the first `true` result the
|
|
44
|
+
* answer is cached in-process and subsequent calls are O(1).
|
|
45
|
+
*
|
|
46
|
+
* On query error the function logs a warning and returns `false` — the
|
|
47
|
+
* conservative interpretation is "we can't prove the user has interacted,
|
|
48
|
+
* so don't fire background work."
|
|
49
|
+
*/
|
|
50
|
+
export function hasReceivedUserMessage(): boolean {
|
|
51
|
+
if (cachedHasUserMessage) return true;
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const row = rawGet<{ one: number }>(
|
|
55
|
+
`SELECT 1 AS one FROM messages m
|
|
56
|
+
JOIN conversations c ON m.conversation_id = c.id
|
|
57
|
+
WHERE m.role = 'user'
|
|
58
|
+
AND c.conversation_type = 'standard'
|
|
59
|
+
LIMIT 1`,
|
|
60
|
+
);
|
|
61
|
+
if (row != null) {
|
|
62
|
+
cachedHasUserMessage = true;
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
log.warn(
|
|
68
|
+
{ err },
|
|
69
|
+
"hasReceivedUserMessage: query failed; treating as not-yet-received so background work stays paused",
|
|
70
|
+
);
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Test-only reset of the in-process cache. Real code paths must never
|
|
77
|
+
* call this — the cache is monotonic by design.
|
|
78
|
+
*
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
export function _resetPreFirstMessageGateCacheForTests(): void {
|
|
82
|
+
cachedHasUserMessage = false;
|
|
83
|
+
}
|
|
@@ -720,10 +720,17 @@ describe("handleBackupVerify", () => {
|
|
|
720
720
|
// ---------------------------------------------------------------------------
|
|
721
721
|
|
|
722
722
|
describe("ROUTES", () => {
|
|
723
|
-
test("registers
|
|
723
|
+
test("registers routes with the expected endpoint+method pairs", () => {
|
|
724
724
|
const pairs = ROUTES.map((d) => `${d.method} ${d.endpoint}`).sort();
|
|
725
725
|
expect(pairs).toEqual([
|
|
726
|
+
"GET backup/destinations",
|
|
727
|
+
"GET backup/status",
|
|
726
728
|
"GET backups",
|
|
729
|
+
"POST backup/destinations/add",
|
|
730
|
+
"POST backup/destinations/remove",
|
|
731
|
+
"POST backup/destinations/set-encrypt",
|
|
732
|
+
"POST backup/disable",
|
|
733
|
+
"POST backup/enable",
|
|
727
734
|
"POST backups/create",
|
|
728
735
|
"POST backups/restore",
|
|
729
736
|
"POST backups/verify",
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the bookmark route handlers in `bookmark-routes.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* - POST + GET round-trip
|
|
6
|
+
* - POST idempotency (no duplicate row, same id returned)
|
|
7
|
+
* - POST FK validation (unknown messageId → 4xx)
|
|
8
|
+
* - DELETE /by-message/:messageId
|
|
9
|
+
* - SSE event publication on create AND delete
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
13
|
+
|
|
14
|
+
// Capture publish() invocations so the tests can assert on emitted events
|
|
15
|
+
// without spinning up real SSE infrastructure.
|
|
16
|
+
const publishCalls: unknown[] = [];
|
|
17
|
+
|
|
18
|
+
mock.module("../../assistant-event-hub.js", () => ({
|
|
19
|
+
assistantEventHub: {
|
|
20
|
+
publish: async (event: unknown) => {
|
|
21
|
+
publishCalls.push(event);
|
|
22
|
+
},
|
|
23
|
+
subscribe: () => () => {},
|
|
24
|
+
},
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
import { getDb } from "../../../memory/db-connection.js";
|
|
28
|
+
import { initializeDb } from "../../../memory/db-init.js";
|
|
29
|
+
import {
|
|
30
|
+
conversations,
|
|
31
|
+
messageBookmarks,
|
|
32
|
+
messages,
|
|
33
|
+
} from "../../../memory/schema.js";
|
|
34
|
+
import { ROUTES as BOOKMARK_ROUTES } from "../bookmark-routes.js";
|
|
35
|
+
import type { RouteDefinition, RouteHandlerArgs } from "../types.js";
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// DB bootstrap
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
initializeDb();
|
|
42
|
+
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Helpers
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
function findHandler(operationId: string): RouteDefinition["handler"] {
|
|
48
|
+
const route = BOOKMARK_ROUTES.find((r) => r.operationId === operationId);
|
|
49
|
+
if (!route) throw new Error(`Route ${operationId} not found`);
|
|
50
|
+
return route.handler;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const listHandler = findHandler("bookmarks_list");
|
|
54
|
+
const createHandler = findHandler("bookmarks_create");
|
|
55
|
+
const deleteByMessageHandler = findHandler("bookmarks_delete_by_message");
|
|
56
|
+
|
|
57
|
+
function clearDb(): void {
|
|
58
|
+
const db = getDb();
|
|
59
|
+
// Bookmarks first (FK), then messages, then conversations.
|
|
60
|
+
db.delete(messageBookmarks).run();
|
|
61
|
+
db.delete(messages).run();
|
|
62
|
+
db.delete(conversations).run();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function seedConversationAndMessage(opts: {
|
|
66
|
+
conversationId: string;
|
|
67
|
+
messageId: string;
|
|
68
|
+
conversationTitle?: string;
|
|
69
|
+
messageContent?: string;
|
|
70
|
+
messageRole?: string;
|
|
71
|
+
}): void {
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
const db = getDb();
|
|
74
|
+
db.insert(conversations)
|
|
75
|
+
.values({
|
|
76
|
+
id: opts.conversationId,
|
|
77
|
+
title: opts.conversationTitle ?? "Test conversation",
|
|
78
|
+
createdAt: now,
|
|
79
|
+
updatedAt: now,
|
|
80
|
+
source: "test",
|
|
81
|
+
conversationType: "standard",
|
|
82
|
+
memoryScopeId: "default",
|
|
83
|
+
})
|
|
84
|
+
.run();
|
|
85
|
+
db.insert(messages)
|
|
86
|
+
.values({
|
|
87
|
+
id: opts.messageId,
|
|
88
|
+
conversationId: opts.conversationId,
|
|
89
|
+
role: opts.messageRole ?? "user",
|
|
90
|
+
content: opts.messageContent ?? "hello world",
|
|
91
|
+
createdAt: now,
|
|
92
|
+
})
|
|
93
|
+
.run();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function call(
|
|
97
|
+
handler: RouteDefinition["handler"],
|
|
98
|
+
args: RouteHandlerArgs,
|
|
99
|
+
): Promise<unknown> {
|
|
100
|
+
return await handler(args);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
interface EventEnvelope {
|
|
104
|
+
message: { type: string; [key: string]: unknown };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function publishedTypes(): string[] {
|
|
108
|
+
return publishCalls.map((e) => (e as EventEnvelope).message.type);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
beforeEach(() => {
|
|
112
|
+
clearDb();
|
|
113
|
+
publishCalls.length = 0;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Tests
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
describe("bookmark routes", () => {
|
|
121
|
+
test("POST then GET returns the new bookmark", async () => {
|
|
122
|
+
seedConversationAndMessage({
|
|
123
|
+
conversationId: "conv-1",
|
|
124
|
+
messageId: "msg-1",
|
|
125
|
+
messageContent: "first message body",
|
|
126
|
+
messageRole: "assistant",
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const created = (await call(createHandler, {
|
|
130
|
+
body: { messageId: "msg-1", conversationId: "conv-1" },
|
|
131
|
+
})) as { id: string; messageId: string; messagePreview: string };
|
|
132
|
+
|
|
133
|
+
expect(created.messageId).toBe("msg-1");
|
|
134
|
+
expect(created.messagePreview).toBe("first message body");
|
|
135
|
+
|
|
136
|
+
const listed = (await call(listHandler, {})) as {
|
|
137
|
+
bookmarks: Array<{ id: string; messageId: string }>;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
expect(listed.bookmarks).toHaveLength(1);
|
|
141
|
+
expect(listed.bookmarks[0]?.id).toBe(created.id);
|
|
142
|
+
expect(listed.bookmarks[0]?.messageId).toBe("msg-1");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("POST is idempotent — second call returns same id, no duplicate row", async () => {
|
|
146
|
+
seedConversationAndMessage({
|
|
147
|
+
conversationId: "conv-2",
|
|
148
|
+
messageId: "msg-2",
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const first = (await call(createHandler, {
|
|
152
|
+
body: { messageId: "msg-2", conversationId: "conv-2" },
|
|
153
|
+
})) as { id: string };
|
|
154
|
+
const second = (await call(createHandler, {
|
|
155
|
+
body: { messageId: "msg-2", conversationId: "conv-2" },
|
|
156
|
+
})) as { id: string };
|
|
157
|
+
|
|
158
|
+
expect(second.id).toBe(first.id);
|
|
159
|
+
|
|
160
|
+
const listed = (await call(listHandler, {})) as {
|
|
161
|
+
bookmarks: unknown[];
|
|
162
|
+
};
|
|
163
|
+
expect(listed.bookmarks).toHaveLength(1);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("POST with non-existent messageId returns a 4xx", async () => {
|
|
167
|
+
seedConversationAndMessage({
|
|
168
|
+
conversationId: "conv-3",
|
|
169
|
+
messageId: "msg-3",
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
let caught: unknown = null;
|
|
173
|
+
try {
|
|
174
|
+
await call(createHandler, {
|
|
175
|
+
body: { messageId: "missing-msg", conversationId: "conv-3" },
|
|
176
|
+
});
|
|
177
|
+
} catch (err) {
|
|
178
|
+
caught = err;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
expect(caught).not.toBeNull();
|
|
182
|
+
// RouteError subclasses (BadRequestError, NotFoundError, …) carry a
|
|
183
|
+
// `statusCode` field that the HTTP adapter forwards to the wire — assert
|
|
184
|
+
// that we throw something in the 4xx range without coupling to the
|
|
185
|
+
// specific subclass.
|
|
186
|
+
const statusCode = (caught as { statusCode?: number }).statusCode;
|
|
187
|
+
expect(
|
|
188
|
+
typeof statusCode === "number" && statusCode >= 400 && statusCode < 500,
|
|
189
|
+
).toBe(true);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("DELETE /by-message/:messageId removes the row", async () => {
|
|
193
|
+
seedConversationAndMessage({
|
|
194
|
+
conversationId: "conv-5",
|
|
195
|
+
messageId: "msg-5",
|
|
196
|
+
});
|
|
197
|
+
await call(createHandler, {
|
|
198
|
+
body: { messageId: "msg-5", conversationId: "conv-5" },
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const result = (await call(deleteByMessageHandler, {
|
|
202
|
+
pathParams: { messageId: "msg-5" },
|
|
203
|
+
})) as { success: boolean };
|
|
204
|
+
expect(result.success).toBe(true);
|
|
205
|
+
|
|
206
|
+
const listed = (await call(listHandler, {})) as { bookmarks: unknown[] };
|
|
207
|
+
expect(listed.bookmarks).toHaveLength(0);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("publishes SSE events on create AND delete", async () => {
|
|
211
|
+
seedConversationAndMessage({
|
|
212
|
+
conversationId: "conv-6",
|
|
213
|
+
messageId: "msg-6",
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const created = (await call(createHandler, {
|
|
217
|
+
body: { messageId: "msg-6", conversationId: "conv-6" },
|
|
218
|
+
})) as { id: string };
|
|
219
|
+
|
|
220
|
+
// Publishes are fire-and-forget (`.catch(...)`), so let any pending
|
|
221
|
+
// microtasks settle before asserting.
|
|
222
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
223
|
+
|
|
224
|
+
expect(publishedTypes()).toEqual(["bookmark.created"]);
|
|
225
|
+
const createdEvent = publishCalls[0] as EventEnvelope;
|
|
226
|
+
expect(createdEvent.message.type).toBe("bookmark.created");
|
|
227
|
+
expect(
|
|
228
|
+
(createdEvent.message as unknown as { bookmark: { id: string } }).bookmark
|
|
229
|
+
.id,
|
|
230
|
+
).toBe(created.id);
|
|
231
|
+
|
|
232
|
+
publishCalls.length = 0;
|
|
233
|
+
|
|
234
|
+
await call(deleteByMessageHandler, { pathParams: { messageId: "msg-6" } });
|
|
235
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
236
|
+
|
|
237
|
+
expect(publishedTypes()).toEqual(["bookmark.deleted"]);
|
|
238
|
+
const deletedEvent = publishCalls[0] as EventEnvelope;
|
|
239
|
+
expect(
|
|
240
|
+
(deletedEvent.message as unknown as { messageId?: string }).messageId,
|
|
241
|
+
).toBe("msg-6");
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test("DELETE on a non-existent messageId does not publish", async () => {
|
|
245
|
+
await call(deleteByMessageHandler, {
|
|
246
|
+
pathParams: { messageId: "does-not-exist" },
|
|
247
|
+
});
|
|
248
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
249
|
+
expect(publishCalls).toHaveLength(0);
|
|
250
|
+
});
|
|
251
|
+
});
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cutover-proof parity test: CLI create vs HTTP route create.
|
|
3
|
+
*
|
|
4
|
+
* Runs a CLI `createConnection` call and an HTTP-route `handleCreateConnection`
|
|
5
|
+
* call with the same payload, then asserts the resulting DB rows are identical
|
|
6
|
+
* (after normalizing timestamps). This proves the HTTP route wraps the same
|
|
7
|
+
* store path the CLI uses — no divergent code path.
|
|
8
|
+
*
|
|
9
|
+
* Rule: cc-cutover-proof (see PR_B_TASK.md).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
13
|
+
|
|
14
|
+
// ── Module mocks (must come before imports) ──────────────────────────────────
|
|
15
|
+
|
|
16
|
+
mock.module("../../../config/loader.js", () => ({
|
|
17
|
+
getConfigReadOnly: () => ({}),
|
|
18
|
+
getConfig: () => ({}),
|
|
19
|
+
invalidateConfigCache: () => {},
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
mock.module("../../../util/logger.js", () => ({
|
|
23
|
+
getLogger: () =>
|
|
24
|
+
new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
// ── Real imports ──────────────────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
import { getDb } from "../../../memory/db-connection.js";
|
|
30
|
+
import { initializeDb } from "../../../memory/db-init.js";
|
|
31
|
+
import { providerConnections } from "../../../memory/schema/inference.js";
|
|
32
|
+
import { createConnection, getConnection } from "../../../providers/inference/connections.js";
|
|
33
|
+
import { ROUTES } from "../inference-provider-connection-routes.js";
|
|
34
|
+
import type { RouteDefinition } from "../types.js";
|
|
35
|
+
|
|
36
|
+
// ── DB bootstrap ──────────────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
initializeDb();
|
|
39
|
+
|
|
40
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
function findHandler(operationId: string): RouteDefinition["handler"] {
|
|
43
|
+
const route = ROUTES.find((r) => r.operationId === operationId);
|
|
44
|
+
if (!route) throw new Error(`Route ${operationId} not found`);
|
|
45
|
+
return route.handler;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function clearConnections(): void {
|
|
49
|
+
getDb().delete(providerConnections).run();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function normalizeTimestamps<T extends object>(obj: T): Omit<T, "createdAt" | "updatedAt"> {
|
|
53
|
+
const { createdAt: _c, updatedAt: _u, ...rest } = obj as T & { createdAt?: unknown; updatedAt?: unknown };
|
|
54
|
+
return rest as Omit<T, "createdAt" | "updatedAt">;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
clearConnections();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe("CLI vs HTTP route parity", () => {
|
|
64
|
+
test("api_key connection: CLI createConnection and HTTP POST produce identical DB rows", async () => {
|
|
65
|
+
const payload = {
|
|
66
|
+
name: "parity-anthropic",
|
|
67
|
+
provider: "anthropic" as const,
|
|
68
|
+
auth: { type: "api_key" as const, credential: "vault/anthropic/key" },
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// ── CLI path ──────────────────────────────────────────────────────────────
|
|
72
|
+
const cliResult = createConnection(getDb(), payload);
|
|
73
|
+
expect(cliResult.ok).toBe(true);
|
|
74
|
+
if (!cliResult.ok) throw new Error("CLI create failed");
|
|
75
|
+
const cliRow = getConnection(getDb(), payload.name);
|
|
76
|
+
expect(cliRow).not.toBeNull();
|
|
77
|
+
|
|
78
|
+
// Clean up CLI row before HTTP create so names don't collide.
|
|
79
|
+
clearConnections();
|
|
80
|
+
|
|
81
|
+
// ── HTTP route path ───────────────────────────────────────────────────────
|
|
82
|
+
const httpResult = (await findHandler("inference_provider_connections_create")({
|
|
83
|
+
body: {
|
|
84
|
+
name: payload.name,
|
|
85
|
+
provider: payload.provider,
|
|
86
|
+
auth: payload.auth,
|
|
87
|
+
},
|
|
88
|
+
})) as { name: string; provider: string; auth: object };
|
|
89
|
+
|
|
90
|
+
expect(httpResult.name).toBe(payload.name);
|
|
91
|
+
const httpRow = getConnection(getDb(), payload.name);
|
|
92
|
+
expect(httpRow).not.toBeNull();
|
|
93
|
+
|
|
94
|
+
// ── Compare ───────────────────────────────────────────────────────────────
|
|
95
|
+
// Both rows should have identical non-timestamp fields.
|
|
96
|
+
expect(normalizeTimestamps(httpRow!)).toEqual(normalizeTimestamps(cliRow!));
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("platform connection: CLI createConnection and HTTP POST produce identical DB rows", async () => {
|
|
100
|
+
const payload = {
|
|
101
|
+
name: "parity-openai-managed",
|
|
102
|
+
provider: "openai" as const,
|
|
103
|
+
auth: { type: "platform" as const },
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const cliResult = createConnection(getDb(), payload);
|
|
107
|
+
expect(cliResult.ok).toBe(true);
|
|
108
|
+
if (!cliResult.ok) throw new Error("CLI create failed");
|
|
109
|
+
const cliRow = getConnection(getDb(), payload.name);
|
|
110
|
+
|
|
111
|
+
clearConnections();
|
|
112
|
+
|
|
113
|
+
await findHandler("inference_provider_connections_create")({
|
|
114
|
+
body: { name: payload.name, provider: payload.provider, auth: payload.auth },
|
|
115
|
+
});
|
|
116
|
+
const httpRow = getConnection(getDb(), payload.name);
|
|
117
|
+
|
|
118
|
+
expect(normalizeTimestamps(httpRow!)).toEqual(normalizeTimestamps(cliRow!));
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("none auth connection: CLI createConnection and HTTP POST produce identical DB rows", async () => {
|
|
122
|
+
const payload = {
|
|
123
|
+
name: "parity-ollama",
|
|
124
|
+
provider: "ollama" as const,
|
|
125
|
+
auth: { type: "none" as const },
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const cliResult = createConnection(getDb(), payload);
|
|
129
|
+
expect(cliResult.ok).toBe(true);
|
|
130
|
+
if (!cliResult.ok) throw new Error("CLI create failed");
|
|
131
|
+
const cliRow = getConnection(getDb(), payload.name);
|
|
132
|
+
|
|
133
|
+
clearConnections();
|
|
134
|
+
|
|
135
|
+
await findHandler("inference_provider_connections_create")({
|
|
136
|
+
body: { name: payload.name, provider: payload.provider, auth: payload.auth },
|
|
137
|
+
});
|
|
138
|
+
const httpRow = getConnection(getDb(), payload.name);
|
|
139
|
+
|
|
140
|
+
expect(normalizeTimestamps(httpRow!)).toEqual(normalizeTimestamps(cliRow!));
|
|
141
|
+
});
|
|
142
|
+
});
|