@vellumai/assistant 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +11 -0
- package/Dockerfile +5 -4
- package/README.md +2 -2
- package/docker-entrypoint.sh +16 -0
- package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
- package/eslint-rules/cli-no-daemon-internals.js +283 -0
- package/eslint.config.mjs +12 -0
- package/knip.json +2 -1
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/openapi.yaml +4847 -1698
- package/package.json +3 -1
- package/scripts/generate-openapi.ts +52 -4
- package/scripts/sync-llm-catalog.ts +165 -0
- package/scripts/sync-web-search-catalog.ts +107 -0
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
- package/src/__tests__/anthropic-provider.test.ts +92 -2
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/avatar-identity-sync.test.ts +87 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/call-site-routing-provider.test.ts +172 -45
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
- package/src/__tests__/channel-policy.test.ts +12 -0
- package/src/__tests__/checker.test.ts +89 -0
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
- package/src/__tests__/config-loader-backfill.test.ts +526 -102
- package/src/__tests__/config-loader-corrupt.test.ts +68 -0
- package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
- package/src/__tests__/config-schema-cmd.test.ts +63 -29
- package/src/__tests__/config-schema.test.ts +14 -3
- package/src/__tests__/config-set-platform-guard.test.ts +75 -152
- package/src/__tests__/config-set-route.test.ts +198 -0
- package/src/__tests__/config-watcher.test.ts +6 -0
- package/src/__tests__/contacts-tools.test.ts +51 -199
- package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
- package/src/__tests__/context-search-agent-runner.test.ts +22 -138
- package/src/__tests__/context-search-conversations-source.test.ts +42 -16
- package/src/__tests__/context-search-fanout.test.ts +20 -157
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
- package/src/__tests__/context-search-types.test.ts +7 -2
- package/src/__tests__/context-window-manager.test.ts +389 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
- package/src/__tests__/conversation-error.test.ts +38 -0
- package/src/__tests__/conversation-fork-crud.test.ts +241 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
- package/src/__tests__/conversation-lifecycle.test.ts +124 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
- package/src/__tests__/conversation-process-callsite.test.ts +21 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +4 -4
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -6
- package/src/__tests__/daemon-credential-client.test.ts +56 -1
- package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
- package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
- package/src/__tests__/db-proxy-transaction.test.ts +206 -0
- package/src/__tests__/external-plugin-loader.test.ts +458 -0
- package/src/__tests__/filing-service.test.ts +23 -3
- package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -8
- package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
- package/src/__tests__/heartbeat-service.test.ts +50 -233
- package/src/__tests__/history-repair.test.ts +89 -0
- package/src/__tests__/host-app-control-proxy.test.ts +109 -1
- package/src/__tests__/host-app-control-routes.test.ts +247 -1
- package/src/__tests__/host-browser-proxy.test.ts +416 -20
- package/src/__tests__/host-browser-routes.test.ts +325 -33
- package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
- package/src/__tests__/inference-profile-reaper.test.ts +154 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
- package/src/__tests__/install-skill-routing.test.ts +2 -2
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +15 -0
- package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
- package/src/__tests__/llm-catalog-parity.test.ts +146 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
- package/src/__tests__/llm-resolver.test.ts +46 -0
- package/src/__tests__/managed-profile-guard.test.ts +131 -2
- package/src/__tests__/mcp-auth-routes.test.ts +1 -0
- package/src/__tests__/mcp-cli.test.ts +182 -220
- package/src/__tests__/mcp-health-check.test.ts +56 -27
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
- package/src/__tests__/message-complete-display-id.test.ts +175 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -2009
- package/src/__tests__/oauth-commands-routes.test.ts +711 -0
- package/src/__tests__/oauth-connect-routes.test.ts +174 -11
- package/src/__tests__/oauth-providers-routes.test.ts +14 -10
- package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
- package/src/__tests__/openai-responses-provider.test.ts +17 -0
- package/src/__tests__/plugin-bootstrap.test.ts +31 -2
- package/src/__tests__/plugin-route-contribution.test.ts +31 -3
- package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
- package/src/__tests__/plugin-types.test.ts +13 -11
- package/src/__tests__/process-message-background-slack.test.ts +46 -0
- package/src/__tests__/profile-entry-status.test.ts +43 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
- package/src/__tests__/provider-registry-ollama.test.ts +12 -4
- package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
- package/src/__tests__/relay-server.test.ts +118 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
- package/src/__tests__/schedule-retry.test.ts +56 -4
- package/src/__tests__/schedule-routes.test.ts +104 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
- package/src/__tests__/scheduler-recurrence.test.ts +87 -34
- package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
- package/src/__tests__/scheduler-wake.test.ts +0 -63
- package/src/__tests__/secret-allowlist.test.ts +1 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
- package/src/__tests__/shell-credential-ref.test.ts +95 -3
- package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skill-load-tool.test.ts +2 -4
- package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +63 -0
- package/src/__tests__/task-scheduler.test.ts +88 -23
- package/src/__tests__/update-bulletin-job.test.ts +96 -193
- package/src/__tests__/usage-cli.test.ts +11 -73
- package/src/__tests__/user-plugin-loader.test.ts +145 -0
- package/src/__tests__/vercel-config.test.ts +168 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
- package/src/__tests__/web-search.test.ts +303 -2
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
- package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
- package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
- package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
- package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
- package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
- package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
- package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
- package/src/acp/__tests__/helpers/which-stub.ts +4 -2
- package/src/acp/resolve-agent.test.ts +25 -0
- package/src/acp/resolve-agent.ts +13 -2
- package/src/acp/session-manager.ts +14 -0
- package/src/approvals/guardian-request-resolvers.ts +32 -87
- package/src/calls/relay-server.ts +35 -0
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +23 -4
- package/src/channels/config.ts +14 -1
- package/src/channels/types.ts +1 -0
- package/src/cli/AGENTS.md +164 -4
- package/src/cli/__tests__/notifications.test.ts +54 -0
- package/src/cli/commands/__tests__/avatar.test.ts +540 -0
- package/src/cli/commands/__tests__/backup.test.ts +236 -776
- package/src/cli/commands/__tests__/cache.test.ts +1 -1
- package/src/cli/commands/__tests__/changelog.test.ts +593 -0
- package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
- package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
- package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
- package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
- package/src/cli/commands/__tests__/email-core.test.ts +579 -0
- package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
- package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
- package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
- package/src/cli/commands/__tests__/skills.test.ts +563 -0
- package/src/cli/commands/__tests__/status.test.ts +249 -0
- package/src/cli/commands/__tests__/stt.test.ts +320 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
- package/src/cli/commands/__tests__/tts.test.ts +321 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
- package/src/cli/commands/attachment.ts +8 -3
- package/src/cli/commands/audit.ts +95 -64
- package/src/cli/commands/auth.ts +61 -58
- package/src/cli/commands/avatar.ts +276 -390
- package/src/cli/commands/backup.ts +409 -505
- package/src/cli/commands/bash.ts +9 -5
- package/src/cli/commands/browser.ts +28 -9
- package/src/cli/commands/cache.ts +9 -4
- package/src/cli/commands/changelog.ts +414 -0
- package/src/cli/commands/channel-verification-sessions.ts +238 -317
- package/src/cli/commands/clients.ts +8 -3
- package/src/cli/commands/completions.ts +9 -9
- package/src/cli/commands/config.ts +102 -72
- package/src/cli/commands/contacts.ts +575 -696
- package/src/cli/commands/conversations-defer.ts +17 -69
- package/src/cli/commands/conversations-import.ts +90 -253
- package/src/cli/commands/conversations.ts +346 -436
- package/src/cli/commands/credential-execution.ts +9 -6
- package/src/cli/commands/credentials.ts +456 -736
- package/src/cli/commands/domain.ts +128 -206
- package/src/cli/commands/email.ts +606 -794
- package/src/cli/commands/gateway.ts +8 -1
- package/src/cli/commands/image-generation.ts +157 -205
- package/src/cli/commands/inference-providers.ts +352 -0
- package/src/cli/commands/inference-session.ts +415 -0
- package/src/cli/commands/inference.ts +87 -65
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.ts +103 -287
- package/src/cli/commands/memory-v2.ts +162 -516
- package/src/cli/commands/notifications.ts +33 -7
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +176 -297
- package/src/cli/commands/oauth/disconnect.ts +16 -215
- package/src/cli/commands/oauth/index.ts +49 -45
- package/src/cli/commands/oauth/mode.ts +43 -199
- package/src/cli/commands/oauth/ping.ts +17 -125
- package/src/cli/commands/oauth/providers.ts +732 -921
- package/src/cli/commands/oauth/request.ts +60 -350
- package/src/cli/commands/oauth/shared.ts +11 -121
- package/src/cli/commands/oauth/status.ts +31 -121
- package/src/cli/commands/oauth/token.ts +13 -55
- package/src/cli/commands/pending.ts +19 -10
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
- package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
- package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
- package/src/cli/commands/platform/connect.ts +16 -80
- package/src/cli/commands/platform/disconnect.ts +14 -112
- package/src/cli/commands/platform/index.ts +177 -246
- package/src/cli/commands/routes.ts +153 -336
- package/src/cli/commands/sequence.ts +316 -360
- package/src/cli/commands/skills.ts +449 -671
- package/src/cli/commands/status.ts +58 -37
- package/src/cli/commands/stt.ts +94 -262
- package/src/cli/commands/task.ts +14 -40
- package/src/cli/commands/trust.ts +8 -3
- package/src/cli/commands/tts.ts +162 -167
- package/src/cli/commands/ui.ts +35 -42
- package/src/cli/commands/usage.ts +188 -126
- package/src/cli/commands/watchers.ts +8 -3
- package/src/cli/commands/webhooks.ts +99 -193
- package/src/cli/lib/__tests__/register-command.test.ts +85 -0
- package/src/cli/lib/daemon-credential-client.ts +4 -5
- package/src/cli/lib/nested-value.ts +44 -0
- package/src/cli/lib/open-browser.ts +36 -0
- package/src/cli/lib/register-command.ts +19 -0
- package/src/cli/lib/time-ago.ts +34 -0
- package/src/cli/program.ts +2 -4
- package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
- package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
- package/src/cli/utils/conversation-id.ts +30 -0
- package/src/cli/utils/parse-duration.ts +41 -0
- package/src/config/acp-defaults.test.ts +5 -1
- package/src/config/acp-defaults.ts +11 -4
- package/src/config/bundled-skills/acp/TOOLS.json +2 -2
- package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
- package/src/config/bundled-skills/contacts/SKILL.md +12 -45
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
- package/src/config/bundled-tool-registry.ts +0 -2
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +76 -14
- package/src/config/raw-config-utils.ts +2 -30
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
- package/src/config/schemas/call-site-catalog.ts +29 -7
- package/src/config/schemas/llm-request-logs.ts +57 -0
- package/src/config/schemas/llm.ts +52 -2
- package/src/config/schemas/memory-retrospective.ts +48 -0
- package/src/config/schemas/memory-v2.ts +32 -1
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +15 -12
- package/src/config/seed-inference-profiles.ts +195 -134
- package/src/contacts/contact-store.ts +0 -61
- package/src/context/window-manager.ts +191 -5
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +79 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
- package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
- package/src/daemon/approval-generators.ts +23 -29
- package/src/daemon/config-watcher.ts +2 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
- package/src/daemon/conversation-agent-loop.ts +127 -97
- package/src/daemon/conversation-error.ts +21 -0
- package/src/daemon/conversation-lifecycle.ts +46 -5
- package/src/daemon/conversation-process.ts +36 -19
- package/src/daemon/conversation-runtime-assembly.ts +14 -5
- package/src/daemon/conversation-slash.ts +175 -23
- package/src/daemon/conversation-store.ts +17 -10
- package/src/daemon/conversation-surfaces.ts +76 -12
- package/src/daemon/conversation-tool-setup.ts +24 -14
- package/src/daemon/conversation.ts +48 -9
- package/src/daemon/external-plugins-bootstrap.ts +18 -8
- package/src/daemon/guardian-action-generators.ts +7 -22
- package/src/daemon/handlers/config-model.ts +8 -126
- package/src/daemon/handlers/config-slack-channel.ts +10 -7
- package/src/daemon/handlers/config-vercel.ts +3 -1
- package/src/daemon/handlers/skills.ts +84 -5
- package/src/daemon/history-repair.ts +33 -6
- package/src/daemon/host-app-control-proxy.ts +44 -19
- package/src/daemon/host-bash-proxy.ts +85 -158
- package/src/daemon/host-browser-proxy.ts +96 -35
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +42 -43
- package/src/daemon/meet-host-supervisor.ts +15 -15
- package/src/daemon/memory-v2-startup.ts +9 -2
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/bookmarks.ts +18 -0
- package/src/daemon/message-types/conversations.ts +12 -9
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/sync.ts +60 -0
- package/src/daemon/pkb-reminder-builder.test.ts +54 -13
- package/src/daemon/pkb-reminder-builder.ts +21 -7
- package/src/daemon/process-message.ts +56 -23
- package/src/daemon/server.ts +23 -18
- package/src/daemon/shutdown-handlers.ts +0 -2
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/daemon/tool-side-effects.ts +6 -4
- package/src/daemon/wake-target-adapter.ts +11 -0
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +40 -53
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +148 -127
- package/src/home/__tests__/feed-types.test.ts +63 -131
- package/src/home/__tests__/feed-writer.test.ts +77 -278
- package/src/home/__tests__/post-connect-feed.test.ts +9 -12
- package/src/home/feed-types.ts +19 -73
- package/src/home/feed-writer.ts +25 -156
- package/src/home/post-connect-feed.ts +1 -3
- package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
- package/src/ipc/__tests__/email-ipc.test.ts +506 -0
- package/src/ipc/__tests__/exit-helper.test.ts +104 -0
- package/src/ipc/__tests__/streaming-client.test.ts +237 -0
- package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
- package/src/ipc/assistant-server.ts +55 -6
- package/src/ipc/cli-client.ts +370 -50
- package/src/ipc/routes/db-proxy-transaction.ts +151 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
- package/src/ipc/skill-routes/events.ts +30 -3
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
- package/src/live-voice/live-voice-session-manager.ts +11 -4
- package/src/live-voice/live-voice-session.ts +14 -6
- package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
- package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
- package/src/memory/__tests__/conversation-types.test.ts +36 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
- package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
- package/src/memory/bookmark-crud.ts +179 -0
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
- package/src/memory/context-search/agent-protocol.ts +5 -1
- package/src/memory/context-search/agent-runner.ts +60 -85
- package/src/memory/context-search/limits.ts +1 -4
- package/src/memory/context-search/search.ts +23 -113
- package/src/memory/context-search/sources/conversations.ts +18 -6
- package/src/memory/context-search/sources/memory-v2.ts +39 -14
- package/src/memory/context-search/sources/memory.ts +7 -0
- package/src/memory/context-search/sources/workspace.ts +13 -10
- package/src/memory/context-search/types.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +11 -0
- package/src/memory/conversation-crud.ts +312 -10
- package/src/memory/conversation-queries.ts +9 -5
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/conversation-types.ts +16 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +2 -1
- package/src/memory/embedding-runtime-manager.ts +1 -2
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +76 -5
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/tool-handlers.ts +17 -7
- package/src/memory/graph/tools.ts +44 -5
- package/src/memory/indexer.ts +17 -0
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +13 -15
- package/src/memory/jobs/embed-concept-page.ts +45 -9
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +52 -3
- package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
- package/src/memory/llm-request-log-source-local.ts +26 -0
- package/src/memory/llm-request-log-source.ts +97 -0
- package/src/memory/llm-request-log-store.ts +1 -1
- package/src/memory/memory-retrospective-constants.ts +13 -0
- package/src/memory/memory-retrospective-enqueue.ts +114 -0
- package/src/memory/memory-retrospective-job.ts +351 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
- package/src/memory/memory-retrospective-state.ts +162 -0
- package/src/memory/memory-retrospective-trigger-check.ts +91 -0
- package/src/memory/memory-v2-activation-log-store.ts +49 -5
- package/src/memory/memory-v2-concept-frequency.ts +4 -0
- package/src/memory/message-content.ts +38 -1
- package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
- package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
- package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
- package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
- package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
- package/src/memory/migrations/242-message-bookmarks.ts +38 -0
- package/src/memory/migrations/243-provider-connections.ts +68 -0
- package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
- package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
- package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
- package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
- package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
- package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/schema/bookmarks.ts +38 -0
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/inference.ts +29 -0
- package/src/memory/schema/memory-core.ts +9 -0
- package/src/memory/search/semantic.ts +1 -4
- package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
- package/src/memory/v2/__tests__/activation.test.ts +11 -4
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
- package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
- package/src/memory/v2/__tests__/injection.test.ts +628 -10
- package/src/memory/v2/__tests__/migration.test.ts +7 -3
- package/src/memory/v2/__tests__/page-index.test.ts +277 -0
- package/src/memory/v2/__tests__/page-store.test.ts +14 -1
- package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +72 -0
- package/src/memory/v2/__tests__/reranker.test.ts +4 -4
- package/src/memory/v2/__tests__/router.test.ts +516 -0
- package/src/memory/v2/__tests__/sim.test.ts +45 -1
- package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
- package/src/memory/v2/__tests__/static-context.test.ts +7 -22
- package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
- package/src/memory/v2/activation-store.ts +34 -5
- package/src/memory/v2/activation.ts +40 -27
- package/src/memory/v2/backfill-jobs.ts +17 -84
- package/src/memory/v2/consolidation-job.ts +85 -78
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +440 -109
- package/src/memory/v2/migration.ts +117 -20
- package/src/memory/v2/page-index.ts +191 -0
- package/src/memory/v2/page-store.ts +3 -0
- package/src/memory/v2/prompts/consolidation.ts +9 -7
- package/src/memory/v2/prompts/router.ts +192 -0
- package/src/memory/v2/qdrant.ts +100 -87
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +322 -0
- package/src/memory/v2/sim.ts +25 -12
- package/src/memory/v2/skill-store.ts +118 -29
- package/src/memory/v2/static-context.ts +16 -9
- package/src/memory/v2/sweep-job.ts +122 -96
- package/src/memory/v2/types.ts +10 -6
- package/src/memory/validation.ts +13 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
- package/src/notifications/__tests__/signal-registry.test.ts +17 -0
- package/src/notifications/adapters/platform.ts +171 -0
- package/src/notifications/conversation-pairing.ts +2 -2
- package/src/notifications/copy-composer.ts +15 -0
- package/src/notifications/destination-resolver.ts +21 -0
- package/src/notifications/emit-signal.ts +28 -1
- package/src/notifications/home-feed-side-effect.ts +111 -0
- package/src/notifications/signal.ts +5 -0
- package/src/permissions/checker.ts +12 -0
- package/src/permissions/ipc-risk-types.ts +2 -0
- package/src/plugin-api/index.ts +13 -0
- package/src/plugin-api/package.json +12 -0
- package/src/plugin-api/types.ts +62 -0
- package/src/plugins/defaults/injectors.ts +19 -3
- package/src/plugins/external-plugin-loader.ts +294 -0
- package/src/plugins/types.ts +46 -30
- package/src/plugins/user-loader.ts +64 -41
- package/src/proactive-artifact/job.test.ts +12 -4
- package/src/proactive-artifact/job.ts +4 -0
- package/src/proactive-artifact/trigger-state.test.ts +9 -0
- package/src/proactive-artifact/trigger-state.ts +4 -0
- package/src/prompts/__tests__/system-prompt.test.ts +105 -0
- package/src/prompts/system-prompt.ts +22 -1
- package/src/prompts/update-bulletin-job.ts +61 -73
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
- package/src/providers/__tests__/inference.test.ts +288 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +14 -32
- package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
- package/src/providers/anthropic/client.ts +95 -26
- package/src/providers/call-site-routing.ts +94 -16
- package/src/providers/connection-resolution.ts +163 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
- package/src/providers/inference/adapter-factory.ts +173 -0
- package/src/providers/inference/auth.ts +112 -0
- package/src/providers/inference/backfill.ts +196 -0
- package/src/providers/inference/connections.ts +356 -0
- package/src/providers/inference/resolve-auth.ts +65 -0
- package/src/providers/model-catalog.ts +104 -6
- package/src/providers/openai/responses-provider.ts +4 -2
- package/src/providers/provider-env-vars.ts +17 -7
- package/src/providers/provider-secret-catalog.ts +49 -30
- package/src/providers/provider-send-message.ts +41 -20
- package/src/providers/registry.ts +143 -159
- package/src/providers/retry.ts +18 -10
- package/src/providers/search-provider-catalog.ts +121 -0
- package/src/runtime/AGENTS.md +18 -5
- package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
- package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
- package/src/runtime/actor-trust-resolver.ts +32 -10
- package/src/runtime/agent-wake.ts +35 -6
- package/src/runtime/assistant-event-hub.ts +3 -85
- package/src/runtime/auth/route-policy.ts +303 -8
- package/src/runtime/auth/same-actor.ts +2 -0
- package/src/runtime/background-job-runner.ts +339 -0
- package/src/runtime/btw-sidechain.ts +1 -0
- package/src/runtime/http-router.ts +36 -1
- package/src/runtime/http-server.ts +31 -5
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
- package/src/runtime/middleware/request-logger.ts +62 -1
- package/src/runtime/pre-first-message-gate.ts +83 -0
- package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/acp-routes.ts +10 -8
- package/src/runtime/routes/app-management-routes.ts +228 -3
- package/src/runtime/routes/approval-routes.ts +0 -18
- package/src/runtime/routes/audit-routes.ts +43 -0
- package/src/runtime/routes/auth-routes.ts +72 -0
- package/src/runtime/routes/avatar-routes.ts +273 -20
- package/src/runtime/routes/backup-routes.ts +406 -2
- package/src/runtime/routes/bookmark-routes.ts +154 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/contact-routes.ts +0 -160
- package/src/runtime/routes/conversation-cli-routes.ts +192 -0
- package/src/runtime/routes/conversation-management-routes.ts +30 -43
- package/src/runtime/routes/conversation-query-routes.ts +334 -86
- package/src/runtime/routes/conversation-routes.ts +31 -10
- package/src/runtime/routes/conversations-import-routes.ts +229 -0
- package/src/runtime/routes/credential-routes.ts +540 -0
- package/src/runtime/routes/debug-routes.ts +2 -2
- package/src/runtime/routes/document-pdf-renderer.ts +5 -1
- package/src/runtime/routes/domain-routes.ts +167 -0
- package/src/runtime/routes/email-routes.ts +603 -0
- package/src/runtime/routes/errors.ts +2 -2
- package/src/runtime/routes/events-routes.ts +192 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -78
- package/src/runtime/routes/host-app-control-routes.ts +44 -2
- package/src/runtime/routes/host-browser-routes.ts +103 -22
- package/src/runtime/routes/http-adapter.ts +2 -0
- package/src/runtime/routes/identity-routes.ts +5 -0
- package/src/runtime/routes/image-generation-routes.ts +99 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
- package/src/runtime/routes/index.ts +36 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
- package/src/runtime/routes/inference-send-routes.ts +115 -0
- package/src/runtime/routes/integrations/twilio.ts +1 -0
- package/src/runtime/routes/mcp-auth-routes.ts +283 -9
- package/src/runtime/routes/memory-v2-routes.ts +13 -398
- package/src/runtime/routes/notification-routes.ts +2 -0
- package/src/runtime/routes/oauth-apps.ts +112 -7
- package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
- package/src/runtime/routes/oauth-connect-routes.ts +67 -5
- package/src/runtime/routes/oauth-providers.ts +298 -8
- package/src/runtime/routes/platform-routes.ts +336 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -1
- package/src/runtime/routes/playground/reset-circuit.ts +2 -1
- package/src/runtime/routes/playground/state.ts +2 -1
- package/src/runtime/routes/publish-routes.ts +221 -0
- package/src/runtime/routes/schedule-routes.ts +82 -0
- package/src/runtime/routes/sequence-routes.ts +291 -0
- package/src/runtime/routes/settings-routes.ts +2 -10
- package/src/runtime/routes/skills-routes.ts +31 -1
- package/src/runtime/routes/stt-routes.ts +240 -3
- package/src/runtime/routes/surface-action-routes.ts +43 -7
- package/src/runtime/routes/tts-routes.ts +67 -0
- package/src/runtime/routes/types.ts +32 -0
- package/src/runtime/routes/user-routes-cli.ts +243 -0
- package/src/runtime/routes/webhook-routes.ts +165 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/sync/sync-publisher.test.ts +105 -0
- package/src/runtime/sync/sync-publisher.ts +21 -0
- package/src/schedule/scheduler.ts +200 -123
- package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
- package/src/security/secret-patterns.ts +3 -0
- package/src/sequence/engine.ts +38 -40
- package/src/subagent/manager.ts +20 -15
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
- package/src/tools/browser/browser-execution.ts +15 -4
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
- package/src/tools/browser/cdp-client/factory.ts +66 -5
- package/src/tools/browser/runtime-check.ts +77 -0
- package/src/tools/memory/register.test.ts +3 -3
- package/src/tools/memory/register.ts +9 -1
- package/src/tools/network/__tests__/web-search.test.ts +156 -0
- package/src/tools/network/web-search.ts +280 -37
- package/src/tools/permission-checker.ts +13 -5
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/terminal/shell.ts +44 -0
- package/src/usage/attribution.ts +3 -2
- package/src/util/pricing.ts +86 -160
- package/src/watcher/__tests__/engine.test.ts +301 -0
- package/src/watcher/constants.ts +7 -0
- package/src/watcher/engine.ts +90 -90
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
- package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
- package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
- package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
- package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
- package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
- package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
- package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
- package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
- package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
- package/src/workspace/migrations/registry.ts +22 -0
- package/src/workspace/migrations/runner.ts +13 -2
- package/src/workspace/migrations/types.ts +13 -3
- package/src/workspace/provider-commit-message-generator.ts +3 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -498
- package/src/__tests__/credentials-cli.test.ts +0 -1225
- package/src/__tests__/memory-admin-recall.test.ts +0 -213
- package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
- package/src/cli/commands/__tests__/email-download.test.ts +0 -260
- package/src/cli/commands/__tests__/email-list.test.ts +0 -216
- package/src/cli/commands/__tests__/email-register.test.ts +0 -186
- package/src/cli/commands/__tests__/email-send.test.ts +0 -416
- package/src/cli/commands/__tests__/email-status.test.ts +0 -185
- package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
- package/src/cli/commands/__tests__/routes.test.ts +0 -562
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
- package/src/cli/commands/autonomy.ts +0 -365
- package/src/cli/commands/memory.ts +0 -424
- package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
- package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
- package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
- package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
- package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
- package/src/cli/lib/daemon-avatar-client.ts +0 -37
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
- package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
- package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
- package/src/home/__tests__/emit-feed-event.test.ts +0 -169
- package/src/home/__tests__/feed-population-integration.test.ts +0 -312
- package/src/home/__tests__/feed-scheduler.test.ts +0 -222
- package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
- package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
- package/src/home/__tests__/rollup-producer.test.ts +0 -507
- package/src/home/assistant-feed-authoring.ts +0 -135
- package/src/home/emit-feed-event.ts +0 -169
- package/src/home/feed-scheduler.ts +0 -281
- package/src/home/platform-gmail-digest.ts +0 -163
- package/src/home/rewrite-command-preview.ts +0 -66
- package/src/home/rewrite-feed-title.ts +0 -58
- package/src/home/rollup-producer.ts +0 -426
- package/src/memory/admin.ts +0 -326
- package/src/memory/context-search/sources/pkb.ts +0 -476
- package/src/memory/graph/compaction.ts +0 -299
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loadConfig } from "../config/loader.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { wrapWithCallSiteRouting } from "../providers/call-site-routing.js";
|
|
3
|
+
import { resolveDefaultProvider } from "../providers/connection-resolution.js";
|
|
4
4
|
import type { Provider } from "../providers/types.js";
|
|
5
5
|
import {
|
|
6
6
|
APPROVAL_COPY_MAX_TOKENS,
|
|
@@ -79,15 +79,18 @@ const VALID_DISPOSITIONS: ReadonlySet<string> = new Set([
|
|
|
79
79
|
export function createApprovalCopyGenerator(): ApprovalCopyGenerator {
|
|
80
80
|
return async (context, options = {}) => {
|
|
81
81
|
const config = loadConfig();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
// Connection-aware default-provider resolution. Throws
|
|
83
|
+
// `ConnectionResolutionError` on hard config errors (missing /
|
|
84
|
+
// unknown / mismatched connection). Returns null on soft credential
|
|
85
|
+
// failures (vault miss, transient auth) — we treat null as "no
|
|
86
|
+
// provider available" and skip generating copy.
|
|
87
|
+
const baseProvider: Provider | null = await resolveDefaultProvider(config);
|
|
88
|
+
if (!baseProvider) return null;
|
|
88
89
|
// Wrap so per-call `callSite` can route to an alternative provider
|
|
89
90
|
// transport when `llm.callSites.<id>.provider` overrides the default.
|
|
90
|
-
|
|
91
|
+
// The `wrapWithCallSiteRouting` helper threads `config` through so the
|
|
92
|
+
// wrapper's per-call resolution is also connection-aware.
|
|
93
|
+
const provider = wrapWithCallSiteRouting(baseProvider, config);
|
|
91
94
|
|
|
92
95
|
const fallbackText =
|
|
93
96
|
options.fallbackText?.trim() || getFallbackMessage(context);
|
|
@@ -136,12 +139,19 @@ export function createApprovalCopyGenerator(): ApprovalCopyGenerator {
|
|
|
136
139
|
export function createApprovalConversationGenerator(): ApprovalConversationGenerator {
|
|
137
140
|
return async (context) => {
|
|
138
141
|
const config = loadConfig();
|
|
139
|
-
|
|
142
|
+
// Connection-aware default + per-call routing. `resolveDefaultProvider`
|
|
143
|
+
// throws `ConnectionResolutionError` on hard config errors (missing /
|
|
144
|
+
// unknown / mismatched connection) and returns null on soft credential
|
|
145
|
+
// failures (vault miss, transient auth) — we treat null as "no
|
|
146
|
+
// provider available" and throw a domain-specific error below. We do
|
|
147
|
+
// not pre-gate on `listProviders()` because the default provider lives
|
|
148
|
+
// behind a `provider_connection` and never appears in the registry's
|
|
149
|
+
// initialization-time provider list.
|
|
150
|
+
const baseProvider = await resolveDefaultProvider(config);
|
|
151
|
+
if (!baseProvider) {
|
|
140
152
|
throw new Error("No provider available for approval conversation");
|
|
141
153
|
}
|
|
142
|
-
const provider = wrapWithCallSiteRouting(
|
|
143
|
-
getProvider(config.llm.default.provider),
|
|
144
|
-
);
|
|
154
|
+
const provider = wrapWithCallSiteRouting(baseProvider, config);
|
|
145
155
|
|
|
146
156
|
const pendingDescription = context.pendingApprovals
|
|
147
157
|
.map((p) => `- Request ${p.requestId}: tool "${p.toolName}"`)
|
|
@@ -212,19 +222,3 @@ export function createApprovalConversationGenerator(): ApprovalConversationGener
|
|
|
212
222
|
return result;
|
|
213
223
|
};
|
|
214
224
|
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Wrap a base Provider so per-call `callSite` metadata can route the actual
|
|
218
|
-
* transport to a different provider when `llm.callSites.<id>.provider`
|
|
219
|
-
* differs from the default. Without this wrapper, only request metadata
|
|
220
|
-
* reflects the callSite — the HTTP transport stays bound to the default.
|
|
221
|
-
*/
|
|
222
|
-
function wrapWithCallSiteRouting(base: Provider): Provider {
|
|
223
|
-
return new CallSiteRoutingProvider(base, (name) => {
|
|
224
|
-
try {
|
|
225
|
-
return getProvider(name);
|
|
226
|
-
} catch {
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
}
|
|
@@ -18,6 +18,7 @@ import { getConfig, invalidateConfigCache } from "../config/loader.js";
|
|
|
18
18
|
import type { MemoryCleanupConfig } from "../config/schemas/memory-lifecycle.js";
|
|
19
19
|
import { resetCleanupScheduleThrottle } from "../memory/cleanup-schedule-state.js";
|
|
20
20
|
import { clearEmbeddingBackendCache } from "../memory/embedding-backend.js";
|
|
21
|
+
import { invalidateLlmRequestLogSourceCache } from "../memory/llm-request-log-source.js";
|
|
21
22
|
import { initializeProviders } from "../providers/registry.js";
|
|
22
23
|
import { handleCancelSignal } from "../signals/cancel.js";
|
|
23
24
|
import { handleConversationUndoSignal } from "../signals/conversation-undo.js";
|
|
@@ -140,6 +141,7 @@ export class ConfigWatcher {
|
|
|
140
141
|
return false;
|
|
141
142
|
}
|
|
142
143
|
clearEmbeddingBackendCache();
|
|
144
|
+
invalidateLlmRequestLogSourceCache();
|
|
143
145
|
// If cleanup retention settings changed, reset the cleanup scheduler
|
|
144
146
|
// throttle so the next worker tick re-enqueues jobs with the new values
|
|
145
147
|
// instead of waiting out the remaining enqueueIntervalMs (default 6h).
|
|
@@ -118,6 +118,12 @@ export interface EventHandlerState {
|
|
|
118
118
|
orderingErrorDetected: boolean;
|
|
119
119
|
deferredOrderingError: string | null;
|
|
120
120
|
contextTooLargeDetected: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Set when the provider rejects with an image-dimension error. The agent
|
|
123
|
+
* loop strips or downscales oversized image blocks from ctx.messages and
|
|
124
|
+
* retries once before surfacing an error to the user.
|
|
125
|
+
*/
|
|
126
|
+
imageTooLargeDetected: boolean;
|
|
121
127
|
/**
|
|
122
128
|
* The provider error object when context_too_large is detected, preserved
|
|
123
129
|
* so `parseActualTokensFromError` can prefer the typed
|
|
@@ -127,6 +133,11 @@ export interface EventHandlerState {
|
|
|
127
133
|
*/
|
|
128
134
|
contextTooLargeError: unknown;
|
|
129
135
|
providerErrorUserMessage: string | null;
|
|
136
|
+
/**
|
|
137
|
+
* First persisted assistant row in this run; history keeps this id when it
|
|
138
|
+
* merges tool-turn rows into one display bubble.
|
|
139
|
+
*/
|
|
140
|
+
firstAssistantMessageId: string | undefined;
|
|
130
141
|
lastAssistantMessageId: string | undefined;
|
|
131
142
|
readonly pendingToolResults: Map<string, PendingToolResult>;
|
|
132
143
|
readonly persistedToolUseIds: Set<string>;
|
|
@@ -220,8 +231,10 @@ export function createEventHandlerState(): EventHandlerState {
|
|
|
220
231
|
orderingErrorDetected: false,
|
|
221
232
|
deferredOrderingError: null,
|
|
222
233
|
contextTooLargeDetected: false,
|
|
234
|
+
imageTooLargeDetected: false,
|
|
223
235
|
contextTooLargeError: null,
|
|
224
236
|
providerErrorUserMessage: null,
|
|
237
|
+
firstAssistantMessageId: undefined,
|
|
225
238
|
lastAssistantMessageId: undefined,
|
|
226
239
|
pendingToolResults: new Map(),
|
|
227
240
|
persistedToolUseIds: new Set(),
|
|
@@ -245,6 +258,12 @@ export function createEventHandlerState(): EventHandlerState {
|
|
|
245
258
|
};
|
|
246
259
|
}
|
|
247
260
|
|
|
261
|
+
export function getClientDisplayMessageId(
|
|
262
|
+
state: EventHandlerState,
|
|
263
|
+
): string | undefined {
|
|
264
|
+
return state.firstAssistantMessageId ?? state.lastAssistantMessageId;
|
|
265
|
+
}
|
|
266
|
+
|
|
248
267
|
// ── Shared Helper ────────────────────────────────────────────────────
|
|
249
268
|
|
|
250
269
|
// providerNameOverride should be supplied when the caller already knows the
|
|
@@ -781,6 +800,10 @@ function handleError(
|
|
|
781
800
|
if (classified.code === "CONTEXT_TOO_LARGE") {
|
|
782
801
|
state.contextTooLargeDetected = true;
|
|
783
802
|
state.contextTooLargeError = event.error;
|
|
803
|
+
} else if (classified.code === "IMAGE_TOO_LARGE") {
|
|
804
|
+
// Trigger silent recovery: the agent loop will strip/downscale images
|
|
805
|
+
// in ctx.messages and retry once before surfacing an error.
|
|
806
|
+
state.imageTooLargeDetected = true;
|
|
784
807
|
} else if (
|
|
785
808
|
classified.code === "PROVIDER_ORDERING" ||
|
|
786
809
|
classified.code === "PROVIDER_WEB_SEARCH"
|
|
@@ -1004,6 +1027,7 @@ export async function handleMessageComplete(
|
|
|
1004
1027
|
DEFAULT_TIMEOUTS.persistence,
|
|
1005
1028
|
)) as PersistAddResult;
|
|
1006
1029
|
const assistantMsg = assistantPersistResult.message;
|
|
1030
|
+
state.firstAssistantMessageId ??= assistantMsg.id;
|
|
1007
1031
|
state.lastAssistantMessageId = assistantMsg.id;
|
|
1008
1032
|
|
|
1009
1033
|
// Backfill message_id on all LLM request logs from this turn.
|
|
@@ -11,6 +11,7 @@ import { join } from "node:path";
|
|
|
11
11
|
|
|
12
12
|
import { v4 as uuid } from "uuid";
|
|
13
13
|
|
|
14
|
+
import { optimizeImageForTransport } from "../agent/image-optimize.js";
|
|
14
15
|
import type {
|
|
15
16
|
AgentEvent,
|
|
16
17
|
AgentLoop,
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
contextWindowConfigFromEffective,
|
|
29
30
|
resolveEffectiveContextWindow,
|
|
30
31
|
} from "../config/llm-context-resolution.js";
|
|
32
|
+
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
31
33
|
import { getConfig } from "../config/loader.js";
|
|
32
34
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
33
35
|
import type { ContextWindowConfig } from "../config/types.js";
|
|
@@ -41,9 +43,7 @@ import {
|
|
|
41
43
|
} from "../context/token-estimator.js";
|
|
42
44
|
import type { ContextWindowManager } from "../context/window-manager.js";
|
|
43
45
|
import type { ToolProfiler } from "../events/tool-profiling-listener.js";
|
|
44
|
-
import { emitFeedEvent } from "../home/emit-feed-event.js";
|
|
45
46
|
import { writeRelationshipState } from "../home/relationship-state-writer.js";
|
|
46
|
-
import { rewriteFeedTitle } from "../home/rewrite-feed-title.js";
|
|
47
47
|
import {
|
|
48
48
|
clearSentryConversationContext,
|
|
49
49
|
setSentryConversationContext,
|
|
@@ -71,11 +71,12 @@ import {
|
|
|
71
71
|
} from "../memory/conversation-title-service.js";
|
|
72
72
|
import type { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
|
|
73
73
|
import { recordMemoryRecallLog } from "../memory/memory-recall-log-store.js";
|
|
74
|
+
import { enqueueMemoryRetrospectiveOnCompaction } from "../memory/memory-retrospective-enqueue.js";
|
|
74
75
|
import { PKB_WORKSPACE_SCOPE } from "../memory/pkb/types.js";
|
|
75
76
|
import type { QdrantSparseVector } from "../memory/qdrant-client.js";
|
|
76
77
|
import {
|
|
77
78
|
readMemoryV2StaticContent,
|
|
78
|
-
|
|
79
|
+
shouldExposePersonalMemory,
|
|
79
80
|
} from "../memory/v2/static-context.js";
|
|
80
81
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
81
82
|
import { defaultCompactionTerminal } from "../plugins/defaults/compaction.js";
|
|
@@ -147,6 +148,7 @@ import {
|
|
|
147
148
|
createEventHandlerState,
|
|
148
149
|
dispatchAgentEvent,
|
|
149
150
|
type EventHandlerDeps,
|
|
151
|
+
getClientDisplayMessageId,
|
|
150
152
|
} from "./conversation-agent-loop-handlers.js";
|
|
151
153
|
import {
|
|
152
154
|
approveHostAttachmentRead,
|
|
@@ -679,7 +681,9 @@ export async function runAgentLoopImpl(
|
|
|
679
681
|
overrideProfile: turnOverrideProfile ?? undefined,
|
|
680
682
|
});
|
|
681
683
|
const turnContextWindowConfig = contextWindowConfigFromEffective(
|
|
682
|
-
config.llm
|
|
684
|
+
resolveCallSiteConfig(turnCallSite, config.llm, {
|
|
685
|
+
overrideProfile: turnOverrideProfile ?? undefined,
|
|
686
|
+
}).contextWindow,
|
|
683
687
|
effectiveContextWindow,
|
|
684
688
|
);
|
|
685
689
|
(
|
|
@@ -1411,33 +1415,44 @@ export async function runAgentLoopImpl(
|
|
|
1411
1415
|
|
|
1412
1416
|
// The `remember` tool handles scratchpad-style memory writes directly to the graph.
|
|
1413
1417
|
|
|
1418
|
+
// Personal-memory trust gate: PKB, NOW.md, and v2 static blocks all
|
|
1419
|
+
// hold private user content. Block exposure to non-guardian actors
|
|
1420
|
+
// arriving over a remote channel; internal/local flows pass through.
|
|
1421
|
+
// See `shouldExposePersonalMemory` for the threat model.
|
|
1422
|
+
const personalMemoryAllowed = shouldExposePersonalMemory({
|
|
1423
|
+
sourceChannel: ctx.trustContext?.sourceChannel,
|
|
1424
|
+
isTrustedActor,
|
|
1425
|
+
});
|
|
1426
|
+
|
|
1414
1427
|
// Inject NOW.md and PKB content only on the first turn (or after
|
|
1415
1428
|
// compaction re-strips them). Old injections persist in history and
|
|
1416
1429
|
// are never stripped on normal turns — this preserves the cached prefix.
|
|
1417
1430
|
// PKB/NOW content is sourced from the `memoryRetrieval` pipeline above
|
|
1418
1431
|
// so plugins can override either source without touching the agent loop.
|
|
1419
|
-
const currentNowContent =
|
|
1432
|
+
const currentNowContent = personalMemoryAllowed
|
|
1433
|
+
? memoryResult.nowContent
|
|
1434
|
+
: null;
|
|
1420
1435
|
const shouldInjectNowAndPkb = isFirstMessage || compactedThisTurn;
|
|
1421
1436
|
const nowScratchpad = shouldInjectNowAndPkb ? currentNowContent : null;
|
|
1422
1437
|
|
|
1423
|
-
const currentPkbContent =
|
|
1438
|
+
const currentPkbContent = personalMemoryAllowed
|
|
1439
|
+
? memoryResult.pkbContent
|
|
1440
|
+
: null;
|
|
1424
1441
|
const pkbContext = shouldInjectNowAndPkb ? currentPkbContent : null;
|
|
1425
1442
|
const pkbActive = currentPkbContent !== null;
|
|
1426
1443
|
|
|
1427
|
-
// V2 static memory block (essentials/threads/recent/buffer).
|
|
1428
|
-
//
|
|
1429
|
-
//
|
|
1430
|
-
//
|
|
1431
|
-
//
|
|
1432
|
-
//
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
isTrustedActor,
|
|
1437
|
-
})
|
|
1444
|
+
// V2 static memory block (essentials/threads/recent/buffer).
|
|
1445
|
+
// `currentMemoryV2Static` is the trust-gated content reused by every
|
|
1446
|
+
// re-injection path — it stays non-null on non-full-mode turns so
|
|
1447
|
+
// that mid-turn reducer compaction (which strips the prior `<memory>`
|
|
1448
|
+
// block) can restore the freshest content. `memoryV2Static` is the
|
|
1449
|
+
// first-turn / post-compaction cadence-gated value for initial
|
|
1450
|
+
// injection only. `readMemoryV2StaticContent` self-gates on the v2
|
|
1451
|
+
// flag + config and returns null when v2 is off.
|
|
1452
|
+
const currentMemoryV2Static = personalMemoryAllowed
|
|
1438
1453
|
? readMemoryV2StaticContent()
|
|
1439
1454
|
: null;
|
|
1440
|
-
const memoryV2Static = currentMemoryV2Static;
|
|
1455
|
+
const memoryV2Static = shouldInjectNowAndPkb ? currentMemoryV2Static : null;
|
|
1441
1456
|
|
|
1442
1457
|
// PKB relevance-hint inputs. Resolved once per turn and reused across
|
|
1443
1458
|
// re-injections so post-compaction rebuilds pick up fresh hints against
|
|
@@ -1575,7 +1590,8 @@ export async function runAgentLoopImpl(
|
|
|
1575
1590
|
injection.blocks.pkbSystemReminder ||
|
|
1576
1591
|
injection.blocks.workspaceBlock ||
|
|
1577
1592
|
injection.blocks.nowScratchpadBlock ||
|
|
1578
|
-
injection.blocks.pkbContextBlock
|
|
1593
|
+
injection.blocks.pkbContextBlock ||
|
|
1594
|
+
injection.blocks.memoryV2StaticBlock
|
|
1579
1595
|
) {
|
|
1580
1596
|
try {
|
|
1581
1597
|
const metadataUpdates: Record<string, unknown> = {};
|
|
@@ -1597,6 +1613,10 @@ export async function runAgentLoopImpl(
|
|
|
1597
1613
|
if (injection.blocks.pkbContextBlock) {
|
|
1598
1614
|
metadataUpdates.pkbContextBlock = injection.blocks.pkbContextBlock;
|
|
1599
1615
|
}
|
|
1616
|
+
if (injection.blocks.memoryV2StaticBlock) {
|
|
1617
|
+
metadataUpdates.memoryV2StaticBlock =
|
|
1618
|
+
injection.blocks.memoryV2StaticBlock;
|
|
1619
|
+
}
|
|
1600
1620
|
await runPipeline<PersistArgs, PersistResult>(
|
|
1601
1621
|
"persistence",
|
|
1602
1622
|
getMiddlewaresFor("persistence"),
|
|
@@ -2240,6 +2260,83 @@ export async function runAgentLoopImpl(
|
|
|
2240
2260
|
}
|
|
2241
2261
|
}
|
|
2242
2262
|
|
|
2263
|
+
// ── Image-dimension overflow recovery ──────────────────────────
|
|
2264
|
+
// When the provider rejects because an image block exceeds its pixel
|
|
2265
|
+
// cap, strip every image block from ctx.messages and retry once.
|
|
2266
|
+
// optimizeImageForTransport already ran at upload time; if sips was
|
|
2267
|
+
// unavailable (non-macOS) it returns the same bytes unchanged. In
|
|
2268
|
+
// that case we swap the block for a text note so the model can tell
|
|
2269
|
+
// the user what happened instead of hard-failing with a red banner.
|
|
2270
|
+
if (state.imageTooLargeDetected) {
|
|
2271
|
+
state.imageTooLargeDetected = false;
|
|
2272
|
+
rlog.warn(
|
|
2273
|
+
{ phase: "image-recovery" },
|
|
2274
|
+
"Image too large — stripping oversized image blocks and retrying",
|
|
2275
|
+
);
|
|
2276
|
+
ctx.messages = ctx.messages.map((msg) => {
|
|
2277
|
+
if (!Array.isArray(msg.content)) return msg;
|
|
2278
|
+
if (!msg.content.some((b) => b.type === "image")) return msg;
|
|
2279
|
+
return {
|
|
2280
|
+
...msg,
|
|
2281
|
+
content: msg.content.flatMap((b): ContentBlock[] => {
|
|
2282
|
+
if (b.type !== "image") return [b];
|
|
2283
|
+
const resized = optimizeImageForTransport(
|
|
2284
|
+
b.source.data,
|
|
2285
|
+
b.source.media_type,
|
|
2286
|
+
);
|
|
2287
|
+
if (resized.data !== b.source.data) {
|
|
2288
|
+
// sips managed to downscale — use the smaller version
|
|
2289
|
+
return [
|
|
2290
|
+
{
|
|
2291
|
+
...b,
|
|
2292
|
+
source: {
|
|
2293
|
+
type: "base64" as const,
|
|
2294
|
+
media_type: resized.mediaType,
|
|
2295
|
+
data: resized.data,
|
|
2296
|
+
},
|
|
2297
|
+
},
|
|
2298
|
+
];
|
|
2299
|
+
}
|
|
2300
|
+
// Can't resize — replace with a text annotation so the model
|
|
2301
|
+
// can explain the situation rather than silently dropping context
|
|
2302
|
+
return [
|
|
2303
|
+
{
|
|
2304
|
+
type: "text" as const,
|
|
2305
|
+
text: "(An image was attached but could not be sent — its dimensions exceed the provider limit and automatic resize was not available. Please resize the image and try again.)",
|
|
2306
|
+
},
|
|
2307
|
+
];
|
|
2308
|
+
}),
|
|
2309
|
+
};
|
|
2310
|
+
});
|
|
2311
|
+
runMessages = ctx.messages;
|
|
2312
|
+
updatedHistory = await ctx.agentLoop.run(
|
|
2313
|
+
runMessages,
|
|
2314
|
+
eventHandler,
|
|
2315
|
+
abortController.signal,
|
|
2316
|
+
reqId,
|
|
2317
|
+
onCheckpoint,
|
|
2318
|
+
turnCallSite,
|
|
2319
|
+
loopTurnCtx,
|
|
2320
|
+
turnOverrideProfile,
|
|
2321
|
+
effectiveContextWindow.maxInputTokens,
|
|
2322
|
+
);
|
|
2323
|
+
if (state.imageTooLargeDetected) {
|
|
2324
|
+
rlog.error(
|
|
2325
|
+
{ phase: "image-recovery" },
|
|
2326
|
+
"Image-recovery retry also failed — surfacing error to user",
|
|
2327
|
+
);
|
|
2328
|
+
const classified = classifyConversationError(
|
|
2329
|
+
new Error("Image dimensions too large"),
|
|
2330
|
+
{ phase: "agent_loop" },
|
|
2331
|
+
);
|
|
2332
|
+
deps.onEvent(
|
|
2333
|
+
buildConversationErrorMessage(deps.ctx.conversationId, classified),
|
|
2334
|
+
);
|
|
2335
|
+
state.providerErrorUserMessage = classified.userMessage;
|
|
2336
|
+
state.imageTooLargeDetected = false;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2243
2340
|
// ── Bounded context overflow convergence loop ──────────────────
|
|
2244
2341
|
// When the provider rejects with context-too-large, iterate through
|
|
2245
2342
|
// reducer tiers (forced compaction, tool-result truncation, media
|
|
@@ -2834,6 +2931,7 @@ export async function runAgentLoopImpl(
|
|
|
2834
2931
|
ctx.lastAssistantAttachments = assistantAttachments;
|
|
2835
2932
|
ctx.lastAttachmentWarnings = attachmentResult.directiveWarnings;
|
|
2836
2933
|
syncLastAssistantMessageToDisk();
|
|
2934
|
+
const clientDisplayMessageId = getClientDisplayMessageId(state);
|
|
2837
2935
|
|
|
2838
2936
|
// Re-check: the user may have cancelled during attachment resolution
|
|
2839
2937
|
if (abortController.signal.aborted) {
|
|
@@ -2874,6 +2972,9 @@ export async function runAgentLoopImpl(
|
|
|
2874
2972
|
...(state.lastAssistantMessageId
|
|
2875
2973
|
? { messageId: state.lastAssistantMessageId }
|
|
2876
2974
|
: {}),
|
|
2975
|
+
...(clientDisplayMessageId
|
|
2976
|
+
? { displayMessageId: clientDisplayMessageId }
|
|
2977
|
+
: {}),
|
|
2877
2978
|
});
|
|
2878
2979
|
} else {
|
|
2879
2980
|
ctx.emitActivityState("idle", "message_complete", "global", reqId);
|
|
@@ -2897,86 +2998,11 @@ export async function runAgentLoopImpl(
|
|
|
2897
2998
|
...(state.lastAssistantMessageId
|
|
2898
2999
|
? { messageId: state.lastAssistantMessageId }
|
|
2899
3000
|
: {}),
|
|
3001
|
+
...(clientDisplayMessageId
|
|
3002
|
+
? { displayMessageId: clientDisplayMessageId }
|
|
3003
|
+
: {}),
|
|
2900
3004
|
});
|
|
2901
3005
|
|
|
2902
|
-
// Emit a home-feed event for background/scheduled conversation completions.
|
|
2903
|
-
// Scoped to message_complete only (not cancelled/handoff), wrapped in
|
|
2904
|
-
// try-catch so malformed message content can never propagate errors.
|
|
2905
|
-
try {
|
|
2906
|
-
const conv = getConversation(ctx.conversationId);
|
|
2907
|
-
if (
|
|
2908
|
-
conv &&
|
|
2909
|
-
(conv.conversationType === "background" ||
|
|
2910
|
-
conv.conversationType === "scheduled")
|
|
2911
|
-
) {
|
|
2912
|
-
const lastMsg = state.lastAssistantMessageId
|
|
2913
|
-
? getMessageById(state.lastAssistantMessageId, ctx.conversationId)
|
|
2914
|
-
: undefined;
|
|
2915
|
-
let summary: string;
|
|
2916
|
-
if (lastMsg) {
|
|
2917
|
-
const parsed: unknown = JSON.parse(lastMsg.content);
|
|
2918
|
-
if (typeof parsed === "string") {
|
|
2919
|
-
summary = parsed.slice(0, 200);
|
|
2920
|
-
} else if (Array.isArray(parsed)) {
|
|
2921
|
-
const textBlock = parsed.find(
|
|
2922
|
-
(b: { type?: string }) => b.type === "text",
|
|
2923
|
-
);
|
|
2924
|
-
summary =
|
|
2925
|
-
typeof textBlock?.text === "string"
|
|
2926
|
-
? textBlock.text.slice(0, 200)
|
|
2927
|
-
: (conv.title ?? "Background task completed.");
|
|
2928
|
-
} else {
|
|
2929
|
-
summary = conv.title ?? "Background task completed.";
|
|
2930
|
-
}
|
|
2931
|
-
} else {
|
|
2932
|
-
summary = conv.title ?? "Background task completed.";
|
|
2933
|
-
}
|
|
2934
|
-
const feedTitle =
|
|
2935
|
-
conv.title && !isReplaceableTitle(conv.title)
|
|
2936
|
-
? conv.title
|
|
2937
|
-
: "Background task";
|
|
2938
|
-
const dedupKey = `bg-conv:${ctx.conversationId}`;
|
|
2939
|
-
void emitFeedEvent({
|
|
2940
|
-
source: "assistant",
|
|
2941
|
-
title: feedTitle,
|
|
2942
|
-
summary,
|
|
2943
|
-
dedupKey,
|
|
2944
|
-
conversationId: ctx.conversationId,
|
|
2945
|
-
}).catch((err) => {
|
|
2946
|
-
log.warn(
|
|
2947
|
-
{ err, conversationId: ctx.conversationId },
|
|
2948
|
-
"Failed to emit background conversation feed event",
|
|
2949
|
-
);
|
|
2950
|
-
});
|
|
2951
|
-
|
|
2952
|
-
if (isReplaceableTitle(conv.title ?? null)) {
|
|
2953
|
-
void rewriteFeedTitle(feedTitle)
|
|
2954
|
-
.then((prose) => {
|
|
2955
|
-
if (prose && prose !== feedTitle) {
|
|
2956
|
-
return emitFeedEvent({
|
|
2957
|
-
source: "assistant",
|
|
2958
|
-
title: prose,
|
|
2959
|
-
summary,
|
|
2960
|
-
dedupKey,
|
|
2961
|
-
conversationId: ctx.conversationId,
|
|
2962
|
-
});
|
|
2963
|
-
}
|
|
2964
|
-
})
|
|
2965
|
-
.catch((err) => {
|
|
2966
|
-
log.warn(
|
|
2967
|
-
{ err, conversationId: ctx.conversationId },
|
|
2968
|
-
"Failed to update feed event with prose title rewrite",
|
|
2969
|
-
);
|
|
2970
|
-
});
|
|
2971
|
-
}
|
|
2972
|
-
}
|
|
2973
|
-
} catch (feedErr) {
|
|
2974
|
-
log.warn(
|
|
2975
|
-
{ err: feedErr, conversationId: ctx.conversationId },
|
|
2976
|
-
"Failed to build home-feed event for background conversation",
|
|
2977
|
-
);
|
|
2978
|
-
}
|
|
2979
|
-
|
|
2980
3006
|
// Proactive artifact: fire once when the processed turn was the 4th user message.
|
|
2981
3007
|
// Only trigger for real user-authored turns (not subagent/system messages).
|
|
2982
3008
|
{
|
|
@@ -3274,6 +3300,10 @@ export async function applyCompactionResult(
|
|
|
3274
3300
|
ctx.conversationId,
|
|
3275
3301
|
ctx.trustContext?.trustClass,
|
|
3276
3302
|
);
|
|
3303
|
+
enqueueMemoryRetrospectiveOnCompaction(
|
|
3304
|
+
ctx.conversationId,
|
|
3305
|
+
ctx.trustContext?.trustClass,
|
|
3306
|
+
);
|
|
3277
3307
|
const summarySignals = computeSummaryQualitySignals(result.summaryText);
|
|
3278
3308
|
onEvent({
|
|
3279
3309
|
type: "context_compacted",
|
|
@@ -120,6 +120,13 @@ const STREAMING_ERROR_PATTERNS = [
|
|
|
120
120
|
];
|
|
121
121
|
|
|
122
122
|
// User-initiated cancellation patterns — these should NOT produce conversation_error
|
|
123
|
+
// Image-input validation patterns — Anthropic 400s with this message when an image
|
|
124
|
+
// block exceeds the per-side pixel cap. Distinct classification matters because
|
|
125
|
+
// retrying with the same oversized image is futile; the user needs to resize.
|
|
126
|
+
const IMAGE_DIMENSIONS_TOO_LARGE_PATTERNS = [
|
|
127
|
+
/image dimensions? exceeds? max allowed size/i,
|
|
128
|
+
];
|
|
129
|
+
|
|
123
130
|
const CANCEL_PATTERNS = [/abort/i, /cancel/i];
|
|
124
131
|
|
|
125
132
|
/**
|
|
@@ -370,6 +377,15 @@ function classifyCore(
|
|
|
370
377
|
errorCategory: "provider_not_configured",
|
|
371
378
|
};
|
|
372
379
|
}
|
|
380
|
+
if (isImageDimensionsTooLarge(message)) {
|
|
381
|
+
return {
|
|
382
|
+
code: "IMAGE_TOO_LARGE",
|
|
383
|
+
userMessage:
|
|
384
|
+
"An attached image is too large for the AI provider — image dimensions must be under 8000 pixels per side. Resize the image and try again.",
|
|
385
|
+
retryable: false,
|
|
386
|
+
errorCategory: "image_dimensions_too_large",
|
|
387
|
+
};
|
|
388
|
+
}
|
|
373
389
|
return {
|
|
374
390
|
code: "PROVIDER_API",
|
|
375
391
|
userMessage: "The AI provider rejected the request.",
|
|
@@ -388,6 +404,11 @@ export function isContextTooLarge(message: string): boolean {
|
|
|
388
404
|
return CONTEXT_TOO_LARGE_PATTERNS.some((p) => p.test(message));
|
|
389
405
|
}
|
|
390
406
|
|
|
407
|
+
/** Check whether an error message indicates an image-input dimension failure. */
|
|
408
|
+
function isImageDimensionsTooLarge(message: string): boolean {
|
|
409
|
+
return IMAGE_DIMENSIONS_TOO_LARGE_PATTERNS.some((p) => p.test(message));
|
|
410
|
+
}
|
|
411
|
+
|
|
391
412
|
/** Check whether an error message indicates a web-search-specific ordering failure. */
|
|
392
413
|
function isWebSearchOrderingError(message: string): boolean {
|
|
393
414
|
return WEB_SEARCH_ORDERING_PATTERNS.some((p) => p.test(message));
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
type MessageRow,
|
|
18
18
|
} from "../memory/conversation-crud.js";
|
|
19
19
|
import { enqueueMemoryJob } from "../memory/jobs-store.js";
|
|
20
|
+
import { enqueueMemoryRetrospectiveIfEnabled } from "../memory/memory-retrospective-enqueue.js";
|
|
20
21
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
21
22
|
import type { SecretPrompter } from "../permissions/secret-prompter.js";
|
|
22
23
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
@@ -183,6 +184,7 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
183
184
|
ctx.contextCompactedAt = conv?.contextCompactedAt ?? null;
|
|
184
185
|
}
|
|
185
186
|
|
|
187
|
+
const personalMemoryAllowed = !isUntrustedTrustClass(trustClass);
|
|
186
188
|
const parsedMessages: Message[] = dbMessages
|
|
187
189
|
.slice(ctx.contextCompactedMessageCount)
|
|
188
190
|
.map((m, index, arr) => {
|
|
@@ -215,7 +217,8 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
215
217
|
// shape right-to-left, since each prepend shifts previously-
|
|
216
218
|
// prepended blocks one slot right:
|
|
217
219
|
// [<workspace>, <turn_context>, <NOW.md>, <memory __injected>,
|
|
218
|
-
// <system_reminder>, <knowledge_base>,
|
|
220
|
+
// <memory>\n…</memory>, <system_reminder>, <knowledge_base>,
|
|
221
|
+
// ...original]
|
|
219
222
|
//
|
|
220
223
|
// Persisted non-tail rows rehydrate the full set so Anthropic's
|
|
221
224
|
// prefix cache keeps matching msg[0] across daemon restarts and
|
|
@@ -238,15 +241,37 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
238
241
|
];
|
|
239
242
|
}
|
|
240
243
|
|
|
244
|
+
// The v2 static memory block (essentials/threads/recent/buffer
|
|
245
|
+
// wrapped in `<memory>…</memory>`) carries personal user memory.
|
|
246
|
+
// Trust-gated to mirror `shouldExposePersonalMemory` at injection
|
|
247
|
+
// time — untrusted-actor views must not read persisted personal
|
|
248
|
+
// memory back through metadata. Skipped on the tail row because
|
|
249
|
+
// the next turn re-injects fresh content on full-mode turns.
|
|
250
|
+
if (
|
|
251
|
+
!isTail &&
|
|
252
|
+
personalMemoryAllowed &&
|
|
253
|
+
typeof meta.memoryV2StaticBlock === "string"
|
|
254
|
+
) {
|
|
255
|
+
content = [
|
|
256
|
+
{ type: "text" as const, text: meta.memoryV2StaticBlock },
|
|
257
|
+
...content,
|
|
258
|
+
];
|
|
259
|
+
}
|
|
260
|
+
|
|
241
261
|
// Memory remains rehydrated on all rows (existing behavior).
|
|
242
262
|
// Strip any pre-existing wrapper before re-wrapping so historical
|
|
243
263
|
// rows persisted with the wrapper (v2 path before the
|
|
244
264
|
// injectedBlockText contract was unified with v1's unwrapped form)
|
|
245
|
-
// don't render double-wrapped after rehydrate.
|
|
265
|
+
// don't render double-wrapped after rehydrate. Only unwrap when
|
|
266
|
+
// the full <memory>...</memory> pair is present so we don't mutate
|
|
267
|
+
// legitimate unwrapped payloads that happen to start with
|
|
268
|
+
// "<memory>\n" or end with "\n</memory>".
|
|
246
269
|
if (typeof meta.memoryInjectedBlock === "string") {
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
.
|
|
270
|
+
const block = meta.memoryInjectedBlock;
|
|
271
|
+
const inner =
|
|
272
|
+
block.startsWith("<memory>\n") && block.endsWith("\n</memory>")
|
|
273
|
+
? block.slice("<memory>\n".length, -"\n</memory>".length)
|
|
274
|
+
: block;
|
|
250
275
|
content = [
|
|
251
276
|
{
|
|
252
277
|
type: "text" as const,
|
|
@@ -411,6 +436,22 @@ export function disposeConversation(ctx: DisposeContext): void {
|
|
|
411
436
|
} catch {
|
|
412
437
|
// Best-effort — don't block conversation disposal
|
|
413
438
|
}
|
|
439
|
+
|
|
440
|
+
try {
|
|
441
|
+
// Memory-retrospective lifecycle safety-net. The periodic triggers
|
|
442
|
+
// (interval / message_count / pre-compaction) handle the common
|
|
443
|
+
// path; lifecycle catches the gap between the last interval fire
|
|
444
|
+
// and conversation eviction. The job's `no_new_messages` early
|
|
445
|
+
// return makes this a cheap no-op when the periodic path already
|
|
446
|
+
// covered things. `enqueueMemoryRetrospectiveIfEnabled` has its
|
|
447
|
+
// own internal recursion guard.
|
|
448
|
+
enqueueMemoryRetrospectiveIfEnabled({
|
|
449
|
+
conversationId: ctx.conversationId,
|
|
450
|
+
trigger: "lifecycle",
|
|
451
|
+
});
|
|
452
|
+
} catch {
|
|
453
|
+
// Best-effort — don't block conversation disposal
|
|
454
|
+
}
|
|
414
455
|
}
|
|
415
456
|
|
|
416
457
|
abortConversation(
|