@vellumai/assistant 0.10.0 → 0.10.1-dev.202606240317.ea25efe
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 +12 -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__/guardian-delivery-contract.test.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +96 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +28 -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 +95 -0
- package/openapi.yaml +458 -18
- package/package.json +2 -1
- package/scripts/memory-inspect.ts +24 -14
- package/scripts/test.sh +36 -15
- 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 +39 -17
- 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 +210 -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 +20 -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__/card-surface-data.test.ts +60 -0
- 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 +291 -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 +188 -52
- package/src/__tests__/config-schema.test.ts +35 -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 +7 -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 +95 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +12 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +12 -0
- 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 +4 -4
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +352 -0
- package/src/__tests__/conversation-sync-tags.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
- 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 +28 -8
- package/src/__tests__/disk-pressure-guard.test.ts +41 -0
- 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__/dynamic-page-surface.test.ts +0 -94
- package/src/__tests__/edit-propagation.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +93 -5
- package/src/__tests__/empty-response-hook.test.ts +42 -0
- package/src/__tests__/events-client-registration.test.ts +1 -1
- package/src/__tests__/events-dev-bypass-actor.test.ts +7 -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 +76 -11
- 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 +96 -2
- package/src/__tests__/guardian-outbound-http.test.ts +20 -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 +92 -0
- package/src/__tests__/host-app-control-routes.test.ts +24 -30
- package/src/__tests__/host-bash-routes.test.ts +31 -41
- package/src/__tests__/host-browser-routes.test.ts +26 -32
- package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
- package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
- package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
- package/src/__tests__/http-conversation-lineage.test.ts +1 -1
- package/src/__tests__/http-user-message-parity.test.ts +165 -8
- 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-normalization.test.ts +105 -0
- 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-resolver.test.ts +205 -5
- package/src/__tests__/llm-usage-store.test.ts +65 -1
- package/src/__tests__/log-export-routes.test.ts +1 -1
- package/src/__tests__/log-export-workspace.test.ts +3 -3
- package/src/__tests__/media-stream-server-integration.test.ts +127 -0
- 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 +190 -19
- package/src/__tests__/notification-broadcaster.test.ts +4 -0
- package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
- package/src/__tests__/notification-deep-link.test.ts +4 -0
- package/src/__tests__/notification-guardian-path.test.ts +20 -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__/pending-interactions-resolved-event.test.ts +7 -4
- 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 +40 -1
- package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/registry.test.ts +3 -0
- package/src/__tests__/relay-server.test.ts +1026 -73
- package/src/__tests__/runtime-attachment-metadata.test.ts +9 -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-ingress-http.test.ts +12 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +31 -9
- 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__/skills.test.ts +44 -0
- package/src/__tests__/slack-inbound-verification.test.ts +48 -5
- 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__/sse-actor-principal-guardian-source.test.ts +102 -0
- package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
- package/src/__tests__/stt-hints.test.ts +44 -13
- package/src/__tests__/subagent-detail.test.ts +27 -0
- package/src/__tests__/subagent-disposal.test.ts +65 -0
- 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 +37 -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 +98 -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/__tests__/workspace-tool-loader.test.ts +3 -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-exclusive-tool.test.ts +150 -0
- package/src/agent/loop.ts +101 -27
- package/src/api/constants/sse-replay.ts +41 -0
- package/src/api/events/ui-surface-show.ts +8 -3
- package/src/api/index.ts +7 -6
- package/src/api/responses/conversation-message.ts +4 -0
- package/src/api/responses/llm-request-log-entry.ts +25 -0
- package/src/api/responses/subagent-detail.ts +17 -0
- package/src/api/surfaces.ts +33 -0
- 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 +349 -65
- package/src/calls/guardian-dispatch.ts +10 -8
- package/src/calls/inbound-trust-reader.ts +56 -0
- package/src/calls/media-stream-server.ts +21 -0
- package/src/calls/relay-server.ts +231 -72
- package/src/calls/relay-setup-router.ts +57 -13
- package/src/calls/relay-verification.ts +7 -7
- package/src/calls/stt-hints.ts +9 -12
- package/src/calls/twilio-routes.ts +13 -3
- package/src/cli/commands/__tests__/cache.test.ts +8 -1
- package/src/cli/commands/cache.ts +194 -181
- 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/mcp.ts +252 -218
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
- package/src/cli/commands/memory/__tests__/worker.test.ts +302 -0
- package/src/cli/commands/memory/index.ts +4 -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/memory/worker.ts +175 -0
- package/src/cli/commands/plugins.ts +343 -14
- package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
- 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/list-installed-plugins.ts +179 -1
- 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__/loader-callsite-strip-fallback.test.ts +143 -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/llm-resolver.ts +151 -14
- package/src/config/loader.ts +36 -5
- package/src/config/profile-dispatchability.ts +11 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -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 +17 -3
- package/src/config/schemas/memory-v3.ts +7 -0
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/timeouts.ts +32 -0
- package/src/config/seed-inference-profiles.ts +147 -50
- package/src/config/skills.ts +27 -5
- package/src/config/sync-gated-profiles.ts +13 -1
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
- package/src/contacts/contact-store.ts +21 -0
- package/src/contacts/contacts-write.ts +3 -0
- package/src/contacts/guardian-delivery-reader.ts +223 -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 +18 -36
- package/src/daemon/conversation-process.ts +35 -16
- package/src/daemon/conversation-runtime-assembly.ts +91 -66
- package/src/daemon/conversation-surfaces.ts +273 -18
- package/src/daemon/conversation-tool-setup.ts +24 -64
- package/src/daemon/conversation.ts +149 -53
- package/src/daemon/disk-pressure-guard.ts +12 -2
- 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 +41 -27
- package/src/daemon/handlers/conversations.ts +84 -0
- package/src/daemon/handlers/shared.ts +7 -0
- package/src/daemon/lifecycle.ts +44 -5
- package/src/daemon/memory-v2-startup.test.ts +72 -0
- package/src/daemon/memory-v2-startup.ts +87 -19
- 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 +12 -11
- package/src/daemon/server.ts +0 -4
- package/src/daemon/shutdown-handlers.ts +20 -0
- package/src/daemon/tool-setup-types.ts +7 -5
- 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__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
- package/src/ipc/assistant-server.ts +10 -2
- 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__/prompt-override.test.ts +192 -0
- 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/embedding-gemini.test.ts +3 -1
- package/src/memory/embedding-gemini.ts +18 -2
- 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 +79 -21
- 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/014-backfill-inbox-thread-state.ts +13 -3
- 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 +241 -219
- 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 +135 -68
- 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__/014-backfill-inbox-thread-state.test.ts +108 -0
- package/src/memory/migrations/__tests__/136-drop-assistant-id-columns.test.ts +82 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +224 -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/schema-introspection.ts +14 -0
- package/src/memory/migrations/validate-migration-state.ts +50 -145
- package/src/memory/prompt-override.ts +129 -0
- 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__/cli-command-store.test.ts +25 -0
- 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__/skill-store.test.ts +80 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
- package/src/memory/v2/cli-command-store.ts +75 -38
- package/src/memory/v2/prompts/consolidation.ts +13 -82
- package/src/memory/v2/prompts/router.ts +21 -93
- package/src/memory/v2/skill-store.ts +68 -31
- 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/memory/worker-control.ts +118 -0
- package/src/memory/worker-process.ts +72 -0
- package/src/messaging/provider.ts +10 -0
- package/src/messaging/providers/gmail/adapter.ts +1 -0
- package/src/messaging/providers/gmail/client.ts +13 -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__/broadcaster.test.ts +16 -8
- package/src/notifications/__tests__/connected-channels.test.ts +114 -0
- package/src/notifications/__tests__/decision-engine.test.ts +78 -9
- package/src/notifications/__tests__/destination-resolver.test.ts +256 -0
- 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/broadcaster.ts +8 -1
- 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/decision-engine.ts +15 -7
- package/src/notifications/destination-resolver.ts +68 -24
- package/src/notifications/deterministic-checks.ts +19 -16
- package/src/notifications/emit-signal.ts +68 -15
- 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 +174 -6
- package/src/oauth/connection-resolver.ts +132 -5
- package/src/oauth/oauth-store.ts +16 -3
- package/src/oauth/scope-utils.ts +39 -0
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +7 -4
- 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 +173 -0
- package/src/plugin-api/vision-support.ts +113 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +90 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +106 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +60 -0
- package/src/plugins/defaults/advisor/consult.ts +65 -6
- package/src/plugins/defaults/advisor/context-pack.ts +288 -0
- package/src/plugins/defaults/advisor/steering.ts +14 -2
- package/src/plugins/defaults/advisor/tools/advisor.ts +32 -5
- 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 +441 -0
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +57 -0
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +61 -0
- package/src/plugins/defaults/image-fallback/package.json +14 -0
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +108 -0
- package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
- package/src/plugins/defaults/image-fallback/src/image-persist.ts +56 -0
- package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
- package/src/plugins/defaults/index.ts +27 -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/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +134 -5
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +246 -19
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +8 -1
- 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 +290 -185
- package/src/providers/call-site-routing.ts +14 -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 +53 -0
- package/src/providers/openai/responses-provider.ts +5 -0
- package/src/providers/openrouter/client.ts +5 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/provider-send-message.ts +4 -0
- package/src/providers/ratelimit.ts +13 -0
- package/src/providers/retry.ts +14 -0
- package/src/providers/together/client.ts +35 -0
- package/src/providers/types.ts +25 -0
- package/src/providers/usage-tracking.ts +11 -0
- package/src/runtime/AGENTS.md +9 -1
- package/src/runtime/__tests__/agent-wake.test.ts +259 -4
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +181 -0
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +64 -0
- package/src/runtime/__tests__/local-principal-trust.test.ts +164 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +670 -0
- package/src/runtime/access-request-helper.ts +19 -39
- package/src/runtime/actor-trust-resolver.ts +8 -16
- package/src/runtime/agent-wake.ts +183 -60
- package/src/runtime/anchored-guardian.test.ts +156 -0
- package/src/runtime/anchored-guardian.ts +135 -0
- package/src/runtime/assistant-stream-state.ts +9 -2
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
- package/src/runtime/auth/require-bound-guardian.ts +21 -11
- package/src/runtime/channel-reply-delivery.ts +6 -3
- package/src/runtime/channel-verification-service.ts +24 -0
- package/src/runtime/guardian-decision-types.ts +3 -22
- package/src/runtime/guardian-vellum-migration.ts +66 -7
- 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/local-actor-identity.ts +76 -11
- package/src/runtime/local-principal-trust.ts +52 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
- package/src/runtime/pending-interactions.ts +11 -1
- 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/__tests__/surface-action-routes.test.ts +163 -0
- 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 +13 -2
- 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 +80 -66
- package/src/runtime/routes/conversation-starter-routes.ts +7 -8
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/guardian-approval-interception.ts +13 -274
- package/src/runtime/routes/host-app-control-routes.ts +5 -4
- package/src/runtime/routes/host-bash-routes.ts +5 -4
- package/src/runtime/routes/host-browser-routes.ts +9 -11
- package/src/runtime/routes/host-cu-routes.ts +5 -4
- package/src/runtime/routes/host-file-routes.ts +5 -4
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/inbound-message-handler.ts +21 -16
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +376 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +86 -64
- package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +16 -4
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
- package/src/runtime/routes/llm-context-normalization.ts +71 -0
- package/src/runtime/routes/log-export-routes.ts +2 -2
- package/src/runtime/routes/mcp-auth-routes.ts +38 -15
- 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/subagents-routes.ts +5 -0
- package/src/runtime/routes/surface-action-routes.ts +39 -51
- 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 +210 -0
- package/src/schedule/scheduler.ts +6 -9
- package/src/signals/user-message.ts +16 -0
- package/src/subagent/manager.ts +9 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +89 -52
- package/src/tools/ask-question/ask-question-tool.ts +27 -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/tool-defaults.ts +2 -0
- package/src/tools/types.ts +18 -2
- package/src/tools/ui-surface/definitions.ts +0 -43
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/log-redact.ts +2 -4
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/memory-db-path.ts +23 -0
- package/src/util/platform.ts +5 -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
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* - conversation-usage.ts — recordUsage
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import type { AgentLoopConfig
|
|
18
|
+
import type { AgentLoopConfig } from "../agent/loop.js";
|
|
19
19
|
import { AgentLoop } from "../agent/loop.js";
|
|
20
20
|
import type { AssistantActivityStateEvent } from "../api/events/assistant-activity-state.js";
|
|
21
21
|
import type {
|
|
@@ -91,7 +91,7 @@ import {
|
|
|
91
91
|
isActivationMomentParam,
|
|
92
92
|
} from "../telemetry/activation-funnel.js";
|
|
93
93
|
import { ToolExecutor } from "../tools/executor.js";
|
|
94
|
-
import { getAllToolDefinitions } from "../tools/registry.js";
|
|
94
|
+
import { getAllToolDefinitions, getTool } from "../tools/registry.js";
|
|
95
95
|
import type { ToolLifecycleEvent } from "../tools/types.js";
|
|
96
96
|
import type { OnboardingContext } from "../types/onboarding-context.js";
|
|
97
97
|
import type { AbortReason } from "../util/abort-reasons.js";
|
|
@@ -296,7 +296,7 @@ export class Conversation {
|
|
|
296
296
|
outputTokens: 0,
|
|
297
297
|
estimatedCost: 0,
|
|
298
298
|
};
|
|
299
|
-
/** @internal */
|
|
299
|
+
/** @internal */ systemPrompt: string;
|
|
300
300
|
/** @internal */ contextCompactedMessageCount = 0;
|
|
301
301
|
/** @internal */ contextCompactedAt: number | null = null;
|
|
302
302
|
/** @internal */ contextSummary: string | null = null;
|
|
@@ -376,7 +376,7 @@ export class Conversation {
|
|
|
376
376
|
*/
|
|
377
377
|
wakePersonaOverride?: SystemPromptPersonaOverride;
|
|
378
378
|
/** @internal */ currentTurnOverrideProfile?: string;
|
|
379
|
-
/** @internal */
|
|
379
|
+
/** @internal */ currentTurnIsNonInteractive?: boolean;
|
|
380
380
|
/** @internal */ authContext?: AuthContext;
|
|
381
381
|
/** @internal */ currentTurnAuthContext?: AuthContext;
|
|
382
382
|
/** @internal */ currentTurnSourceActorPrincipalId?: string;
|
|
@@ -537,6 +537,7 @@ export class Conversation {
|
|
|
537
537
|
};
|
|
538
538
|
public readonly traceEmitter: TraceEmitter;
|
|
539
539
|
/** @internal */ hasSystemPromptOverride: boolean;
|
|
540
|
+
/** @internal */ modelOverride: string | undefined;
|
|
540
541
|
/** @internal */ readonly graphMemory: ConversationGraphMemory;
|
|
541
542
|
/** @internal */ activeContextNodeIds?: string[];
|
|
542
543
|
/** @internal */ streamThinking: boolean;
|
|
@@ -666,34 +667,9 @@ export class Conversation {
|
|
|
666
667
|
const hasSystemPromptOverride = systemPrompt !== buildSystemPrompt();
|
|
667
668
|
this.hasSystemPromptOverride = hasSystemPromptOverride;
|
|
668
669
|
|
|
669
|
-
//
|
|
670
|
-
//
|
|
671
|
-
|
|
672
|
-
const resolvedModel: string | undefined = modelOverride;
|
|
673
|
-
|
|
674
|
-
const resolveSystemPromptCallback = (
|
|
675
|
-
_history: Message[],
|
|
676
|
-
): ResolvedSystemPrompt => {
|
|
677
|
-
const resolved: ResolvedSystemPrompt = {
|
|
678
|
-
systemPrompt: this.hasSystemPromptOverride
|
|
679
|
-
? systemPrompt
|
|
680
|
-
: buildSystemPrompt({
|
|
681
|
-
hasNoClient: this.hasNoClient,
|
|
682
|
-
trustContext: this.currentTurnTrustContext,
|
|
683
|
-
channelCapabilities: this.currentTurnChannelCapabilities,
|
|
684
|
-
personaOverride: this.wakePersonaOverride,
|
|
685
|
-
onboardingContext: this.getOnboardingContext(),
|
|
686
|
-
conversationId: this.conversationId,
|
|
687
|
-
}),
|
|
688
|
-
};
|
|
689
|
-
if (configuredMaxTokens !== undefined) {
|
|
690
|
-
resolved.maxTokens = configuredMaxTokens;
|
|
691
|
-
}
|
|
692
|
-
if (resolvedModel !== undefined) {
|
|
693
|
-
resolved.model = resolvedModel;
|
|
694
|
-
}
|
|
695
|
-
return resolved;
|
|
696
|
-
};
|
|
670
|
+
// Store the model override for per-run resolution. The loop receives it
|
|
671
|
+
// as a top-level `model` param on `run()`.
|
|
672
|
+
this.modelOverride = modelOverride;
|
|
697
673
|
|
|
698
674
|
const fastModeEnabled = isAssistantFeatureFlagEnabled("fast-mode", config);
|
|
699
675
|
const resolvedSpeed = speedOverride ?? resolvedMainAgent.speed;
|
|
@@ -726,7 +702,9 @@ export class Conversation {
|
|
|
726
702
|
tools: toolDefs.length > 0 ? toolDefs : undefined,
|
|
727
703
|
toolExecutor: toolDefs.length > 0 ? toolExecutor : undefined,
|
|
728
704
|
resolveTools,
|
|
729
|
-
|
|
705
|
+
// A tool the registry marks exclusive (e.g. `advisor`) runs alone in its
|
|
706
|
+
// turn; the loop defers any sibling calls until the next turn.
|
|
707
|
+
isExclusiveTool: (name) => getTool(name)?.exclusive === true,
|
|
730
708
|
resolveConversationDir: () => {
|
|
731
709
|
const conv = getConversation(this.conversationId);
|
|
732
710
|
if (!conv) return null;
|
|
@@ -738,7 +716,6 @@ export class Conversation {
|
|
|
738
716
|
});
|
|
739
717
|
createContextWindowManager({
|
|
740
718
|
provider,
|
|
741
|
-
systemPrompt: () => resolveSystemPromptCallback([]).systemPrompt,
|
|
742
719
|
config: initialContextWindowConfig,
|
|
743
720
|
toolTokenBudget: this.agentLoop.getToolTokenBudget(),
|
|
744
721
|
conversationId: this.conversationId,
|
|
@@ -799,6 +776,29 @@ export class Conversation {
|
|
|
799
776
|
this.inferenceProfileExpiresAt = state.expiresAt;
|
|
800
777
|
}
|
|
801
778
|
|
|
779
|
+
/**
|
|
780
|
+
* Build the system prompt for the current conversation state. When a
|
|
781
|
+
* system-prompt override was supplied at construction, use it as-is;
|
|
782
|
+
* otherwise rebuild the full prompt (picks up workspace file changes,
|
|
783
|
+
* live trust/channel context, persona overrides, onboarding context).
|
|
784
|
+
*
|
|
785
|
+
* Called by the caller before invoking `agentLoop.run()` — the loop
|
|
786
|
+
* itself never re-resolves the prompt mid-loop (re-resolving would bust
|
|
787
|
+
* the provider's prefix cache).
|
|
788
|
+
*/
|
|
789
|
+
buildCurrentSystemPrompt(): string {
|
|
790
|
+
return this.hasSystemPromptOverride
|
|
791
|
+
? this.systemPrompt
|
|
792
|
+
: buildSystemPrompt({
|
|
793
|
+
hasNoClient: this.hasNoClient,
|
|
794
|
+
trustContext: this.currentTurnTrustContext,
|
|
795
|
+
channelCapabilities: this.currentTurnChannelCapabilities,
|
|
796
|
+
personaOverride: this.wakePersonaOverride,
|
|
797
|
+
onboardingContext: this.getOnboardingContext(),
|
|
798
|
+
conversationId: this.conversationId,
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
|
|
802
802
|
// ── Prompt Cache Warming ─────────────────────────────────────────
|
|
803
803
|
|
|
804
804
|
/**
|
|
@@ -811,16 +811,7 @@ export class Conversation {
|
|
|
811
811
|
const abort = new AbortController();
|
|
812
812
|
this.cacheWarmAbort = abort;
|
|
813
813
|
|
|
814
|
-
const systemPrompt = this.
|
|
815
|
-
? this.systemPrompt
|
|
816
|
-
: buildSystemPrompt({
|
|
817
|
-
hasNoClient: this.hasNoClient,
|
|
818
|
-
trustContext: this.currentTurnTrustContext,
|
|
819
|
-
channelCapabilities: this.currentTurnChannelCapabilities,
|
|
820
|
-
personaOverride: this.wakePersonaOverride,
|
|
821
|
-
onboardingContext: this.getOnboardingContext(),
|
|
822
|
-
conversationId: this.conversationId,
|
|
823
|
-
});
|
|
814
|
+
const systemPrompt = this.buildCurrentSystemPrompt();
|
|
824
815
|
const tools = getAllToolDefinitions();
|
|
825
816
|
const provider = this.provider;
|
|
826
817
|
|
|
@@ -976,6 +967,18 @@ export class Conversation {
|
|
|
976
967
|
const meta = JSON.parse(m.metadata);
|
|
977
968
|
const isTail = index === arr.length - 1;
|
|
978
969
|
|
|
970
|
+
// `<non_interactive_context>` is the only rehydrated block that
|
|
971
|
+
// APPENDS to the tail (live injection appends it in Step 3), so it
|
|
972
|
+
// must land after the original content. Apply it first — before the
|
|
973
|
+
// prepends below — so the prepends stack in front of it and it stays
|
|
974
|
+
// last, matching the live layout.
|
|
975
|
+
if (!isTail && typeof meta.nonInteractiveContextBlock === "string") {
|
|
976
|
+
content = [
|
|
977
|
+
...content,
|
|
978
|
+
{ type: "text" as const, text: meta.nonInteractiveContextBlock },
|
|
979
|
+
];
|
|
980
|
+
}
|
|
981
|
+
|
|
979
982
|
// Rehydrate in reverse injection order (innermost block first)
|
|
980
983
|
// so the resulting layout matches `applyRuntimeInjections`'s
|
|
981
984
|
// after-memory-prefix splices in ascending injector order
|
|
@@ -1086,6 +1089,17 @@ export class Conversation {
|
|
|
1086
1089
|
];
|
|
1087
1090
|
}
|
|
1088
1091
|
|
|
1092
|
+
// `<channel_capabilities>` lands just below `<turn_context>`: live
|
|
1093
|
+
// injection prepends it (Step 3) before the prepend-user-tail chain
|
|
1094
|
+
// blocks (Step 4), so it must be prepended BEFORE turnContextBlock
|
|
1095
|
+
// here to land one slot deeper than `<turn_context>`.
|
|
1096
|
+
if (!isTail && typeof meta.channelCapabilitiesBlock === "string") {
|
|
1097
|
+
content = [
|
|
1098
|
+
{ type: "text" as const, text: meta.channelCapabilitiesBlock },
|
|
1099
|
+
...content,
|
|
1100
|
+
];
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1089
1103
|
if (!isTail && typeof meta.turnContextBlock === "string") {
|
|
1090
1104
|
content = [
|
|
1091
1105
|
{ type: "text" as const, text: meta.turnContextBlock },
|
|
@@ -1093,6 +1107,16 @@ export class Conversation {
|
|
|
1093
1107
|
];
|
|
1094
1108
|
}
|
|
1095
1109
|
|
|
1110
|
+
// `<background_turn>` lands between `<workspace>` and `<turn_context>`
|
|
1111
|
+
// (injector order 15, between workspace 10 and unified-turn-context
|
|
1112
|
+
// 20), so prepend it AFTER turnContextBlock and BEFORE workspaceBlock.
|
|
1113
|
+
if (!isTail && typeof meta.backgroundTurnBlock === "string") {
|
|
1114
|
+
content = [
|
|
1115
|
+
{ type: "text" as const, text: meta.backgroundTurnBlock },
|
|
1116
|
+
...content,
|
|
1117
|
+
];
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1096
1120
|
if (!isTail && typeof meta.workspaceBlock === "string") {
|
|
1097
1121
|
content = [
|
|
1098
1122
|
{ type: "text" as const, text: meta.workspaceBlock },
|
|
@@ -1529,9 +1553,7 @@ export class Conversation {
|
|
|
1529
1553
|
|
|
1530
1554
|
ensureHostProxiesForTurn(
|
|
1531
1555
|
sourceInterface: import("../channels/types.js").InterfaceId | undefined,
|
|
1532
|
-
sourceActorPrincipalId = this.
|
|
1533
|
-
this.currentTurnAuthContext?.actorPrincipalId ??
|
|
1534
|
-
this.authContext?.actorPrincipalId,
|
|
1556
|
+
sourceActorPrincipalId = this.getTurnActorPrincipalId(),
|
|
1535
1557
|
): void {
|
|
1536
1558
|
if (
|
|
1537
1559
|
shouldAttachHostProxyForCapability(
|
|
@@ -1606,8 +1628,65 @@ export class Conversation {
|
|
|
1606
1628
|
}
|
|
1607
1629
|
}
|
|
1608
1630
|
|
|
1631
|
+
/**
|
|
1632
|
+
* Token count for `messages` used to render the user-facing `/compact` and
|
|
1633
|
+
* `/clean` figures. Prefers the provider's real `count_tokens` tokenizer (so
|
|
1634
|
+
* the numbers match the context-window indicator's provider-reported usage)
|
|
1635
|
+
* and falls back to the context-window manager's local estimate when the
|
|
1636
|
+
* provider has no count endpoint or the count call fails — both measure the
|
|
1637
|
+
* same system-prompt + tools composition the manager sizes against.
|
|
1638
|
+
*
|
|
1639
|
+
* The count is a network round-trip with its own rate limit, so this is for
|
|
1640
|
+
* user-initiated actions only, never the per-turn auto-compaction gate.
|
|
1641
|
+
*/
|
|
1642
|
+
private async calculateTokens(messages: Message[]): Promise<number> {
|
|
1643
|
+
const countInputTokens = this.provider.countInputTokens;
|
|
1644
|
+
if (!countInputTokens) {
|
|
1645
|
+
return this.contextWindowManager.estimateInputTokens(messages);
|
|
1646
|
+
}
|
|
1647
|
+
try {
|
|
1648
|
+
const { systemPrompt, tools } =
|
|
1649
|
+
this.contextWindowManager.tokenCountInputs;
|
|
1650
|
+
return await countInputTokens.call(
|
|
1651
|
+
this.provider,
|
|
1652
|
+
messages,
|
|
1653
|
+
systemPrompt,
|
|
1654
|
+
tools,
|
|
1655
|
+
);
|
|
1656
|
+
} catch (err) {
|
|
1657
|
+
log.warn(
|
|
1658
|
+
{ err, conversationId: this.conversationId },
|
|
1659
|
+
"Provider token count failed — falling back to local estimate",
|
|
1660
|
+
);
|
|
1661
|
+
return this.contextWindowManager.estimateInputTokens(messages);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1609
1665
|
async forceCompact(): Promise<ContextWindowResult> {
|
|
1610
|
-
|
|
1666
|
+
// Report the user-facing before/after using the provider's real tokenizer
|
|
1667
|
+
// (count_tokens) so the `/compact` line matches the context-window
|
|
1668
|
+
// indicator, which reflects the provider's actual reported usage — rather
|
|
1669
|
+
// than the local chars/4 estimate the compaction pipeline runs internally
|
|
1670
|
+
// (it under-counts by ~25% on typical histories). `calculateTokens`
|
|
1671
|
+
// falls back to that estimate when the provider has no count endpoint or
|
|
1672
|
+
// the count call fails, so behavior degrades gracefully.
|
|
1673
|
+
//
|
|
1674
|
+
// Only the *displayed* numbers are overridden — the compaction log and
|
|
1675
|
+
// circuit-breaker accounting inside `runCompaction` keep the estimate-based
|
|
1676
|
+
// figures, leaving calibration and historical logs untouched.
|
|
1677
|
+
const before = await this.calculateTokens(this.messages);
|
|
1678
|
+
const result = await this.runCompaction(true);
|
|
1679
|
+
// `runCompaction` applies the compacted history to `this.messages` in
|
|
1680
|
+
// place, so after a successful compaction this re-counts the new history;
|
|
1681
|
+
// a no-op leaves the context unchanged, so before === after.
|
|
1682
|
+
const after = result.compacted
|
|
1683
|
+
? await this.calculateTokens(this.messages)
|
|
1684
|
+
: before;
|
|
1685
|
+
return {
|
|
1686
|
+
...result,
|
|
1687
|
+
previousEstimatedInputTokens: before,
|
|
1688
|
+
estimatedInputTokens: after,
|
|
1689
|
+
};
|
|
1611
1690
|
}
|
|
1612
1691
|
|
|
1613
1692
|
/**
|
|
@@ -1726,15 +1805,17 @@ export class Conversation {
|
|
|
1726
1805
|
* activations are no longer deduped against the prior session.
|
|
1727
1806
|
*/
|
|
1728
1807
|
async forceClean(): Promise<CleanResult> {
|
|
1729
|
-
|
|
1730
|
-
|
|
1808
|
+
// Use the provider's real tokenizer for the displayed before/after (see
|
|
1809
|
+
// `forceCompact` for why); falls back to the local estimate when count
|
|
1810
|
+
// isn't available.
|
|
1811
|
+
const previousEstimatedInputTokens = await this.calculateTokens(
|
|
1812
|
+
this.messages,
|
|
1813
|
+
);
|
|
1731
1814
|
const stripped = stripInjectionsForCompaction(this.messages);
|
|
1732
1815
|
this.messages = stripped;
|
|
1733
1816
|
await this.graphMemory.onCompacted(0);
|
|
1734
1817
|
setConversationHistoryStrippedAt(this.conversationId, Date.now());
|
|
1735
|
-
const estimatedInputTokens = this.
|
|
1736
|
-
this.messages,
|
|
1737
|
-
);
|
|
1818
|
+
const estimatedInputTokens = await this.calculateTokens(this.messages);
|
|
1738
1819
|
return {
|
|
1739
1820
|
previousEstimatedInputTokens,
|
|
1740
1821
|
estimatedInputTokens,
|
|
@@ -1767,6 +1848,21 @@ export class Conversation {
|
|
|
1767
1848
|
return this.authContext;
|
|
1768
1849
|
}
|
|
1769
1850
|
|
|
1851
|
+
/**
|
|
1852
|
+
* The actor principal that owns the current turn, for host-proxy routing.
|
|
1853
|
+
* Prefers the in-flight turn's actor over the conversation's resting
|
|
1854
|
+
* authContext so a /v1/messages turn (which sets only
|
|
1855
|
+
* `currentTurnSourceActorPrincipalId`/`currentTurnAuthContext`) scopes
|
|
1856
|
+
* correctly. Returns `undefined` when no actor identity is known.
|
|
1857
|
+
*/
|
|
1858
|
+
getTurnActorPrincipalId(): string | undefined {
|
|
1859
|
+
return (
|
|
1860
|
+
this.currentTurnSourceActorPrincipalId ??
|
|
1861
|
+
this.currentTurnAuthContext?.actorPrincipalId ??
|
|
1862
|
+
this.authContext?.actorPrincipalId
|
|
1863
|
+
);
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1770
1866
|
setVoiceCallControlPrompt(prompt: string | null): void {
|
|
1771
1867
|
this.voiceCallControlPrompt = prompt ?? undefined;
|
|
1772
1868
|
}
|
|
@@ -24,6 +24,12 @@ export const DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT = 90;
|
|
|
24
24
|
// clears the warning state, which discards the banner's (state-scoped) dismissal
|
|
25
25
|
// so it re-appears the moment usage ticks back up.
|
|
26
26
|
export const DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT = 77;
|
|
27
|
+
// Absolute free-space floor (MiB). Regardless of usage percentage, never enter
|
|
28
|
+
// the warning or critical state while at least this much space remains free. A
|
|
29
|
+
// high usage percentage on a large disk can still leave many gigabytes
|
|
30
|
+
// available, where locking is pointless. Small volumes (where a high percentage
|
|
31
|
+
// genuinely means near-full) drop below the floor and remain protected.
|
|
32
|
+
export const DISK_PRESSURE_MIN_FREE_FLOOR_MB = 2048;
|
|
27
33
|
export const DISK_PRESSURE_CHECK_INTERVAL_MS = 60_000;
|
|
28
34
|
export const DISK_PRESSURE_OVERRIDE_CONFIRMATION = "I understand the risks";
|
|
29
35
|
export const DISK_PRESSURE_BLOCKED_CAPABILITIES = [
|
|
@@ -219,7 +225,10 @@ export function evaluateDiskPressureNow(): DiskPressureStatus {
|
|
|
219
225
|
const criticalThreshold = state.status.locked
|
|
220
226
|
? DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT
|
|
221
227
|
: DISK_PRESSURE_THRESHOLD_PERCENT;
|
|
222
|
-
|
|
228
|
+
// Absolute free-space floor overrides the percentage thresholds: while ample
|
|
229
|
+
// space remains free, report "ok" no matter how full the volume is by percent.
|
|
230
|
+
const hasAmpleFreeSpace = usageInfo.freeMb >= DISK_PRESSURE_MIN_FREE_FLOOR_MB;
|
|
231
|
+
const isCritical = !hasAmpleFreeSpace && usagePercent >= criticalThreshold;
|
|
223
232
|
// Mirror the critical deadband for the warning band: once in an active
|
|
224
233
|
// pressure state (warning or critical), hold warning until usage clears the
|
|
225
234
|
// lower warning-clear threshold. Treating "critical" as active here matters
|
|
@@ -235,7 +244,8 @@ export function evaluateDiskPressureNow(): DiskPressureStatus {
|
|
|
235
244
|
const warningThreshold = inActivePressureState
|
|
236
245
|
? DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT
|
|
237
246
|
: DISK_PRESSURE_WARNING_THRESHOLD_PERCENT;
|
|
238
|
-
const isWarning =
|
|
247
|
+
const isWarning =
|
|
248
|
+
!hasAmpleFreeSpace && !isCritical && usagePercent >= warningThreshold;
|
|
239
249
|
const lastCheckedAt = new Date().toISOString();
|
|
240
250
|
|
|
241
251
|
if (!isCritical && !isWarning) {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the event-loop block watchdog.
|
|
3
|
+
*
|
|
4
|
+
* - `evaluateTick` must derive the blocked duration as elapsed-beyond-interval
|
|
5
|
+
* and apply the threshold inclusively, clamping early/normal ticks to zero so
|
|
6
|
+
* a healthy loop never reports.
|
|
7
|
+
* - `start`/`stop` must be idempotent and safe to call in any order so daemon
|
|
8
|
+
* startup and the two shutdown paths can call them unconditionally.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
11
|
+
|
|
12
|
+
mock.module("../util/logger.js", () => ({
|
|
13
|
+
getLogger: () =>
|
|
14
|
+
new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
const { evaluateTick, startEventLoopWatchdog, stopEventLoopWatchdog } =
|
|
18
|
+
await import("./event-loop-watchdog.js");
|
|
19
|
+
|
|
20
|
+
describe("evaluateTick", () => {
|
|
21
|
+
const INTERVAL = 1_000;
|
|
22
|
+
const THRESHOLD = 5_000;
|
|
23
|
+
|
|
24
|
+
test("a healthy tick at the scheduled interval is not a block", () => {
|
|
25
|
+
// GIVEN the timer fired right on schedule
|
|
26
|
+
// WHEN the tick is evaluated
|
|
27
|
+
const { blockedMs, exceeded } = evaluateTick(INTERVAL, INTERVAL, THRESHOLD);
|
|
28
|
+
// THEN no block is observed
|
|
29
|
+
expect(blockedMs).toBe(0);
|
|
30
|
+
expect(exceeded).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("an early tick clamps the blocked duration to zero", () => {
|
|
34
|
+
// GIVEN the timer fired sooner than the interval (e.g. clock jitter)
|
|
35
|
+
// WHEN the tick is evaluated
|
|
36
|
+
const { blockedMs, exceeded } = evaluateTick(200, INTERVAL, THRESHOLD);
|
|
37
|
+
// THEN the blocked duration never goes negative
|
|
38
|
+
expect(blockedMs).toBe(0);
|
|
39
|
+
expect(exceeded).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("lateness under the threshold is measured but not reported", () => {
|
|
43
|
+
// GIVEN the loop was blocked ~2s (below the 5s threshold)
|
|
44
|
+
// WHEN the tick is evaluated
|
|
45
|
+
const { blockedMs, exceeded } = evaluateTick(3_000, INTERVAL, THRESHOLD);
|
|
46
|
+
// THEN the block is quantified but does not trip a report
|
|
47
|
+
expect(blockedMs).toBe(2_000);
|
|
48
|
+
expect(exceeded).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("the threshold is inclusive", () => {
|
|
52
|
+
// GIVEN the blocked duration lands exactly on the threshold
|
|
53
|
+
// WHEN the tick is evaluated
|
|
54
|
+
const { blockedMs, exceeded } = evaluateTick(
|
|
55
|
+
INTERVAL + THRESHOLD,
|
|
56
|
+
INTERVAL,
|
|
57
|
+
THRESHOLD,
|
|
58
|
+
);
|
|
59
|
+
// THEN it counts as exceeded
|
|
60
|
+
expect(blockedMs).toBe(THRESHOLD);
|
|
61
|
+
expect(exceeded).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("a multi-minute freeze reports the full blocked duration", () => {
|
|
65
|
+
// GIVEN a ~123s freeze (the observed daemon-freeze magnitude) with a 1s tick
|
|
66
|
+
// WHEN the first tick after unblock is evaluated
|
|
67
|
+
const { blockedMs, exceeded } = evaluateTick(124_000, INTERVAL, THRESHOLD);
|
|
68
|
+
// THEN the reported block excludes the one normal interval of wait
|
|
69
|
+
expect(blockedMs).toBe(123_000);
|
|
70
|
+
expect(exceeded).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe("start/stop lifecycle", () => {
|
|
75
|
+
test("start and stop are idempotent and order-independent", () => {
|
|
76
|
+
// GIVEN a fresh module
|
|
77
|
+
// WHEN start/stop are called repeatedly and out of order
|
|
78
|
+
// THEN none of the calls throw (daemon boot + both shutdown paths are safe)
|
|
79
|
+
expect(() => stopEventLoopWatchdog()).not.toThrow();
|
|
80
|
+
expect(() => startEventLoopWatchdog()).not.toThrow();
|
|
81
|
+
expect(() => startEventLoopWatchdog()).not.toThrow();
|
|
82
|
+
expect(() => stopEventLoopWatchdog()).not.toThrow();
|
|
83
|
+
expect(() => stopEventLoopWatchdog()).not.toThrow();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-loop block watchdog.
|
|
3
|
+
*
|
|
4
|
+
* The daemon runs all request handling, synchronous `bun:sqlite` access, and
|
|
5
|
+
* background jobs on a single event-loop thread. Any synchronous operation that
|
|
6
|
+
* runs long — a large conversation-history load, a memory retrospective
|
|
7
|
+
* assembling an oversized conversation, a VACUUM or WAL checkpoint — blocks that
|
|
8
|
+
* thread, so the daemon stops answering health probes and SSE for the duration
|
|
9
|
+
* (a proxied `vellum ps` health check then reports `timeout` even though the
|
|
10
|
+
* process is alive). Such a freeze is otherwise invisible: the blocked thread is
|
|
11
|
+
* too busy to emit logs, so it leaves only a gap that self-heals when the
|
|
12
|
+
* operation returns, and is noticed only by chance.
|
|
13
|
+
*
|
|
14
|
+
* This watchdog makes those freezes observable. It schedules a timer every
|
|
15
|
+
* `TICK_INTERVAL_MS`; when the loop is blocked the callback cannot run, so it
|
|
16
|
+
* fires late by roughly the block duration. On the first tick after the loop
|
|
17
|
+
* frees up, the elapsed-since-last-tick beyond a normal interval is how long the
|
|
18
|
+
* loop was unavailable; above a threshold it emits a warn log + Sentry capture.
|
|
19
|
+
*
|
|
20
|
+
* What it does NOT do: capture the JS stack of the blocking operation. JS is
|
|
21
|
+
* single-threaded, so while the loop is blocked no callback — including this one
|
|
22
|
+
* — can run; by the time the tick fires, the offending synchronous call has
|
|
23
|
+
* returned and its stack is gone. The watchdog reports *that* and *how long* a
|
|
24
|
+
* freeze happened, not *what* caused it. The report lands at unblock, so the
|
|
25
|
+
* surrounding log lines (which job or turn was active) are the correlation
|
|
26
|
+
* handle. For deterministic attribution of a specific subsystem, time that
|
|
27
|
+
* subsystem's synchronous calls at their source.
|
|
28
|
+
*
|
|
29
|
+
* A cumulative event-loop-delay histogram is separately exposed pull-based over
|
|
30
|
+
* SSE diagnostics (`runtime/routes/events-routes.ts`); this watchdog is the
|
|
31
|
+
* push/alert counterpart and runs unconditionally for the daemon's lifetime.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import * as Sentry from "@sentry/node";
|
|
35
|
+
|
|
36
|
+
import { getLogger } from "../util/logger.js";
|
|
37
|
+
|
|
38
|
+
const log = getLogger("event-loop-watchdog");
|
|
39
|
+
|
|
40
|
+
/** How often the probe timer is scheduled. */
|
|
41
|
+
const TICK_INTERVAL_MS = 1_000;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Report only when the loop was unavailable for at least this long beyond a
|
|
45
|
+
* normal tick. Set above the floor of the daemon's known-legitimate
|
|
46
|
+
* multi-second main-thread operations so the signal stays actionable rather than
|
|
47
|
+
* noisy; tune here.
|
|
48
|
+
*/
|
|
49
|
+
const DEFAULT_BLOCK_THRESHOLD_MS = 5_000;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Minimum spacing between reports. A single long freeze fires the timer once on
|
|
53
|
+
* unblock (an overdue interval is not replayed per missed tick), but a loop that
|
|
54
|
+
* blocks repeatedly could trip every tick; the cooldown bounds that to one
|
|
55
|
+
* report per window.
|
|
56
|
+
*/
|
|
57
|
+
const REPORT_COOLDOWN_MS = 30_000;
|
|
58
|
+
|
|
59
|
+
let tickTimer: ReturnType<typeof setInterval> | null = null;
|
|
60
|
+
let lastTickAt = 0;
|
|
61
|
+
let lastReportAt = Number.NEGATIVE_INFINITY;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Given the wall-clock elapsed since the previous tick and the scheduled tick
|
|
65
|
+
* interval, the loop was blocked for the excess over the interval. Pure so the
|
|
66
|
+
* threshold decision is unit-testable without real timers or a blocked loop.
|
|
67
|
+
*/
|
|
68
|
+
export function evaluateTick(
|
|
69
|
+
elapsedMs: number,
|
|
70
|
+
intervalMs: number,
|
|
71
|
+
thresholdMs: number,
|
|
72
|
+
): { blockedMs: number; exceeded: boolean } {
|
|
73
|
+
const blockedMs = Math.max(0, elapsedMs - intervalMs);
|
|
74
|
+
return { blockedMs, exceeded: blockedMs >= thresholdMs };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function reportBlock(blockedMs: number, thresholdMs: number): void {
|
|
78
|
+
log.warn(
|
|
79
|
+
{ blockedMs, thresholdMs, tickIntervalMs: TICK_INTERVAL_MS },
|
|
80
|
+
"event loop blocked",
|
|
81
|
+
);
|
|
82
|
+
try {
|
|
83
|
+
Sentry.withScope((scope) => {
|
|
84
|
+
scope.setLevel("warning");
|
|
85
|
+
scope.setTag("event_loop_blocked_ms", String(blockedMs));
|
|
86
|
+
scope.setContext("event_loop_block", {
|
|
87
|
+
blocked_ms: blockedMs,
|
|
88
|
+
threshold_ms: thresholdMs,
|
|
89
|
+
tick_interval_ms: TICK_INTERVAL_MS,
|
|
90
|
+
});
|
|
91
|
+
Sentry.captureMessage("event_loop_blocked");
|
|
92
|
+
});
|
|
93
|
+
} catch {
|
|
94
|
+
// Never let a telemetry failure escape the timer callback.
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Start the event-loop block watchdog. Idempotent. The timer is `unref`'d so it
|
|
100
|
+
* never keeps the process alive on its own.
|
|
101
|
+
*/
|
|
102
|
+
export function startEventLoopWatchdog(
|
|
103
|
+
thresholdMs: number = DEFAULT_BLOCK_THRESHOLD_MS,
|
|
104
|
+
): void {
|
|
105
|
+
if (tickTimer) return;
|
|
106
|
+
lastTickAt = performance.now();
|
|
107
|
+
lastReportAt = Number.NEGATIVE_INFINITY;
|
|
108
|
+
tickTimer = setInterval(() => {
|
|
109
|
+
const now = performance.now();
|
|
110
|
+
const { blockedMs, exceeded } = evaluateTick(
|
|
111
|
+
now - lastTickAt,
|
|
112
|
+
TICK_INTERVAL_MS,
|
|
113
|
+
thresholdMs,
|
|
114
|
+
);
|
|
115
|
+
lastTickAt = now;
|
|
116
|
+
if (exceeded && now - lastReportAt >= REPORT_COOLDOWN_MS) {
|
|
117
|
+
lastReportAt = now;
|
|
118
|
+
reportBlock(blockedMs, thresholdMs);
|
|
119
|
+
}
|
|
120
|
+
}, TICK_INTERVAL_MS);
|
|
121
|
+
tickTimer.unref?.();
|
|
122
|
+
log.info(
|
|
123
|
+
{ tickIntervalMs: TICK_INTERVAL_MS, thresholdMs },
|
|
124
|
+
"Event-loop watchdog started",
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function stopEventLoopWatchdog(): void {
|
|
129
|
+
if (tickTimer) {
|
|
130
|
+
clearInterval(tickTimer);
|
|
131
|
+
tickTimer = null;
|
|
132
|
+
}
|
|
133
|
+
}
|