@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
|
@@ -34,10 +34,6 @@ import {
|
|
|
34
34
|
} from "../config/llm-resolver.js";
|
|
35
35
|
import { getConfig } from "../config/loader.js";
|
|
36
36
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
37
|
-
import {
|
|
38
|
-
derefToolResultReReads,
|
|
39
|
-
postTurnTruncateToolResults,
|
|
40
|
-
} from "../context/post-turn-tool-result-truncation.js";
|
|
41
37
|
import { writeRelationshipState } from "../home/relationship-state-writer.js";
|
|
42
38
|
import {
|
|
43
39
|
clearSentryConversationContext,
|
|
@@ -56,8 +52,6 @@ import {
|
|
|
56
52
|
updateConversationContextWindow,
|
|
57
53
|
updateConversationSlackContextWatermark,
|
|
58
54
|
} from "../persistence/conversation-crud.js";
|
|
59
|
-
import { getResolvedConversationDirPath } from "../persistence/conversation-directories.js";
|
|
60
|
-
import { syncMessageToDisk } from "../persistence/conversation-disk-view.js";
|
|
61
55
|
import { isReplaceableTitle } from "../persistence/conversation-title-service.js";
|
|
62
56
|
import {
|
|
63
57
|
backfillMessageIdOnLogs,
|
|
@@ -81,6 +75,7 @@ import { timeAgo } from "../util/time.js";
|
|
|
81
75
|
import { truncate } from "../util/truncate.js";
|
|
82
76
|
import { getWorkspaceGitService } from "../workspace/git-service.js";
|
|
83
77
|
import { commitTurnChanges } from "../workspace/turn-commit.js";
|
|
78
|
+
import { ABORT_WATCHDOG_MS } from "./abort-watchdog.js";
|
|
84
79
|
import { cleanAssistantContent } from "./assistant-attachments.js";
|
|
85
80
|
import { conversationSupportsDynamicUi } from "./channel-ui-capability.js";
|
|
86
81
|
import type { Conversation } from "./conversation.js";
|
|
@@ -113,6 +108,7 @@ import {
|
|
|
113
108
|
type SlackChronologicalContext,
|
|
114
109
|
} from "./conversation-runtime-assembly.js";
|
|
115
110
|
import { markSurfaceCompleted } from "./conversation-surfaces.js";
|
|
111
|
+
import { runDeferredTurnTail } from "./conversation-turn-finalize.js";
|
|
116
112
|
import { recordUsage } from "./conversation-usage.js";
|
|
117
113
|
import { resolveTurnTimezoneContext } from "./date-context.js";
|
|
118
114
|
import { getDiskPressureStatus } from "./disk-pressure-guard.js";
|
|
@@ -197,28 +193,25 @@ export interface AssistantSurface {
|
|
|
197
193
|
// ── abort watchdog ───────────────────────────────────────────────────
|
|
198
194
|
|
|
199
195
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
196
|
+
* Race `work` against an abort watchdog. The watchdog is a backstop that drives
|
|
197
|
+
* an aborted turn to its `finally` even if some awaited operation fails to
|
|
198
|
+
* observe the abort signal. Abort is otherwise cooperative and already wired
|
|
199
|
+
* into the slow paths: the provider call forwards the signal to its
|
|
200
|
+
* HTTP/streaming fetch, and tool execution races the signal so a stuck tool
|
|
201
|
+
* can't block cancellation. The watchdog only fires when a future code path
|
|
202
|
+
* silently ignores abort — without it, such a path would hang the loop forever
|
|
203
|
+
* and latch the conversation's `processing` flag true (the wedged "Thinking…"
|
|
204
|
+
* indicator). It is defense-in-depth, not the primary mechanism: in the common
|
|
205
|
+
* case abort settles in-flight work in well under a second, so ABORT_WATCHDOG_MS
|
|
206
|
+
* is ample headroom for a cooperative unwind while still releasing a genuinely
|
|
207
|
+
* wedged turn promptly.
|
|
202
208
|
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* defense-in-depth, not the primary mechanism: in the common case abort settles
|
|
210
|
-
* in-flight work in well under a second, so a few seconds is ample headroom for
|
|
211
|
-
* a cooperative unwind while still releasing a genuinely wedged turn promptly.
|
|
212
|
-
*/
|
|
213
|
-
const ABORT_WATCHDOG_MS = 5_000;
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Race `work` against an abort watchdog. The watchdog stays disarmed until the
|
|
217
|
-
* signal fires; once it does, the turn has `timeoutMs` to settle before the
|
|
218
|
-
* watchdog rejects with the signal's own abort reason so the caller unwinds to
|
|
219
|
-
* its `finally` and the reason classifies as a user cancellation downstream.
|
|
220
|
-
* The abandoned `work` promise keeps running detached — its eventual rejection
|
|
221
|
-
* is swallowed so it can't surface as an unhandled rejection.
|
|
209
|
+
* The watchdog stays disarmed until the signal fires; once it does, the turn has
|
|
210
|
+
* `timeoutMs` to settle before the watchdog rejects with the signal's own abort
|
|
211
|
+
* reason so the caller unwinds to its `finally` and the reason classifies as a
|
|
212
|
+
* user cancellation downstream. The abandoned `work` promise keeps running
|
|
213
|
+
* detached — its eventual rejection is swallowed so it can't surface as an
|
|
214
|
+
* unhandled rejection.
|
|
222
215
|
*/
|
|
223
216
|
async function withAbortWatchdog<T>(
|
|
224
217
|
work: Promise<T>,
|
|
@@ -267,6 +260,13 @@ export async function runAgentLoopImpl(
|
|
|
267
260
|
isInteractive?: boolean;
|
|
268
261
|
isUserMessage?: boolean;
|
|
269
262
|
titleText?: string;
|
|
263
|
+
/**
|
|
264
|
+
* True when the triggering message is a transcript-suppressed machine
|
|
265
|
+
* signal (`metadata.hidden`). Forwarded to the user-prompt-submit hook
|
|
266
|
+
* context so prompt-as-user-speech consumers (title generation) skip
|
|
267
|
+
* the turn.
|
|
268
|
+
*/
|
|
269
|
+
isHiddenPrompt?: boolean;
|
|
270
270
|
/**
|
|
271
271
|
* LLM call-site identifier threaded into the per-call provider config.
|
|
272
272
|
* Adapter callers (heartbeat, filing, scheduler, etc.) pass their own
|
|
@@ -317,6 +317,13 @@ export async function runAgentLoopImpl(
|
|
|
317
317
|
ctx.currentTurnTrustContext = ctx.trustContext;
|
|
318
318
|
ctx.currentTurnChannelCapabilities = ctx.channelCapabilities;
|
|
319
319
|
|
|
320
|
+
// Re-resolve the system prompt under the snapshots just set and push it into
|
|
321
|
+
// the loop when the persona changed. The loop reuses the prompt frozen at
|
|
322
|
+
// construction otherwise, so a flow that binds trust after construction (a
|
|
323
|
+
// voice call resolves the caller only after `getOrCreateConversation`) would
|
|
324
|
+
// run the whole conversation under the construction-time persona.
|
|
325
|
+
ctx.syncLoopSystemPrompt();
|
|
326
|
+
|
|
320
327
|
const abortController = ctx.abortController;
|
|
321
328
|
const reqId = ctx.currentRequestId ?? uuid();
|
|
322
329
|
// First-token latency instrumentation for this turn. Stamped here at the
|
|
@@ -846,6 +853,13 @@ export async function runAgentLoopImpl(
|
|
|
846
853
|
timeSinceLastMessage,
|
|
847
854
|
};
|
|
848
855
|
|
|
856
|
+
// Freeze the turn-start client OS for the same anti-race reason as the
|
|
857
|
+
// timezone above: the live `ctx.clientOs` is re-applied from transport
|
|
858
|
+
// whenever a newer message for this conversation arrives mid-turn, so the
|
|
859
|
+
// assembly reads this frozen copy to avoid leaking a queued message's
|
|
860
|
+
// `client_os` into the in-flight turn.
|
|
861
|
+
ctx.currentTurnClientOs = ctx.clientOs ?? undefined;
|
|
862
|
+
|
|
849
863
|
// Resolve the effective profile key for this turn and detect changes.
|
|
850
864
|
// `modelProfileKey` is the actual profile used for this turn. The
|
|
851
865
|
// notice key is narrower: it only marks turns where runtime context should
|
|
@@ -895,6 +909,7 @@ export async function runAgentLoopImpl(
|
|
|
895
909
|
userMessageId,
|
|
896
910
|
requestId: reqId,
|
|
897
911
|
prompt: options?.titleText ?? content,
|
|
912
|
+
isHiddenPrompt: options?.isHiddenPrompt === true,
|
|
898
913
|
originalMessages: ctx.messages,
|
|
899
914
|
latestMessages: ctx.messages,
|
|
900
915
|
logger: rlog,
|
|
@@ -1031,6 +1046,10 @@ export async function runAgentLoopImpl(
|
|
|
1031
1046
|
};
|
|
1032
1047
|
|
|
1033
1048
|
const updatedHistory = await runAgentLoop(runMessages, true);
|
|
1049
|
+
// Generation is done streaming. Anything awaited between here and the
|
|
1050
|
+
// terminal SSE is what the user perceives as the gap between the last
|
|
1051
|
+
// token and the composer re-enabling, so keep that window minimal.
|
|
1052
|
+
const generationCompletedAt = Date.now();
|
|
1034
1053
|
|
|
1035
1054
|
rlog.info(
|
|
1036
1055
|
{ resultMessageCount: updatedHistory.length },
|
|
@@ -1290,39 +1309,18 @@ export async function runAgentLoopImpl(
|
|
|
1290
1309
|
0,
|
|
1291
1310
|
updatedHistory.length - lastRunNewMessages.length,
|
|
1292
1311
|
);
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
// Post-turn tool result truncation: save large results to disk and
|
|
1296
|
-
// replace in-context content with a prefix/suffix stub + file pointer.
|
|
1297
|
-
try {
|
|
1298
|
-
const conv = getConversation(ctx.conversationId);
|
|
1299
|
-
if (conv) {
|
|
1300
|
-
const convDir = getResolvedConversationDirPath(
|
|
1301
|
-
ctx.conversationId,
|
|
1302
|
-
conv.createdAt,
|
|
1303
|
-
);
|
|
1304
|
-
const { messages: derefMessages, dereferencedCount } =
|
|
1305
|
-
derefToolResultReReads(restoredHistory);
|
|
1306
|
-
const { messages: truncatedMessages, truncatedCount } =
|
|
1307
|
-
postTurnTruncateToolResults(derefMessages, {
|
|
1308
|
-
conversationDir: convDir,
|
|
1309
|
-
});
|
|
1310
|
-
if (truncatedCount > 0 || dereferencedCount > 0) {
|
|
1311
|
-
rlog.info(
|
|
1312
|
-
{ truncatedCount, dereferencedCount },
|
|
1313
|
-
"Post-turn tool result truncation applied",
|
|
1314
|
-
);
|
|
1315
|
-
}
|
|
1316
|
-
restoredHistory = truncatedMessages;
|
|
1317
|
-
}
|
|
1318
|
-
} catch (err) {
|
|
1319
|
-
rlog.warn({ err }, "Post-turn tool result truncation failed (non-fatal)");
|
|
1320
|
-
}
|
|
1312
|
+
const restoredHistory = [...loopBase, ...newMessages];
|
|
1321
1313
|
|
|
1322
1314
|
// Persist injections in history: runtime-injected context stays on
|
|
1323
1315
|
// historical user messages so the conversation prefix is stable for
|
|
1324
1316
|
// Anthropic's prefix caching. Stripping only happens during
|
|
1325
1317
|
// compaction/overflow recovery (where a cache miss is expected).
|
|
1318
|
+
//
|
|
1319
|
+
// Post-turn tool-result truncation (spooling large results to disk and
|
|
1320
|
+
// shrinking the next turn's context) is deferred to `runDeferredTurnTail`
|
|
1321
|
+
// below. It only rewrites the in-memory history the NEXT turn is built
|
|
1322
|
+
// from — never the just-delivered reply — so it must not sit on the
|
|
1323
|
+
// critical path to the terminal SSE that re-enables the composer.
|
|
1326
1324
|
ctx.messages = restoredHistory;
|
|
1327
1325
|
|
|
1328
1326
|
emitUsage(
|
|
@@ -1349,21 +1347,11 @@ export async function runAgentLoopImpl(
|
|
|
1349
1347
|
turnCronRunId,
|
|
1350
1348
|
);
|
|
1351
1349
|
|
|
1352
|
-
const syncLastAssistantMessageToDisk = (): void => {
|
|
1353
|
-
if (!state.lastAssistantMessageId) return;
|
|
1354
|
-
const convForDisk = getConversation(ctx.conversationId);
|
|
1355
|
-
if (!convForDisk) return;
|
|
1356
|
-
syncMessageToDisk(
|
|
1357
|
-
ctx.conversationId,
|
|
1358
|
-
state.lastAssistantMessageId,
|
|
1359
|
-
convForDisk.createdAt,
|
|
1360
|
-
);
|
|
1361
|
-
};
|
|
1362
1350
|
// Fast-path: when the user cancelled, skip expensive post-loop work
|
|
1363
1351
|
// (attachment resolution) and emit the cancellation event immediately
|
|
1364
|
-
// so the client can re-enable the UI without delay.
|
|
1352
|
+
// so the client can re-enable the UI without delay. Disk sync and the rest
|
|
1353
|
+
// of the bookkeeping run in `runDeferredTurnTail` after this SSE.
|
|
1365
1354
|
if (abortController.signal.aborted) {
|
|
1366
|
-
syncLastAssistantMessageToDisk();
|
|
1367
1355
|
ctx.emitActivityState("idle", "generation_cancelled", {
|
|
1368
1356
|
anchor: "global",
|
|
1369
1357
|
requestId: reqId,
|
|
@@ -1403,7 +1391,6 @@ export async function runAgentLoopImpl(
|
|
|
1403
1391
|
|
|
1404
1392
|
ctx.lastAssistantAttachments = assistantAttachments;
|
|
1405
1393
|
ctx.lastAttachmentWarnings = attachmentResult.directiveWarnings;
|
|
1406
|
-
syncLastAssistantMessageToDisk();
|
|
1407
1394
|
|
|
1408
1395
|
// Re-check: the user may have cancelled during attachment resolution
|
|
1409
1396
|
if (abortController.signal.aborted) {
|
|
@@ -1484,6 +1471,12 @@ export async function runAgentLoopImpl(
|
|
|
1484
1471
|
publishLoopMessagesChanged();
|
|
1485
1472
|
}
|
|
1486
1473
|
}
|
|
1474
|
+
|
|
1475
|
+
// The terminal SSE for this turn has now been emitted (message_complete,
|
|
1476
|
+
// generation_handoff, or generation_cancelled), so the composer is already
|
|
1477
|
+
// re-enabling. Drain the deferred bookkeeping now — after the SSE, before
|
|
1478
|
+
// the `finally` commits and drains the queue for the next turn.
|
|
1479
|
+
await runDeferredTurnTail({ ctx, state, rlog, generationCompletedAt });
|
|
1487
1480
|
} catch (err) {
|
|
1488
1481
|
clearConversationNotices(ctx.conversationId);
|
|
1489
1482
|
const errorCtx = {
|
|
@@ -156,7 +156,7 @@ const CANCEL_PATTERNS = [/abort/i, /cancel/i];
|
|
|
156
156
|
*/
|
|
157
157
|
export interface ErrorContext {
|
|
158
158
|
/** Where in the processing pipeline the error occurred. */
|
|
159
|
-
phase: "agent_loop" | "
|
|
159
|
+
phase: "agent_loop" | "handler" | "persist";
|
|
160
160
|
/** Whether the abort signal was active when the error occurred. */
|
|
161
161
|
aborted?: boolean;
|
|
162
162
|
/**
|
|
@@ -266,20 +266,6 @@ export function classifyConversationError(
|
|
|
266
266
|
};
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
// Phase-specific overrides
|
|
270
|
-
if (ctx.phase === "regenerate") {
|
|
271
|
-
const base = classifyCore(error, message, attribution);
|
|
272
|
-
return {
|
|
273
|
-
code: "REGENERATE_FAILED",
|
|
274
|
-
userMessage: `Could not regenerate the response. ${base.userMessage}`,
|
|
275
|
-
retryable: true,
|
|
276
|
-
debugDetails,
|
|
277
|
-
errorCategory: `regenerate:${base.errorCategory}`,
|
|
278
|
-
...(base.connectionName ? { connectionName: base.connectionName } : {}),
|
|
279
|
-
...(base.profileName ? { profileName: base.profileName } : {}),
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
|
|
283
269
|
// Classify using statusCode (if ProviderError) then regex fallback
|
|
284
270
|
const classified = classifyCore(error, message, attribution);
|
|
285
271
|
return {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { v4 as uuid } from "uuid";
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
deleteLastExchange,
|
|
5
3
|
deleteMessageById,
|
|
@@ -10,14 +8,12 @@ import {
|
|
|
10
8
|
import { isLastUserMessageToolResult } from "../persistence/conversation-queries.js";
|
|
11
9
|
import { withQdrantBreaker } from "../persistence/embeddings/qdrant-circuit-breaker.js";
|
|
12
10
|
import { getQdrantClient } from "../persistence/embeddings/qdrant-client.js";
|
|
11
|
+
import { enqueueLexicalIndexForMessage } from "../persistence/job-handlers/message-lexical.js";
|
|
13
12
|
import { enqueueMemoryJob } from "../persistence/jobs-store.js";
|
|
14
13
|
import { relinkLlmRequestLogs } from "../persistence/llm-request-log-store.js";
|
|
15
14
|
import { getSummaryFromContextMessage } from "../plugins/defaults/compaction/window-manager.js";
|
|
16
15
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
17
16
|
import { getLogger } from "../util/logger.js";
|
|
18
|
-
import { truncate } from "../util/truncate.js";
|
|
19
|
-
import type { ServerMessage } from "./message-protocol.js";
|
|
20
|
-
import type { TraceEmitter } from "./trace-emitter.js";
|
|
21
17
|
|
|
22
18
|
const log = getLogger("conversation-history");
|
|
23
19
|
|
|
@@ -34,7 +30,9 @@ export function isToolResultBlock(
|
|
|
34
30
|
function isSystemNoticeBlock(
|
|
35
31
|
block: ContentBlock | Record<string, unknown>,
|
|
36
32
|
): boolean {
|
|
37
|
-
if (block.type !== "text")
|
|
33
|
+
if (block.type !== "text") {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
38
36
|
const text = (block as { text?: string }).text ?? "";
|
|
39
37
|
return (
|
|
40
38
|
text.startsWith("<system_notice>") && text.endsWith("</system_notice>")
|
|
@@ -42,8 +40,12 @@ function isSystemNoticeBlock(
|
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
function isUndoableUserMessage(message: Message): boolean {
|
|
45
|
-
if (message.role !== "user")
|
|
46
|
-
|
|
43
|
+
if (message.role !== "user") {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (getSummaryFromContextMessage(message) != null) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
47
49
|
// A user message is undoable if it contains user-authored content (non-tool_result
|
|
48
50
|
// blocks). Messages that contain ONLY tool_result blocks (e.g. automated tool
|
|
49
51
|
// responses) are not undoable. Messages that have both tool_result and text blocks
|
|
@@ -53,7 +55,9 @@ function isUndoableUserMessage(message: Message): boolean {
|
|
|
53
55
|
const hasNonToolResultContent = message.content.some(
|
|
54
56
|
(block) => !isToolResultBlock(block) && !isSystemNoticeBlock(block),
|
|
55
57
|
);
|
|
56
|
-
if (!hasNonToolResultContent)
|
|
58
|
+
if (!hasNonToolResultContent) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
57
61
|
return true;
|
|
58
62
|
}
|
|
59
63
|
|
|
@@ -84,7 +88,9 @@ async function cleanupQdrantVectors(
|
|
|
84
88
|
return; // Qdrant not initialized — nothing to clean up.
|
|
85
89
|
}
|
|
86
90
|
|
|
87
|
-
if (segmentIds.length === 0)
|
|
91
|
+
if (segmentIds.length === 0) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
88
94
|
|
|
89
95
|
const targets: Array<{ targetType: string; targetId: string }> = [];
|
|
90
96
|
for (const segId of segmentIds) {
|
|
@@ -122,7 +128,7 @@ async function cleanupQdrantVectors(
|
|
|
122
128
|
failed,
|
|
123
129
|
segments: segmentIds.length,
|
|
124
130
|
},
|
|
125
|
-
"Cleaned up Qdrant vectors after
|
|
131
|
+
"Cleaned up Qdrant vectors after undo",
|
|
126
132
|
);
|
|
127
133
|
}
|
|
128
134
|
}
|
|
@@ -142,7 +148,9 @@ export function consolidateAssistantMessages(
|
|
|
142
148
|
): boolean {
|
|
143
149
|
const allMessages = getMessages(conversationId);
|
|
144
150
|
const userMsgIndex = allMessages.findIndex((m) => m.id === userMessageId);
|
|
145
|
-
if (userMsgIndex === -1)
|
|
151
|
+
if (userMsgIndex === -1) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
146
154
|
|
|
147
155
|
const messagesToConsolidate: typeof allMessages = [];
|
|
148
156
|
const internalToolResultMessages: typeof allMessages = [];
|
|
@@ -285,6 +293,11 @@ export function consolidateAssistantMessages(
|
|
|
285
293
|
firstAssistantMsg.id,
|
|
286
294
|
JSON.stringify(consolidatedContent),
|
|
287
295
|
);
|
|
296
|
+
// Consolidation changed the retained message's searchable text (merged in the
|
|
297
|
+
// other rows' blocks); `updateMessageContent` is CRUD-only, so reindex it into
|
|
298
|
+
// the lexical index. The merged-away rows' points are removed by
|
|
299
|
+
// `deleteMessageById` below.
|
|
300
|
+
enqueueLexicalIndexForMessage(firstAssistantMsg.id);
|
|
288
301
|
|
|
289
302
|
// Re-link attachments and LLM request logs from messages about to be
|
|
290
303
|
// deleted to the consolidated message. Without this, ON DELETE CASCADE on
|
|
@@ -345,26 +358,12 @@ export function consolidateAssistantMessages(
|
|
|
345
358
|
// ── Undo ─────────────────────────────────────────────────────────────
|
|
346
359
|
|
|
347
360
|
/**
|
|
348
|
-
* Subset of Conversation state that undo
|
|
361
|
+
* Subset of Conversation state that undo needs access to.
|
|
349
362
|
*/
|
|
350
363
|
export interface HistoryConversationContext {
|
|
351
364
|
readonly conversationId: string;
|
|
352
|
-
readonly traceEmitter: TraceEmitter;
|
|
353
|
-
/** @internal */ sendToClient: (msg: ServerMessage) => void;
|
|
354
365
|
messages: Message[];
|
|
355
366
|
isProcessing(): boolean;
|
|
356
|
-
setProcessing(value: boolean): void;
|
|
357
|
-
abortController: AbortController | null;
|
|
358
|
-
currentRequestId?: string;
|
|
359
|
-
runAgentLoop(
|
|
360
|
-
content: string,
|
|
361
|
-
userMessageId: string,
|
|
362
|
-
options?: {
|
|
363
|
-
onEvent?: (msg: ServerMessage) => void;
|
|
364
|
-
isUserMessage?: boolean;
|
|
365
|
-
titleText?: string;
|
|
366
|
-
},
|
|
367
|
-
): Promise<void>;
|
|
368
367
|
}
|
|
369
368
|
|
|
370
369
|
/**
|
|
@@ -372,10 +371,14 @@ export interface HistoryConversationContext {
|
|
|
372
371
|
* Returns the number of messages removed.
|
|
373
372
|
*/
|
|
374
373
|
export function undo(conversation: HistoryConversationContext): number {
|
|
375
|
-
if (conversation.isProcessing())
|
|
374
|
+
if (conversation.isProcessing()) {
|
|
375
|
+
return 0;
|
|
376
|
+
}
|
|
376
377
|
|
|
377
378
|
const lastUserIdx = findLastUndoableUserMessageIndex(conversation.messages);
|
|
378
|
-
if (lastUserIdx === -1)
|
|
379
|
+
if (lastUserIdx === -1) {
|
|
380
|
+
return 0;
|
|
381
|
+
}
|
|
379
382
|
|
|
380
383
|
const removed = conversation.messages.length - lastUserIdx;
|
|
381
384
|
conversation.messages = conversation.messages.slice(0, lastUserIdx);
|
|
@@ -406,210 +409,3 @@ export function undo(conversation: HistoryConversationContext): number {
|
|
|
406
409
|
|
|
407
410
|
return removed;
|
|
408
411
|
}
|
|
409
|
-
|
|
410
|
-
// ── Regenerate ───────────────────────────────────────────────────────
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Regenerate the last assistant response: remove the assistant's reply
|
|
414
|
-
* (and any intermediate tool_result messages) from memory, DB, and
|
|
415
|
-
* Qdrant, then re-run the agent loop with the same user message.
|
|
416
|
-
*/
|
|
417
|
-
export async function regenerate(
|
|
418
|
-
conversation: HistoryConversationContext,
|
|
419
|
-
requestId?: string,
|
|
420
|
-
): Promise<void> {
|
|
421
|
-
if (conversation.isProcessing()) {
|
|
422
|
-
conversation.sendToClient({
|
|
423
|
-
type: "error",
|
|
424
|
-
conversationId: conversation.conversationId,
|
|
425
|
-
message: "Cannot regenerate while processing",
|
|
426
|
-
});
|
|
427
|
-
if (requestId) {
|
|
428
|
-
conversation.traceEmitter.emit(
|
|
429
|
-
"request_error",
|
|
430
|
-
"Cannot regenerate while processing",
|
|
431
|
-
{
|
|
432
|
-
requestId,
|
|
433
|
-
status: "error",
|
|
434
|
-
attributes: { reason: "already_processing" },
|
|
435
|
-
},
|
|
436
|
-
);
|
|
437
|
-
}
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// Find the last undoable user message — everything after it is the
|
|
442
|
-
// assistant's exchange that we want to regenerate.
|
|
443
|
-
const lastUserIdx = findLastUndoableUserMessageIndex(conversation.messages);
|
|
444
|
-
if (lastUserIdx === -1) {
|
|
445
|
-
conversation.sendToClient({
|
|
446
|
-
type: "error",
|
|
447
|
-
conversationId: conversation.conversationId,
|
|
448
|
-
message: "No messages to regenerate",
|
|
449
|
-
});
|
|
450
|
-
if (requestId) {
|
|
451
|
-
conversation.traceEmitter.emit(
|
|
452
|
-
"request_error",
|
|
453
|
-
"No messages to regenerate",
|
|
454
|
-
{
|
|
455
|
-
requestId,
|
|
456
|
-
status: "error",
|
|
457
|
-
attributes: { reason: "no_messages" },
|
|
458
|
-
},
|
|
459
|
-
);
|
|
460
|
-
}
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// There must be at least one message after the user message (the assistant reply).
|
|
465
|
-
if (lastUserIdx >= conversation.messages.length - 1) {
|
|
466
|
-
conversation.sendToClient({
|
|
467
|
-
type: "error",
|
|
468
|
-
conversationId: conversation.conversationId,
|
|
469
|
-
message: "No assistant response to regenerate",
|
|
470
|
-
});
|
|
471
|
-
if (requestId) {
|
|
472
|
-
conversation.traceEmitter.emit(
|
|
473
|
-
"request_error",
|
|
474
|
-
"No assistant response to regenerate",
|
|
475
|
-
{
|
|
476
|
-
requestId,
|
|
477
|
-
status: "error",
|
|
478
|
-
attributes: { reason: "no_assistant_response" },
|
|
479
|
-
},
|
|
480
|
-
);
|
|
481
|
-
}
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Remove the assistant's exchange from in-memory history (keep the user message).
|
|
486
|
-
conversation.messages = conversation.messages.slice(0, lastUserIdx + 1);
|
|
487
|
-
|
|
488
|
-
// Find DB message IDs to delete: get all messages from the DB, then
|
|
489
|
-
// identify the ones that come after the last user message.
|
|
490
|
-
const dbMessages = getMessages(conversation.conversationId);
|
|
491
|
-
|
|
492
|
-
// Walk backwards to find the last real (non-tool_result) user message in the DB.
|
|
493
|
-
let dbUserMsgIdx = -1;
|
|
494
|
-
for (let i = dbMessages.length - 1; i >= 0; i--) {
|
|
495
|
-
if (dbMessages[i].role !== "user") continue;
|
|
496
|
-
try {
|
|
497
|
-
const parsed = JSON.parse(dbMessages[i].content);
|
|
498
|
-
if (
|
|
499
|
-
Array.isArray(parsed) &&
|
|
500
|
-
parsed.length > 0 &&
|
|
501
|
-
parsed.every((b: Record<string, unknown>) => isToolResultBlock(b))
|
|
502
|
-
) {
|
|
503
|
-
continue; // Skip tool_result-only user messages
|
|
504
|
-
}
|
|
505
|
-
} catch {
|
|
506
|
-
/* plain text = real user message */
|
|
507
|
-
}
|
|
508
|
-
dbUserMsgIdx = i;
|
|
509
|
-
break;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (dbUserMsgIdx === -1) {
|
|
513
|
-
conversation.sendToClient({
|
|
514
|
-
type: "error",
|
|
515
|
-
conversationId: conversation.conversationId,
|
|
516
|
-
message: "No user message found in DB",
|
|
517
|
-
});
|
|
518
|
-
if (requestId) {
|
|
519
|
-
conversation.traceEmitter.emit(
|
|
520
|
-
"request_error",
|
|
521
|
-
"No user message found in DB",
|
|
522
|
-
{
|
|
523
|
-
requestId,
|
|
524
|
-
status: "error",
|
|
525
|
-
attributes: { reason: "no_db_user_message" },
|
|
526
|
-
},
|
|
527
|
-
);
|
|
528
|
-
}
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
// Capture the existing DB user message ID so we can pass it to
|
|
533
|
-
// runAgentLoop without re-persisting the user message.
|
|
534
|
-
const existingUserMessageId = dbMessages[dbUserMsgIdx].id;
|
|
535
|
-
|
|
536
|
-
// Everything after the user message needs to be deleted.
|
|
537
|
-
const messagesToDelete = dbMessages.slice(dbUserMsgIdx + 1);
|
|
538
|
-
|
|
539
|
-
// Delete each message via deleteMessageById and collect IDs for Qdrant cleanup.
|
|
540
|
-
const allSegmentIds: string[] = [];
|
|
541
|
-
for (const msg of messagesToDelete) {
|
|
542
|
-
const deleted = deleteMessageById(msg.id);
|
|
543
|
-
allSegmentIds.push(...deleted.segmentIds);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
// Clean up Qdrant vectors (fire-and-forget).
|
|
547
|
-
cleanupQdrantVectors(conversation.conversationId, allSegmentIds).catch(
|
|
548
|
-
(err) => {
|
|
549
|
-
log.warn(
|
|
550
|
-
{ err, conversationId: conversation.conversationId },
|
|
551
|
-
"Qdrant cleanup after regenerate failed (non-fatal)",
|
|
552
|
-
);
|
|
553
|
-
},
|
|
554
|
-
);
|
|
555
|
-
|
|
556
|
-
// Re-extract the user message content for the agent loop.
|
|
557
|
-
// Use all content blocks (text, image, file) so attachments are
|
|
558
|
-
// preserved — not just text blocks.
|
|
559
|
-
const userMessage = conversation.messages[lastUserIdx];
|
|
560
|
-
const textBlocks = userMessage.content.filter((b) => b.type === "text");
|
|
561
|
-
const content = textBlocks
|
|
562
|
-
.map((b) => (b as { type: "text"; text: string }).text)
|
|
563
|
-
.join("");
|
|
564
|
-
|
|
565
|
-
// Notify client that the old response has been removed.
|
|
566
|
-
conversation.sendToClient({
|
|
567
|
-
type: "undo_complete",
|
|
568
|
-
removedCount: messagesToDelete.length,
|
|
569
|
-
conversationId: conversation.conversationId,
|
|
570
|
-
});
|
|
571
|
-
|
|
572
|
-
// Set up processing state manually and call runAgentLoop directly,
|
|
573
|
-
// bypassing processMessage to avoid duplicating the user message
|
|
574
|
-
// in both this.messages and the DB.
|
|
575
|
-
conversation.setProcessing(true);
|
|
576
|
-
conversation.abortController = new AbortController();
|
|
577
|
-
const resolvedRequestId = requestId ?? uuid();
|
|
578
|
-
conversation.currentRequestId = resolvedRequestId;
|
|
579
|
-
|
|
580
|
-
// Fire-and-forget: matches the /v1/messages pattern so the HTTP handler
|
|
581
|
-
// returns 202 immediately rather than blocking on the full agent turn.
|
|
582
|
-
// Otherwise the client's 15s POST timeout fires on any non-trivial
|
|
583
|
-
// regenerate and surfaces a misleading "Failed to regenerate message"
|
|
584
|
-
// banner even though the response streams in normally via SSE.
|
|
585
|
-
//
|
|
586
|
-
// runAgentLoop catches most errors internally and emits `request_error`
|
|
587
|
-
// itself, but anything thrown from its `finally` block (commit, drain,
|
|
588
|
-
// profiler) would otherwise escape silently because the caller does
|
|
589
|
-
// not await the agent loop. Emit a structured trace event so the
|
|
590
|
-
// observability contract is preserved on those paths too.
|
|
591
|
-
void conversation
|
|
592
|
-
.runAgentLoop(content, existingUserMessageId, {
|
|
593
|
-
isUserMessage: true,
|
|
594
|
-
})
|
|
595
|
-
.catch((err) => {
|
|
596
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
597
|
-
log.error(
|
|
598
|
-
{ err, conversationId: conversation.conversationId },
|
|
599
|
-
"runAgentLoop after regenerate failed",
|
|
600
|
-
);
|
|
601
|
-
conversation.traceEmitter.emit(
|
|
602
|
-
"request_error",
|
|
603
|
-
truncate(message, 200, ""),
|
|
604
|
-
{
|
|
605
|
-
requestId: resolvedRequestId,
|
|
606
|
-
status: "error",
|
|
607
|
-
attributes: {
|
|
608
|
-
errorClass: err instanceof Error ? err.constructor.name : "Error",
|
|
609
|
-
message: truncate(message, 500, ""),
|
|
610
|
-
source: "regenerate_fire_and_forget",
|
|
611
|
-
},
|
|
612
|
-
},
|
|
613
|
-
);
|
|
614
|
-
});
|
|
615
|
-
}
|