@vellumai/assistant 0.8.5 → 0.8.6
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 +33 -1
- package/ARCHITECTURE.md +1 -1
- package/bunfig.toml +6 -1
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +4 -3
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
- package/openapi.yaml +1900 -166
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +3 -2
- package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
- package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/annotate-risk-options.test.ts +1 -0
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +9 -13
- package/src/__tests__/assert-not-live-db.ts +79 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +9 -25
- package/src/__tests__/audit-log-rotation.test.ts +2 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- package/src/__tests__/background-workers-disk-pressure.test.ts +5 -8
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +3 -2
- package/src/__tests__/call-controller.test.ts +3 -2
- package/src/__tests__/channel-approval-routes.test.ts +3 -2
- package/src/__tests__/channel-guardian.test.ts +3 -2
- package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
- package/src/__tests__/channel-reply-delivery.test.ts +35 -0
- package/src/__tests__/channel-retry-sweep.test.ts +320 -3
- package/src/__tests__/checker.test.ts +12 -12
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compaction-trail-store.test.ts +264 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
- package/src/__tests__/computer-use-tools.test.ts +12 -14
- package/src/__tests__/config-loader-backfill.test.ts +13 -28
- package/src/__tests__/config-loader-corrupt.test.ts +5 -5
- package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
- package/src/__tests__/config-schema.test.ts +10 -10
- package/src/__tests__/connection-model-compat.test.ts +83 -0
- package/src/__tests__/contacts-tools.test.ts +3 -2
- package/src/__tests__/context-token-estimator.test.ts +22 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +34 -0
- package/src/__tests__/conversation-agent-loop.test.ts +488 -2
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
- package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-attention-store.test.ts +101 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-error.test.ts +30 -0
- package/src/__tests__/conversation-fork-crud.test.ts +69 -8
- package/src/__tests__/conversation-fork-route.test.ts +3 -2
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
- package/src/__tests__/conversation-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -0
- package/src/__tests__/conversation-pairing.test.ts +53 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -0
- package/src/__tests__/conversation-queue.test.ts +333 -291
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -18
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
- package/src/__tests__/conversation-routes-slash-commands.test.ts +33 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
- package/src/__tests__/conversation-skill-tools.test.ts +38 -142
- package/src/__tests__/conversation-slash-queue.test.ts +84 -32
- package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
- package/src/__tests__/conversation-sync-tags.test.ts +128 -12
- package/src/__tests__/conversation-title-service.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
- package/src/__tests__/conversation-usage.test.ts +1 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
- package/src/__tests__/credential-broker-server-use.test.ts +5 -5
- package/src/__tests__/credential-execution-client.test.ts +72 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -5
- package/src/__tests__/credential-vault-unit.test.ts +19 -19
- package/src/__tests__/credential-vault.test.ts +5 -5
- package/src/__tests__/cross-provider-web-search.test.ts +56 -2
- package/src/__tests__/db-connection-isolation.test.ts +7 -6
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
- package/src/__tests__/db-test-helpers.ts +58 -0
- package/src/__tests__/disk-pressure-guard.test.ts +58 -41
- package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
- package/src/__tests__/disk-pressure-routes.test.ts +0 -33
- package/src/__tests__/disk-pressure-tools.test.ts +0 -4
- package/src/__tests__/dm-persistence.test.ts +26 -40
- package/src/__tests__/document-create-dedupe.test.ts +189 -0
- package/src/__tests__/document-find-replace.test.ts +3 -2
- package/src/__tests__/document-tool-security.test.ts +81 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
- package/src/__tests__/encrypted-store.test.ts +11 -9
- package/src/__tests__/feature-flag-test-helpers.ts +53 -0
- package/src/__tests__/filing-service.test.ts +1 -0
- package/src/__tests__/first-greeting.test.ts +62 -12
- package/src/__tests__/gateway-flag-listener.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +26 -0
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-outbound-http.test.ts +3 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/mock-logger.ts +26 -0
- package/src/__tests__/host-bash-routes.test.ts +1 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-shell-tool.test.ts +5 -4
- package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +29 -7
- package/src/__tests__/identity-intro-cache.test.ts +133 -22
- package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
- package/src/__tests__/inference-profile-reaper.test.ts +3 -2
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
- package/src/__tests__/injector-disk-pressure.test.ts +3 -17
- package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
- package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
- package/src/__tests__/llm-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-resolver.test.ts +331 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +14 -0
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- package/src/__tests__/messaging-send-tool.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +18 -2
- package/src/__tests__/model-intents.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +30 -2
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/oauth-commands-routes.test.ts +37 -0
- package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
- package/src/__tests__/oauth-store.test.ts +3 -2
- package/src/__tests__/onboarding-template-contract.test.ts +3 -2
- package/src/__tests__/openai-provider.test.ts +8 -9
- package/src/__tests__/openai-responses-provider.test.ts +70 -10
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
- package/src/__tests__/persistence-pipeline.test.ts +139 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
- package/src/__tests__/plugin-bootstrap.test.ts +9 -11
- package/src/__tests__/plugin-tool-contribution.test.ts +41 -38
- package/src/__tests__/process-message-background-slack.test.ts +21 -16
- package/src/__tests__/process-message-display-content.test.ts +19 -22
- package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
- package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
- package/src/__tests__/provider-registry-ollama.test.ts +45 -22
- package/src/__tests__/recording-handler.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +82 -76
- package/src/__tests__/relay-server.test.ts +10 -10
- package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
- package/src/__tests__/schedule-store.test.ts +16 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
- package/src/__tests__/secret-ingress-http.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +3 -3
- package/src/__tests__/send-endpoint-busy.test.ts +81 -42
- package/src/__tests__/server-history-render.test.ts +4 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
- package/src/__tests__/skill-feature-flags.test.ts +14 -16
- package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
- package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
- package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
- package/src/__tests__/skill-tool-factory.test.ts +96 -95
- package/src/__tests__/slack-channel-config.test.ts +3 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
- package/src/__tests__/subagent-disposal.test.ts +27 -8
- package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
- package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
- package/src/__tests__/subagent-manager-notify.test.ts +20 -8
- package/src/__tests__/subagent-notify-parent.test.ts +5 -4
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
- package/src/__tests__/subagent-tools.test.ts +2 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/system-prompt.test.ts +38 -0
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +20 -7
- package/src/__tests__/tool-executor.test.ts +55 -10
- package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/twilio-routes.test.ts +3 -2
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
- package/src/__tests__/voice-session-bridge.test.ts +37 -28
- package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
- package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
- package/src/acp/session-manager.ts +5 -6
- package/src/agent/loop.ts +80 -0
- package/src/api/README.md +124 -2
- package/src/api/constants/call-sites.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +51 -0
- package/src/api/events/assistant-text-delta.ts +32 -0
- package/src/api/events/assistant-turn-start.ts +33 -0
- package/src/api/events/document-comment-created.ts +48 -0
- package/src/api/events/document-comment-deleted.ts +24 -0
- package/src/api/events/document-comment-reopened.ts +25 -0
- package/src/api/events/document-comment-resolved.ts +27 -0
- package/src/api/events/generation-cancelled.ts +24 -0
- package/src/api/events/generation-handoff.ts +41 -0
- package/src/api/events/message-complete.ts +42 -0
- package/src/api/events/open-url.ts +30 -0
- package/src/{events → api/events}/relationship-state-updated.ts +3 -3
- package/src/api/events/tool-use-start.ts +32 -0
- package/src/api/index.ts +128 -3
- package/src/api/responses/llm-context-response.ts +39 -0
- package/src/api/responses/llm-request-log-entry.ts +93 -0
- package/src/api/responses/memory-recall-log.ts +65 -0
- package/src/api/responses/memory-v2-activation-log.ts +78 -0
- package/src/background-wake/background-wake-routes.test.ts +687 -52
- package/src/background-wake/platform-client.test.ts +308 -0
- package/src/background-wake/platform-client.ts +167 -0
- package/src/background-wake/publisher.ts +91 -0
- package/src/background-wake/runtime-registry.ts +2 -2
- package/src/background-wake/wake-intent-hooks.test.ts +282 -0
- package/src/calls/guardian-dispatch.ts +1 -0
- package/src/calls/voice-session-bridge.ts +4 -4
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- package/src/cli/commands/memory-v3-render.ts +147 -0
- package/src/cli/commands/memory-v3.ts +255 -4
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +23 -42
- package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
- package/src/config/call-site-defaults.ts +1 -1
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-context-resolution.ts +10 -1
- package/src/config/llm-resolver.ts +121 -15
- package/src/config/loader.ts +4 -5
- package/src/config/schemas/__tests__/memory-v2.test.ts +15 -0
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +90 -1
- package/src/config/schemas/memory-v2.ts +26 -0
- package/src/config/schemas/services.ts +6 -2
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/token-estimator.ts +10 -5
- package/src/credential-execution/executable-discovery.ts +40 -0
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +125 -40
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +389 -68
- package/src/daemon/conversation-agent-loop.ts +132 -28
- package/src/daemon/conversation-error.ts +33 -5
- package/src/daemon/conversation-messaging.ts +84 -43
- package/src/daemon/conversation-process.ts +74 -37
- package/src/daemon/conversation-runtime-assembly.ts +29 -9
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-surfaces.ts +69 -34
- package/src/daemon/conversation-tool-setup.ts +33 -48
- package/src/daemon/conversation.ts +26 -46
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +9 -2
- package/src/daemon/disk-pressure-guard.ts +27 -29
- package/src/daemon/first-greeting.ts +31 -13
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/lifecycle.ts +12 -12
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +10 -17
- package/src/daemon/message-types/conversations.ts +20 -22
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/home.ts +2 -2
- package/src/daemon/message-types/integrations.ts +2 -7
- package/src/daemon/message-types/messages.ts +23 -38
- package/src/daemon/message-types/subagents.ts +6 -0
- package/src/daemon/process-message.ts +9 -9
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +16 -0
- package/src/daemon/switch-inference-profile-tool.ts +13 -3
- package/src/daemon/tool-setup-types.ts +0 -6
- package/src/daemon/wake-target-adapter.ts +10 -0
- package/src/documents/document-store.ts +38 -0
- package/src/export/__tests__/transcript-formatter.test.ts +1 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -0
- package/src/heartbeat/heartbeat-service.ts +63 -0
- package/src/home/__tests__/feed-writer.test.ts +161 -0
- package/src/home/__tests__/post-connect-feed.test.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +55 -59
- package/src/home/feed-writer.ts +146 -7
- package/src/home/suggested-prompts.ts +27 -145
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/gateway-client.test.ts +4 -1
- package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
- package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
- package/src/ipc/skill-routes/memory.ts +4 -3
- package/src/ipc/skill-routes/registries.ts +28 -29
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +1 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
- package/src/memory/conversation-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +352 -112
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +4 -0
- package/src/memory/db-singleton.ts +77 -0
- package/src/memory/delivery-channels.ts +82 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
- package/src/memory/graph/retriever.test.ts +3 -3
- package/src/memory/job-handlers/embedding.test.ts +3 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
- package/src/memory/jobs-worker.ts +12 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +80 -0
- package/src/memory/llm-request-log-source-local.ts +24 -0
- package/src/memory/llm-request-log-source.ts +31 -0
- package/src/memory/llm-request-log-store.ts +188 -3
- package/src/memory/memory-v2-activation-log-store.ts +95 -1
- package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
- package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/schema/conversations.ts +9 -1
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
- package/src/memory/v2/__tests__/harness-runner.test.ts +26 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
- package/src/memory/v2/harness/metrics.ts +5 -1
- package/src/memory/v2/harness/replay-input.ts +19 -3
- package/src/memory/v2/harness/runner.ts +6 -0
- package/src/memory/v2/harness/trace.ts +6 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +2 -4
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
- package/src/memory/v3/__tests__/edges.test.ts +144 -1
- package/src/memory/v3/__tests__/filter.test.ts +48 -0
- package/src/memory/v3/__tests__/gate.test.ts +96 -33
- package/src/memory/v3/__tests__/index-composition.test.ts +58 -0
- package/src/memory/v3/__tests__/loop.test.ts +250 -5
- package/src/memory/v3/__tests__/scouts.test.ts +49 -0
- package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +88 -2
- package/src/memory/v3/__tests__/traversal.test.ts +39 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +77 -0
- package/src/memory/v3/__tests__/validate.test.ts +32 -0
- package/src/memory/v3/coretrieval-seed.ts +240 -0
- package/src/memory/v3/edges.ts +58 -21
- package/src/memory/v3/filter.ts +27 -22
- package/src/memory/v3/gate.ts +51 -36
- package/src/memory/v3/index-composition.ts +18 -5
- package/src/memory/v3/loop.ts +65 -17
- package/src/memory/v3/scouts.ts +15 -4
- package/src/memory/v3/shadow-diff.ts +287 -0
- package/src/memory/v3/shadow-middleware.ts +44 -2
- package/src/memory/v3/traversal.ts +6 -1
- package/src/memory/v3/tree-walk.ts +6 -1
- package/src/memory/v3/validate.ts +56 -33
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
- package/src/notifications/adapters/slack.ts +45 -11
- package/src/notifications/broadcaster.ts +114 -63
- package/src/notifications/conversation-pairing.ts +23 -3
- package/src/notifications/decisions-store.ts +32 -1
- package/src/notifications/deliveries-store.ts +45 -0
- package/src/notifications/edit-notification.ts +201 -0
- package/src/notifications/emit-signal.ts +11 -1
- package/src/notifications/signal.ts +10 -0
- package/src/notifications/types.ts +37 -0
- package/src/oauth/byo-connection.test.ts +67 -3
- package/src/oauth/byo-connection.ts +32 -5
- package/src/oauth/connect-orchestrator.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +76 -0
- package/src/oauth/connection-resolver.ts +49 -10
- package/src/oauth/manual-token-connection.ts +51 -3
- package/src/oauth/seed-providers.ts +3 -0
- package/src/permissions/approval-policy.test.ts +19 -5
- package/src/permissions/approval-policy.ts +14 -3
- package/src/permissions/checker.ts +21 -8
- package/src/platform/client.test.ts +24 -1
- package/src/platform/client.ts +8 -0
- package/src/platform/feature-gate.ts +15 -0
- package/src/plugins/defaults/injectors.ts +2 -8
- package/src/plugins/defaults/persistence.ts +25 -6
- package/src/plugins/types.ts +57 -13
- package/src/proactive-artifact/job.test.ts +1 -0
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/system-prompt.ts +38 -40
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP.md +7 -11
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
- package/src/providers/call-site-routing.ts +33 -9
- package/src/providers/connection-model-compat.ts +23 -0
- package/src/providers/connection-resolution.ts +39 -20
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +24 -3
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
- package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
- package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
- package/src/providers/inference/auth.ts +0 -8
- package/src/providers/inference/connections.ts +3 -66
- package/src/providers/inference/resolve-auth.ts +2 -3
- package/src/providers/model-catalog.ts +35 -1
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
- package/src/providers/openai/chat-completions-provider.ts +110 -12
- package/src/providers/openai/codex-models.ts +2 -0
- package/src/providers/openai/responses-provider.ts +53 -53
- package/src/providers/openrouter/client.ts +13 -8
- package/src/providers/provider-send-message.ts +18 -9
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +16 -4
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/types.ts +9 -0
- package/src/runtime/__tests__/agent-wake.test.ts +1 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
- package/src/runtime/access-request-helper.ts +1 -0
- package/src/runtime/auth/route-policy.ts +10 -0
- package/src/runtime/channel-readiness-service.ts +68 -0
- package/src/runtime/channel-reply-delivery.ts +23 -0
- package/src/runtime/channel-retry-sweep.ts +47 -14
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/migrations/vbundle-builder.ts +3 -2
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +51 -3
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
- package/src/runtime/routes/acp-routes-list.test.ts +3 -0
- package/src/runtime/routes/app-management-routes.ts +111 -4
- package/src/runtime/routes/background-wake-routes.ts +188 -20
- package/src/runtime/routes/btw-routes.ts +4 -4
- package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
- package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
- package/src/runtime/routes/conversation-list-routes.ts +147 -0
- package/src/runtime/routes/conversation-management-routes.ts +39 -14
- package/src/runtime/routes/conversation-query-routes.ts +60 -10
- package/src/runtime/routes/conversation-routes.ts +186 -140
- package/src/runtime/routes/conversations-import-routes.ts +19 -6
- package/src/runtime/routes/documents-routes.ts +10 -1
- package/src/runtime/routes/group-routes.ts +11 -0
- package/src/runtime/routes/home-feed-routes.ts +129 -0
- package/src/runtime/routes/identity-intro-cache.ts +61 -16
- package/src/runtime/routes/identity-routes.ts +30 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
- package/src/runtime/routes/integrations/vercel.ts +15 -0
- package/src/runtime/routes/llm-context-normalization.ts +7 -2
- package/src/runtime/routes/memory-v3-routes.ts +160 -2
- package/src/runtime/routes/migration-routes.ts +20 -13
- package/src/runtime/routes/notification-routes.ts +63 -1
- package/src/runtime/routes/oauth-commands-routes.ts +6 -1
- package/src/runtime/routes/surface-action-routes.ts +1 -38
- package/src/runtime/routes/surface-content-routes.ts +12 -5
- package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
- package/src/runtime/slack-dm-text-delivery.ts +177 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -1
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/schedule/schedule-store.ts +8 -1
- package/src/schedule/scheduler.ts +111 -15
- package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
- package/src/security/encrypted-store.ts +7 -16
- package/src/security/store-path-override.ts +61 -0
- package/src/signals/user-message.ts +5 -8
- package/src/skills/validate-input.ts +177 -0
- package/src/subagent/manager.ts +13 -13
- package/src/subagent/types.ts +6 -0
- package/src/tasks/tool-sanitizer.ts +2 -2
- package/src/tools/apps/definitions.ts +35 -21
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/computer-use/definitions.ts +268 -266
- package/src/tools/document/document-tool.ts +131 -8
- package/src/tools/execution-target.ts +2 -5
- package/src/tools/executor.ts +18 -55
- package/src/tools/host-filesystem/edit.test.ts +1 -0
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/mcp/mcp-tool-factory.ts +0 -2
- package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
- package/src/tools/network/__tests__/web-search.test.ts +211 -3
- package/src/tools/network/managed-search-proxy.ts +183 -0
- package/src/tools/network/web-search.ts +199 -44
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +146 -103
- package/src/tools/schedule/create.ts +1 -1
- package/src/tools/skills/skill-tool-factory.ts +17 -36
- package/src/tools/subagent/spawn.ts +3 -0
- package/src/tools/tool-approval-handler.ts +10 -4
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +17 -15
- package/src/tools/ui-surface/definitions.ts +98 -86
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/util/browser.ts +7 -2
- package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
- package/src/workspace/migrations/registry.ts +4 -0
|
@@ -6,12 +6,15 @@ import { Database } from "bun:sqlite";
|
|
|
6
6
|
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
7
7
|
|
|
8
8
|
import { ensureDataDir, getDbPath } from "../util/platform.js";
|
|
9
|
+
import {
|
|
10
|
+
clearStoredDb,
|
|
11
|
+
getStoredDb,
|
|
12
|
+
setStoredDb,
|
|
13
|
+
} from "./db-singleton.js";
|
|
9
14
|
import * as schema from "./schema.js";
|
|
10
15
|
|
|
11
16
|
export type DrizzleDb = ReturnType<typeof drizzle<typeof schema>>;
|
|
12
17
|
|
|
13
|
-
let db: DrizzleDb | null = null;
|
|
14
|
-
|
|
15
18
|
function canonicalizePathThroughExistingParent(path: string): string {
|
|
16
19
|
const resolvedPath = resolve(path);
|
|
17
20
|
const pendingSegments: string[] = [];
|
|
@@ -71,18 +74,20 @@ function assertTestDbIsIsolated(): void {
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
export function getDb(): DrizzleDb {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
77
|
+
const existing = getStoredDb<DrizzleDb>();
|
|
78
|
+
if (existing) return existing;
|
|
79
|
+
|
|
80
|
+
assertTestDbIsIsolated();
|
|
81
|
+
ensureDataDir();
|
|
82
|
+
const sqlite = new Database(getDbPath());
|
|
83
|
+
sqlite.exec("PRAGMA journal_mode=WAL");
|
|
84
|
+
sqlite.exec("PRAGMA synchronous=FULL");
|
|
85
|
+
sqlite.exec("PRAGMA busy_timeout=5000");
|
|
86
|
+
sqlite.exec("PRAGMA foreign_keys = ON");
|
|
87
|
+
sqlite.exec("PRAGMA cache_size=-256000");
|
|
88
|
+
sqlite.exec("PRAGMA temp_store=MEMORY");
|
|
89
|
+
const db = drizzle(sqlite, { schema });
|
|
90
|
+
setStoredDb(db, () => sqlite.close());
|
|
86
91
|
return db;
|
|
87
92
|
}
|
|
88
93
|
|
|
@@ -107,10 +112,15 @@ export function getSqliteFrom(drizzleDb: DrizzleDb): Database {
|
|
|
107
112
|
return (drizzleDb as unknown as { $client: Database }).$client;
|
|
108
113
|
}
|
|
109
114
|
|
|
110
|
-
/**
|
|
115
|
+
/**
|
|
116
|
+
* Reset the db singleton. Used by production callers that need to close
|
|
117
|
+
* the live connection so the file can be replaced (post-migration,
|
|
118
|
+
* post-restore, post-vbundle-import) and on graceful shutdown.
|
|
119
|
+
*
|
|
120
|
+
* Tests should use `resetDbForTesting()` from
|
|
121
|
+
* `__tests__/db-test-helpers.ts` instead so they don't depend on this
|
|
122
|
+
* module's heavy import chain (`drizzle-orm/bun-sqlite`).
|
|
123
|
+
*/
|
|
111
124
|
export function resetDb(): void {
|
|
112
|
-
|
|
113
|
-
getSqliteFrom(db).close();
|
|
114
|
-
db = null;
|
|
115
|
-
}
|
|
125
|
+
clearStoredDb();
|
|
116
126
|
}
|
package/src/memory/db-init.ts
CHANGED
|
@@ -96,6 +96,7 @@ import {
|
|
|
96
96
|
migrateDropMemoryItemsTables,
|
|
97
97
|
migrateDropMemorySegmentFts,
|
|
98
98
|
migrateDropOrphanedMediaTables,
|
|
99
|
+
migrateDropProviderConnectionStatus,
|
|
99
100
|
migrateDropRemindersTable,
|
|
100
101
|
migrateDropSetupSkillIdColumn,
|
|
101
102
|
migrateDropSimplifiedMemory,
|
|
@@ -133,6 +134,7 @@ import {
|
|
|
133
134
|
migrateMemoryV3AutoEdges,
|
|
134
135
|
migrateMemoryV3Coactivation,
|
|
135
136
|
migrateMessageBookmarks,
|
|
137
|
+
migrateMessagesClientMessageId,
|
|
136
138
|
migrateMessagesConversationCreatedAtIndex,
|
|
137
139
|
migrateMessagesFtsBackfill,
|
|
138
140
|
migrateNormalizePhoneIdentities,
|
|
@@ -462,6 +464,8 @@ export function initializeDb(): void {
|
|
|
462
464
|
migrateMemoryV3Coactivation,
|
|
463
465
|
migrateMemoryV3AutoEdges,
|
|
464
466
|
migrateLlmRequestLogCallSite,
|
|
467
|
+
migrateDropProviderConnectionStatus,
|
|
468
|
+
migrateMessagesClientMessageId,
|
|
465
469
|
];
|
|
466
470
|
|
|
467
471
|
// Run each migration step, catching and logging individual failures so one
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Holds the assistant DB connection singleton and its close callback.
|
|
3
|
+
*
|
|
4
|
+
* Lives in its own module (rather than alongside the resolver in
|
|
5
|
+
* `db-connection.ts`) so test code can reset the singleton without
|
|
6
|
+
* importing `db-connection.ts` — which transitively pulls
|
|
7
|
+
* `drizzle-orm/bun-sqlite`. Stdlib-only by design: this file must remain
|
|
8
|
+
* safe to import from the test preload's load-time chain, where a broken
|
|
9
|
+
* `node_modules` symlink has historically tripped the env override
|
|
10
|
+
* (see DB ghost #3, /workspace/journal/2026-05-25-db-ghost-3-recovery.md).
|
|
11
|
+
*
|
|
12
|
+
* State is held on `globalThis.vellumAssistant.dbSingleton` so test
|
|
13
|
+
* helpers in `__tests__/` can read/write it WITHOUT importing this
|
|
14
|
+
* module — they declare the same slot shape locally and access the
|
|
15
|
+
* globalThis namespace directly. See
|
|
16
|
+
* `__tests__/db-test-helpers.ts` for the test-side mirror; the slot
|
|
17
|
+
* shape MUST stay in sync between the two.
|
|
18
|
+
*
|
|
19
|
+
* The stored value is typed as `unknown` so this file never has to import
|
|
20
|
+
* Drizzle types. Callers in `db-connection.ts` narrow via the type
|
|
21
|
+
* parameter on `getStoredDb<DrizzleDb>()`.
|
|
22
|
+
*
|
|
23
|
+
* Consumers:
|
|
24
|
+
* - `db-connection.ts` (opens/owns the connection)
|
|
25
|
+
* - production callers that need to close the active connection
|
|
26
|
+
* (migration routes, vbundle import, backup/restore, daemon shutdown)
|
|
27
|
+
* - `__tests__/db-test-helpers.ts` (per-test reset, via globalThis)
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
type DbSlot = {
|
|
31
|
+
db: unknown;
|
|
32
|
+
closer: (() => void) | null;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type VellumAssistantNamespace = {
|
|
36
|
+
dbSingleton?: DbSlot;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function slot(): DbSlot {
|
|
40
|
+
const g = globalThis as { vellumAssistant?: VellumAssistantNamespace };
|
|
41
|
+
const ns = (g.vellumAssistant ??= {});
|
|
42
|
+
return (ns.dbSingleton ??= { db: null, closer: null });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Read the current singleton, narrowed to `T`. `null` means not yet opened. */
|
|
46
|
+
export function getStoredDb<T>(): T | null {
|
|
47
|
+
return slot().db as T | null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Store a freshly-opened connection and the closer to run on
|
|
52
|
+
* `clearStoredDb()`. The closer must be self-contained — it is invoked
|
|
53
|
+
* inside a try/catch, so partial failures are swallowed (best-effort
|
|
54
|
+
* close on shutdown / restore paths).
|
|
55
|
+
*/
|
|
56
|
+
export function setStoredDb<T>(newDb: T, close: () => void): void {
|
|
57
|
+
const s = slot();
|
|
58
|
+
s.db = newDb;
|
|
59
|
+
s.closer = close;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Close the active connection (if any) via the stored closer, then drop
|
|
64
|
+
* both. Idempotent: safe to call when no connection is stored.
|
|
65
|
+
*/
|
|
66
|
+
export function clearStoredDb(): void {
|
|
67
|
+
const s = slot();
|
|
68
|
+
if (s.closer) {
|
|
69
|
+
try {
|
|
70
|
+
s.closer();
|
|
71
|
+
} catch {
|
|
72
|
+
/* best-effort close */
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
s.db = null;
|
|
76
|
+
s.closer = null;
|
|
77
|
+
}
|
|
@@ -10,6 +10,36 @@ import { eq } from "drizzle-orm";
|
|
|
10
10
|
import { getDb } from "./db-connection.js";
|
|
11
11
|
import { channelInboundEvents } from "./schema.js";
|
|
12
12
|
|
|
13
|
+
const SLACK_DM_LIVE_DELIVERED_TEXT_RESPONSE_INDEXES =
|
|
14
|
+
"slackDmLiveDeliveredTextResponseIndexes";
|
|
15
|
+
|
|
16
|
+
function parseRawPayload(
|
|
17
|
+
rawPayload: string | null,
|
|
18
|
+
): Record<string, unknown> | undefined {
|
|
19
|
+
if (!rawPayload) return undefined;
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(rawPayload) as unknown;
|
|
22
|
+
if (
|
|
23
|
+
parsed === null ||
|
|
24
|
+
typeof parsed !== "object" ||
|
|
25
|
+
Array.isArray(parsed)
|
|
26
|
+
) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
return parsed as Record<string, unknown>;
|
|
30
|
+
} catch {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function normalizePositiveIntegerIndexes(value: unknown): number[] {
|
|
36
|
+
if (!Array.isArray(value)) return [];
|
|
37
|
+
const indexes = value.filter(
|
|
38
|
+
(item): item is number => Number.isSafeInteger(item) && item > 0,
|
|
39
|
+
);
|
|
40
|
+
return [...new Set(indexes)].sort((a, b) => a - b);
|
|
41
|
+
}
|
|
42
|
+
|
|
13
43
|
// ── Pending verification reply helpers ───────────────────────────────
|
|
14
44
|
//
|
|
15
45
|
// When a guardian verification succeeds but the confirmation reply fails
|
|
@@ -100,6 +130,58 @@ export function updateDeliveredSegmentCount(
|
|
|
100
130
|
.run();
|
|
101
131
|
}
|
|
102
132
|
|
|
133
|
+
export function getSlackDmLiveDeliveredTextResponseIndexes(
|
|
134
|
+
eventId: string,
|
|
135
|
+
): number[] {
|
|
136
|
+
const db = getDb();
|
|
137
|
+
const row = db
|
|
138
|
+
.select({ rawPayload: channelInboundEvents.rawPayload })
|
|
139
|
+
.from(channelInboundEvents)
|
|
140
|
+
.where(eq(channelInboundEvents.id, eventId))
|
|
141
|
+
.get();
|
|
142
|
+
const payload = parseRawPayload(row?.rawPayload ?? null);
|
|
143
|
+
if (!payload) return [];
|
|
144
|
+
return normalizePositiveIntegerIndexes(
|
|
145
|
+
payload[SLACK_DM_LIVE_DELIVERED_TEXT_RESPONSE_INDEXES],
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function addSlackDmLiveDeliveredTextResponseIndex(
|
|
150
|
+
eventId: string,
|
|
151
|
+
responseIndex: number,
|
|
152
|
+
): void {
|
|
153
|
+
if (!Number.isSafeInteger(responseIndex) || responseIndex <= 0) return;
|
|
154
|
+
|
|
155
|
+
const db = getDb();
|
|
156
|
+
db.transaction((tx) => {
|
|
157
|
+
const row = tx
|
|
158
|
+
.select({ rawPayload: channelInboundEvents.rawPayload })
|
|
159
|
+
.from(channelInboundEvents)
|
|
160
|
+
.where(eq(channelInboundEvents.id, eventId))
|
|
161
|
+
.get();
|
|
162
|
+
if (!row?.rawPayload) return;
|
|
163
|
+
|
|
164
|
+
const payload = parseRawPayload(row.rawPayload);
|
|
165
|
+
if (!payload) return;
|
|
166
|
+
const indexes = normalizePositiveIntegerIndexes(
|
|
167
|
+
payload[SLACK_DM_LIVE_DELIVERED_TEXT_RESPONSE_INDEXES],
|
|
168
|
+
);
|
|
169
|
+
if (!indexes.includes(responseIndex)) indexes.push(responseIndex);
|
|
170
|
+
indexes.sort((a, b) => a - b);
|
|
171
|
+
|
|
172
|
+
tx.update(channelInboundEvents)
|
|
173
|
+
.set({
|
|
174
|
+
rawPayload: JSON.stringify({
|
|
175
|
+
...payload,
|
|
176
|
+
[SLACK_DM_LIVE_DELIVERED_TEXT_RESPONSE_INDEXES]: indexes,
|
|
177
|
+
}),
|
|
178
|
+
updatedAt: Date.now(),
|
|
179
|
+
})
|
|
180
|
+
.where(eq(channelInboundEvents.id, eventId))
|
|
181
|
+
.run();
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
103
185
|
// ── Deliver-once guard for terminal reply idempotency ────────────────
|
|
104
186
|
//
|
|
105
187
|
// When both the main poll (processChannelMessageWithApprovals) and the
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
|
|
29
29
|
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
30
30
|
|
|
31
|
+
import { createMockLoggerModule } from "../../../__tests__/helpers/mock-logger.js";
|
|
31
32
|
import type { AssistantConfig } from "../../../config/types.js";
|
|
32
33
|
import type { Message } from "../../../providers/types.js";
|
|
33
34
|
|
|
@@ -35,10 +36,7 @@ import type { Message } from "../../../providers/types.js";
|
|
|
35
36
|
// Module mocks (must precede the dynamic imports below)
|
|
36
37
|
// ---------------------------------------------------------------------------
|
|
37
38
|
|
|
38
|
-
mock.module("../../../util/logger.js", () => (
|
|
39
|
-
getLogger: () =>
|
|
40
|
-
new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
|
|
41
|
-
}));
|
|
39
|
+
mock.module("../../../util/logger.js", () => createMockLoggerModule());
|
|
42
40
|
|
|
43
41
|
// Stub the v1 retriever so we don't reach Qdrant. Both modes return zero
|
|
44
42
|
// nodes — the v1 injection branch becomes a no-op, isolating the assertion
|
|
@@ -71,9 +71,9 @@ mock.module("../../providers/provider-send-message.js", () => ({
|
|
|
71
71
|
extractToolUse: () => null,
|
|
72
72
|
}));
|
|
73
73
|
|
|
74
|
+
import { resetDbForTesting } from "../../__tests__/db-test-helpers.js";
|
|
74
75
|
import { DEFAULT_CONFIG } from "../../config/defaults.js";
|
|
75
76
|
import type { AssistantConfig } from "../../config/types.js";
|
|
76
|
-
import { resetDb } from "../db-connection.js";
|
|
77
77
|
import { initializeDb } from "../db-init.js";
|
|
78
78
|
import { resetTestTables } from "../raw-query.js";
|
|
79
79
|
import { InContextTracker } from "./injection.js";
|
|
@@ -134,7 +134,7 @@ describe("loadContextMemory — query/sparse vector surfacing", () => {
|
|
|
134
134
|
embedCallCount = 0;
|
|
135
135
|
embedRouter = null;
|
|
136
136
|
searchRouter = null;
|
|
137
|
-
|
|
137
|
+
resetDbForTesting();
|
|
138
138
|
initializeDb();
|
|
139
139
|
});
|
|
140
140
|
|
|
@@ -190,7 +190,7 @@ describe("retrieveForTurn — query/sparse vector surfacing", () => {
|
|
|
190
190
|
embedCallCount = 0;
|
|
191
191
|
embedRouter = null;
|
|
192
192
|
searchRouter = null;
|
|
193
|
-
|
|
193
|
+
resetDbForTesting();
|
|
194
194
|
initializeDb();
|
|
195
195
|
});
|
|
196
196
|
|
|
@@ -40,9 +40,10 @@ mock.module("../job-utils.js", () => ({
|
|
|
40
40
|
},
|
|
41
41
|
}));
|
|
42
42
|
|
|
43
|
+
import { resetDbForTesting } from "../../__tests__/db-test-helpers.js";
|
|
43
44
|
import { DEFAULT_CONFIG } from "../../config/defaults.js";
|
|
44
45
|
import type { AssistantConfig } from "../../config/types.js";
|
|
45
|
-
import { getDb
|
|
46
|
+
import { getDb } from "../db-connection.js";
|
|
46
47
|
import { initializeDb } from "../db-init.js";
|
|
47
48
|
import type { MemoryJob } from "../jobs-store.js";
|
|
48
49
|
import { mediaAssets } from "../schema.js";
|
|
@@ -66,7 +67,7 @@ describe("embedMediaJob", () => {
|
|
|
66
67
|
|
|
67
68
|
beforeEach(() => {
|
|
68
69
|
embedAndUpsertCalls.length = 0;
|
|
69
|
-
|
|
70
|
+
resetDbForTesting();
|
|
70
71
|
initializeDb();
|
|
71
72
|
});
|
|
72
73
|
|
|
@@ -142,7 +142,10 @@ afterAll(() => {
|
|
|
142
142
|
// Imports are deferred to after the env var is set so any internal use of
|
|
143
143
|
// `getWorkspaceDir()` resolves to the tmpdir.
|
|
144
144
|
const { DEFAULT_CONFIG } = await import("../../../config/defaults.js");
|
|
145
|
-
const { getDb
|
|
145
|
+
const { getDb } = await import("../../db-connection.js");
|
|
146
|
+
const { resetDbForTesting } = await import(
|
|
147
|
+
"../../../__tests__/db-test-helpers.js"
|
|
148
|
+
);
|
|
146
149
|
const { initializeDb } = await import("../../db-init.js");
|
|
147
150
|
const { memoryEmbeddings, memoryJobs } = await import("../../schema.js");
|
|
148
151
|
const { claimMemoryJobs } = await import("../../jobs-store.js");
|
|
@@ -183,7 +186,7 @@ function makeJob(payload: Record<string, unknown>): MemoryJob {
|
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
beforeEach(() => {
|
|
186
|
-
|
|
189
|
+
resetDbForTesting();
|
|
187
190
|
initializeDb();
|
|
188
191
|
embedWithBackendCalls.length = 0;
|
|
189
192
|
upsertCalls.length = 0;
|
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
enqueuePruneOldTraceEventsJob,
|
|
66
66
|
failMemoryJob,
|
|
67
67
|
failStalledJobs,
|
|
68
|
+
hasActiveJobOfType,
|
|
68
69
|
type MemoryJob,
|
|
69
70
|
type MemoryJobType,
|
|
70
71
|
resetRunningJobsToPending,
|
|
@@ -791,8 +792,18 @@ export function maybeEnqueueGraphMaintenanceJobs(
|
|
|
791
792
|
// Size-based trigger: when the shared buffer crosses the configured line
|
|
792
793
|
// count, drain it now rather than waiting out the interval. Retargets to the
|
|
793
794
|
// same consolidator the interval branch above selected.
|
|
795
|
+
//
|
|
796
|
+
// The size branch is checkpoint-blind by design (it must fire before the
|
|
797
|
+
// interval elapses), so it dedupes against an already-active consolidate job
|
|
798
|
+
// instead — otherwise it would re-enqueue on every worker tick while the
|
|
799
|
+
// buffer stays over threshold, flooding the queue with redundant LLM work.
|
|
794
800
|
const maxLines = config.memory.v2.consolidation_max_buffer_lines;
|
|
795
|
-
if (
|
|
801
|
+
if (
|
|
802
|
+
v2Active &&
|
|
803
|
+
!enqueuedConsolidate &&
|
|
804
|
+
maxLines !== null &&
|
|
805
|
+
!hasActiveJobOfType(consolidateEntry.jobType)
|
|
806
|
+
) {
|
|
796
807
|
const bufferPath = join(getWorkspaceDir(), "memory", "buffer.md");
|
|
797
808
|
if (countBufferLines(bufferPath) >= maxLines) {
|
|
798
809
|
enqueueMemoryJob(consolidateEntry.jobType, {});
|
|
@@ -209,6 +209,86 @@ export class ClickHouseLlmRequestLogSource implements LlmRequestLogSource {
|
|
|
209
209
|
return rows.map((r) => this.toLogRow(r));
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
async getCompactionLogsBetween(
|
|
213
|
+
conversationId: string,
|
|
214
|
+
afterCreatedAt: number | null,
|
|
215
|
+
beforeCreatedAt: number,
|
|
216
|
+
): Promise<LogRow[]> {
|
|
217
|
+
const aid = await this.assistantId();
|
|
218
|
+
// `call_site` is bound as a literal via type-bound parameter (not
|
|
219
|
+
// string interpolation) for parity with the rest of this class —
|
|
220
|
+
// even though "compactionAgent" is a hard-coded identifier today,
|
|
221
|
+
// future call sites should plug into the same parameter slot
|
|
222
|
+
// without re-templating the query string.
|
|
223
|
+
//
|
|
224
|
+
// The `afterCreatedAt` lower bound is appended dynamically because
|
|
225
|
+
// type-bound parameter slots that are referenced in the SQL but
|
|
226
|
+
// unbound at exec time return a server error — so we only template
|
|
227
|
+
// the predicate in when the caller actually has a floor to enforce.
|
|
228
|
+
const params: Record<string, string> = {
|
|
229
|
+
assistant_id: aid,
|
|
230
|
+
conversation_id: conversationId,
|
|
231
|
+
call_site: "compactionAgent",
|
|
232
|
+
before_created_at: String(beforeCreatedAt),
|
|
233
|
+
};
|
|
234
|
+
let afterPredicate = "";
|
|
235
|
+
if (afterCreatedAt !== null) {
|
|
236
|
+
params.after_created_at = String(afterCreatedAt);
|
|
237
|
+
afterPredicate =
|
|
238
|
+
" AND created_at > fromUnixTimestamp64Milli({after_created_at:Int64})";
|
|
239
|
+
}
|
|
240
|
+
const sql = `SELECT
|
|
241
|
+
id,
|
|
242
|
+
conversation_id,
|
|
243
|
+
message_id,
|
|
244
|
+
provider,
|
|
245
|
+
request_payload,
|
|
246
|
+
response_payload,
|
|
247
|
+
toUnixTimestamp64Milli(created_at) AS created_at,
|
|
248
|
+
agent_loop_exit_reason,
|
|
249
|
+
call_site
|
|
250
|
+
FROM ${this.tableRef()}
|
|
251
|
+
WHERE assistant_id = {assistant_id:String}
|
|
252
|
+
AND conversation_id = {conversation_id:String}
|
|
253
|
+
AND call_site = {call_site:String}
|
|
254
|
+
AND created_at < fromUnixTimestamp64Milli({before_created_at:Int64})${afterPredicate}
|
|
255
|
+
ORDER BY created_at ASC, id ASC
|
|
256
|
+
LIMIT 1 BY id
|
|
257
|
+
FORMAT JSONEachRow`;
|
|
258
|
+
const rows = await this.exec(sql, params);
|
|
259
|
+
return rows.map((r) => this.toLogRow(r));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async getPreviousNonCompactionCallCreatedAt(
|
|
263
|
+
conversationId: string,
|
|
264
|
+
beforeCreatedAt: number,
|
|
265
|
+
): Promise<number | null> {
|
|
266
|
+
const aid = await this.assistantId();
|
|
267
|
+
// "Non-compactionAgent" includes empty-string `call_site`, which is
|
|
268
|
+
// what the CH mirror writes for pre-migration-264 rows whose SQLite
|
|
269
|
+
// value was NULL (CH columns are `DEFAULT ''`, not Nullable — see
|
|
270
|
+
// `toLogRow`). The local store treats NULL `callSite` the same way,
|
|
271
|
+
// so the predicate stays in sync.
|
|
272
|
+
const sql = `SELECT
|
|
273
|
+
toUnixTimestamp64Milli(created_at) AS created_at
|
|
274
|
+
FROM ${this.tableRef()}
|
|
275
|
+
WHERE assistant_id = {assistant_id:String}
|
|
276
|
+
AND conversation_id = {conversation_id:String}
|
|
277
|
+
AND created_at < fromUnixTimestamp64Milli({before_created_at:Int64})
|
|
278
|
+
AND call_site != {call_site:String}
|
|
279
|
+
ORDER BY created_at DESC, id DESC
|
|
280
|
+
LIMIT 1
|
|
281
|
+
FORMAT JSONEachRow`;
|
|
282
|
+
const rows = await this.exec(sql, {
|
|
283
|
+
assistant_id: aid,
|
|
284
|
+
conversation_id: conversationId,
|
|
285
|
+
call_site: "compactionAgent",
|
|
286
|
+
before_created_at: String(beforeCreatedAt),
|
|
287
|
+
});
|
|
288
|
+
const value = rows[0]?.created_at;
|
|
289
|
+
return value === undefined ? null : Number(value);
|
|
290
|
+
}
|
|
291
|
+
|
|
212
292
|
private async selectByMessageIds(ids: string[]): Promise<LogRow[]> {
|
|
213
293
|
if (ids.length === 0) return [];
|
|
214
294
|
const aid = await this.assistantId();
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { LlmRequestLogSource } from "./llm-request-log-source.js";
|
|
12
12
|
import {
|
|
13
|
+
getCompactionLogsBetween,
|
|
14
|
+
getPreviousNonCompactionCallCreatedAt,
|
|
13
15
|
getRequestLogById,
|
|
14
16
|
getRequestLogsByConversationId,
|
|
15
17
|
getRequestLogsByMessageId,
|
|
@@ -30,4 +32,26 @@ export class LocalLlmRequestLogSource implements LlmRequestLogSource {
|
|
|
30
32
|
): Promise<LogRow[]> {
|
|
31
33
|
return getRequestLogsByConversationId(conversationId);
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
async getCompactionLogsBetween(
|
|
37
|
+
conversationId: string,
|
|
38
|
+
afterCreatedAt: number | null,
|
|
39
|
+
beforeCreatedAt: number,
|
|
40
|
+
): Promise<LogRow[]> {
|
|
41
|
+
return getCompactionLogsBetween(
|
|
42
|
+
conversationId,
|
|
43
|
+
afterCreatedAt,
|
|
44
|
+
beforeCreatedAt,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async getPreviousNonCompactionCallCreatedAt(
|
|
49
|
+
conversationId: string,
|
|
50
|
+
beforeCreatedAt: number,
|
|
51
|
+
): Promise<number | null> {
|
|
52
|
+
return getPreviousNonCompactionCallCreatedAt(
|
|
53
|
+
conversationId,
|
|
54
|
+
beforeCreatedAt,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
33
57
|
}
|
|
@@ -38,6 +38,37 @@ export interface LlmRequestLogSource {
|
|
|
38
38
|
* and orphaned logs are all included because they share conversation_id.
|
|
39
39
|
*/
|
|
40
40
|
getRequestLogsByConversationId(conversationId: string): Promise<LogRow[]>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Fetch every `callSite = "compactionAgent"` log row in the conversation
|
|
44
|
+
* whose `createdAt` falls in the **open window**
|
|
45
|
+
* `(afterCreatedAt, beforeCreatedAt)`, ordered chronologically.
|
|
46
|
+
*
|
|
47
|
+
* Drives the Inspector's Compaction tab. The route handler resolves
|
|
48
|
+
* both bounds: the selected LLM call's `createdAt` (ceiling) and the
|
|
49
|
+
* previous non-`compactionAgent` call's `createdAt` (floor) — passing
|
|
50
|
+
* `null` for the floor when the selected call is the first real call
|
|
51
|
+
* in the conversation. See `getCompactionLogsBetween` and
|
|
52
|
+
* `getPreviousNonCompactionCallCreatedAt` in `llm-request-log-store.ts`
|
|
53
|
+
* for the full bound semantics.
|
|
54
|
+
*/
|
|
55
|
+
getCompactionLogsBetween(
|
|
56
|
+
conversationId: string,
|
|
57
|
+
afterCreatedAt: number | null,
|
|
58
|
+
beforeCreatedAt: number,
|
|
59
|
+
): Promise<LogRow[]>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Find the `createdAt` of the most recent non-`compactionAgent` LLM
|
|
63
|
+
* call in the conversation strictly before `beforeCreatedAt`, or
|
|
64
|
+
* `null` when no such call exists. Pairs with
|
|
65
|
+
* `getCompactionLogsBetween` to bound the compaction trail to the
|
|
66
|
+
* window between the prior real call and the selected call.
|
|
67
|
+
*/
|
|
68
|
+
getPreviousNonCompactionCallCreatedAt(
|
|
69
|
+
conversationId: string,
|
|
70
|
+
beforeCreatedAt: number,
|
|
71
|
+
): Promise<number | null>;
|
|
41
72
|
}
|
|
42
73
|
|
|
43
74
|
/**
|