@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
|
@@ -44,6 +44,13 @@ export interface TrustContext {
|
|
|
44
44
|
memberStatus?: string;
|
|
45
45
|
/** Channel policy of the requester's channel (ACL). */
|
|
46
46
|
memberPolicy?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Prior-interaction count for the requester's member channel, sourced from
|
|
49
|
+
* the gateway trust verdict (gateway owns interaction telemetry). Undefined
|
|
50
|
+
* when the verdict carries no member telemetry (unknown sender) or when trust
|
|
51
|
+
* was resolved locally without a gateway verdict.
|
|
52
|
+
*/
|
|
53
|
+
requesterInteractionCount?: number;
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
/**
|
|
@@ -75,17 +82,25 @@ export const FALLBACK_TURN_TRUST: TrustContext = {
|
|
|
75
82
|
/**
|
|
76
83
|
* Resolve the effective trust class for an actor.
|
|
77
84
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
85
|
+
* Trust is a property of the actor, never of the deployment's auth posture.
|
|
86
|
+
* The dev/local bypass therefore fills in `'guardian'` only when NO actor was
|
|
87
|
+
* resolved: local/native turns reach the daemon without a channel-resolved
|
|
88
|
+
* trustContext, and in an auth-disabled (local) deployment that unresolved
|
|
89
|
+
* actor is the guardian. A *present* trustContext always reflects the real
|
|
90
|
+
* actor — even under `DISABLE_HTTP_AUTH`, which is the standing config in
|
|
91
|
+
* platform-managed deployments — so a resolved non-guardian channel actor is
|
|
92
|
+
* never elevated to guardian.
|
|
80
93
|
*
|
|
81
|
-
* When no trust context is available (e.g. desktop-only
|
|
82
|
-
*
|
|
83
|
-
* to fail-closed.
|
|
94
|
+
* When no trust context is available and auth is enabled (e.g. a desktop-only
|
|
95
|
+
* conversation that hasn't gone through channel trust resolution), defaults to
|
|
96
|
+
* `'unknown'` to fail-closed.
|
|
84
97
|
*/
|
|
85
98
|
export function resolveTrustClass(
|
|
86
99
|
trustContext: TrustContext | undefined,
|
|
87
100
|
): TrustClass {
|
|
88
|
-
if (isHttpAuthDisabled())
|
|
101
|
+
if (trustContext === undefined && isHttpAuthDisabled()) {
|
|
102
|
+
return "guardian";
|
|
103
|
+
}
|
|
89
104
|
return trustContext?.trustClass ?? "unknown";
|
|
90
105
|
}
|
|
91
106
|
|
|
@@ -115,6 +115,99 @@ describe("TurnLatencyTracker", () => {
|
|
|
115
115
|
expect(breakdown!.providerDurationMs).toBe(135);
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
+
test("a failed first attempt is superseded by the successful retry", () => {
|
|
119
|
+
const t = new TurnLatencyTracker();
|
|
120
|
+
clock = 0;
|
|
121
|
+
t.mark("turn_start");
|
|
122
|
+
clock = 10;
|
|
123
|
+
t.mark("prompt_hook_start"); // queue = 10
|
|
124
|
+
clock = 110;
|
|
125
|
+
t.mark("prompt_hook_end"); // memory_context = 100
|
|
126
|
+
// First attempt: tools resolved and request sent, then the provider
|
|
127
|
+
// rejects (context overflow) — no first_token, no call_complete.
|
|
128
|
+
clock = 120;
|
|
129
|
+
t.mark("tools_resolved");
|
|
130
|
+
clock = 130;
|
|
131
|
+
t.mark("request_sent");
|
|
132
|
+
// Recovery runs, then the loop re-issues the call.
|
|
133
|
+
clock = 1000;
|
|
134
|
+
t.mark("tools_resolved");
|
|
135
|
+
clock = 1010;
|
|
136
|
+
t.mark("request_sent");
|
|
137
|
+
clock = 1200;
|
|
138
|
+
t.markFirstToken("text");
|
|
139
|
+
clock = 1260;
|
|
140
|
+
t.mark("call_complete");
|
|
141
|
+
|
|
142
|
+
const { breakdown } = t.serializeSince(0);
|
|
143
|
+
// ttft / provider-duration reflect ONLY the successful attempt (1010),
|
|
144
|
+
// not the failed attempt's request_sent (130).
|
|
145
|
+
expect(breakdown!.ttftMs).toBe(190);
|
|
146
|
+
expect(breakdown!.providerDurationMs).toBe(250);
|
|
147
|
+
// The failed attempt's per-call marks are gone: no duplicate phases.
|
|
148
|
+
expect(breakdown!.phases.map((p) => p.key)).toEqual([
|
|
149
|
+
"queue",
|
|
150
|
+
"memory_context",
|
|
151
|
+
"setup",
|
|
152
|
+
"request_prep",
|
|
153
|
+
"ttft",
|
|
154
|
+
"generation",
|
|
155
|
+
]);
|
|
156
|
+
expect(phaseMap(breakdown!.phases).request_prep).toBe(10);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("a failed retry mid tool-loop is superseded", () => {
|
|
160
|
+
const t = new TurnLatencyTracker();
|
|
161
|
+
clock = 0;
|
|
162
|
+
t.mark("turn_start");
|
|
163
|
+
clock = 10;
|
|
164
|
+
t.mark("prompt_hook_start");
|
|
165
|
+
clock = 110;
|
|
166
|
+
t.mark("prompt_hook_end");
|
|
167
|
+
clock = 120;
|
|
168
|
+
t.mark("tools_resolved");
|
|
169
|
+
clock = 130;
|
|
170
|
+
t.mark("request_sent");
|
|
171
|
+
clock = 430;
|
|
172
|
+
t.markFirstToken("thinking");
|
|
173
|
+
clock = 700;
|
|
174
|
+
t.mark("call_complete");
|
|
175
|
+
const first = t.serializeSince(0);
|
|
176
|
+
|
|
177
|
+
// Second call fails after streaming a partial token, then retries.
|
|
178
|
+
clock = 1000;
|
|
179
|
+
t.mark("tools_resolved");
|
|
180
|
+
clock = 1010;
|
|
181
|
+
t.mark("request_sent");
|
|
182
|
+
clock = 1100;
|
|
183
|
+
t.markFirstToken("text"); // partial stream before the failure
|
|
184
|
+
clock = 2000;
|
|
185
|
+
t.mark("tools_resolved");
|
|
186
|
+
clock = 2010;
|
|
187
|
+
t.mark("request_sent");
|
|
188
|
+
clock = 2200;
|
|
189
|
+
t.markFirstToken("text");
|
|
190
|
+
clock = 2260;
|
|
191
|
+
t.mark("call_complete");
|
|
192
|
+
|
|
193
|
+
const { breakdown } = t.serializeSince(first.cursor);
|
|
194
|
+
// Only the successful retry (2010) drives ttft / provider-duration; the
|
|
195
|
+
// failed attempt's request_sent (1010) and its stray first_token (1100)
|
|
196
|
+
// are dropped.
|
|
197
|
+
expect(breakdown!.ttftMs).toBe(190);
|
|
198
|
+
expect(breakdown!.providerDurationMs).toBe(250);
|
|
199
|
+
expect(breakdown!.firstTokenKind).toBe("text");
|
|
200
|
+
// No duplicate per-call phases from the failed attempt.
|
|
201
|
+
expect(breakdown!.phases.map((p) => p.key)).toEqual([
|
|
202
|
+
"setup",
|
|
203
|
+
"request_prep",
|
|
204
|
+
"ttft",
|
|
205
|
+
"generation",
|
|
206
|
+
]);
|
|
207
|
+
expect(phaseMap(breakdown!.phases).request_prep).toBe(10);
|
|
208
|
+
expect(breakdown!.totalToFirstTokenMs).toBeUndefined();
|
|
209
|
+
});
|
|
210
|
+
|
|
118
211
|
test("no marks serializes to null", () => {
|
|
119
212
|
const t = new TurnLatencyTracker();
|
|
120
213
|
expect(t.serializeSince(0).breakdown).toBeNull();
|
|
@@ -56,9 +56,47 @@ export class TurnLatencyTracker {
|
|
|
56
56
|
|
|
57
57
|
/** Stamp a point-in-time mark. Cheap (`Date.now()`); safe to over-call. */
|
|
58
58
|
mark(name: LatencyMark): void {
|
|
59
|
+
// A retried provider call re-issues `request_sent`; drop the failed
|
|
60
|
+
// attempt's stale marks first so the retry's segment measures only itself.
|
|
61
|
+
if (name === "request_sent") this.supersedeFailedAttempt();
|
|
59
62
|
this.marks.push({ name, at: Date.now() });
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Discard the per-call marks of a prior provider attempt that never
|
|
67
|
+
* completed. A call retried within the same turn (context-overflow recovery,
|
|
68
|
+
* post-model-call repair on a rejection) leaves a `request_sent` with no
|
|
69
|
+
* `call_complete` and no `usage` event to serialize it and advance the
|
|
70
|
+
* cursor; the next successful segment would otherwise measure ttft /
|
|
71
|
+
* provider-duration / phases from the failed attempt's marks.
|
|
72
|
+
*
|
|
73
|
+
* Detection is cursor-free: a completed call always stamps `call_complete`
|
|
74
|
+
* before its `usage` event, so a `request_sent` with none after it belongs
|
|
75
|
+
* to a call that never returned. A retry re-stamps its setup `tools_resolved`
|
|
76
|
+
* before this `request_sent`, so that trailing mark is preserved as the
|
|
77
|
+
* successful segment's setup mark.
|
|
78
|
+
*/
|
|
79
|
+
private supersedeFailedAttempt(): void {
|
|
80
|
+
let failedRequestSent = -1;
|
|
81
|
+
for (let i = this.marks.length - 1; i >= 0; i--) {
|
|
82
|
+
const name = this.marks[i]!.name;
|
|
83
|
+
if (name === "call_complete") return; // prior attempt finished — nothing stale
|
|
84
|
+
if (name === "request_sent") {
|
|
85
|
+
failedRequestSent = i;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (failedRequestSent === -1) return; // no prior attempt this turn
|
|
90
|
+
// Drop from the failed attempt's paired setup mark (its `tools_resolved`,
|
|
91
|
+
// if any) through its trailing marks, keeping a retry `tools_resolved`
|
|
92
|
+
// already stamped as the last mark.
|
|
93
|
+
let start = failedRequestSent;
|
|
94
|
+
if (this.marks[start - 1]?.name === "tools_resolved") start -= 1;
|
|
95
|
+
let end = this.marks.length;
|
|
96
|
+
if (this.marks[end - 1]!.name === "tools_resolved") end -= 1;
|
|
97
|
+
this.marks.splice(start, end - start);
|
|
98
|
+
}
|
|
99
|
+
|
|
62
100
|
/**
|
|
63
101
|
* Stamp the first streamed token of the current call, carrying its kind on
|
|
64
102
|
* the mark. The caller fires this once per call (guarded loop-side), so each
|
|
@@ -23,6 +23,7 @@ import { backfillMessageIdOnLogs } from "../persistence/llm-request-log-store.js
|
|
|
23
23
|
import type { Message } from "../providers/types.js";
|
|
24
24
|
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
25
25
|
import { publishConversationMessagesChanged } from "../runtime/sync/resource-sync-events.js";
|
|
26
|
+
import type { CompletedBackgroundTool } from "../tools/background-tool-registry.js";
|
|
26
27
|
import { getLogger } from "../util/logger.js";
|
|
27
28
|
import type { Conversation } from "./conversation.js";
|
|
28
29
|
import type { ServerMessage } from "./message-protocol.js";
|
|
@@ -266,13 +267,15 @@ export async function persistWakeTailMessage(
|
|
|
266
267
|
*
|
|
267
268
|
* Mirrors {@link persistWakeTailMessage}'s channel/interface/provenance
|
|
268
269
|
* metadata, but stamps `kind: "background-event"` (+ the originating `source`)
|
|
269
|
-
* for identification
|
|
270
|
-
* output)
|
|
270
|
+
* for identification and skips indexing (the body may carry untrusted command
|
|
271
|
+
* output). The `backgroundEventSource` stamp lets clients hide this row from the
|
|
272
|
+
* rendered transcript — the user-facing wake card carries the status instead.
|
|
271
273
|
*/
|
|
272
274
|
export async function persistWakeTriggerMessage(
|
|
273
275
|
conversation: Conversation,
|
|
274
276
|
message: Message,
|
|
275
277
|
source: string,
|
|
278
|
+
completion?: CompletedBackgroundTool,
|
|
276
279
|
): Promise<void> {
|
|
277
280
|
const turnChannelCtx = conversation.getTurnChannelContext();
|
|
278
281
|
const turnInterfaceCtx = conversation.getTurnInterfaceContext();
|
|
@@ -287,6 +290,7 @@ export async function persistWakeTriggerMessage(
|
|
|
287
290
|
kind: "background-event",
|
|
288
291
|
backgroundEventSource: source,
|
|
289
292
|
automated: true,
|
|
293
|
+
...(completion ? { backgroundToolCompletion: completion } : {}),
|
|
290
294
|
};
|
|
291
295
|
const persisted = await addMessage(
|
|
292
296
|
conversation.conversationId,
|
|
@@ -309,12 +313,10 @@ export async function persistWakeTriggerMessage(
|
|
|
309
313
|
"wake trigger persist: syncMessageToDisk failed (non-fatal)",
|
|
310
314
|
);
|
|
311
315
|
}
|
|
312
|
-
// Tell connected clients the message list changed so they refetch
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
// another client, would not show the <background_event> row until a manual
|
|
317
|
-
// reload.
|
|
316
|
+
// Tell connected clients the message list changed so they refetch. The
|
|
317
|
+
// trigger row itself is hidden from the transcript (clients drop rows carrying
|
|
318
|
+
// `backgroundEventSource`), but the refetch keeps other clients' state in sync
|
|
319
|
+
// and lets a wake that produces no assistant stream still settle cleanly.
|
|
318
320
|
try {
|
|
319
321
|
publishConversationMessagesChanged(conversation.conversationId);
|
|
320
322
|
} catch (err) {
|
|
@@ -31,12 +31,14 @@ const CONVERSATION_ID = "conv-test-123";
|
|
|
31
31
|
function seedDocument(surfaceId: string = SURFACE_ID): void {
|
|
32
32
|
const now = Date.now();
|
|
33
33
|
rawRun(
|
|
34
|
+
"test:seedConversation",
|
|
34
35
|
/*sql*/ `INSERT OR IGNORE INTO conversations (id, created_at, updated_at) VALUES (?, ?, ?)`,
|
|
35
36
|
CONVERSATION_ID,
|
|
36
37
|
now,
|
|
37
38
|
now,
|
|
38
39
|
);
|
|
39
40
|
rawRun(
|
|
41
|
+
"test:seedDocument",
|
|
40
42
|
/*sql*/ `INSERT OR IGNORE INTO documents (surface_id, conversation_id, title, content, word_count, created_at, updated_at)
|
|
41
43
|
VALUES (?, ?, 'Test Doc', 'body', 2, ?, ?)`,
|
|
42
44
|
surfaceId,
|
|
@@ -331,7 +333,11 @@ describe("cascade on document delete", () => {
|
|
|
331
333
|
expect(listComments(SURFACE_ID)).toHaveLength(1);
|
|
332
334
|
|
|
333
335
|
// Delete the document — FK cascade should remove comments.
|
|
334
|
-
rawRun(
|
|
336
|
+
rawRun(
|
|
337
|
+
"test:deleteDocument",
|
|
338
|
+
/*sql*/ `DELETE FROM documents WHERE surface_id = ?`,
|
|
339
|
+
SURFACE_ID,
|
|
340
|
+
);
|
|
335
341
|
|
|
336
342
|
expect(listComments(SURFACE_ID)).toHaveLength(0);
|
|
337
343
|
});
|
|
@@ -92,6 +92,7 @@ export function createComment(params: {
|
|
|
92
92
|
const now = Date.now();
|
|
93
93
|
|
|
94
94
|
rawRun(
|
|
95
|
+
"docComments:createComment",
|
|
95
96
|
/*sql*/ `INSERT INTO document_comments
|
|
96
97
|
(id, surface_id, conversation_id, author, content,
|
|
97
98
|
anchor_start, anchor_end, anchor_text, parent_comment_id,
|
|
@@ -132,6 +133,7 @@ export function createComment(params: {
|
|
|
132
133
|
|
|
133
134
|
export function getComment(id: string): CommentRecord | null {
|
|
134
135
|
const row = rawGet<CommentRow>(
|
|
136
|
+
"docComments:getComment",
|
|
135
137
|
/*sql*/ `SELECT * FROM document_comments WHERE id = ?`,
|
|
136
138
|
id,
|
|
137
139
|
);
|
|
@@ -162,6 +164,7 @@ export function listComments(
|
|
|
162
164
|
|
|
163
165
|
const where = conditions.join(" AND ");
|
|
164
166
|
const rows = rawAll<CommentRow>(
|
|
167
|
+
"docComments:listComments",
|
|
165
168
|
/*sql*/ `SELECT * FROM document_comments WHERE ${where} ORDER BY created_at ASC`,
|
|
166
169
|
...params,
|
|
167
170
|
);
|
|
@@ -172,6 +175,7 @@ export function listComments(
|
|
|
172
175
|
export function resolveComment(id: string, resolvedBy: string): boolean {
|
|
173
176
|
const now = Date.now();
|
|
174
177
|
const changes = rawRun(
|
|
178
|
+
"docComments:resolveComment",
|
|
175
179
|
/*sql*/ `UPDATE document_comments
|
|
176
180
|
SET status = 'resolved', resolved_by = ?, resolved_at = ?, updated_at = ?
|
|
177
181
|
WHERE id = ?`,
|
|
@@ -189,6 +193,7 @@ export function resolveComment(id: string, resolvedBy: string): boolean {
|
|
|
189
193
|
export function reopenComment(id: string): boolean {
|
|
190
194
|
const now = Date.now();
|
|
191
195
|
const changes = rawRun(
|
|
196
|
+
"docComments:reopenComment",
|
|
192
197
|
/*sql*/ `UPDATE document_comments
|
|
193
198
|
SET status = 'open', resolved_by = NULL, resolved_at = NULL, updated_at = ?
|
|
194
199
|
WHERE id = ?`,
|
|
@@ -204,6 +209,7 @@ export function reopenComment(id: string): boolean {
|
|
|
204
209
|
export function updateCommentContent(id: string, content: string): boolean {
|
|
205
210
|
const now = Date.now();
|
|
206
211
|
const changes = rawRun(
|
|
212
|
+
"docComments:updateCommentContent",
|
|
207
213
|
/*sql*/ `UPDATE document_comments SET content = ?, updated_at = ? WHERE id = ?`,
|
|
208
214
|
content,
|
|
209
215
|
now,
|
|
@@ -218,6 +224,7 @@ export function updateCommentContent(id: string, content: string): boolean {
|
|
|
218
224
|
export function deleteComment(id: string): boolean {
|
|
219
225
|
// Replies cascade-delete via the self-referential FK on parent_comment_id.
|
|
220
226
|
const changes = rawRun(
|
|
227
|
+
"docComments:deleteComment",
|
|
221
228
|
/*sql*/ `DELETE FROM document_comments WHERE id = ?`,
|
|
222
229
|
id,
|
|
223
230
|
);
|
|
@@ -229,6 +236,7 @@ export function deleteComment(id: string): boolean {
|
|
|
229
236
|
|
|
230
237
|
export function getCommentCountForDocument(surfaceId: string): number {
|
|
231
238
|
const row = rawGet<{ count: number }>(
|
|
239
|
+
"docComments:getCommentCount",
|
|
232
240
|
/*sql*/ `SELECT COUNT(*) AS count FROM document_comments
|
|
233
241
|
WHERE surface_id = ? AND status = 'open'`,
|
|
234
242
|
surfaceId,
|
|
@@ -35,6 +35,7 @@ export function addDocumentConversation(
|
|
|
35
35
|
conversationId: string,
|
|
36
36
|
): void {
|
|
37
37
|
rawRun(
|
|
38
|
+
"documents:addDocumentConversation",
|
|
38
39
|
/*sql*/ `INSERT OR IGNORE INTO document_conversations (surface_id, conversation_id, created_at) VALUES (?, ?, ?)`,
|
|
39
40
|
surfaceId,
|
|
40
41
|
conversationId,
|
|
@@ -78,6 +79,7 @@ function mapRowToRecord(row: DocumentRow): DocumentRecord {
|
|
|
78
79
|
export function getDocumentById(surfaceId: string): DocumentRecord | null {
|
|
79
80
|
try {
|
|
80
81
|
const row = rawGet<DocumentRow>(
|
|
82
|
+
"documents:getDocumentById",
|
|
81
83
|
/*sql*/ `SELECT surface_id, conversation_id, title, content, word_count, created_at, updated_at
|
|
82
84
|
FROM documents
|
|
83
85
|
WHERE surface_id = ?`,
|
|
@@ -104,6 +106,7 @@ export function isDocumentAssociatedWithConversation(
|
|
|
104
106
|
): boolean {
|
|
105
107
|
try {
|
|
106
108
|
const row = rawGet<{ found: number }>(
|
|
109
|
+
"documents:isAssociatedWithConversation",
|
|
107
110
|
/*sql*/ `
|
|
108
111
|
SELECT 1 AS found
|
|
109
112
|
FROM document_conversations
|
|
@@ -132,6 +135,7 @@ export function getDocumentsForConversation(
|
|
|
132
135
|
): Omit<DocumentRecord, "content">[] {
|
|
133
136
|
try {
|
|
134
137
|
const rows = rawAll<DocumentListRow>(
|
|
138
|
+
"documents:getDocumentsForConversation",
|
|
135
139
|
/*sql*/ `
|
|
136
140
|
SELECT d.surface_id, dc.conversation_id AS conversation_id,
|
|
137
141
|
d.title, d.word_count, d.created_at, d.updated_at
|
|
@@ -175,6 +179,7 @@ export function searchDocumentsByTitle(
|
|
|
175
179
|
const pattern = `%${escapeSqlLikePattern(query)}%`;
|
|
176
180
|
const rows = options.conversationId
|
|
177
181
|
? rawAll<DocumentListRow>(
|
|
182
|
+
"documents:searchByTitle:scoped",
|
|
178
183
|
/*sql*/ `
|
|
179
184
|
SELECT d.surface_id, dc.conversation_id AS conversation_id,
|
|
180
185
|
d.title, d.word_count, d.created_at, d.updated_at
|
|
@@ -189,6 +194,7 @@ export function searchDocumentsByTitle(
|
|
|
189
194
|
pattern,
|
|
190
195
|
)
|
|
191
196
|
: rawAll<DocumentListRow>(
|
|
197
|
+
"documents:searchByTitle:all",
|
|
192
198
|
/*sql*/ `
|
|
193
199
|
SELECT surface_id, conversation_id, title, word_count, created_at, updated_at
|
|
194
200
|
FROM documents
|
|
@@ -234,6 +240,7 @@ export function findRecentEmptyDocumentByTitle(
|
|
|
234
240
|
try {
|
|
235
241
|
const threshold = Date.now() - withinMs;
|
|
236
242
|
const row = rawGet<{ surface_id: string }>(
|
|
243
|
+
"documents:findRecentEmptyByTitle",
|
|
237
244
|
/*sql*/ `SELECT surface_id FROM documents
|
|
238
245
|
WHERE conversation_id = ?
|
|
239
246
|
AND title = ?
|
|
@@ -262,10 +269,12 @@ export function findRecentEmptyDocumentByTitle(
|
|
|
262
269
|
export function deleteDocument(surfaceId: string): boolean {
|
|
263
270
|
try {
|
|
264
271
|
const changes = rawRun(
|
|
272
|
+
"documents:deleteDocument:doc",
|
|
265
273
|
/*sql*/ `DELETE FROM documents WHERE surface_id = ?`,
|
|
266
274
|
surfaceId,
|
|
267
275
|
);
|
|
268
276
|
rawRun(
|
|
277
|
+
"documents:deleteDocument:associations",
|
|
269
278
|
/*sql*/ `DELETE FROM document_conversations WHERE surface_id = ?`,
|
|
270
279
|
surfaceId,
|
|
271
280
|
);
|
|
@@ -310,6 +319,7 @@ export function findInDocument(
|
|
|
310
319
|
): FindResult | null {
|
|
311
320
|
try {
|
|
312
321
|
const row = rawGet<{ content: string }>(
|
|
322
|
+
"documents:findInDocument:getContent",
|
|
313
323
|
/*sql*/ `SELECT content FROM documents WHERE surface_id = ?`,
|
|
314
324
|
surfaceId,
|
|
315
325
|
);
|
|
@@ -385,6 +395,7 @@ export function saveDocument(params: {
|
|
|
385
395
|
try {
|
|
386
396
|
const now = Date.now();
|
|
387
397
|
rawRun(
|
|
398
|
+
"documents:saveDocument",
|
|
388
399
|
`INSERT INTO documents (surface_id, conversation_id, title, content, word_count, created_at, updated_at)
|
|
389
400
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
390
401
|
ON CONFLICT(surface_id) DO UPDATE SET
|
|
@@ -458,6 +469,7 @@ export function replaceInDocument(
|
|
|
458
469
|
): ReplaceInDocumentResult {
|
|
459
470
|
try {
|
|
460
471
|
const row = rawGet<{ content: string }>(
|
|
472
|
+
"documents:replaceInDocument:getContent",
|
|
461
473
|
/*sql*/ `SELECT content FROM documents WHERE surface_id = ?`,
|
|
462
474
|
surfaceId,
|
|
463
475
|
);
|
|
@@ -516,6 +528,7 @@ export function replaceInDocument(
|
|
|
516
528
|
.split(/\s+/)
|
|
517
529
|
.filter((w) => w.length > 0).length;
|
|
518
530
|
rawRun(
|
|
531
|
+
"documents:replaceInDocument:update",
|
|
519
532
|
/*sql*/ `UPDATE documents SET content = ?, word_count = ?, updated_at = ? WHERE surface_id = ?`,
|
|
520
533
|
newContent,
|
|
521
534
|
wordCount,
|
|
@@ -545,6 +558,7 @@ export function updateDocumentContent(
|
|
|
545
558
|
): { success: true } | { success: false; error: string } {
|
|
546
559
|
try {
|
|
547
560
|
const existing = rawGet<{ content: string }>(
|
|
561
|
+
"documents:updateDocumentContent:get",
|
|
548
562
|
/*sql*/ `SELECT content FROM documents WHERE surface_id = ?`,
|
|
549
563
|
surfaceId,
|
|
550
564
|
);
|
|
@@ -559,6 +573,7 @@ export function updateDocumentContent(
|
|
|
559
573
|
.split(/\s+/)
|
|
560
574
|
.filter((w) => w.length > 0).length;
|
|
561
575
|
rawRun(
|
|
576
|
+
"documents:updateDocumentContent:update",
|
|
562
577
|
/*sql*/ `UPDATE documents SET content = ?, word_count = ?, updated_at = ? WHERE surface_id = ?`,
|
|
563
578
|
newContent,
|
|
564
579
|
wordCount,
|
|
@@ -81,6 +81,17 @@ mock.module("../../persistence/conversation-crud.js", () => ({
|
|
|
81
81
|
getMessages: (id: string) =>
|
|
82
82
|
id === "child-conv-1" ? childMessages : parentMessages,
|
|
83
83
|
messageMetadataSchema,
|
|
84
|
+
parseMessageMetadata: (json: string | null) => {
|
|
85
|
+
if (!json) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const parsed = messageMetadataSchema.safeParse(JSON.parse(json));
|
|
90
|
+
return parsed.success ? parsed.data : undefined;
|
|
91
|
+
} catch {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
84
95
|
reserveMessage: mock(async () => ({ id: "msg-reserve" })),
|
|
85
96
|
}));
|
|
86
97
|
|
|
@@ -9,7 +9,7 @@ import { formatLocalTimestamp } from "../daemon/date-context.js";
|
|
|
9
9
|
import {
|
|
10
10
|
getConversation,
|
|
11
11
|
getMessages,
|
|
12
|
-
|
|
12
|
+
parseMessageMetadata,
|
|
13
13
|
} from "../persistence/conversation-crud.js";
|
|
14
14
|
import { truncate } from "../util/truncate.js";
|
|
15
15
|
|
|
@@ -29,7 +29,9 @@ function extractAnalysisText(blocks: ContentBlock[]): string {
|
|
|
29
29
|
for (const block of blocks) {
|
|
30
30
|
switch (block.type) {
|
|
31
31
|
case "text":
|
|
32
|
-
if (block.text)
|
|
32
|
+
if (block.text) {
|
|
33
|
+
parts.push(block.text);
|
|
34
|
+
}
|
|
33
35
|
break;
|
|
34
36
|
case "tool_use":
|
|
35
37
|
parts.push(
|
|
@@ -141,6 +143,45 @@ export function formatMessageSliceForTranscript(
|
|
|
141
143
|
return lines.join("\n");
|
|
142
144
|
}
|
|
143
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Append the `### Subagent: …` section for `msg` when its metadata carries a
|
|
148
|
+
* terminal (completed/failed/aborted) subagent notification; a no-op otherwise.
|
|
149
|
+
*
|
|
150
|
+
* `subagentOptions` controls how the child transcript renders. Callers pass the
|
|
151
|
+
* parent's time zone but NOT its display names: a subagent conversation persists
|
|
152
|
+
* the parent assistant's objective as a `user` message (see subagent/manager.ts),
|
|
153
|
+
* so reusing the parent's names would render the assistant's tasking text under
|
|
154
|
+
* the human user's name. An empty options object keeps child transcripts on
|
|
155
|
+
* generic role labels.
|
|
156
|
+
*/
|
|
157
|
+
function appendSubagentSection(
|
|
158
|
+
lines: string[],
|
|
159
|
+
msg: TranscriptMessage,
|
|
160
|
+
subagentOptions: TranscriptFormatOptions = {},
|
|
161
|
+
): void {
|
|
162
|
+
const notif = parseMessageMetadata(msg.metadata)?.subagentNotification;
|
|
163
|
+
if (
|
|
164
|
+
!notif ||
|
|
165
|
+
(notif.status !== "completed" &&
|
|
166
|
+
notif.status !== "failed" &&
|
|
167
|
+
notif.status !== "aborted") ||
|
|
168
|
+
!notif.conversationId
|
|
169
|
+
) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const subMessages = getMessages(notif.conversationId);
|
|
173
|
+
lines.push(`### Subagent: ${notif.label} (${notif.status})`);
|
|
174
|
+
lines.push("");
|
|
175
|
+
lines.push(formatSubagentMessages(subMessages, subagentOptions));
|
|
176
|
+
lines.push("");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Render one message as a transcript block: a `## role (time)` header, the
|
|
181
|
+
* extracted body text, and any terminal subagent section. Role and time honor
|
|
182
|
+
* `options` (display names + time zone); the subagent child transcript inherits
|
|
183
|
+
* only the time zone — see {@link appendSubagentSection}.
|
|
184
|
+
*/
|
|
144
185
|
function appendMessageBlock(
|
|
145
186
|
lines: string[],
|
|
146
187
|
msg: TranscriptMessage,
|
|
@@ -155,35 +196,7 @@ function appendMessageBlock(
|
|
|
155
196
|
lines.push(text);
|
|
156
197
|
lines.push("");
|
|
157
198
|
|
|
158
|
-
|
|
159
|
-
try {
|
|
160
|
-
const parsed = messageMetadataSchema.safeParse(JSON.parse(msg.metadata));
|
|
161
|
-
if (parsed.success && parsed.data.subagentNotification) {
|
|
162
|
-
const notif = parsed.data.subagentNotification;
|
|
163
|
-
if (
|
|
164
|
-
(notif.status === "completed" ||
|
|
165
|
-
notif.status === "failed" ||
|
|
166
|
-
notif.status === "aborted") &&
|
|
167
|
-
notif.conversationId
|
|
168
|
-
) {
|
|
169
|
-
const subMessages = getMessages(notif.conversationId);
|
|
170
|
-
lines.push(`### Subagent: ${notif.label} (${notif.status})`);
|
|
171
|
-
lines.push("");
|
|
172
|
-
// Subagent conversations persist the parent assistant's objective
|
|
173
|
-
// as a `user` message (see subagent/manager.ts), so reusing the
|
|
174
|
-
// parent's display-name options would render the assistant's
|
|
175
|
-
// tasking text under the human user's name. Keep child transcripts
|
|
176
|
-
// on generic role labels — and only pass through the time zone.
|
|
177
|
-
lines.push(
|
|
178
|
-
formatSubagentMessages(subMessages, { timeZone: options.timeZone }),
|
|
179
|
-
);
|
|
180
|
-
lines.push("");
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
} catch {
|
|
184
|
-
// Skip unparseable metadata
|
|
185
|
-
}
|
|
186
|
-
}
|
|
199
|
+
appendSubagentSection(lines, msg, { timeZone: options.timeZone });
|
|
187
200
|
}
|
|
188
201
|
|
|
189
202
|
export function buildAnalysisTranscript(conversationId: string): string {
|
|
@@ -192,7 +205,6 @@ export function buildAnalysisTranscript(conversationId: string): string {
|
|
|
192
205
|
return `# Conversation not found: ${conversationId}\n`;
|
|
193
206
|
}
|
|
194
207
|
|
|
195
|
-
const allMessages = getMessages(conversationId);
|
|
196
208
|
const title = conversation.title ?? "Untitled";
|
|
197
209
|
const lines: string[] = [];
|
|
198
210
|
|
|
@@ -200,41 +212,11 @@ export function buildAnalysisTranscript(conversationId: string): string {
|
|
|
200
212
|
lines.push(`Created: ${formatLocalTimestamp(conversation.createdAt)}`);
|
|
201
213
|
lines.push("");
|
|
202
214
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
lines.push(`## ${role} (${time})`);
|
|
210
|
-
lines.push(text);
|
|
211
|
-
lines.push("");
|
|
212
|
-
|
|
213
|
-
// Check for subagent notifications in metadata
|
|
214
|
-
if (msg.metadata) {
|
|
215
|
-
try {
|
|
216
|
-
const parsed = messageMetadataSchema.safeParse(
|
|
217
|
-
JSON.parse(msg.metadata),
|
|
218
|
-
);
|
|
219
|
-
if (parsed.success && parsed.data.subagentNotification) {
|
|
220
|
-
const notif = parsed.data.subagentNotification;
|
|
221
|
-
if (
|
|
222
|
-
(notif.status === "completed" ||
|
|
223
|
-
notif.status === "failed" ||
|
|
224
|
-
notif.status === "aborted") &&
|
|
225
|
-
notif.conversationId
|
|
226
|
-
) {
|
|
227
|
-
const subMessages = getMessages(notif.conversationId);
|
|
228
|
-
lines.push(`### Subagent: ${notif.label} (${notif.status})`);
|
|
229
|
-
lines.push("");
|
|
230
|
-
lines.push(formatSubagentMessages(subMessages));
|
|
231
|
-
lines.push("");
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
} catch {
|
|
235
|
-
// Skip unparseable metadata
|
|
236
|
-
}
|
|
237
|
-
}
|
|
215
|
+
// Analyze-conversation flow renders under generic "User"/"Assistant" labels,
|
|
216
|
+
// so no options are threaded through (see `formatMessageSliceForTranscript`
|
|
217
|
+
// for the display-name variant).
|
|
218
|
+
for (const msg of getMessages(conversationId)) {
|
|
219
|
+
appendMessageBlock(lines, msg);
|
|
238
220
|
}
|
|
239
221
|
|
|
240
222
|
return lines.join("\n");
|