@vellumai/assistant 0.12.1 → 0.12.2-staging.2
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 +4 -0
- package/ARCHITECTURE.md +20 -21
- package/docs/architecture/turn-actor.md +15 -8
- package/docs/guardian-request-flow.md +16 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +13 -8
- package/node_modules/@vellumai/slack-text/src/label-resolution-entities.test.ts +95 -0
- package/openapi.yaml +360 -51
- package/package.json +3 -1
- package/scripts/smoke-desktop-window-theme.ts +186 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
- package/src/__tests__/anthropic-provider.test.ts +0 -63
- package/src/__tests__/app-compiler.test.ts +6 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
- package/src/__tests__/app-dir-path-guard.test.ts +1 -3
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +6 -7
- package/src/__tests__/assistant-event-hub.test.ts +44 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
- package/src/__tests__/computer-use-tools.test.ts +19 -7
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +28 -29
- package/src/__tests__/config-watcher.test.ts +23 -8
- package/src/__tests__/connection-model-compat.test.ts +2 -2
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +26 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
- package/src/__tests__/conversation-queue.test.ts +48 -207
- package/src/__tests__/conversation-retry-discard.test.ts +54 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +28 -0
- package/src/__tests__/conversation-skill-tools.test.ts +27 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
- package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-point-at-capability.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
- package/src/__tests__/conversation-title-service.test.ts +14 -10
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
- package/src/__tests__/credential-record-retire.test.ts +171 -1
- package/src/__tests__/credential-routes.test.ts +250 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -3
- package/src/__tests__/cu-unified-flow.test.ts +14 -4
- package/src/__tests__/document-sync-tags.test.ts +25 -0
- package/src/__tests__/drain-kick-guard.test.ts +0 -2
- package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
- package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
- package/src/__tests__/git-porcelain.test.ts +47 -0
- package/src/__tests__/heartbeat-service.test.ts +56 -40
- package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
- package/src/__tests__/host-bash-proxy.test.ts +26 -45
- package/src/__tests__/host-browser-proxy.test.ts +6 -17
- package/src/__tests__/host-cu-proxy.test.ts +596 -0
- package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
- package/src/__tests__/host-file-proxy.test.ts +11 -23
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
- package/src/__tests__/list-messages-camera-frame.test.ts +121 -0
- package/src/__tests__/llm-catalog-parity.test.ts +25 -0
- package/src/__tests__/mcp-auth-routes.test.ts +6 -9
- package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
- package/src/__tests__/mcp-health-check.test.ts +8 -11
- package/src/__tests__/mcp-list-plugin-servers.test.ts +8 -10
- package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
- package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
- package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +355 -548
- package/src/__tests__/model-intents.test.ts +3 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
- package/src/__tests__/oauth-commands-routes.test.ts +168 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +22 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/openai-provider.test.ts +1 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
- package/src/__tests__/platform-callback-registration.test.ts +8 -16
- package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +14 -0
- package/src/__tests__/qdrant-manager.test.ts +132 -0
- package/src/__tests__/resolve-app.test.ts +135 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +229 -6
- package/src/__tests__/script-proxy-certs.test.ts +35 -0
- package/src/__tests__/secret-routes-acp-guard.test.ts +59 -1
- package/src/__tests__/service-account-token.test.ts +247 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skills.test.ts +9 -4
- package/src/__tests__/source-fingerprint.test.ts +184 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +70 -3
- package/src/__tests__/subagent-tools.test.ts +3 -2
- package/src/__tests__/telephony-tts-guard.test.ts +38 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/ui-channel-variants.test.ts +1 -56
- package/src/__tests__/unicode.test.ts +13 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
- package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
- package/src/__tests__/workspace-git-service.test.ts +26 -0
- package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +257 -6
- package/src/acp/__tests__/acp-credentials.test.ts +13 -0
- package/src/acp/__tests__/agent-process.test.ts +258 -4
- package/src/acp/__tests__/auth-required.test.ts +96 -0
- package/src/acp/__tests__/claude-token-refresh.test.ts +257 -0
- package/src/acp/__tests__/client-handler.test.ts +90 -2
- package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +60 -1
- package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
- package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
- package/src/acp/__tests__/session-manager.test.ts +895 -4
- package/src/acp/acp-claude-oauth.ts +328 -14
- package/src/acp/acp-credentials.ts +19 -0
- package/src/acp/agent-process.test.ts +4 -1
- package/src/acp/agent-process.ts +96 -10
- package/src/acp/auth-required.ts +50 -1
- package/src/acp/auto-install.test.ts +9 -7
- package/src/acp/claude-token-refresh.ts +150 -0
- package/src/acp/client-handler.ts +16 -3
- package/src/acp/model-config.test.ts +166 -0
- package/src/acp/model-config.ts +138 -0
- package/src/acp/prepare-agent-env.ts +21 -6
- package/src/acp/resolve-agent.test.ts +220 -6
- package/src/acp/resolve-agent.ts +88 -23
- package/src/acp/session-manager.test.ts +196 -3
- package/src/acp/session-manager.ts +441 -18
- package/src/acp/types.ts +50 -5
- package/src/agent/loop.ts +1 -0
- package/src/api/events/acp-session-model-update.test.ts +88 -0
- package/src/api/events/acp-session-model-update.ts +46 -0
- package/src/api/events/app-files-changed.ts +4 -3
- package/src/api/events/notification-intent.ts +2 -0
- package/src/api/events/user-message-echo.ts +7 -1
- package/src/api/index.ts +6 -0
- package/src/api/responses/conversation-message.ts +5 -0
- package/src/apps/app-store.ts +1 -1
- package/src/apps/resolve-app.ts +81 -0
- package/src/apps/source-fingerprint.ts +266 -0
- package/src/avatar/identity-avatar.ts +7 -2
- package/src/bundler/app-compiler.ts +15 -0
- package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
- package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
- package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
- package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
- package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
- package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
- package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
- package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
- package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +4 -4
- package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
- package/src/calls/__tests__/voice-control-protocol.test.ts +120 -25
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
- package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
- package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
- package/src/calls/__tests__/voice-session-bridge.test.ts +56 -1
- package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
- package/src/calls/barge-in-guard.ts +118 -0
- package/src/calls/call-constants.ts +24 -4
- package/src/calls/call-controller.ts +499 -199
- package/src/calls/call-transport.ts +16 -0
- package/src/calls/media-stream-output.ts +32 -0
- package/src/calls/media-stream-server.ts +82 -30
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/{live-voice → calls}/progress-narration.ts +2 -2
- package/src/calls/resolve-call-tts-provider.ts +33 -2
- package/src/calls/tts-call-strategy.ts +9 -5
- package/src/calls/types.ts +2 -0
- package/src/calls/voice-control-protocol.ts +155 -21
- package/src/calls/voice-leg-coordinator.ts +189 -0
- package/src/calls/voice-progress-cadence.ts +423 -0
- package/src/calls/voice-session-bridge.ts +92 -72
- package/src/calls/voice-triage-escalate.ts +178 -59
- package/src/cli/commands/__tests__/apps.test.ts +245 -0
- package/src/cli/commands/__tests__/bash.test.ts +53 -0
- package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
- package/src/cli/commands/apps.help.ts +67 -13
- package/src/cli/commands/apps.ts +183 -0
- package/src/cli/commands/bash.help.ts +8 -13
- package/src/cli/commands/bash.ts +7 -25
- package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
- package/src/cli/commands/channels/index.help.ts +70 -2
- package/src/cli/commands/channels/index.ts +16 -3
- package/src/cli/commands/channels/send.ts +128 -0
- package/src/cli/commands/credentials.help.ts +6 -2
- package/src/cli/commands/credentials.ts +2 -2
- package/src/cli/commands/mcp.help.ts +8 -8
- package/src/cli/commands/mcp.ts +1 -1
- package/src/cli/commands/oauth/status.ts +5 -0
- package/src/cli/commands/roadmap.help.ts +5 -1
- package/src/cli/commands/roadmap.ts +1 -1
- package/src/cli/lib/bundled-marketplace.json +103 -90
- package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
- package/src/config/__tests__/platform-identity.test.ts +255 -0
- package/src/config/__tests__/platform-rehydration.test.ts +99 -9
- package/src/config/acp-agent-write.ts +43 -0
- package/src/config/acp-defaults.test.ts +13 -3
- package/src/config/acp-defaults.ts +23 -6
- package/src/config/acp-schema.test.ts +81 -0
- package/src/config/acp-schema.ts +30 -2
- package/src/config/bundled-skills/acp/SKILL.md +22 -14
- package/src/config/bundled-skills/acp/TOOLS.json +5 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +29 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +99 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-sequence.ts +12 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -1
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -1
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -1
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +67 -139
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -1
- package/src/config/bundled-skills/schedule/SKILL.md +3 -4
- package/src/config/bundled-skills/screen-annotation/SKILL.md +8 -1
- package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +6 -2
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -2
- package/src/config/default-profile-catalog.ts +1 -1
- package/src/config/env.ts +2 -2
- package/src/config/feature-flag-registry.json +33 -13
- package/src/config/loader.ts +2 -0
- package/src/config/memory-v3-gate.test.ts +31 -0
- package/src/config/memory-v3-gate.ts +20 -16
- package/src/config/platform-identity.ts +201 -0
- package/src/config/platform-rehydration.ts +11 -27
- package/src/config/schema.ts +2 -2
- package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
- package/src/config/schemas/__tests__/voice.test.ts +148 -0
- package/src/config/schemas/calls.ts +1 -28
- package/src/config/schemas/live-voice.ts +1 -173
- package/src/config/schemas/mcp.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +10 -0
- package/src/config/schemas/services.ts +18 -0
- package/src/config/schemas/skills.ts +0 -14
- package/src/config/schemas/voice.ts +150 -0
- package/src/credential-execution/process-manager.test.ts +18 -19
- package/src/credential-health/credential-health-service.ts +11 -17
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -121
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +4 -1
- package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
- package/src/daemon/app-change-notify.ts +45 -0
- package/src/daemon/config-watcher.ts +13 -194
- package/src/daemon/conversation-error.ts +3 -2
- package/src/daemon/conversation-media-retry.ts +2 -1
- package/src/daemon/conversation-process.ts +35 -64
- package/src/daemon/conversation-runtime-assembly.ts +20 -7
- package/src/daemon/conversation-skill-tools.ts +13 -31
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +21 -10
- package/src/daemon/conversation-tool-setup.ts +45 -59
- package/src/daemon/conversation.ts +0 -3
- package/src/daemon/dictation-profile-store.ts +2 -1
- package/src/daemon/handlers/shared.ts +2 -1
- package/src/daemon/handlers/skills.ts +6 -3
- package/src/daemon/host-bash-proxy.ts +8 -12
- package/src/daemon/host-browser-proxy.ts +15 -1
- package/src/daemon/host-cu-proxy.ts +224 -19
- package/src/daemon/host-file-proxy.ts +8 -10
- package/src/daemon/host-proxy-preactivation.ts +2 -1
- package/src/daemon/host-transfer-proxy.ts +14 -18
- package/src/daemon/lifecycle.ts +0 -5
- package/src/daemon/mcp-reload-service.ts +5 -5
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/orphan-reaper.ts +1 -1
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/reaction-history-render.ts +2 -1
- package/src/daemon/shutdown-handlers.ts +1 -9
- package/src/daemon/skill-memory-refresh.ts +64 -0
- package/src/daemon/tool-side-effects.ts +7 -18
- package/src/desktop/__tests__/fake-desktop.ts +122 -0
- package/src/desktop/desktop-chrome-policy.test.ts +79 -0
- package/src/desktop/desktop-chrome-policy.ts +47 -0
- package/src/desktop/desktop-chrome-session.ts +37 -0
- package/src/desktop/desktop-dependencies.test.ts +102 -0
- package/src/desktop/desktop-dependencies.ts +308 -0
- package/src/desktop/desktop-feature.test.ts +18 -0
- package/src/desktop/desktop-feature.ts +19 -0
- package/src/desktop/desktop-panel-config.test.ts +135 -0
- package/src/desktop/desktop-panel-config.ts +149 -0
- package/src/desktop/desktop-session-manager.test.ts +730 -0
- package/src/desktop/desktop-session-manager.ts +850 -0
- package/src/desktop/desktop-stream-bridge.test.ts +395 -0
- package/src/desktop/desktop-stream-bridge.ts +214 -0
- package/src/desktop/desktop-wallpaper.test.ts +191 -0
- package/src/desktop/desktop-wallpaper.ts +113 -0
- package/src/desktop/desktop-window-drag.ts +177 -0
- package/src/desktop/desktop-window-manager-config.test.ts +230 -0
- package/src/desktop/desktop-window-manager-config.ts +238 -0
- package/src/desktop/desktop-window-theme.ts +170 -0
- package/src/heartbeat/heartbeat-service.ts +21 -3
- package/src/home/__tests__/feed-writer.test.ts +22 -0
- package/src/home/feed-writer.ts +11 -2
- package/src/hooks/types.ts +33 -0
- package/src/i18n/AGENTS.md +22 -0
- package/src/i18n/__tests__/i18n.test.ts +108 -0
- package/src/i18n/index.ts +16 -0
- package/src/i18n/locales.ts +93 -0
- package/src/i18n/messages.ts +61 -0
- package/src/i18n/title.ts +25 -0
- package/src/inbound/platform-callback-registration.ts +4 -5
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +121 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +8 -7
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +94 -15
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
- package/src/live-voice/__tests__/protocol.test.ts +39 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
- package/src/live-voice/__tests__/session-controls.test.ts +79 -0
- package/src/live-voice/live-voice-photo.ts +25 -6
- package/src/live-voice/live-voice-session.ts +297 -699
- package/src/live-voice/protocol.ts +60 -2
- package/src/live-voice/session-controls.ts +111 -0
- package/src/mcp/__tests__/effective-config.test.ts +2 -2
- package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
- package/src/mcp/effective-config.ts +3 -3
- package/src/mcp/mcp-header-store.ts +29 -45
- package/src/mcp/spec-schema.ts +111 -0
- package/src/mcp/startup.ts +8 -4
- package/src/mcp/workspace-mcp-config.ts +188 -0
- package/src/messaging/provider.ts +10 -3
- package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
- package/src/messaging/providers/callback-routing.ts +18 -0
- package/src/messaging/providers/channel-transport.ts +56 -0
- package/src/messaging/providers/discord/transport.ts +17 -0
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
- package/src/messaging/providers/slack/adapter.ts +7 -44
- package/src/messaging/providers/slack/transport.ts +16 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
- package/src/messaging/providers/telegram-bot/client.ts +0 -26
- package/src/messaging/providers/telegram-bot/transport.ts +20 -0
- package/src/messaging/providers/whatsapp/adapter.ts +1 -48
- package/src/messaging/providers/whatsapp/transport.ts +18 -0
- package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
- package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
- package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
- package/src/notifications/adapters/macos.ts +3 -0
- package/src/notifications/assistant-reply-producer.ts +8 -3
- package/src/notifications/conversation-pairing.ts +36 -16
- package/src/notifications/delivered-post-record.ts +11 -1
- package/src/notifications/guardian-feed-projection.ts +125 -5
- package/src/notifications/home-feed-side-effect.ts +55 -7
- package/src/notifications/schedule-result-producer.ts +66 -22
- package/src/oauth/AGENTS.md +2 -0
- package/src/oauth/__tests__/seed-providers-managed.test.ts +149 -0
- package/src/oauth/byo-connection.test.ts +105 -0
- package/src/oauth/byo-connection.ts +36 -6
- package/src/oauth/connection-resolver.test.ts +100 -0
- package/src/oauth/connection-resolver.ts +120 -3
- package/src/oauth/provider-serializer.ts +9 -0
- package/src/oauth/scope-utils.ts +24 -0
- package/src/oauth/seed-providers.ts +314 -27
- package/src/outbound-proxy/certs.ts +3 -5
- package/src/permissions/checker.test.ts +11 -6
- package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
- package/src/persistence/conversation-crud.ts +71 -63
- package/src/persistence/conversation-lineage.ts +12 -4
- package/src/persistence/conversation-queries.ts +2 -2
- package/src/persistence/conversation-title-placeholders.ts +23 -0
- package/src/persistence/conversation-title-service.ts +9 -26
- package/src/persistence/embeddings/qdrant-manager.ts +163 -18
- package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
- package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
- package/src/persistence/message-cursor.ts +78 -0
- package/src/persistence/message-reads.ts +30 -0
- package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
- package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
- package/src/persistence/schema/memory-core.ts +5 -0
- package/src/platform/client.test.ts +4 -2
- package/src/platform/client.ts +2 -10
- package/src/plugin-api/constants.ts +2 -0
- package/src/plugin-api/index.ts +1 -0
- package/src/plugin-api/types.ts +2 -0
- package/src/plugins/defaults/index.ts +2 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +20 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +5 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -2
- package/src/plugins/defaults/memory/context-search/format.ts +3 -2
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +6 -3
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +3 -2
- package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -7
- package/src/plugins/defaults/memory/hooks/init.ts +10 -0
- package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
- package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
- package/src/plugins/defaults/memory/host-utils.ts +10 -0
- package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
- package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
- package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
- package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +12 -3
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
- package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
- package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
- package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
- package/src/plugins/defaults/memory/startup.ts +28 -2
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
- package/src/plugins/defaults/memory/substrate/page-index.ts +6 -1
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
- package/src/plugins/defaults/memory/v2/reranker.ts +6 -1
- package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -0
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +125 -0
- package/src/plugins/defaults/memory/v3/__tests__/sections.test.ts +26 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +30 -0
- package/src/plugins/defaults/memory/v3/card.ts +3 -2
- package/src/plugins/defaults/memory/v3/pool-select.ts +5 -3
- package/src/plugins/defaults/memory/v3/sections.ts +9 -3
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +5 -2
- package/src/plugins/defaults/memory/worker.ts +6 -0
- package/src/plugins/mcp-servers.ts +15 -75
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
- package/src/providers/__tests__/retry-callsite.test.ts +41 -0
- package/src/providers/__tests__/retry-outbound-sanitize.test.ts +176 -0
- package/src/providers/anthropic/client.ts +0 -47
- package/src/providers/gemini/client.ts +9 -23
- package/src/providers/gemini-thought-signature.test.ts +63 -0
- package/src/providers/gemini-thought-signature.ts +44 -0
- package/src/providers/inference/__tests__/endpoint-probe.test.ts +42 -3
- package/src/providers/inference/auth.ts +2 -3
- package/src/providers/inference/connection-availability.ts +27 -8
- package/src/providers/inference/endpoint-probe.ts +10 -1
- package/src/providers/inference/resolve-auth.ts +22 -4
- package/src/providers/inference/service-account-token.ts +248 -0
- package/src/providers/model-catalog.ts +34 -0
- package/src/providers/model-intents.ts +10 -5
- package/src/providers/openai/__tests__/chat-completions-output-token-limit.test.ts +141 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
- package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
- package/src/providers/openai/chat-completions-provider.ts +212 -79
- package/src/providers/openai/codex-models.ts +0 -4
- package/src/providers/openai/google-thought-signature.ts +320 -0
- package/src/providers/opencode/client.test.ts +73 -4
- package/src/providers/opencode/client.ts +60 -3
- package/src/providers/openrouter/client.ts +20 -0
- package/src/providers/outbound-request-sanitize.ts +96 -0
- package/src/providers/retry.ts +30 -19
- package/src/providers/unparseable-tool-args.ts +5 -1
- package/src/runtime/AGENTS.md +3 -1
- package/src/runtime/__tests__/channel-send.test.ts +443 -0
- package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +89 -0
- package/src/runtime/__tests__/host-observe.test.ts +40 -1
- package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
- package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
- package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
- package/src/runtime/agent-wake.ts +2 -1
- package/src/runtime/assistant-event-hub.ts +21 -3
- package/src/runtime/auth/same-actor.ts +38 -3
- package/src/runtime/channel-send.ts +316 -0
- package/src/runtime/host-observe.ts +11 -1
- package/src/runtime/http-server.ts +160 -151
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +16 -5
- package/src/runtime/routes/__tests__/acp-routes.test.ts +159 -4
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +275 -0
- package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
- package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
- package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
- package/src/runtime/routes/acp-claude-auth-routes.ts +11 -3
- package/src/runtime/routes/acp-routes.test.ts +15 -0
- package/src/runtime/routes/acp-routes.ts +72 -9
- package/src/runtime/routes/app-management-routes.ts +90 -2
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/channel-send-routes.ts +85 -0
- package/src/runtime/routes/conversation-list-routes.ts +14 -3
- package/src/runtime/routes/conversation-query-routes.ts +40 -0
- package/src/runtime/routes/conversation-routes.ts +16 -3
- package/src/runtime/routes/credential-routes.ts +20 -14
- package/src/runtime/routes/desktop-setup-routes.test.ts +74 -0
- package/src/runtime/routes/desktop-setup-routes.ts +35 -0
- package/src/runtime/routes/diagnostics-routes.ts +61 -4
- package/src/runtime/routes/events-routes.ts +4 -0
- package/src/runtime/routes/host-cu-routes.ts +6 -0
- package/src/runtime/routes/index.ts +4 -2
- package/src/runtime/routes/log-export-routes.ts +2 -0
- package/src/runtime/routes/mcp-auth-routes.ts +39 -47
- package/src/runtime/routes/migration-routes.ts +6 -20
- package/src/runtime/routes/oauth-commands-routes.ts +50 -0
- package/src/runtime/routes/oauth-providers.ts +7 -0
- package/src/runtime/routes/platform-routes.ts +18 -15
- package/src/runtime/routes/workspace-routes.test.ts +55 -26
- package/src/runtime/routes/workspace-routes.ts +46 -63
- package/src/runtime/routes/workspace-tree-walk.test.ts +244 -0
- package/src/runtime/routes/workspace-tree-walk.ts +240 -0
- package/src/runtime/routes/workspace-utils.ts +17 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +16 -3
- package/src/runtime/sync/resource-sync-events.ts +2 -1
- package/src/schedule/run-script.ts +2 -1
- package/src/schedule/schedule-store.ts +9 -2
- package/src/schedule/worker.ts +1 -1
- package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
- package/src/security/ces-http-record-backend.ts +120 -0
- package/src/security/ces-rpc-record-backend.ts +7 -0
- package/src/security/untrusted-content.ts +3 -1
- package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
- package/src/skills/workspace-skill-md-signature.ts +50 -0
- package/src/subagent/consult-context.ts +12 -25
- package/src/tools/__tests__/side-effect-abort-guard.test.ts +1 -0
- package/src/tools/acp/list-agents.test.ts +3 -1
- package/src/tools/acp/spawn.test.ts +146 -11
- package/src/tools/acp/spawn.ts +21 -3
- package/src/tools/acp/status.test.ts +94 -0
- package/src/tools/acp/status.ts +40 -3
- package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +3 -2
- package/src/tools/browser/network-recorder.ts +2 -1
- package/src/tools/capability-offer.test.ts +22 -2
- package/src/tools/capability-offer.ts +16 -1
- package/src/tools/computer-use/definitions.ts +121 -2
- package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
- package/src/tools/credentials/metadata-store.ts +100 -0
- package/src/tools/filesystem/search.ts +2 -1
- package/src/tools/host-filesystem/edit.test.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +2 -2
- package/src/tools/host-filesystem/read.test.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/transfer.test.ts +2 -1
- package/src/tools/host-filesystem/transfer.ts +2 -2
- package/src/tools/host-filesystem/write.test.ts +2 -1
- package/src/tools/host-filesystem/write.ts +2 -2
- package/src/tools/host-terminal/host-shell.test.ts +16 -0
- package/src/tools/host-terminal/host-shell.ts +4 -20
- package/src/tools/network/web-search.ts +6 -1
- package/src/tools/policy-context.ts +6 -7
- package/src/tools/skills/scaffold-managed.ts +61 -3
- package/src/tools/subagent/spawn.ts +5 -8
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +57 -0
- package/src/tools/terminal/sanitized-bash.ts +105 -0
- package/src/tools/ui-surface/channel-variants.ts +10 -59
- package/src/tools/watch/watch-retro-report.ts +0 -8
- package/src/types/host-capabilities.ts +5 -3
- package/src/util/__tests__/language-subtag.test.ts +23 -1
- package/src/util/ca-bundle.ts +13 -0
- package/src/util/language-subtag.ts +16 -0
- package/src/util/platform.ts +8 -0
- package/src/util/unicode.ts +15 -1
- package/src/watch/watch-retro.ts +6 -8
- package/src/watch/watch-timeline.ts +2 -2
- package/src/workflows/run-manager.ts +2 -1
- package/src/workspace/git-porcelain.ts +66 -0
- package/src/workspace/git-service.ts +6 -55
- package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
- package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
- package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
- package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/app-source-watcher.test.ts +0 -218
- package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
- package/src/__tests__/speaker-identification.test.ts +0 -56
- package/src/calls/speaker-identification.ts +0 -233
- package/src/daemon/app-source-watcher.ts +0 -218
- package/src/messaging/providers/whatsapp/client.ts +0 -29
- package/src/runtime/routes/debug-bash-routes.ts +0 -173
- package/src/util/fs-watcher-error.ts +0 -36
- /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
|
@@ -28,6 +28,9 @@ describe("model intents", () => {
|
|
|
28
28
|
expect(resolveModelIntent("openai", "latency-optimized")).toBe(
|
|
29
29
|
"gpt-5.6-luna",
|
|
30
30
|
);
|
|
31
|
+
expect(resolveModelIntent("gemini", "cost-optimized")).toBe(
|
|
32
|
+
"gemini-3.1-flash-lite",
|
|
33
|
+
);
|
|
31
34
|
expect(resolveModelIntent("gemini", "latency-optimized")).toBe(
|
|
32
35
|
"gemini-3.1-flash-lite",
|
|
33
36
|
);
|
|
@@ -3,6 +3,11 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
3
3
|
// ── Mocks: declared before imports that depend on them ──────────────
|
|
4
4
|
|
|
5
5
|
let updateMessageContentShouldThrow = false;
|
|
6
|
+
let assistantName: string | null = null;
|
|
7
|
+
|
|
8
|
+
mock.module("../daemon/identity-helpers.js", () => ({
|
|
9
|
+
getAssistantName: () => assistantName,
|
|
10
|
+
}));
|
|
6
11
|
|
|
7
12
|
const updateMessageContentMock = mock(
|
|
8
13
|
(_messageId: string, _content: string) => {
|
|
@@ -55,12 +60,21 @@ function makeDestination(
|
|
|
55
60
|
function captureBroadcast(): {
|
|
56
61
|
adapter: VellumAdapter;
|
|
57
62
|
sent: AssistantEvent[];
|
|
63
|
+
conversationIds: Array<string | undefined>;
|
|
58
64
|
} {
|
|
59
65
|
const sent: AssistantEvent[] = [];
|
|
60
|
-
const
|
|
61
|
-
|
|
66
|
+
const conversationIds: Array<string | undefined> = [];
|
|
67
|
+
const adapter = new VellumAdapter((msg, conversationId) => {
|
|
68
|
+
sent.push(msg);
|
|
69
|
+
conversationIds.push(conversationId);
|
|
70
|
+
});
|
|
71
|
+
return { adapter, sent, conversationIds };
|
|
62
72
|
}
|
|
63
73
|
|
|
74
|
+
beforeEach(() => {
|
|
75
|
+
assistantName = null;
|
|
76
|
+
});
|
|
77
|
+
|
|
64
78
|
describe("VellumAdapter silent flag", () => {
|
|
65
79
|
test("non-urgent (low) urgency broadcasts silent: true", async () => {
|
|
66
80
|
const { adapter, sent } = captureBroadcast();
|
|
@@ -181,6 +195,75 @@ describe("VellumAdapter remotePushDispatched pass-through", () => {
|
|
|
181
195
|
});
|
|
182
196
|
});
|
|
183
197
|
|
|
198
|
+
describe("VellumAdapter assistant name", () => {
|
|
199
|
+
test("broadcasts the current verified assistant name after trimming it", async () => {
|
|
200
|
+
assistantName = " Example Assistant ";
|
|
201
|
+
const { adapter, sent } = captureBroadcast();
|
|
202
|
+
|
|
203
|
+
await adapter.send(makePayload(), makeDestination());
|
|
204
|
+
|
|
205
|
+
const intent = sent[0] as Extract<
|
|
206
|
+
AssistantEvent,
|
|
207
|
+
{ type: "notification_intent" }
|
|
208
|
+
>;
|
|
209
|
+
expect(intent.assistantName).toBe("Example Assistant");
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("omits the assistant name when it is unavailable", async () => {
|
|
213
|
+
const { adapter, sent } = captureBroadcast();
|
|
214
|
+
|
|
215
|
+
await adapter.send(makePayload(), makeDestination());
|
|
216
|
+
|
|
217
|
+
const intent = sent[0] as Extract<
|
|
218
|
+
AssistantEvent,
|
|
219
|
+
{ type: "notification_intent" }
|
|
220
|
+
>;
|
|
221
|
+
expect(intent.assistantName).toBeUndefined();
|
|
222
|
+
expect("assistantName" in intent).toBe(false);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("omits a blank assistant name", async () => {
|
|
226
|
+
assistantName = " \t\n ";
|
|
227
|
+
const { adapter, sent } = captureBroadcast();
|
|
228
|
+
|
|
229
|
+
await adapter.send(makePayload(), makeDestination());
|
|
230
|
+
|
|
231
|
+
const intent = sent[0] as Extract<
|
|
232
|
+
AssistantEvent,
|
|
233
|
+
{ type: "notification_intent" }
|
|
234
|
+
>;
|
|
235
|
+
expect(intent.assistantName).toBeUndefined();
|
|
236
|
+
expect("assistantName" in intent).toBe(false);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test("reflects a renamed assistant on the next intent", async () => {
|
|
240
|
+
assistantName = "Assistant A";
|
|
241
|
+
const { adapter, sent } = captureBroadcast();
|
|
242
|
+
await adapter.send(makePayload(), makeDestination());
|
|
243
|
+
|
|
244
|
+
assistantName = "Assistant B";
|
|
245
|
+
await adapter.send(makePayload(), makeDestination());
|
|
246
|
+
|
|
247
|
+
const intents = sent as Array<
|
|
248
|
+
Extract<AssistantEvent, { type: "notification_intent" }>
|
|
249
|
+
>;
|
|
250
|
+
expect(intents.map((intent) => intent.assistantName)).toEqual([
|
|
251
|
+
"Assistant A",
|
|
252
|
+
"Assistant B",
|
|
253
|
+
]);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test("keeps notification intents outside conversation replay scope", async () => {
|
|
257
|
+
assistantName = "Example Assistant";
|
|
258
|
+
const { adapter, sent, conversationIds } = captureBroadcast();
|
|
259
|
+
|
|
260
|
+
await adapter.send(makePayload(), makeDestination());
|
|
261
|
+
|
|
262
|
+
expect(conversationIds).toEqual([undefined]);
|
|
263
|
+
expect("conversationId" in sent[0]!).toBe(false);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
184
267
|
describe("VellumAdapter update", () => {
|
|
185
268
|
beforeEach(() => {
|
|
186
269
|
updateMessageContentMock.mockClear();
|
|
@@ -25,6 +25,9 @@ interface MockProviderRow {
|
|
|
25
25
|
managedServiceConfigKey: string | null;
|
|
26
26
|
baseUrl: string | null;
|
|
27
27
|
injectionTemplates: string | null;
|
|
28
|
+
defaultScopes?: string;
|
|
29
|
+
authorizeParams?: string | null;
|
|
30
|
+
scopeSeparator?: string;
|
|
28
31
|
pingUrl: string | null;
|
|
29
32
|
pingMethod: string | null;
|
|
30
33
|
pingHeaders: string | null;
|
|
@@ -109,10 +112,15 @@ mock.module("../oauth/oauth-store.js", () => ({
|
|
|
109
112
|
listActiveConnectionsByProvider: (provider: string) =>
|
|
110
113
|
mockActiveConnectionsByProvider[provider] ?? [],
|
|
111
114
|
listConnections: (provider: string) => mockAllConnections[provider] ?? [],
|
|
115
|
+
// Imported by seed-providers.js at module load; the seed data is read here,
|
|
116
|
+
// never written.
|
|
117
|
+
migrateProviderBaseUrl: () => {},
|
|
118
|
+
seedProviders: () => {},
|
|
112
119
|
}));
|
|
113
120
|
|
|
114
121
|
mock.module("../oauth/connection-resolver.js", () => {
|
|
115
122
|
const makeConnection = () => ({
|
|
123
|
+
id: "conn-1",
|
|
116
124
|
accountInfo: "user@example.com",
|
|
117
125
|
request: async (req: unknown) => {
|
|
118
126
|
mockResolveRequests.push(req);
|
|
@@ -155,6 +163,7 @@ mock.module("../security/token-manager.js", () => ({
|
|
|
155
163
|
}));
|
|
156
164
|
|
|
157
165
|
import { loadRawConfig } from "../config/loader.js";
|
|
166
|
+
import { PROVIDER_SEED_DATA } from "../oauth/seed-providers.js";
|
|
158
167
|
import {
|
|
159
168
|
BadRequestError,
|
|
160
169
|
InternalError,
|
|
@@ -899,6 +908,110 @@ describe("POST oauth/request", () => {
|
|
|
899
908
|
]);
|
|
900
909
|
});
|
|
901
910
|
|
|
911
|
+
/** The provider row exactly as seeding writes it, so the seed data is what the guard reads. */
|
|
912
|
+
function seededProvider(provider: keyof typeof PROVIDER_SEED_DATA) {
|
|
913
|
+
const seed = PROVIDER_SEED_DATA[provider];
|
|
914
|
+
return {
|
|
915
|
+
...baseProvider,
|
|
916
|
+
provider,
|
|
917
|
+
managedServiceConfigKey: null,
|
|
918
|
+
baseUrl: seed.baseUrl ?? null,
|
|
919
|
+
injectionTemplates: JSON.stringify(seed.injectionTemplates),
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
test("admits a Slack file URL on both seeded Slack providers", async () => {
|
|
924
|
+
// Each Slack credential reads messages, and a file shared in a message is
|
|
925
|
+
// fetched from its `url_private_download` on files.slack.com with the
|
|
926
|
+
// same token.
|
|
927
|
+
for (const provider of ["slack", "slack_channel"] as const) {
|
|
928
|
+
mockProviders[provider] = seededProvider(provider);
|
|
929
|
+
mockResolveRequests = [];
|
|
930
|
+
|
|
931
|
+
await getRoute("POST", "oauth/request").handler(
|
|
932
|
+
makeArgs({
|
|
933
|
+
body: {
|
|
934
|
+
provider,
|
|
935
|
+
url: "https://files.slack.com/files-pri/T0123-F0456/download/shot.png",
|
|
936
|
+
},
|
|
937
|
+
}),
|
|
938
|
+
);
|
|
939
|
+
|
|
940
|
+
expect(mockResolveRequests).toEqual([
|
|
941
|
+
{
|
|
942
|
+
method: "GET",
|
|
943
|
+
path: "/files-pri/T0123-F0456/download/shot.png",
|
|
944
|
+
baseUrl: "https://files.slack.com",
|
|
945
|
+
},
|
|
946
|
+
]);
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
test("the seeded Slack host policy admits nothing beyond the documented hosts", async () => {
|
|
951
|
+
mockProviders.slack_channel = seededProvider("slack_channel");
|
|
952
|
+
|
|
953
|
+
// A lookalike, an unrelated host, and the CDN host Slack redirects file
|
|
954
|
+
// downloads to: the guard sees only the URL the caller names, and that
|
|
955
|
+
// URL is the documented file host or nothing.
|
|
956
|
+
for (const url of [
|
|
957
|
+
"https://files.slack.com.attacker.example/files-pri/T0123-F0456/x.png",
|
|
958
|
+
"https://attacker.example/files-pri/T0123-F0456/x.png",
|
|
959
|
+
"https://files-origin.slack.com/files-pri/T0123-F0456/x.png",
|
|
960
|
+
]) {
|
|
961
|
+
await expect(
|
|
962
|
+
getRoute("POST", "oauth/request").handler(
|
|
963
|
+
makeArgs({ body: { provider: "slack_channel", url } }),
|
|
964
|
+
),
|
|
965
|
+
).rejects.toBeInstanceOf(BadRequestError);
|
|
966
|
+
}
|
|
967
|
+
expect(mockResolveRequests).toHaveLength(0);
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
test("names the required scopes a stored grant lacks on the request itself", async () => {
|
|
971
|
+
// A connection made before a scope was required keeps working for every
|
|
972
|
+
// call that does not need it, so the caller must be told on the request,
|
|
973
|
+
// not only by the next health check.
|
|
974
|
+
const seed = PROVIDER_SEED_DATA.slack;
|
|
975
|
+
mockProviders.slack = {
|
|
976
|
+
...seededProvider("slack"),
|
|
977
|
+
defaultScopes: JSON.stringify(seed.defaultScopes),
|
|
978
|
+
authorizeParams: JSON.stringify(seed.authorizeParams),
|
|
979
|
+
scopeSeparator: " ",
|
|
980
|
+
};
|
|
981
|
+
const grantedBeforeFilesRead = seed
|
|
982
|
+
.authorizeParams!.user_scope.split(",")
|
|
983
|
+
.filter((scope) => scope !== "files:read");
|
|
984
|
+
mockAllConnections.slack = [
|
|
985
|
+
{
|
|
986
|
+
id: "conn-1",
|
|
987
|
+
provider: "slack",
|
|
988
|
+
grantedScopes: JSON.stringify(grantedBeforeFilesRead),
|
|
989
|
+
},
|
|
990
|
+
];
|
|
991
|
+
|
|
992
|
+
const stale = (await getRoute("POST", "oauth/request").handler(
|
|
993
|
+
makeArgs({ body: { provider: "slack", url: "/conversations.history" } }),
|
|
994
|
+
)) as { ok: boolean; hint?: string };
|
|
995
|
+
|
|
996
|
+
expect(stale.ok).toBe(true);
|
|
997
|
+
expect(stale.hint).toContain("files:read");
|
|
998
|
+
expect(stale.hint).toContain("oauth connect slack");
|
|
999
|
+
|
|
1000
|
+
mockAllConnections.slack = [
|
|
1001
|
+
{
|
|
1002
|
+
id: "conn-1",
|
|
1003
|
+
provider: "slack",
|
|
1004
|
+
grantedScopes: JSON.stringify(
|
|
1005
|
+
seed.authorizeParams!.user_scope.split(","),
|
|
1006
|
+
),
|
|
1007
|
+
},
|
|
1008
|
+
];
|
|
1009
|
+
const current = (await getRoute("POST", "oauth/request").handler(
|
|
1010
|
+
makeArgs({ body: { provider: "slack", url: "/conversations.history" } }),
|
|
1011
|
+
)) as { hint?: string };
|
|
1012
|
+
expect(current.hint).toBeUndefined();
|
|
1013
|
+
});
|
|
1014
|
+
|
|
902
1015
|
test("allows cross-host absolute URLs declared by provider injection templates", async () => {
|
|
903
1016
|
mockProviders.google = {
|
|
904
1017
|
...baseProvider,
|
|
@@ -1052,6 +1165,33 @@ describe("POST oauth/managed-connect/start", () => {
|
|
|
1052
1165
|
expect(result.connect_url).toBe("https://app.vellum.ai/connect/abc");
|
|
1053
1166
|
});
|
|
1054
1167
|
|
|
1168
|
+
test("forwards tenant_host to the platform only when one is supplied", async () => {
|
|
1169
|
+
// Shopify's endpoints live on the merchant's host, which the platform
|
|
1170
|
+
// substitutes into its templates; other providers must not see the key.
|
|
1171
|
+
const bodies: Array<Record<string, unknown>> = [];
|
|
1172
|
+
mockFetchImpl = async (_path, init) => {
|
|
1173
|
+
bodies.push(JSON.parse(String(init?.body)) as Record<string, unknown>);
|
|
1174
|
+
return {
|
|
1175
|
+
ok: true,
|
|
1176
|
+
status: 200,
|
|
1177
|
+
json: async () => ({
|
|
1178
|
+
connect_url: "https://app.vellum.ai/connect/abc",
|
|
1179
|
+
}),
|
|
1180
|
+
text: async () => "",
|
|
1181
|
+
};
|
|
1182
|
+
};
|
|
1183
|
+
await getRoute("POST", "oauth/managed-connect/start").handler(
|
|
1184
|
+
makeArgs({
|
|
1185
|
+
body: { provider: "shopify", tenant_host: " my-store.myshopify.com " },
|
|
1186
|
+
}),
|
|
1187
|
+
);
|
|
1188
|
+
await getRoute("POST", "oauth/managed-connect/start").handler(
|
|
1189
|
+
makeArgs({ body: { provider: "google", tenant_host: " " } }),
|
|
1190
|
+
);
|
|
1191
|
+
expect(bodies[0]?.tenant_host).toBe("my-store.myshopify.com");
|
|
1192
|
+
expect(bodies[1]).not.toHaveProperty("tenant_host");
|
|
1193
|
+
});
|
|
1194
|
+
|
|
1055
1195
|
test("raises InternalError when platform returns 401", async () => {
|
|
1056
1196
|
mockFetchImpl = async () => ({
|
|
1057
1197
|
ok: false,
|
|
@@ -1115,6 +1255,7 @@ describe("GET oauth/managed-connect/poll", () => {
|
|
|
1115
1255
|
id: string;
|
|
1116
1256
|
account_label: string | null;
|
|
1117
1257
|
scopes_granted: string[];
|
|
1258
|
+
provider_params: Record<string, string>;
|
|
1118
1259
|
}>;
|
|
1119
1260
|
};
|
|
1120
1261
|
expect(result.ok).toBe(true);
|
|
@@ -1123,6 +1264,7 @@ describe("GET oauth/managed-connect/poll", () => {
|
|
|
1123
1264
|
id: "conn-1",
|
|
1124
1265
|
account_label: "alice@example.com",
|
|
1125
1266
|
scopes_granted: ["email"],
|
|
1267
|
+
provider_params: {},
|
|
1126
1268
|
},
|
|
1127
1269
|
]);
|
|
1128
1270
|
});
|
|
@@ -1135,4 +1277,30 @@ describe("GET oauth/managed-connect/poll", () => {
|
|
|
1135
1277
|
),
|
|
1136
1278
|
).rejects.toBeInstanceOf(BadRequestError);
|
|
1137
1279
|
});
|
|
1280
|
+
|
|
1281
|
+
test("passes through the provider params a connection is scoped by", async () => {
|
|
1282
|
+
// QuickBooks pins the company (realm) the user picked to the connection;
|
|
1283
|
+
// a caller addressing /companyinfo/<realmId> needs it back.
|
|
1284
|
+
mockFetchImpl = async () => ({
|
|
1285
|
+
ok: true,
|
|
1286
|
+
status: 200,
|
|
1287
|
+
json: async () => [
|
|
1288
|
+
{
|
|
1289
|
+
id: "conn-qb",
|
|
1290
|
+
account_label: "Acme Widgets",
|
|
1291
|
+
scopes_granted: ["com.intuit.quickbooks.accounting"],
|
|
1292
|
+
provider_params: { realm_id: "9130357849012345" },
|
|
1293
|
+
},
|
|
1294
|
+
],
|
|
1295
|
+
text: async () => "",
|
|
1296
|
+
});
|
|
1297
|
+
const result = (await getRoute("GET", "oauth/managed-connect/poll").handler(
|
|
1298
|
+
makeArgs({ queryParams: { provider: "quickbooks" } }),
|
|
1299
|
+
)) as {
|
|
1300
|
+
connections: Array<{ provider_params: Record<string, string> }>;
|
|
1301
|
+
};
|
|
1302
|
+
expect(result.connections[0]?.provider_params).toEqual({
|
|
1303
|
+
realm_id: "9130357849012345",
|
|
1304
|
+
});
|
|
1305
|
+
});
|
|
1138
1306
|
});
|
|
@@ -7,6 +7,7 @@ mock.module("../security/secure-keys.js", () => ({
|
|
|
7
7
|
}));
|
|
8
8
|
|
|
9
9
|
import { getProvider } from "../oauth/oauth-store.js";
|
|
10
|
+
import { expectedScopesForStoredToken } from "../oauth/scope-utils.js";
|
|
10
11
|
import { seedOAuthProviders } from "../oauth/seed-providers.js";
|
|
11
12
|
import { initializeDb } from "../persistence/db-init.js";
|
|
12
13
|
|
|
@@ -22,6 +23,23 @@ describe("oauth provider profiles (DB-seeded)", () => {
|
|
|
22
23
|
expect(scopes).toContain("https://www.googleapis.com/auth/drive");
|
|
23
24
|
});
|
|
24
25
|
|
|
26
|
+
test("slack provider row requests files:read for the token it stores", () => {
|
|
27
|
+
// The flow persists the authed_user token, and credential health measures
|
|
28
|
+
// its grant through the same function used here, so this is the scope set
|
|
29
|
+
// an integration connection must carry to fetch a file from files.slack.com.
|
|
30
|
+
const provider = getProvider("slack");
|
|
31
|
+
|
|
32
|
+
expect(provider).toBeDefined();
|
|
33
|
+
const expected = expectedScopesForStoredToken(
|
|
34
|
+
JSON.parse(provider!.defaultScopes) as string[],
|
|
35
|
+
provider!.authorizeParams
|
|
36
|
+
? (JSON.parse(provider!.authorizeParams) as Record<string, string>)
|
|
37
|
+
: undefined,
|
|
38
|
+
provider!.scopeSeparator ?? undefined,
|
|
39
|
+
);
|
|
40
|
+
expect(expected).toContain("files:read");
|
|
41
|
+
});
|
|
42
|
+
|
|
25
43
|
test("google provider row contains bearer injection templates for 8 Google API hosts", () => {
|
|
26
44
|
const provider = getProvider("google");
|
|
27
45
|
|
|
@@ -291,10 +291,32 @@ describe("serializeProviderSummary", () => {
|
|
|
291
291
|
supports_managed_mode: true,
|
|
292
292
|
managed_service_is_paid: false,
|
|
293
293
|
feature_flag: null,
|
|
294
|
+
tenant_host: null,
|
|
294
295
|
acts_as: "user",
|
|
295
296
|
});
|
|
296
297
|
});
|
|
297
298
|
|
|
299
|
+
test("exposes the tenant host a per-tenant provider needs at connect", () => {
|
|
300
|
+
// Shopify's OAuth endpoints live on the merchant's own host, so a client
|
|
301
|
+
// has to collect it before the managed flow can start. The summary is the
|
|
302
|
+
// only provider metadata the web client reads, so it carries the ask.
|
|
303
|
+
const shopify = serializeProviderSummary(makeRow({ provider: "shopify" }))!;
|
|
304
|
+
expect(shopify.tenant_host).toEqual({
|
|
305
|
+
pattern: "^[a-z0-9][a-z0-9-]*\\.myshopify\\.com$",
|
|
306
|
+
label: "Shop domain",
|
|
307
|
+
placeholder: "your-store.myshopify.com",
|
|
308
|
+
});
|
|
309
|
+
expect(
|
|
310
|
+
new RegExp(shopify.tenant_host!.pattern).test("my-store.myshopify.com"),
|
|
311
|
+
).toBe(true);
|
|
312
|
+
expect(new RegExp(shopify.tenant_host!.pattern).test("evil.com")).toBe(
|
|
313
|
+
false,
|
|
314
|
+
);
|
|
315
|
+
expect(
|
|
316
|
+
serializeProviderSummary(makeRow({ provider: "github" }))!.tenant_host,
|
|
317
|
+
).toBeNull();
|
|
318
|
+
});
|
|
319
|
+
|
|
298
320
|
test("names which sense of connected a provider represents", () => {
|
|
299
321
|
// The provider key does not say, and the naming actively misleads:
|
|
300
322
|
// `slack` is the user integration while its bot is `slack_channel`, but
|
|
@@ -982,6 +982,7 @@ describe("OpenAIProvider", () => {
|
|
|
982
982
|
);
|
|
983
983
|
|
|
984
984
|
expect(lastCreateParams!.max_completion_tokens).toBe(64000);
|
|
985
|
+
expect(lastCreateParams).not.toHaveProperty("max_tokens");
|
|
985
986
|
});
|
|
986
987
|
|
|
987
988
|
// -----------------------------------------------------------------------
|
|
@@ -429,7 +429,7 @@ describe("Outlook messaging provider", () => {
|
|
|
429
429
|
describe("sendMessage", () => {
|
|
430
430
|
test("sends a new message with correct recipient, subject, and body", async () => {
|
|
431
431
|
const conn = createMockConnection();
|
|
432
|
-
const result = await outlookMessagingProvider.sendMessage(
|
|
432
|
+
const result = await outlookMessagingProvider.sendMessage!(
|
|
433
433
|
conn,
|
|
434
434
|
"recipient@example.com",
|
|
435
435
|
"Hello!",
|
|
@@ -452,7 +452,7 @@ describe("Outlook messaging provider", () => {
|
|
|
452
452
|
|
|
453
453
|
test("uses empty string for subject when not provided", async () => {
|
|
454
454
|
const conn = createMockConnection();
|
|
455
|
-
await outlookMessagingProvider.sendMessage(
|
|
455
|
+
await outlookMessagingProvider.sendMessage!(
|
|
456
456
|
conn,
|
|
457
457
|
"recipient@example.com",
|
|
458
458
|
"Hello!",
|
|
@@ -471,7 +471,7 @@ describe("Outlook messaging provider", () => {
|
|
|
471
471
|
|
|
472
472
|
test("calls replyToMessage when inReplyTo is provided", async () => {
|
|
473
473
|
const conn = createMockConnection();
|
|
474
|
-
const result = await outlookMessagingProvider.sendMessage(
|
|
474
|
+
const result = await outlookMessagingProvider.sendMessage!(
|
|
475
475
|
conn,
|
|
476
476
|
"conv-id",
|
|
477
477
|
"Reply text",
|
|
@@ -493,7 +493,7 @@ describe("Outlook messaging provider", () => {
|
|
|
493
493
|
|
|
494
494
|
test("attaches files to a new message as Graph file attachments", async () => {
|
|
495
495
|
const conn = createMockConnection();
|
|
496
|
-
await outlookMessagingProvider.sendMessage(
|
|
496
|
+
await outlookMessagingProvider.sendMessage!(
|
|
497
497
|
conn,
|
|
498
498
|
"recipient@example.com",
|
|
499
499
|
"See attached",
|
|
@@ -530,7 +530,7 @@ describe("Outlook messaging provider", () => {
|
|
|
530
530
|
|
|
531
531
|
test("forwards attachments to replyToMessage when replying", async () => {
|
|
532
532
|
const conn = createMockConnection();
|
|
533
|
-
await outlookMessagingProvider.sendMessage(
|
|
533
|
+
await outlookMessagingProvider.sendMessage!(
|
|
534
534
|
conn,
|
|
535
535
|
"conv-id",
|
|
536
536
|
"Reply body",
|
|
@@ -563,7 +563,7 @@ describe("Outlook messaging provider", () => {
|
|
|
563
563
|
|
|
564
564
|
test("throws when connection is undefined", async () => {
|
|
565
565
|
await expect(
|
|
566
|
-
outlookMessagingProvider.sendMessage(
|
|
566
|
+
outlookMessagingProvider.sendMessage!(
|
|
567
567
|
undefined,
|
|
568
568
|
"recipient@example.com",
|
|
569
569
|
"Hello!",
|
|
@@ -110,8 +110,7 @@ describe("platform callback registration", () => {
|
|
|
110
110
|
test("resolves managed callback context from stored credentials", async () => {
|
|
111
111
|
mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
|
|
112
112
|
"https://platform.example.com";
|
|
113
|
-
|
|
114
|
-
"11111111-2222-4333-8444-555555555555";
|
|
113
|
+
mockPlatformAssistantId = "11111111-2222-4333-8444-555555555555";
|
|
115
114
|
mockSecureKeys[credentialKey("vellum", "assistant_api_key")] =
|
|
116
115
|
"ast-managed-key";
|
|
117
116
|
|
|
@@ -129,8 +128,7 @@ describe("platform callback registration", () => {
|
|
|
129
128
|
mockIsPlatform = false;
|
|
130
129
|
mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
|
|
131
130
|
"https://platform.example.com";
|
|
132
|
-
|
|
133
|
-
"22222222-3333-4444-8555-666666666666";
|
|
131
|
+
mockPlatformAssistantId = "22222222-3333-4444-8555-666666666666";
|
|
134
132
|
mockSecureKeys[credentialKey("vellum", "assistant_api_key")] =
|
|
135
133
|
"ast-self-hosted-key";
|
|
136
134
|
|
|
@@ -161,8 +159,7 @@ describe("platform callback registration", () => {
|
|
|
161
159
|
test("registerCallbackRoute falls back to assistant API key auth", async () => {
|
|
162
160
|
mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
|
|
163
161
|
"https://platform.example.com";
|
|
164
|
-
|
|
165
|
-
"11111111-2222-4333-8444-555555555555";
|
|
162
|
+
mockPlatformAssistantId = "11111111-2222-4333-8444-555555555555";
|
|
166
163
|
mockSecureKeys[credentialKey("vellum", "assistant_api_key")] =
|
|
167
164
|
"ast-managed-key";
|
|
168
165
|
|
|
@@ -209,8 +206,7 @@ describe("platform callback registration", () => {
|
|
|
209
206
|
};
|
|
210
207
|
mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
|
|
211
208
|
"https://platform.example.com";
|
|
212
|
-
|
|
213
|
-
"22222222-3333-4444-8555-666666666666";
|
|
209
|
+
mockPlatformAssistantId = "22222222-3333-4444-8555-666666666666";
|
|
214
210
|
mockSecureKeys[credentialKey("vellum", "assistant_api_key")] =
|
|
215
211
|
"ast-self-hosted-key";
|
|
216
212
|
|
|
@@ -251,8 +247,7 @@ describe("platform callback registration", () => {
|
|
|
251
247
|
setIngressPublicBaseUrl("https://detected.example.com/");
|
|
252
248
|
mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
|
|
253
249
|
"https://platform.example.com";
|
|
254
|
-
|
|
255
|
-
"22222222-3333-4444-8555-666666666666";
|
|
250
|
+
mockPlatformAssistantId = "22222222-3333-4444-8555-666666666666";
|
|
256
251
|
mockSecureKeys[credentialKey("vellum", "assistant_api_key")] =
|
|
257
252
|
"ast-self-hosted-key";
|
|
258
253
|
|
|
@@ -292,8 +287,7 @@ describe("platform callback registration", () => {
|
|
|
292
287
|
mockConfig = {};
|
|
293
288
|
mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
|
|
294
289
|
"https://platform.example.com";
|
|
295
|
-
|
|
296
|
-
"22222222-3333-4444-8555-666666666666";
|
|
290
|
+
mockPlatformAssistantId = "22222222-3333-4444-8555-666666666666";
|
|
297
291
|
mockSecureKeys[credentialKey("vellum", "assistant_api_key")] =
|
|
298
292
|
"ast-self-hosted-key";
|
|
299
293
|
|
|
@@ -334,8 +328,7 @@ describe("platform callback registration", () => {
|
|
|
334
328
|
mockConfig = { ingress: { publicBaseUrl: "https://velay.example.com" } };
|
|
335
329
|
mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
|
|
336
330
|
"https://platform.example.com";
|
|
337
|
-
|
|
338
|
-
"11111111-2222-4333-8444-555555555555";
|
|
331
|
+
mockPlatformAssistantId = "11111111-2222-4333-8444-555555555555";
|
|
339
332
|
mockSecureKeys[credentialKey("vellum", "assistant_api_key")] =
|
|
340
333
|
"ast-managed-key";
|
|
341
334
|
|
|
@@ -396,8 +389,7 @@ describe("resolveCallbackUrl resolution order", () => {
|
|
|
396
389
|
function seedPlatformCredentials(): void {
|
|
397
390
|
mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
|
|
398
391
|
"https://platform.example.com";
|
|
399
|
-
|
|
400
|
-
"11111111-2222-4333-8444-555555555555";
|
|
392
|
+
mockPlatformAssistantId = "11111111-2222-4333-8444-555555555555";
|
|
401
393
|
mockSecureKeys[credentialKey("vellum", "assistant_api_key")] =
|
|
402
394
|
"ast-managed-key";
|
|
403
395
|
}
|
|
@@ -19,7 +19,9 @@ mock.module("../providers/platform-proxy/context.js", () => ({
|
|
|
19
19
|
}),
|
|
20
20
|
}));
|
|
21
21
|
|
|
22
|
+
const actualEnv = await import("../config/env.js");
|
|
22
23
|
mock.module("../config/env.js", () => ({
|
|
24
|
+
...actualEnv,
|
|
23
25
|
getPlatformAssistantId: () => platformAssistantId,
|
|
24
26
|
}));
|
|
25
27
|
|
|
@@ -129,6 +129,9 @@ const BASELINE: Record<string, readonly string[]> = {
|
|
|
129
129
|
"../../../../daemon/embedding-reconcile.js",
|
|
130
130
|
"../../../../daemon/trust-context.js",
|
|
131
131
|
"../../../../daemon/turn-latency-sub-spans.js",
|
|
132
|
+
// mcp-setup capability cards list configured server names from the
|
|
133
|
+
// workspace mcp.json document. No plugin-api equivalent.
|
|
134
|
+
"../../../../mcp/workspace-mcp-config.js",
|
|
132
135
|
"../../../../notifications/background-failure-signal.js",
|
|
133
136
|
"../../../../persistence/checkpoints.js",
|
|
134
137
|
"../../../../persistence/conversation-types.js",
|
|
@@ -210,6 +213,16 @@ const BASELINE: Record<string, readonly string[]> = {
|
|
|
210
213
|
"../../../persistence/job-handlers/message-lexical.js",
|
|
211
214
|
"../../../persistence/job-utils.js",
|
|
212
215
|
"../../../persistence/jobs-store.js",
|
|
216
|
+
// The retrospective cursor is a `(createdAt, id)` bound that must keep
|
|
217
|
+
// working after its message row is deleted. The resolver lives beside
|
|
218
|
+
// the persistence after-reads it also drives, so the plugin's
|
|
219
|
+
// accounting imports it rather than re-deriving the bound. No
|
|
220
|
+
// plugin-api equivalent.
|
|
221
|
+
"../../../persistence/message-cursor.js",
|
|
222
|
+
// Named any-state `createdAt` lookup the cursor bookkeeping uses for
|
|
223
|
+
// forks and the timestamp backfill; the messages-read boundary guard
|
|
224
|
+
// requires the read to live in persistence. No plugin-api equivalent.
|
|
225
|
+
"../../../persistence/message-reads.js",
|
|
213
226
|
"../../../persistence/raw-query.js",
|
|
214
227
|
"../../../persistence/schema/index.js",
|
|
215
228
|
"../../../prompts/persona-resolver.js",
|
|
@@ -235,6 +248,7 @@ const BASELINE: Record<string, readonly string[]> = {
|
|
|
235
248
|
"../../../util/sqlite-retry.js",
|
|
236
249
|
"../../../util/strip-comment-lines.js",
|
|
237
250
|
"../../../util/truncate.js",
|
|
251
|
+
"../../../util/unicode.js",
|
|
238
252
|
"../../../util/worker-compute.js",
|
|
239
253
|
"../../../util/worker-memory.js",
|
|
240
254
|
"../../../util/worker-process.js",
|