@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
|
@@ -58,11 +58,10 @@ async function runDbMaintenance(): Promise<void> {
|
|
|
58
58
|
);
|
|
59
59
|
|
|
60
60
|
// Prune finished workflow runs (and their journals) past the retention
|
|
61
|
-
// window
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
// whole routine to an idle window.
|
|
61
|
+
// window. This is a fast bounded DELETE on the small workflow tables, so it
|
|
62
|
+
// runs on the main connection (`rawRun`). SQLite reuses the pages it frees
|
|
63
|
+
// for later writes — we deliberately do not VACUUM to hand them back to the
|
|
64
|
+
// OS (see the WAL note below).
|
|
66
65
|
try {
|
|
67
66
|
const deletedRuns = pruneRuns(getConfig().workflows.journalRetentionDays);
|
|
68
67
|
if (deletedRuns > 0) {
|
|
@@ -72,18 +71,9 @@ async function runDbMaintenance(): Promise<void> {
|
|
|
72
71
|
log.warn({ err }, "Workflow run pruning failed (non-fatal)");
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
// backend is available.
|
|
79
|
-
const vacuumResult = await runAsyncSqlite("VACUUM");
|
|
80
|
-
if (!vacuumResult.ok) {
|
|
81
|
-
log.warn(
|
|
82
|
-
{ error: vacuumResult.error, backend: vacuumResult.backend },
|
|
83
|
-
"VACUUM failed (non-fatal)",
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
74
|
+
// Refresh the query planner's statistics. PRAGMA optimize is cheap; it is
|
|
75
|
+
// routed through the async path for consistency and to keep it off the main
|
|
76
|
+
// thread when the sqlite3 CLI backend is available.
|
|
87
77
|
const optimizeResult = await runAsyncSqlite("PRAGMA optimize");
|
|
88
78
|
if (!optimizeResult.ok) {
|
|
89
79
|
log.warn(
|
|
@@ -92,26 +82,42 @@ async function runDbMaintenance(): Promise<void> {
|
|
|
92
82
|
);
|
|
93
83
|
}
|
|
94
84
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
// Truncate the WAL so it doesn't sit at its high-water mark. We intentionally
|
|
86
|
+
// do NOT run a full VACUUM: in WAL mode VACUUM rewrites the whole database
|
|
87
|
+
// through the WAL, inflating it to ~the database size and needing up to 2x the
|
|
88
|
+
// DB size in free disk to finish. SQLite already reuses freed pages for new
|
|
89
|
+
// writes, so eager space return isn't worth that cost on a multi-GB database.
|
|
90
|
+
//
|
|
91
|
+
// The checkpoint goes through the async path (sqlite3 subprocess when one is
|
|
92
|
+
// available) for the same reason VACUUM/optimize do: a synchronous
|
|
93
|
+
// wal_checkpoint(TRUNCATE) on the shared connection blocks the event loop
|
|
94
|
+
// while it checkpoints frames and waits out readers — the health/IPC stall
|
|
95
|
+
// runAsyncSqlite exists to avoid. A checkpoint from a separate connection
|
|
96
|
+
// still truncates the shared WAL; if a reader holds it back it's a
|
|
97
|
+
// best-effort no-op and the next maintenance pass retries.
|
|
98
|
+
const checkpointResult = await runAsyncSqlite(
|
|
99
|
+
"PRAGMA wal_checkpoint(TRUNCATE)",
|
|
100
|
+
);
|
|
101
|
+
if (!checkpointResult.ok) {
|
|
102
|
+
log.warn(
|
|
103
|
+
{ error: checkpointResult.error, backend: checkpointResult.backend },
|
|
104
|
+
"WAL checkpoint failed (non-fatal)",
|
|
105
|
+
);
|
|
106
|
+
}
|
|
101
107
|
|
|
108
|
+
const after = getDbStats();
|
|
102
109
|
log.info(
|
|
103
110
|
{
|
|
104
|
-
backend: vacuumResult.backend,
|
|
105
|
-
vacuumOk: vacuumResult.ok,
|
|
106
111
|
optimizeOk: optimizeResult.ok,
|
|
107
|
-
|
|
112
|
+
optimizeBackend: optimizeResult.backend,
|
|
108
113
|
optimizeElapsedMs: optimizeResult.elapsedMs,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
checkpointOk: checkpointResult.ok,
|
|
115
|
+
checkpointBackend: checkpointResult.backend,
|
|
116
|
+
checkpointResult: checkpointResult.stdout?.trim(),
|
|
117
|
+
checkpointElapsedMs: checkpointResult.elapsedMs,
|
|
118
|
+
pageCount: after.pageCount,
|
|
119
|
+
freelistCount: after.freelistCount,
|
|
120
|
+
fileSizeBytes: after.fileSizeBytes,
|
|
115
121
|
},
|
|
116
122
|
"Database maintenance complete",
|
|
117
123
|
);
|
|
@@ -126,12 +132,11 @@ export async function maybeRunDbMaintenance(nowMs = Date.now()): Promise<void> {
|
|
|
126
132
|
);
|
|
127
133
|
if (nowMs - lastRun < intervalMs) return;
|
|
128
134
|
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
// deferred run is simply retried on a later (still-idle) worker tick.
|
|
135
|
+
// Maintenance still takes brief write locks (PRAGMA optimize and the
|
|
136
|
+
// truncating WAL checkpoint), so defer it until the user has been quiet for
|
|
137
|
+
// `quietPeriodMs` and those locks never land mid-conversation. The checkpoint
|
|
138
|
+
// below is only written once maintenance actually runs, so a deferred run is
|
|
139
|
+
// simply retried on a later (still-idle) worker tick.
|
|
135
140
|
if (quietPeriodMs > 0) {
|
|
136
141
|
const lastUserMessageAt = getLastUserMessageTimestamp();
|
|
137
142
|
if (lastUserMessageAt > 0 && nowMs - lastUserMessageAt < quietPeriodMs) {
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Holds the assistant DB connection
|
|
2
|
+
* Holds the assistant DB connection singletons and their close callbacks.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Three connections live here under the same `globalThis.vellumAssistant`
|
|
5
|
+
* namespace, keyed by slot: the `main` daemon connection, the `logs`
|
|
6
|
+
* connection (`assistant-logs.db`), and the `memory` connection
|
|
7
|
+
* (`assistant-memory.db`). Each is opened lazily by `db-connection.ts`.
|
|
8
|
+
*
|
|
9
|
+
* Lives in its own module (rather than alongside the resolvers in
|
|
10
|
+
* `db-connection.ts`) so test code can reset the singletons without
|
|
6
11
|
* importing `db-connection.ts` — which transitively pulls
|
|
7
12
|
* `drizzle-orm/bun-sqlite`. Stdlib-only by design: this file must remain
|
|
8
13
|
* safe to import from the test preload's load-time chain, where a broken
|
|
9
14
|
* `node_modules` symlink has historically tripped the env override
|
|
10
15
|
* (see DB ghost #3, /workspace/journal/2026-05-25-db-ghost-3-recovery.md).
|
|
11
16
|
*
|
|
12
|
-
* State is held on `globalThis.vellumAssistant.
|
|
17
|
+
* State is held on `globalThis.vellumAssistant.dbSingletons` so test
|
|
13
18
|
* helpers in `__tests__/` can read/write it WITHOUT importing this
|
|
14
19
|
* module — they declare the same slot shape locally and access the
|
|
15
20
|
* globalThis namespace directly. See
|
|
@@ -21,50 +26,71 @@
|
|
|
21
26
|
* parameter on `getStoredDb<DrizzleDb>()`.
|
|
22
27
|
*
|
|
23
28
|
* Consumers:
|
|
24
|
-
* - `db-connection.ts` (opens/owns the
|
|
25
|
-
* - production callers that need to close the active
|
|
29
|
+
* - `db-connection.ts` (opens/owns the connections)
|
|
30
|
+
* - production callers that need to close the active connections
|
|
26
31
|
* (migration routes, vbundle import, backup/restore, daemon shutdown)
|
|
27
32
|
* - `__tests__/db-test-helpers.ts` (per-test reset, via globalThis)
|
|
28
33
|
*/
|
|
29
34
|
|
|
35
|
+
/** Which connection a slot holds. */
|
|
36
|
+
export type DbSlotKey = "main" | "logs" | "memory";
|
|
37
|
+
|
|
30
38
|
type DbSlot = {
|
|
31
39
|
db: unknown;
|
|
32
40
|
closer: (() => void) | null;
|
|
33
41
|
};
|
|
34
42
|
|
|
43
|
+
type DbSlots = Record<DbSlotKey, DbSlot>;
|
|
44
|
+
|
|
35
45
|
type VellumAssistantNamespace = {
|
|
36
|
-
|
|
46
|
+
dbSingletons?: DbSlots;
|
|
37
47
|
};
|
|
38
48
|
|
|
39
|
-
function
|
|
49
|
+
function emptySlot(): DbSlot {
|
|
50
|
+
return { db: null, closer: null };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function slots(): DbSlots {
|
|
40
54
|
const g = globalThis as { vellumAssistant?: VellumAssistantNamespace };
|
|
41
55
|
const ns = (g.vellumAssistant ??= {});
|
|
42
|
-
return (ns.
|
|
56
|
+
return (ns.dbSingletons ??= {
|
|
57
|
+
main: emptySlot(),
|
|
58
|
+
logs: emptySlot(),
|
|
59
|
+
memory: emptySlot(),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function slot(key: DbSlotKey): DbSlot {
|
|
64
|
+
return slots()[key];
|
|
43
65
|
}
|
|
44
66
|
|
|
45
|
-
/** Read the current singleton
|
|
46
|
-
export function getStoredDb<T>(): T | null {
|
|
47
|
-
return slot().db as T | null;
|
|
67
|
+
/** Read the current singleton for `key`, narrowed to `T`. `null` means not yet opened. */
|
|
68
|
+
export function getStoredDb<T>(key: DbSlotKey): T | null {
|
|
69
|
+
return slot(key).db as T | null;
|
|
48
70
|
}
|
|
49
71
|
|
|
50
72
|
/**
|
|
51
73
|
* Store a freshly-opened connection and the closer to run on
|
|
52
|
-
* `clearStoredDb()`. The closer must be self-contained — it is invoked
|
|
74
|
+
* `clearStoredDb(key)`. The closer must be self-contained — it is invoked
|
|
53
75
|
* inside a try/catch, so partial failures are swallowed (best-effort
|
|
54
76
|
* close on shutdown / restore paths).
|
|
55
77
|
*/
|
|
56
|
-
export function setStoredDb<T>(
|
|
57
|
-
|
|
78
|
+
export function setStoredDb<T>(
|
|
79
|
+
key: DbSlotKey,
|
|
80
|
+
newDb: T,
|
|
81
|
+
close: () => void,
|
|
82
|
+
): void {
|
|
83
|
+
const s = slot(key);
|
|
58
84
|
s.db = newDb;
|
|
59
85
|
s.closer = close;
|
|
60
86
|
}
|
|
61
87
|
|
|
62
88
|
/**
|
|
63
|
-
* Close the active connection (if any) via the stored closer,
|
|
64
|
-
* both. Idempotent: safe to call when no connection is stored.
|
|
89
|
+
* Close the active connection for `key` (if any) via the stored closer,
|
|
90
|
+
* then drop both. Idempotent: safe to call when no connection is stored.
|
|
65
91
|
*/
|
|
66
|
-
export function clearStoredDb(): void {
|
|
67
|
-
const s = slot();
|
|
92
|
+
export function clearStoredDb(key: DbSlotKey): void {
|
|
93
|
+
const s = slot(key);
|
|
68
94
|
if (s.closer) {
|
|
69
95
|
try {
|
|
70
96
|
s.closer();
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Fork message-copy — off-event-loop bulk copy of a conversation's messages.
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// The fork-based memory retrospective copies the entire source conversation's
|
|
6
|
+
// message rows into a throwaway background conversation. Done in-process via
|
|
7
|
+
// `bun:sqlite` (synchronous), that copy is the single longest uninterruptible
|
|
8
|
+
// block on the daemon's event loop — on a multi-GB database it pegs the CPU
|
|
9
|
+
// for minutes, stalling `/healthz` and the gateway's IPC calls (see the
|
|
10
|
+
// runtime-freeze investigation).
|
|
11
|
+
//
|
|
12
|
+
// This module moves the message-row copy off the event loop via
|
|
13
|
+
// {@link runAsyncSqlite}, which runs the statements in a `sqlite3` CLI
|
|
14
|
+
// subprocess (its own connection; SQLite file-locking arbitrates with the
|
|
15
|
+
// in-process handle). The content/metadata never round-trip through JS — they
|
|
16
|
+
// are copied SELECT→INSERT inside SQLite — so there is no string-escaping
|
|
17
|
+
// hazard and the heavy bytes stay in the database.
|
|
18
|
+
//
|
|
19
|
+
// Two properties matter for correctness:
|
|
20
|
+
//
|
|
21
|
+
// 1. **Lock-friendly batching.** The main connection runs `busy_timeout=5000`
|
|
22
|
+
// (`db-connection.ts`). A single `INSERT … SELECT` over the whole history
|
|
23
|
+
// is one implicit transaction that holds the write lock for its full
|
|
24
|
+
// duration — a concurrent in-process write (a live user turn persisting a
|
|
25
|
+
// message) would then block up to 5 s and throw `SQLITE_BUSY`. So the copy
|
|
26
|
+
// is split into batches that each auto-commit, releasing the lock between
|
|
27
|
+
// batches so in-process writers slip in.
|
|
28
|
+
//
|
|
29
|
+
// 2. **`cloneForkMessageMetadata` parity.** The in-process fork stamps
|
|
30
|
+
// `forkSourceMessageId` onto each copied row's metadata. The SQL `CASE`
|
|
31
|
+
// below is a faithful translation of that helper's three branches
|
|
32
|
+
// (object → preserve-or-stamp; null/non-object/invalid → fresh object).
|
|
33
|
+
// `client_message_id` is intentionally NOT copied, matching the
|
|
34
|
+
// in-process fork (a forked row is not a client-submitted message).
|
|
35
|
+
|
|
36
|
+
import { type AsyncSqliteResult, runAsyncSqlite } from "./db-async-query.js";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Default batch size for the chunked copy. Each batch is one `INSERT … SELECT`
|
|
40
|
+
* that auto-commits, so this bounds how long the subprocess holds the write
|
|
41
|
+
* lock before releasing it to in-process writers. Small enough to keep the
|
|
42
|
+
* lock-hold window short on a bloated database; large enough that per-batch
|
|
43
|
+
* statement overhead stays negligible against the row copy.
|
|
44
|
+
*/
|
|
45
|
+
export const DEFAULT_FORK_COPY_BATCH_SIZE = 500;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* A single source→fork message-id mapping. `oldId` is an existing source
|
|
49
|
+
* message id; `newId` is the freshly-generated id the fork row will carry.
|
|
50
|
+
* Generated by the caller (in JS) so the same map drives both this copy and
|
|
51
|
+
* the in-process attachment relink that follows.
|
|
52
|
+
*/
|
|
53
|
+
export interface ForkIdPair {
|
|
54
|
+
oldId: string;
|
|
55
|
+
newId: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface CopyForkMessagesOptions {
|
|
59
|
+
/** The fork conversation id every copied row is assigned to. */
|
|
60
|
+
forkConversationId: string;
|
|
61
|
+
/** Ordered source→fork id pairs for every message to copy. */
|
|
62
|
+
idPairs: readonly ForkIdPair[];
|
|
63
|
+
/** Override the per-batch row count (see {@link DEFAULT_FORK_COPY_BATCH_SIZE}). */
|
|
64
|
+
batchSize?: number;
|
|
65
|
+
/** Test-only passthrough to force the in-process backend. */
|
|
66
|
+
forceInProcess?: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Server-generated ids only ever use this charset. We interpolate ids (never
|
|
70
|
+
// message content) into the SQL script, so reject anything outside it as a
|
|
71
|
+
// defense-in-depth guard against a malformed id breaking out of the literal.
|
|
72
|
+
const SAFE_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
73
|
+
|
|
74
|
+
function assertSafeId(id: string): void {
|
|
75
|
+
if (!SAFE_ID.test(id)) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`fork message-copy: unsafe id literal: ${JSON.stringify(id)}`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* SQL translation of `cloneForkMessageMetadata`. `m` is the source `messages`
|
|
84
|
+
* row alias; the stamped value is the SOURCE message id (`m.id`), preserving an
|
|
85
|
+
* existing `forkSourceMessageId` when the metadata is already an object.
|
|
86
|
+
*/
|
|
87
|
+
const METADATA_CLONE_EXPR = `CASE
|
|
88
|
+
WHEN json_valid(m.metadata) AND json_type(m.metadata) = 'object'
|
|
89
|
+
THEN json_set(m.metadata, '$.forkSourceMessageId',
|
|
90
|
+
coalesce(json_extract(m.metadata, '$.forkSourceMessageId'), m.id))
|
|
91
|
+
ELSE json_object('forkSourceMessageId', m.id)
|
|
92
|
+
END`;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Build the multi-statement SQL script that copies the given id pairs into the
|
|
96
|
+
* fork conversation in lock-friendly batches. Exported for unit testing the
|
|
97
|
+
* generated SQL without spawning a subprocess.
|
|
98
|
+
*/
|
|
99
|
+
export function buildForkCopyScript(options: CopyForkMessagesOptions): string {
|
|
100
|
+
const { forkConversationId, idPairs } = options;
|
|
101
|
+
assertSafeId(forkConversationId);
|
|
102
|
+
const batchSize = Math.max(
|
|
103
|
+
1,
|
|
104
|
+
options.batchSize ?? DEFAULT_FORK_COPY_BATCH_SIZE,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const statements: string[] = [
|
|
108
|
+
// Connection-scoped staging table holding the current batch's id map. The
|
|
109
|
+
// unqualified `messages` reference in the SELECT resolves to the main DB.
|
|
110
|
+
`CREATE TEMP TABLE IF NOT EXISTS _fork_id_map (old_id TEXT PRIMARY KEY, new_id TEXT NOT NULL);`,
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
for (let i = 0; i < idPairs.length; i += batchSize) {
|
|
114
|
+
const batch = idPairs.slice(i, i + batchSize);
|
|
115
|
+
const values = batch
|
|
116
|
+
.map(({ oldId, newId }) => {
|
|
117
|
+
assertSafeId(oldId);
|
|
118
|
+
assertSafeId(newId);
|
|
119
|
+
return `('${oldId}','${newId}')`;
|
|
120
|
+
})
|
|
121
|
+
.join(",");
|
|
122
|
+
|
|
123
|
+
// Each batch auto-commits (no surrounding BEGIN), so the write lock is
|
|
124
|
+
// released between batches for in-process writers.
|
|
125
|
+
statements.push(`DELETE FROM _fork_id_map;`);
|
|
126
|
+
statements.push(
|
|
127
|
+
`INSERT INTO _fork_id_map (old_id, new_id) VALUES ${values};`,
|
|
128
|
+
);
|
|
129
|
+
statements.push(
|
|
130
|
+
`INSERT INTO messages (id, conversation_id, role, content, created_at, metadata)
|
|
131
|
+
SELECT map.new_id, '${forkConversationId}', m.role, m.content, m.created_at, ${METADATA_CLONE_EXPR}
|
|
132
|
+
FROM messages m JOIN _fork_id_map map ON map.old_id = m.id;`,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Drop the staging table so the in-process fallback (which runs on the shared
|
|
137
|
+
// daemon connection) does not leave it lingering; harmless for the subprocess
|
|
138
|
+
// backend, whose connection is discarded on exit.
|
|
139
|
+
statements.push(`DROP TABLE IF EXISTS _fork_id_map;`);
|
|
140
|
+
|
|
141
|
+
return statements.join("\n");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Copy the message rows for a fork off the event loop, in lock-friendly
|
|
146
|
+
* batches. Resolves once every batch has committed (or rejects via the
|
|
147
|
+
* returned result's `ok: false` on subprocess failure — the caller is
|
|
148
|
+
* responsible for cleaning up the partially-built fork).
|
|
149
|
+
*
|
|
150
|
+
* No-op (returns a synthetic ok result) when there is nothing to copy.
|
|
151
|
+
*/
|
|
152
|
+
export async function copyForkMessagesViaSubprocess(
|
|
153
|
+
options: CopyForkMessagesOptions,
|
|
154
|
+
): Promise<AsyncSqliteResult> {
|
|
155
|
+
if (options.idPairs.length === 0) {
|
|
156
|
+
return {
|
|
157
|
+
ok: true,
|
|
158
|
+
backend: "in-process-blocking",
|
|
159
|
+
error: null,
|
|
160
|
+
elapsedMs: 0,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const sql = buildForkCopyScript(options);
|
|
165
|
+
return runAsyncSqlite(sql, {
|
|
166
|
+
...(options.forceInProcess
|
|
167
|
+
? { forceBackend: "in-process-blocking" as const }
|
|
168
|
+
: {}),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
@@ -227,3 +227,95 @@ describe("handleRemember — memory.v2.enabled off (v1 PKB path)", () => {
|
|
|
227
227
|
}
|
|
228
228
|
});
|
|
229
229
|
});
|
|
230
|
+
|
|
231
|
+
describe("handleRemember — batch (array) content", () => {
|
|
232
|
+
test("v2: writes every fact from an array in a single call", () => {
|
|
233
|
+
const result = handleRemember(
|
|
234
|
+
{ content: ["fact one", "fact two", "fact three"] },
|
|
235
|
+
"conv-batch-1",
|
|
236
|
+
"default",
|
|
237
|
+
CONFIG,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
expect(result.success).toBe(true);
|
|
241
|
+
expect(result.message).toContain("3");
|
|
242
|
+
|
|
243
|
+
const memoryDir = join(tmpWorkspace, "memory");
|
|
244
|
+
const buffer = readFileSync(join(memoryDir, "buffer.md"), "utf-8");
|
|
245
|
+
expect(buffer).toContain("fact one");
|
|
246
|
+
expect(buffer).toContain("fact two");
|
|
247
|
+
expect(buffer).toContain("fact three");
|
|
248
|
+
// Three independent timestamped bullets from the one call.
|
|
249
|
+
expect(buffer.match(/^- /gm)?.length).toBe(3);
|
|
250
|
+
|
|
251
|
+
const archive = readFileSync(
|
|
252
|
+
join(memoryDir, "archive", todaysArchiveBasename()),
|
|
253
|
+
"utf-8",
|
|
254
|
+
);
|
|
255
|
+
expect(archive).toContain("fact one");
|
|
256
|
+
expect(archive).toContain("fact three");
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test("v1: a batched call still enqueues exactly two re-index jobs (per file, not per fact)", () => {
|
|
260
|
+
const result = handleRemember(
|
|
261
|
+
{ content: ["alpha", "beta", "gamma"] },
|
|
262
|
+
"conv-batch-2",
|
|
263
|
+
"default",
|
|
264
|
+
CONFIG_V2_OFF,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
expect(result.success).toBe(true);
|
|
268
|
+
|
|
269
|
+
const pkbDir = join(tmpWorkspace, "pkb");
|
|
270
|
+
const buffer = readFileSync(join(pkbDir, "buffer.md"), "utf-8");
|
|
271
|
+
expect(buffer).toContain("alpha");
|
|
272
|
+
expect(buffer).toContain("beta");
|
|
273
|
+
expect(buffer).toContain("gamma");
|
|
274
|
+
expect(buffer.match(/^- /gm)?.length).toBe(3);
|
|
275
|
+
|
|
276
|
+
// One enqueue per written file (buffer + archive), regardless of fact count.
|
|
277
|
+
expect(enqueueCalls).toHaveLength(2);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test("drops blank entries and rejects an all-empty array", () => {
|
|
281
|
+
const ok = handleRemember(
|
|
282
|
+
{ content: [" ", "kept fact", ""] },
|
|
283
|
+
"conv-batch-3",
|
|
284
|
+
"default",
|
|
285
|
+
CONFIG,
|
|
286
|
+
);
|
|
287
|
+
expect(ok.success).toBe(true);
|
|
288
|
+
const buffer = readFileSync(
|
|
289
|
+
join(tmpWorkspace, "memory", "buffer.md"),
|
|
290
|
+
"utf-8",
|
|
291
|
+
);
|
|
292
|
+
expect(buffer).toContain("kept fact");
|
|
293
|
+
expect(buffer.match(/^- /gm)?.length).toBe(1);
|
|
294
|
+
|
|
295
|
+
const empty = handleRemember(
|
|
296
|
+
{ content: [" ", ""] },
|
|
297
|
+
"conv-batch-4",
|
|
298
|
+
"default",
|
|
299
|
+
CONFIG,
|
|
300
|
+
);
|
|
301
|
+
expect(empty.success).toBe(false);
|
|
302
|
+
expect(empty.message).toContain("content is required");
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
test("single-string content still records exactly one fact", () => {
|
|
306
|
+
const result = handleRemember(
|
|
307
|
+
{ content: "lone fact" },
|
|
308
|
+
"conv-batch-5",
|
|
309
|
+
"default",
|
|
310
|
+
CONFIG,
|
|
311
|
+
);
|
|
312
|
+
expect(result.success).toBe(true);
|
|
313
|
+
expect(result.message).toBe("Saved to knowledge base.");
|
|
314
|
+
const buffer = readFileSync(
|
|
315
|
+
join(tmpWorkspace, "memory", "buffer.md"),
|
|
316
|
+
"utf-8",
|
|
317
|
+
);
|
|
318
|
+
expect(buffer).toContain("lone fact");
|
|
319
|
+
expect(buffer.match(/^- /gm)?.length).toBe(1);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import { setMemoryCheckpoint } from "../checkpoints.js";
|
|
4
|
+
import { getMemoryDb } from "../db-connection.js";
|
|
4
5
|
import { initializeDb } from "../db-init.js";
|
|
5
6
|
import { rawAll, rawGet, rawRun, resetTestTables } from "../raw-query.js";
|
|
6
7
|
import { migrateToolCreatedItems } from "./bootstrap.js";
|
|
@@ -15,13 +16,15 @@ const MIGRATE_ITEMS_CHECKPOINT = "graph_bootstrap:migrated_tool_items";
|
|
|
15
16
|
// Setup
|
|
16
17
|
// ---------------------------------------------------------------------------
|
|
17
18
|
|
|
18
|
-
beforeAll(() => {
|
|
19
|
-
initializeDb();
|
|
19
|
+
beforeAll(async () => {
|
|
20
|
+
await initializeDb();
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
beforeEach(() => {
|
|
23
24
|
// Clear graph nodes and checkpoints between tests so each test starts clean.
|
|
24
|
-
|
|
25
|
+
// memory_jobs lives in the dedicated memory connection; the rest in main.
|
|
26
|
+
resetTestTables("memory_graph_nodes", "memory_checkpoints");
|
|
27
|
+
getMemoryDb()!.run("DELETE FROM memory_jobs");
|
|
25
28
|
});
|
|
26
29
|
|
|
27
30
|
// ---------------------------------------------------------------------------
|
|
@@ -124,18 +124,18 @@ function makeCapabilityNode(content: string, capId: string): NewNode {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
describe("loadContextMemory — query/sparse vector surfacing", () => {
|
|
127
|
-
beforeAll(() => {
|
|
128
|
-
initializeDb();
|
|
127
|
+
beforeAll(async () => {
|
|
128
|
+
await initializeDb();
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
beforeEach(() => {
|
|
131
|
+
beforeEach(async () => {
|
|
132
132
|
embedShouldThrow = false;
|
|
133
133
|
embedVector = [0.1, 0.2, 0.3];
|
|
134
134
|
embedCallCount = 0;
|
|
135
135
|
embedRouter = null;
|
|
136
136
|
searchRouter = null;
|
|
137
137
|
resetDbForTesting();
|
|
138
|
-
initializeDb();
|
|
138
|
+
await initializeDb();
|
|
139
139
|
});
|
|
140
140
|
|
|
141
141
|
test("returns the dense queryVector when embedding succeeds", async () => {
|
|
@@ -180,18 +180,18 @@ describe("loadContextMemory — query/sparse vector surfacing", () => {
|
|
|
180
180
|
});
|
|
181
181
|
|
|
182
182
|
describe("retrieveForTurn — query/sparse vector surfacing", () => {
|
|
183
|
-
beforeAll(() => {
|
|
184
|
-
initializeDb();
|
|
183
|
+
beforeAll(async () => {
|
|
184
|
+
await initializeDb();
|
|
185
185
|
});
|
|
186
186
|
|
|
187
|
-
beforeEach(() => {
|
|
187
|
+
beforeEach(async () => {
|
|
188
188
|
embedShouldThrow = false;
|
|
189
189
|
embedVector = [0.1, 0.2, 0.3];
|
|
190
190
|
embedCallCount = 0;
|
|
191
191
|
embedRouter = null;
|
|
192
192
|
searchRouter = null;
|
|
193
193
|
resetDbForTesting();
|
|
194
|
-
initializeDb();
|
|
194
|
+
await initializeDb();
|
|
195
195
|
});
|
|
196
196
|
|
|
197
197
|
test("returns the dense queryVector when embedding succeeds", async () => {
|
|
@@ -309,8 +309,8 @@ describe("retrieveForTurn — topic-pivot recovery", () => {
|
|
|
309
309
|
};
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
-
beforeAll(() => {
|
|
313
|
-
initializeDb();
|
|
312
|
+
beforeAll(async () => {
|
|
313
|
+
await initializeDb();
|
|
314
314
|
});
|
|
315
315
|
|
|
316
316
|
beforeEach(() => {
|
|
@@ -458,8 +458,8 @@ describe("loadContextMemory — dual-query capability ranking", () => {
|
|
|
458
458
|
return [];
|
|
459
459
|
}
|
|
460
460
|
|
|
461
|
-
beforeAll(() => {
|
|
462
|
-
initializeDb();
|
|
461
|
+
beforeAll(async () => {
|
|
462
|
+
await initializeDb();
|
|
463
463
|
});
|
|
464
464
|
|
|
465
465
|
beforeEach(() => {
|
|
@@ -61,8 +61,8 @@ function makeNewNode(overrides: Partial<NewNode> = {}): NewNode {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
beforeAll(() => {
|
|
65
|
-
initializeDb();
|
|
64
|
+
beforeAll(async () => {
|
|
65
|
+
await initializeDb();
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
beforeEach(() => {
|
|
@@ -259,12 +259,8 @@ describe("queryNodes", () => {
|
|
|
259
259
|
});
|
|
260
260
|
|
|
261
261
|
test("filters by eventDateAfter", () => {
|
|
262
|
-
createNode(
|
|
263
|
-
|
|
264
|
-
);
|
|
265
|
-
createNode(
|
|
266
|
-
makeNewNode({ content: "Recent.", eventDate: 1710000000000 }),
|
|
267
|
-
);
|
|
262
|
+
createNode(makeNewNode({ content: "Old.", eventDate: 1700000000000 }));
|
|
263
|
+
createNode(makeNewNode({ content: "Recent.", eventDate: 1710000000000 }));
|
|
268
264
|
createNode(makeNewNode({ content: "None.", eventDate: null }));
|
|
269
265
|
|
|
270
266
|
const results = queryNodes({ eventDateAfter: 1705000000000 });
|
|
@@ -273,12 +269,8 @@ describe("queryNodes", () => {
|
|
|
273
269
|
});
|
|
274
270
|
|
|
275
271
|
test("filters by eventDateBefore", () => {
|
|
276
|
-
createNode(
|
|
277
|
-
|
|
278
|
-
);
|
|
279
|
-
createNode(
|
|
280
|
-
makeNewNode({ content: "Recent.", eventDate: 1710000000000 }),
|
|
281
|
-
);
|
|
272
|
+
createNode(makeNewNode({ content: "Old.", eventDate: 1700000000000 }));
|
|
273
|
+
createNode(makeNewNode({ content: "Recent.", eventDate: 1710000000000 }));
|
|
282
274
|
createNode(makeNewNode({ content: "None.", eventDate: null }));
|
|
283
275
|
|
|
284
276
|
const results = queryNodes({ eventDateBefore: 1705000000000 });
|
|
@@ -287,15 +279,9 @@ describe("queryNodes", () => {
|
|
|
287
279
|
});
|
|
288
280
|
|
|
289
281
|
test("combines eventDateAfter and eventDateBefore for range query", () => {
|
|
290
|
-
createNode(
|
|
291
|
-
|
|
292
|
-
);
|
|
293
|
-
createNode(
|
|
294
|
-
makeNewNode({ content: "In range.", eventDate: 1700000000000 }),
|
|
295
|
-
);
|
|
296
|
-
createNode(
|
|
297
|
-
makeNewNode({ content: "After.", eventDate: 1720000000000 }),
|
|
298
|
-
);
|
|
282
|
+
createNode(makeNewNode({ content: "Before.", eventDate: 1690000000000 }));
|
|
283
|
+
createNode(makeNewNode({ content: "In range.", eventDate: 1700000000000 }));
|
|
284
|
+
createNode(makeNewNode({ content: "After.", eventDate: 1720000000000 }));
|
|
299
285
|
|
|
300
286
|
const results = queryNodes({
|
|
301
287
|
eventDateAfter: 1695000000000,
|
|
@@ -687,7 +673,9 @@ describe("supersedeNode", () => {
|
|
|
687
673
|
|
|
688
674
|
test("inherits eventDate from old node when new node has null eventDate", () => {
|
|
689
675
|
const eventDate = 1712534400000; // April 8 2024
|
|
690
|
-
const old = createNode(
|
|
676
|
+
const old = createNode(
|
|
677
|
+
makeNewNode({ content: "Dentist April 8.", eventDate }),
|
|
678
|
+
);
|
|
691
679
|
const newNodeInput = makeNewNode({
|
|
692
680
|
content: "Dentist appointment rescheduled.",
|
|
693
681
|
eventDate: null,
|
|
@@ -699,7 +687,9 @@ describe("supersedeNode", () => {
|
|
|
699
687
|
});
|
|
700
688
|
|
|
701
689
|
test("uses new node eventDate when both nodes have eventDate", () => {
|
|
702
|
-
const old = createNode(
|
|
690
|
+
const old = createNode(
|
|
691
|
+
makeNewNode({ content: "Flight Tuesday.", eventDate: 1712534400000 }),
|
|
692
|
+
);
|
|
703
693
|
const newEventDate = 1712620800000;
|
|
704
694
|
const newNodeInput = makeNewNode({
|
|
705
695
|
content: "Flight moved to Thursday.",
|