@vellumai/assistant 0.12.0 → 0.12.1-dev.202609141913.5e16607
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 +5 -1
- package/ARCHITECTURE.md +11 -12
- package/docs/architecture/turn-actor.md +15 -8
- package/docs/guardian-request-flow.md +16 -0
- package/openapi.yaml +292 -50
- package/package.json +1 -1
- package/scripts/smoke-desktop-window-theme.ts +186 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
- 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__/computer-use-skill-proxy-bridge.test.ts +5 -2
- package/src/__tests__/computer-use-tools.test.ts +17 -5
- 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__/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-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__/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__/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 +13 -0
- package/src/__tests__/resolve-app.test.ts +135 -0
- 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__/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__/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 +94 -9
- 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/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/index.ts +6 -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/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/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/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 +2 -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/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-process.ts +35 -64
- package/src/daemon/conversation-skill-tools.ts +13 -31
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +10 -8
- package/src/daemon/conversation-tool-setup.ts +37 -43
- package/src/daemon/conversation.ts +0 -3
- package/src/daemon/host-bash-proxy.ts +8 -12
- package/src/daemon/host-browser-proxy.ts +15 -1
- package/src/daemon/host-file-proxy.ts +8 -10
- 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/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 +119 -0
- package/src/desktop/desktop-chrome-policy.test.ts +71 -0
- package/src/desktop/desktop-chrome-policy.ts +42 -0
- package/src/desktop/desktop-dependencies.test.ts +102 -0
- package/src/desktop/desktop-dependencies.ts +306 -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 +627 -0
- package/src/desktop/desktop-session-manager.ts +814 -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-theme.ts +170 -0
- 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-vad.test.ts +2 -2
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
- 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/__tests__/seed-providers-managed.test.ts +54 -0
- package/src/oauth/byo-connection.test.ts +45 -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/seed-providers.ts +165 -0
- 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-title-placeholders.ts +23 -0
- package/src/persistence/conversation-title-service.ts +9 -26
- 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-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/graph/capability-seed.ts +4 -6
- 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/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-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 +6 -1
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +89 -0
- 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/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/auth.ts +2 -3
- package/src/providers/inference/connection-availability.ts +27 -8
- 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-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 +192 -78
- package/src/providers/openai/codex-models.ts +0 -4
- package/src/providers/openai/google-thought-signature.ts +320 -0
- package/src/runtime/AGENTS.md +2 -0
- 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__/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/auth/same-actor.ts +38 -3
- package/src/runtime/channel-send.ts +316 -0
- 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/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 +55 -3
- 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/platform-routes.ts +18 -15
- 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/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/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/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/capability-offer.test.ts +22 -2
- package/src/tools/capability-offer.ts +16 -1
- package/src/tools/computer-use/definitions.ts +4 -2
- package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
- package/src/tools/credentials/metadata-store.ts +100 -0
- 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/policy-context.ts +6 -7
- package/src/tools/subagent/spawn.ts +5 -8
- package/src/tools/terminal/__tests__/safe-env.test.ts +6 -6
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +57 -0
- package/src/tools/terminal/safe-env.ts +23 -3
- package/src/tools/terminal/sanitized-bash.ts +105 -0
- package/src/tools/watch/watch-retro-report.ts +0 -8
- 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/workspace/git-porcelain.ts +66 -0
- package/src/workspace/git-service.ts +5 -54
- 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
|
@@ -21,11 +21,29 @@ const log = getLogger("byo-oauth-connection");
|
|
|
21
21
|
/** Default per-request timeout to prevent hung requests from blocking indefinitely. */
|
|
22
22
|
const REQUEST_TIMEOUT_MS = 30_000;
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* How the access token is attached to an outbound request. Almost every
|
|
26
|
+
* provider reads `Authorization: Bearer <token>`; a few use their own header
|
|
27
|
+
* (Shopify's Admin API reads `X-Shopify-Access-Token` and ignores
|
|
28
|
+
* Authorization entirely). Derived from the provider's header-type injection
|
|
29
|
+
* template so the seed is the single source of truth.
|
|
30
|
+
*/
|
|
31
|
+
export interface BYOTokenHeader {
|
|
32
|
+
name: string;
|
|
33
|
+
/** Text placed before the token, e.g. `"Bearer "`, `"Bot "`, or `""`. */
|
|
34
|
+
valuePrefix: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
export interface BYOOAuthConnectionOptions {
|
|
25
38
|
id: string;
|
|
26
39
|
provider: string;
|
|
27
40
|
baseUrl: string;
|
|
28
41
|
accountInfo: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Token header override. When omitted the connection falls back to
|
|
44
|
+
* `Authorization: Bearer` (or `Bot` for discord_channel).
|
|
45
|
+
*/
|
|
46
|
+
tokenHeader?: BYOTokenHeader | null;
|
|
29
47
|
}
|
|
30
48
|
|
|
31
49
|
export class BYOOAuthConnection implements OAuthConnection {
|
|
@@ -34,12 +52,14 @@ export class BYOOAuthConnection implements OAuthConnection {
|
|
|
34
52
|
readonly accountInfo: string | null;
|
|
35
53
|
|
|
36
54
|
private readonly baseUrl: string;
|
|
55
|
+
private readonly tokenHeader: BYOTokenHeader | null;
|
|
37
56
|
|
|
38
57
|
constructor(opts: BYOOAuthConnectionOptions) {
|
|
39
58
|
this.id = opts.id;
|
|
40
59
|
this.provider = opts.provider;
|
|
41
60
|
this.baseUrl = opts.baseUrl;
|
|
42
61
|
this.accountInfo = opts.accountInfo;
|
|
62
|
+
this.tokenHeader = opts.tokenHeader ?? null;
|
|
43
63
|
}
|
|
44
64
|
|
|
45
65
|
async request(req: OAuthConnectionRequest): Promise<OAuthConnectionResponse> {
|
|
@@ -51,8 +71,12 @@ export class BYOOAuthConnection implements OAuthConnection {
|
|
|
51
71
|
// Discord bot tokens authenticate with the `Bot ` scheme, not
|
|
52
72
|
// `Bearer`. Sending Bearer here reaches Discord as an unusable
|
|
53
73
|
// credential and comes back 401, which reads as a revoked token.
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
// Providers with their own token header (Shopify) override the
|
|
75
|
+
// whole thing via `tokenHeader`.
|
|
76
|
+
const tokenHeader: BYOTokenHeader = this.tokenHeader ?? {
|
|
77
|
+
name: "Authorization",
|
|
78
|
+
valuePrefix: this.provider === "discord_channel" ? "Bot " : "Bearer ",
|
|
79
|
+
};
|
|
56
80
|
const requestPath = isTelegram
|
|
57
81
|
? buildTelegramBotApiPath(req.path, token)
|
|
58
82
|
: req.path;
|
|
@@ -93,16 +117,22 @@ export class BYOOAuthConnection implements OAuthConnection {
|
|
|
93
117
|
}
|
|
94
118
|
}
|
|
95
119
|
if (!isTelegram) {
|
|
96
|
-
|
|
120
|
+
// The credential always wins over a caller-supplied value, and a
|
|
121
|
+
// provider that reads its own header must not also receive a
|
|
122
|
+
// stray Authorization the caller happened to send.
|
|
123
|
+
if (tokenHeader.name.toLowerCase() !== "authorization") {
|
|
124
|
+
headers.delete("Authorization");
|
|
125
|
+
}
|
|
126
|
+
headers.set(tokenHeader.name, `${tokenHeader.valuePrefix}${token}`);
|
|
97
127
|
}
|
|
98
128
|
|
|
99
129
|
const resp = await fetch(fullUrl, {
|
|
100
130
|
method: req.method,
|
|
101
131
|
headers,
|
|
102
132
|
body: hasBody
|
|
103
|
-
?
|
|
104
|
-
|
|
105
|
-
|
|
133
|
+
? binaryBody !== undefined
|
|
134
|
+
? Buffer.from(binaryBody)
|
|
135
|
+
: (rawBody ?? JSON.stringify(req.body))
|
|
106
136
|
: undefined,
|
|
107
137
|
// Following a redirect would replay a POST as a GET against a URL
|
|
108
138
|
// the caller never asked for, and hide the 3xx from them.
|
|
@@ -75,6 +75,7 @@ import {
|
|
|
75
75
|
resolveEffectiveBaseUrl,
|
|
76
76
|
resolveOAuthConnection,
|
|
77
77
|
resolveOAuthConnectionWithMeta,
|
|
78
|
+
resolveTokenHeader,
|
|
78
79
|
} from "./connection-resolver.js";
|
|
79
80
|
import { PlatformOAuthConnection } from "./platform-connection.js";
|
|
80
81
|
|
|
@@ -753,3 +754,75 @@ describe("resolveEffectiveBaseUrl", () => {
|
|
|
753
754
|
).toBe("https://gmail.googleapis.com/gmail/v1/users/me");
|
|
754
755
|
});
|
|
755
756
|
});
|
|
757
|
+
|
|
758
|
+
describe("resolveTokenHeader", () => {
|
|
759
|
+
const shopify = JSON.stringify([
|
|
760
|
+
{
|
|
761
|
+
hostPattern: "*.myshopify.com",
|
|
762
|
+
injectionType: "header",
|
|
763
|
+
headerName: "X-Shopify-Access-Token",
|
|
764
|
+
valuePrefix: "",
|
|
765
|
+
},
|
|
766
|
+
]);
|
|
767
|
+
|
|
768
|
+
test("returns null when the provider declares no templates", () => {
|
|
769
|
+
expect(resolveTokenHeader(undefined, "https://api.example.com")).toBeNull();
|
|
770
|
+
expect(resolveTokenHeader(null, "https://api.example.com")).toBeNull();
|
|
771
|
+
expect(resolveTokenHeader("[]", "https://api.example.com")).toBeNull();
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
test("returns null for malformed JSON", () => {
|
|
775
|
+
expect(
|
|
776
|
+
resolveTokenHeader("{not json", "https://api.example.com"),
|
|
777
|
+
).toBeNull();
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
test("ignores non-header injection templates", () => {
|
|
781
|
+
const query = JSON.stringify([
|
|
782
|
+
{
|
|
783
|
+
hostPattern: "api.example.com",
|
|
784
|
+
injectionType: "query",
|
|
785
|
+
headerName: "",
|
|
786
|
+
},
|
|
787
|
+
]);
|
|
788
|
+
expect(resolveTokenHeader(query, "https://api.example.com")).toBeNull();
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
test("picks the template whose wildcard host pattern matches the base URL", () => {
|
|
792
|
+
const templates = JSON.stringify([
|
|
793
|
+
{
|
|
794
|
+
hostPattern: "api.other.com",
|
|
795
|
+
injectionType: "header",
|
|
796
|
+
headerName: "Authorization",
|
|
797
|
+
valuePrefix: "Bearer ",
|
|
798
|
+
},
|
|
799
|
+
...JSON.parse(shopify),
|
|
800
|
+
]);
|
|
801
|
+
expect(
|
|
802
|
+
resolveTokenHeader(templates, "https://example-store.myshopify.com"),
|
|
803
|
+
).toEqual({ name: "X-Shopify-Access-Token", valuePrefix: "" });
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
test("falls back to the first header template when the host cannot be matched", () => {
|
|
807
|
+
// A still-templated base URL is not a parseable URL.
|
|
808
|
+
expect(resolveTokenHeader(shopify, "https://{tenant_host}")).toEqual({
|
|
809
|
+
name: "X-Shopify-Access-Token",
|
|
810
|
+
valuePrefix: "",
|
|
811
|
+
});
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
test("preserves the Bot prefix for discord_channel", () => {
|
|
815
|
+
const discord = JSON.stringify([
|
|
816
|
+
{
|
|
817
|
+
hostPattern: "discord.com",
|
|
818
|
+
injectionType: "header",
|
|
819
|
+
headerName: "Authorization",
|
|
820
|
+
valuePrefix: "Bot ",
|
|
821
|
+
},
|
|
822
|
+
]);
|
|
823
|
+
expect(resolveTokenHeader(discord, "https://discord.com/api")).toEqual({
|
|
824
|
+
name: "Authorization",
|
|
825
|
+
valuePrefix: "Bot ",
|
|
826
|
+
});
|
|
827
|
+
});
|
|
828
|
+
});
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "../config/schemas/services.js";
|
|
7
7
|
import { VellumPlatformClient } from "../platform/client.js";
|
|
8
8
|
import { getLogger } from "../util/logger.js";
|
|
9
|
-
import { BYOOAuthConnection } from "./byo-connection.js";
|
|
9
|
+
import { BYOOAuthConnection, type BYOTokenHeader } from "./byo-connection.js";
|
|
10
10
|
import type { OAuthConnection } from "./connection.js";
|
|
11
11
|
import { getConnectionAccessTokenResult } from "./credential-token-resolver.js";
|
|
12
12
|
import { syncManualTokenConnection } from "./manual-token-connection.js";
|
|
@@ -215,15 +215,108 @@ export async function resolveOAuthConnectionWithMeta(
|
|
|
215
215
|
);
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
const effectiveBaseUrl = resolveEffectiveBaseUrl(
|
|
219
|
+
conn.provider,
|
|
220
|
+
baseUrl,
|
|
221
|
+
conn.metadata,
|
|
222
|
+
);
|
|
218
223
|
const connection = new BYOOAuthConnection({
|
|
219
224
|
id: conn.id,
|
|
220
225
|
provider: conn.provider,
|
|
221
|
-
baseUrl:
|
|
226
|
+
baseUrl: effectiveBaseUrl,
|
|
222
227
|
accountInfo: conn.accountInfo,
|
|
228
|
+
tokenHeader: resolveTokenHeader(
|
|
229
|
+
providerRow?.injectionTemplates,
|
|
230
|
+
effectiveBaseUrl,
|
|
231
|
+
),
|
|
223
232
|
});
|
|
224
233
|
return { connection, ambiguous, allAccounts };
|
|
225
234
|
}
|
|
226
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Pick the header a provider expects its access token in from the seed's
|
|
238
|
+
* header-type injection templates.
|
|
239
|
+
*
|
|
240
|
+
* Prefers the template whose `hostPattern` matches the base URL's host
|
|
241
|
+
* (`*.myshopify.com` style globs included), then falls back to the first
|
|
242
|
+
* header template. Returns `null` when the provider declares none, which
|
|
243
|
+
* leaves `BYOOAuthConnection` on its `Authorization: Bearer` default.
|
|
244
|
+
*
|
|
245
|
+
* Shopify is why this exists: its Admin API reads `X-Shopify-Access-Token`
|
|
246
|
+
* and ignores `Authorization`, so a Bearer header reaches the shop as an
|
|
247
|
+
* unauthenticated request and comes back 401.
|
|
248
|
+
*/
|
|
249
|
+
export function resolveTokenHeader(
|
|
250
|
+
rawTemplates: string | null | undefined,
|
|
251
|
+
baseUrl: string,
|
|
252
|
+
): BYOTokenHeader | null {
|
|
253
|
+
if (!rawTemplates) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
let parsed: unknown;
|
|
257
|
+
try {
|
|
258
|
+
parsed = JSON.parse(rawTemplates);
|
|
259
|
+
} catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
if (!Array.isArray(parsed)) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const headerTemplates = parsed.filter(
|
|
267
|
+
(
|
|
268
|
+
t,
|
|
269
|
+
): t is {
|
|
270
|
+
hostPattern?: unknown;
|
|
271
|
+
headerName: string;
|
|
272
|
+
valuePrefix?: unknown;
|
|
273
|
+
} =>
|
|
274
|
+
typeof t === "object" &&
|
|
275
|
+
t !== null &&
|
|
276
|
+
(t as { injectionType?: unknown }).injectionType === "header" &&
|
|
277
|
+
typeof (t as { headerName?: unknown }).headerName === "string" &&
|
|
278
|
+
(t as { headerName: string }).headerName.trim() !== "",
|
|
279
|
+
);
|
|
280
|
+
if (headerTemplates.length === 0) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
let host = "";
|
|
285
|
+
try {
|
|
286
|
+
host = new URL(baseUrl).hostname.toLowerCase();
|
|
287
|
+
} catch {
|
|
288
|
+
// Templated or malformed base URLs (e.g. a still-unfilled
|
|
289
|
+
// `https://{tenant_host}`) cannot be matched by host; fall through to
|
|
290
|
+
// the first header template.
|
|
291
|
+
}
|
|
292
|
+
const matching =
|
|
293
|
+
host === ""
|
|
294
|
+
? undefined
|
|
295
|
+
: headerTemplates.find(
|
|
296
|
+
(t) =>
|
|
297
|
+
typeof t.hostPattern === "string" &&
|
|
298
|
+
hostMatchesPattern(host, t.hostPattern),
|
|
299
|
+
);
|
|
300
|
+
const chosen = matching ?? headerTemplates[0];
|
|
301
|
+
return {
|
|
302
|
+
name: chosen.headerName.trim(),
|
|
303
|
+
valuePrefix:
|
|
304
|
+
typeof chosen.valuePrefix === "string" ? chosen.valuePrefix : "",
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function hostMatchesPattern(host: string, pattern: string): boolean {
|
|
309
|
+
const p = pattern.trim().toLowerCase();
|
|
310
|
+
if (p === "") {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
if (p.startsWith("*.")) {
|
|
314
|
+
const suffix = p.slice(1); // ".myshopify.com"
|
|
315
|
+
return host.endsWith(suffix) && host.length > suffix.length;
|
|
316
|
+
}
|
|
317
|
+
return host === p;
|
|
318
|
+
}
|
|
319
|
+
|
|
227
320
|
/**
|
|
228
321
|
* Resolve the effective API base URL for a connection, preferring per-tenant
|
|
229
322
|
* values stored on the connection's `metadata` over the provider's static
|
|
@@ -1329,6 +1329,171 @@ export const PROVIDER_SEED_DATA: Record<
|
|
|
1329
1329
|
identityUrl: "https://api.link.com/userinfo",
|
|
1330
1330
|
identityResponsePaths: ["email", "phone"],
|
|
1331
1331
|
},
|
|
1332
|
+
shopify: {
|
|
1333
|
+
provider: "shopify",
|
|
1334
|
+
// Shopify is per-tenant: every OAuth endpoint lives on the merchant's own
|
|
1335
|
+
// myshopify.com domain, so these carry a {tenant_host} placeholder the
|
|
1336
|
+
// platform fills in from the shop domain the user supplies at connect
|
|
1337
|
+
// time. There is no global Shopify authorization host to point at.
|
|
1338
|
+
authorizeUrl: "https://{tenant_host}/admin/oauth/authorize",
|
|
1339
|
+
tokenExchangeUrl: "https://{tenant_host}/admin/oauth/access_token",
|
|
1340
|
+
// Requesting `expiring=1` at token exchange yields a short-lived access
|
|
1341
|
+
// token plus a refresh token, which is refreshed against the same
|
|
1342
|
+
// per-shop endpoint.
|
|
1343
|
+
refreshUrl: "https://{tenant_host}/admin/oauth/access_token",
|
|
1344
|
+
pingUrl: "https://{tenant_host}/admin/api/2026-07/shop.json",
|
|
1345
|
+
baseUrl: "https://{tenant_host}",
|
|
1346
|
+
displayLabel: "Shopify",
|
|
1347
|
+
description: "Products, orders, customers, and inventory",
|
|
1348
|
+
dashboardUrl: "https://shopify.dev/dashboard",
|
|
1349
|
+
clientIdPlaceholder: null,
|
|
1350
|
+
logoUrl: "https://cdn.simpleicons.org/shopify",
|
|
1351
|
+
// Shopify parses `scope` as a comma-separated list. A space-separated
|
|
1352
|
+
// list is read as one malformed scope and the request is rejected.
|
|
1353
|
+
scopeSeparator: ",",
|
|
1354
|
+
// Admin API scopes only: Storefront, Customer Account and Shop APIs are
|
|
1355
|
+
// buyer-facing surfaces an assistant has no use for. Every scope here is
|
|
1356
|
+
// grantable without Shopify approval -- the approval-gated ones
|
|
1357
|
+
// (read_all_orders, customer payment methods, subscription contracts,
|
|
1358
|
+
// dispute evidence) are deliberately absent, because Shopify rejects the
|
|
1359
|
+
// whole authorization request if the app cannot grant a requested scope.
|
|
1360
|
+
// A write_* grant implies its read_* counterpart, so the response may
|
|
1361
|
+
// name only the write scope.
|
|
1362
|
+
defaultScopes: [
|
|
1363
|
+
"read_products",
|
|
1364
|
+
"write_products",
|
|
1365
|
+
"read_orders",
|
|
1366
|
+
"write_orders",
|
|
1367
|
+
"read_draft_orders",
|
|
1368
|
+
"write_draft_orders",
|
|
1369
|
+
"read_customers",
|
|
1370
|
+
"write_customers",
|
|
1371
|
+
"read_inventory",
|
|
1372
|
+
"read_locations",
|
|
1373
|
+
"read_fulfillments",
|
|
1374
|
+
"read_discounts",
|
|
1375
|
+
"write_discounts",
|
|
1376
|
+
"read_price_rules",
|
|
1377
|
+
],
|
|
1378
|
+
availableScopes: [
|
|
1379
|
+
{
|
|
1380
|
+
scope: "read_products",
|
|
1381
|
+
description: "Read products, variants, and collections",
|
|
1382
|
+
},
|
|
1383
|
+
{
|
|
1384
|
+
scope: "write_products",
|
|
1385
|
+
description: "Create and update products, variants, and collections",
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
scope: "read_orders",
|
|
1389
|
+
description: "Read orders, transactions, and abandoned checkouts",
|
|
1390
|
+
},
|
|
1391
|
+
{
|
|
1392
|
+
scope: "write_orders",
|
|
1393
|
+
description: "Create and update orders and fulfillments",
|
|
1394
|
+
},
|
|
1395
|
+
{ scope: "read_draft_orders", description: "Read draft orders" },
|
|
1396
|
+
{
|
|
1397
|
+
scope: "write_draft_orders",
|
|
1398
|
+
description: "Create and update draft orders",
|
|
1399
|
+
},
|
|
1400
|
+
{
|
|
1401
|
+
scope: "read_customers",
|
|
1402
|
+
description: "Read customers, segments, and companies",
|
|
1403
|
+
},
|
|
1404
|
+
{
|
|
1405
|
+
scope: "write_customers",
|
|
1406
|
+
description: "Create and update customers and segments",
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
scope: "read_inventory",
|
|
1410
|
+
description: "Read inventory levels and items",
|
|
1411
|
+
},
|
|
1412
|
+
{
|
|
1413
|
+
scope: "write_inventory",
|
|
1414
|
+
description: "Adjust inventory levels and items",
|
|
1415
|
+
},
|
|
1416
|
+
{ scope: "read_locations", description: "Read store locations" },
|
|
1417
|
+
{ scope: "read_fulfillments", description: "Read fulfillment services" },
|
|
1418
|
+
{
|
|
1419
|
+
scope: "write_fulfillments",
|
|
1420
|
+
description: "Create and update fulfillment services",
|
|
1421
|
+
},
|
|
1422
|
+
{ scope: "read_discounts", description: "Read discounts" },
|
|
1423
|
+
{ scope: "write_discounts", description: "Create and update discounts" },
|
|
1424
|
+
{ scope: "read_price_rules", description: "Read price rules" },
|
|
1425
|
+
{
|
|
1426
|
+
scope: "write_price_rules",
|
|
1427
|
+
description: "Create and update price rules",
|
|
1428
|
+
},
|
|
1429
|
+
{ scope: "read_files", description: "Read files uploaded to the store" },
|
|
1430
|
+
{ scope: "write_files", description: "Upload and update files" },
|
|
1431
|
+
{ scope: "read_gift_cards", description: "Read gift cards" },
|
|
1432
|
+
{
|
|
1433
|
+
scope: "write_gift_cards",
|
|
1434
|
+
description: "Create and update gift cards",
|
|
1435
|
+
},
|
|
1436
|
+
{ scope: "read_returns", description: "Read returns" },
|
|
1437
|
+
{ scope: "write_returns", description: "Create and update returns" },
|
|
1438
|
+
{ scope: "read_markets", description: "Read markets" },
|
|
1439
|
+
{ scope: "read_locales", description: "Read shop locales" },
|
|
1440
|
+
{
|
|
1441
|
+
scope: "read_shipping",
|
|
1442
|
+
description: "Read shipping and delivery carrier services",
|
|
1443
|
+
},
|
|
1444
|
+
{ scope: "read_analytics", description: "Read analytics and reports" },
|
|
1445
|
+
{
|
|
1446
|
+
scope: "read_marketing_events",
|
|
1447
|
+
description: "Read marketing events and activities",
|
|
1448
|
+
},
|
|
1449
|
+
{ scope: "read_order_edits", description: "Read order edits" },
|
|
1450
|
+
{
|
|
1451
|
+
scope: "write_order_edits",
|
|
1452
|
+
description: "Create and apply order edits",
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
scope: "read_metaobjects",
|
|
1456
|
+
description: "Read metaobjects and their definitions",
|
|
1457
|
+
},
|
|
1458
|
+
{
|
|
1459
|
+
scope: "write_metaobjects",
|
|
1460
|
+
description: "Create and update metaobjects",
|
|
1461
|
+
},
|
|
1462
|
+
{ scope: "read_translations", description: "Read translated content" },
|
|
1463
|
+
{
|
|
1464
|
+
scope: "read_shopify_payments_payouts",
|
|
1465
|
+
description: "Read Shopify Payments payouts and balance",
|
|
1466
|
+
},
|
|
1467
|
+
{
|
|
1468
|
+
scope: "read_shopify_payments_disputes",
|
|
1469
|
+
description: "Read Shopify Payments disputes",
|
|
1470
|
+
},
|
|
1471
|
+
],
|
|
1472
|
+
loopbackPort: 17341,
|
|
1473
|
+
managedServiceConfigKey: "shopify-oauth",
|
|
1474
|
+
injectionTemplates: [
|
|
1475
|
+
{
|
|
1476
|
+
hostPattern: "*.myshopify.com",
|
|
1477
|
+
injectionType: "header",
|
|
1478
|
+
headerName: "X-Shopify-Access-Token",
|
|
1479
|
+
valuePrefix: "",
|
|
1480
|
+
},
|
|
1481
|
+
],
|
|
1482
|
+
appType: "App",
|
|
1483
|
+
setupNotes: [
|
|
1484
|
+
"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.",
|
|
1485
|
+
"The Admin API authenticates with the X-Shopify-Access-Token header rather than an Authorization Bearer header.",
|
|
1486
|
+
],
|
|
1487
|
+
// The Admin API's shop endpoint nests its payload under "shop"; the
|
|
1488
|
+
// myshopify domain is the stable, human-recognisable handle.
|
|
1489
|
+
identityUrl: "https://{tenant_host}/admin/api/2026-07/shop.json",
|
|
1490
|
+
identityResponsePaths: ["shop.myshopify_domain", "shop.name"],
|
|
1491
|
+
// Gated like monday/figma/stripe-link: the platform side and the
|
|
1492
|
+
// shop-domain input in the clients land separately, and until both are
|
|
1493
|
+
// in place a visible Shopify tile would offer a connect flow that
|
|
1494
|
+
// cannot complete.
|
|
1495
|
+
featureFlag: "shopify-oauth",
|
|
1496
|
+
},
|
|
1332
1497
|
};
|
|
1333
1498
|
|
|
1334
1499
|
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
|
|