@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
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named read accessors for the `messages` table.
|
|
3
|
+
*
|
|
4
|
+
* Every row in `messages` is conversation content in some state of
|
|
5
|
+
* completeness: `finalized = 1` rows are immutable history, `finalized = 0`
|
|
6
|
+
* rows are still being written and their `content` may be a `{ ref }` into an
|
|
7
|
+
* in-flight delta file that disappears when the turn completes. Ad-hoc queries
|
|
8
|
+
* tend to encode a visibility decision without stating it; each accessor here
|
|
9
|
+
* states its decision in its name and contract, so a caller (and a reviewer)
|
|
10
|
+
* chooses between "completed history" and "any row" deliberately.
|
|
11
|
+
*
|
|
12
|
+
* Conversation-history reads (transcripts, lineage, pagination) stay with
|
|
13
|
+
* `getMessages` / `getMessagesAfter` / `getMessagesPaginated` in
|
|
14
|
+
* `conversation-crud.ts`, which also own fork-lineage resolution. This module
|
|
15
|
+
* is for the narrower point lookups and aggregates that other persistence
|
|
16
|
+
* modules need.
|
|
17
|
+
*
|
|
18
|
+
* Correlated subqueries embedded inside larger SQL (usage accounting's
|
|
19
|
+
* turn-index arithmetic, search candidate joins, `message_count` projections)
|
|
20
|
+
* are out of scope: extracting them would restructure their host queries. They
|
|
21
|
+
* carry their visibility decision as a comment at the site instead.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { and, desc, eq, inArray, lt, sql } from "drizzle-orm";
|
|
25
|
+
|
|
26
|
+
import { type DrizzleDb, getDb } from "./db-connection.js";
|
|
27
|
+
import { messages } from "./schema/index.js";
|
|
28
|
+
|
|
29
|
+
/** `(id, createdAt)` of a message, the shape cursor and watermark logic needs. */
|
|
30
|
+
export interface MessageRef {
|
|
31
|
+
id: string;
|
|
32
|
+
createdAt: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Structural read handle: anything that can `select` like the shared
|
|
37
|
+
* connection, which includes the connection itself and an open transaction.
|
|
38
|
+
* Every accessor takes `opts.db` with this type and defaults to the shared
|
|
39
|
+
* connection, so a caller holding its own handle (a transaction, an injected
|
|
40
|
+
* or in-memory database) reads the same database it writes.
|
|
41
|
+
*/
|
|
42
|
+
export type MessageReadHandle = Pick<DrizzleDb, "select">;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The newest completed assistant message in a conversation, or null when it
|
|
46
|
+
* has none.
|
|
47
|
+
*
|
|
48
|
+
* Finalized-only: an assistant row that is still streaming is not a reply yet,
|
|
49
|
+
* so consumers tracking "the latest reply" (read/unread watermarks, previews)
|
|
50
|
+
* must not anchor on it. The row qualifies on its own once the turn completes.
|
|
51
|
+
*
|
|
52
|
+
* `db` lets a caller inside a transaction read through its own handle.
|
|
53
|
+
*/
|
|
54
|
+
export function latestAssistantMessage(
|
|
55
|
+
conversationId: string,
|
|
56
|
+
opts?: { db?: MessageReadHandle },
|
|
57
|
+
): MessageRef | null {
|
|
58
|
+
return newestFinalizedAssistantRow(conversationId, opts?.db ?? getDb());
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The newest completed assistant message strictly before `createdAt`, or null.
|
|
63
|
+
* Strict comparison: rewind logic that landed on a same-timestamp sibling
|
|
64
|
+
* would classify the latest reply as already seen.
|
|
65
|
+
*/
|
|
66
|
+
export function latestAssistantMessageBefore(
|
|
67
|
+
conversationId: string,
|
|
68
|
+
createdAt: number,
|
|
69
|
+
opts?: { db?: MessageReadHandle },
|
|
70
|
+
): MessageRef | null {
|
|
71
|
+
return newestFinalizedAssistantRow(
|
|
72
|
+
conversationId,
|
|
73
|
+
opts?.db ?? getDb(),
|
|
74
|
+
createdAt,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function newestFinalizedAssistantRow(
|
|
79
|
+
conversationId: string,
|
|
80
|
+
db: MessageReadHandle,
|
|
81
|
+
strictlyBefore?: number,
|
|
82
|
+
): MessageRef | null {
|
|
83
|
+
const row = db
|
|
84
|
+
.select({ id: messages.id, createdAt: messages.createdAt })
|
|
85
|
+
.from(messages)
|
|
86
|
+
.where(
|
|
87
|
+
and(
|
|
88
|
+
eq(messages.conversationId, conversationId),
|
|
89
|
+
eq(messages.role, "assistant"),
|
|
90
|
+
eq(messages.finalized, 1),
|
|
91
|
+
...(strictlyBefore === undefined
|
|
92
|
+
? []
|
|
93
|
+
: [lt(messages.createdAt, strictlyBefore)]),
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
.orderBy(desc(messages.createdAt), desc(messages.id))
|
|
97
|
+
.limit(1)
|
|
98
|
+
.get();
|
|
99
|
+
return row ?? null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Raw `content` of the last user-role row in a conversation, in insertion
|
|
104
|
+
* order (`rowid DESC`, not `createdAt`), or null when there is none.
|
|
105
|
+
*
|
|
106
|
+
* Insertion order is load-bearing for the undo path this serves: same-
|
|
107
|
+
* millisecond rows must resolve to the one written last. User rows are always
|
|
108
|
+
* written finalized, so no completeness predicate applies; only assistant
|
|
109
|
+
* turns stream.
|
|
110
|
+
*/
|
|
111
|
+
export function latestUserMessageRawContent(
|
|
112
|
+
conversationId: string,
|
|
113
|
+
opts?: { db?: MessageReadHandle },
|
|
114
|
+
): string | null {
|
|
115
|
+
const row = (opts?.db ?? getDb())
|
|
116
|
+
.select({ content: messages.content })
|
|
117
|
+
.from(messages)
|
|
118
|
+
.where(
|
|
119
|
+
and(
|
|
120
|
+
eq(messages.conversationId, conversationId),
|
|
121
|
+
eq(messages.role, "user"),
|
|
122
|
+
),
|
|
123
|
+
)
|
|
124
|
+
.orderBy(sql`rowid DESC`)
|
|
125
|
+
.limit(1)
|
|
126
|
+
.get();
|
|
127
|
+
return row?.content ?? null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Per-conversation count and latest timestamp of rows with `role`, for the
|
|
132
|
+
* given conversations.
|
|
133
|
+
*
|
|
134
|
+
* Any-state deliberately: these aggregates feed list ordering and previews,
|
|
135
|
+
* where a streaming reply still counts as activity. A caller needing
|
|
136
|
+
* completed-only aggregates should say so here rather than post-filtering.
|
|
137
|
+
*/
|
|
138
|
+
export function countMessagesByRoleForConversations(
|
|
139
|
+
conversationIds: string[],
|
|
140
|
+
role: string,
|
|
141
|
+
opts?: { db?: MessageReadHandle },
|
|
142
|
+
): Map<string, { count: number; lastAt: number }> {
|
|
143
|
+
if (conversationIds.length === 0) {
|
|
144
|
+
return new Map();
|
|
145
|
+
}
|
|
146
|
+
const rows = (opts?.db ?? getDb())
|
|
147
|
+
.select({
|
|
148
|
+
conversationId: messages.conversationId,
|
|
149
|
+
count: sql<number>`COUNT(*)`.as("count"),
|
|
150
|
+
lastAt: sql<number>`MAX(${messages.createdAt})`.as("last_at"),
|
|
151
|
+
})
|
|
152
|
+
.from(messages)
|
|
153
|
+
.where(
|
|
154
|
+
and(
|
|
155
|
+
inArray(messages.conversationId, conversationIds),
|
|
156
|
+
eq(messages.role, role),
|
|
157
|
+
),
|
|
158
|
+
)
|
|
159
|
+
.groupBy(messages.conversationId)
|
|
160
|
+
.all();
|
|
161
|
+
return new Map(
|
|
162
|
+
rows.map((r) => [
|
|
163
|
+
r.conversationId,
|
|
164
|
+
{ count: Number(r.count), lastAt: Number(r.lastAt) },
|
|
165
|
+
]),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Which of `messageIds` exist as rows, in any state.
|
|
171
|
+
*
|
|
172
|
+
* Any-state deliberately: existence is the question (orphan detection for
|
|
173
|
+
* rows referencing messages), and a streaming row exists. An empty input
|
|
174
|
+
* returns an empty set without querying.
|
|
175
|
+
*/
|
|
176
|
+
export function existingMessageIds(
|
|
177
|
+
messageIds: string[],
|
|
178
|
+
opts?: { db?: MessageReadHandle },
|
|
179
|
+
): Set<string> {
|
|
180
|
+
if (messageIds.length === 0) {
|
|
181
|
+
return new Set();
|
|
182
|
+
}
|
|
183
|
+
return new Set(
|
|
184
|
+
(opts?.db ?? getDb())
|
|
185
|
+
.select({ id: messages.id })
|
|
186
|
+
.from(messages)
|
|
187
|
+
.where(inArray(messages.id, messageIds))
|
|
188
|
+
.all()
|
|
189
|
+
.map((r) => r.id),
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The conversation that owns `messageId`, in any state, or null when the
|
|
195
|
+
* message does not exist.
|
|
196
|
+
*
|
|
197
|
+
* Any-state deliberately: callers hold an id the user acted on (a bookmark on
|
|
198
|
+
* a rendered row, an attachment link), and a rendered row may still be
|
|
199
|
+
* streaming.
|
|
200
|
+
*/
|
|
201
|
+
export function messageConversationId(
|
|
202
|
+
messageId: string,
|
|
203
|
+
opts?: { db?: MessageReadHandle },
|
|
204
|
+
): string | null {
|
|
205
|
+
const row = (opts?.db ?? getDb())
|
|
206
|
+
.select({ conversationId: messages.conversationId })
|
|
207
|
+
.from(messages)
|
|
208
|
+
.where(eq(messages.id, messageId))
|
|
209
|
+
.get();
|
|
210
|
+
return row?.conversationId ?? null;
|
|
211
|
+
}
|
|
@@ -7,20 +7,11 @@ const COLUMN_DEFINITION = "workspace_path TEXT";
|
|
|
7
7
|
/**
|
|
8
8
|
* Add `workspace_path` to `documents` and enforce one document per file.
|
|
9
9
|
*
|
|
10
|
-
* The column
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* drafts, client-created surfaces) stay NULL.
|
|
16
|
-
*
|
|
17
|
-
* The unique index is partial (`WHERE workspace_path IS NOT NULL`) so the many
|
|
18
|
-
* NULL rows stay unconstrained while a given file resolves to exactly one
|
|
19
|
-
* document. The find-or-create route depends on that uniqueness for its
|
|
20
|
-
* idempotency.
|
|
21
|
-
*
|
|
22
|
-
* Nullable with no backfill: nothing recorded a file binding before this
|
|
23
|
-
* column existed, so pre-existing rows correctly stay NULL.
|
|
10
|
+
* The column and its partial unique index are unused by the daemon: no code
|
|
11
|
+
* reads or writes them. Some rows carry a non-NULL path; new rows stay NULL.
|
|
12
|
+
* The migration stays in the chain because migrations are append-only, and the
|
|
13
|
+
* drizzle model in `schema/documents.ts` carries the column so it keeps
|
|
14
|
+
* describing the physical table.
|
|
24
15
|
*
|
|
25
16
|
* Idempotent: the column add is guarded with `tableHasColumn` and the index
|
|
26
17
|
* with `IF NOT EXISTS`, so a crash between the two does not break the next
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
import { describe, expect, test } from "bun:test";
|
|
3
|
+
|
|
4
|
+
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
5
|
+
|
|
6
|
+
import * as schema from "../schema.js";
|
|
7
|
+
import { migrateChatgptSubscriptionRowIdentity } from "./366-chatgpt-subscription-row-identity.js";
|
|
8
|
+
|
|
9
|
+
function createTestDb() {
|
|
10
|
+
const sqlite = new Database(":memory:");
|
|
11
|
+
sqlite.exec(/*sql*/ `
|
|
12
|
+
CREATE TABLE provider_connections (
|
|
13
|
+
name TEXT PRIMARY KEY,
|
|
14
|
+
provider TEXT NOT NULL,
|
|
15
|
+
auth TEXT NOT NULL,
|
|
16
|
+
label TEXT,
|
|
17
|
+
base_url TEXT,
|
|
18
|
+
models TEXT,
|
|
19
|
+
created_at INTEGER NOT NULL,
|
|
20
|
+
updated_at INTEGER NOT NULL
|
|
21
|
+
);
|
|
22
|
+
`);
|
|
23
|
+
return { sqlite, db: drizzle(sqlite, { schema }) };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function insertRow(
|
|
27
|
+
sqlite: Database,
|
|
28
|
+
name: string,
|
|
29
|
+
provider: string,
|
|
30
|
+
auth: string,
|
|
31
|
+
): void {
|
|
32
|
+
sqlite
|
|
33
|
+
.query(
|
|
34
|
+
/*sql*/ `INSERT INTO provider_connections (name, provider, auth, created_at, updated_at)
|
|
35
|
+
VALUES (?, ?, ?, 1, 1)`,
|
|
36
|
+
)
|
|
37
|
+
.run(name, provider, auth);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readProvider(sqlite: Database, name: string): string | undefined {
|
|
41
|
+
const row = sqlite
|
|
42
|
+
.query(`SELECT provider FROM provider_connections WHERE name = ?`)
|
|
43
|
+
.get(name) as { provider: string } | null;
|
|
44
|
+
return row?.provider;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe("migration 366: chatgpt-subscription row identity", () => {
|
|
48
|
+
test("flips the subscription row to provider chatgpt", () => {
|
|
49
|
+
const { sqlite, db } = createTestDb();
|
|
50
|
+
insertRow(
|
|
51
|
+
sqlite,
|
|
52
|
+
"chatgpt-subscription",
|
|
53
|
+
"openai",
|
|
54
|
+
'{"type":"oauth_subscription","credential":"credential/chatgpt/access_token"}',
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
migrateChatgptSubscriptionRowIdentity(db);
|
|
58
|
+
|
|
59
|
+
expect(readProvider(sqlite, "chatgpt-subscription")).toBe("chatgpt");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("leaves a claiming row with key auth untouched", () => {
|
|
63
|
+
const { sqlite, db } = createTestDb();
|
|
64
|
+
insertRow(
|
|
65
|
+
sqlite,
|
|
66
|
+
"chatgpt-subscription",
|
|
67
|
+
"openai",
|
|
68
|
+
'{"type":"api_key","credential":"vault/openai"}',
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
migrateChatgptSubscriptionRowIdentity(db);
|
|
72
|
+
|
|
73
|
+
expect(readProvider(sqlite, "chatgpt-subscription")).toBe("openai");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("leaves other rows untouched", () => {
|
|
77
|
+
const { sqlite, db } = createTestDb();
|
|
78
|
+
insertRow(sqlite, "openai-key", "openai", '{"type":"api_key"}');
|
|
79
|
+
insertRow(sqlite, "vellum", "vellum", '{"type":"platform"}');
|
|
80
|
+
|
|
81
|
+
migrateChatgptSubscriptionRowIdentity(db);
|
|
82
|
+
|
|
83
|
+
expect(readProvider(sqlite, "openai-key")).toBe("openai");
|
|
84
|
+
expect(readProvider(sqlite, "vellum")).toBe("vellum");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("leaves unparseable auth untouched", () => {
|
|
88
|
+
const { sqlite, db } = createTestDb();
|
|
89
|
+
insertRow(sqlite, "chatgpt-subscription", "openai", "not json");
|
|
90
|
+
|
|
91
|
+
migrateChatgptSubscriptionRowIdentity(db);
|
|
92
|
+
|
|
93
|
+
expect(readProvider(sqlite, "chatgpt-subscription")).toBe("openai");
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("is idempotent", () => {
|
|
97
|
+
const { sqlite, db } = createTestDb();
|
|
98
|
+
insertRow(
|
|
99
|
+
sqlite,
|
|
100
|
+
"chatgpt-subscription",
|
|
101
|
+
"openai",
|
|
102
|
+
'{"type":"oauth_subscription"}',
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
migrateChatgptSubscriptionRowIdentity(db);
|
|
106
|
+
migrateChatgptSubscriptionRowIdentity(db);
|
|
107
|
+
|
|
108
|
+
expect(readProvider(sqlite, "chatgpt-subscription")).toBe("chatgpt");
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("no-ops without the table or the row", () => {
|
|
112
|
+
const bare = new Database(":memory:");
|
|
113
|
+
expect(() =>
|
|
114
|
+
migrateChatgptSubscriptionRowIdentity(drizzle(bare, { schema })),
|
|
115
|
+
).not.toThrow();
|
|
116
|
+
|
|
117
|
+
const { db } = createTestDb();
|
|
118
|
+
expect(() => migrateChatgptSubscriptionRowIdentity(db)).not.toThrow();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stamp the ChatGPT-subscription row with its own provider identity.
|
|
5
|
+
*
|
|
6
|
+
* The row is the subscription route by definition (auth modality = provider
|
|
7
|
+
* identity), but it historically stored `provider: "openai"` and was found
|
|
8
|
+
* by name, which left provider "openai" ambiguous on disk: a BYOK api_key
|
|
9
|
+
* row and the subscription row read identically at the provider column.
|
|
10
|
+
* With the row carrying `provider: "chatgpt"`, auth type is derivable from
|
|
11
|
+
* the provider for every row, and provider-keyed scans for "openai" no
|
|
12
|
+
* longer surface the subscription row.
|
|
13
|
+
*
|
|
14
|
+
* Scoped tightly: only the canonical row name with oauth_subscription auth
|
|
15
|
+
* is flipped. A claiming row under the same name with key auth is an
|
|
16
|
+
* ordinary connection and keeps its provider. Idempotent: a flipped row no
|
|
17
|
+
* longer matches, and the table-exists guard covers databases from before
|
|
18
|
+
* migration 243.
|
|
19
|
+
*/
|
|
20
|
+
export function migrateChatgptSubscriptionRowIdentity(
|
|
21
|
+
database: DrizzleDb,
|
|
22
|
+
): void {
|
|
23
|
+
const raw = getSqliteFrom(database);
|
|
24
|
+
|
|
25
|
+
const tableExists = raw
|
|
26
|
+
.query(
|
|
27
|
+
`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'provider_connections'`,
|
|
28
|
+
)
|
|
29
|
+
.get();
|
|
30
|
+
if (!tableExists) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const row = raw
|
|
35
|
+
.query(
|
|
36
|
+
`SELECT provider, auth FROM provider_connections WHERE name = 'chatgpt-subscription'`,
|
|
37
|
+
)
|
|
38
|
+
.get() as { provider: string; auth: string } | null;
|
|
39
|
+
if (!row || row.provider !== "openai") {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let authType: unknown;
|
|
44
|
+
try {
|
|
45
|
+
const parsed: unknown = JSON.parse(row.auth);
|
|
46
|
+
authType =
|
|
47
|
+
parsed !== null && typeof parsed === "object"
|
|
48
|
+
? (parsed as { type?: unknown }).type
|
|
49
|
+
: undefined;
|
|
50
|
+
} catch {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (authType !== "oauth_subscription") {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
raw
|
|
58
|
+
.prepare(
|
|
59
|
+
`UPDATE provider_connections SET provider = 'chatgpt', updated_at = ? WHERE name = 'chatgpt-subscription'`,
|
|
60
|
+
)
|
|
61
|
+
.run(Date.now());
|
|
62
|
+
}
|
|
@@ -19,8 +19,32 @@ import { sql } from "drizzle-orm";
|
|
|
19
19
|
export function realUserTurnContentFilter(
|
|
20
20
|
alias: string,
|
|
21
21
|
): ReturnType<typeof sql> {
|
|
22
|
-
return sql.raw(
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
return sql.raw(realUserTurnContentFilterSql(alias));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Raw-string form of {@link realUserTurnContentFilter}, for queries built as
|
|
27
|
+
* plain SQL template strings (`rawAll` sites). Same fragment, one source.
|
|
28
|
+
*
|
|
29
|
+
* `finalized = 1`: the grouped tool-result row is a USER-role row reserved
|
|
30
|
+
* in-flight (`ensureToolResultRowReserved`), and while it streams its content
|
|
31
|
+
* is a `{ ref }` pointer that does not contain the tool_result text the
|
|
32
|
+
* exclusions match. Without this predicate it counts as a real user turn
|
|
33
|
+
* mid-tool-execution and stops counting once the content folds inline.
|
|
34
|
+
*
|
|
35
|
+
* Bare `[]` content is deliberately NOT excluded: a hidden send persists its
|
|
36
|
+
* user row with empty display content (`processMessage` with
|
|
37
|
+
* `displayContent: ""`) and still runs a turn, so `[]` rows are legitimate
|
|
38
|
+
* turns. The cost is a narrow pre-existing window in the writer-creation
|
|
39
|
+
* fallback, where the tool-result row is born finalized with a `[]`
|
|
40
|
+
* placeholder and counts until the first content write lands; that window is
|
|
41
|
+
* rare (writer creation failure only) and transient, and closing it needs a
|
|
42
|
+
* signal that distinguishes the placeholder from a real empty-display turn.
|
|
43
|
+
*/
|
|
44
|
+
export function realUserTurnContentFilterSql(alias: string): string {
|
|
45
|
+
return (
|
|
46
|
+
`${alias}.finalized = 1 ` +
|
|
47
|
+
`AND ${alias}.content NOT LIKE '%"type":"tool\\_result"%' ESCAPE '\\' ` +
|
|
48
|
+
`AND ${alias}.content NOT LIKE '%"type":"web\\_search\\_tool\\_result"%' ESCAPE '\\'`
|
|
25
49
|
);
|
|
26
50
|
}
|
|
@@ -22,13 +22,13 @@ export const documents = sqliteTable(
|
|
|
22
22
|
wordCount: integer("word_count").notNull().default(0),
|
|
23
23
|
createdAt: integer("created_at").notNull(),
|
|
24
24
|
updatedAt: integer("updated_at").notNull(),
|
|
25
|
-
//
|
|
26
|
-
// NULL
|
|
25
|
+
// Unused by the daemon: no code reads or writes the column, and some rows
|
|
26
|
+
// carry a non-NULL path. It stays in the model because migration 360 puts
|
|
27
|
+
// it in the physical table and the model must keep describing that table.
|
|
27
28
|
workspacePath: text("workspace_path"),
|
|
28
29
|
},
|
|
29
30
|
(table) => [
|
|
30
|
-
// Partial so the
|
|
31
|
-
// file resolves to exactly one document.
|
|
31
|
+
// Partial, so the NULL rows stay unconstrained.
|
|
32
32
|
uniqueIndex("idx_documents_workspace_path")
|
|
33
33
|
.on(table.workspacePath)
|
|
34
34
|
.where(sql`workspace_path IS NOT NULL`),
|
package/src/persistence/steps.ts
CHANGED
|
@@ -473,6 +473,7 @@ import { migrateAddConversationSubagentKind } from "./migrations/362-add-convers
|
|
|
473
473
|
import { migrateBackfillScheduleInferenceProfile } from "./migrations/363-backfill-schedule-inference-profile.js";
|
|
474
474
|
import { migrateAddScheduleSourceKey } from "./migrations/364-add-schedule-source-key.js";
|
|
475
475
|
import { migrateAddConversationForkStrategy } from "./migrations/365-add-conversation-fork-strategy.js";
|
|
476
|
+
import { migrateChatgptSubscriptionRowIdentity } from "./migrations/366-chatgpt-subscription-row-identity.js";
|
|
476
477
|
import type { MigrationStep } from "./migrations/run-migrations.js";
|
|
477
478
|
|
|
478
479
|
export const migrationSteps: MigrationStep[] = [
|
|
@@ -1573,4 +1574,12 @@ export const migrationSteps: MigrationStep[] = [
|
|
|
1573
1574
|
},
|
|
1574
1575
|
migrateAddScheduleSourceKey,
|
|
1575
1576
|
migrateAddConversationForkStrategy,
|
|
1577
|
+
{
|
|
1578
|
+
name: "migrateChatgptSubscriptionRowIdentity",
|
|
1579
|
+
run: migrateChatgptSubscriptionRowIdentity,
|
|
1580
|
+
// The table-exists guard treats a missing table as nothing-to-do, so the
|
|
1581
|
+
// creating migration must be checkpointed first or a repair flow could
|
|
1582
|
+
// permanently checkpoint the no-op.
|
|
1583
|
+
dependsOn: ["migrateCreateProviderConnections"],
|
|
1584
|
+
},
|
|
1576
1585
|
];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guards that `resolveOauthCallbackUrl` reaches plugins.
|
|
3
|
+
*
|
|
4
|
+
* The shim written into `<workspaceDir>/node_modules/@vellumai/plugin-api`
|
|
5
|
+
* re-binds whatever `Object.keys()` finds on the plugin-api namespace, so an
|
|
6
|
+
* export missing from `index.ts` is missing from every installed plugin with
|
|
7
|
+
* no other signal than a plugin failing to import it.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, test } from "bun:test";
|
|
11
|
+
|
|
12
|
+
import { PLUGIN_API_EXPORTS } from "../../embedded/plugin-api.js";
|
|
13
|
+
import * as pluginApi from "../index.js";
|
|
14
|
+
|
|
15
|
+
describe("plugin-api OAuth callback export", () => {
|
|
16
|
+
test("is exported from the plugin-api surface", () => {
|
|
17
|
+
expect(typeof pluginApi.resolveOauthCallbackUrl).toEqual("function");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("is carried into the generated shim's binding list", () => {
|
|
21
|
+
expect(PLUGIN_API_EXPORTS).toContain("resolveOauthCallbackUrl");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("takes no arguments, so a plugin cannot vary the URI", () => {
|
|
25
|
+
// The value a Client ID Metadata Document publishes and the value the
|
|
26
|
+
// host later authorizes with have to be the same string.
|
|
27
|
+
expect(pluginApi.resolveOauthCallbackUrl.length).toEqual(0);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -39,6 +39,14 @@ export const HOOKS = {
|
|
|
39
39
|
/** Union of every hook name declared in {@link HOOKS}. */
|
|
40
40
|
export type HookName = (typeof HOOKS)[keyof typeof HOOKS];
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Message kind for the hidden user row that starts a voice escalation leg.
|
|
44
|
+
* Hooks use this marker to distinguish the continuation instruction from
|
|
45
|
+
* other transcript-suppressed prompts without depending on host voice code.
|
|
46
|
+
*/
|
|
47
|
+
export const VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND =
|
|
48
|
+
"voice_escalation_continuation";
|
|
49
|
+
|
|
42
50
|
/**
|
|
43
51
|
* Appended (inside the `<system_notice>` wrapper) to the internal continuation /
|
|
44
52
|
* completion nudge strings that re-query the model. Those notices are injected
|