@vellumai/assistant 0.12.1 → 0.12.2-staging.1
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/openapi.yaml +327 -52
- 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-skill-tools.test.ts +27 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
- 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 +212 -3
- package/src/__tests__/credential-security-invariants.test.ts +4 -2
- package/src/__tests__/cu-unified-flow.test.ts +8 -2
- 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 +539 -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 +113 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +18 -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__/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 +19 -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__/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__/agent-process.test.ts +258 -4
- package/src/acp/__tests__/auth-required.test.ts +96 -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__/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/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/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/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 +58 -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 +37 -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 +53 -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 +59 -46
- package/src/calls/voice-triage-escalate.ts +175 -56
- 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/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 +20 -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 +24 -12
- package/src/config/loader.ts +1 -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 +8 -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 +2 -1
- package/src/daemon/conversation-skill-tools.ts +13 -31
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +15 -9
- package/src/daemon/conversation-tool-setup.ts +37 -43
- 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 +186 -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-metrics.test.ts +0 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -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__/runtime-websocket-shell.test.ts +13 -69
- package/src/live-voice/live-voice-photo.ts +25 -6
- package/src/live-voice/live-voice-session.ts +213 -693
- package/src/live-voice/protocol.ts +0 -2
- 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 +54 -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 +73 -0
- package/src/oauth/connection-resolver.ts +95 -2
- package/src/oauth/scope-utils.ts +24 -0
- package/src/oauth/seed-providers.ts +204 -25
- 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-routes.test.ts +159 -4
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +205 -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-routes.test.ts +15 -0
- package/src/runtime/routes/acp-routes.ts +72 -9
- package/src/runtime/routes/app-management-routes.ts +73 -0
- 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 +19 -10
- 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 +36 -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/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-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
|
@@ -9,6 +9,30 @@ import { migrateProviderBaseUrl, seedProviders } from "./oauth-store.js";
|
|
|
9
9
|
*/
|
|
10
10
|
const STALE_GOOGLE_BASE_URL = "https://gmail.googleapis.com/gmail/v1/users/me";
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* The hosts a Slack credential may be sent to, shared by the person-identity
|
|
14
|
+
* `slack` provider and the `slack_channel` bot: both read messages, and a file
|
|
15
|
+
* shared in a message is fetched from the file object's `url_private`,
|
|
16
|
+
* `url_private_download`, or `thumb_*` URL on `files.slack.com` with the same
|
|
17
|
+
* Bearer token as the Web API. Slack documents that one file host by name.
|
|
18
|
+
*/
|
|
19
|
+
const SLACK_PROVIDER_INJECTION_TEMPLATES: NonNullable<
|
|
20
|
+
(typeof PROVIDER_SEED_DATA)[string]["injectionTemplates"]
|
|
21
|
+
> = [
|
|
22
|
+
{
|
|
23
|
+
hostPattern: "slack.com",
|
|
24
|
+
injectionType: "header",
|
|
25
|
+
headerName: "Authorization",
|
|
26
|
+
valuePrefix: "Bearer ",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
hostPattern: "files.slack.com",
|
|
30
|
+
injectionType: "header",
|
|
31
|
+
headerName: "Authorization",
|
|
32
|
+
valuePrefix: "Bearer ",
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
12
36
|
/**
|
|
13
37
|
* Protocol-level seed data for each well-known OAuth provider.
|
|
14
38
|
*
|
|
@@ -183,14 +207,13 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
183
207
|
clientIdPlaceholder: null,
|
|
184
208
|
logoUrl:
|
|
185
209
|
"https://cdn.jsdelivr.net/gh/glincker/thesvg@main/public/icons/slack/default.svg",
|
|
186
|
-
// Sent as the bot `scope` parameter
|
|
187
|
-
// `authed_user` token and stores `authed_user.scope` as
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
// `
|
|
191
|
-
//
|
|
192
|
-
//
|
|
193
|
-
// channel-readiness-service.ts.
|
|
210
|
+
// Sent as the bot `scope` parameter on the same authorize request. This
|
|
211
|
+
// flow persists the `authed_user` token and stores `authed_user.scope` as
|
|
212
|
+
// `grantedScopes`; credential health measures that grant against
|
|
213
|
+
// `user_scope` below, never against this list, so a scope the stored
|
|
214
|
+
// token needs belongs in `user_scope`. The wider bot set belongs to Socket
|
|
215
|
+
// Mode installs, which verify the live `x-oauth-scopes` header against
|
|
216
|
+
// SLACK_REQUIRED_BOT_SCOPES in channel-readiness-service.ts.
|
|
194
217
|
defaultScopes: [
|
|
195
218
|
"channels:join",
|
|
196
219
|
"channels:read",
|
|
@@ -212,19 +235,17 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
212
235
|
// only credential this flow stores, so it acts as the installer for every
|
|
213
236
|
// call including `chat.postMessage`. The manifest's user list is read-only
|
|
214
237
|
// instead, since a Socket Mode install keeps a bot token beside it.
|
|
238
|
+
// `files:read` is what lets that token fetch a file shared in a message
|
|
239
|
+
// from files.slack.com. Credential health measures every stored grant
|
|
240
|
+
// against this list, so a scope added here reports each existing
|
|
241
|
+
// connection as `missing_scopes` until it reconnects: that is how a newly
|
|
242
|
+
// required scope reaches an install.
|
|
215
243
|
authorizeParams: {
|
|
216
244
|
user_scope:
|
|
217
|
-
"channels:read,channels:history,groups:read,groups:history,im:read,im:history,im:write,mpim:read,mpim:history,users:read,chat:write,search:read,reactions:write",
|
|
245
|
+
"channels:read,channels:history,groups:read,groups:history,im:read,im:history,im:write,mpim:read,mpim:history,users:read,chat:write,search:read,reactions:write,files:read",
|
|
218
246
|
},
|
|
219
247
|
loopbackPort: 17322,
|
|
220
|
-
injectionTemplates:
|
|
221
|
-
{
|
|
222
|
-
hostPattern: "slack.com",
|
|
223
|
-
injectionType: "header",
|
|
224
|
-
headerName: "Authorization",
|
|
225
|
-
valuePrefix: "Bearer ",
|
|
226
|
-
},
|
|
227
|
-
],
|
|
248
|
+
injectionTemplates: SLACK_PROVIDER_INJECTION_TEMPLATES,
|
|
228
249
|
appType: "Slack App",
|
|
229
250
|
identityUrl: "https://slack.com/api/auth.test",
|
|
230
251
|
identityOkField: "ok",
|
|
@@ -1194,14 +1215,7 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
1194
1215
|
logoUrl:
|
|
1195
1216
|
"https://cdn.jsdelivr.net/gh/glincker/thesvg@main/public/icons/slack/default.svg",
|
|
1196
1217
|
defaultScopes: [],
|
|
1197
|
-
injectionTemplates:
|
|
1198
|
-
{
|
|
1199
|
-
hostPattern: "slack.com",
|
|
1200
|
-
injectionType: "header",
|
|
1201
|
-
headerName: "Authorization",
|
|
1202
|
-
valuePrefix: "Bearer ",
|
|
1203
|
-
},
|
|
1204
|
-
],
|
|
1218
|
+
injectionTemplates: SLACK_PROVIDER_INJECTION_TEMPLATES,
|
|
1205
1219
|
},
|
|
1206
1220
|
|
|
1207
1221
|
// The bot that sits in a server and talks to people there, which is a
|
|
@@ -1329,6 +1343,171 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
1329
1343
|
identityUrl: "https://api.link.com/userinfo",
|
|
1330
1344
|
identityResponsePaths: ["email", "phone"],
|
|
1331
1345
|
},
|
|
1346
|
+
shopify: {
|
|
1347
|
+
provider: "shopify",
|
|
1348
|
+
// Shopify is per-tenant: every OAuth endpoint lives on the merchant's own
|
|
1349
|
+
// myshopify.com domain, so these carry a {tenant_host} placeholder the
|
|
1350
|
+
// platform fills in from the shop domain the user supplies at connect
|
|
1351
|
+
// time. There is no global Shopify authorization host to point at.
|
|
1352
|
+
authorizeUrl: "https://{tenant_host}/admin/oauth/authorize",
|
|
1353
|
+
tokenExchangeUrl: "https://{tenant_host}/admin/oauth/access_token",
|
|
1354
|
+
// Requesting `expiring=1` at token exchange yields a short-lived access
|
|
1355
|
+
// token plus a refresh token, which is refreshed against the same
|
|
1356
|
+
// per-shop endpoint.
|
|
1357
|
+
refreshUrl: "https://{tenant_host}/admin/oauth/access_token",
|
|
1358
|
+
pingUrl: "https://{tenant_host}/admin/api/2026-07/shop.json",
|
|
1359
|
+
baseUrl: "https://{tenant_host}",
|
|
1360
|
+
displayLabel: "Shopify",
|
|
1361
|
+
description: "Products, orders, customers, and inventory",
|
|
1362
|
+
dashboardUrl: "https://shopify.dev/dashboard",
|
|
1363
|
+
clientIdPlaceholder: null,
|
|
1364
|
+
logoUrl: "https://cdn.simpleicons.org/shopify",
|
|
1365
|
+
// Shopify parses `scope` as a comma-separated list. A space-separated
|
|
1366
|
+
// list is read as one malformed scope and the request is rejected.
|
|
1367
|
+
scopeSeparator: ",",
|
|
1368
|
+
// Admin API scopes only: Storefront, Customer Account and Shop APIs are
|
|
1369
|
+
// buyer-facing surfaces an assistant has no use for. Every scope here is
|
|
1370
|
+
// grantable without Shopify approval -- the approval-gated ones
|
|
1371
|
+
// (read_all_orders, customer payment methods, subscription contracts,
|
|
1372
|
+
// dispute evidence) are deliberately absent, because Shopify rejects the
|
|
1373
|
+
// whole authorization request if the app cannot grant a requested scope.
|
|
1374
|
+
// A write_* grant implies its read_* counterpart, so the response may
|
|
1375
|
+
// name only the write scope.
|
|
1376
|
+
defaultScopes: [
|
|
1377
|
+
"read_products",
|
|
1378
|
+
"write_products",
|
|
1379
|
+
"read_orders",
|
|
1380
|
+
"write_orders",
|
|
1381
|
+
"read_draft_orders",
|
|
1382
|
+
"write_draft_orders",
|
|
1383
|
+
"read_customers",
|
|
1384
|
+
"write_customers",
|
|
1385
|
+
"read_inventory",
|
|
1386
|
+
"read_locations",
|
|
1387
|
+
"read_fulfillments",
|
|
1388
|
+
"read_discounts",
|
|
1389
|
+
"write_discounts",
|
|
1390
|
+
"read_price_rules",
|
|
1391
|
+
],
|
|
1392
|
+
availableScopes: [
|
|
1393
|
+
{
|
|
1394
|
+
scope: "read_products",
|
|
1395
|
+
description: "Read products, variants, and collections",
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
scope: "write_products",
|
|
1399
|
+
description: "Create and update products, variants, and collections",
|
|
1400
|
+
},
|
|
1401
|
+
{
|
|
1402
|
+
scope: "read_orders",
|
|
1403
|
+
description: "Read orders, transactions, and abandoned checkouts",
|
|
1404
|
+
},
|
|
1405
|
+
{
|
|
1406
|
+
scope: "write_orders",
|
|
1407
|
+
description: "Create and update orders and fulfillments",
|
|
1408
|
+
},
|
|
1409
|
+
{ scope: "read_draft_orders", description: "Read draft orders" },
|
|
1410
|
+
{
|
|
1411
|
+
scope: "write_draft_orders",
|
|
1412
|
+
description: "Create and update draft orders",
|
|
1413
|
+
},
|
|
1414
|
+
{
|
|
1415
|
+
scope: "read_customers",
|
|
1416
|
+
description: "Read customers, segments, and companies",
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
scope: "write_customers",
|
|
1420
|
+
description: "Create and update customers and segments",
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
scope: "read_inventory",
|
|
1424
|
+
description: "Read inventory levels and items",
|
|
1425
|
+
},
|
|
1426
|
+
{
|
|
1427
|
+
scope: "write_inventory",
|
|
1428
|
+
description: "Adjust inventory levels and items",
|
|
1429
|
+
},
|
|
1430
|
+
{ scope: "read_locations", description: "Read store locations" },
|
|
1431
|
+
{ scope: "read_fulfillments", description: "Read fulfillment services" },
|
|
1432
|
+
{
|
|
1433
|
+
scope: "write_fulfillments",
|
|
1434
|
+
description: "Create and update fulfillment services",
|
|
1435
|
+
},
|
|
1436
|
+
{ scope: "read_discounts", description: "Read discounts" },
|
|
1437
|
+
{ scope: "write_discounts", description: "Create and update discounts" },
|
|
1438
|
+
{ scope: "read_price_rules", description: "Read price rules" },
|
|
1439
|
+
{
|
|
1440
|
+
scope: "write_price_rules",
|
|
1441
|
+
description: "Create and update price rules",
|
|
1442
|
+
},
|
|
1443
|
+
{ scope: "read_files", description: "Read files uploaded to the store" },
|
|
1444
|
+
{ scope: "write_files", description: "Upload and update files" },
|
|
1445
|
+
{ scope: "read_gift_cards", description: "Read gift cards" },
|
|
1446
|
+
{
|
|
1447
|
+
scope: "write_gift_cards",
|
|
1448
|
+
description: "Create and update gift cards",
|
|
1449
|
+
},
|
|
1450
|
+
{ scope: "read_returns", description: "Read returns" },
|
|
1451
|
+
{ scope: "write_returns", description: "Create and update returns" },
|
|
1452
|
+
{ scope: "read_markets", description: "Read markets" },
|
|
1453
|
+
{ scope: "read_locales", description: "Read shop locales" },
|
|
1454
|
+
{
|
|
1455
|
+
scope: "read_shipping",
|
|
1456
|
+
description: "Read shipping and delivery carrier services",
|
|
1457
|
+
},
|
|
1458
|
+
{ scope: "read_analytics", description: "Read analytics and reports" },
|
|
1459
|
+
{
|
|
1460
|
+
scope: "read_marketing_events",
|
|
1461
|
+
description: "Read marketing events and activities",
|
|
1462
|
+
},
|
|
1463
|
+
{ scope: "read_order_edits", description: "Read order edits" },
|
|
1464
|
+
{
|
|
1465
|
+
scope: "write_order_edits",
|
|
1466
|
+
description: "Create and apply order edits",
|
|
1467
|
+
},
|
|
1468
|
+
{
|
|
1469
|
+
scope: "read_metaobjects",
|
|
1470
|
+
description: "Read metaobjects and their definitions",
|
|
1471
|
+
},
|
|
1472
|
+
{
|
|
1473
|
+
scope: "write_metaobjects",
|
|
1474
|
+
description: "Create and update metaobjects",
|
|
1475
|
+
},
|
|
1476
|
+
{ scope: "read_translations", description: "Read translated content" },
|
|
1477
|
+
{
|
|
1478
|
+
scope: "read_shopify_payments_payouts",
|
|
1479
|
+
description: "Read Shopify Payments payouts and balance",
|
|
1480
|
+
},
|
|
1481
|
+
{
|
|
1482
|
+
scope: "read_shopify_payments_disputes",
|
|
1483
|
+
description: "Read Shopify Payments disputes",
|
|
1484
|
+
},
|
|
1485
|
+
],
|
|
1486
|
+
loopbackPort: 17341,
|
|
1487
|
+
managedServiceConfigKey: "shopify-oauth",
|
|
1488
|
+
injectionTemplates: [
|
|
1489
|
+
{
|
|
1490
|
+
hostPattern: "*.myshopify.com",
|
|
1491
|
+
injectionType: "header",
|
|
1492
|
+
headerName: "X-Shopify-Access-Token",
|
|
1493
|
+
valuePrefix: "",
|
|
1494
|
+
},
|
|
1495
|
+
],
|
|
1496
|
+
appType: "App",
|
|
1497
|
+
setupNotes: [
|
|
1498
|
+
"Shopify OAuth is per-shop: the authorize, token and API endpoints all live on the merchant's own myshopify.com domain, so connecting requires the shop domain (for example your-store.myshopify.com) alongside the usual credentials.",
|
|
1499
|
+
"The Admin API authenticates with the X-Shopify-Access-Token header rather than an Authorization Bearer header.",
|
|
1500
|
+
],
|
|
1501
|
+
// The Admin API's shop endpoint nests its payload under "shop"; the
|
|
1502
|
+
// myshopify domain is the stable, human-recognisable handle.
|
|
1503
|
+
identityUrl: "https://{tenant_host}/admin/api/2026-07/shop.json",
|
|
1504
|
+
identityResponsePaths: ["shop.myshopify_domain", "shop.name"],
|
|
1505
|
+
// Gated like monday/figma/stripe-link: the platform side and the
|
|
1506
|
+
// shop-domain input in the clients land separately, and until both are
|
|
1507
|
+
// in place a visible Shopify tile would offer a connect flow that
|
|
1508
|
+
// cannot complete.
|
|
1509
|
+
featureFlag: "shopify-oauth",
|
|
1510
|
+
},
|
|
1332
1511
|
};
|
|
1333
1512
|
|
|
1334
1513
|
export const SEEDED_PROVIDER_KEYS = new Set(Object.keys(PROVIDER_SEED_DATA));
|
|
@@ -2,6 +2,8 @@ import { X509Certificate } from "node:crypto";
|
|
|
2
2
|
import { chmod, mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
|
|
5
|
+
import { writeCombinedCABundle } from "../util/ca-bundle.js";
|
|
6
|
+
|
|
5
7
|
const CA_CERT_FILENAME = "ca.pem";
|
|
6
8
|
const CA_KEY_FILENAME = "ca-key.pem";
|
|
7
9
|
const COMBINED_CA_FILENAME = "combined-ca-bundle.pem";
|
|
@@ -263,11 +265,7 @@ export async function ensureCombinedCABundle(
|
|
|
263
265
|
}
|
|
264
266
|
|
|
265
267
|
try {
|
|
266
|
-
|
|
267
|
-
readFile(systemBundlePath, "utf-8"),
|
|
268
|
-
readFile(caCertPath, "utf-8"),
|
|
269
|
-
]);
|
|
270
|
-
await writeFile(combinedPath, systemCAs + "\n" + proxyCACert);
|
|
268
|
+
await writeCombinedCABundle(systemBundlePath, caCertPath, combinedPath);
|
|
271
269
|
return combinedPath;
|
|
272
270
|
} catch {
|
|
273
271
|
return null;
|
|
@@ -15,13 +15,16 @@ mock.module("../config/assistant-feature-flags.js", () => ({
|
|
|
15
15
|
}));
|
|
16
16
|
|
|
17
17
|
// `buildPolicyContext` (used by the integration tests below) precomputes the
|
|
18
|
-
//
|
|
19
|
-
//
|
|
18
|
+
// retrospective skill-improvement gate. Keep the v3 tier active while the
|
|
19
|
+
// dedicated gate changes so the production threading test covers the new
|
|
20
|
+
// opt-out rather than the old v3 condition.
|
|
20
21
|
let mockV3TierActive = true;
|
|
22
|
+
let mockSkillImprovementActive = true;
|
|
21
23
|
mock.module("../config/memory-v3-gate.js", () => ({
|
|
22
24
|
isMemoryEnabled: (config?: { memory?: { enabled?: boolean } }) =>
|
|
23
25
|
config?.memory?.enabled !== false,
|
|
24
26
|
isV3TierActive: () => mockV3TierActive,
|
|
27
|
+
isSkillImprovementActive: () => mockSkillImprovementActive,
|
|
25
28
|
isMemoryV3Live: () => mockV3TierActive,
|
|
26
29
|
usesConceptPageMemory: (memory?: {
|
|
27
30
|
enabled?: boolean;
|
|
@@ -219,6 +222,7 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
219
222
|
mockCachedThreshold = "low";
|
|
220
223
|
mockRefreshedThreshold = null;
|
|
221
224
|
mockV3TierActive = true;
|
|
225
|
+
mockSkillImprovementActive = true;
|
|
222
226
|
thresholdCallLog.length = 0;
|
|
223
227
|
mockSkillCatalog = [];
|
|
224
228
|
mockResolvedSkill = null;
|
|
@@ -1173,10 +1177,11 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
1173
1177
|
});
|
|
1174
1178
|
|
|
1175
1179
|
test("grant does NOT fire when proc-to-skills is inactive, even for the retrospective turn", async () => {
|
|
1176
|
-
//
|
|
1177
|
-
//
|
|
1178
|
-
//
|
|
1179
|
-
mockV3TierActive =
|
|
1180
|
+
// The retrospective keeps its live v3 tier, but this independent flag is
|
|
1181
|
+
// off. buildPolicyContext stamps `procToSkillsActive: false`, so the
|
|
1182
|
+
// grant is dead and the high-risk scaffold prompts.
|
|
1183
|
+
mockV3TierActive = true;
|
|
1184
|
+
mockSkillImprovementActive = false;
|
|
1180
1185
|
mockIpcClassifyRiskResult = {
|
|
1181
1186
|
risk: "high",
|
|
1182
1187
|
reason: "Skill scaffold",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import type { AgentEvent } from "../agent/loop.js";
|
|
28
28
|
import { getConfig } from "../config/loader.js";
|
|
29
|
+
import { resolvePlatformAssistantIdOrNull } from "../config/platform-identity.js";
|
|
29
30
|
import type { CompactionLogsClickHouseConfig } from "../config/schemas/compaction-logs.js";
|
|
30
31
|
import { credentialKey } from "../security/credential-key.js";
|
|
31
32
|
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
@@ -136,7 +137,7 @@ export interface ClickHouseCompactionLogStoreDeps {
|
|
|
136
137
|
resolveUrl?: () => Promise<string | null>;
|
|
137
138
|
/** Override the credential read for `clickhouse:password`. */
|
|
138
139
|
resolvePassword?: () => Promise<string | null>;
|
|
139
|
-
/** Override the
|
|
140
|
+
/** Override the in-memory platform assistant id. */
|
|
140
141
|
resolveAssistantId?: () => Promise<string | null>;
|
|
141
142
|
/** Override fetch for testing. */
|
|
142
143
|
fetchImpl?: CompactionLogFetch;
|
|
@@ -163,8 +164,7 @@ export class ClickHouseCompactionLogStore {
|
|
|
163
164
|
deps.resolvePassword ??
|
|
164
165
|
(() => readCredentialOrNull("clickhouse", "password"));
|
|
165
166
|
this.resolveAssistantId =
|
|
166
|
-
deps.resolveAssistantId ??
|
|
167
|
-
(() => readCredentialOrNull("vellum", "platform_assistant_id"));
|
|
167
|
+
deps.resolveAssistantId ?? resolvePlatformAssistantIdOrNull;
|
|
168
168
|
this.fetchImpl = deps.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
169
169
|
}
|
|
170
170
|
|
|
@@ -35,7 +35,10 @@ import { findConversation } from "../daemon/conversation-registry.js";
|
|
|
35
35
|
import { conversationMetadataSyncTag } from "../daemon/message-types/sync.js";
|
|
36
36
|
import type { TrustContext } from "../daemon/trust-context-types.js";
|
|
37
37
|
import { clearAllConversationIds } from "../home/feed-writer.js";
|
|
38
|
-
import type {
|
|
38
|
+
import type {
|
|
39
|
+
ConversationDeletedInputContext,
|
|
40
|
+
MessageDeletedInputContext,
|
|
41
|
+
} from "../hooks/types.js";
|
|
39
42
|
import { readProviderMetadata } from "../messaging/read-provider-metadata.js";
|
|
40
43
|
import { HOOKS } from "../plugin-api/constants.js";
|
|
41
44
|
import { forkConversationMemory } from "../plugins/defaults/memory/fork-conversation-memory.js";
|
|
@@ -81,7 +84,6 @@ import { ensureDisplayOrderMigration } from "./conversation-display-order-migrat
|
|
|
81
84
|
import { ensureGroupMigration } from "./conversation-group-migration.js";
|
|
82
85
|
import {
|
|
83
86
|
isReferentialFork,
|
|
84
|
-
type LineageBound,
|
|
85
87
|
type LineageConversationRow,
|
|
86
88
|
lineageMessageFilter,
|
|
87
89
|
lineageMessagesAfterFilter,
|
|
@@ -121,6 +123,11 @@ import {
|
|
|
121
123
|
} from "./job-handlers/message-lexical.js";
|
|
122
124
|
import { buildLifecycleTelemetryEvent } from "./lifecycle-events-store.js";
|
|
123
125
|
import { resolveMessageContentBlocks } from "./message-content-file.js";
|
|
126
|
+
import {
|
|
127
|
+
loadMessageBound,
|
|
128
|
+
type MessagesAfterRef,
|
|
129
|
+
resolveMessagesAfterBound,
|
|
130
|
+
} from "./message-cursor.js";
|
|
124
131
|
import { mergeMessageMetadata } from "./message-metadata.js";
|
|
125
132
|
import {
|
|
126
133
|
rawAll,
|
|
@@ -2641,16 +2648,6 @@ function loadLineageRow(id: string): LineageConversationRow | null {
|
|
|
2641
2648
|
return row ?? null;
|
|
2642
2649
|
}
|
|
2643
2650
|
|
|
2644
|
-
/** The `(createdAt, id)` bound of a single message, or null when it is gone. */
|
|
2645
|
-
function loadMessageBound(messageId: string): LineageBound | null {
|
|
2646
|
-
const row = getDb()
|
|
2647
|
-
.select({ createdAt: messages.createdAt, id: messages.id })
|
|
2648
|
-
.from(messages)
|
|
2649
|
-
.where(eq(messages.id, messageId))
|
|
2650
|
-
.get();
|
|
2651
|
-
return row ?? null;
|
|
2652
|
-
}
|
|
2653
|
-
|
|
2654
2651
|
/**
|
|
2655
2652
|
* The segments making up a conversation's logical message set. Non-forks and
|
|
2656
2653
|
* copied forks resolve to a single unbounded segment after one row lookup, so
|
|
@@ -2972,81 +2969,67 @@ export function selectNewestSightFrameCapture(
|
|
|
2972
2969
|
}
|
|
2973
2970
|
|
|
2974
2971
|
/**
|
|
2975
|
-
* Count messages in a conversation
|
|
2976
|
-
* `
|
|
2977
|
-
*
|
|
2978
|
-
*
|
|
2979
|
-
*
|
|
2980
|
-
*
|
|
2972
|
+
* Count messages in a conversation created strictly after the `after`
|
|
2973
|
+
* reference. `null`, `""`, or a cursor with an empty id counts every message.
|
|
2974
|
+
* The reference resolves through `resolveMessagesAfterBound`: a live row's
|
|
2975
|
+
* `(createdAt, id)` is authoritative, a `MessageCursor` whose row has been
|
|
2976
|
+
* deleted still bounds the count from the `createdAt` it carries, and a bare
|
|
2977
|
+
* id whose row is gone counts 0: a caller holding only an id has no
|
|
2978
|
+
* defensible starting point, and the conservative answer is "no new work."
|
|
2981
2979
|
*
|
|
2982
2980
|
* Used by the memory-retrospective trigger check to decide whether to fire
|
|
2983
2981
|
* the message-count trigger without loading message bodies.
|
|
2984
2982
|
*/
|
|
2985
2983
|
export function countMessagesAfter(
|
|
2986
2984
|
conversationId: string,
|
|
2987
|
-
|
|
2985
|
+
after: MessagesAfterRef,
|
|
2988
2986
|
): number {
|
|
2989
2987
|
const db = getDb();
|
|
2990
2988
|
const segments = resolveLineage(conversationId);
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
.select({ c: count() })
|
|
2994
|
-
.from(messages)
|
|
2995
|
-
.where(lineageMessageFilter(segments))
|
|
2996
|
-
.get();
|
|
2997
|
-
return row?.c ?? 0;
|
|
2998
|
-
}
|
|
2999
|
-
const ref = loadMessageBound(afterMessageId);
|
|
3000
|
-
if (!ref) {
|
|
2989
|
+
const start = resolveMessagesAfterBound(after);
|
|
2990
|
+
if (start.kind === "vanished") {
|
|
3001
2991
|
return 0;
|
|
3002
2992
|
}
|
|
3003
|
-
// Tie-breaker on `messages.id` so rows that share a millisecond timestamp
|
|
3004
|
-
// with the reference are not permanently skipped. Mirrors the
|
|
3005
|
-
// `(createdAt, id)` cursor pattern used by the backfill job-handler and
|
|
3006
|
-
// turn-events-store.
|
|
3007
2993
|
const row = db
|
|
3008
2994
|
.select({ c: count() })
|
|
3009
2995
|
.from(messages)
|
|
3010
|
-
.where(
|
|
2996
|
+
.where(
|
|
2997
|
+
start.kind === "all"
|
|
2998
|
+
? lineageMessageFilter(segments)
|
|
2999
|
+
: lineageMessagesAfterFilter(segments, start.bound),
|
|
3000
|
+
)
|
|
3011
3001
|
.get();
|
|
3012
3002
|
return row?.c ?? 0;
|
|
3013
3003
|
}
|
|
3014
3004
|
|
|
3015
3005
|
/**
|
|
3016
|
-
* Return messages in a conversation created strictly after the
|
|
3017
|
-
* `
|
|
3018
|
-
*
|
|
3019
|
-
*
|
|
3020
|
-
*
|
|
3006
|
+
* Return messages in a conversation created strictly after the `after`
|
|
3007
|
+
* reference, in `(createdAt, id)` order. Resolves the reference exactly as
|
|
3008
|
+
* `countMessagesAfter` does, returning an empty array where that returns 0.
|
|
3009
|
+
* Used by the memory-retrospective job handler to load the message slice it
|
|
3010
|
+
* processes.
|
|
3021
3011
|
*/
|
|
3022
3012
|
export function getMessagesAfter(
|
|
3023
3013
|
conversationId: string,
|
|
3024
|
-
|
|
3014
|
+
after: MessagesAfterRef,
|
|
3025
3015
|
): MessageRow[] {
|
|
3026
3016
|
const db = getDb();
|
|
3027
3017
|
const segments = resolveLineage(conversationId);
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
// ordering, so callers tracking `cutoffMessageId` across runs see a
|
|
3031
|
-
// consistent ordering when multiple rows share a millisecond timestamp.
|
|
3032
|
-
return db
|
|
3033
|
-
.select()
|
|
3034
|
-
.from(messages)
|
|
3035
|
-
.where(lineageMessageFilter(segments))
|
|
3036
|
-
.orderBy(asc(messages.createdAt), asc(messages.id))
|
|
3037
|
-
.all()
|
|
3038
|
-
.map(parseMessage);
|
|
3039
|
-
}
|
|
3040
|
-
const ref = loadMessageBound(afterMessageId);
|
|
3041
|
-
if (!ref) {
|
|
3018
|
+
const start = resolveMessagesAfterBound(after);
|
|
3019
|
+
if (start.kind === "vanished") {
|
|
3042
3020
|
return [];
|
|
3043
3021
|
}
|
|
3044
|
-
//
|
|
3045
|
-
//
|
|
3022
|
+
// Secondary `asc(messages.id)` mirrors the bound's tie-breaker, so callers
|
|
3023
|
+
// tracking `cutoffMessageId` across runs see a consistent ordering when
|
|
3024
|
+
// multiple rows share a millisecond timestamp.
|
|
3046
3025
|
return db
|
|
3047
3026
|
.select()
|
|
3048
3027
|
.from(messages)
|
|
3049
|
-
.where(
|
|
3028
|
+
.where(
|
|
3029
|
+
start.kind === "all"
|
|
3030
|
+
? lineageMessageFilter(segments)
|
|
3031
|
+
: lineageMessagesAfterFilter(segments, start.bound),
|
|
3032
|
+
)
|
|
3050
3033
|
.orderBy(asc(messages.createdAt), asc(messages.id))
|
|
3051
3034
|
.all()
|
|
3052
3035
|
.map(parseMessage);
|
|
@@ -4304,12 +4287,12 @@ export function deleteLastExchange(conversationId: string): number {
|
|
|
4304
4287
|
|
|
4305
4288
|
// Collect attachment IDs linked to the messages being deleted so we can
|
|
4306
4289
|
// scope orphan cleanup to only those candidates (not freshly uploaded ones).
|
|
4307
|
-
const
|
|
4308
|
-
.select({ id: messages.id })
|
|
4290
|
+
const deletedRows = db
|
|
4291
|
+
.select({ id: messages.id, createdAt: messages.createdAt })
|
|
4309
4292
|
.from(messages)
|
|
4310
4293
|
.where(condition)
|
|
4311
|
-
.all()
|
|
4312
|
-
|
|
4294
|
+
.all();
|
|
4295
|
+
const messageIds = deletedRows.map((r) => r.id);
|
|
4313
4296
|
const candidateAttachmentIds =
|
|
4314
4297
|
messageIds.length > 0
|
|
4315
4298
|
? db
|
|
@@ -4356,6 +4339,17 @@ export function deleteLastExchange(conversationId: string): number {
|
|
|
4356
4339
|
enqueueDeleteMessageLexical(deletedMessageId);
|
|
4357
4340
|
}
|
|
4358
4341
|
|
|
4342
|
+
// Notify `message-deleted` hooks for each removed row, as the
|
|
4343
|
+
// single-message primitive does: undo removes the same tail a regenerate
|
|
4344
|
+
// does, and a hook keeping a cursor on one of these rows needs its position.
|
|
4345
|
+
for (const row of deletedRows) {
|
|
4346
|
+
void runHook(HOOKS.MESSAGE_DELETED, {
|
|
4347
|
+
conversationId,
|
|
4348
|
+
messageId: row.id,
|
|
4349
|
+
createdAt: row.createdAt,
|
|
4350
|
+
} satisfies MessageDeletedInputContext);
|
|
4351
|
+
}
|
|
4352
|
+
|
|
4359
4353
|
return deleted;
|
|
4360
4354
|
}
|
|
4361
4355
|
|
|
@@ -4594,9 +4588,13 @@ export function deleteMessageById(
|
|
|
4594
4588
|
.map((r) => r.attachmentId)
|
|
4595
4589
|
.filter((id): id is string => id !== undefined);
|
|
4596
4590
|
|
|
4597
|
-
// Look up the conversation before the transaction so we can recalculate
|
|
4591
|
+
// Look up the conversation before the transaction so we can recalculate
|
|
4592
|
+
// lastMessageAt, and the row's createdAt for the `message-deleted` hook.
|
|
4598
4593
|
const msgRow = db
|
|
4599
|
-
.select({
|
|
4594
|
+
.select({
|
|
4595
|
+
conversationId: messages.conversationId,
|
|
4596
|
+
createdAt: messages.createdAt,
|
|
4597
|
+
})
|
|
4600
4598
|
.from(messages)
|
|
4601
4599
|
.where(eq(messages.id, messageId))
|
|
4602
4600
|
.get();
|
|
@@ -4652,6 +4650,16 @@ export function deleteMessageById(
|
|
|
4652
4650
|
// not go through the conversation-level purge.
|
|
4653
4651
|
if (msgRow) {
|
|
4654
4652
|
enqueueDeleteMessageLexical(messageId);
|
|
4653
|
+
|
|
4654
|
+
// Notify `message-deleted` hooks (e.g. the memory plugin stamping a
|
|
4655
|
+
// retrospective cursor that sat on this row). Fire-and-forget from this
|
|
4656
|
+
// synchronous primitive, like `conversation-deleted`; the context carries
|
|
4657
|
+
// the row's position because the row itself is gone.
|
|
4658
|
+
void runHook(HOOKS.MESSAGE_DELETED, {
|
|
4659
|
+
conversationId: msgRow.conversationId,
|
|
4660
|
+
messageId,
|
|
4661
|
+
createdAt: msgRow.createdAt,
|
|
4662
|
+
} satisfies MessageDeletedInputContext);
|
|
4655
4663
|
}
|
|
4656
4664
|
|
|
4657
4665
|
return result;
|
|
@@ -227,9 +227,17 @@ export function lineageMessagesAfterFilter(
|
|
|
227
227
|
): SQL {
|
|
228
228
|
return and(
|
|
229
229
|
lineageMessageFilter(segments),
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
230
|
+
messagesAfterBoundFilter(after),
|
|
231
|
+
) as SQL;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Predicate for rows strictly after a `(createdAt, id)` bound, with the id
|
|
236
|
+
* tie-breaker so rows sharing the bound's millisecond keep their order.
|
|
237
|
+
*/
|
|
238
|
+
export function messagesAfterBoundFilter(after: LineageBound): SQL {
|
|
239
|
+
return or(
|
|
240
|
+
gt(messages.createdAt, after.createdAt),
|
|
241
|
+
and(eq(messages.createdAt, after.createdAt), gt(messages.id, after.id)),
|
|
234
242
|
) as SQL;
|
|
235
243
|
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
wrapUntrustedContent,
|
|
18
18
|
} from "../security/untrusted-content.js";
|
|
19
19
|
import { getLogger } from "../util/logger.js";
|
|
20
|
+
import { safeStringSlice } from "../util/unicode.js";
|
|
20
21
|
import { isLexicalBackfillComplete } from "./checkpoints.js";
|
|
21
22
|
import { unseenAttentionStateConditions } from "./conversation-attention-store.js";
|
|
22
23
|
import type { ConversationRow } from "./conversation-crud.js";
|
|
@@ -1443,8 +1444,7 @@ function buildExcerptFromText(
|
|
|
1443
1444
|
if (!match) {
|
|
1444
1445
|
// Neither the query nor any of its tokens is present (e.g. the lexical
|
|
1445
1446
|
// index matched JSON structure instead); fall back to the text start.
|
|
1446
|
-
return text
|
|
1447
|
-
.slice(0, EXCERPT_WINDOW * 2)
|
|
1447
|
+
return safeStringSlice(text, 0, EXCERPT_WINDOW * 2)
|
|
1448
1448
|
.replace(/\s+/g, " ")
|
|
1449
1449
|
.trim();
|
|
1450
1450
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { isMessageKey } from "../i18n/index.js";
|
|
2
|
+
|
|
3
|
+
const REPLACEABLE_PATTERNS = [
|
|
4
|
+
/^Runtime:\s/,
|
|
5
|
+
/^New Conversation$/,
|
|
6
|
+
/^Untitled$/,
|
|
7
|
+
/^Untitled Conversation$/,
|
|
8
|
+
/^Generating title\.\.\.$/,
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Check whether a title is a system-generated placeholder that can be
|
|
13
|
+
* replaced or omitted without discarding user-provided copy.
|
|
14
|
+
*/
|
|
15
|
+
export function isReplaceableTitle(title: string | null): boolean {
|
|
16
|
+
if (title == null || title.trim() === "") {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
if (isMessageKey(title.trim())) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return REPLACEABLE_PATTERNS.some((pattern) => pattern.test(title));
|
|
23
|
+
}
|