@vellumai/assistant 0.12.1-dev.202609141913.5e16607 → 0.12.1-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +0 -4
- package/ARCHITECTURE.md +12 -11
- package/docs/architecture/turn-actor.md +8 -15
- package/docs/guardian-request-flow.md +0 -16
- package/openapi.yaml +49 -291
- package/package.json +1 -1
- package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
- package/src/__tests__/app-compiler.test.ts +0 -6
- package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
- package/src/__tests__/app-dir-path-guard.test.ts +3 -1
- package/src/__tests__/app-source-watcher.test.ts +218 -0
- package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
- package/src/__tests__/computer-use-tools.test.ts +5 -17
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +29 -28
- package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
- package/src/__tests__/config-watcher.test.ts +8 -23
- 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 +0 -26
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
- package/src/__tests__/conversation-queue.test.ts +207 -48
- package/src/__tests__/conversation-retry-discard.test.ts +1 -54
- package/src/__tests__/conversation-skill-tools.test.ts +0 -27
- package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
- package/src/__tests__/conversation-title-service.test.ts +10 -14
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
- package/src/__tests__/credential-record-retire.test.ts +1 -171
- package/src/__tests__/credential-routes.test.ts +3 -212
- package/src/__tests__/credential-security-invariants.test.ts +2 -4
- package/src/__tests__/cu-unified-flow.test.ts +2 -8
- package/src/__tests__/document-sync-tags.test.ts +0 -25
- package/src/__tests__/drain-kick-guard.test.ts +2 -0
- package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
- package/src/__tests__/host-bash-proxy.test.ts +45 -26
- package/src/__tests__/host-browser-proxy.test.ts +17 -6
- package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
- package/src/__tests__/host-file-proxy.test.ts +23 -11
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
- package/src/__tests__/llm-catalog-parity.test.ts +0 -25
- package/src/__tests__/mcp-auth-routes.test.ts +9 -6
- package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
- package/src/__tests__/mcp-health-check.test.ts +11 -8
- package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
- package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
- package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
- package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
- package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
- package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
- package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
- package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
- package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +548 -355
- package/src/__tests__/model-intents.test.ts +0 -3
- package/src/__tests__/notification-vellum-adapter.test.ts +2 -85
- package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
- package/src/__tests__/platform-callback-registration.test.ts +16 -8
- package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
- package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
- package/src/__tests__/script-proxy-certs.test.ts +0 -35
- package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/speaker-identification.test.ts +56 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
- package/src/__tests__/subagent-tools.test.ts +2 -3
- package/src/__tests__/telephony-tts-guard.test.ts +3 -38
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
- package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
- package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
- package/src/__tests__/workspace-git-service.test.ts +0 -26
- package/src/acp/__tests__/agent-process.test.ts +4 -258
- package/src/acp/__tests__/auth-required.test.ts +0 -96
- package/src/acp/__tests__/client-handler.test.ts +2 -90
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
- package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
- package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
- package/src/acp/__tests__/session-manager.test.ts +4 -895
- package/src/acp/agent-process.test.ts +1 -4
- package/src/acp/agent-process.ts +9 -94
- package/src/acp/auth-required.ts +1 -50
- package/src/acp/auto-install.test.ts +7 -9
- package/src/acp/client-handler.ts +3 -16
- package/src/acp/resolve-agent.test.ts +6 -220
- package/src/acp/resolve-agent.ts +23 -88
- package/src/acp/session-manager.test.ts +3 -196
- package/src/acp/session-manager.ts +18 -441
- package/src/acp/types.ts +5 -50
- package/src/api/events/app-files-changed.ts +3 -4
- package/src/api/events/notification-intent.ts +0 -2
- package/src/api/index.ts +0 -6
- package/src/apps/app-store.ts +1 -1
- package/src/bundler/app-compiler.ts +0 -15
- package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
- package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
- package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
- package/src/calls/call-constants.ts +4 -24
- package/src/calls/call-controller.ts +199 -499
- package/src/calls/call-transport.ts +0 -16
- package/src/calls/media-stream-output.ts +0 -32
- package/src/calls/media-stream-server.ts +30 -82
- package/src/calls/media-stream-stt-session.ts +0 -15
- package/src/calls/resolve-call-tts-provider.ts +2 -33
- package/src/calls/speaker-identification.ts +233 -0
- package/src/calls/tts-call-strategy.ts +5 -9
- package/src/calls/types.ts +0 -2
- package/src/calls/voice-control-protocol.ts +21 -53
- package/src/calls/voice-session-bridge.ts +46 -59
- package/src/calls/voice-triage-escalate.ts +56 -175
- package/src/cli/commands/apps.help.ts +13 -67
- package/src/cli/commands/apps.ts +0 -183
- package/src/cli/commands/bash.help.ts +13 -8
- package/src/cli/commands/bash.ts +25 -7
- package/src/cli/commands/channels/index.help.ts +2 -70
- package/src/cli/commands/channels/index.ts +3 -16
- package/src/cli/commands/credentials.help.ts +2 -6
- 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 +1 -5
- package/src/cli/commands/roadmap.ts +1 -1
- package/src/cli/lib/bundled-marketplace.json +90 -103
- package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
- package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
- package/src/config/__tests__/platform-rehydration.test.ts +9 -99
- package/src/config/acp-defaults.test.ts +3 -13
- package/src/config/acp-defaults.ts +6 -23
- package/src/config/acp-schema.ts +2 -30
- package/src/config/bundled-skills/acp/SKILL.md +14 -22
- package/src/config/bundled-skills/acp/TOOLS.json +1 -5
- package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
- 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 +139 -67
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +4 -3
- package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
- package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
- 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 +12 -24
- package/src/config/loader.ts +0 -1
- package/src/config/memory-v3-gate.test.ts +0 -31
- package/src/config/memory-v3-gate.ts +16 -20
- package/src/config/platform-rehydration.ts +27 -11
- package/src/config/schema.ts +2 -2
- package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
- package/src/config/schemas/calls.ts +28 -1
- package/src/config/schemas/live-voice.ts +173 -1
- package/src/config/schemas/mcp.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +0 -10
- package/src/config/schemas/services.ts +0 -8
- package/src/config/schemas/skills.ts +14 -0
- package/src/credential-execution/process-manager.test.ts +19 -18
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
- package/src/daemon/app-source-watcher.ts +218 -0
- package/src/daemon/config-watcher.ts +194 -13
- package/src/daemon/conversation-process.ts +64 -35
- package/src/daemon/conversation-skill-tools.ts +31 -13
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +8 -10
- package/src/daemon/conversation-tool-setup.ts +43 -37
- package/src/daemon/conversation.ts +3 -0
- package/src/daemon/host-bash-proxy.ts +12 -8
- package/src/daemon/host-browser-proxy.ts +1 -15
- package/src/daemon/host-file-proxy.ts +10 -8
- package/src/daemon/host-transfer-proxy.ts +18 -14
- package/src/daemon/lifecycle.ts +5 -0
- package/src/daemon/mcp-reload-service.ts +5 -5
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/orphan-reaper.ts +1 -1
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/shutdown-handlers.ts +9 -1
- package/src/daemon/skill-memory-refresh.ts +0 -64
- package/src/daemon/tool-side-effects.ts +18 -7
- package/src/home/__tests__/feed-writer.test.ts +0 -22
- package/src/home/feed-writer.ts +2 -11
- package/src/hooks/types.ts +0 -33
- package/src/inbound/platform-callback-registration.ts +5 -4
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
- 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/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
- package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
- package/src/live-voice/live-voice-session.ts +693 -213
- package/src/{calls → live-voice}/progress-narration.ts +2 -2
- package/src/live-voice/protocol.ts +2 -0
- package/src/mcp/__tests__/effective-config.test.ts +2 -2
- package/src/mcp/effective-config.ts +3 -3
- package/src/mcp/mcp-header-store.ts +45 -29
- package/src/mcp/startup.ts +4 -8
- package/src/messaging/provider.ts +3 -10
- package/src/messaging/providers/callback-routing.ts +0 -18
- package/src/messaging/providers/channel-transport.ts +0 -56
- package/src/messaging/providers/discord/transport.ts +0 -17
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
- package/src/messaging/providers/slack/adapter.ts +44 -7
- package/src/messaging/providers/slack/transport.ts +0 -16
- package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
- package/src/messaging/providers/telegram-bot/client.ts +26 -0
- package/src/messaging/providers/telegram-bot/transport.ts +0 -20
- package/src/messaging/providers/whatsapp/adapter.ts +48 -1
- package/src/messaging/providers/whatsapp/client.ts +29 -0
- package/src/messaging/providers/whatsapp/transport.ts +0 -18
- package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
- package/src/notifications/__tests__/guardian-feed-projection.test.ts +2 -158
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
- package/src/notifications/__tests__/schedule-result-producer.test.ts +3 -99
- package/src/notifications/adapters/macos.ts +0 -3
- package/src/notifications/assistant-reply-producer.ts +3 -8
- package/src/notifications/conversation-pairing.ts +16 -36
- package/src/notifications/delivered-post-record.ts +1 -11
- package/src/notifications/guardian-feed-projection.ts +5 -125
- package/src/notifications/home-feed-side-effect.ts +7 -55
- package/src/notifications/schedule-result-producer.ts +22 -66
- package/src/oauth/__tests__/seed-providers-managed.test.ts +0 -54
- package/src/oauth/byo-connection.test.ts +0 -45
- package/src/oauth/byo-connection.ts +6 -36
- package/src/oauth/connection-resolver.test.ts +0 -73
- package/src/oauth/connection-resolver.ts +2 -95
- package/src/oauth/seed-providers.ts +0 -165
- package/src/outbound-proxy/certs.ts +5 -3
- package/src/permissions/checker.test.ts +6 -11
- package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
- package/src/persistence/conversation-crud.ts +63 -71
- package/src/persistence/conversation-lineage.ts +4 -12
- package/src/persistence/conversation-title-service.ts +26 -9
- 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-reads.ts +0 -30
- package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
- package/src/persistence/schema/memory-core.ts +0 -5
- package/src/platform/client.test.ts +2 -4
- package/src/platform/client.ts +10 -2
- package/src/plugin-api/constants.ts +0 -2
- package/src/plugin-api/index.ts +0 -1
- package/src/plugin-api/types.ts +0 -2
- package/src/plugins/defaults/index.ts +0 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
- package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
- package/src/plugins/defaults/memory/hooks/init.ts +0 -10
- package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
- package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
- package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
- package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
- package/src/plugins/defaults/memory/startup.ts +1 -6
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
- package/src/plugins/defaults/memory/worker.ts +0 -6
- package/src/plugins/mcp-servers.ts +75 -15
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
- package/src/providers/gemini/client.ts +23 -9
- package/src/providers/inference/auth.ts +3 -2
- package/src/providers/inference/connection-availability.ts +8 -27
- package/src/providers/inference/resolve-auth.ts +4 -22
- package/src/providers/model-catalog.ts +0 -34
- package/src/providers/model-intents.ts +5 -10
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
- package/src/providers/openai/chat-completions-provider.ts +78 -192
- package/src/providers/openai/codex-models.ts +4 -0
- package/src/runtime/AGENTS.md +0 -2
- package/src/runtime/auth/same-actor.ts +3 -38
- package/src/runtime/http-server.ts +151 -160
- package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
- package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
- package/src/runtime/routes/acp-routes.test.ts +0 -15
- package/src/runtime/routes/acp-routes.ts +9 -72
- package/src/runtime/routes/app-management-routes.ts +0 -73
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +3 -14
- package/src/runtime/routes/conversation-query-routes.ts +0 -40
- package/src/runtime/routes/credential-routes.ts +10 -19
- package/src/runtime/routes/debug-bash-routes.ts +173 -0
- package/src/runtime/routes/diagnostics-routes.ts +3 -55
- package/src/runtime/routes/index.ts +2 -4
- package/src/runtime/routes/log-export-routes.ts +0 -2
- package/src/runtime/routes/mcp-auth-routes.ts +47 -39
- package/src/runtime/routes/migration-routes.ts +20 -6
- package/src/runtime/routes/platform-routes.ts +15 -18
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
- package/src/runtime/services/conversation-serializer.ts +3 -16
- package/src/runtime/sync/resource-sync-events.ts +1 -2
- package/src/schedule/worker.ts +1 -1
- package/src/security/ces-rpc-record-backend.ts +0 -7
- package/src/subagent/consult-context.ts +25 -12
- package/src/tools/acp/list-agents.test.ts +1 -3
- package/src/tools/acp/spawn.test.ts +11 -146
- package/src/tools/acp/spawn.ts +3 -21
- package/src/tools/acp/status.ts +3 -40
- package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
- package/src/tools/capability-offer.test.ts +2 -22
- package/src/tools/capability-offer.ts +1 -16
- package/src/tools/computer-use/definitions.ts +2 -4
- package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
- package/src/tools/credentials/metadata-store.ts +0 -100
- package/src/tools/host-filesystem/edit.test.ts +1 -2
- package/src/tools/host-filesystem/edit.ts +2 -2
- package/src/tools/host-filesystem/read.test.ts +1 -2
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/transfer.test.ts +1 -2
- package/src/tools/host-filesystem/transfer.ts +2 -2
- package/src/tools/host-filesystem/write.test.ts +1 -2
- package/src/tools/host-filesystem/write.ts +2 -2
- package/src/tools/host-terminal/host-shell.test.ts +0 -16
- package/src/tools/host-terminal/host-shell.ts +20 -4
- package/src/tools/policy-context.ts +7 -6
- package/src/tools/subagent/spawn.ts +8 -5
- package/src/tools/watch/watch-retro-report.ts +8 -0
- package/src/util/__tests__/language-subtag.test.ts +1 -23
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/language-subtag.ts +0 -16
- package/src/util/platform.ts +0 -8
- package/src/workspace/git-service.ts +54 -5
- package/src/workspace/migrations/registry.ts +0 -6
- package/scripts/smoke-desktop-window-theme.ts +0 -186
- package/src/__tests__/git-porcelain.test.ts +0 -47
- package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
- package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
- package/src/__tests__/resolve-app.test.ts +0 -135
- package/src/__tests__/service-account-token.test.ts +0 -247
- package/src/__tests__/source-fingerprint.test.ts +0 -184
- package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
- package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
- package/src/acp/model-config.test.ts +0 -166
- package/src/acp/model-config.ts +0 -138
- package/src/api/events/acp-session-model-update.test.ts +0 -88
- package/src/api/events/acp-session-model-update.ts +0 -46
- package/src/apps/resolve-app.ts +0 -81
- package/src/apps/source-fingerprint.ts +0 -266
- package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
- package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
- package/src/calls/barge-in-guard.ts +0 -118
- package/src/calls/voice-leg-coordinator.ts +0 -189
- package/src/calls/voice-progress-cadence.ts +0 -423
- package/src/cli/commands/__tests__/apps.test.ts +0 -245
- package/src/cli/commands/__tests__/bash.test.ts +0 -53
- package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
- package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
- package/src/cli/commands/channels/send.ts +0 -128
- package/src/config/__tests__/platform-identity.test.ts +0 -255
- package/src/config/acp-agent-write.ts +0 -43
- package/src/config/acp-schema.test.ts +0 -81
- package/src/config/platform-identity.ts +0 -201
- package/src/config/schemas/__tests__/voice.test.ts +0 -148
- package/src/config/schemas/voice.ts +0 -150
- package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
- package/src/daemon/app-change-notify.ts +0 -45
- package/src/desktop/__tests__/fake-desktop.ts +0 -119
- package/src/desktop/desktop-chrome-policy.test.ts +0 -71
- package/src/desktop/desktop-chrome-policy.ts +0 -42
- package/src/desktop/desktop-dependencies.test.ts +0 -102
- package/src/desktop/desktop-dependencies.ts +0 -306
- package/src/desktop/desktop-feature.test.ts +0 -18
- package/src/desktop/desktop-feature.ts +0 -19
- package/src/desktop/desktop-panel-config.test.ts +0 -135
- package/src/desktop/desktop-panel-config.ts +0 -149
- package/src/desktop/desktop-session-manager.test.ts +0 -627
- package/src/desktop/desktop-session-manager.ts +0 -814
- package/src/desktop/desktop-stream-bridge.test.ts +0 -395
- package/src/desktop/desktop-stream-bridge.ts +0 -214
- package/src/desktop/desktop-wallpaper.test.ts +0 -191
- package/src/desktop/desktop-wallpaper.ts +0 -113
- package/src/desktop/desktop-window-theme.ts +0 -170
- package/src/i18n/AGENTS.md +0 -22
- package/src/i18n/__tests__/i18n.test.ts +0 -108
- package/src/i18n/index.ts +0 -16
- package/src/i18n/locales.ts +0 -93
- package/src/i18n/messages.ts +0 -61
- package/src/i18n/title.ts +0 -25
- package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
- package/src/mcp/spec-schema.ts +0 -111
- package/src/mcp/workspace-mcp-config.ts +0 -188
- package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
- package/src/persistence/conversation-title-placeholders.ts +0 -23
- package/src/persistence/message-cursor.ts +0 -78
- package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
- package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
- package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
- package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
- package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
- package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
- package/src/providers/gemini-thought-signature.test.ts +0 -63
- package/src/providers/gemini-thought-signature.ts +0 -44
- package/src/providers/inference/service-account-token.ts +0 -248
- package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
- package/src/providers/openai/google-thought-signature.ts +0 -320
- package/src/runtime/__tests__/channel-send.test.ts +0 -443
- package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
- package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
- package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
- package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
- package/src/runtime/channel-send.ts +0 -316
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
- package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
- package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
- package/src/runtime/routes/channel-send-routes.ts +0 -85
- package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
- package/src/runtime/routes/desktop-setup-routes.ts +0 -35
- package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
- package/src/security/ces-http-record-backend.ts +0 -120
- package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
- package/src/skills/workspace-skill-md-signature.ts +0 -50
- package/src/tools/acp/status.test.ts +0 -94
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -57
- package/src/tools/terminal/sanitized-bash.ts +0 -105
- package/src/util/ca-bundle.ts +0 -13
- package/src/workspace/git-porcelain.ts +0 -66
- package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
- package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
- package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
- package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
- /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
package/src/i18n/locales.ts
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Locales the daemon can resolve user-facing copy into.
|
|
3
|
-
*
|
|
4
|
-
* Keep this set aligned with `clients/web/src/i18n/supported-locales.ts`.
|
|
5
|
-
* A locale that exists only here cannot be requested by the web app; a
|
|
6
|
-
* locale that exists only there cannot be resolved for CLI or HTTP
|
|
7
|
-
* consumers that go through this module.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export const DEFAULT_LOCALE = "en";
|
|
11
|
-
|
|
12
|
-
export const SUPPORTED_LOCALES = ["en", "es", "ru", "zh", "zh-TW"] as const;
|
|
13
|
-
|
|
14
|
-
export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
|
|
15
|
-
|
|
16
|
-
export function isSupportedLocale(value: unknown): value is SupportedLocale {
|
|
17
|
-
return (
|
|
18
|
-
typeof value === "string" &&
|
|
19
|
-
(SUPPORTED_LOCALES as readonly string[]).includes(value)
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Pick the best shipped locale for an ordered list of preferred BCP 47 tags.
|
|
25
|
-
*
|
|
26
|
-
* Full tag first, then the primary language subtag, so `es-MX` resolves to
|
|
27
|
-
* `es`. `zh-Hant` / `zh-HK` / `zh-MO` map to `zh-TW`.
|
|
28
|
-
*/
|
|
29
|
-
export function negotiateLocale(preferred: readonly string[]): SupportedLocale {
|
|
30
|
-
for (const tag of preferred) {
|
|
31
|
-
const normalized = tag.trim();
|
|
32
|
-
if (normalized === "") {
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
const exact = SUPPORTED_LOCALES.find(
|
|
36
|
-
(locale) => locale.toLowerCase() === normalized.toLowerCase(),
|
|
37
|
-
);
|
|
38
|
-
if (exact) {
|
|
39
|
-
return exact;
|
|
40
|
-
}
|
|
41
|
-
const lower = normalized.toLowerCase();
|
|
42
|
-
if (
|
|
43
|
-
lower === "zh-hant" ||
|
|
44
|
-
lower.startsWith("zh-hant-") ||
|
|
45
|
-
lower === "zh-hk" ||
|
|
46
|
-
lower === "zh-mo"
|
|
47
|
-
) {
|
|
48
|
-
return "zh-TW";
|
|
49
|
-
}
|
|
50
|
-
const base = normalized.split("-")[0]?.toLowerCase();
|
|
51
|
-
const baseMatched = SUPPORTED_LOCALES.find(
|
|
52
|
-
(locale) => locale.toLowerCase() === base,
|
|
53
|
-
);
|
|
54
|
-
if (baseMatched) {
|
|
55
|
-
return baseMatched;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return DEFAULT_LOCALE;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Parse an `Accept-Language` header into preference order and negotiate.
|
|
63
|
-
*
|
|
64
|
-
* Quality values are honored; the header is a hint, not a required input.
|
|
65
|
-
* Missing or empty headers resolve to {@link DEFAULT_LOCALE}.
|
|
66
|
-
*/
|
|
67
|
-
export function localeFromAcceptLanguage(
|
|
68
|
-
header: string | null | undefined,
|
|
69
|
-
): SupportedLocale {
|
|
70
|
-
if (header == null || header.trim() === "") {
|
|
71
|
-
return DEFAULT_LOCALE;
|
|
72
|
-
}
|
|
73
|
-
const tags = header
|
|
74
|
-
.split(",")
|
|
75
|
-
.map((part) => {
|
|
76
|
-
const [tag, ...params] = part.trim().split(";");
|
|
77
|
-
let quality = 1;
|
|
78
|
-
for (const param of params) {
|
|
79
|
-
const [name, value] = param.trim().split("=");
|
|
80
|
-
if (name === "q" && value !== undefined) {
|
|
81
|
-
const parsed = Number.parseFloat(value);
|
|
82
|
-
if (Number.isFinite(parsed)) {
|
|
83
|
-
quality = parsed;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return { tag: tag?.trim() ?? "", quality };
|
|
88
|
-
})
|
|
89
|
-
.filter((entry) => entry.tag.length > 0)
|
|
90
|
-
.sort((a, b) => b.quality - a.quality)
|
|
91
|
-
.map((entry) => entry.tag);
|
|
92
|
-
return negotiateLocale(tags);
|
|
93
|
-
}
|
package/src/i18n/messages.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Daemon message catalog.
|
|
3
|
-
*
|
|
4
|
-
* Keys are the stable identity of a hardcoded constant. English is the
|
|
5
|
-
* source language. Add a key here, then add the same key to every locale
|
|
6
|
-
* catalog. A key present in a translated catalog but missing from English
|
|
7
|
-
* is a test failure.
|
|
8
|
-
*
|
|
9
|
-
* Persist the key when a column holds a system constant. Never persist a
|
|
10
|
-
* translated string, and never treat a stored display string as a key:
|
|
11
|
-
* a user title may be in any language.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
DEFAULT_LOCALE,
|
|
16
|
-
type SupportedLocale,
|
|
17
|
-
} from "./locales.js";
|
|
18
|
-
|
|
19
|
-
export const MESSAGE_KEYS = {
|
|
20
|
-
CONVERSATION_TITLE_GENERATING: "conversation.title.generating",
|
|
21
|
-
CONVERSATION_TITLE_UNTITLED: "conversation.title.untitled",
|
|
22
|
-
} as const;
|
|
23
|
-
|
|
24
|
-
export type MessageKey = (typeof MESSAGE_KEYS)[keyof typeof MESSAGE_KEYS];
|
|
25
|
-
|
|
26
|
-
export const MESSAGE_CATALOGS: Record<
|
|
27
|
-
SupportedLocale,
|
|
28
|
-
Record<MessageKey, string>
|
|
29
|
-
> = {
|
|
30
|
-
en: {
|
|
31
|
-
"conversation.title.generating": "Generating title...",
|
|
32
|
-
"conversation.title.untitled": "Untitled Conversation",
|
|
33
|
-
},
|
|
34
|
-
es: {
|
|
35
|
-
"conversation.title.generating": "Generando título...",
|
|
36
|
-
"conversation.title.untitled": "Sin título",
|
|
37
|
-
},
|
|
38
|
-
ru: {
|
|
39
|
-
"conversation.title.generating": "Создание названия...",
|
|
40
|
-
"conversation.title.untitled": "Без названия",
|
|
41
|
-
},
|
|
42
|
-
zh: {
|
|
43
|
-
"conversation.title.generating": "标题生成中...",
|
|
44
|
-
"conversation.title.untitled": "无标题",
|
|
45
|
-
},
|
|
46
|
-
"zh-TW": {
|
|
47
|
-
"conversation.title.generating": "標題產生中...",
|
|
48
|
-
"conversation.title.untitled": "未命名",
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export function t(
|
|
53
|
-
key: MessageKey,
|
|
54
|
-
locale: SupportedLocale = DEFAULT_LOCALE,
|
|
55
|
-
): string {
|
|
56
|
-
return MESSAGE_CATALOGS[locale][key] ?? MESSAGE_CATALOGS[DEFAULT_LOCALE][key];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function isMessageKey(value: string): value is MessageKey {
|
|
60
|
-
return (Object.values(MESSAGE_KEYS) as string[]).includes(value);
|
|
61
|
-
}
|
package/src/i18n/title.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve a conversation title for a locale.
|
|
3
|
-
*
|
|
4
|
-
* A stored message key (or an empty title) is a hardcoded constant and
|
|
5
|
-
* resolves through the catalog. Any other stored string is user or model
|
|
6
|
-
* copy and passes through, including English placeholders written before
|
|
7
|
-
* keys were persisted.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { DEFAULT_LOCALE, type SupportedLocale } from "./locales.js";
|
|
11
|
-
import { isMessageKey, MESSAGE_KEYS, t } from "./messages.js";
|
|
12
|
-
|
|
13
|
-
export function resolveConversationTitle(
|
|
14
|
-
title: string | null | undefined,
|
|
15
|
-
locale: SupportedLocale = DEFAULT_LOCALE,
|
|
16
|
-
): string {
|
|
17
|
-
const trimmed = title?.trim() ?? "";
|
|
18
|
-
if (trimmed === "") {
|
|
19
|
-
return t(MESSAGE_KEYS.CONVERSATION_TITLE_UNTITLED, locale);
|
|
20
|
-
}
|
|
21
|
-
if (isMessageKey(trimmed)) {
|
|
22
|
-
return t(trimmed, locale);
|
|
23
|
-
}
|
|
24
|
-
return trimmed;
|
|
25
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { beforeEach, describe, expect, test } from "bun:test";
|
|
4
|
-
|
|
5
|
-
import { AGENT_PLUGINS_MCP_SCHEMA_URL } from "../spec-schema.js";
|
|
6
|
-
import {
|
|
7
|
-
loadWorkspaceMcpConfig,
|
|
8
|
-
overlayWorkspaceMcpForConfigRead,
|
|
9
|
-
readWorkspaceMcpFile,
|
|
10
|
-
saveWorkspaceMcpConfig,
|
|
11
|
-
} from "../workspace-mcp-config.js";
|
|
12
|
-
|
|
13
|
-
function mcpPath(): string {
|
|
14
|
-
return join(process.env.VELLUM_WORKSPACE_DIR!, "mcp.json");
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
describe("workspace mcp.json", () => {
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
mkdirSync(process.env.VELLUM_WORKSPACE_DIR!, { recursive: true });
|
|
20
|
-
rmSync(mcpPath(), { force: true });
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test("missing file is an empty server map", () => {
|
|
24
|
-
expect(loadWorkspaceMcpConfig()).toEqual({ servers: {} });
|
|
25
|
-
expect(readWorkspaceMcpFile().fileState).toBe("missing");
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test("round-trips a spec document without wrapping transport", () => {
|
|
29
|
-
saveWorkspaceMcpConfig({
|
|
30
|
-
servers: {
|
|
31
|
-
remote: {
|
|
32
|
-
transport: {
|
|
33
|
-
type: "streamable-http",
|
|
34
|
-
url: "https://example.com/mcp",
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
local: {
|
|
38
|
-
transport: {
|
|
39
|
-
type: "stdio",
|
|
40
|
-
command: "npx",
|
|
41
|
-
args: ["-y", "srv"],
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
expect(JSON.parse(readFileSync(mcpPath(), "utf8"))).toEqual({
|
|
48
|
-
$schema: AGENT_PLUGINS_MCP_SCHEMA_URL,
|
|
49
|
-
mcpServers: {
|
|
50
|
-
remote: {
|
|
51
|
-
type: "streamable-http",
|
|
52
|
-
url: "https://example.com/mcp",
|
|
53
|
-
},
|
|
54
|
-
local: {
|
|
55
|
-
type: "stdio",
|
|
56
|
-
command: "npx",
|
|
57
|
-
args: ["-y", "srv"],
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
expect(loadWorkspaceMcpConfig()).toEqual({
|
|
62
|
-
servers: {
|
|
63
|
-
remote: {
|
|
64
|
-
transport: {
|
|
65
|
-
type: "streamable-http",
|
|
66
|
-
url: "https://example.com/mcp",
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
local: {
|
|
70
|
-
transport: {
|
|
71
|
-
type: "stdio",
|
|
72
|
-
command: "npx",
|
|
73
|
-
args: ["-y", "srv"],
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("does not persist transport headers", () => {
|
|
81
|
-
saveWorkspaceMcpConfig({
|
|
82
|
-
servers: {
|
|
83
|
-
remote: {
|
|
84
|
-
transport: {
|
|
85
|
-
type: "streamable-http",
|
|
86
|
-
url: "https://example.com/mcp",
|
|
87
|
-
headers: { Authorization: "Bearer secret" },
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const onDisk = readFileSync(mcpPath(), "utf8");
|
|
94
|
-
expect(onDisk).not.toContain("secret");
|
|
95
|
-
expect(loadWorkspaceMcpConfig().servers.remote?.transport).toEqual({
|
|
96
|
-
type: "streamable-http",
|
|
97
|
-
url: "https://example.com/mcp",
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test("invalid file does not throw on read and refuses a later write", () => {
|
|
102
|
-
mkdirSync(process.env.VELLUM_WORKSPACE_DIR!, { recursive: true });
|
|
103
|
-
writeFileSync(mcpPath(), "{ not json");
|
|
104
|
-
|
|
105
|
-
expect(loadWorkspaceMcpConfig()).toEqual({ servers: {} });
|
|
106
|
-
expect(readWorkspaceMcpFile().fileState).toBe("invalid");
|
|
107
|
-
expect(() => saveWorkspaceMcpConfig({ servers: {} })).toThrow(/invalid JSON/);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test("overlay projects transport-only servers for config reads", () => {
|
|
111
|
-
saveWorkspaceMcpConfig({
|
|
112
|
-
servers: {
|
|
113
|
-
remote: {
|
|
114
|
-
transport: {
|
|
115
|
-
type: "streamable-http",
|
|
116
|
-
url: "https://example.com/mcp",
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
const config: Record<string, unknown> = { llm: { activeProfile: "balanced" } };
|
|
123
|
-
overlayWorkspaceMcpForConfigRead(config);
|
|
124
|
-
expect(config.mcp).toEqual({
|
|
125
|
-
servers: {
|
|
126
|
-
remote: {
|
|
127
|
-
transport: {
|
|
128
|
-
type: "streamable-http",
|
|
129
|
-
url: "https://example.com/mcp",
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
});
|
package/src/mcp/spec-schema.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Plugins 1.0.0 `mcp.json` wire schema and projections onto the
|
|
3
|
-
* assistant's in-memory `McpTransport` union.
|
|
4
|
-
*
|
|
5
|
-
* Workspace `/workspace/mcp.json` and each plugin's root `mcp.json` share
|
|
6
|
-
* this document shape. Origin (`workspace` vs `plugin`) is resolved from
|
|
7
|
-
* which file was read, never from a field in the file.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { z } from "zod";
|
|
11
|
-
|
|
12
|
-
import type { McpTransport } from "../config/schemas/mcp.js";
|
|
13
|
-
|
|
14
|
-
/** Canonical `$schema` value for an Agent Plugins 1.0.0 MCP document. */
|
|
15
|
-
export const AGENT_PLUGINS_MCP_SCHEMA_URL =
|
|
16
|
-
"https://agent-plugins.org/schemas/1.0.0/mcp.schema.json";
|
|
17
|
-
|
|
18
|
-
const SpecStdioServerSchema = z.object({
|
|
19
|
-
type: z.literal("stdio"),
|
|
20
|
-
command: z.string().min(1),
|
|
21
|
-
args: z.array(z.string()).optional(),
|
|
22
|
-
env: z.record(z.string(), z.string()).optional(),
|
|
23
|
-
cwd: z.string().optional(),
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Remote MCP entry. Agent Plugins 1.0.0 requires `type` and names no
|
|
28
|
-
* default. MCP's current remote transport is Streamable HTTP, so this
|
|
29
|
-
* host fills omitted `type` and the Claude-style `http` alias as
|
|
30
|
-
* `streamable-http`. `sse` stays explicit.
|
|
31
|
-
*/
|
|
32
|
-
const SpecHttpServerSchema = z.object({
|
|
33
|
-
type: z
|
|
34
|
-
.union([
|
|
35
|
-
z.literal("streamable-http"),
|
|
36
|
-
z.literal("sse"),
|
|
37
|
-
z.literal("http").transform(() => "streamable-http" as const),
|
|
38
|
-
])
|
|
39
|
-
.default("streamable-http"),
|
|
40
|
-
url: z.string().min(1),
|
|
41
|
-
headers: z.record(z.string(), z.string()).optional(),
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
export const SpecMcpServerSchema = z.union([
|
|
45
|
-
SpecStdioServerSchema,
|
|
46
|
-
SpecHttpServerSchema,
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
export const SpecMcpDocumentSchema = z.object({
|
|
50
|
-
$schema: z.string().optional(),
|
|
51
|
-
mcpServers: z.record(z.string(), z.unknown()),
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
export type SpecMcpServer = z.infer<typeof SpecMcpServerSchema>;
|
|
55
|
-
export type SpecMcpDocument = z.infer<typeof SpecMcpDocumentSchema>;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Project one spec-shaped entry onto the assistant's transport union. The
|
|
59
|
-
* two vocabularies already agree on type names and required fields, so this
|
|
60
|
-
* is a field copy plus an optional expander for plugin path variables.
|
|
61
|
-
*/
|
|
62
|
-
export function projectSpecServerToTransport(
|
|
63
|
-
entry: SpecMcpServer,
|
|
64
|
-
expand?: (value: string) => string,
|
|
65
|
-
): McpTransport {
|
|
66
|
-
if (entry.type === "stdio") {
|
|
67
|
-
const map = expand ?? ((value: string) => value);
|
|
68
|
-
return {
|
|
69
|
-
type: "stdio",
|
|
70
|
-
command: entry.command,
|
|
71
|
-
args: (entry.args ?? []).map(map),
|
|
72
|
-
...(entry.env && {
|
|
73
|
-
env: Object.fromEntries(
|
|
74
|
-
Object.entries(entry.env).map(([key, value]) => [key, map(value)]),
|
|
75
|
-
),
|
|
76
|
-
}),
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
type: entry.type,
|
|
81
|
-
url: entry.url,
|
|
82
|
-
...(entry.headers && { headers: entry.headers }),
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Project an in-memory transport onto a spec server entry. Headers are
|
|
88
|
-
* omitted: workspace secrets live in the credential store, and a write
|
|
89
|
-
* must not copy them into `mcp.json`.
|
|
90
|
-
*/
|
|
91
|
-
export function projectTransportToSpecServer(
|
|
92
|
-
transport: McpTransport,
|
|
93
|
-
): Record<string, unknown> {
|
|
94
|
-
if (transport.type === "stdio") {
|
|
95
|
-
const entry: Record<string, unknown> = {
|
|
96
|
-
type: "stdio",
|
|
97
|
-
command: transport.command,
|
|
98
|
-
};
|
|
99
|
-
if (transport.args && transport.args.length > 0) {
|
|
100
|
-
entry.args = transport.args;
|
|
101
|
-
}
|
|
102
|
-
if (transport.env) {
|
|
103
|
-
entry.env = transport.env;
|
|
104
|
-
}
|
|
105
|
-
return entry;
|
|
106
|
-
}
|
|
107
|
-
return {
|
|
108
|
-
type: transport.type,
|
|
109
|
-
url: transport.url,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User-owned MCP servers in `$VELLUM_WORKSPACE_DIR/mcp.json`.
|
|
3
|
-
*
|
|
4
|
-
* The file is an Agent Plugins 1.0.0 document (`$schema` + `mcpServers`).
|
|
5
|
-
* This module is the only reader and writer of that file. Presence of a
|
|
6
|
-
* server starts it. Headers are never persisted here.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
existsSync,
|
|
11
|
-
mkdirSync,
|
|
12
|
-
readFileSync,
|
|
13
|
-
renameSync,
|
|
14
|
-
writeFileSync,
|
|
15
|
-
} from "node:fs";
|
|
16
|
-
import { dirname } from "node:path";
|
|
17
|
-
|
|
18
|
-
import type { McpConfig, McpServerConfig } from "../config/schemas/mcp.js";
|
|
19
|
-
import { McpConfigSchema } from "../config/schemas/mcp.js";
|
|
20
|
-
import { getLogger } from "../util/logger.js";
|
|
21
|
-
import { getWorkspaceMcpConfigPath } from "../util/platform.js";
|
|
22
|
-
import {
|
|
23
|
-
AGENT_PLUGINS_MCP_SCHEMA_URL,
|
|
24
|
-
projectSpecServerToTransport,
|
|
25
|
-
projectTransportToSpecServer,
|
|
26
|
-
SpecMcpDocumentSchema,
|
|
27
|
-
SpecMcpServerSchema,
|
|
28
|
-
} from "./spec-schema.js";
|
|
29
|
-
|
|
30
|
-
const log = getLogger("workspace-mcp-config");
|
|
31
|
-
|
|
32
|
-
export type WorkspaceMcpFileState = "missing" | "ok" | "invalid";
|
|
33
|
-
|
|
34
|
-
export interface WorkspaceMcpLoadResult {
|
|
35
|
-
readonly config: McpConfig;
|
|
36
|
-
readonly issues: readonly string[];
|
|
37
|
-
readonly fileState: WorkspaceMcpFileState;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Read `/workspace/mcp.json` and project it onto the in-memory MCP config.
|
|
42
|
-
*
|
|
43
|
-
* A missing file is an empty server map. An invalid file disables the
|
|
44
|
-
* workspace half only (plugin servers still load) and is reported so a
|
|
45
|
-
* write can refuse to overwrite it.
|
|
46
|
-
*/
|
|
47
|
-
export function readWorkspaceMcpFile(
|
|
48
|
-
path: string = getWorkspaceMcpConfigPath(),
|
|
49
|
-
): WorkspaceMcpLoadResult {
|
|
50
|
-
if (!existsSync(path)) {
|
|
51
|
-
return {
|
|
52
|
-
config: McpConfigSchema.parse({}),
|
|
53
|
-
issues: [],
|
|
54
|
-
fileState: "missing",
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
let raw: string;
|
|
59
|
-
try {
|
|
60
|
-
raw = readFileSync(path, "utf8");
|
|
61
|
-
} catch (err) {
|
|
62
|
-
const message = `mcp.json unreadable: ${err instanceof Error ? err.message : String(err)}`;
|
|
63
|
-
return {
|
|
64
|
-
config: McpConfigSchema.parse({}),
|
|
65
|
-
issues: [message],
|
|
66
|
-
fileState: "invalid",
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
let json: unknown;
|
|
71
|
-
try {
|
|
72
|
-
json = JSON.parse(raw);
|
|
73
|
-
} catch (err) {
|
|
74
|
-
const message = `mcp.json invalid JSON: ${err instanceof Error ? err.message : String(err)}`;
|
|
75
|
-
return {
|
|
76
|
-
config: McpConfigSchema.parse({}),
|
|
77
|
-
issues: [message],
|
|
78
|
-
fileState: "invalid",
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const document = SpecMcpDocumentSchema.safeParse(json);
|
|
83
|
-
if (!document.success) {
|
|
84
|
-
return {
|
|
85
|
-
config: McpConfigSchema.parse({}),
|
|
86
|
-
issues: ['mcp.json is missing a valid "mcpServers" object'],
|
|
87
|
-
fileState: "invalid",
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const servers: Record<string, McpServerConfig> = {};
|
|
92
|
-
const issues: string[] = [];
|
|
93
|
-
|
|
94
|
-
for (const [serverKey, rawEntry] of Object.entries(document.data.mcpServers)) {
|
|
95
|
-
if (serverKey.trim().length === 0) {
|
|
96
|
-
issues.push("server key must be a non-empty string; skipping");
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const entry = SpecMcpServerSchema.safeParse(rawEntry);
|
|
101
|
-
if (!entry.success) {
|
|
102
|
-
issues.push(
|
|
103
|
-
`invalid server entry "${serverKey}": ${entry.error.issues
|
|
104
|
-
.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
|
|
105
|
-
.join("; ")}`,
|
|
106
|
-
);
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (entry.data.type === "stdio" && entry.data.cwd) {
|
|
111
|
-
issues.push(
|
|
112
|
-
`"${serverKey}": "cwd" is not supported by this host and was ignored; the server runs in the assistant's working directory`,
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
servers[serverKey] = {
|
|
117
|
-
transport: projectSpecServerToTransport(entry.data),
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
config: { servers },
|
|
123
|
-
issues,
|
|
124
|
-
fileState: "ok",
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** Load the workspace MCP config, logging any declaration problems. */
|
|
129
|
-
export function loadWorkspaceMcpConfig(): McpConfig {
|
|
130
|
-
const result = readWorkspaceMcpFile();
|
|
131
|
-
for (const issue of result.issues) {
|
|
132
|
-
log.warn(issue);
|
|
133
|
-
}
|
|
134
|
-
return result.config;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Refuse a write when `mcp.json` exists but is not a usable document, so a
|
|
139
|
-
* later add/remove cannot clobber a hand-edit the user still means to fix.
|
|
140
|
-
*/
|
|
141
|
-
export function assertWorkspaceMcpWritable(): void {
|
|
142
|
-
const result = readWorkspaceMcpFile();
|
|
143
|
-
if (result.fileState === "invalid") {
|
|
144
|
-
throw new Error(result.issues[0] ?? "mcp.json is not a valid document");
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/** Persist the in-memory workspace MCP config as a spec-pure document. */
|
|
149
|
-
export function saveWorkspaceMcpConfig(config: McpConfig): void {
|
|
150
|
-
assertWorkspaceMcpWritable();
|
|
151
|
-
const path = getWorkspaceMcpConfigPath();
|
|
152
|
-
const mcpServers: Record<string, unknown> = {};
|
|
153
|
-
for (const [id, server] of Object.entries(config.servers)) {
|
|
154
|
-
mcpServers[id] = projectTransportToSpecServer(server.transport);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const document = {
|
|
158
|
-
$schema: AGENT_PLUGINS_MCP_SCHEMA_URL,
|
|
159
|
-
mcpServers,
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
163
|
-
const tmpPath = `${path}.tmp`;
|
|
164
|
-
writeFileSync(tmpPath, JSON.stringify(document, null, 2) + "\n");
|
|
165
|
-
renameSync(tmpPath, path);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Replace `config.mcp` on a settings/export payload with the projected
|
|
170
|
-
* workspace servers (transport only, headers stripped). Old clients that
|
|
171
|
-
* still read `mcp.servers` from `/v1/config` keep seeing the same shape.
|
|
172
|
-
*/
|
|
173
|
-
export function overlayWorkspaceMcpForConfigRead(config: unknown): void {
|
|
174
|
-
if (config === null || typeof config !== "object" || Array.isArray(config)) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
const root = config as Record<string, unknown>;
|
|
178
|
-
const { servers } = loadWorkspaceMcpConfig();
|
|
179
|
-
const projected: Record<string, unknown> = {};
|
|
180
|
-
for (const [id, server] of Object.entries(servers)) {
|
|
181
|
-
const { headers: _headers, ...safeTransport } = server.transport as Record<
|
|
182
|
-
string,
|
|
183
|
-
unknown
|
|
184
|
-
>;
|
|
185
|
-
projected[id] = { transport: safeTransport };
|
|
186
|
-
}
|
|
187
|
-
root.mcp = { servers: projected };
|
|
188
|
-
}
|