@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022329.d89bf2f
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 +94 -91
- package/Dockerfile +5 -16
- package/README.md +7 -10
- package/bun.lock +0 -4
- package/docs/architecture/security.md +20 -20
- package/docs/stt-provider-onboarding.md +4 -5
- package/docs/trusted-contact-access.md +7 -7
- package/eslint-rules/cli-no-daemon-internals.js +4 -0
- package/eslint.config.mjs +7 -1
- package/knip.json +0 -1
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
- package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
- package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
- package/openapi.yaml +1073 -225
- package/package.json +1 -4
- package/scripts/test.sh +35 -13
- package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
- package/src/__tests__/acp-session.test.ts +4 -1
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
- package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
- package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
- package/src/__tests__/app-source-watcher.test.ts +11 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
- package/src/__tests__/assistant-attachments.test.ts +62 -4
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
- package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
- package/src/__tests__/attachments-store.test.ts +3 -0
- package/src/__tests__/background-shell-bash.test.ts +34 -0
- package/src/__tests__/background-shell-host-bash.test.ts +12 -0
- package/src/__tests__/background-tool-registry.test.ts +97 -0
- package/src/__tests__/background-tool-routes.test.ts +72 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/btw-routes.test.ts +57 -3
- package/src/__tests__/call-controller.test.ts +474 -84
- package/src/__tests__/call-domain.test.ts +48 -1
- package/src/__tests__/call-pointer-messages.test.ts +57 -19
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +15 -14
- package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
- package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
- package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
- package/src/__tests__/call-setup-flow.test.ts +311 -0
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +4 -7
- package/src/__tests__/channel-readiness-service.test.ts +0 -6
- package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
- package/src/__tests__/channel-retry-sweep.test.ts +76 -64
- package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
- package/src/__tests__/clear-all-lexical.test.ts +90 -0
- package/src/__tests__/compactor-media-strip.test.ts +177 -0
- package/src/__tests__/config-loader-backfill.test.ts +5 -5
- package/src/__tests__/config-schema.test.ts +17 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
- package/src/__tests__/contacts-relay-reads.test.ts +188 -23
- package/src/__tests__/contacts-tools.test.ts +42 -1
- package/src/__tests__/contacts-write.test.ts +181 -0
- package/src/__tests__/context-search-conversations-source.test.ts +220 -81
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +39 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
- package/src/__tests__/conversation-clear-safety.test.ts +0 -1
- package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -0
- package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
- package/src/__tests__/conversation-error.test.ts +0 -18
- package/src/__tests__/conversation-fork-crud.test.ts +67 -0
- package/src/__tests__/conversation-history-web-search.test.ts +7 -137
- package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
- package/src/__tests__/conversation-process-callsite.test.ts +37 -0
- package/src/__tests__/conversation-queue.test.ts +149 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
- package/src/__tests__/conversation-skill-tools.test.ts +73 -0
- package/src/__tests__/conversation-wipe.test.ts +20 -5
- package/src/__tests__/credential-prompt-route.test.ts +69 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -3
- package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
- package/src/__tests__/edit-propagation.test.ts +56 -2
- package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
- package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
- package/src/__tests__/guardian-question-mode.test.ts +57 -0
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/guardian-wait-controller.test.ts +619 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
- package/src/__tests__/heic-fixture.ts +55 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
- package/src/__tests__/http-conversation-lineage.test.ts +6 -1
- package/src/__tests__/image-conversion.test.ts +170 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
- package/src/__tests__/introduction-card-resolver.test.ts +354 -0
- package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
- package/src/__tests__/invite-routes-http.test.ts +246 -420
- package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
- package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
- package/src/__tests__/list-messages-attachments.test.ts +159 -0
- package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
- package/src/__tests__/list-messages-queued.test.ts +25 -0
- package/src/__tests__/managed-store.test.ts +129 -1
- package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
- package/src/__tests__/media-stream-output.test.ts +350 -19
- package/src/__tests__/media-stream-server-integration.test.ts +943 -169
- package/src/__tests__/media-stream-stt-session.test.ts +498 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +19 -0
- package/src/__tests__/non-member-access-request.test.ts +349 -3
- package/src/__tests__/notification-decision-fallback.test.ts +104 -8
- package/src/__tests__/notification-decision-strategy.test.ts +57 -8
- package/src/__tests__/onboarding-template-contract.test.ts +27 -43
- package/src/__tests__/openai-provider.test.ts +33 -0
- package/src/__tests__/openai-responses-provider.test.ts +40 -0
- package/src/__tests__/persistence-layering-guard.test.ts +29 -20
- package/src/__tests__/persona-resolver.test.ts +56 -2
- package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
- package/src/__tests__/phone.test.ts +1 -15
- package/src/__tests__/plugin-bootstrap.test.ts +25 -196
- package/src/__tests__/plugin-disabled-state.test.ts +33 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
- package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
- package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
- package/src/__tests__/plugin-pipeline.test.ts +63 -1
- package/src/__tests__/plugin-route-contribution.test.ts +62 -115
- package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
- package/src/__tests__/plugin-types.test.ts +0 -1
- package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
- package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
- package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
- package/src/__tests__/public-ingress-urls.test.ts +0 -48
- package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
- package/src/__tests__/resolve-trust-class.test.ts +28 -10
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
- package/src/__tests__/schedule-retry.test.ts +38 -14
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
- package/src/__tests__/schedule-routes.test.ts +14 -6
- package/src/__tests__/schedule-store.test.ts +3 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
- package/src/__tests__/scheduler-recurrence.test.ts +57 -107
- package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
- package/src/__tests__/scheduler-wake.test.ts +13 -23
- package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/shell-observability.test.ts +1 -0
- package/src/__tests__/skill-boundary-guard.test.ts +3 -4
- package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
- package/src/__tests__/skill-script-runner-host.test.ts +53 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
- package/src/__tests__/skill-tool-factory.test.ts +73 -1
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
- package/src/__tests__/slack-inbound-verification.test.ts +36 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
- package/src/__tests__/stt-hints.test.ts +2 -256
- package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
- package/src/__tests__/subagent-persistence.test.ts +122 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
- package/src/__tests__/subagent-terminal-message.test.ts +99 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
- package/src/__tests__/system-prompt.test.ts +17 -118
- package/src/__tests__/task-scheduler.test.ts +68 -89
- package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
- package/src/__tests__/telephony-tts-guard.test.ts +538 -0
- package/src/__tests__/title-generate-hook.test.ts +16 -0
- package/src/__tests__/tool-approval-handler.test.ts +87 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
- package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
- package/src/__tests__/trust-context-guards.test.ts +21 -10
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
- package/src/__tests__/twilio-provider.test.ts +17 -17
- package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
- package/src/__tests__/twilio-routes.test.ts +257 -387
- package/src/__tests__/twilio-validation.test.ts +1 -1
- package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
- package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
- package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
- package/src/__tests__/voice-quality.test.ts +2 -2
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
- package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
- package/src/__tests__/voice-session-bridge.test.ts +1 -10
- package/src/__tests__/workspace-git-service.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
- package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
- package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
- package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
- package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
- package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
- package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
- package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
- package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
- package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
- package/src/acp/__tests__/session-manager.test.ts +6 -0
- package/src/acp/agent-process.test.ts +116 -0
- package/src/acp/agent-process.ts +71 -0
- package/src/acp/auto-install.ts +12 -8
- package/src/acp/failure-error.test.ts +109 -0
- package/src/acp/failure-error.ts +111 -0
- package/src/acp/prepare-agent-env.ts +0 -12
- package/src/acp/resolve-agent.test.ts +6 -45
- package/src/acp/resolve-agent.ts +2 -4
- package/src/acp/session-manager.test.ts +312 -0
- package/src/acp/session-manager.ts +102 -46
- package/src/agent/ax-tree-compaction.test.ts +4 -1
- package/src/agent/image-optimize.ts +17 -127
- package/src/agent/loop.ts +45 -192
- package/src/api/events/background-tool-completed.test.ts +51 -0
- package/src/api/events/background-tool-completed.ts +29 -0
- package/src/api/events/background-tool-started.test.ts +36 -0
- package/src/api/events/background-tool-started.ts +28 -0
- package/src/api/events/conversation-error.ts +0 -1
- package/src/api/events/open-panel.ts +33 -0
- package/src/api/events/subagent-status-changed.ts +4 -1
- package/src/api/index.ts +19 -0
- package/src/api/responses/conversation-message.ts +34 -0
- package/src/approvals/guardian-decision-primitive.ts +74 -24
- package/src/approvals/guardian-request-resolvers.ts +450 -122
- package/src/apps/app-store.ts +1 -0
- package/src/apps/shared-app-links-store.ts +1 -0
- package/src/avatar/identity-avatar.ts +3 -7
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
- package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
- package/src/calls/call-controller.ts +134 -48
- package/src/calls/call-domain.ts +18 -42
- package/src/calls/call-pointer-messages.ts +51 -67
- package/src/calls/call-setup-flow-types.ts +76 -0
- package/src/calls/call-setup-flow.ts +1743 -0
- package/src/calls/call-speech-output.ts +87 -23
- package/src/calls/call-store.ts +4 -0
- package/src/calls/call-transport.ts +22 -36
- package/src/calls/fish-audio-client.ts +3 -0
- package/src/calls/gateway-invite-reader.ts +98 -0
- package/src/calls/guardian-wait-controller.ts +451 -0
- package/src/calls/media-stream-audio-transcode.ts +82 -2
- package/src/calls/media-stream-output.ts +142 -36
- package/src/calls/media-stream-server.ts +297 -178
- package/src/calls/media-stream-stt-session.ts +393 -50
- package/src/calls/media-turn-detector.ts +4 -6
- package/src/calls/relay-access-wait.ts +3 -4
- package/src/calls/relay-setup-router.ts +22 -43
- package/src/calls/relay-verification.ts +17 -24
- package/src/calls/resolve-call-tts-provider.ts +96 -29
- package/src/calls/stt-hints.ts +24 -87
- package/src/calls/telephony-credential-preflight.ts +159 -0
- package/src/calls/telephony-tts-capability.ts +183 -0
- package/src/calls/tts-call-strategy.ts +18 -20
- package/src/calls/twilio-provider.ts +3 -2
- package/src/calls/twilio-routes.ts +47 -351
- package/src/calls/types.ts +5 -3
- package/src/calls/voice-ingress-preflight.ts +9 -0
- package/src/calls/voice-quality.ts +13 -18
- package/src/calls/voice-session-bridge.ts +25 -35
- package/src/channels/__tests__/types.test.ts +28 -0
- package/src/channels/channel-verification-sessions.ts +7 -2
- package/src/channels/config.ts +0 -42
- package/src/channels/slack-thread-store.ts +12 -0
- package/src/channels/types.ts +23 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
- package/src/cli/commands/__tests__/schedules.test.ts +83 -34
- package/src/cli/commands/__tests__/status.test.ts +42 -2
- package/src/cli/commands/contacts.ts +2 -2
- package/src/cli/commands/credentials.ts +17 -0
- package/src/cli/commands/monitoring.ts +191 -0
- package/src/cli/commands/schedules-worker.ts +175 -0
- package/src/cli/commands/schedules.ts +169 -43
- package/src/cli/commands/status.ts +12 -1
- package/src/cli/commands/tools.ts +5 -1
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
- package/src/cli/lib/search-plugins.ts +6 -0
- package/src/cli/lib/toggle-plugin.ts +21 -2
- package/src/cli/program.ts +3 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
- package/src/config/acp-defaults.test.ts +0 -10
- package/src/config/acp-defaults.ts +0 -6
- package/src/config/bundled-skills/acp/SKILL.md +13 -45
- package/src/config/bundled-skills/acp/TOOLS.json +3 -3
- package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
- package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
- package/src/config/call-site-defaults.ts +0 -2
- package/src/config/feature-flag-registry.json +16 -8
- package/src/config/loader.ts +11 -0
- package/src/config/schema.ts +9 -1
- package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
- package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
- package/src/config/schemas/call-site-catalog.ts +0 -12
- package/src/config/schemas/calls.ts +8 -0
- package/src/config/schemas/elevenlabs.ts +1 -1
- package/src/config/schemas/llm.ts +0 -2
- package/src/config/schemas/memory-v2.ts +1 -1
- package/src/config/schemas/memory-v3.ts +82 -0
- package/src/config/schemas/monitoring.ts +61 -0
- package/src/config/schemas/schedules.ts +35 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills-plugin-filter.test.ts +96 -0
- package/src/config/skills.ts +26 -0
- package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
- package/src/contacts/canonical-guardian-store.ts +5 -0
- package/src/contacts/contact-store.ts +81 -35
- package/src/contacts/contacts-write.ts +50 -25
- package/src/contacts/member-write-relay.ts +115 -31
- package/src/contacts/types.ts +0 -8
- package/src/context/compactor.ts +29 -15
- package/src/context/outbound-sanitize.ts +202 -0
- package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
- package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
- package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
- package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
- package/src/daemon/abort-watchdog.ts +7 -0
- package/src/daemon/app-source-watcher.ts +9 -0
- package/src/daemon/assistant-attachments.ts +42 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
- package/src/daemon/conversation-agent-loop.ts +61 -68
- package/src/daemon/conversation-error.ts +1 -15
- package/src/daemon/conversation-history.ts +32 -236
- package/src/daemon/conversation-initial-prompt.ts +77 -0
- package/src/daemon/conversation-lifecycle.ts +25 -1
- package/src/daemon/conversation-messaging.ts +2 -2
- package/src/daemon/conversation-plugin-scope.ts +38 -0
- package/src/daemon/conversation-process.ts +50 -14
- package/src/daemon/conversation-runtime-assembly.ts +36 -6
- package/src/daemon/conversation-skill-tools.ts +19 -3
- package/src/daemon/conversation-store.ts +3 -3
- package/src/daemon/conversation-surfaces.ts +171 -0
- package/src/daemon/conversation-tool-setup.test.ts +95 -0
- package/src/daemon/conversation-tool-setup.ts +116 -1
- package/src/daemon/conversation-turn-finalize.ts +211 -0
- package/src/daemon/conversation.ts +92 -1
- package/src/daemon/disk-pressure-policy.ts +2 -1
- package/src/daemon/event-loop-watchdog.ts +22 -6
- package/src/daemon/external-plugins-bootstrap.ts +47 -134
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
- package/src/daemon/handlers/config-a2a.ts +7 -14
- package/src/daemon/handlers/config-channels.ts +2 -10
- package/src/daemon/handlers/conversation-history.ts +3 -1
- package/src/daemon/handlers/conversations.ts +0 -52
- package/src/daemon/handlers/shared.ts +4 -24
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +59 -472
- package/src/daemon/message-protocol.ts +3 -3
- package/src/daemon/message-provenance.ts +12 -14
- package/src/daemon/message-types/background-tools.ts +28 -0
- package/src/daemon/message-types/contacts.ts +2 -10
- package/src/daemon/message-types/conversations.ts +10 -0
- package/src/daemon/message-types/integrations.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pointer-conversation-trust.ts +23 -9
- package/src/daemon/pointer-turn-runner.ts +174 -0
- package/src/daemon/providers-setup.ts +16 -0
- package/src/daemon/shutdown-handlers.ts +139 -47
- package/src/daemon/skill-memory-refresh.ts +2 -2
- package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
- package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
- package/src/daemon/tool-setup-types.ts +8 -0
- package/src/daemon/trust-context.ts +21 -6
- package/src/daemon/turn-latency-tracker.test.ts +93 -0
- package/src/daemon/turn-latency-tracker.ts +38 -0
- package/src/daemon/wake-conversation-ops.ts +10 -8
- package/src/documents/document-comments-store.test.ts +7 -1
- package/src/documents/document-comments-store.ts +8 -0
- package/src/documents/document-store.ts +15 -0
- package/src/export/__tests__/transcript-formatter.test.ts +11 -0
- package/src/export/transcript-formatter.ts +49 -67
- package/src/home/__tests__/feed-writer.test.ts +247 -1
- package/src/home/conversation-starter-checkpoints.ts +1 -0
- package/src/home/feed-writer.ts +61 -0
- package/src/home/job-handlers/conversation-starters.ts +1 -0
- package/src/hooks/hook-loader.ts +12 -0
- package/src/hooks/registry.ts +32 -4
- package/src/inbound/public-ingress-urls.ts +0 -17
- package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
- package/src/ipc/assistant-server.ts +28 -7
- package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
- package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
- package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
- package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
- package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
- package/src/ipc/routes/db-proxy.ts +5 -2
- package/src/ipc/routes/invite-ipc-routes.ts +53 -39
- package/src/jobs/worker.ts +9 -2
- package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
- package/src/live-voice/live-voice-archive.ts +5 -0
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
- package/src/messaging/providers/channel-transport.ts +6 -0
- package/src/messaging/providers/index.ts +3 -0
- package/src/messaging/providers/slack/api.test.ts +49 -1
- package/src/messaging/providers/slack/api.ts +110 -0
- package/src/messaging/providers/slack/send.test.ts +85 -0
- package/src/messaging/providers/slack/send.ts +100 -28
- package/src/messaging/providers/slack/transport.ts +7 -13
- package/src/messaging/providers/whatsapp/send.ts +29 -9
- package/src/monitoring/__tests__/control.test.ts +235 -0
- package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
- package/src/monitoring/control.ts +105 -0
- package/src/monitoring/resource-sampler.ts +258 -0
- package/src/monitoring/sample-ring-buffer.ts +108 -0
- package/src/monitoring/worker.ts +94 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/access-request-copy.ts +94 -23
- package/src/notifications/adapters/slack.ts +89 -21
- package/src/notifications/approval-card-builder.ts +33 -18
- package/src/notifications/approval-card-data.ts +48 -15
- package/src/notifications/broadcaster.ts +25 -16
- package/src/notifications/decision-engine.ts +131 -32
- package/src/notifications/guardian-question-mode.ts +58 -10
- package/src/permissions/approval-policy.ts +8 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/gateway-threshold-reader.ts +7 -6
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/secret-prompter.ts +11 -3
- package/src/permissions/types.ts +2 -2
- package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
- package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
- package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
- package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
- package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
- package/src/persistence/a2a-invite-store.ts +205 -0
- package/src/persistence/attachments-store.ts +94 -10
- package/src/persistence/checkpoints.ts +45 -0
- package/src/persistence/conversation-crud.ts +453 -260
- package/src/persistence/conversation-display-order-migration.ts +8 -2
- package/src/persistence/conversation-group-migration.test.ts +8 -0
- package/src/persistence/conversation-group-migration.ts +9 -0
- package/src/persistence/conversation-queries.ts +244 -125
- package/src/persistence/conversation-row-batch-delete.ts +9 -5
- package/src/persistence/conversation-search-lexical.ts +49 -0
- package/src/persistence/db-async-query.ts +42 -0
- package/src/persistence/db-connection.ts +13 -0
- package/src/persistence/delivery-channels.ts +0 -82
- package/src/persistence/delivery-crud.ts +27 -6
- package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
- package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
- package/src/persistence/embeddings/embedding-identity.ts +17 -5
- package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
- package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
- package/src/persistence/embeddings/qdrant-client.ts +81 -5
- package/src/persistence/group-crud.ts +13 -1
- package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
- package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
- package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
- package/src/persistence/job-handlers/cleanup.ts +57 -9
- package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
- package/src/persistence/job-handlers/message-lexical.ts +251 -0
- package/src/persistence/jobs-store.ts +102 -8
- package/src/persistence/jobs-worker.ts +68 -28
- package/src/persistence/llm-request-log-store.ts +35 -19
- package/src/persistence/llm-usage-store.ts +11 -0
- package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
- package/src/persistence/memory-lifecycle-hooks.ts +55 -1
- package/src/persistence/migrations/028-call-session-mode.ts +1 -1
- package/src/persistence/migrations/116-messages-fts.ts +8 -1
- package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
- package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
- package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
- package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
- package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
- package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
- package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
- package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
- package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
- package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
- package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
- package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
- package/src/persistence/raw-query.ts +50 -11
- package/src/persistence/schema/a2a.ts +14 -0
- package/src/persistence/schema/contacts.ts +0 -62
- package/src/persistence/schema/conversation-groups.ts +12 -0
- package/src/persistence/schema/conversations.ts +2 -0
- package/src/persistence/schema/documents.ts +65 -0
- package/src/persistence/schema/guardian.ts +4 -0
- package/src/persistence/schema/index.ts +4 -0
- package/src/persistence/schema/memory-injection.ts +62 -0
- package/src/persistence/schema/workflows.ts +55 -0
- package/src/persistence/slow-query-log.ts +437 -0
- package/src/persistence/slow-sync-log.ts +204 -0
- package/src/persistence/steps.ts +16 -0
- package/src/persistence/subagent-store.ts +125 -0
- package/src/persistence/worker-control.ts +45 -238
- package/src/plugin-api/event-hub-facade.ts +172 -0
- package/src/plugin-api/index.ts +9 -1
- package/src/plugin-api/types.ts +40 -9
- package/src/plugins/defaults/default-plugin-names.ts +60 -0
- package/src/plugins/defaults/index.ts +19 -29
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
- package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
- package/src/plugins/defaults/memory/config.ts +11 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
- package/src/plugins/defaults/memory/embeddings.ts +77 -0
- package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
- package/src/plugins/defaults/memory/frontmatter.ts +50 -0
- package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
- package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
- package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
- package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
- package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
- package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
- package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
- package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
- package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
- package/src/plugins/defaults/memory/graph/tools.ts +1 -1
- package/src/plugins/defaults/memory/hooks/init.ts +31 -5
- package/src/plugins/defaults/memory/indexer.ts +2 -3
- package/src/plugins/defaults/memory/injectors.ts +2 -2
- package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
- package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
- package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
- package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
- package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
- package/src/plugins/defaults/memory/job-handlers.ts +13 -12
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
- package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
- package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
- package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
- package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
- package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
- package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
- package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
- package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
- package/src/plugins/defaults/memory/search/semantic.ts +2 -2
- package/src/plugins/defaults/memory/startup.ts +244 -0
- package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
- package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
- package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
- package/src/plugins/defaults/memory/v2/activation.ts +2 -4
- package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
- package/src/plugins/defaults/memory/v2/migration.ts +2 -5
- package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
- package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
- package/src/plugins/defaults/memory/v2/router.ts +5 -5
- package/src/plugins/defaults/memory/v2/sim.ts +2 -4
- package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
- package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
- package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
- package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
- package/src/plugins/defaults/memory/v3/card.ts +1 -4
- package/src/plugins/defaults/memory/v3/dense.ts +60 -25
- package/src/plugins/defaults/memory/v3/edge.ts +1 -1
- package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
- package/src/plugins/defaults/memory/v3/gate.ts +158 -0
- package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
- package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
- package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
- package/src/plugins/defaults/memory/v3/prune.ts +2 -2
- package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
- package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
- package/src/plugins/defaults/turn-context/injectors.ts +1 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
- package/src/plugins/injector-registry.ts +13 -2
- package/src/plugins/mtime-cache.ts +36 -47
- package/src/plugins/pipeline.ts +15 -1
- package/src/plugins/types.ts +14 -23
- package/src/prompts/__tests__/system-prompt.test.ts +170 -32
- package/src/prompts/persona-resolver.ts +13 -9
- package/src/prompts/system-prompt.ts +30 -9
- package/src/prompts/templates/BOOTSTRAP.md +16 -119
- package/src/prompts/templates/SOUL.md +43 -13
- package/src/prompts/templates/system-sections.ts +32 -27
- package/src/prompts/templates/users/default.md +19 -0
- package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +14 -1
- package/src/providers/openai/responses-provider.ts +18 -0
- package/src/providers/placeholder-sentinels.ts +18 -8
- package/src/providers/retry.ts +1 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
- package/src/providers/speech-to-text/provider-catalog.ts +0 -89
- package/src/providers/speech-to-text/resolve.ts +55 -0
- package/src/providers/tool-progress-events.test.ts +50 -0
- package/src/providers/tool-progress-events.ts +99 -0
- package/src/providers/types.ts +1 -1
- package/src/providers/vellum-model-routing.test.ts +51 -0
- package/src/providers/vellum-model-routing.ts +84 -0
- package/src/runtime/AGENTS.md +5 -4
- package/src/runtime/__tests__/agent-wake.test.ts +158 -1
- package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
- package/src/runtime/access-request-helper.ts +154 -3
- package/src/runtime/actor-trust-resolver.ts +7 -21
- package/src/runtime/agent-wake.ts +41 -1
- package/src/runtime/assistant-event.ts +86 -12
- package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
- package/src/runtime/channel-approval-types.ts +52 -2
- package/src/runtime/channel-approvals.ts +23 -8
- package/src/runtime/channel-invite-transport.ts +2 -2
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-readiness-service.ts +3 -5
- package/src/runtime/channel-retry-sweep.ts +18 -24
- package/src/runtime/channel-verification-service.ts +9 -11
- package/src/runtime/finalize-event-delivery.ts +30 -16
- package/src/runtime/guardian-action-service.ts +10 -11
- package/src/runtime/guardian-reply-router.ts +122 -21
- package/src/runtime/http-server.ts +44 -101
- package/src/runtime/introduction-policy.test.ts +214 -0
- package/src/runtime/introduction-policy.ts +284 -0
- package/src/runtime/invite-service.ts +104 -361
- package/src/runtime/local-actor-identity.test.ts +38 -0
- package/src/runtime/local-actor-identity.ts +14 -0
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
- package/src/runtime/middleware/rate-limiter.ts +30 -0
- package/src/runtime/middleware/twilio-validation.ts +5 -7
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
- package/src/runtime/migrations/origin-mode.ts +6 -6
- package/src/runtime/pre-first-message-gate.ts +1 -0
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
- package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
- package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
- package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
- package/src/runtime/routes/acp-routes.ts +15 -3
- package/src/runtime/routes/app-management-routes.ts +4 -7
- package/src/runtime/routes/approval-routes.ts +4 -0
- package/src/runtime/routes/attachment-routes.ts +54 -3
- package/src/runtime/routes/avatar-routes.ts +0 -4
- package/src/runtime/routes/background-tool-routes.ts +34 -5
- package/src/runtime/routes/btw-routes.ts +32 -4
- package/src/runtime/routes/channel-route-shared.ts +18 -14
- package/src/runtime/routes/channel-verification-routes.ts +0 -3
- package/src/runtime/routes/contact-routes.ts +298 -117
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +74 -37
- package/src/runtime/routes/conversation-query-routes.ts +5 -2
- package/src/runtime/routes/conversation-routes.ts +222 -82
- package/src/runtime/routes/conversations-import-routes.ts +8 -1
- package/src/runtime/routes/credential-prompt-routes.ts +20 -5
- package/src/runtime/routes/debug-routes.ts +1 -0
- package/src/runtime/routes/documents-routes.ts +5 -2
- package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
- package/src/runtime/routes/global-search-routes.ts +2 -1
- package/src/runtime/routes/guardian-approval-interception.ts +51 -0
- package/src/runtime/routes/home-feed-routes.ts +60 -1
- package/src/runtime/routes/identity-routes.ts +4 -87
- package/src/runtime/routes/inbound-message-handler.ts +82 -41
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
- package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
- package/src/runtime/routes/internal-twilio-routes.ts +0 -15
- package/src/runtime/routes/messages-lexical-routes.ts +75 -0
- package/src/runtime/routes/migration-routes.ts +69 -6
- package/src/runtime/routes/monitoring-routes.ts +237 -0
- package/src/runtime/routes/plugins-routes.ts +329 -8
- package/src/runtime/routes/schedule-routes.ts +49 -8
- package/src/runtime/routes/schedule-worker-routes.ts +210 -0
- package/src/runtime/routes/secret-routes.ts +1 -1
- package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
- package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
- package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
- package/src/runtime/services/analyze-conversation.ts +14 -4
- package/src/runtime/services/conversation-serializer.ts +5 -0
- package/src/runtime/slack-no-response.ts +47 -0
- package/src/runtime/slack-reply-session.test.ts +633 -0
- package/src/runtime/slack-reply-session.ts +382 -0
- package/src/runtime/slack-task-progress.ts +95 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/tool-grant-request-helper.ts +17 -1
- package/src/runtime/trust-class.test.ts +141 -0
- package/src/runtime/trust-class.ts +121 -0
- package/src/runtime/trust-verdict-consumer.ts +7 -6
- package/src/schedule/__tests__/run-script.test.ts +21 -0
- package/src/schedule/__tests__/worker-control.test.ts +241 -0
- package/src/schedule/run-script.ts +13 -6
- package/src/schedule/schedule-usage-store.ts +1 -0
- package/src/schedule/scheduler.ts +178 -127
- package/src/schedule/worker-control.ts +118 -0
- package/src/schedule/worker.ts +131 -0
- package/src/skills/__tests__/categories-cache.test.ts +38 -0
- package/src/skills/categories-cache.ts +40 -5
- package/src/skills/managed-store.ts +41 -6
- package/src/skills/validate-input.ts +47 -0
- package/src/stt/types.ts +5 -9
- package/src/subagent/manager.ts +267 -39
- package/src/subagent/types.ts +6 -2
- package/src/subagent/validate-allowlists.ts +65 -0
- package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
- package/src/telemetry/watchdog-direct-emit.ts +89 -0
- package/src/tools/acp/list-agents.test.ts +0 -6
- package/src/tools/background-tool-registry.ts +61 -0
- package/src/tools/document/document-comment-tool.test.ts +4 -0
- package/src/tools/host-terminal/host-shell.test.ts +397 -0
- package/src/tools/host-terminal/host-shell.ts +203 -14
- package/src/tools/skills/find-similar-skills.test.ts +152 -1
- package/src/tools/skills/find-similar-skills.ts +30 -4
- package/src/tools/skills/load.ts +36 -0
- package/src/tools/skills/scaffold-managed.ts +66 -34
- package/src/tools/skills/skill-script-runner.ts +17 -0
- package/src/tools/skills/skill-tool-factory.ts +5 -1
- package/src/tools/terminal/safe-env.ts +3 -0
- package/src/tools/terminal/shell.test.ts +177 -0
- package/src/tools/terminal/shell.ts +98 -4
- package/src/tools/tool-approval-handler.ts +106 -29
- package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
- package/src/tools/types.ts +29 -17
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/tts/__tests__/provider-adapters.test.ts +37 -0
- package/src/tts/__tests__/provider-catalog.test.ts +21 -0
- package/src/tts/provider-catalog.ts +40 -9
- package/src/tts/providers/fish-audio-provider.ts +19 -10
- package/src/tts/types.ts +3 -4
- package/src/util/__tests__/process-tree.test.ts +10 -2
- package/src/util/__tests__/text-spacing.test.ts +53 -0
- package/src/util/cgroup-memory.ts +142 -0
- package/src/util/image-conversion.ts +281 -0
- package/src/util/phone.ts +1 -8
- package/src/util/platform.ts +33 -0
- package/src/util/process-tree.ts +10 -2
- package/src/util/text-spacing.ts +53 -0
- package/src/util/worker-process.ts +271 -0
- package/src/workflows/journal-store.ts +16 -1
- package/src/workflows/library.test.ts +35 -20
- package/src/workflows/library.ts +105 -66
- package/src/workspace/git-service.ts +1 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
- package/src/workspace/migrations/118-seed-now-md.ts +64 -0
- package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
- package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
- package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
- package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
- package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
- package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
- package/src/workspace/migrations/registry.ts +12 -0
- package/drizzle/0000_dizzy_maggott.sql +0 -301
- package/drizzle/meta/0000_snapshot.json +0 -1933
- package/drizzle/meta/_journal.json +0 -13
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
- package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
- package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
- package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
- package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
- package/src/__tests__/invite-redemption-service.test.ts +0 -1180
- package/src/__tests__/invite-service-ipc.test.ts +0 -350
- package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
- package/src/__tests__/relay-server.test.ts +0 -6153
- package/src/__tests__/telephony-stt-routing.test.ts +0 -329
- package/src/__tests__/voice-invite-redemption.test.ts +0 -702
- package/src/calls/relay-server.ts +0 -2463
- package/src/calls/telephony-stt-routing.ts +0 -145
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
- package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
- package/src/daemon/daemon-skill-host.ts +0 -262
- package/src/daemon/message-types/meet.ts +0 -143
- package/src/daemon/shutdown-registry.ts +0 -40
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
- package/src/ipc/__tests__/skill-server.test.ts +0 -182
- package/src/ipc/skill-ipc-types.ts +0 -54
- package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
- package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
- package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
- package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
- package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
- package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
- package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
- package/src/ipc/skill-routes/config.ts +0 -47
- package/src/ipc/skill-routes/events.ts +0 -147
- package/src/ipc/skill-routes/identity.ts +0 -21
- package/src/ipc/skill-routes/index.ts +0 -37
- package/src/ipc/skill-routes/log.ts +0 -40
- package/src/ipc/skill-routes/memory.ts +0 -92
- package/src/ipc/skill-routes/platform.ts +0 -39
- package/src/ipc/skill-routes/providers.ts +0 -162
- package/src/ipc/skill-routes/registries.ts +0 -338
- package/src/ipc/skill-server.ts +0 -831
- package/src/ipc/skill-socket-path.ts +0 -20
- package/src/jobs/register-job-handlers.ts +0 -74
- package/src/persistence/invite-store.ts +0 -481
- package/src/plugins/job-handler-registry.ts +0 -94
- package/src/providers/cache-control.ts +0 -26
- package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
- package/src/runtime/invite-redemption-service.ts +0 -828
- package/src/runtime/invite-redemption-templates.ts +0 -46
- package/src/runtime/runtime-mode.ts +0 -40
- package/src/runtime/slack-dm-text-delivery.ts +0 -177
- package/src/util/voice-code.ts +0 -31
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
recordCompactionEndBestEffort,
|
|
29
29
|
recordCompactionStartBestEffort,
|
|
30
30
|
} from "../persistence/compaction-log-store-clickhouse.js";
|
|
31
|
-
import { projectAssistantMessage } from "../persistence/conversation-attention-store.js";
|
|
32
31
|
import {
|
|
33
32
|
deleteMessageById,
|
|
34
33
|
getConversation,
|
|
@@ -42,12 +41,14 @@ import {
|
|
|
42
41
|
updateMessageContent,
|
|
43
42
|
} from "../persistence/conversation-crud.js";
|
|
44
43
|
import { syncMessageToDisk } from "../persistence/conversation-disk-view.js";
|
|
44
|
+
import { enqueueLexicalIndexForMessage } from "../persistence/job-handlers/message-lexical.js";
|
|
45
45
|
import {
|
|
46
46
|
backfillMessageIdOnLogs,
|
|
47
47
|
buildProviderErrorResponsePayload,
|
|
48
48
|
recordRequestLog,
|
|
49
49
|
setAgentLoopExitReasonOnLatestLog,
|
|
50
50
|
} from "../persistence/llm-request-log-store.js";
|
|
51
|
+
import { endSection, markSection } from "../persistence/slow-sync-log.js";
|
|
51
52
|
import type { ContextWindowResult } from "../plugins/defaults/compaction/window-manager.js";
|
|
52
53
|
import { indexMessageNow } from "../plugins/defaults/memory/indexer.js";
|
|
53
54
|
import { backfillMemoryRecallLogMessageId } from "../plugins/defaults/memory/memory-recall-log-store.js";
|
|
@@ -59,7 +60,6 @@ import type {
|
|
|
59
60
|
Message,
|
|
60
61
|
} from "../providers/types.js";
|
|
61
62
|
import { getCurrentSeq } from "../runtime/assistant-stream-state.js";
|
|
62
|
-
import { publishSyncInvalidation } from "../runtime/sync/sync-publisher.js";
|
|
63
63
|
import { redactSecrets } from "../security/secret-scanner.js";
|
|
64
64
|
import { extractDomain } from "../tools/network/domain-normalize.js";
|
|
65
65
|
import {
|
|
@@ -74,6 +74,7 @@ import {
|
|
|
74
74
|
import { ProviderError } from "../util/errors.js";
|
|
75
75
|
import { faviconUrlForDomain } from "../util/favicon.js";
|
|
76
76
|
import { getLogger } from "../util/logger.js";
|
|
77
|
+
import { withSqliteRetry } from "../util/sqlite-retry.js";
|
|
77
78
|
import type { DirectiveRequest } from "./assistant-attachments.js";
|
|
78
79
|
import {
|
|
79
80
|
cleanAssistantContent,
|
|
@@ -86,6 +87,7 @@ import {
|
|
|
86
87
|
classifyConversationError,
|
|
87
88
|
maxTokensReachedClassification,
|
|
88
89
|
} from "./conversation-error.js";
|
|
90
|
+
import { buildDeferredFinalizeEffect } from "./conversation-turn-finalize.js";
|
|
89
91
|
import { resolveTurnTimezoneContext } from "./date-context.js";
|
|
90
92
|
import type {
|
|
91
93
|
CardSurfaceData,
|
|
@@ -93,7 +95,6 @@ import type {
|
|
|
93
95
|
SurfaceAction,
|
|
94
96
|
UiSurfaceShow,
|
|
95
97
|
} from "./message-protocol.js";
|
|
96
|
-
import { conversationMetadataSyncTag } from "./message-types/sync.js";
|
|
97
98
|
import type {
|
|
98
99
|
ToolActivityMetadata,
|
|
99
100
|
WebSearchMetadata,
|
|
@@ -317,6 +318,18 @@ export interface EventHandlerState {
|
|
|
317
318
|
* latency segment. Advances on every `handleUsage`.
|
|
318
319
|
*/
|
|
319
320
|
latencyCursor: number;
|
|
321
|
+
/**
|
|
322
|
+
* Non-critical finalize side-effects deferred off the turn's critical path —
|
|
323
|
+
* one closure per assistant message that completes (memory segment indexing,
|
|
324
|
+
* lexical indexing, attention projection). `handleMessageComplete` persists
|
|
325
|
+
* the message content synchronously (so a snapshot/refetch on the terminal
|
|
326
|
+
* `message_complete` SSE still sees the full reply) and pushes these
|
|
327
|
+
* follow-ups here; the orchestrator drains them after the terminal SSE has
|
|
328
|
+
* re-enabled the composer but before the next turn can start. Each closure is
|
|
329
|
+
* individually best-effort. Accumulates across retries/multi-call turns so
|
|
330
|
+
* every produced assistant row is indexed.
|
|
331
|
+
*/
|
|
332
|
+
readonly deferredFinalizeEffects: Array<() => Promise<void>>;
|
|
320
333
|
}
|
|
321
334
|
|
|
322
335
|
/** Immutable context shared across event handlers within a single agent loop run. */
|
|
@@ -405,6 +418,7 @@ export function createEventHandlerState(): EventHandlerState {
|
|
|
405
418
|
lastPersistedContentSeq: undefined,
|
|
406
419
|
compactionStartMessages: new Map(),
|
|
407
420
|
latencyCursor: 0,
|
|
421
|
+
deferredFinalizeEffects: [],
|
|
408
422
|
};
|
|
409
423
|
}
|
|
410
424
|
|
|
@@ -470,12 +484,18 @@ export function stampThinkingTiming(
|
|
|
470
484
|
content: ContentBlock[],
|
|
471
485
|
timings: ReadonlyArray<{ startedAt: number; completedAt: number }>,
|
|
472
486
|
): ContentBlock[] {
|
|
473
|
-
if (timings.length === 0)
|
|
487
|
+
if (timings.length === 0) {
|
|
488
|
+
return content;
|
|
489
|
+
}
|
|
474
490
|
let thinkingIdx = 0;
|
|
475
491
|
return content.map((block) => {
|
|
476
|
-
if (block.type !== "thinking")
|
|
492
|
+
if (block.type !== "thinking") {
|
|
493
|
+
return block;
|
|
494
|
+
}
|
|
477
495
|
const timing = timings[thinkingIdx++];
|
|
478
|
-
if (!timing)
|
|
496
|
+
if (!timing) {
|
|
497
|
+
return block;
|
|
498
|
+
}
|
|
479
499
|
return {
|
|
480
500
|
...block,
|
|
481
501
|
_startedAt: timing.startedAt,
|
|
@@ -489,7 +509,9 @@ function appendTextToCurrentMessage(
|
|
|
489
509
|
state: EventHandlerState,
|
|
490
510
|
text: string,
|
|
491
511
|
): void {
|
|
492
|
-
if (text.length === 0)
|
|
512
|
+
if (text.length === 0) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
493
515
|
const tail = state.currentMessageContent.at(-1);
|
|
494
516
|
if (tail && tail.type === "text") {
|
|
495
517
|
tail.text = tail.text + text;
|
|
@@ -509,13 +531,17 @@ function appendThinkingToCurrentMessage(
|
|
|
509
531
|
state: EventHandlerState,
|
|
510
532
|
thinking: string,
|
|
511
533
|
): void {
|
|
512
|
-
if (thinking.length === 0)
|
|
534
|
+
if (thinking.length === 0) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
513
537
|
const now = Date.now();
|
|
514
538
|
const tail = state.currentMessageContent.at(-1);
|
|
515
539
|
if (tail && tail.type === "thinking") {
|
|
516
540
|
tail.thinking = tail.thinking + thinking;
|
|
517
541
|
const timing = state.currentThinkingTimestamps.at(-1);
|
|
518
|
-
if (timing)
|
|
542
|
+
if (timing) {
|
|
543
|
+
timing.completedAt = now;
|
|
544
|
+
}
|
|
519
545
|
} else {
|
|
520
546
|
state.currentMessageContent.push({
|
|
521
547
|
type: "thinking",
|
|
@@ -538,14 +564,51 @@ function resetPartialPersistAccumulator(state: EventHandlerState): void {
|
|
|
538
564
|
state.pendingPartialFlushPromise = undefined;
|
|
539
565
|
}
|
|
540
566
|
|
|
567
|
+
/**
|
|
568
|
+
* Persist an in-loop message-content write, retrying transient SQLite write
|
|
569
|
+
* contention (`SQLITE_BUSY`/`SQLITE_IOERR`) and swallowing a final failure so a
|
|
570
|
+
* lock held by another writer cannot abort the turn. Every in-loop write
|
|
571
|
+
* rewrites the full content snapshot of its assistant/tool-result row, so a
|
|
572
|
+
* dropped write is overwritten by a later write in the same turn (the
|
|
573
|
+
* end-of-turn finalize) or the next turn — missing one is a self-healing
|
|
574
|
+
* cosmetic gap, not corruption.
|
|
575
|
+
*
|
|
576
|
+
* Returns whether the write committed, so callers can gate dependent
|
|
577
|
+
* bookkeeping (e.g. advancing the persisted seq) on durable content.
|
|
578
|
+
*/
|
|
579
|
+
async function persistLoopMessageContent(
|
|
580
|
+
messageId: string,
|
|
581
|
+
contentJson: string,
|
|
582
|
+
op: string,
|
|
583
|
+
rlog: pino.Logger,
|
|
584
|
+
): Promise<boolean> {
|
|
585
|
+
try {
|
|
586
|
+
await withSqliteRetry(() => updateMessageContent(messageId, contentJson), {
|
|
587
|
+
op,
|
|
588
|
+
context: { messageId },
|
|
589
|
+
});
|
|
590
|
+
return true;
|
|
591
|
+
} catch (err) {
|
|
592
|
+
rlog.error(
|
|
593
|
+
{ err, messageId, op },
|
|
594
|
+
"in-loop message-content write failed after retries; continuing without interrupting the turn",
|
|
595
|
+
);
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
541
600
|
/** Flush `state.currentMessageContent` to the persisted assistant row. */
|
|
542
601
|
async function flushAccumulatedContent(
|
|
543
602
|
state: EventHandlerState,
|
|
544
603
|
deps: EventHandlerDeps,
|
|
545
604
|
): Promise<void> {
|
|
546
605
|
const messageId = state.lastAssistantMessageId;
|
|
547
|
-
if (messageId === undefined)
|
|
548
|
-
|
|
606
|
+
if (messageId === undefined) {
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
if (state.currentMessageContent.length === 0) {
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
549
612
|
|
|
550
613
|
const built = buildPersistedAssistantContent(
|
|
551
614
|
state.currentMessageContent,
|
|
@@ -558,18 +621,16 @@ async function flushAccumulatedContent(
|
|
|
558
621
|
// again, but they are not part of this write.
|
|
559
622
|
const flushedSeq = state.lastPersistedContentSeq;
|
|
560
623
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
"partial flush of accumulated assistant content failed; finalize at message_complete will recover",
|
|
572
|
-
);
|
|
624
|
+
const persisted = await persistLoopMessageContent(
|
|
625
|
+
messageId,
|
|
626
|
+
contentJson,
|
|
627
|
+
"partial_flush_assistant_content",
|
|
628
|
+
deps.rlog,
|
|
629
|
+
);
|
|
630
|
+
// Record only after the write commits, so the snapshot seq never
|
|
631
|
+
// claims content that is not yet durable.
|
|
632
|
+
if (persisted && flushedSeq != null) {
|
|
633
|
+
recordConversationPersistedSeq(deps.ctx.conversationId, flushedSeq);
|
|
573
634
|
}
|
|
574
635
|
}
|
|
575
636
|
|
|
@@ -578,7 +639,9 @@ function schedulePartialFlush(
|
|
|
578
639
|
state: EventHandlerState,
|
|
579
640
|
deps: EventHandlerDeps,
|
|
580
641
|
): void {
|
|
581
|
-
if (state.pendingPartialFlushTimer !== undefined)
|
|
642
|
+
if (state.pendingPartialFlushTimer !== undefined) {
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
582
645
|
state.pendingPartialFlushTimer = setTimeout(() => {
|
|
583
646
|
state.pendingPartialFlushTimer = undefined;
|
|
584
647
|
const flushPromise = flushAccumulatedContent(state, deps);
|
|
@@ -607,7 +670,9 @@ function emitLlmCallStartedIfNeeded(
|
|
|
607
670
|
deps: EventHandlerDeps,
|
|
608
671
|
providerNameOverride?: string,
|
|
609
672
|
): void {
|
|
610
|
-
if (state.llmCallStartedEmitted)
|
|
673
|
+
if (state.llmCallStartedEmitted) {
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
611
676
|
state.llmCallStartedEmitted = true;
|
|
612
677
|
const providerName = providerNameOverride ?? deps.ctx.provider.name;
|
|
613
678
|
deps.ctx.traceEmitter.emit(
|
|
@@ -662,9 +727,13 @@ export function formatSearchStatusText(
|
|
|
662
727
|
toolName: string,
|
|
663
728
|
query: string,
|
|
664
729
|
): string {
|
|
665
|
-
if (toolName !== "web_search")
|
|
730
|
+
if (toolName !== "web_search") {
|
|
731
|
+
return `Running ${toolName}`;
|
|
732
|
+
}
|
|
666
733
|
const trimmed = query.trim();
|
|
667
|
-
if (!trimmed)
|
|
734
|
+
if (!trimmed) {
|
|
735
|
+
return "Searching the web";
|
|
736
|
+
}
|
|
668
737
|
const truncated =
|
|
669
738
|
trimmed.length > 60 ? trimmed.slice(0, 57) + "..." : trimmed;
|
|
670
739
|
return `Searching "${truncated}"`;
|
|
@@ -675,9 +744,13 @@ export function formatSearchStatusText(
|
|
|
675
744
|
* Surfaces the domain so users can tell what page is being read.
|
|
676
745
|
*/
|
|
677
746
|
export function formatFetchStatusText(url: unknown): string {
|
|
678
|
-
if (typeof url !== "string")
|
|
747
|
+
if (typeof url !== "string") {
|
|
748
|
+
return "Reading a page";
|
|
749
|
+
}
|
|
679
750
|
const domain = extractDomain(url);
|
|
680
|
-
if (!domain)
|
|
751
|
+
if (!domain) {
|
|
752
|
+
return "Reading a page";
|
|
753
|
+
}
|
|
681
754
|
return `Reading ${domain}`;
|
|
682
755
|
}
|
|
683
756
|
|
|
@@ -858,7 +931,9 @@ function handleTextDelta(
|
|
|
858
931
|
conversationId: deps.ctx.conversationId,
|
|
859
932
|
messageId: state.lastAssistantMessageId,
|
|
860
933
|
});
|
|
861
|
-
if (deps.shouldGenerateTitle)
|
|
934
|
+
if (deps.shouldGenerateTitle) {
|
|
935
|
+
state.firstAssistantText += drained.emitText;
|
|
936
|
+
}
|
|
862
937
|
// Mirror the drained delta into state.currentMessageContent so partial
|
|
863
938
|
// flushes mid-turn see the same content the user is watching live.
|
|
864
939
|
appendTextToCurrentMessage(state, drained.emitText);
|
|
@@ -894,7 +969,9 @@ function handleThinkingDelta(
|
|
|
894
969
|
});
|
|
895
970
|
}
|
|
896
971
|
}
|
|
897
|
-
if (!deps.ctx.streamThinking)
|
|
972
|
+
if (!deps.ctx.streamThinking) {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
898
975
|
emitLlmCallStartedIfNeeded(state, deps);
|
|
899
976
|
deps.onEvent({
|
|
900
977
|
type: "assistant_thinking_delta",
|
|
@@ -1081,7 +1158,9 @@ export function handleInputJsonDelta(
|
|
|
1081
1158
|
// Only forward input deltas for app tools — the client only uses this
|
|
1082
1159
|
// stream for app_create code previews. Non-app tools would send large
|
|
1083
1160
|
// cumulative JSON on every delta with no benefit.
|
|
1084
|
-
if (!APP_TOOL_NAMES.has(event.toolName))
|
|
1161
|
+
if (!APP_TOOL_NAMES.has(event.toolName)) {
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1085
1164
|
deps.onEvent({
|
|
1086
1165
|
type: "tool_input_delta",
|
|
1087
1166
|
toolName: event.toolName,
|
|
@@ -1180,7 +1259,9 @@ async function persistPendingToolResultRow(
|
|
|
1180
1259
|
deps: EventHandlerDeps,
|
|
1181
1260
|
seq: number,
|
|
1182
1261
|
): Promise<void> {
|
|
1183
|
-
if (state.pendingToolResults.size === 0)
|
|
1262
|
+
if (state.pendingToolResults.size === 0) {
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1184
1265
|
const rowId = await ensureToolResultRowReserved(
|
|
1185
1266
|
state,
|
|
1186
1267
|
deps.ctx.conversationId,
|
|
@@ -1188,11 +1269,15 @@ async function persistPendingToolResultRow(
|
|
|
1188
1269
|
);
|
|
1189
1270
|
// Serialize the content after the reservation resolves so the last of the
|
|
1190
1271
|
// concurrent writers reflects the fullest batch.
|
|
1191
|
-
|
|
1272
|
+
const persisted = await persistLoopMessageContent(
|
|
1192
1273
|
rowId,
|
|
1193
1274
|
JSON.stringify(buildToolResultBlocks(state.pendingToolResults)),
|
|
1275
|
+
"persist_tool_result_row",
|
|
1276
|
+
deps.rlog,
|
|
1194
1277
|
);
|
|
1195
|
-
|
|
1278
|
+
if (persisted) {
|
|
1279
|
+
recordConversationPersistedSeq(deps.ctx.conversationId, seq);
|
|
1280
|
+
}
|
|
1196
1281
|
const conv = getConversation(deps.ctx.conversationId);
|
|
1197
1282
|
if (conv != null) {
|
|
1198
1283
|
syncMessageToDisk(deps.ctx.conversationId, rowId, conv.createdAt);
|
|
@@ -1213,7 +1298,9 @@ export async function finalizePendingToolResultRow(
|
|
|
1213
1298
|
metadata: Record<string, unknown>,
|
|
1214
1299
|
rlog: pino.Logger,
|
|
1215
1300
|
): Promise<void> {
|
|
1216
|
-
if (state.pendingToolResults.size === 0)
|
|
1301
|
+
if (state.pendingToolResults.size === 0) {
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1217
1304
|
const rowId = await ensureToolResultRowReserved(
|
|
1218
1305
|
state,
|
|
1219
1306
|
conversationId,
|
|
@@ -1222,7 +1309,12 @@ export async function finalizePendingToolResultRow(
|
|
|
1222
1309
|
const contentJson = JSON.stringify(
|
|
1223
1310
|
buildToolResultBlocks(state.pendingToolResults),
|
|
1224
1311
|
);
|
|
1225
|
-
|
|
1312
|
+
await persistLoopMessageContent(
|
|
1313
|
+
rowId,
|
|
1314
|
+
contentJson,
|
|
1315
|
+
"finalize_tool_result_row",
|
|
1316
|
+
rlog,
|
|
1317
|
+
);
|
|
1226
1318
|
// Sync the row to the JSONL disk view so it stays in lockstep with the DB.
|
|
1227
1319
|
// `getConversation` returns `ConversationRow | null`, so `!= null` gates on a
|
|
1228
1320
|
// real row (skipping the sync when the conversation was not found rather than
|
|
@@ -1277,6 +1369,10 @@ export async function finalizePendingToolResultRow(
|
|
|
1277
1369
|
"Failed to index tool-result message for memory (non-fatal)",
|
|
1278
1370
|
);
|
|
1279
1371
|
}
|
|
1372
|
+
// Dual-write the finalized tool-result content into the lexical index. The
|
|
1373
|
+
// reserve+finalize path bypasses `onMessagePersisted`, so enqueue here to
|
|
1374
|
+
// keep the lexical index in lockstep with the segment index.
|
|
1375
|
+
enqueueLexicalIndexForMessage(rowId);
|
|
1280
1376
|
}
|
|
1281
1377
|
for (const id of state.pendingToolResults.keys()) {
|
|
1282
1378
|
state.persistedToolUseIds.add(id);
|
|
@@ -1350,7 +1446,9 @@ export async function handleToolResult(
|
|
|
1350
1446
|
// Record tool completion timestamp
|
|
1351
1447
|
const completedAt = Date.now();
|
|
1352
1448
|
const ts = state.toolCallTimestamps.get(event.toolUseId);
|
|
1353
|
-
if (ts)
|
|
1449
|
+
if (ts) {
|
|
1450
|
+
ts.completedAt = completedAt;
|
|
1451
|
+
}
|
|
1354
1452
|
state.currentToolUseId = undefined;
|
|
1355
1453
|
|
|
1356
1454
|
// Capture risk metadata when present. autoApproved is true when the tool
|
|
@@ -1502,10 +1600,14 @@ function recordToolStartOnPersistedMessage(
|
|
|
1502
1600
|
startedAt: number,
|
|
1503
1601
|
): void {
|
|
1504
1602
|
const messageId = state.lastAssistantMessageId;
|
|
1505
|
-
if (!messageId)
|
|
1603
|
+
if (!messageId) {
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1506
1606
|
|
|
1507
1607
|
const row = getMessageById(messageId);
|
|
1508
|
-
if (!row)
|
|
1608
|
+
if (!row) {
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1509
1611
|
|
|
1510
1612
|
let content: ContentBlock[];
|
|
1511
1613
|
try {
|
|
@@ -1515,12 +1617,28 @@ function recordToolStartOnPersistedMessage(
|
|
|
1515
1617
|
}
|
|
1516
1618
|
|
|
1517
1619
|
for (const block of content) {
|
|
1518
|
-
if (block.type !== "tool_use")
|
|
1620
|
+
if (block.type !== "tool_use") {
|
|
1621
|
+
continue;
|
|
1622
|
+
}
|
|
1519
1623
|
const rec = block as unknown as Record<string, unknown>;
|
|
1520
|
-
if (rec.id !== toolUseId)
|
|
1521
|
-
|
|
1624
|
+
if (rec.id !== toolUseId) {
|
|
1625
|
+
continue;
|
|
1626
|
+
}
|
|
1627
|
+
if (rec._startedAt === startedAt) {
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1522
1630
|
rec._startedAt = startedAt;
|
|
1523
|
-
|
|
1631
|
+
// Best-effort early stamp: `annotatePersistedAssistantMessage` re-stamps
|
|
1632
|
+
// once every tool in the turn completes, so a transient `SQLITE_BUSY` here
|
|
1633
|
+
// must not abort the turn — the end-of-turn write recovers it.
|
|
1634
|
+
try {
|
|
1635
|
+
updateMessageContent(messageId, JSON.stringify(content));
|
|
1636
|
+
} catch (err) {
|
|
1637
|
+
log.error(
|
|
1638
|
+
{ err, messageId },
|
|
1639
|
+
"stamping tool start time failed; end-of-turn annotation will recover",
|
|
1640
|
+
);
|
|
1641
|
+
}
|
|
1524
1642
|
return;
|
|
1525
1643
|
}
|
|
1526
1644
|
}
|
|
@@ -1541,10 +1659,14 @@ function recordToolPreviewStartOnPersistedMessage(
|
|
|
1541
1659
|
previewStartedAt: number,
|
|
1542
1660
|
): void {
|
|
1543
1661
|
const messageId = state.lastAssistantMessageId;
|
|
1544
|
-
if (!messageId)
|
|
1662
|
+
if (!messageId) {
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1545
1665
|
|
|
1546
1666
|
const row = getMessageById(messageId);
|
|
1547
|
-
if (!row)
|
|
1667
|
+
if (!row) {
|
|
1668
|
+
return;
|
|
1669
|
+
}
|
|
1548
1670
|
|
|
1549
1671
|
let content: ContentBlock[];
|
|
1550
1672
|
try {
|
|
@@ -1554,12 +1676,28 @@ function recordToolPreviewStartOnPersistedMessage(
|
|
|
1554
1676
|
}
|
|
1555
1677
|
|
|
1556
1678
|
for (const block of content) {
|
|
1557
|
-
if (block.type !== "tool_use")
|
|
1679
|
+
if (block.type !== "tool_use") {
|
|
1680
|
+
continue;
|
|
1681
|
+
}
|
|
1558
1682
|
const rec = block as unknown as Record<string, unknown>;
|
|
1559
|
-
if (rec.id !== toolUseId)
|
|
1560
|
-
|
|
1683
|
+
if (rec.id !== toolUseId) {
|
|
1684
|
+
continue;
|
|
1685
|
+
}
|
|
1686
|
+
if (rec._previewStartedAt === previewStartedAt) {
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1561
1689
|
rec._previewStartedAt = previewStartedAt;
|
|
1562
|
-
|
|
1690
|
+
// Best-effort early stamp, mirroring `recordToolStartOnPersistedMessage`:
|
|
1691
|
+
// `annotatePersistedAssistantMessage` re-stamps at end of turn, so a
|
|
1692
|
+
// transient `SQLITE_BUSY` here must not abort the turn.
|
|
1693
|
+
try {
|
|
1694
|
+
updateMessageContent(messageId, JSON.stringify(content));
|
|
1695
|
+
} catch (err) {
|
|
1696
|
+
log.error(
|
|
1697
|
+
{ err, messageId },
|
|
1698
|
+
"stamping tool preview-start time failed; end-of-turn annotation will recover",
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1563
1701
|
return;
|
|
1564
1702
|
}
|
|
1565
1703
|
}
|
|
@@ -1575,10 +1713,14 @@ function annotatePersistedAssistantMessage(
|
|
|
1575
1713
|
deps: EventHandlerDeps,
|
|
1576
1714
|
): void {
|
|
1577
1715
|
const messageId = state.lastAssistantMessageId;
|
|
1578
|
-
if (!messageId)
|
|
1716
|
+
if (!messageId) {
|
|
1717
|
+
return;
|
|
1718
|
+
}
|
|
1579
1719
|
|
|
1580
1720
|
const row = getMessageById(messageId);
|
|
1581
|
-
if (!row)
|
|
1721
|
+
if (!row) {
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1582
1724
|
|
|
1583
1725
|
let content: ContentBlock[];
|
|
1584
1726
|
try {
|
|
@@ -1592,7 +1734,9 @@ function annotatePersistedAssistantMessage(
|
|
|
1592
1734
|
if (block.type === "tool_use") {
|
|
1593
1735
|
const rec = block as unknown as Record<string, unknown>;
|
|
1594
1736
|
const id = rec.id as string | undefined;
|
|
1595
|
-
if (!id)
|
|
1737
|
+
if (!id) {
|
|
1738
|
+
continue;
|
|
1739
|
+
}
|
|
1596
1740
|
|
|
1597
1741
|
const ts = state.toolCallTimestamps.get(id);
|
|
1598
1742
|
if (ts) {
|
|
@@ -1616,26 +1760,38 @@ function annotatePersistedAssistantMessage(
|
|
|
1616
1760
|
const risk = state.toolRiskOutcomes.get(id);
|
|
1617
1761
|
if (risk) {
|
|
1618
1762
|
rec._riskLevel = risk.riskLevel;
|
|
1619
|
-
if (risk.riskReason)
|
|
1763
|
+
if (risk.riskReason) {
|
|
1764
|
+
rec._riskReason = risk.riskReason;
|
|
1765
|
+
}
|
|
1620
1766
|
rec._autoApproved = risk.autoApproved;
|
|
1621
|
-
if (risk.matchedTrustRuleId)
|
|
1767
|
+
if (risk.matchedTrustRuleId) {
|
|
1622
1768
|
rec._matchedTrustRuleId = risk.matchedTrustRuleId;
|
|
1623
|
-
|
|
1624
|
-
if (risk.
|
|
1625
|
-
|
|
1769
|
+
}
|
|
1770
|
+
if (risk.approvalMode) {
|
|
1771
|
+
rec._approvalMode = risk.approvalMode;
|
|
1772
|
+
}
|
|
1773
|
+
if (risk.approvalReason) {
|
|
1774
|
+
rec._approvalReason = risk.approvalReason;
|
|
1775
|
+
}
|
|
1776
|
+
if (risk.riskThreshold) {
|
|
1777
|
+
rec._riskThreshold = risk.riskThreshold;
|
|
1778
|
+
}
|
|
1626
1779
|
// Persist the 3 risk-option arrays so the rule editor's chip ladder
|
|
1627
1780
|
// survives chat-history reload. These mirror the same-named fields
|
|
1628
1781
|
// on the live `tool_result` event; clients should read them back via
|
|
1629
1782
|
// `shared.ts` and treat them identically to the live values.
|
|
1630
|
-
if (risk.riskScopeOptions && risk.riskScopeOptions.length > 0)
|
|
1783
|
+
if (risk.riskScopeOptions && risk.riskScopeOptions.length > 0) {
|
|
1631
1784
|
rec._riskScopeOptions = risk.riskScopeOptions;
|
|
1632
|
-
|
|
1785
|
+
}
|
|
1786
|
+
if (risk.riskAllowlistOptions && risk.riskAllowlistOptions.length > 0) {
|
|
1633
1787
|
rec._riskAllowlistOptions = risk.riskAllowlistOptions;
|
|
1788
|
+
}
|
|
1634
1789
|
if (
|
|
1635
1790
|
risk.riskDirectoryScopeOptions &&
|
|
1636
1791
|
risk.riskDirectoryScopeOptions.length > 0
|
|
1637
|
-
)
|
|
1792
|
+
) {
|
|
1638
1793
|
rec._riskDirectoryScopeOptions = risk.riskDirectoryScopeOptions;
|
|
1794
|
+
}
|
|
1639
1795
|
modified = true;
|
|
1640
1796
|
}
|
|
1641
1797
|
// External provider tools (brave/perplexity/tavily) + web_fetch produce
|
|
@@ -1680,6 +1836,10 @@ function annotatePersistedAssistantMessage(
|
|
|
1680
1836
|
}
|
|
1681
1837
|
|
|
1682
1838
|
if (modified) {
|
|
1839
|
+
// This end-of-turn write is best-effort: the caller wraps it in a
|
|
1840
|
+
// try/catch (and `dispatchAgentEvent` swallows `tool_result` handler
|
|
1841
|
+
// errors), so a transient `SQLITE_BUSY` here is logged and the turn
|
|
1842
|
+
// continues — it never reaches the turn-level catch.
|
|
1683
1843
|
updateMessageContent(messageId, JSON.stringify(content));
|
|
1684
1844
|
}
|
|
1685
1845
|
|
|
@@ -1845,8 +2005,9 @@ export async function handleMessageComplete(
|
|
|
1845
2005
|
conversationId: deps.ctx.conversationId,
|
|
1846
2006
|
messageId: state.lastAssistantMessageId,
|
|
1847
2007
|
});
|
|
1848
|
-
if (deps.shouldGenerateTitle)
|
|
2008
|
+
if (deps.shouldGenerateTitle) {
|
|
1849
2009
|
state.firstAssistantText += state.pendingDirectiveDisplayBuffer;
|
|
2010
|
+
}
|
|
1850
2011
|
state.pendingDirectiveDisplayBuffer = "";
|
|
1851
2012
|
}
|
|
1852
2013
|
|
|
@@ -1917,7 +2078,12 @@ export async function handleMessageComplete(
|
|
|
1917
2078
|
);
|
|
1918
2079
|
}
|
|
1919
2080
|
const contentJson = JSON.stringify(contentForPersistence);
|
|
1920
|
-
|
|
2081
|
+
const persisted = await persistLoopMessageContent(
|
|
2082
|
+
assistantMessageId,
|
|
2083
|
+
contentJson,
|
|
2084
|
+
"finalize_assistant_message",
|
|
2085
|
+
deps.rlog,
|
|
2086
|
+
);
|
|
1921
2087
|
state.assistantRowAwaitingFinalization = false;
|
|
1922
2088
|
// The assistant row now holds the authoritative content (text + thinking +
|
|
1923
2089
|
// tool_use blocks from `event.message`), and any drained tool-result rows
|
|
@@ -1927,8 +2093,9 @@ export async function handleMessageComplete(
|
|
|
1927
2093
|
// turn, so this seq already covers it; a call that streams no content (a
|
|
1928
2094
|
// pure tool call) advances instead via `tool_use_start`.
|
|
1929
2095
|
// `recordConversationPersistedSeq` clamps monotonically, so a lower value
|
|
1930
|
-
// here never regresses the seq.
|
|
1931
|
-
|
|
2096
|
+
// here never regresses the seq. Gate on `persisted` so a swallowed finalize
|
|
2097
|
+
// write never advances the seq past content that is not durable.
|
|
2098
|
+
if (persisted && state.lastPersistedContentSeq != null) {
|
|
1932
2099
|
recordConversationPersistedSeq(
|
|
1933
2100
|
deps.ctx.conversationId,
|
|
1934
2101
|
state.lastPersistedContentSeq,
|
|
@@ -1940,89 +2107,24 @@ export async function handleMessageComplete(
|
|
|
1940
2107
|
state.currentThinkingTimestamps = [];
|
|
1941
2108
|
state.lastPersistedContentSeq = undefined;
|
|
1942
2109
|
|
|
1943
|
-
// ── Indexing + attention projection ──
|
|
1944
|
-
// `reserveMessage` + `updateMessageContent` are CRUD-only
|
|
1945
|
-
// the memory indexer or the attention-cursor
|
|
1946
|
-
//
|
|
1947
|
-
//
|
|
1948
|
-
//
|
|
1949
|
-
//
|
|
1950
|
-
//
|
|
1951
|
-
//
|
|
1952
|
-
//
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
2110
|
+
// ── Indexing + attention projection (deferred off the critical path) ──
|
|
2111
|
+
// `reserveMessage` + `updateMessageContent` are CRUD-only — unlike
|
|
2112
|
+
// `addMessage`, they don't run the memory indexer or the attention-cursor
|
|
2113
|
+
// projector as insert side-effects — so the assistant row's external state
|
|
2114
|
+
// must be brought into lockstep explicitly. Neither gates delivery of the
|
|
2115
|
+
// reply or the composer re-enabling, so the work is queued here and drained
|
|
2116
|
+
// by the orchestrator after the terminal `message_complete` SSE fires (but
|
|
2117
|
+
// before the next turn). See `conversation-turn-finalize.ts`. The content
|
|
2118
|
+
// persisted synchronously above, so a snapshot/refetch on `message_complete`
|
|
2119
|
+
// still sees the full reply.
|
|
2120
|
+
state.deferredFinalizeEffects.push(
|
|
2121
|
+
buildDeferredFinalizeEffect({
|
|
2122
|
+
conversationId: deps.ctx.conversationId,
|
|
2123
|
+
assistantMessageId,
|
|
2124
|
+
contentJson,
|
|
2125
|
+
rlog: deps.rlog,
|
|
2126
|
+
}),
|
|
1957
2127
|
);
|
|
1958
|
-
if (finalizedRow) {
|
|
1959
|
-
let provenanceTrustClass:
|
|
1960
|
-
| "guardian"
|
|
1961
|
-
| "trusted_contact"
|
|
1962
|
-
| "unverified_contact"
|
|
1963
|
-
| "unknown"
|
|
1964
|
-
| undefined;
|
|
1965
|
-
let automated: boolean | undefined;
|
|
1966
|
-
if (finalizedRow.metadata) {
|
|
1967
|
-
try {
|
|
1968
|
-
const parsedMeta = messageMetadataSchema.safeParse(
|
|
1969
|
-
JSON.parse(finalizedRow.metadata),
|
|
1970
|
-
);
|
|
1971
|
-
if (parsedMeta.success) {
|
|
1972
|
-
provenanceTrustClass = parsedMeta.data.provenanceTrustClass;
|
|
1973
|
-
automated = parsedMeta.data.automated;
|
|
1974
|
-
}
|
|
1975
|
-
} catch {
|
|
1976
|
-
// Malformed metadata JSON — fall through with undefined fields,
|
|
1977
|
-
// matching the legacy behavior in `addMessage`.
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
try {
|
|
1981
|
-
await indexMessageNow(
|
|
1982
|
-
{
|
|
1983
|
-
messageId: assistantMessageId,
|
|
1984
|
-
conversationId: deps.ctx.conversationId,
|
|
1985
|
-
role: "assistant",
|
|
1986
|
-
content: contentJson,
|
|
1987
|
-
createdAt: finalizedRow.createdAt,
|
|
1988
|
-
scopeId: "default",
|
|
1989
|
-
provenanceTrustClass,
|
|
1990
|
-
automated,
|
|
1991
|
-
},
|
|
1992
|
-
getConfig().memory,
|
|
1993
|
-
);
|
|
1994
|
-
} catch (err) {
|
|
1995
|
-
deps.rlog.warn(
|
|
1996
|
-
{
|
|
1997
|
-
err,
|
|
1998
|
-
conversationId: deps.ctx.conversationId,
|
|
1999
|
-
messageId: assistantMessageId,
|
|
2000
|
-
},
|
|
2001
|
-
"Failed to index assistant message for memory (non-fatal)",
|
|
2002
|
-
);
|
|
2003
|
-
}
|
|
2004
|
-
try {
|
|
2005
|
-
const attentionStateChanged = projectAssistantMessage({
|
|
2006
|
-
conversationId: deps.ctx.conversationId,
|
|
2007
|
-
messageId: assistantMessageId,
|
|
2008
|
-
messageAt: finalizedRow.createdAt,
|
|
2009
|
-
});
|
|
2010
|
-
if (attentionStateChanged) {
|
|
2011
|
-
void publishSyncInvalidation([
|
|
2012
|
-
conversationMetadataSyncTag(deps.ctx.conversationId),
|
|
2013
|
-
]);
|
|
2014
|
-
}
|
|
2015
|
-
} catch (err) {
|
|
2016
|
-
deps.rlog.warn(
|
|
2017
|
-
{
|
|
2018
|
-
err,
|
|
2019
|
-
conversationId: deps.ctx.conversationId,
|
|
2020
|
-
messageId: assistantMessageId,
|
|
2021
|
-
},
|
|
2022
|
-
"Failed to project assistant message for attention tracking (non-fatal)",
|
|
2023
|
-
);
|
|
2024
|
-
}
|
|
2025
|
-
}
|
|
2026
2128
|
|
|
2027
2129
|
// Backfill message_id on all LLM request logs from this turn.
|
|
2028
2130
|
// The agent loop is single-threaded per conversation, so all rows with
|
|
@@ -2298,6 +2400,11 @@ export async function dispatchAgentEvent(
|
|
|
2298
2400
|
deps: EventHandlerDeps,
|
|
2299
2401
|
event: AgentEvent,
|
|
2300
2402
|
): Promise<void> {
|
|
2403
|
+
// Section-trail breadcrumb for event-loop freeze attribution: the dispatch
|
|
2404
|
+
// is the single choke point for per-turn persistence work (message writes,
|
|
2405
|
+
// usage/request-log rows, SSE fan-out), so a watchdog report during a
|
|
2406
|
+
// handler names the event type that was being processed.
|
|
2407
|
+
const sectionMark = markSection(`agent-event:${event.type}`);
|
|
2301
2408
|
try {
|
|
2302
2409
|
switch (event.type) {
|
|
2303
2410
|
case "llm_call_started":
|
|
@@ -2605,5 +2712,7 @@ export async function dispatchAgentEvent(
|
|
|
2605
2712
|
) {
|
|
2606
2713
|
throw err;
|
|
2607
2714
|
}
|
|
2715
|
+
} finally {
|
|
2716
|
+
endSection(sectionMark);
|
|
2608
2717
|
}
|
|
2609
2718
|
}
|