@vellumai/assistant 0.11.3 → 0.11.4-dev.202608190019.b94dbf2
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/AGENTS.md +9 -3
- package/ARCHITECTURE.md +32 -10
- package/docs/architecture/memory.md +43 -5
- package/docs/architecture/security.md +96 -152
- package/docs/architecture/turn-actor.md +70 -0
- package/docs/browser-use-architecture-phase2.md +128 -56
- package/docs/flux-turn-detection-spike.md +248 -0
- package/docs/guardian-request-flow.md +35 -0
- package/docs/stt-provider-onboarding.md +3 -1
- package/knip.json +3 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +34 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
- package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/openapi.yaml +289 -113
- package/package.json +1 -1
- package/scripts/voice-ttft-spike.ts +3 -3
- package/scripts/write-plugin-api-shim.ts +10 -0
- package/src/__tests__/app-compiler.test.ts +38 -3
- package/src/__tests__/app-control-flow.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -2
- package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
- package/src/__tests__/attachments-store.test.ts +21 -12
- package/src/__tests__/byok-default-profile-ensure.test.ts +17 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +0 -1
- package/src/__tests__/call-site-routing-provider.test.ts +1 -1
- package/src/__tests__/channel-availability-routes.test.ts +14 -1
- package/src/__tests__/channel-capabilities-dedupe.test.ts +214 -0
- package/src/__tests__/channel-delivery-store.test.ts +14 -14
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +4 -4
- package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
- package/src/__tests__/checker.test.ts +20 -314
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
- package/src/__tests__/compaction-events.test.ts +8 -10
- package/src/__tests__/config-loader-backfill.test.ts +3 -3
- package/src/__tests__/config-schema.test.ts +25 -10
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop.test.ts +32 -21
- package/src/__tests__/conversation-attachments.test.ts +0 -1
- package/src/__tests__/conversation-attention-store.test.ts +63 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -4
- package/src/__tests__/conversation-fork-crud.test.ts +69 -0
- package/src/__tests__/conversation-fork-referential.test.ts +67 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +24 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +209 -0
- package/src/__tests__/conversation-notifiers-provenance.test.ts +59 -0
- package/src/__tests__/conversation-queue.test.ts +154 -4
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +187 -102
- package/src/__tests__/conversation-runtime-workspace.test.ts +14 -10
- package/src/__tests__/conversation-slash-queue.test.ts +3 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +7 -10
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/custom-profile-ensure.test.ts +5 -1
- package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +5 -1
- package/src/__tests__/discord-requester-notice-privacy.test.ts +3 -3
- package/src/__tests__/document-append-idempotency.test.ts +233 -0
- package/src/__tests__/document-sync-tags.test.ts +0 -75
- package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
- package/src/__tests__/edit-propagation.test.ts +107 -11
- package/src/__tests__/file-ops-service.test.ts +163 -30
- package/src/__tests__/filesystem-tools.test.ts +23 -24
- package/src/__tests__/gateway-only-guard.test.ts +2 -5
- package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
- package/src/__tests__/helpers/mock-actor-context.ts +49 -0
- package/src/__tests__/helpers/mock-conversation.ts +13 -1
- package/src/__tests__/host-file-read-tool.test.ts +16 -19
- package/src/__tests__/http-user-message-parity.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
- package/src/__tests__/injector-chain.test.ts +63 -41
- package/src/__tests__/injector-disk-pressure.test.ts +11 -23
- package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
- package/src/__tests__/llm-context-resolution.test.ts +73 -1
- package/src/__tests__/llm-schema.test.ts +5 -2
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
- package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
- package/src/__tests__/media-generate-image.test.ts +131 -21
- package/src/__tests__/memory-retrieval-hook.test.ts +100 -7
- package/src/__tests__/messages-read-boundary-guard.test.ts +134 -0
- package/src/__tests__/mtime-cache.test.ts +3 -1
- package/src/__tests__/non-member-access-request.test.ts +0 -20
- package/src/__tests__/outbound-slack-persistence.test.ts +40 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
- package/src/__tests__/plugin-api-store-credential.test.ts +261 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
- package/src/__tests__/plugin-disabled-state.test.ts +2 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
- package/src/__tests__/plugin-execution-context.test.ts +73 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -4
- package/src/__tests__/plugin-secret-pattern-contribution.test.ts +1 -1
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +14 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +20 -0
- package/src/__tests__/proxy-approval-callback.test.ts +1 -0
- package/src/__tests__/qdrant-manager.test.ts +14 -1
- package/src/__tests__/reaction-persistence.test.ts +200 -7
- package/src/__tests__/require-fresh-approval.test.ts +0 -4
- package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +460 -105
- package/src/__tests__/run-due-schedules.test.ts +21 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
- package/src/__tests__/schedule-routes.test.ts +23 -0
- package/src/__tests__/schedule-store.test.ts +17 -0
- package/src/__tests__/scoped-approval-grants.test.ts +11 -6
- package/src/__tests__/secret-ingress-channel.test.ts +0 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -3
- package/src/__tests__/skills.test.ts +32 -0
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +0 -1
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/subagent-call-site-routing.test.ts +31 -19
- package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
- package/src/__tests__/subagent-spawn-and-await.test.ts +18 -17
- package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +81 -101
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
- package/src/__tests__/tool-executor.test.ts +68 -39
- package/src/__tests__/turn-events-store.test.ts +43 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
- package/src/__tests__/ui-shape-teaching.test.ts +33 -0
- package/src/__tests__/ui-visual-surface.test.ts +1 -1
- package/src/__tests__/ui-voice-picker-surface.test.ts +128 -0
- package/src/__tests__/ui-work-result-surface.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +3 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/visible-app-context.test.ts +16 -9
- package/src/__tests__/voice-config-update.test.ts +40 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
- package/src/__tests__/voice-session-bridge.test.ts +85 -29
- package/src/__tests__/worker-entrypoint-guards.test.ts +54 -0
- package/src/__tests__/worker-plugin-surface.test.ts +77 -0
- package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +158 -0
- package/src/__tests__/workspace-migration-143-repair-deprecated-codex-model-id.test.ts +133 -0
- package/src/__tests__/workspace-migration-144-convert-stranded-subscription-openai-profiles.test.ts +316 -0
- package/src/__tests__/workspace-migration-145-collapse-profile-bindings-to-entries.test.ts +325 -0
- package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +235 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +10 -2
- package/src/acp/__tests__/auth-required.test.ts +161 -0
- package/src/acp/acp-claude-oauth.ts +19 -2
- package/src/acp/agent-process.test.ts +100 -0
- package/src/acp/agent-process.ts +29 -26
- package/src/acp/auth-required.ts +102 -0
- package/src/acp/session-manager.test.ts +119 -0
- package/src/acp/session-manager.ts +76 -3
- package/src/api/events/acp-auth-required.ts +55 -0
- package/src/api/events/host-file.ts +2 -2
- package/src/api/index.ts +7 -0
- package/src/api/surfaces.ts +12 -3
- package/src/apps/app-store.ts +3 -0
- package/src/bundler/package-resolver.ts +2 -30
- package/src/calls/__tests__/voice-session-bridge.test.ts +194 -11
- package/src/calls/__tests__/voice-triage-escalate.test.ts +102 -0
- package/src/calls/call-controller.ts +19 -3
- package/src/calls/call-setup-flow.ts +0 -1
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/calls/voice-session-bridge.ts +115 -41
- package/src/calls/voice-triage-escalate.ts +105 -2
- package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
- package/src/channels/config.ts +13 -0
- package/src/channels/plugin-channel-declarations.ts +108 -0
- package/src/channels/types.ts +30 -0
- package/src/cli/AGENTS.md +5 -2
- package/src/cli/bundled-modules.ts +29 -0
- package/src/cli/commands/credentials.help.ts +2 -2
- package/src/cli/commands/db/repair.ts +4 -8
- package/src/cli/commands/domain.ts +6 -3
- package/src/cli/commands/email.ts +6 -3
- package/src/cli/commands/inference-providers.ts +1 -1
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.help.ts +13 -4
- package/src/cli/commands/mcp.ts +9 -0
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +128 -5
- package/src/cli/commands/memory/index.help.ts +84 -28
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/memory-v2.ts +58 -54
- package/src/cli/commands/memory/memory-v3.ts +64 -0
- package/src/cli/commands/memory/memory-validate.ts +18 -0
- package/src/cli/commands/plugins.ts +85 -36
- package/src/cli/commands/schedules.ts +35 -1
- package/src/cli/commands/stt.help.ts +27 -2
- package/src/cli/commands/trust.ts +3 -14
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +39 -0
- package/src/cli/lib/bundled-marketplace.json +14 -1
- package/src/cli/lib/upgrade-plugin.ts +42 -0
- package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
- package/src/config/__tests__/default-profile-catalog.test.ts +34 -2
- package/src/config/__tests__/default-provider.test.ts +6 -1
- package/src/config/__tests__/profile-materialization.test.ts +75 -19
- package/src/config/assistant-feature-flags.ts +36 -15
- package/src/config/balanced-model-experiment.ts +35 -0
- package/src/config/bundled-skills/acp/SKILL.md +6 -7
- package/src/config/bundled-skills/document-editor/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.test.ts +65 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +7 -1
- package/src/config/bundled-skills/settings/tools/shared.ts +16 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -12
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
- package/src/config/call-site-defaults.ts +11 -5
- package/src/config/default-profile-catalog.ts +179 -16
- package/src/config/default-profile-names.ts +4 -1
- package/src/config/default-provider-resolution.ts +4 -0
- package/src/config/feature-flag-registry.json +12 -12
- package/src/config/llm-context-resolution.ts +11 -3
- package/src/config/llm-resolver.ts +28 -1
- package/src/config/profile-materialization.ts +70 -22
- package/src/config/schemas/__tests__/live-voice.test.ts +107 -4
- package/src/config/schemas/call-site-catalog.ts +4 -4
- package/src/config/schemas/live-voice.ts +57 -23
- package/src/config/schemas/llm.ts +59 -32
- package/src/config/schemas/mcp.ts +23 -0
- package/src/config/schemas/plugin-updates.ts +6 -2
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/skills.ts +9 -2
- package/src/context/outbound-sanitize.ts +96 -1
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +82 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +15 -10
- package/src/daemon/conversation-agent-loop.ts +31 -19
- package/src/daemon/conversation-messaging.ts +5 -1
- package/src/daemon/conversation-notifiers.ts +20 -10
- package/src/daemon/conversation-process.ts +20 -6
- package/src/daemon/conversation-runtime-assembly.ts +12 -6
- package/src/daemon/conversation-store.ts +14 -4
- package/src/daemon/conversation-surfaces.ts +75 -26
- package/src/daemon/conversation-tool-setup.ts +3 -6
- package/src/daemon/conversation.ts +154 -51
- package/src/daemon/doordash-steps.ts +2 -2
- package/src/daemon/lifecycle.ts +14 -1
- package/src/daemon/mcp-reload-service.ts +36 -6
- package/src/daemon/process-message.ts +13 -26
- package/src/daemon/providers-setup.ts +6 -3
- package/src/daemon/trust-context-types.ts +29 -0
- package/src/daemon/trust-context.ts +12 -7
- package/src/daemon/wake-conversation-ops.ts +3 -2
- package/src/daemon/windows-compiled-entry.ts +4 -0
- package/src/documents/document-store.ts +143 -240
- package/src/hooks/hook-loader.ts +3 -3
- package/src/hooks/registry.ts +103 -45
- package/src/hooks/types.ts +5 -0
- package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
- package/src/inbound/oauth-callback-url.ts +61 -0
- package/src/ipc/gateway-client.test.ts +1 -1
- package/src/ipc/gateway-client.ts +14 -21
- package/src/ipc/gateway-flag-listener.ts +17 -3
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
- package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +1050 -0
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
- package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +60 -194
- package/src/live-voice/__tests__/live-voice-stt.test.ts +14 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +29 -0
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
- package/src/live-voice/__tests__/live-voice-vad.test.ts +0 -16
- package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
- package/src/live-voice/live-voice-archive.ts +2 -0
- package/src/live-voice/live-voice-manager.ts +16 -3
- package/src/live-voice/live-voice-metrics.ts +57 -32
- package/src/live-voice/live-voice-photo.ts +1 -2
- package/src/live-voice/live-voice-session.ts +598 -323
- package/src/live-voice/progress-narration.ts +277 -0
- package/src/live-voice/protocol.ts +21 -1
- package/src/live-voice/windows-compiled-live-voice.ts +4 -0
- package/src/mcp/__tests__/effective-config.test.ts +238 -0
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +200 -0
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
- package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +95 -0
- package/src/mcp/client.ts +16 -11
- package/src/mcp/effective-config.ts +113 -0
- package/src/mcp/manager.ts +11 -6
- package/src/mcp/mcp-auth-orchestrator.ts +13 -22
- package/src/mcp/mcp-oauth-provider.ts +205 -240
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +166 -3
- package/src/monitoring/control.ts +1 -0
- package/src/monitoring/db-integrity-sample.ts +4 -5
- package/src/monitoring/plugin-auto-update.ts +128 -24
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/approval-card-data.ts +33 -0
- package/src/notifications/signal.ts +1 -0
- package/src/permissions/AGENTS.md +16 -0
- package/src/permissions/checker.test.ts +75 -122
- package/src/permissions/checker.ts +44 -560
- package/src/permissions/confirmation-guardian-request.test.ts +15 -11
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/prompter.ts +1 -5
- package/src/permissions/question-guardian-request.test.ts +14 -6
- package/src/permissions/question-guardian-request.ts +1 -2
- package/src/persistence/attachments-store.ts +8 -1
- package/src/persistence/bookmark-crud.ts +3 -7
- package/src/persistence/conversation-attention-store.ts +16 -45
- package/src/persistence/conversation-crud.ts +33 -4
- package/src/persistence/conversation-lineage.ts +9 -0
- package/src/persistence/conversation-queries.ts +182 -52
- package/src/persistence/delivery-crud.ts +150 -36
- package/src/persistence/embeddings/qdrant-manager.ts +84 -49
- package/src/persistence/external-conversation-store.ts +32 -4
- package/src/persistence/llm-request-log-store.ts +4 -10
- package/src/persistence/llm-usage-store.ts +8 -3
- package/src/persistence/message-reads.test.ts +197 -0
- package/src/persistence/message-reads.ts +211 -0
- package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.test.ts +120 -0
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.ts +62 -0
- package/src/persistence/real-user-turn-filter.ts +27 -3
- package/src/persistence/schema/documents.ts +4 -4
- package/src/persistence/steps.ts +9 -0
- package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
- package/src/plugin-api/constants.ts +8 -0
- package/src/plugin-api/conversation-turn.ts +195 -5
- package/src/plugin-api/index.ts +38 -6
- package/src/plugin-api/resolve-credential.ts +3 -2
- package/src/plugin-api/store-credential.ts +146 -0
- package/src/plugin-api/vision-support.test.ts +1 -1
- package/src/plugin-api/webhook-url.ts +13 -11
- package/src/plugins/__tests__/mcp-servers.test.ts +371 -0
- package/src/plugins/defaults/main.ts +21 -7
- package/src/plugins/defaults/memory/AGENTS.md +15 -3
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +204 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +72 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
- package/src/plugins/defaults/memory/buffer-format.ts +165 -0
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +6 -0
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
- package/src/plugins/defaults/memory/graph/image-ref-utils.ts +3 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -30
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +34 -0
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +17 -24
- package/src/plugins/defaults/memory/hooks/post-compact.ts +1 -4
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
- package/src/plugins/defaults/memory/indexer.ts +3 -1
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +19 -7
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
- package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +281 -0
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
- package/src/plugins/defaults/memory/src/memory-v3-routes.ts +207 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +147 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
- package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
- package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
- package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
- package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
- package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +195 -58
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +93 -24
- package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
- package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
- package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
- package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
- package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
- package/src/plugins/defaults/memory/substrate/static-context.ts +160 -33
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +2 -4
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +3 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
- package/src/plugins/defaults/memory/v3/card.ts +9 -9
- package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
- package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
- package/src/plugins/defaults/memory/v3/edge.ts +13 -57
- package/src/plugins/defaults/memory/v3/injector.ts +8 -0
- package/src/plugins/defaults/memory/v3/prune.ts +2 -0
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +2 -0
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
- package/src/plugins/defaults/memory/worker-control.ts +1 -0
- package/src/plugins/defaults/memory/worker.ts +6 -3
- package/src/plugins/defaults/worker-entrypoints.ts +3 -0
- package/src/plugins/external-plugin-loader.ts +47 -0
- package/src/plugins/mcp-servers.ts +361 -0
- package/src/plugins/mtime-cache.ts +37 -46
- package/src/plugins/pipeline.ts +14 -7
- package/src/plugins/plugin-execution-context.ts +35 -11
- package/src/plugins/worker-plugin-surface.ts +33 -0
- package/src/prompts/templates/system-sections.ts +0 -7
- package/src/providers/__tests__/connection-model-compat.test.ts +1 -1
- package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +214 -2
- package/src/providers/__tests__/preflight-resolved-config.test.ts +57 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -2
- package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
- package/src/providers/anthropic/client.ts +332 -241
- package/src/providers/call-site-routing.ts +30 -3
- package/src/providers/connection-resolution.ts +194 -11
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +4 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/inference/auth.ts +6 -0
- package/src/providers/inference/connection-availability.ts +24 -2
- package/src/providers/inference/connections.ts +2 -0
- package/src/providers/model-catalog.ts +3 -3
- package/src/providers/model-intents.ts +28 -8
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +163 -40
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
- package/src/providers/openai/chat-completions-provider.ts +133 -36
- package/src/providers/openai/codex-models.ts +2 -1
- package/src/providers/provider-send-message.ts +32 -3
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +625 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +285 -6
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +679 -0
- package/src/providers/speech-to-text/provider-catalog.ts +99 -8
- package/src/providers/speech-to-text/resolve.ts +25 -2
- package/src/routes/control.ts +1 -0
- package/src/routes/route-host-client.ts +1 -0
- package/src/routes/route-host-protocol.ts +7 -0
- package/src/routes/worker.ts +48 -15
- package/src/runtime/AGENTS.md +16 -17
- package/src/runtime/access-request-helper.ts +9 -12
- package/src/runtime/agent-wake.ts +18 -15
- package/src/runtime/effective-capabilities.test.ts +43 -0
- package/src/runtime/effective-capabilities.ts +27 -0
- package/src/runtime/guardian-reply-router.ts +6 -2
- package/src/runtime/pre-first-message-gate.ts +4 -0
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +12 -4
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +522 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +52 -0
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +61 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +44 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +102 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +132 -35
- package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +133 -1
- package/src/runtime/routes/channel-availability-routes.ts +32 -14
- package/src/runtime/routes/channel-route-shared.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +6 -6
- package/src/runtime/routes/conversation-list-routes.ts +181 -23
- package/src/runtime/routes/conversation-management-routes.ts +17 -12
- package/src/runtime/routes/conversation-query-routes.ts +40 -27
- package/src/runtime/routes/conversation-routes.ts +43 -29
- package/src/runtime/routes/credential-prompt-routes.ts +4 -7
- package/src/runtime/routes/credential-routes.ts +26 -82
- package/src/runtime/routes/default-provider-routes.ts +15 -0
- package/src/runtime/routes/documents-routes.ts +3 -222
- package/src/runtime/routes/inbound-message-handler.ts +21 -45
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -9
- package/src/runtime/routes/inbound-stages/admission-policy.ts +1 -17
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -79
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +12 -7
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -8
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -79
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +2 -3
- package/src/runtime/routes/inference-profiles-routes.ts +20 -11
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -15
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/mcp-auth-routes.ts +148 -57
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -2
- package/src/runtime/routes/playground/reset-circuit.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +38 -8
- package/src/runtime/routes/schedule-routes.ts +94 -7
- package/src/runtime/routes/settings-routes.ts +6 -6
- package/src/runtime/routes/stt-routes.ts +31 -25
- package/src/runtime/routes/surface-action-routes.ts +20 -19
- package/src/runtime/routes/surface-conversation-resolver.ts +3 -0
- package/src/runtime/routes/user-route-dispatcher.ts +69 -15
- package/src/runtime/routes/user-route-import.ts +108 -0
- package/src/runtime/routes/user-route-resolution.ts +18 -1
- package/src/runtime/routes/workspace-routes.ts +0 -9
- package/src/runtime/routes/workspace-utils.ts +3 -13
- package/src/runtime/services/conversation-serializer.ts +7 -2
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
- package/src/schedule/plugin-schedule-availability.ts +58 -0
- package/src/schedule/plugin-schedule-declarations.ts +23 -27
- package/src/schedule/plugin-schedule-reconciler.ts +12 -3
- package/src/schedule/schedule-store.ts +5 -1
- package/src/schedule/scheduler.ts +9 -4
- package/src/schedule/worker-control.ts +1 -0
- package/src/schedule/worker.ts +6 -0
- package/src/security/oauth2.ts +6 -22
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
- package/src/stt/__tests__/types.test.ts +94 -0
- package/src/stt/daemon-batch-transcriber.ts +10 -0
- package/src/stt/stt-stream-session.ts +8 -4
- package/src/stt/types.ts +103 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
- package/src/subagent/consult-context.ts +11 -11
- package/src/subagent/consult-prompt.ts +26 -35
- package/src/subagent/manager.ts +21 -40
- package/src/subagent/notify.ts +7 -1
- package/src/subagent/types.ts +15 -12
- package/src/tools/__tests__/tool-input-schemas.test.ts +7 -7
- package/src/tools/acp/spawn.test.ts +97 -0
- package/src/tools/acp/spawn.ts +38 -4
- package/src/tools/credentials/ref-parse.ts +35 -0
- package/src/tools/credentials/resolve.ts +4 -10
- package/src/tools/credentials/store.ts +168 -0
- package/src/tools/document/document-tool.ts +12 -3
- package/src/tools/executor.ts +53 -15
- package/src/tools/filesystem/read.ts +27 -10
- package/src/tools/host-filesystem/read.ts +27 -15
- package/src/tools/network/url-safety.ts +9 -16
- package/src/tools/permission-checker.ts +43 -52
- package/src/tools/registry.ts +2 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +63 -35
- package/src/tools/shared/filesystem/legacy-read-args.ts +22 -0
- package/src/tools/shared/filesystem/types.ts +5 -5
- package/src/tools/skills/scaffold-managed.ts +25 -7
- package/src/tools/subagent/spawn.ts +28 -88
- package/src/tools/tool-types.ts +26 -13
- package/src/tools/types.ts +6 -6
- package/src/tools/ui-surface/surface-shape-docs.ts +12 -1
- package/src/tools/workflows/run-workflow.ts +1 -2
- package/src/tts/__tests__/reasoning-tag-filter.test.ts +78 -0
- package/src/tts/reasoning-tag-filter.ts +89 -0
- package/src/util/__tests__/worker-process-command.test.ts +37 -0
- package/src/util/logger.ts +16 -0
- package/src/util/think-tag-stream.ts +95 -0
- package/src/util/worker-process.ts +37 -4
- package/src/windows-compiled-cli.ts +32 -0
- package/src/windows-compiled-entry.ts +4 -0
- package/src/windows-compiled-logger.ts +6 -0
- package/src/windows-compiled-worker-entry.ts +29 -0
- package/src/workspace/byok-default-profile-ensure.ts +76 -24
- package/src/workspace/custom-profile-ensure.ts +4 -24
- package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
- package/src/workspace/migrations/143-repair-deprecated-codex-model-id.ts +134 -0
- package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +265 -0
- package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +328 -0
- package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +195 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +0 -10
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/provider-commit-message-generator.ts +7 -5
- package/src/__tests__/document-workspace-file.test.ts +0 -467
- package/src/live-voice/__tests__/front-decision.test.ts +0 -645
- package/src/live-voice/front-decision.ts +0 -476
- package/src/permissions/ipc-risk-types.ts +0 -143
- package/src/permissions/risk-types.ts +0 -76
- package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
- package/src/subagent/consult-transcript.ts +0 -90
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* or an access-request notification (LUM-2489),
|
|
10
10
|
* - a stranger's reaction creates no conversation, binding, or transcript
|
|
11
11
|
* row — it is dropped as channel noise,
|
|
12
|
-
* - a known contact's reaction is recorded as an inline transcript signal
|
|
12
|
+
* - a known contact's reaction is recorded as an inline transcript signal in
|
|
13
|
+
* the conversation of the message it was attached to, whether that message
|
|
14
|
+
* arrived from the channel or the assistant posted it,
|
|
13
15
|
* - a guardian's reaction on an approval card is routed through the guardian
|
|
14
16
|
* decision pipeline (the same path as buttons and text replies).
|
|
15
17
|
*
|
|
@@ -28,14 +30,14 @@ import {
|
|
|
28
30
|
} from "../../../messaging/providers/slack/message-metadata.js";
|
|
29
31
|
import { addMessage } from "../../../persistence/conversation-crud.js";
|
|
30
32
|
import {
|
|
31
|
-
|
|
33
|
+
findInboundEvent,
|
|
34
|
+
findMessageBySourceId,
|
|
35
|
+
findSlackConversationByMessageTs,
|
|
32
36
|
linkMessage,
|
|
33
37
|
recordInbound,
|
|
34
38
|
} from "../../../persistence/delivery-crud.js";
|
|
35
39
|
import { markProcessed } from "../../../persistence/delivery-status.js";
|
|
36
|
-
import { upsertBinding } from "../../../persistence/external-conversation-store.js";
|
|
37
40
|
import { getLogger } from "../../../util/logger.js";
|
|
38
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../assistant-scope.js";
|
|
39
41
|
import type { ApprovalConversationGenerator } from "../../http-types.js";
|
|
40
42
|
import {
|
|
41
43
|
actorTrustContextFromVerdict,
|
|
@@ -100,15 +102,12 @@ export interface ReactionInterceptParams {
|
|
|
100
102
|
sourceInterface: InterfaceId | undefined;
|
|
101
103
|
conversationExternalId: string;
|
|
102
104
|
externalMessageId: string;
|
|
103
|
-
canonicalAssistantId: string;
|
|
104
105
|
rawSenderId: string | undefined;
|
|
105
106
|
canonicalSenderId: string | null;
|
|
106
107
|
actorDisplayName: string | undefined;
|
|
107
108
|
actorUsername: string | undefined;
|
|
108
109
|
replyCallbackUrl: string | undefined;
|
|
109
110
|
sourceMetadata: SourceMetadata | undefined;
|
|
110
|
-
/** Slack channel display name, for the conversation binding. */
|
|
111
|
-
slackChannelName: string | null;
|
|
112
111
|
approvalConversationGenerator: ApprovalConversationGenerator | undefined;
|
|
113
112
|
}
|
|
114
113
|
|
|
@@ -126,14 +125,12 @@ export async function handleSlackReactionIntercept(
|
|
|
126
125
|
sourceInterface,
|
|
127
126
|
conversationExternalId,
|
|
128
127
|
externalMessageId,
|
|
129
|
-
canonicalAssistantId,
|
|
130
128
|
rawSenderId,
|
|
131
129
|
canonicalSenderId,
|
|
132
130
|
actorDisplayName,
|
|
133
131
|
actorUsername,
|
|
134
132
|
replyCallbackUrl,
|
|
135
133
|
sourceMetadata,
|
|
136
|
-
slackChannelName,
|
|
137
134
|
approvalConversationGenerator,
|
|
138
135
|
} = params;
|
|
139
136
|
|
|
@@ -168,28 +165,11 @@ export async function handleSlackReactionIntercept(
|
|
|
168
165
|
typeof sourceMetadata?.messageId === "string"
|
|
169
166
|
? sourceMetadata.messageId
|
|
170
167
|
: undefined;
|
|
171
|
-
const threadTs =
|
|
172
|
-
typeof sourceMetadata?.threadId === "string" &&
|
|
173
|
-
sourceMetadata.threadId.trim().length > 0
|
|
174
|
-
? sourceMetadata.threadId.trim()
|
|
175
|
-
: undefined;
|
|
176
|
-
|
|
177
|
-
// Record for dedup + conversation resolution (known contacts only — strangers
|
|
178
|
-
// were dropped above).
|
|
179
|
-
const result = recordInbound(
|
|
180
|
-
sourceChannel,
|
|
181
|
-
conversationExternalId,
|
|
182
|
-
externalMessageId,
|
|
183
|
-
{
|
|
184
|
-
sourceMessageId: reactedMessageTs,
|
|
185
|
-
assistantId: canonicalAssistantId,
|
|
186
|
-
sourceThreadId: threadTs,
|
|
187
|
-
},
|
|
188
|
-
);
|
|
189
|
-
|
|
190
168
|
// Respect disk-pressure cleanup so reactions don't bypass storage
|
|
191
169
|
// protection. Guardians resolve to `allow-cleanup-mode` (not `block`), so a
|
|
192
|
-
// guardian's approval-by-reaction still flows.
|
|
170
|
+
// guardian's approval-by-reaction still flows. Blocked silently and before
|
|
171
|
+
// any write: a reaction is a passive signal, so the message pipeline's
|
|
172
|
+
// "storage is low, try again" notice is meaningless for an emoji.
|
|
193
173
|
const diskPressure = classifyDiskPressureTurnPolicy(getDiskPressureStatus(), {
|
|
194
174
|
sourceChannel,
|
|
195
175
|
sourceInterface,
|
|
@@ -199,86 +179,97 @@ export async function handleSlackReactionIntercept(
|
|
|
199
179
|
},
|
|
200
180
|
});
|
|
201
181
|
if (diskPressure.action === "block") {
|
|
202
|
-
// Block silently: a reaction is a passive signal, so the message
|
|
203
|
-
// pipeline's "storage is low, try again" notice is meaningless for an
|
|
204
|
-
// emoji — there is nothing to retry. Mark the event processed and stop
|
|
205
|
-
// before binding/persistence.
|
|
206
|
-
if (!result.duplicate) {
|
|
207
|
-
clearPayload(result.eventId);
|
|
208
|
-
markProcessed(result.eventId);
|
|
209
|
-
}
|
|
210
182
|
return {
|
|
211
183
|
accepted: true,
|
|
212
|
-
|
|
213
|
-
eventId: result.eventId,
|
|
184
|
+
reaction: "dropped_disk_pressure",
|
|
214
185
|
diskPressure: "blocked",
|
|
215
186
|
reason: diskPressure.reason,
|
|
216
187
|
};
|
|
217
188
|
}
|
|
218
189
|
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
190
|
+
// A redelivery is answered before anything acts on it. Recording the event
|
|
191
|
+
// is what dedups a reaction, and that happens after the guardian rail, so
|
|
192
|
+
// without this probe the same emoji could drive a decision twice.
|
|
193
|
+
const alreadyRecorded = findInboundEvent(
|
|
194
|
+
sourceChannel,
|
|
195
|
+
conversationExternalId,
|
|
196
|
+
externalMessageId,
|
|
197
|
+
);
|
|
198
|
+
if (alreadyRecorded) {
|
|
199
|
+
return {
|
|
200
|
+
accepted: true,
|
|
201
|
+
duplicate: true,
|
|
202
|
+
eventId: alreadyRecorded.eventId,
|
|
203
|
+
};
|
|
233
204
|
}
|
|
234
205
|
|
|
235
|
-
// Guardian approval-by-reaction
|
|
236
|
-
//
|
|
206
|
+
// Guardian approval-by-reaction runs before the reacted message is resolved:
|
|
207
|
+
// an approval card is addressed by its own message id and is not always a
|
|
208
|
+
// stored message. Only `reaction:` (added) expresses intent;
|
|
237
209
|
// `reaction_removed:` never does. `handleGuardianReplyIntercept` self-gates
|
|
238
|
-
// on `trustClass === "guardian"`, so a contact's reaction returns no
|
|
239
|
-
// and falls through to persistence.
|
|
240
|
-
|
|
241
|
-
if (isReactionAdded && replyCallbackUrl && !result.duplicate) {
|
|
210
|
+
// on `trustClass === "guardian"`, so a contact's reaction returns no
|
|
211
|
+
// response and falls through to persistence.
|
|
212
|
+
if (callbackData.startsWith("reaction:") && replyCallbackUrl) {
|
|
242
213
|
const reactionIntercept = await handleGuardianReplyIntercept({
|
|
243
|
-
isDuplicate:
|
|
214
|
+
isDuplicate: false,
|
|
244
215
|
trimmedContent: "",
|
|
245
216
|
hasCallbackData: true,
|
|
246
217
|
callbackData,
|
|
247
218
|
reactedMessageTs,
|
|
248
219
|
rawSenderId,
|
|
249
220
|
canonicalSenderId,
|
|
250
|
-
canonicalAssistantId,
|
|
251
221
|
sourceChannel,
|
|
252
222
|
conversationExternalId,
|
|
253
|
-
conversationId: result.conversationId,
|
|
254
|
-
eventId: result.eventId,
|
|
255
223
|
replyCallbackUrl,
|
|
256
224
|
trustClass: trustCtx.trustClass,
|
|
257
225
|
guardianPrincipalId: trustCtx.guardianPrincipalId,
|
|
258
226
|
approvalConversationGenerator,
|
|
259
227
|
});
|
|
260
|
-
// Consumed as a guardian decision (applied, or a surfaced failure delivered
|
|
261
|
-
// as an ephemeral reply). Short-circuit so we do not also persist a
|
|
262
|
-
// transcript row.
|
|
263
228
|
if (reactionIntercept.response) {
|
|
264
229
|
return reactionIntercept.response;
|
|
265
230
|
}
|
|
266
231
|
}
|
|
267
232
|
|
|
268
|
-
//
|
|
269
|
-
//
|
|
270
|
-
|
|
233
|
+
// The reaction belongs to the conversation of the message it was attached
|
|
234
|
+
// to. Slack sends no `thread_ts` on a reaction, so resolving a conversation
|
|
235
|
+
// from the reaction's own address keys one on the reacted message instead of
|
|
236
|
+
// finding the one that message lives in, minting an orphan per reaction.
|
|
237
|
+
// A message the assistant never stored has nothing to annotate, so the
|
|
238
|
+
// reaction is dropped rather than given a conversation of its own.
|
|
239
|
+
// Inbound messages carry their provider id on the event that delivered
|
|
240
|
+
// them. The assistant's own posts open no inbound event, so a reaction on
|
|
241
|
+
// one is resolved through the `slackMeta` those rows carry.
|
|
242
|
+
const targetConversationId = reactedMessageTs
|
|
243
|
+
? (findMessageBySourceId(
|
|
244
|
+
sourceChannel,
|
|
245
|
+
conversationExternalId,
|
|
246
|
+
reactedMessageTs,
|
|
247
|
+
)?.conversationId ??
|
|
248
|
+
findSlackConversationByMessageTs(
|
|
249
|
+
conversationExternalId,
|
|
250
|
+
reactedMessageTs,
|
|
251
|
+
))
|
|
252
|
+
: null;
|
|
253
|
+
if (!targetConversationId || !reactedMessageTs) {
|
|
271
254
|
log.debug(
|
|
272
|
-
{
|
|
273
|
-
"
|
|
255
|
+
{ sourceChannel, conversationExternalId, reactedMessageTs },
|
|
256
|
+
"Dropping reaction: reacted message is not stored",
|
|
274
257
|
);
|
|
275
|
-
return {
|
|
276
|
-
accepted: result.accepted,
|
|
277
|
-
duplicate: result.duplicate,
|
|
278
|
-
eventId: result.eventId,
|
|
279
|
-
};
|
|
258
|
+
return { accepted: true, reaction: "dropped_unknown_target" };
|
|
280
259
|
}
|
|
281
260
|
|
|
261
|
+
const result = recordInbound(
|
|
262
|
+
sourceChannel,
|
|
263
|
+
conversationExternalId,
|
|
264
|
+
externalMessageId,
|
|
265
|
+
// No `sourceMessageId`: that column names the provider id of the event's
|
|
266
|
+
// own message, and a reaction is not one. Claiming the reacted message's
|
|
267
|
+
// id here would put two linked rows on that id, leaving a later edit or
|
|
268
|
+
// delete of it free to resolve to the reaction instead.
|
|
269
|
+
{ conversationId: targetConversationId },
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
// Record the reaction as an inline transcript signal.
|
|
282
273
|
try {
|
|
283
274
|
await persistSlackReactionAsMessage({
|
|
284
275
|
conversationId: result.conversationId,
|
|
@@ -286,7 +277,6 @@ export async function handleSlackReactionIntercept(
|
|
|
286
277
|
eventId: result.eventId,
|
|
287
278
|
callbackData,
|
|
288
279
|
actorDisplayName,
|
|
289
|
-
threadTs,
|
|
290
280
|
reactedMessageTs,
|
|
291
281
|
duplicate: result.duplicate,
|
|
292
282
|
});
|
|
@@ -320,7 +310,6 @@ async function persistSlackReactionAsMessage(params: {
|
|
|
320
310
|
eventId: string;
|
|
321
311
|
callbackData: string;
|
|
322
312
|
actorDisplayName?: string;
|
|
323
|
-
threadTs?: string;
|
|
324
313
|
reactedMessageTs: string;
|
|
325
314
|
duplicate: boolean;
|
|
326
315
|
}): Promise<void> {
|
|
@@ -345,7 +334,11 @@ async function persistSlackReactionAsMessage(params: {
|
|
|
345
334
|
channelId: params.conversationExternalId,
|
|
346
335
|
channelTs: params.reactedMessageTs,
|
|
347
336
|
eventKind: "reaction",
|
|
348
|
-
|
|
337
|
+
// No `threadTs`: Slack sends none on a reaction, so the gateway's thread
|
|
338
|
+
// id here is the reacted message's own ts. It equals `channelTs`, which
|
|
339
|
+
// every reader treats as "not in a thread" anyway, and storing it makes
|
|
340
|
+
// the row false evidence that a thread belongs to this conversation
|
|
341
|
+
// (`legacySlackConversationHasThreadEvidence`).
|
|
349
342
|
...(params.actorDisplayName
|
|
350
343
|
? { displayName: params.actorDisplayName }
|
|
351
344
|
: {}),
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "../../../persistence/delivery-crud.js";
|
|
15
15
|
import { checkIngressForSecrets } from "../../../security/secret-ingress.js";
|
|
16
16
|
import { getLogger } from "../../../util/logger.js";
|
|
17
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../assistant-scope.js";
|
|
17
18
|
|
|
18
19
|
const log = getLogger("runtime-http");
|
|
19
20
|
|
|
@@ -36,7 +37,6 @@ export interface SecretIngressCheckParams {
|
|
|
36
37
|
actorUsername: string | undefined;
|
|
37
38
|
trustCtx: TrustContext;
|
|
38
39
|
replyCallbackUrl: string | undefined;
|
|
39
|
-
canonicalAssistantId: string;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export interface SecretIngressCheckResult {
|
|
@@ -69,7 +69,6 @@ export function runSecretIngressCheck(
|
|
|
69
69
|
actorUsername,
|
|
70
70
|
trustCtx,
|
|
71
71
|
replyCallbackUrl,
|
|
72
|
-
canonicalAssistantId,
|
|
73
72
|
} = params;
|
|
74
73
|
|
|
75
74
|
// Persist the raw payload so dead-lettered events can always be replayed.
|
|
@@ -85,7 +84,7 @@ export function runSecretIngressCheck(
|
|
|
85
84
|
senderUsername: actorUsername,
|
|
86
85
|
trustCtx,
|
|
87
86
|
replyCallbackUrl,
|
|
88
|
-
assistantId:
|
|
87
|
+
assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
89
88
|
});
|
|
90
89
|
|
|
91
90
|
// ── Secret ingress scan ──
|
|
@@ -29,11 +29,14 @@ import {
|
|
|
29
29
|
loadRawConfig,
|
|
30
30
|
} from "../../config/loader.js";
|
|
31
31
|
import {
|
|
32
|
-
LLMProvider,
|
|
33
32
|
ProfileEntry,
|
|
34
33
|
routingIdentityModelIssue,
|
|
35
34
|
} from "../../config/schemas/llm.js";
|
|
36
35
|
import { getDb } from "../../persistence/db-connection.js";
|
|
36
|
+
import {
|
|
37
|
+
resolveEntryProviderKind,
|
|
38
|
+
writableProfileProviderIssue,
|
|
39
|
+
} from "../../providers/connection-resolution.js";
|
|
37
40
|
import { ROUTING_IDENTITY_PROVIDERS } from "../../providers/inference/auth.js";
|
|
38
41
|
import type { ConnectionAvailability } from "../../providers/inference/connection-availability.js";
|
|
39
42
|
import {
|
|
@@ -150,10 +153,9 @@ const updateRequestSchema = z.object({
|
|
|
150
153
|
// ---------------------------------------------------------------------------
|
|
151
154
|
|
|
152
155
|
function assertValidProvider(provider: string): void {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
);
|
|
156
|
+
const issue = writableProfileProviderIssue(provider);
|
|
157
|
+
if (issue) {
|
|
158
|
+
throw new BadRequestError(issue);
|
|
157
159
|
}
|
|
158
160
|
}
|
|
159
161
|
|
|
@@ -182,31 +184,38 @@ function validateModel(
|
|
|
182
184
|
}
|
|
183
185
|
return [];
|
|
184
186
|
}
|
|
185
|
-
|
|
187
|
+
// An entry-name provider validates against its row's dispatchable kind,
|
|
188
|
+
// the same translation dispatch uses; the entry itself also serves as the
|
|
189
|
+
// model-list connection for custom endpoints below.
|
|
190
|
+
const entryKind = resolveEntryProviderKind(provider, model);
|
|
191
|
+
const catalogProvider = entryKind ?? provider;
|
|
192
|
+
if (isModelInCatalog(catalogProvider, model)) {
|
|
186
193
|
return [];
|
|
187
194
|
}
|
|
188
195
|
// The named connection's advertised model list is authoritative for models
|
|
189
196
|
// the code-owned catalog doesn't know — a custom (openai-compatible)
|
|
190
197
|
// endpoint declares its own models at connection-create time.
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
const modelListConnection =
|
|
199
|
+
connectionName ?? (entryKind !== null ? provider : undefined);
|
|
200
|
+
if (modelListConnection) {
|
|
201
|
+
const connection = getConnection(getDb(), modelListConnection);
|
|
193
202
|
if (connection?.models?.some((m) => m.id === model)) {
|
|
194
203
|
return [];
|
|
195
204
|
}
|
|
196
205
|
}
|
|
197
206
|
if (!allowUnlisted) {
|
|
198
207
|
const remedy =
|
|
199
|
-
|
|
208
|
+
catalogProvider === "openai-compatible"
|
|
200
209
|
? `Pass allowUnlisted to create it anyway, or declare the model on the connection ` +
|
|
201
210
|
`("assistant inference providers update <name> --model ${model}").`
|
|
202
211
|
: `Pass allowUnlisted to create it anyway, or run ` +
|
|
203
212
|
`"assistant inference models list --provider ${provider}" to see valid ids.`;
|
|
204
213
|
throw new BadRequestError(
|
|
205
|
-
`Model "${model}" is not in the catalog for provider "${
|
|
214
|
+
`Model "${model}" is not in the catalog for provider "${catalogProvider}". ${remedy}`,
|
|
206
215
|
);
|
|
207
216
|
}
|
|
208
217
|
return [
|
|
209
|
-
`Model "${model}" is not in the catalog for provider "${
|
|
218
|
+
`Model "${model}" is not in the catalog for provider "${catalogProvider}"; created anyway (allowUnlisted).`,
|
|
210
219
|
];
|
|
211
220
|
}
|
|
212
221
|
|
|
@@ -21,6 +21,7 @@ import { getDb } from "../../persistence/db-connection.js";
|
|
|
21
21
|
import {
|
|
22
22
|
type Auth,
|
|
23
23
|
AuthSchema,
|
|
24
|
+
CHATGPT_SUBSCRIPTION_CONNECTION_NAME,
|
|
24
25
|
type ConnectionModel,
|
|
25
26
|
ConnectionModelSchema,
|
|
26
27
|
ConnectionProviderSchema,
|
|
@@ -205,14 +206,26 @@ function deriveConnectionAuth(provider: string, credential: unknown): Auth {
|
|
|
205
206
|
function assertAuthMatchesProvider(provider: string, auth: Auth): void {
|
|
206
207
|
const managedAuth = auth.type === "platform";
|
|
207
208
|
const managedProvider = provider === VELLUM_MANAGED_PROVIDER;
|
|
208
|
-
if (managedAuth
|
|
209
|
-
|
|
209
|
+
if (managedAuth !== managedProvider) {
|
|
210
|
+
throw new BadRequestError(
|
|
211
|
+
managedAuth
|
|
212
|
+
? `Auth type "platform" is only valid for provider "${VELLUM_MANAGED_PROVIDER}", not "${provider}". Vellum-managed routing is selected by the provider, so omit "auth" to derive it.`
|
|
213
|
+
: `Provider "${VELLUM_MANAGED_PROVIDER}" is always platform-authenticated; "${auth.type}" auth is not valid for it. Omit "auth" to derive it, or name a real provider for key-based auth.`,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
// Same rule for the subscription identity: provider "chatgpt" and
|
|
217
|
+
// oauth_subscription auth record one fact and must pair, or a key-auth
|
|
218
|
+
// row under the identity would dispatch against the API while the user
|
|
219
|
+
// believes they are on subscription billing.
|
|
220
|
+
const subscriptionAuth = auth.type === "oauth_subscription";
|
|
221
|
+
const subscriptionProvider = provider === "chatgpt";
|
|
222
|
+
if (subscriptionAuth !== subscriptionProvider) {
|
|
223
|
+
throw new BadRequestError(
|
|
224
|
+
subscriptionAuth
|
|
225
|
+
? `Auth type "oauth_subscription" is only valid for provider "chatgpt", not "${provider}". Run the ChatGPT sign-in flow to connect a subscription.`
|
|
226
|
+
: `Provider "chatgpt" is always subscription-authenticated; "${auth.type}" auth is not valid for it. Run the ChatGPT sign-in flow, or name a real provider for key-based auth.`,
|
|
227
|
+
);
|
|
210
228
|
}
|
|
211
|
-
throw new BadRequestError(
|
|
212
|
-
managedAuth
|
|
213
|
-
? `Auth type "platform" is only valid for provider "${VELLUM_MANAGED_PROVIDER}", not "${provider}". Vellum-managed routing is selected by the provider, so omit "auth" to derive it.`
|
|
214
|
-
: `Provider "${VELLUM_MANAGED_PROVIDER}" is always platform-authenticated; "${auth.type}" auth is not valid for it. Omit "auth" to derive it, or name a real provider for key-based auth.`,
|
|
215
|
-
);
|
|
216
229
|
}
|
|
217
230
|
|
|
218
231
|
/**
|
|
@@ -323,6 +336,15 @@ async function handleCreateConnection({ body = {} }: RouteHandlerArgs) {
|
|
|
323
336
|
`Connection name "${name}" is reserved for the Vellum-managed connection. Pick another name.`,
|
|
324
337
|
);
|
|
325
338
|
}
|
|
339
|
+
// Provider ids and routing identities are labels in profile config, so an
|
|
340
|
+
// entry under one of those names could never be referenced by name (the
|
|
341
|
+
// label reads as the vendor), and a future catalog addition must never
|
|
342
|
+
// capture an existing user name. Reserve the whole vocabulary.
|
|
343
|
+
if (VALID_CONNECTION_PROVIDERS.includes(name)) {
|
|
344
|
+
throw new BadRequestError(
|
|
345
|
+
`Connection name "${name}" is reserved as a provider id. Pick another name.`,
|
|
346
|
+
);
|
|
347
|
+
}
|
|
326
348
|
|
|
327
349
|
const providerResult = ConnectionProviderSchema.safeParse(provider);
|
|
328
350
|
if (!providerResult.success) {
|
|
@@ -330,15 +352,27 @@ async function handleCreateConnection({ body = {} }: RouteHandlerArgs) {
|
|
|
330
352
|
`Invalid provider "${String(provider)}". Valid: ${VALID_CONNECTION_PROVIDERS.join(", ")}`,
|
|
331
353
|
);
|
|
332
354
|
}
|
|
355
|
+
// The chatgpt identity lives on its canonical row: routing resolves the
|
|
356
|
+
// subscription by that name, so an identity row under any other name can
|
|
357
|
+
// never dispatch.
|
|
358
|
+
if (
|
|
359
|
+
providerResult.data === "chatgpt" &&
|
|
360
|
+
name !== CHATGPT_SUBSCRIPTION_CONNECTION_NAME
|
|
361
|
+
) {
|
|
362
|
+
throw new BadRequestError(
|
|
363
|
+
`Provider "chatgpt" is reserved for the "${CHATGPT_SUBSCRIPTION_CONNECTION_NAME}" connection. Run the ChatGPT sign-in flow to connect a subscription.`,
|
|
364
|
+
);
|
|
365
|
+
}
|
|
333
366
|
const authResult = AuthSchema.safeParse(
|
|
334
367
|
auth ?? deriveConnectionAuth(providerResult.data, body.credential),
|
|
335
368
|
);
|
|
336
369
|
if (!authResult.success) {
|
|
337
370
|
throw new BadRequestError(`Invalid auth: ${authResult.error.message}`);
|
|
338
371
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
372
|
+
// Asserted on derived auth as well: derivation pairs every provider
|
|
373
|
+
// correctly except the chatgpt identity, whose fallthrough would mint
|
|
374
|
+
// api_key auth from a bare credential.
|
|
375
|
+
assertAuthMatchesProvider(providerResult.data, authResult.data);
|
|
342
376
|
|
|
343
377
|
const labelRaw = body.label;
|
|
344
378
|
if (
|
|
@@ -434,15 +468,31 @@ async function handleUpdateConnection({
|
|
|
434
468
|
if (!authResult.success) {
|
|
435
469
|
throw new BadRequestError(`Invalid auth: ${authResult.error.message}`);
|
|
436
470
|
}
|
|
471
|
+
// The canonical subscription row owns the "chatgpt" identity: writing
|
|
472
|
+
// subscription auth to it stamps the provider with the auth, mirroring
|
|
473
|
+
// the daemon's own sign-in exchange route. The CLI's login-chatgpt PATCHes
|
|
474
|
+
// auth through this route, and without the stamp a row the identity
|
|
475
|
+
// migration deliberately skipped (a claiming row with key auth) would end
|
|
476
|
+
// up as provider "openai" with subscription auth. Provider stays
|
|
477
|
+
// immutable for every other row.
|
|
478
|
+
const chatgptIdentityStamp =
|
|
479
|
+
name === CHATGPT_SUBSCRIPTION_CONNECTION_NAME &&
|
|
480
|
+
authResult.data.type === "oauth_subscription" &&
|
|
481
|
+
existing.provider !== "chatgpt";
|
|
482
|
+
|
|
437
483
|
// The pairing is enforced on an actual auth change, not on the field being
|
|
438
484
|
// present: the web editor and the CLI both resend the stored auth on every
|
|
439
485
|
// edit, so a row whose columns already disagree stays relabelable and
|
|
440
|
-
// re-pointable.
|
|
486
|
+
// re-pointable. Judged against the stamped provider when the stamp
|
|
487
|
+
// applies, since that is the pair being written.
|
|
441
488
|
if (
|
|
442
489
|
body.auth !== undefined &&
|
|
443
490
|
authFingerprint(authResult.data) !== authFingerprint(existing.auth)
|
|
444
491
|
) {
|
|
445
|
-
assertAuthMatchesProvider(
|
|
492
|
+
assertAuthMatchesProvider(
|
|
493
|
+
chatgptIdentityStamp ? "chatgpt" : existing.provider,
|
|
494
|
+
authResult.data,
|
|
495
|
+
);
|
|
446
496
|
}
|
|
447
497
|
|
|
448
498
|
const labelRaw = body.label;
|
|
@@ -473,6 +523,7 @@ async function handleUpdateConnection({
|
|
|
473
523
|
|
|
474
524
|
const result = updateConnection(getDb(), name, {
|
|
475
525
|
auth: authResult.data,
|
|
526
|
+
...(chatgptIdentityStamp ? { provider: "chatgpt" } : {}),
|
|
476
527
|
...(labelRaw !== undefined ? { label: labelRaw as string | null } : {}),
|
|
477
528
|
...customFields,
|
|
478
529
|
});
|
|
@@ -574,10 +625,21 @@ async function handleDeleteConnection({ pathParams = {} }: RouteHandlerArgs) {
|
|
|
574
625
|
// above; this keeps the scan a faithful backstop rather than one that
|
|
575
626
|
// silently skips the defaults.
|
|
576
627
|
const profiles = getEffectiveProfilesForProvider(config.llm?.profiles, dp);
|
|
628
|
+
// A binding lives in `provider` (the entry name) under the entries model,
|
|
629
|
+
// or in the legacy `provider_connection` field; both count, or deleting a
|
|
630
|
+
// bound entry would dangle the profile behind selection's silent healing.
|
|
631
|
+
// Provider values count only for non-vendor names: a profile saying
|
|
632
|
+
// "vellum" references the routing identity, never a row that happens to
|
|
633
|
+
// claim that name, and the claiming-row delete is the recovery path.
|
|
634
|
+
const nameIsEntryName = !VALID_CONNECTION_PROVIDERS.includes(name);
|
|
577
635
|
const referencingProfiles = Object.entries(profiles)
|
|
578
|
-
.filter(
|
|
579
|
-
|
|
580
|
-
|
|
636
|
+
.filter(([, p]) => {
|
|
637
|
+
const entry = p as Record<string, unknown>;
|
|
638
|
+
return (
|
|
639
|
+
entry.provider_connection === name ||
|
|
640
|
+
(nameIsEntryName && entry.provider === name)
|
|
641
|
+
);
|
|
642
|
+
})
|
|
581
643
|
.map(([profileName]) => profileName);
|
|
582
644
|
|
|
583
645
|
const result = deleteConnection(getDb(), name, {
|
|
@@ -143,6 +143,9 @@ async function handleExport({
|
|
|
143
143
|
? [eq(messages.conversationId, conversationId)]
|
|
144
144
|
: [];
|
|
145
145
|
|
|
146
|
+
// Any-state export, deliberately: this is a diagnostic surface, and an
|
|
147
|
+
// in-flight row (finalized = 0, content a { ref } into the turn's delta
|
|
148
|
+
// file) is often exactly what a bug report needs to show.
|
|
146
149
|
const messageRows = capRows(
|
|
147
150
|
db
|
|
148
151
|
.select()
|