@vellumai/assistant 0.10.0 → 0.10.1-staging.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/ARCHITECTURE.md +36 -37
- package/bun.lock +3 -0
- package/docs/workflows.md +12 -7
- package/eslint-rules/cli-no-daemon-internals.js +6 -0
- package/node_modules/@slack/types/LICENSE +23 -0
- package/node_modules/@slack/types/README.md +32 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +953 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.js +4 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +474 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.js +3 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +237 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.js +4 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.d.ts +88 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.js +3 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.js.map +1 -0
- package/node_modules/@slack/types/dist/calls.d.ts +26 -0
- package/node_modules/@slack/types/dist/calls.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/calls.js +6 -0
- package/node_modules/@slack/types/dist/calls.js.map +1 -0
- package/node_modules/@slack/types/dist/chunk.d.ts +52 -0
- package/node_modules/@slack/types/dist/chunk.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/chunk.js +3 -0
- package/node_modules/@slack/types/dist/chunk.js.map +1 -0
- package/node_modules/@slack/types/dist/common/bot-profile.d.ts +12 -0
- package/node_modules/@slack/types/dist/common/bot-profile.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/common/bot-profile.js +3 -0
- package/node_modules/@slack/types/dist/common/bot-profile.js.map +1 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts +6 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.js +3 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.js.map +1 -0
- package/node_modules/@slack/types/dist/dialog.d.ts +36 -0
- package/node_modules/@slack/types/dist/dialog.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/dialog.js +3 -0
- package/node_modules/@slack/types/dist/dialog.js.map +1 -0
- package/node_modules/@slack/types/dist/events/app.d.ts +204 -0
- package/node_modules/@slack/types/dist/events/app.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/app.js +3 -0
- package/node_modules/@slack/types/dist/events/app.js.map +1 -0
- package/node_modules/@slack/types/dist/events/assistant.d.ts +29 -0
- package/node_modules/@slack/types/dist/events/assistant.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/assistant.js +3 -0
- package/node_modules/@slack/types/dist/events/assistant.js.map +1 -0
- package/node_modules/@slack/types/dist/events/call.d.ts +8 -0
- package/node_modules/@slack/types/dist/events/call.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/call.js +3 -0
- package/node_modules/@slack/types/dist/events/call.js.map +1 -0
- package/node_modules/@slack/types/dist/events/channel.d.ts +85 -0
- package/node_modules/@slack/types/dist/events/channel.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/channel.js +3 -0
- package/node_modules/@slack/types/dist/events/channel.js.map +1 -0
- package/node_modules/@slack/types/dist/events/dnd.d.ts +24 -0
- package/node_modules/@slack/types/dist/events/dnd.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/dnd.js +3 -0
- package/node_modules/@slack/types/dist/events/dnd.js.map +1 -0
- package/node_modules/@slack/types/dist/events/email.d.ts +6 -0
- package/node_modules/@slack/types/dist/events/email.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/email.js +3 -0
- package/node_modules/@slack/types/dist/events/email.js.map +1 -0
- package/node_modules/@slack/types/dist/events/emoji.d.ts +11 -0
- package/node_modules/@slack/types/dist/events/emoji.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/emoji.js +3 -0
- package/node_modules/@slack/types/dist/events/emoji.js.map +1 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts +21 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.js +3 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.js.map +1 -0
- package/node_modules/@slack/types/dist/events/file.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/file.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/file.js +4 -0
- package/node_modules/@slack/types/dist/events/file.js.map +1 -0
- package/node_modules/@slack/types/dist/events/function.d.ts +33 -0
- package/node_modules/@slack/types/dist/events/function.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/function.js +3 -0
- package/node_modules/@slack/types/dist/events/function.js.map +1 -0
- package/node_modules/@slack/types/dist/events/grid-migration.d.ts +9 -0
- package/node_modules/@slack/types/dist/events/grid-migration.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/grid-migration.js +3 -0
- package/node_modules/@slack/types/dist/events/grid-migration.js.map +1 -0
- package/node_modules/@slack/types/dist/events/group.d.ts +55 -0
- package/node_modules/@slack/types/dist/events/group.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/group.js +3 -0
- package/node_modules/@slack/types/dist/events/group.js.map +1 -0
- package/node_modules/@slack/types/dist/events/im.d.ts +26 -0
- package/node_modules/@slack/types/dist/events/im.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/im.js +3 -0
- package/node_modules/@slack/types/dist/events/im.js.map +1 -0
- package/node_modules/@slack/types/dist/events/index.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/index.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/index.js +43 -0
- package/node_modules/@slack/types/dist/events/index.js.map +1 -0
- package/node_modules/@slack/types/dist/events/invite.d.ts +20 -0
- package/node_modules/@slack/types/dist/events/invite.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/invite.js +3 -0
- package/node_modules/@slack/types/dist/events/invite.js.map +1 -0
- package/node_modules/@slack/types/dist/events/link-shared.d.ts +16 -0
- package/node_modules/@slack/types/dist/events/link-shared.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/link-shared.js +3 -0
- package/node_modules/@slack/types/dist/events/link-shared.js.map +1 -0
- package/node_modules/@slack/types/dist/events/member.d.ts +19 -0
- package/node_modules/@slack/types/dist/events/member.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/member.js +3 -0
- package/node_modules/@slack/types/dist/events/member.js.map +1 -0
- package/node_modules/@slack/types/dist/events/message-metadata.d.ts +38 -0
- package/node_modules/@slack/types/dist/events/message-metadata.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/message-metadata.js +3 -0
- package/node_modules/@slack/types/dist/events/message-metadata.js.map +1 -0
- package/node_modules/@slack/types/dist/events/message.d.ts +306 -0
- package/node_modules/@slack/types/dist/events/message.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/message.js +3 -0
- package/node_modules/@slack/types/dist/events/message.js.map +1 -0
- package/node_modules/@slack/types/dist/events/pin.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/pin.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/pin.js +3 -0
- package/node_modules/@slack/types/dist/events/pin.js.map +1 -0
- package/node_modules/@slack/types/dist/events/reaction.d.ts +23 -0
- package/node_modules/@slack/types/dist/events/reaction.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/reaction.js +3 -0
- package/node_modules/@slack/types/dist/events/reaction.js.map +1 -0
- package/node_modules/@slack/types/dist/events/shared-channel.d.ts +134 -0
- package/node_modules/@slack/types/dist/events/shared-channel.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/shared-channel.js +3 -0
- package/node_modules/@slack/types/dist/events/shared-channel.js.map +1 -0
- package/node_modules/@slack/types/dist/events/star.d.ts +13 -0
- package/node_modules/@slack/types/dist/events/star.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/star.js +3 -0
- package/node_modules/@slack/types/dist/events/star.js.map +1 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts +82 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.js +3 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.js.map +1 -0
- package/node_modules/@slack/types/dist/events/subteam.d.ts +66 -0
- package/node_modules/@slack/types/dist/events/subteam.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/subteam.js +3 -0
- package/node_modules/@slack/types/dist/events/subteam.js.map +1 -0
- package/node_modules/@slack/types/dist/events/team.d.ts +99 -0
- package/node_modules/@slack/types/dist/events/team.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/team.js +3 -0
- package/node_modules/@slack/types/dist/events/team.js.map +1 -0
- package/node_modules/@slack/types/dist/events/token.d.ts +8 -0
- package/node_modules/@slack/types/dist/events/token.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/token.js +3 -0
- package/node_modules/@slack/types/dist/events/token.js.map +1 -0
- package/node_modules/@slack/types/dist/events/user.d.ts +313 -0
- package/node_modules/@slack/types/dist/events/user.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/user.js +3 -0
- package/node_modules/@slack/types/dist/events/user.js.map +1 -0
- package/node_modules/@slack/types/dist/index.d.ts +12 -0
- package/node_modules/@slack/types/dist/index.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/index.js +28 -0
- package/node_modules/@slack/types/dist/index.js.map +1 -0
- package/node_modules/@slack/types/dist/message-attachments.d.ts +171 -0
- package/node_modules/@slack/types/dist/message-attachments.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/message-attachments.js +3 -0
- package/node_modules/@slack/types/dist/message-attachments.js.map +1 -0
- package/node_modules/@slack/types/dist/message-metadata.d.ts +281 -0
- package/node_modules/@slack/types/dist/message-metadata.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/message-metadata.js +27 -0
- package/node_modules/@slack/types/dist/message-metadata.js.map +1 -0
- package/node_modules/@slack/types/dist/views.d.ts +71 -0
- package/node_modules/@slack/types/dist/views.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/views.js +3 -0
- package/node_modules/@slack/types/dist/views.js.map +1 -0
- package/node_modules/@slack/types/package.json +47 -0
- package/node_modules/@vellumai/gateway-client/bun.lock +3 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +69 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +65 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +4 -2
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +3 -2
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +78 -0
- package/openapi.yaml +345 -18
- package/package.json +2 -1
- package/scripts/memory-inspect.ts +24 -14
- package/src/__tests__/access-request-seed-content-blocks.test.ts +83 -103
- package/src/__tests__/activation-early-marking.test.ts +1 -1
- package/src/__tests__/actor-token-service.test.ts +3 -3
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +1 -40
- package/src/__tests__/agent-loop-compaction-events.test.ts +0 -1
- package/src/__tests__/agent-loop-compaction-strip.test.ts +0 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +0 -1
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +0 -1
- package/src/__tests__/agent-loop.test.ts +3 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
- package/src/__tests__/anthropic-provider.test.ts +143 -9
- package/src/__tests__/app-builder-skill-instructions.test.ts +47 -5
- package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -1
- package/src/__tests__/app-source-watcher.test.ts +30 -10
- package/src/__tests__/approval-cascade.test.ts +6 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +151 -0
- package/src/__tests__/approval-primitive.test.ts +1 -1
- package/src/__tests__/approval-routes-http.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +155 -0
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +2 -4
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-events-sse-shed.test.ts +1 -1
- package/src/__tests__/attachment-upload-trusted-source.test.ts +13 -8
- package/src/__tests__/attachments-store.test.ts +1 -1
- package/src/__tests__/audit-log-rotation.test.ts +50 -54
- package/src/__tests__/auth-fallback-events-store.test.ts +1 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -14
- package/src/__tests__/background-shell-bash.test.ts +4 -1
- package/src/__tests__/background-shell-host-bash.test.ts +17 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-controller.test.ts +1 -1
- package/src/__tests__/call-conversation-messages.test.ts +1 -1
- package/src/__tests__/call-domain.test.ts +1 -1
- package/src/__tests__/call-pointer-messages.test.ts +3 -4
- package/src/__tests__/call-recovery.test.ts +1 -1
- package/src/__tests__/call-routes-http.test.ts +1 -1
- package/src/__tests__/call-store.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/canonical-guardian-store.test.ts +24 -1
- package/src/__tests__/channel-approval-routes.test.ts +73 -1119
- package/src/__tests__/channel-delivery-store.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +265 -641
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -2
- package/src/__tests__/channel-retry-sweep.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +6 -0
- package/src/__tests__/compaction-trail-store.test.ts +6 -5
- package/src/__tests__/compaction.benchmark.test.ts +0 -1
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/config-loader-backfill.test.ts +183 -51
- package/src/__tests__/config-schema.test.ts +34 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -2
- package/src/__tests__/contact-store-user-file.test.ts +2 -2
- package/src/__tests__/contacts-relay-reads.test.ts +409 -0
- package/src/__tests__/contacts-tools.test.ts +4 -4
- package/src/__tests__/contacts-write.test.ts +1 -2
- package/src/__tests__/context-search-conversations-source.test.ts +1 -1
- package/src/__tests__/context-window-manager-compact-retry.test.ts +6 -2
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +6 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop.test.ts +3 -0
- package/src/__tests__/conversation-attachments.test.ts +2 -5
- package/src/__tests__/conversation-attention-store.test.ts +1 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +1 -2
- package/src/__tests__/conversation-clear-safety.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +12 -19
- package/src/__tests__/conversation-disk-view-integration.test.ts +1 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +10 -8
- package/src/__tests__/conversation-fork-retrospective.test.ts +250 -0
- package/src/__tests__/conversation-fork-route.test.ts +1 -1
- package/src/__tests__/conversation-inference-profile-list.test.ts +1 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-lifecycle.test.ts +117 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -3
- package/src/__tests__/conversation-process-callsite.test.ts +6 -14
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +6 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +115 -12
- package/src/__tests__/conversation-slash-queue.test.ts +6 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +6 -0
- package/src/__tests__/conversation-starter-routes.test.ts +5 -5
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -1
- package/src/__tests__/conversation-sync-tags.test.ts +1 -1
- package/src/__tests__/conversation-usage.test.ts +1 -1
- package/src/__tests__/conversation-wipe.test.ts +9 -8
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/conversations-import-system-filter.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +17 -0
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/db-acp-history.test.ts +2 -2
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +5 -7
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +6 -7
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +5 -10
- package/src/__tests__/db-migration-rollback.test.ts +129 -39
- package/src/__tests__/db-proxy-transaction.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -11
- package/src/__tests__/db-test-helpers.ts +36 -19
- package/src/__tests__/delete-propagation.test.ts +1 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +26 -8
- package/src/__tests__/disk-pressure-tools.test.ts +41 -1
- package/src/__tests__/dm-backfill.test.ts +1 -1
- package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
- package/src/__tests__/edit-propagation.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +83 -0
- package/src/__tests__/empty-response-hook.test.ts +42 -0
- package/src/__tests__/events-client-registration.test.ts +1 -1
- package/src/__tests__/followup-tools.test.ts +1 -1
- package/src/__tests__/gemini-count-tokens.test.ts +70 -0
- package/src/__tests__/guardian-action-sweep.test.ts +9 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-card-withdrawal.test.ts +1 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -12
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
- package/src/__tests__/guardian-routing-state.test.ts +1 -2
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/headless-browser-mode.test.ts +2 -2
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +6 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +98 -0
- package/src/__tests__/http-conversation-lineage.test.ts +1 -1
- package/src/__tests__/image-recovery-hook.test.ts +1 -1
- package/src/__tests__/inbound-invite-redemption.test.ts +1 -2
- package/src/__tests__/inbound-trust-verdict.test.ts +254 -0
- package/src/__tests__/inference-profile-reaper.test.ts +1 -1
- package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
- package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-disk-pressure.test.ts +11 -6
- package/src/__tests__/internal-telemetry-routes.test.ts +1 -1
- package/src/__tests__/invite-redemption-service.test.ts +244 -43
- package/src/__tests__/invite-routes-http.test.ts +35 -186
- package/src/__tests__/invite-service-ipc.test.ts +287 -0
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +5 -5
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +9 -12
- package/src/__tests__/list-messages-attachments.test.ts +42 -1
- package/src/__tests__/list-messages-client-message-id.test.ts +1 -1
- package/src/__tests__/list-messages-hidden-metadata.test.ts +1 -1
- package/src/__tests__/list-messages-page-latest.test.ts +1 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +1 -1
- package/src/__tests__/llm-context-route-provider.test.ts +69 -4
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +9 -5
- package/src/__tests__/llm-request-log-call-site.test.ts +6 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +27 -13
- package/src/__tests__/llm-usage-store.test.ts +40 -1
- package/src/__tests__/log-export-routes.test.ts +1 -1
- package/src/__tests__/log-export-workspace.test.ts +3 -3
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +5 -5
- package/src/__tests__/memory-recall-log-store.test.ts +1 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +3 -4
- package/src/__tests__/messages-after-tiebreaker.test.ts +1 -1
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +375 -0
- package/src/__tests__/non-member-access-request.test.ts +1 -2
- package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -1
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +1 -1
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +1 -1
- package/src/__tests__/persist-unsendable-image.test.ts +1 -1
- package/src/__tests__/persona-resolver.test.ts +39 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/playbook-execution.test.ts +1 -1
- package/src/__tests__/playbook-tools.test.ts +1 -1
- package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
- package/src/__tests__/plugin-bootstrap.test.ts +78 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
- package/src/__tests__/provider-usage-tracking.test.ts +1 -1
- package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/relay-server.test.ts +357 -56
- package/src/__tests__/runtime-attachment-metadata.test.ts +10 -1
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +7 -9
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-retry.test.ts +1 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +1 -1
- package/src/__tests__/schedule-store.test.ts +1 -1
- package/src/__tests__/schedule-tools.test.ts +1 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +1 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +1 -1
- package/src/__tests__/scheduler-wake.test.ts +2 -1
- package/src/__tests__/scoped-approval-grants.test.ts +1 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -5
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +0 -8
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +1 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +40 -1
- package/src/__tests__/settings-routes.test.ts +11 -10
- package/src/__tests__/skill-load-tool.test.ts +72 -0
- package/src/__tests__/slack-inbound-verification.test.ts +1 -3
- package/src/__tests__/slack-messaging-token-resolution.test.ts +13 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +1 -1
- package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -73
- package/src/__tests__/subagent-tools.test.ts +1 -31
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
- package/src/__tests__/task-compiler.test.ts +1 -1
- package/src/__tests__/task-management-tools.test.ts +1 -1
- package/src/__tests__/task-memory-cleanup.test.ts +9 -6
- package/src/__tests__/task-scheduler.test.ts +1 -1
- package/src/__tests__/thread-backfill.test.ts +1 -1
- package/src/__tests__/tool-approval-handler.test.ts +1 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +2 -0
- package/src/__tests__/tool-executor.test.ts +32 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +73 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +34 -34
- package/src/__tests__/trusted-contact-multichannel.test.ts +1 -2
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/turn-boundary-resolution.test.ts +3 -3
- package/src/__tests__/turn-events-store.test.ts +1 -1
- package/src/__tests__/twilio-routes.test.ts +2 -3
- package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
- package/src/__tests__/usage-routes.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +34 -29
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/voice-invite-redemption.test.ts +134 -36
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
- package/src/__tests__/voice-session-bridge.test.ts +1 -1
- package/src/__tests__/workspace-git-service.test.ts +114 -1
- package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
- package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
- package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
- package/src/a2a/__tests__/task-store.test.ts +1 -1
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
- package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
- package/src/acp/__tests__/session-manager.test.ts +72 -1
- package/src/acp/index.ts +10 -0
- package/src/acp/session-manager.ts +35 -0
- package/src/agent/loop.ts +45 -27
- package/src/api/index.ts +0 -6
- package/src/approvals/AGENTS.md +1 -2
- package/src/approvals/guardian-decision-primitive.ts +13 -210
- package/src/approvals/guardian-request-resolvers.ts +104 -58
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/inbound-trust-reader.test.ts +110 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +88 -62
- package/src/calls/inbound-trust-reader.ts +40 -0
- package/src/calls/relay-server.ts +65 -23
- package/src/calls/relay-setup-router.ts +20 -6
- package/src/calls/relay-verification.ts +7 -7
- package/src/cli/commands/contacts.ts +6 -24
- package/src/cli/commands/db/__tests__/repair.test.ts +15 -6
- package/src/cli/commands/db/__tests__/status.test.ts +7 -3
- package/src/cli/commands/db/status.ts +212 -33
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/memory-retrospective.ts +129 -0
- package/src/cli/commands/memory/memory-v3.ts +176 -4
- package/src/cli/commands/plugins.ts +268 -11
- package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +158 -0
- package/src/cli/lib/install-from-github.ts +47 -6
- package/src/cli/lib/plugin-marketplace.ts +11 -0
- package/src/cli/lib/plugin-pin-history.ts +257 -0
- package/src/cli/lib/toggle-plugin.ts +146 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +15 -33
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +3 -8
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +64 -37
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +1 -1
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +14 -72
- package/src/config/bundled-skills/app-builder/references/examples/README.md +1 -2
- package/src/config/bundled-skills/contacts/SKILL.md +7 -12
- package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
- package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
- package/src/config/bundled-skills/workflows/SKILL.md +4 -3
- package/src/config/call-site-defaults.ts +11 -2
- package/src/config/feature-flag-registry.json +0 -8
- package/src/config/profile-dispatchability.ts +11 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/llm.ts +2 -0
- package/src/config/schemas/memory-lifecycle.ts +5 -3
- package/src/config/schemas/timeouts.ts +24 -0
- package/src/config/seed-inference-profiles.ts +133 -45
- package/src/config/sync-gated-profiles.ts +13 -1
- package/src/contacts/contact-store.ts +21 -0
- package/src/contacts/member-status.ts +9 -0
- package/src/credential-health/credential-health-service.ts +1 -5
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
- package/src/daemon/app-source-watcher.ts +31 -18
- package/src/daemon/assistant-attachments.ts +94 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +3 -0
- package/src/daemon/conversation-agent-loop.ts +9 -36
- package/src/daemon/conversation-runtime-assembly.ts +91 -66
- package/src/daemon/conversation-tool-setup.ts +20 -63
- package/src/daemon/conversation.ts +144 -52
- package/src/daemon/event-loop-watchdog.test.ts +85 -0
- package/src/daemon/event-loop-watchdog.ts +133 -0
- package/src/daemon/external-plugins-bootstrap.ts +26 -80
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
- package/src/daemon/handlers/config-channels.ts +32 -18
- package/src/daemon/handlers/conversations.ts +7 -0
- package/src/daemon/handlers/shared.ts +7 -0
- package/src/daemon/lifecycle.ts +16 -3
- package/src/daemon/message-types/inbox.ts +0 -6
- package/src/daemon/message-types/messages.ts +0 -4
- package/src/daemon/message-types/surfaces.ts +18 -8
- package/src/daemon/server.ts +0 -4
- package/src/daemon/tool-setup-types.ts +0 -7
- package/src/daemon/trust-context.ts +6 -0
- package/src/daemon/wake-conversation-ops.ts +70 -0
- package/src/daemon/workspace-tools-watcher.ts +7 -3
- package/src/documents/document-comments-store.test.ts +1 -1
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +1 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -0
- package/src/heartbeat/heartbeat-service.ts +3 -4
- package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
- package/src/ipc/__tests__/browser-ipc.test.ts +73 -2
- package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
- package/src/ipc/assistant-server.ts +8 -0
- package/src/ipc/gateway-client.ts +2 -1
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +58 -0
- package/src/ipc/routes/invite-ipc-routes.ts +66 -0
- package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
- package/src/memory/__tests__/activation-session-store.test.ts +1 -1
- package/src/memory/__tests__/auto-analysis-guard.test.ts +1 -1
- package/src/memory/__tests__/conversation-group-migration.test.ts +1 -1
- package/src/memory/__tests__/conversation-queries.test.ts +1 -1
- package/src/memory/__tests__/db-async-query.test.ts +1 -1
- package/src/memory/__tests__/db-logs-attach.test.ts +110 -0
- package/src/memory/__tests__/db-maintenance.test.ts +28 -36
- package/src/memory/__tests__/db-memory-attach.test.ts +113 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +1 -1
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -1
- package/src/memory/__tests__/fork-message-copy.test.ts +232 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +3 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +5 -5
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +8 -6
- package/src/memory/__tests__/memory-retrospective-job.test.ts +30 -37
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +69 -66
- package/src/memory/__tests__/memory-retrospective-state.test.ts +1 -1
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +1 -1
- package/src/memory/__tests__/onboarding-events-store.test.ts +1 -1
- package/src/memory/__tests__/table-relocation.test.ts +129 -0
- package/src/memory/conversation-crud.ts +461 -152
- package/src/memory/db-async-query.ts +89 -5
- package/src/memory/db-connection.ts +101 -18
- package/src/memory/db-init.ts +409 -234
- package/src/memory/db-maintenance.ts +43 -38
- package/src/memory/db-singleton.ts +45 -19
- package/src/memory/fork-message-copy.ts +170 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +92 -0
- package/src/memory/graph/bootstrap.test.ts +6 -3
- package/src/memory/graph/retriever.test.ts +12 -12
- package/src/memory/graph/store.test.ts +15 -25
- package/src/memory/graph/store.ts +23 -14
- package/src/memory/graph/tool-handlers.ts +34 -5
- package/src/memory/graph/tools.ts +5 -2
- package/src/memory/indexer.ts +21 -9
- package/src/memory/job-handlers/cleanup.ts +10 -3
- package/src/memory/job-handlers/embedding.test.ts +4 -4
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +4 -4
- package/src/memory/jobs/embed-pkb-file.test.ts +7 -7
- package/src/memory/jobs-store.ts +36 -24
- package/src/memory/llm-request-log-store.ts +51 -19
- package/src/memory/llm-usage-store.ts +31 -1
- package/src/memory/memory-retrospective-job.ts +27 -19
- package/src/memory/memory-retrospective-startup-cleanup.ts +10 -2
- package/src/memory/migrations/{100-core-tables.ts → 000-core-tables.ts} +6 -10
- package/src/memory/migrations/104-core-indexes.ts +1 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +189 -196
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +98 -105
- package/src/memory/migrations/134-contacts-notes-column.ts +66 -69
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +19 -22
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +227 -230
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +204 -209
- package/src/memory/migrations/141-rename-verification-table.ts +45 -48
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +16 -23
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +23 -30
- package/src/memory/migrations/144-rename-voice-to-phone.ts +133 -136
- package/src/memory/migrations/145-drop-accounts-table.ts +4 -7
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +79 -82
- package/src/memory/migrations/148-drop-reminders-table.ts +3 -6
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +71 -78
- package/src/memory/migrations/157-invite-contact-id.ts +73 -76
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +44 -58
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +36 -43
- package/src/memory/migrations/174-rename-thread-starters-table.ts +30 -37
- package/src/memory/migrations/176-drop-capability-card-state.ts +17 -22
- package/src/memory/migrations/177-create-trace-events-table.ts +23 -28
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +36 -43
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +14 -21
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +17 -24
- package/src/memory/migrations/192-contacts-user-file-column.ts +6 -9
- package/src/memory/migrations/193-add-source-type-columns.ts +33 -36
- package/src/memory/migrations/194-memory-recall-logs.ts +34 -39
- package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +59 -66
- package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +41 -48
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +11 -18
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +76 -83
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +50 -57
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +6 -11
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +4 -9
- package/src/memory/migrations/217-conversation-host-access.ts +13 -18
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +86 -93
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +41 -48
- package/src/memory/migrations/230-acp-session-history.ts +23 -28
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +58 -62
- package/src/memory/migrations/232-activation-state.ts +11 -16
- package/src/memory/migrations/233-document-conversations.ts +20 -25
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +26 -31
- package/src/memory/migrations/235-slack-compaction-watermark.ts +5 -10
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +6 -11
- package/src/memory/migrations/237-heartbeat-runs.ts +22 -27
- package/src/memory/migrations/239-trace-events-created-at-index.ts +4 -9
- package/src/memory/migrations/242-message-bookmarks.ts +17 -22
- package/src/memory/migrations/245-memory-retrospective-state.ts +8 -13
- package/src/memory/migrations/249-normalize-slack-external-content.ts +37 -41
- package/src/memory/migrations/251-a2a-tasks.ts +27 -32
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +12 -17
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +10 -15
- package/src/memory/migrations/256-memory-v2-injection-events.ts +70 -74
- package/src/memory/migrations/259-conversation-cleaned-at.ts +4 -9
- package/src/memory/migrations/260-rename-cleaned-at.ts +11 -16
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +3 -8
- package/src/memory/migrations/262-memory-v3-coactivation.ts +21 -26
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +14 -19
- package/src/memory/migrations/270-schedule-description.ts +7 -12
- package/src/memory/migrations/272-acp-session-history-cwd.ts +8 -13
- package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +8 -13
- package/src/memory/migrations/297-move-llm-request-logs-to-logs-db.ts +111 -0
- package/src/memory/migrations/298-move-memory-jobs-to-memory-db.ts +128 -0
- package/src/memory/migrations/299-canonical-guardian-deliveries-conversation-index.ts +19 -0
- package/src/memory/migrations/__tests__/297-move-llm-request-logs.test.ts +180 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +333 -7
- package/src/memory/migrations/helpers/relocation.ts +227 -0
- package/src/memory/migrations/registry.ts +63 -0
- package/src/memory/migrations/run-migrations.ts +187 -16
- package/src/memory/migrations/validate-migration-state.ts +50 -145
- package/src/memory/raw-query.ts +47 -2
- package/src/memory/skill-loaded-events-store.test.ts +1 -1
- package/src/memory/task-memory-cleanup.ts +62 -41
- package/src/memory/tool-executed-events-store.test.ts +1 -1
- package/src/memory/turn-trace-store.test.ts +1 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +16 -15
- package/src/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +38 -0
- package/src/memory/v3-eval/__tests__/eval-tally.test.ts +139 -0
- package/src/memory/v3-eval/eval-packets.ts +197 -12
- package/src/memory/v3-eval/eval-tally.ts +234 -0
- package/src/messaging/provider.ts +10 -0
- package/src/messaging/providers/gmail/adapter.ts +1 -0
- package/src/messaging/providers/gmail/client.ts +14 -0
- package/src/messaging/providers/index.ts +1 -1
- package/src/messaging/providers/slack/send.test.ts +87 -39
- package/src/messaging/providers/slack/send.ts +84 -105
- package/src/notifications/README.md +9 -5
- package/src/notifications/__tests__/deterministic-checks.test.ts +43 -1
- package/src/notifications/adapters/slack.ts +12 -10
- package/src/notifications/approval-card-builder.ts +81 -20
- package/src/notifications/approval-card-data.ts +8 -5
- package/src/notifications/canonical-delivery-recorder.ts +7 -5
- package/src/notifications/conversation-candidates.ts +24 -59
- package/src/notifications/copy-composer.ts +48 -68
- package/src/notifications/deterministic-checks.ts +19 -16
- package/src/notifications/emit-signal.ts +29 -1
- package/src/notifications/trusted-contact-payloads.ts +70 -0
- package/src/oauth/byo-connection.test.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +146 -6
- package/src/oauth/connection-resolver.ts +132 -5
- package/src/oauth/oauth-store.ts +16 -3
- package/src/oauth/scope-utils.ts +21 -0
- package/src/plugin-api/index.ts +9 -4
- package/src/plugin-api/model-profiles.test.ts +123 -0
- package/src/plugin-api/model-profiles.ts +5 -1
- package/src/plugin-api/vision-support.test.ts +149 -0
- package/src/plugin-api/vision-support.ts +78 -0
- package/src/plugins/defaults/compaction/window-manager.ts +45 -64
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +302 -0
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +103 -0
- package/src/plugins/defaults/image-fallback/package.json +14 -0
- package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
- package/src/plugins/defaults/image-fallback/src/image-persist.ts +59 -0
- package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
- package/src/plugins/defaults/index.ts +23 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +14 -1
- package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
- package/src/plugins/external-plugin-loader.ts +47 -6
- package/src/plugins/mtime-cache.ts +772 -0
- package/src/plugins/pipeline.ts +7 -2
- package/src/plugins/registry.ts +16 -5
- package/src/plugins/user-loader.ts +22 -76
- package/src/prompts/persona-resolver.ts +29 -11
- package/src/prompts/system-prompt.ts +1 -1
- package/src/prompts/templates/system-sections.ts +4 -4
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
- package/src/providers/anthropic/client.ts +254 -185
- package/src/providers/call-site-routing.ts +10 -0
- package/src/providers/gemini/client.ts +43 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +6 -1
- package/src/providers/model-catalog.ts +37 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/ratelimit.ts +9 -0
- package/src/providers/retry.ts +10 -0
- package/src/providers/together/client.ts +35 -0
- package/src/providers/types.ts +16 -0
- package/src/providers/usage-tracking.ts +7 -0
- package/src/runtime/AGENTS.md +9 -1
- package/src/runtime/__tests__/agent-wake.test.ts +259 -4
- package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +417 -0
- package/src/runtime/actor-trust-resolver.ts +8 -16
- package/src/runtime/agent-wake.ts +183 -60
- package/src/runtime/channel-reply-delivery.ts +6 -3
- package/src/runtime/guardian-decision-types.ts +3 -22
- package/src/runtime/http-server.ts +1 -15
- package/src/runtime/invite-redemption-service.ts +155 -6
- package/src/runtime/invite-service.ts +113 -62
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +277 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +140 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +26 -7
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +164 -0
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +8 -8
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +1 -3
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +240 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +4 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +143 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +1 -1
- package/src/runtime/routes/acp-routes-list.test.ts +4 -0
- package/src/runtime/routes/acp-routes.test.ts +5 -6
- package/src/runtime/routes/attachment-routes.ts +21 -17
- package/src/runtime/routes/browser-routes.ts +19 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -9
- package/src/runtime/routes/channel-verification-routes.ts +12 -1
- package/src/runtime/routes/contact-routes.ts +275 -164
- package/src/runtime/routes/conversation-query-routes.ts +15 -5
- package/src/runtime/routes/conversation-routes.ts +24 -3
- package/src/runtime/routes/conversation-starter-routes.ts +7 -8
- package/src/runtime/routes/guardian-approval-interception.ts +13 -274
- package/src/runtime/routes/inbound-message-handler.ts +20 -15
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +285 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +45 -34
- package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
- package/src/runtime/routes/log-export-routes.ts +2 -2
- package/src/runtime/routes/memory-eval-routes.ts +92 -0
- package/src/runtime/routes/memory-item-routes.test.ts +12 -11
- package/src/runtime/routes/migration-routes.ts +51 -40
- package/src/runtime/routes/plugins-routes.ts +164 -8
- package/src/runtime/routes/schedule-routes.ts +1 -0
- package/src/runtime/routes/usage-routes.ts +3 -0
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/slack-block-formatting.ts +46 -48
- package/src/runtime/trust-verdict-consumer.ts +172 -0
- package/src/schedule/scheduler.ts +6 -9
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +60 -52
- package/src/tools/ask-question/ask-question-tool.ts +14 -73
- package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
- package/src/tools/browser/browser-execution.ts +16 -4
- package/src/tools/document/document-comment-tool.test.ts +1 -1
- package/src/tools/executor.ts +15 -3
- package/src/tools/host-terminal/host-shell.ts +28 -9
- package/src/tools/memory/register.test.ts +32 -0
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +4 -10
- package/src/tools/terminal/shell.ts +16 -5
- package/src/tools/types.ts +1 -0
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/memory-db-path.ts +23 -0
- package/src/watcher/providers/gmail.ts +7 -2
- package/src/workflows/engine-integration.test.ts +1 -1
- package/src/workflows/engine.test.ts +1 -1
- package/src/workflows/engine.ts +22 -0
- package/src/workflows/fanout-load.test.ts +1 -1
- package/src/workflows/journal-store.test.ts +1 -1
- package/src/workflows/leaf-runner.test.ts +40 -1
- package/src/workflows/leaf-runner.ts +26 -1
- package/src/workspace/git-service.ts +144 -29
- package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +121 -0
- package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +82 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/workspace/migrations/runner.ts +32 -2
- package/src/__tests__/access-request-decision.test.ts +0 -375
- package/src/__tests__/guardian-grant-minting.test.ts +0 -607
- package/src/__tests__/plugin-source-watcher.test.ts +0 -302
- package/src/api/events/turn-profile-auto-routed.ts +0 -28
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +0 -107
- package/src/daemon/plugin-source-watcher.ts +0 -278
- package/src/daemon/switch-inference-profile-tool.ts +0 -62
- package/src/memory/guardian-approvals.ts +0 -361
- package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +0 -66
- package/src/memory/migrations/038-actor-token-records.ts +0 -45
- package/src/memory/migrations/039-actor-refresh-token-records.ts +0 -57
- package/src/memory/migrations/103-complex-migrations.ts +0 -23
- package/src/memory/migrations/113-late-migrations.ts +0 -30
- package/src/memory/migrations/index.ts +0 -301
- package/src/runtime/routes/access-request-decision.ts +0 -297
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -963
- package/src/runtime/routes/channel-guardian-routes.ts +0 -19
- package/src/runtime/routes/guardian-expiry-sweep.ts +0 -132
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
|
|
3
|
+
import { getMemoryDbPath } from "../../util/memory-db-path.js";
|
|
4
|
+
import {
|
|
5
|
+
type DrizzleDb,
|
|
6
|
+
getMemorySqlite,
|
|
7
|
+
getSqliteFrom,
|
|
8
|
+
} from "../db-connection.js";
|
|
9
|
+
import {
|
|
10
|
+
drainStagedTable,
|
|
11
|
+
type RelocationSpec,
|
|
12
|
+
stageTableForRelocation,
|
|
13
|
+
} from "./helpers/relocation.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* How to drain `memory_jobs` from `main` into the memory DB. Only
|
|
17
|
+
* `pending`/`running` jobs are worth keeping; the terminal (`completed`/`failed`)
|
|
18
|
+
* rows that make up the bulk of a runaway queue are purged without copying.
|
|
19
|
+
*
|
|
20
|
+
* A `running` job is copied as `pending`: the worker's startup
|
|
21
|
+
* `resetRunningJobsToPending()` runs against the (empty) new table before this
|
|
22
|
+
* drain copies rows over, so a row left `running` would never be re-claimed.
|
|
23
|
+
* Resetting it here makes the relocated job re-claimable in its new home.
|
|
24
|
+
*/
|
|
25
|
+
export const MEMORY_JOBS_RELOCATION: RelocationSpec = {
|
|
26
|
+
table: "memory_jobs",
|
|
27
|
+
targetDbPath: getMemoryDbPath,
|
|
28
|
+
columns: [
|
|
29
|
+
"id",
|
|
30
|
+
"type",
|
|
31
|
+
"payload",
|
|
32
|
+
"status",
|
|
33
|
+
"attempts",
|
|
34
|
+
"deferrals",
|
|
35
|
+
"run_after",
|
|
36
|
+
"last_error",
|
|
37
|
+
"started_at",
|
|
38
|
+
"created_at",
|
|
39
|
+
"updated_at",
|
|
40
|
+
],
|
|
41
|
+
copyWhere: "status IN ('pending','running')",
|
|
42
|
+
columnExpr: {
|
|
43
|
+
status: "CASE WHEN status = 'running' THEN 'pending' ELSE status END",
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const CREATE_TABLE = /*sql*/ `
|
|
48
|
+
CREATE TABLE IF NOT EXISTS memory_jobs (
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
type TEXT NOT NULL,
|
|
51
|
+
payload TEXT NOT NULL,
|
|
52
|
+
status TEXT NOT NULL,
|
|
53
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
54
|
+
deferrals INTEGER NOT NULL DEFAULT 0,
|
|
55
|
+
run_after INTEGER NOT NULL,
|
|
56
|
+
last_error TEXT,
|
|
57
|
+
started_at INTEGER,
|
|
58
|
+
created_at INTEGER NOT NULL,
|
|
59
|
+
updated_at INTEGER NOT NULL
|
|
60
|
+
)
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create the `memory_jobs` table and its indexes on the memory connection.
|
|
65
|
+
* Idempotent (`IF NOT EXISTS`) — the dedicated connection itself performs no DDL
|
|
66
|
+
* on open, so this migration owns the schema.
|
|
67
|
+
*/
|
|
68
|
+
function ensureMemoryJobsSchema(memoryRaw: Database): void {
|
|
69
|
+
memoryRaw.exec(CREATE_TABLE);
|
|
70
|
+
createIndexes(memoryRaw);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Create the two `memory_jobs` indexes on the memory connection. */
|
|
74
|
+
function createIndexes(raw: Database) {
|
|
75
|
+
raw.exec(
|
|
76
|
+
`CREATE INDEX IF NOT EXISTS idx_memory_jobs_status_run_after ON memory_jobs(status, run_after)`,
|
|
77
|
+
);
|
|
78
|
+
raw.exec(/*sql*/ `
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_memory_jobs_conflict_resolve_dedupe
|
|
80
|
+
ON memory_jobs(
|
|
81
|
+
type,
|
|
82
|
+
status,
|
|
83
|
+
json_extract(payload, '$.messageId'),
|
|
84
|
+
COALESCE(json_extract(payload, '$.scopeId'), 'default')
|
|
85
|
+
)
|
|
86
|
+
`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Move the `memory_jobs` work queue into its own database
|
|
91
|
+
* (`assistant-memory.db`). The queue is the heaviest, highest-churn table —
|
|
92
|
+
* left in the main DB a runaway backlog bloats it (and its WAL) to many GB.
|
|
93
|
+
* Splitting it out lets the queue grow, VACUUM, and checkpoint independently.
|
|
94
|
+
* The jobs store reads/writes the queue over the dedicated memory connection
|
|
95
|
+
* (see `getMemoryDb()`).
|
|
96
|
+
*
|
|
97
|
+
* Like the `llm_request_logs` move (migration 297) this is incremental: create
|
|
98
|
+
* the table (and indexes) on the memory connection, rename any populated
|
|
99
|
+
* `main.memory_jobs` aside to `memory_jobs__relocating`, then drain it in
|
|
100
|
+
* awaited batches (see `helpers/relocation.ts`) per {@link MEMORY_JOBS_RELOCATION}.
|
|
101
|
+
*
|
|
102
|
+
* Because the drain is awaited as part of this step, the pending/running jobs
|
|
103
|
+
* are in their new home before the memory jobs worker starts later in daemon
|
|
104
|
+
* startup — the worker never observes a transiently empty queue.
|
|
105
|
+
*
|
|
106
|
+
* Throws (rather than returning) if the memory database cannot be opened, so
|
|
107
|
+
* the runner records the step as failed instead of applied and retries it on a
|
|
108
|
+
* later boot — never renaming the source aside without a target to write to,
|
|
109
|
+
* and never marking the relocation done while it has not happened. The throw is
|
|
110
|
+
* caught per-step by the runner, so startup is not aborted.
|
|
111
|
+
*/
|
|
112
|
+
export async function migrateMoveMemoryJobsToMemoryDb(
|
|
113
|
+
database: DrizzleDb,
|
|
114
|
+
): Promise<void> {
|
|
115
|
+
const memoryRaw = getMemorySqlite();
|
|
116
|
+
if (!memoryRaw) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
"memory database unavailable — deferring memory_jobs relocation",
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
ensureMemoryJobsSchema(memoryRaw);
|
|
123
|
+
|
|
124
|
+
const raw = getSqliteFrom(database);
|
|
125
|
+
const needsDrain = stageTableForRelocation(raw, MEMORY_JOBS_RELOCATION.table);
|
|
126
|
+
|
|
127
|
+
if (needsDrain) await drainStagedTable(raw, MEMORY_JOBS_RELOCATION);
|
|
128
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DrizzleDb } from "../db-connection.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Add index on canonical_guardian_deliveries(destination_conversation_id).
|
|
5
|
+
*
|
|
6
|
+
* Guardian cards record their associated internal conversation on every
|
|
7
|
+
* delivery — channel cards as well as in-app — and the conversation-scope
|
|
8
|
+
* readers (candidate enrichment, decision gate, reply-routing seed) look up
|
|
9
|
+
* pending requests by destination_conversation_id. Candidate enrichment runs on
|
|
10
|
+
* the per-notification routing path, so without this index those lookups
|
|
11
|
+
* degrade to full table scans as delivery history grows.
|
|
12
|
+
*/
|
|
13
|
+
export function migrateCanonicalGuardianDeliveriesConversationIndex(
|
|
14
|
+
database: DrizzleDb,
|
|
15
|
+
): void {
|
|
16
|
+
database.run(
|
|
17
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_deliveries_dest_conversation ON canonical_guardian_deliveries(destination_conversation_id)`,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for migration 297 — housing `llm_request_logs` in the dedicated
|
|
3
|
+
* `logs` database connection.
|
|
4
|
+
*
|
|
5
|
+
* Covers:
|
|
6
|
+
* 1. End state after a full initializeDb(): the table lives in the logs
|
|
7
|
+
* connection, not `main`, and the Drizzle store round-trips against it.
|
|
8
|
+
* 2. The relocation itself: rows in a `main.llm_request_logs` are copied into
|
|
9
|
+
* the logs connection and the main-DB copy is dropped, with indexes built
|
|
10
|
+
* in the logs connection.
|
|
11
|
+
* 3. A legacy base-only `main` table (predating the newer columns) is copied
|
|
12
|
+
* without error, NULL-filling the absent columns.
|
|
13
|
+
*
|
|
14
|
+
* The step is idempotent and not checkpoint-gated, so each test can drive it
|
|
15
|
+
* directly without clearing any checkpoint.
|
|
16
|
+
*/
|
|
17
|
+
import { describe, expect, test } from "bun:test";
|
|
18
|
+
|
|
19
|
+
const { getDb, getSqlite, getLogsSqlite } =
|
|
20
|
+
await import("../../db-connection.js");
|
|
21
|
+
const { initializeDb } = await import("../../db-init.js");
|
|
22
|
+
const { migrateMoveLlmRequestLogsToLogsDb } =
|
|
23
|
+
await import("../297-move-llm-request-logs-to-logs-db.js");
|
|
24
|
+
const { recordRequestLog, getRequestLogById } =
|
|
25
|
+
await import("../../llm-request-log-store.js");
|
|
26
|
+
|
|
27
|
+
await initializeDb();
|
|
28
|
+
|
|
29
|
+
function existsInMain(name: string): boolean {
|
|
30
|
+
return (
|
|
31
|
+
getSqlite()
|
|
32
|
+
.query(
|
|
33
|
+
`SELECT name FROM main.sqlite_master WHERE type='table' AND name = ?`,
|
|
34
|
+
)
|
|
35
|
+
.get(name) != null
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function existsInLogs(name: string): boolean {
|
|
40
|
+
return (
|
|
41
|
+
getLogsSqlite()!
|
|
42
|
+
.query(`SELECT name FROM sqlite_master WHERE type='table' AND name = ?`)
|
|
43
|
+
.get(name) != null
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function stagingExists(table: string): boolean {
|
|
48
|
+
return existsInMain(`${table}__relocating`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
describe("migration 297 — llm_request_logs lives in the logs database", () => {
|
|
52
|
+
test("after init, the table is in logs and not in main", () => {
|
|
53
|
+
expect(existsInLogs("llm_request_logs")).toBe(true);
|
|
54
|
+
expect(existsInMain("llm_request_logs")).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("the store round-trips against the relocated table", () => {
|
|
58
|
+
const id = recordRequestLog(
|
|
59
|
+
"conv-297",
|
|
60
|
+
JSON.stringify({ req: 1 }),
|
|
61
|
+
JSON.stringify({ res: 1 }),
|
|
62
|
+
"msg-297",
|
|
63
|
+
"anthropic",
|
|
64
|
+
"mainAgent",
|
|
65
|
+
);
|
|
66
|
+
const row = getRequestLogById(id);
|
|
67
|
+
expect(row?.conversationId).toBe("conv-297");
|
|
68
|
+
expect(row?.messageId).toBe("msg-297");
|
|
69
|
+
expect(row?.provider).toBe("anthropic");
|
|
70
|
+
expect(row?.callSite).toBe("mainAgent");
|
|
71
|
+
|
|
72
|
+
// The written row physically lives in the logs database.
|
|
73
|
+
const inLogs = getLogsSqlite()!
|
|
74
|
+
.query<
|
|
75
|
+
{ c: number },
|
|
76
|
+
[string]
|
|
77
|
+
>(`SELECT COUNT(*) AS c FROM llm_request_logs WHERE id = ?`)
|
|
78
|
+
.get(id);
|
|
79
|
+
expect(inLogs?.c).toBe(1);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("relocates rows from a main-DB table and drops it", async () => {
|
|
83
|
+
const sqlite = getSqlite();
|
|
84
|
+
const logs = getLogsSqlite()!;
|
|
85
|
+
|
|
86
|
+
// Simulate a populated pre-relocation main-DB table alongside the logs copy.
|
|
87
|
+
logs.exec(`DROP TABLE IF EXISTS llm_request_logs`);
|
|
88
|
+
sqlite.exec(`DROP TABLE IF EXISTS main.llm_request_logs__relocating`);
|
|
89
|
+
sqlite.exec(`
|
|
90
|
+
CREATE TABLE main.llm_request_logs (
|
|
91
|
+
id TEXT PRIMARY KEY,
|
|
92
|
+
conversation_id TEXT NOT NULL,
|
|
93
|
+
message_id TEXT,
|
|
94
|
+
provider TEXT,
|
|
95
|
+
request_payload TEXT NOT NULL,
|
|
96
|
+
response_payload TEXT NOT NULL,
|
|
97
|
+
created_at INTEGER NOT NULL,
|
|
98
|
+
agent_loop_exit_reason TEXT,
|
|
99
|
+
call_site TEXT
|
|
100
|
+
)
|
|
101
|
+
`);
|
|
102
|
+
sqlite.exec(
|
|
103
|
+
`INSERT INTO main.llm_request_logs (id, conversation_id, request_payload, response_payload, created_at, provider) VALUES ('legacy-1', 'conv-legacy', '{}', '{}', 123, 'openai')`,
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// The migration stages the populated table aside and drains it inline,
|
|
107
|
+
// copying the rows into logs and dropping the staging table before it
|
|
108
|
+
// resolves.
|
|
109
|
+
await migrateMoveLlmRequestLogsToLogsDb(getDb());
|
|
110
|
+
|
|
111
|
+
expect(existsInLogs("llm_request_logs")).toBe(true);
|
|
112
|
+
expect(existsInMain("llm_request_logs")).toBe(false);
|
|
113
|
+
expect(stagingExists("llm_request_logs")).toBe(false);
|
|
114
|
+
const moved = logs
|
|
115
|
+
.query<
|
|
116
|
+
{ conversation_id: string; provider: string },
|
|
117
|
+
[]
|
|
118
|
+
>(`SELECT conversation_id, provider FROM llm_request_logs WHERE id = 'legacy-1'`)
|
|
119
|
+
.get();
|
|
120
|
+
expect(moved?.conversation_id).toBe("conv-legacy");
|
|
121
|
+
expect(moved?.provider).toBe("openai");
|
|
122
|
+
|
|
123
|
+
// Indexes were created in the logs database.
|
|
124
|
+
const indexes = logs
|
|
125
|
+
.query<{ name: string }, []>(
|
|
126
|
+
`SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='llm_request_logs'`,
|
|
127
|
+
)
|
|
128
|
+
.all()
|
|
129
|
+
.map((r) => r.name);
|
|
130
|
+
expect(indexes).toContain("idx_llm_request_logs_message_id");
|
|
131
|
+
expect(indexes).toContain("idx_llm_request_logs_created_at");
|
|
132
|
+
expect(indexes).toContain("idx_llm_request_logs_conv_created");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("copies a legacy base-only table, NULL-filling newer columns", async () => {
|
|
136
|
+
const sqlite = getSqlite();
|
|
137
|
+
const logs = getLogsSqlite()!;
|
|
138
|
+
|
|
139
|
+
// A workspace upgrading from a build that predates the
|
|
140
|
+
// message_id/provider/agent_loop_exit_reason/call_site columns: the main
|
|
141
|
+
// table has only the original base columns.
|
|
142
|
+
logs.exec(`DROP TABLE IF EXISTS llm_request_logs`);
|
|
143
|
+
sqlite.exec(`DROP TABLE IF EXISTS main.llm_request_logs__relocating`);
|
|
144
|
+
sqlite.exec(`
|
|
145
|
+
CREATE TABLE main.llm_request_logs (
|
|
146
|
+
id TEXT PRIMARY KEY,
|
|
147
|
+
conversation_id TEXT NOT NULL,
|
|
148
|
+
request_payload TEXT NOT NULL,
|
|
149
|
+
response_payload TEXT NOT NULL,
|
|
150
|
+
created_at INTEGER NOT NULL
|
|
151
|
+
)
|
|
152
|
+
`);
|
|
153
|
+
sqlite.exec(
|
|
154
|
+
`INSERT INTO main.llm_request_logs (id, conversation_id, request_payload, response_payload, created_at) VALUES ('base-1', 'conv-base', '{}', '{}', 7)`,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Must not throw on the absent columns: the drain NULL-fills them.
|
|
158
|
+
await migrateMoveLlmRequestLogsToLogsDb(getDb());
|
|
159
|
+
|
|
160
|
+
expect(existsInLogs("llm_request_logs")).toBe(true);
|
|
161
|
+
expect(existsInMain("llm_request_logs")).toBe(false);
|
|
162
|
+
const moved = logs
|
|
163
|
+
.query<
|
|
164
|
+
{
|
|
165
|
+
conversation_id: string;
|
|
166
|
+
message_id: string | null;
|
|
167
|
+
provider: string | null;
|
|
168
|
+
call_site: string | null;
|
|
169
|
+
},
|
|
170
|
+
[]
|
|
171
|
+
>(
|
|
172
|
+
`SELECT conversation_id, message_id, provider, call_site FROM llm_request_logs WHERE id = 'base-1'`,
|
|
173
|
+
)
|
|
174
|
+
.get();
|
|
175
|
+
expect(moved?.conversation_id).toBe("conv-base");
|
|
176
|
+
expect(moved?.message_id).toBeNull();
|
|
177
|
+
expect(moved?.provider).toBeNull();
|
|
178
|
+
expect(moved?.call_site).toBeNull();
|
|
179
|
+
});
|
|
180
|
+
});
|
|
@@ -3,8 +3,13 @@ import { describe, expect, test } from "bun:test";
|
|
|
3
3
|
|
|
4
4
|
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
5
5
|
|
|
6
|
+
import { getSqliteFrom } from "../../db-connection.js";
|
|
6
7
|
import * as schema from "../../schema.js";
|
|
7
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
clearMigrationStepCheckpoints,
|
|
10
|
+
type MigrationStep,
|
|
11
|
+
runMigrationSteps,
|
|
12
|
+
} from "../run-migrations.js";
|
|
8
13
|
|
|
9
14
|
function createTestDb() {
|
|
10
15
|
const sqlite = new Database(":memory:");
|
|
@@ -14,10 +19,7 @@ function createTestDb() {
|
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
describe("runMigrationSteps — checkpointing", () => {
|
|
17
|
-
|
|
18
|
-
// current behavior, which re-runs every forward step on every boot. Promote
|
|
19
|
-
// to `test` when true checkpointing of initial migrations lands.
|
|
20
|
-
test.skip("does not re-execute a step that was already applied on a prior run", () => {
|
|
22
|
+
test("does not re-execute a step that was already applied on a prior run", async () => {
|
|
21
23
|
/**
|
|
22
24
|
* Booting an already-migrated database must not re-run forward migration
|
|
23
25
|
* steps. With true checkpointing each step's body executes at most once
|
|
@@ -41,12 +43,336 @@ describe("runMigrationSteps — checkpointing", () => {
|
|
|
41
43
|
|
|
42
44
|
// AND a database that has already been migrated once
|
|
43
45
|
const db = createTestDb();
|
|
44
|
-
runMigrationSteps(db, steps);
|
|
46
|
+
await runMigrationSteps(db, steps);
|
|
45
47
|
|
|
46
48
|
// WHEN the same steps run again against the already-migrated database
|
|
47
|
-
runMigrationSteps(db, steps);
|
|
49
|
+
await runMigrationSteps(db, steps);
|
|
48
50
|
|
|
49
51
|
// THEN no step body executes a second time
|
|
50
52
|
expect(calls).toEqual({ a: 1, b: 1, c: 1 });
|
|
51
53
|
});
|
|
54
|
+
|
|
55
|
+
test("records step completions in the shared memory_checkpoints ledger", async () => {
|
|
56
|
+
/**
|
|
57
|
+
* Step bookkeeping lives in the same memory_checkpoints table the registry
|
|
58
|
+
* uses, under the `step:` namespace — one ledger for all applied state.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
// GIVEN a single named step
|
|
62
|
+
const db = createTestDb();
|
|
63
|
+
await runMigrationSteps(db, [
|
|
64
|
+
function dummyMigrationA() {
|
|
65
|
+
// no-op
|
|
66
|
+
},
|
|
67
|
+
]);
|
|
68
|
+
|
|
69
|
+
// THEN its completion is recorded under the step: namespace in memory_checkpoints
|
|
70
|
+
const row = getSqliteFrom(db)
|
|
71
|
+
.query(
|
|
72
|
+
`SELECT value FROM memory_checkpoints WHERE key = 'step:dummyMigrationA'`,
|
|
73
|
+
)
|
|
74
|
+
.get() as { value: string } | null;
|
|
75
|
+
expect(row?.value).toBe("1");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("runs a newly appended step on a later boot while skipping applied ones", async () => {
|
|
79
|
+
/**
|
|
80
|
+
* Checkpointing must not block migrations added in a later release: an
|
|
81
|
+
* already-applied step is skipped, but a brand-new step still runs.
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
// GIVEN a database already migrated with two steps
|
|
85
|
+
const calls = { a: 0, b: 0, c: 0 };
|
|
86
|
+
const stepA: MigrationStep = function dummyMigrationA() {
|
|
87
|
+
calls.a++;
|
|
88
|
+
};
|
|
89
|
+
const stepB: MigrationStep = function dummyMigrationB() {
|
|
90
|
+
calls.b++;
|
|
91
|
+
};
|
|
92
|
+
const db = createTestDb();
|
|
93
|
+
await runMigrationSteps(db, [stepA, stepB]);
|
|
94
|
+
|
|
95
|
+
// AND a third step appended to the list
|
|
96
|
+
const stepC: MigrationStep = function dummyMigrationC() {
|
|
97
|
+
calls.c++;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// WHEN the expanded list runs against the already-migrated database
|
|
101
|
+
await runMigrationSteps(db, [stepA, stepB, stepC]);
|
|
102
|
+
|
|
103
|
+
// THEN only the newly appended step executes
|
|
104
|
+
expect(calls).toEqual({ a: 1, b: 1, c: 1 });
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("recovers crashed migrations before running steps", async () => {
|
|
108
|
+
/**
|
|
109
|
+
* runMigrationSteps clears stalled `started`/`rolling_back` checkpoints
|
|
110
|
+
* before the loop so a migration interrupted mid-flight re-runs this boot.
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
// GIVEN a database with a stalled registry checkpoint left by a crash
|
|
114
|
+
const db = createTestDb();
|
|
115
|
+
const raw = getSqliteFrom(db);
|
|
116
|
+
raw.run(
|
|
117
|
+
`CREATE TABLE IF NOT EXISTS memory_checkpoints (key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at INTEGER NOT NULL)`,
|
|
118
|
+
);
|
|
119
|
+
raw.run(
|
|
120
|
+
`INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_stalled_v1', 'started', 0)`,
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// WHEN the runner executes
|
|
124
|
+
await runMigrationSteps(db, [
|
|
125
|
+
function dummyMigrationA() {
|
|
126
|
+
// no-op
|
|
127
|
+
},
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
// THEN the stalled checkpoint has been cleared so its migration can re-run
|
|
131
|
+
const row = raw
|
|
132
|
+
.query(
|
|
133
|
+
`SELECT 1 FROM memory_checkpoints WHERE key = 'migration_stalled_v1'`,
|
|
134
|
+
)
|
|
135
|
+
.get();
|
|
136
|
+
expect(row).toBeNull();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("does not checkpoint a failed step so it retries on the next boot", async () => {
|
|
140
|
+
/**
|
|
141
|
+
* A step whose body throws is reported in `failed` and left uncheckpointed,
|
|
142
|
+
* so the next boot retries it instead of silently skipping it.
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
// GIVEN a step that throws on its first run and succeeds afterwards
|
|
146
|
+
const calls = { flaky: 0 };
|
|
147
|
+
const steps: MigrationStep[] = [
|
|
148
|
+
function flakyStep() {
|
|
149
|
+
calls.flaky++;
|
|
150
|
+
if (calls.flaky === 1) {
|
|
151
|
+
throw new Error("transient failure");
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
const db = createTestDb();
|
|
156
|
+
const first = await runMigrationSteps(db, steps);
|
|
157
|
+
|
|
158
|
+
// AND the first run reports the failure
|
|
159
|
+
expect(first.failed).toEqual(["flakyStep"]);
|
|
160
|
+
|
|
161
|
+
// WHEN the step runs again on the next boot
|
|
162
|
+
const second = await runMigrationSteps(db, steps);
|
|
163
|
+
|
|
164
|
+
// THEN it retries, succeeds, and is then checkpointed
|
|
165
|
+
expect(calls.flaky).toBe(2);
|
|
166
|
+
expect(second.failed).toEqual([]);
|
|
167
|
+
expect((await runMigrationSteps(db, steps)).skipped).toEqual(["flakyStep"]);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("clearMigrationStepCheckpoints forces every step to re-run", async () => {
|
|
171
|
+
/**
|
|
172
|
+
* Clearing the step namespace (as rollback does) makes the next run
|
|
173
|
+
* re-execute and re-record all steps.
|
|
174
|
+
*/
|
|
175
|
+
|
|
176
|
+
// GIVEN a database migrated once
|
|
177
|
+
const calls = { a: 0 };
|
|
178
|
+
const steps: MigrationStep[] = [
|
|
179
|
+
function dummyMigrationA() {
|
|
180
|
+
calls.a++;
|
|
181
|
+
},
|
|
182
|
+
];
|
|
183
|
+
const db = createTestDb();
|
|
184
|
+
await runMigrationSteps(db, steps);
|
|
185
|
+
expect(calls.a).toBe(1);
|
|
186
|
+
|
|
187
|
+
// WHEN the step checkpoints are cleared
|
|
188
|
+
clearMigrationStepCheckpoints(db);
|
|
189
|
+
|
|
190
|
+
// THEN the next run re-executes the step
|
|
191
|
+
await runMigrationSteps(db, steps);
|
|
192
|
+
expect(calls.a).toBe(2);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test("awaits an async step to completion before running or checkpointing the next", async () => {
|
|
196
|
+
/**
|
|
197
|
+
* An async step must be fully drained before the runner advances: ordering
|
|
198
|
+
* is the invariant later migrations rely on (step N+1 may assume N's result
|
|
199
|
+
* is true), and the step is checkpointed only after its promise resolves so
|
|
200
|
+
* a crash mid-drain leaves it uncheckpointed and retryable rather than
|
|
201
|
+
* recorded as done.
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
// GIVEN an async step that records its completion order only after yielding,
|
|
205
|
+
// followed by a sync step that records when it starts
|
|
206
|
+
const order: string[] = [];
|
|
207
|
+
const steps: MigrationStep[] = [
|
|
208
|
+
async function asyncDrainStep() {
|
|
209
|
+
await Promise.resolve();
|
|
210
|
+
order.push("async-done");
|
|
211
|
+
},
|
|
212
|
+
function followingStep() {
|
|
213
|
+
order.push("following-start");
|
|
214
|
+
},
|
|
215
|
+
];
|
|
216
|
+
const db = createTestDb();
|
|
217
|
+
|
|
218
|
+
// WHEN the runner executes both steps
|
|
219
|
+
const result = await runMigrationSteps(db, steps);
|
|
220
|
+
|
|
221
|
+
// THEN the async step finishes before the next step starts
|
|
222
|
+
expect(order).toEqual(["async-done", "following-start"]);
|
|
223
|
+
|
|
224
|
+
// AND both steps are checkpointed, so a later boot skips them
|
|
225
|
+
expect(result.failed).toEqual([]);
|
|
226
|
+
expect((await runMigrationSteps(db, steps)).skipped).toEqual([
|
|
227
|
+
"asyncDrainStep",
|
|
228
|
+
"followingStep",
|
|
229
|
+
]);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test("a rejected async step is reported failed and left uncheckpointed", async () => {
|
|
233
|
+
/**
|
|
234
|
+
* A step whose promise rejects must be treated exactly like a synchronous
|
|
235
|
+
* throw: reported in `failed`, not checkpointed, and retried next boot.
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
// GIVEN an async step that rejects on its first run and resolves afterwards
|
|
239
|
+
const calls = { flaky: 0 };
|
|
240
|
+
const steps: MigrationStep[] = [
|
|
241
|
+
async function flakyAsyncStep() {
|
|
242
|
+
calls.flaky++;
|
|
243
|
+
await Promise.resolve();
|
|
244
|
+
if (calls.flaky === 1) {
|
|
245
|
+
throw new Error("transient async failure");
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
];
|
|
249
|
+
const db = createTestDb();
|
|
250
|
+
|
|
251
|
+
// WHEN it runs and rejects
|
|
252
|
+
const first = await runMigrationSteps(db, steps);
|
|
253
|
+
|
|
254
|
+
// THEN the rejection is reported and the step is not checkpointed
|
|
255
|
+
expect(first.failed).toEqual(["flakyAsyncStep"]);
|
|
256
|
+
|
|
257
|
+
// WHEN it runs again on the next boot
|
|
258
|
+
const second = await runMigrationSteps(db, steps);
|
|
259
|
+
|
|
260
|
+
// THEN it retries, resolves, and is then checkpointed
|
|
261
|
+
expect(calls.flaky).toBe(2);
|
|
262
|
+
expect(second.failed).toEqual([]);
|
|
263
|
+
expect((await runMigrationSteps(db, steps)).skipped).toEqual([
|
|
264
|
+
"flakyAsyncStep",
|
|
265
|
+
]);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("detects and recovers step-level 'started' markers from a prior crash", async () => {
|
|
269
|
+
/**
|
|
270
|
+
* If the process crashes mid-step, the runner leaves a `step:<name>` =
|
|
271
|
+
* 'started' checkpoint. On the next boot, recoverCrashedMigrations
|
|
272
|
+
* detects it, clears it, and the step re-runs.
|
|
273
|
+
*/
|
|
274
|
+
|
|
275
|
+
// GIVEN a database with a stalled step: checkpoint left by a crash
|
|
276
|
+
const db = createTestDb();
|
|
277
|
+
const raw = getSqliteFrom(db);
|
|
278
|
+
raw.run(
|
|
279
|
+
`CREATE TABLE IF NOT EXISTS memory_checkpoints (key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at INTEGER NOT NULL)`,
|
|
280
|
+
);
|
|
281
|
+
raw.run(
|
|
282
|
+
`INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('step:crashedStep', 'started', 0)`,
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
let ran = false;
|
|
286
|
+
const steps: MigrationStep[] = [
|
|
287
|
+
function crashedStep() {
|
|
288
|
+
ran = true;
|
|
289
|
+
},
|
|
290
|
+
];
|
|
291
|
+
|
|
292
|
+
// WHEN the runner executes — recoverCrashedMigrations should clear
|
|
293
|
+
// the 'started' marker and let the step run.
|
|
294
|
+
await runMigrationSteps(db, steps);
|
|
295
|
+
|
|
296
|
+
// THEN the stalled checkpoint was cleared and the step ran
|
|
297
|
+
expect(ran).toBe(true);
|
|
298
|
+
const stalled = raw
|
|
299
|
+
.query(
|
|
300
|
+
`SELECT 1 FROM memory_checkpoints WHERE key = 'step:crashedStep' AND value = 'started'`,
|
|
301
|
+
)
|
|
302
|
+
.get();
|
|
303
|
+
expect(stalled).toBeNull();
|
|
304
|
+
// And the step was checkpointed as '1' (completed)
|
|
305
|
+
const completed = raw
|
|
306
|
+
.query(
|
|
307
|
+
`SELECT 1 FROM memory_checkpoints WHERE key = 'step:crashedStep' AND value = '1'`,
|
|
308
|
+
)
|
|
309
|
+
.get();
|
|
310
|
+
expect(completed).not.toBeNull();
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test("does not skip a step whose only checkpoint is 'started' (not '1')", async () => {
|
|
314
|
+
/**
|
|
315
|
+
* The skip query filters for value = '1', so a 'started' marker
|
|
316
|
+
* alone must not cause a step to be skipped — the step should run.
|
|
317
|
+
* (recoverCrashedMigrations clears 'started' markers first, but
|
|
318
|
+
* even if it didn't, the skip logic is independent and correct.)
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
const db = createTestDb();
|
|
322
|
+
const raw = getSqliteFrom(db);
|
|
323
|
+
raw.run(
|
|
324
|
+
`CREATE TABLE IF NOT EXISTS memory_checkpoints (key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at INTEGER NOT NULL)`,
|
|
325
|
+
);
|
|
326
|
+
// Insert a 'started' marker without running recoverCrashedMigrations.
|
|
327
|
+
// We simulate this by inserting directly and checking the applied set.
|
|
328
|
+
raw.run(
|
|
329
|
+
`INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('step:someStep', 'started', 0)`,
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
let ran = false;
|
|
333
|
+
const steps: MigrationStep[] = [
|
|
334
|
+
function someStep() {
|
|
335
|
+
ran = true;
|
|
336
|
+
},
|
|
337
|
+
];
|
|
338
|
+
|
|
339
|
+
// WHEN the runner executes, recoverCrashedMigrations clears the
|
|
340
|
+
// 'started' marker, so the step is not in the applied set and runs.
|
|
341
|
+
const result = await runMigrationSteps(db, steps);
|
|
342
|
+
|
|
343
|
+
// THEN the step ran (was not skipped)
|
|
344
|
+
expect(ran).toBe(true);
|
|
345
|
+
expect(result.applied).toEqual(["someStep"]);
|
|
346
|
+
expect(result.skipped).toEqual([]);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
test("writes 'started' marker before running each step", async () => {
|
|
350
|
+
const db = createTestDb();
|
|
351
|
+
const raw = getSqliteFrom(db);
|
|
352
|
+
|
|
353
|
+
const seen: { marker: string | null } = { marker: null };
|
|
354
|
+
const steps: MigrationStep[] = [
|
|
355
|
+
async function asyncWithInspection() {
|
|
356
|
+
const row = raw
|
|
357
|
+
.query<{ value: string }, []>(
|
|
358
|
+
`SELECT value FROM memory_checkpoints WHERE key = 'step:asyncWithInspection'`,
|
|
359
|
+
)
|
|
360
|
+
.get();
|
|
361
|
+
seen.marker = row?.value ?? null;
|
|
362
|
+
await Promise.resolve();
|
|
363
|
+
},
|
|
364
|
+
];
|
|
365
|
+
|
|
366
|
+
await runMigrationSteps(db, steps);
|
|
367
|
+
|
|
368
|
+
// The 'started' marker was visible during the async step's execution
|
|
369
|
+
expect(seen.marker).toBe("started");
|
|
370
|
+
|
|
371
|
+
const final = raw
|
|
372
|
+
.query<{ value: string }, []>(
|
|
373
|
+
`SELECT value FROM memory_checkpoints WHERE key = 'step:asyncWithInspection'`,
|
|
374
|
+
)
|
|
375
|
+
.get();
|
|
376
|
+
expect(final?.value).toBe("1");
|
|
377
|
+
});
|
|
52
378
|
});
|