@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
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
getConfiguredProvider,
|
|
23
23
|
userMessage,
|
|
24
24
|
} from "../../providers/provider-send-message.js";
|
|
25
|
+
import { isMaxTokensStopReason } from "../../providers/stop-reasons.js";
|
|
25
26
|
import { getLogger } from "../../util/logger.js";
|
|
26
27
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
27
28
|
import { BadRequestError } from "./errors.js";
|
|
@@ -176,9 +177,44 @@ function buildCommandPrompt(body: DictationBody, stylePrompt?: string): string {
|
|
|
176
177
|
return sections.join("\n");
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
function computeMaxTokens(inputLength: number): number {
|
|
180
|
+
export function computeMaxTokens(inputLength: number): number {
|
|
180
181
|
const estimatedInputTokens = Math.ceil(inputLength / 3);
|
|
181
|
-
|
|
182
|
+
// The cleanup tool call carries the whole transcript back in its `text`
|
|
183
|
+
// argument, plus a `reasoning` string and the JSON scaffolding around both,
|
|
184
|
+
// so the budget has to cover well more than the input alone. `max_tokens` is
|
|
185
|
+
// a ceiling rather than a target: a call that stops short of it costs no
|
|
186
|
+
// extra latency.
|
|
187
|
+
return Math.max(512, estimatedInputTokens * 2 + 256);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export type CleanupRejection = "truncated";
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Decide whether the cleanup model's rewrite is safe to use as the payload.
|
|
194
|
+
*
|
|
195
|
+
* The rewrite replaces what the user actually said. A token-cap stop means the
|
|
196
|
+
* tool JSON was cut mid-argument, so however complete the `text` argument
|
|
197
|
+
* happens to look, it is a fragment; the raw transcript is the safer payload
|
|
198
|
+
* then. Unpolished beats wrong.
|
|
199
|
+
*
|
|
200
|
+
* Whether a shorter rewrite still preserved the meaning is the model's call
|
|
201
|
+
* (the prompt asks it to drop fillers and tighten phrasing), so there is no
|
|
202
|
+
* length check here: a deterministic ratio cannot tell a concise cleanup from
|
|
203
|
+
* a summary.
|
|
204
|
+
*/
|
|
205
|
+
export function resolveCleanedDictation(
|
|
206
|
+
raw: string,
|
|
207
|
+
cleaned: string,
|
|
208
|
+
stopReason: string | null | undefined,
|
|
209
|
+
): { text: string; rejected: CleanupRejection | null } {
|
|
210
|
+
const trimmed = cleaned.trim();
|
|
211
|
+
if (!trimmed) {
|
|
212
|
+
return { text: raw, rejected: null };
|
|
213
|
+
}
|
|
214
|
+
if (isMaxTokensStopReason(stopReason)) {
|
|
215
|
+
return { text: raw, rejected: "truncated" };
|
|
216
|
+
}
|
|
217
|
+
return { text: trimmed, rejected: null };
|
|
182
218
|
}
|
|
183
219
|
|
|
184
220
|
interface DictationResult {
|
|
@@ -329,7 +365,23 @@ async function handleDictation(body: DictationBody): Promise<DictationResult> {
|
|
|
329
365
|
...profileMeta,
|
|
330
366
|
};
|
|
331
367
|
}
|
|
332
|
-
const cleanedText =
|
|
368
|
+
const { text: cleanedText, rejected } = resolveCleanedDictation(
|
|
369
|
+
transcription,
|
|
370
|
+
input.text ?? "",
|
|
371
|
+
response.stopReason,
|
|
372
|
+
);
|
|
373
|
+
if (rejected) {
|
|
374
|
+
// Lengths only -- transcript content must never be logged.
|
|
375
|
+
log.warn(
|
|
376
|
+
{
|
|
377
|
+
rejected,
|
|
378
|
+
stopReason: response.stopReason,
|
|
379
|
+
rawChars: transcription.length,
|
|
380
|
+
cleanedChars: input.text?.trim().length ?? 0,
|
|
381
|
+
},
|
|
382
|
+
"Dictation cleanup rejected, using raw transcription",
|
|
383
|
+
);
|
|
384
|
+
}
|
|
333
385
|
const normalizedText = applyDictionary(cleanedText, profile.dictionary);
|
|
334
386
|
return {
|
|
335
387
|
text: normalizedText,
|
|
@@ -39,6 +39,7 @@ import { ROUTES as CALL_ROUTES } from "./call-routes.js";
|
|
|
39
39
|
import { ROUTES as CHANNEL_AVAILABILITY_ROUTES } from "./channel-availability-routes.js";
|
|
40
40
|
import { ROUTES as CHANNEL_READINESS_ROUTES } from "./channel-readiness-routes.js";
|
|
41
41
|
import { CHANNEL_ROUTES } from "./channel-route-definitions.js";
|
|
42
|
+
import { ROUTES as CHANNEL_SEND_ROUTES } from "./channel-send-routes.js";
|
|
42
43
|
import { ROUTES as CHANNEL_VERIFICATION_ROUTES } from "./channel-verification-routes.js";
|
|
43
44
|
import { ROUTES as CHATGPT_SUBSCRIPTION_AUTH_ROUTES } from "./chatgpt-subscription-auth-routes.js";
|
|
44
45
|
import { ROUTES as CLIENT_ROUTES } from "./client-routes.js";
|
|
@@ -58,10 +59,10 @@ import { ROUTES as CONVERSATIONS_IMPORT_ROUTES } from "./conversations-import-ro
|
|
|
58
59
|
import { ROUTES as CREDENTIAL_PROMPT_ROUTES } from "./credential-prompt-routes.js";
|
|
59
60
|
import { ROUTES as CREDENTIAL_REQUEST_ROUTES } from "./credential-request-routes.js";
|
|
60
61
|
import { ROUTES as CREDENTIAL_ROUTES } from "./credential-routes.js";
|
|
61
|
-
import { ROUTES as DEBUG_BASH_ROUTES } from "./debug-bash-routes.js";
|
|
62
62
|
import { ROUTES as DEBUG_ROUTES } from "./debug-routes.js";
|
|
63
63
|
import { ROUTES as DEFAULT_PROVIDER_ROUTES } from "./default-provider-routes.js";
|
|
64
64
|
import { ROUTES as DEFER_ROUTES } from "./defer-routes.js";
|
|
65
|
+
import { ROUTES as DESKTOP_SETUP_ROUTES } from "./desktop-setup-routes.js";
|
|
65
66
|
import { ROUTES as DIAGNOSTICS_ROUTES } from "./diagnostics-routes.js";
|
|
66
67
|
import { ROUTES as DISK_PRESSURE_ROUTES } from "./disk-pressure-routes.js";
|
|
67
68
|
import { ROUTES as DOCUMENT_COMMENT_ROUTES } from "./document-comments-routes.js";
|
|
@@ -191,6 +192,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
191
192
|
...CHANNEL_VERIFICATION_ROUTES,
|
|
192
193
|
...CHANNEL_AVAILABILITY_ROUTES,
|
|
193
194
|
...CHANNEL_READINESS_ROUTES,
|
|
195
|
+
...CHANNEL_SEND_ROUTES,
|
|
194
196
|
...BROWSER_ROUTES,
|
|
195
197
|
...BROWSER_TABS_ROUTES,
|
|
196
198
|
...BTW_ROUTES,
|
|
@@ -215,9 +217,9 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
215
217
|
...CONVERSATION_QUERY_ROUTES,
|
|
216
218
|
...CONVERSATION_STARTER_ROUTES,
|
|
217
219
|
...ACTIVATION_ROUTES,
|
|
218
|
-
...DEBUG_BASH_ROUTES,
|
|
219
220
|
...DEBUG_ROUTES,
|
|
220
221
|
...DEFAULT_PROVIDER_ROUTES,
|
|
222
|
+
...DESKTOP_SETUP_ROUTES,
|
|
221
223
|
...DIAGNOSTICS_ROUTES,
|
|
222
224
|
...DISK_PRESSURE_ROUTES,
|
|
223
225
|
...RESOURCE_PRESSURE_ROUTES,
|
|
@@ -22,6 +22,7 @@ import { join } from "node:path";
|
|
|
22
22
|
import { and, desc, eq, gte, lte } from "drizzle-orm";
|
|
23
23
|
import { z } from "zod";
|
|
24
24
|
|
|
25
|
+
import { overlayWorkspaceMcpForConfigRead } from "../../mcp/workspace-mcp-config.js";
|
|
25
26
|
import { getDb, getLogsDb } from "../../persistence/db-connection.js";
|
|
26
27
|
import {
|
|
27
28
|
llmRequestLogs,
|
|
@@ -568,6 +569,7 @@ function readSanitizedConfig(): Record<string, unknown> | undefined {
|
|
|
568
569
|
}
|
|
569
570
|
}
|
|
570
571
|
|
|
572
|
+
overlayWorkspaceMcpForConfigRead(config);
|
|
571
573
|
const mcpServers = asRecord(asRecord(config.mcp)?.servers);
|
|
572
574
|
for (const server of Object.values(mcpServers ?? {})) {
|
|
573
575
|
const transport = asRecord(asRecord(server)?.transport);
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import type { McpConfig, McpServerConfig } from "../../config/schemas/mcp.js";
|
|
17
|
+
import type { McpServerConfig } from "../../config/schemas/mcp.js";
|
|
19
18
|
import { estimateToolDefinitionTokens } from "../../context/token-estimator.js";
|
|
20
19
|
import { reloadMcpServers } from "../../daemon/mcp-reload-service.js";
|
|
21
20
|
import { McpClient } from "../../mcp/client.js";
|
|
@@ -31,6 +30,10 @@ import {
|
|
|
31
30
|
deleteMcpOAuthCredentials,
|
|
32
31
|
hasMcpOAuthTokens,
|
|
33
32
|
} from "../../mcp/mcp-oauth-provider.js";
|
|
33
|
+
import {
|
|
34
|
+
loadWorkspaceMcpConfig,
|
|
35
|
+
saveWorkspaceMcpConfig,
|
|
36
|
+
} from "../../mcp/workspace-mcp-config.js";
|
|
34
37
|
import { readPluginMcpServers } from "../../plugins/mcp-servers.js";
|
|
35
38
|
import { getMcpToolsByServer } from "../../tools/registry.js";
|
|
36
39
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -65,6 +68,18 @@ const McpAddParams = z.object({
|
|
|
65
68
|
|
|
66
69
|
const McpRemoveParams = z.object({ name: z.string() });
|
|
67
70
|
|
|
71
|
+
function persistWorkspaceMcpConfig(config: {
|
|
72
|
+
servers: Record<string, McpServerConfig>;
|
|
73
|
+
}): void {
|
|
74
|
+
try {
|
|
75
|
+
saveWorkspaceMcpConfig(config);
|
|
76
|
+
} catch (err) {
|
|
77
|
+
throw new InternalError(
|
|
78
|
+
err instanceof Error ? err.message : String(err),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
68
83
|
async function handleMcpAuthStart({
|
|
69
84
|
body,
|
|
70
85
|
}: {
|
|
@@ -76,8 +91,7 @@ async function handleMcpAuthStart({
|
|
|
76
91
|
}> {
|
|
77
92
|
const { serverId } = parseBody(McpServerIdParams, body);
|
|
78
93
|
|
|
79
|
-
const
|
|
80
|
-
const servers = (raw.mcp as Partial<McpConfig> | undefined)?.servers ?? {};
|
|
94
|
+
const servers = loadWorkspaceMcpConfig().servers;
|
|
81
95
|
const serverConfig = servers[serverId];
|
|
82
96
|
|
|
83
97
|
if (!serverConfig) {
|
|
@@ -253,9 +267,7 @@ function detectAuthType(headers: Record<string, string>): "bearer" | "api-key" {
|
|
|
253
267
|
async function handleMcpList(_args: {
|
|
254
268
|
body?: Record<string, unknown>;
|
|
255
269
|
}): Promise<{ servers: McpServerEntry[] }> {
|
|
256
|
-
const
|
|
257
|
-
const mcpConfig = raw.mcp as Partial<McpConfig> | undefined;
|
|
258
|
-
const servers = mcpConfig?.servers ?? {};
|
|
270
|
+
const servers = loadWorkspaceMcpConfig().servers;
|
|
259
271
|
const configEntries = (
|
|
260
272
|
Object.entries(servers) as [string, McpServerConfig][]
|
|
261
273
|
).filter(([, config]) => config && typeof config === "object");
|
|
@@ -434,18 +446,13 @@ async function handleMcpUpdate({
|
|
|
434
446
|
}): Promise<{ updated: true }> {
|
|
435
447
|
const { name, headers } = parseBody(McpUpdateParams, body);
|
|
436
448
|
|
|
437
|
-
const
|
|
438
|
-
const
|
|
439
|
-
const serverMap = mcpConfig?.servers as
|
|
440
|
-
| Record<string, Record<string, unknown>>
|
|
441
|
-
| undefined;
|
|
449
|
+
const servers = loadWorkspaceMcpConfig().servers;
|
|
450
|
+
const server = servers[name];
|
|
442
451
|
|
|
443
|
-
if (!
|
|
452
|
+
if (!server) {
|
|
444
453
|
throw new NotFoundError(`MCP server "${name}" not found.`);
|
|
445
454
|
}
|
|
446
455
|
|
|
447
|
-
const server = serverMap[name];
|
|
448
|
-
|
|
449
456
|
if (headers !== undefined) {
|
|
450
457
|
const transport = server.transport as Record<string, unknown> | undefined;
|
|
451
458
|
if (
|
|
@@ -474,7 +481,7 @@ async function handleMcpUpdate({
|
|
|
474
481
|
}
|
|
475
482
|
}
|
|
476
483
|
|
|
477
|
-
|
|
484
|
+
persistWorkspaceMcpConfig({ servers });
|
|
478
485
|
triggerReload("internal_mcp_update");
|
|
479
486
|
|
|
480
487
|
return { updated: true };
|
|
@@ -494,7 +501,7 @@ async function handleMcpAdd({
|
|
|
494
501
|
body,
|
|
495
502
|
);
|
|
496
503
|
|
|
497
|
-
let transport:
|
|
504
|
+
let transport: McpServerConfig["transport"];
|
|
498
505
|
switch (transportType) {
|
|
499
506
|
case "stdio":
|
|
500
507
|
if (!command) {
|
|
@@ -517,27 +524,16 @@ async function handleMcpAdd({
|
|
|
517
524
|
);
|
|
518
525
|
}
|
|
519
526
|
|
|
520
|
-
const
|
|
521
|
-
if (!raw.mcp) {
|
|
522
|
-
raw.mcp = { servers: {} };
|
|
523
|
-
}
|
|
524
|
-
const mcpConfig = raw.mcp as Record<string, unknown>;
|
|
525
|
-
if (!mcpConfig.servers) {
|
|
526
|
-
mcpConfig.servers = {};
|
|
527
|
-
}
|
|
528
|
-
const serverMap = mcpConfig.servers as Record<string, unknown>;
|
|
527
|
+
const servers = { ...loadWorkspaceMcpConfig().servers };
|
|
529
528
|
|
|
530
|
-
if (
|
|
529
|
+
if (servers[name]) {
|
|
531
530
|
throw new BadRequestError(
|
|
532
531
|
`MCP server "${name}" already exists. Remove it first with: assistant mcp remove ${name}`,
|
|
533
532
|
);
|
|
534
533
|
}
|
|
535
534
|
|
|
536
|
-
|
|
537
|
-
transport,
|
|
538
|
-
};
|
|
535
|
+
servers[name] = { transport };
|
|
539
536
|
|
|
540
|
-
// Store auth headers in credential store, not config
|
|
541
537
|
if (headers && Object.keys(headers).length > 0) {
|
|
542
538
|
const ok = await setMcpHeaders(name, headers);
|
|
543
539
|
if (!ok) {
|
|
@@ -547,7 +543,7 @@ async function handleMcpAdd({
|
|
|
547
543
|
}
|
|
548
544
|
}
|
|
549
545
|
|
|
550
|
-
|
|
546
|
+
persistWorkspaceMcpConfig({ servers });
|
|
551
547
|
triggerReload("internal_mcp_add");
|
|
552
548
|
|
|
553
549
|
return { added: true };
|
|
@@ -564,8 +560,7 @@ async function handleMcpAuthRevoke({
|
|
|
564
560
|
}): Promise<{ revoked: true }> {
|
|
565
561
|
const { serverId } = parseBody(McpServerIdParams, body);
|
|
566
562
|
|
|
567
|
-
const
|
|
568
|
-
const servers = (raw.mcp as Partial<McpConfig> | undefined)?.servers ?? {};
|
|
563
|
+
const servers = loadWorkspaceMcpConfig().servers;
|
|
569
564
|
const serverConfig = servers[serverId];
|
|
570
565
|
|
|
571
566
|
if (!serverConfig) {
|
|
@@ -602,32 +597,29 @@ async function handleMcpRemove({
|
|
|
602
597
|
}): Promise<{ removed: true }> {
|
|
603
598
|
const { name } = parseBody(McpRemoveParams, body);
|
|
604
599
|
|
|
605
|
-
const
|
|
606
|
-
const
|
|
607
|
-
const serverMap = mcpConfig?.servers as Record<string, unknown> | undefined;
|
|
600
|
+
const servers = { ...loadWorkspaceMcpConfig().servers };
|
|
601
|
+
const serverConfig = servers[name];
|
|
608
602
|
|
|
609
|
-
if (!
|
|
603
|
+
if (!serverConfig) {
|
|
610
604
|
throw new NotFoundError(`MCP server "${name}" not found.`);
|
|
611
605
|
}
|
|
612
606
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
| undefined;
|
|
618
|
-
if (transport?.type === "sse" || transport?.type === "streamable-http") {
|
|
607
|
+
if (
|
|
608
|
+
serverConfig.transport.type === "sse" ||
|
|
609
|
+
serverConfig.transport.type === "streamable-http"
|
|
610
|
+
) {
|
|
619
611
|
try {
|
|
620
612
|
await Promise.all([
|
|
621
613
|
deleteMcpOAuthCredentials(name),
|
|
622
614
|
deleteMcpHeaders(name),
|
|
623
615
|
]);
|
|
624
616
|
} catch {
|
|
625
|
-
//
|
|
617
|
+
// Credentials may not exist.
|
|
626
618
|
}
|
|
627
619
|
}
|
|
628
620
|
|
|
629
|
-
delete
|
|
630
|
-
|
|
621
|
+
delete servers[name];
|
|
622
|
+
persistWorkspaceMcpConfig({ servers });
|
|
631
623
|
triggerReload("internal_mcp_remove");
|
|
632
624
|
|
|
633
625
|
return { removed: true };
|
|
@@ -22,8 +22,8 @@ import { PassThrough, Readable } from "node:stream";
|
|
|
22
22
|
|
|
23
23
|
import { z } from "zod";
|
|
24
24
|
|
|
25
|
-
import { getPlatformAssistantId } from "../../config/env.js";
|
|
26
25
|
import { invalidateConfigCache } from "../../config/loader.js";
|
|
26
|
+
import { resolvePlatformAssistantId } from "../../config/platform-identity.js";
|
|
27
27
|
import { getAssistantName } from "../../daemon/identity-helpers.js";
|
|
28
28
|
import { runAsyncSqlite } from "../../persistence/db-async-query.js";
|
|
29
29
|
import {
|
|
@@ -236,28 +236,14 @@ interface ExportManifestInputs {
|
|
|
236
236
|
/**
|
|
237
237
|
* Resolve the `assistant.id` for an export.
|
|
238
238
|
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
* fallback. The schema requires `id` to be non-empty, so we fall back to
|
|
239
|
+
* In-memory identity (validate rehydration or secret-routes). The schema
|
|
240
|
+
* requires `id` to be non-empty, so we fall back to
|
|
242
241
|
* `DAEMON_INTERNAL_ASSISTANT_ID` rather than the empty string.
|
|
243
242
|
*/
|
|
244
243
|
async function resolveAssistantId(): Promise<string> {
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
247
|
-
return
|
|
248
|
-
}
|
|
249
|
-
try {
|
|
250
|
-
const stored = await getSecureKeyAsync(
|
|
251
|
-
credentialKey("vellum", "platform_assistant_id"),
|
|
252
|
-
);
|
|
253
|
-
if (stored) {
|
|
254
|
-
return stored;
|
|
255
|
-
}
|
|
256
|
-
} catch (err) {
|
|
257
|
-
log.warn(
|
|
258
|
-
{ err },
|
|
259
|
-
"Failed to read platform_assistant_id from credential store; falling back to daemon-internal id",
|
|
260
|
-
);
|
|
244
|
+
const resolved = await resolvePlatformAssistantId();
|
|
245
|
+
if (resolved) {
|
|
246
|
+
return resolved;
|
|
261
247
|
}
|
|
262
248
|
return DAEMON_INTERNAL_ASSISTANT_ID;
|
|
263
249
|
}
|
|
@@ -39,7 +39,17 @@ import {
|
|
|
39
39
|
} from "@vellumai/service-contracts/platform-credential";
|
|
40
40
|
import { z } from "zod";
|
|
41
41
|
|
|
42
|
+
import {
|
|
43
|
+
setPlatformAssistantId,
|
|
44
|
+
setPlatformBaseUrl,
|
|
45
|
+
setPlatformOrganizationId,
|
|
46
|
+
setPlatformUserId,
|
|
47
|
+
} from "../../config/env.js";
|
|
42
48
|
import { isPlatformRemote } from "../../config/env-registry.js";
|
|
49
|
+
import {
|
|
50
|
+
resolvePlatformOrganizationId,
|
|
51
|
+
resolvePlatformUserId,
|
|
52
|
+
} from "../../config/platform-identity.js";
|
|
43
53
|
import {
|
|
44
54
|
registerCallbackRoute,
|
|
45
55
|
resolvePlatformCallbackRegistrationContext,
|
|
@@ -289,24 +299,12 @@ async function handlePlatformStatus(
|
|
|
289
299
|
): Promise<PlatformStatusResponse> {
|
|
290
300
|
const context = await resolvePlatformCallbackRegistrationContext();
|
|
291
301
|
|
|
292
|
-
const [
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
CREDENTIAL_KEYS.organizationId.service,
|
|
296
|
-
CREDENTIAL_KEYS.organizationId.field,
|
|
297
|
-
),
|
|
298
|
-
),
|
|
299
|
-
getSecureKeyAsync(
|
|
300
|
-
credentialKey(
|
|
301
|
-
CREDENTIAL_KEYS.userId.service,
|
|
302
|
-
CREDENTIAL_KEYS.userId.field,
|
|
303
|
-
),
|
|
304
|
-
),
|
|
302
|
+
const [organizationId, userId, webhookSecretRaw] = await Promise.all([
|
|
303
|
+
resolvePlatformOrganizationId(),
|
|
304
|
+
resolvePlatformUserId(),
|
|
305
305
|
getSecureKeyAsync(credentialKey("vellum", "webhook_secret")),
|
|
306
306
|
]);
|
|
307
307
|
|
|
308
|
-
const organizationId = orgIdRaw?.trim() ?? "";
|
|
309
|
-
const userId = userIdRaw?.trim() ?? "";
|
|
310
308
|
const hasWebhookSecret = !!webhookSecretRaw;
|
|
311
309
|
|
|
312
310
|
return {
|
|
@@ -467,6 +465,11 @@ async function handlePlatformDisconnect(
|
|
|
467
465
|
);
|
|
468
466
|
}
|
|
469
467
|
|
|
468
|
+
setPlatformBaseUrl(undefined);
|
|
469
|
+
setPlatformAssistantId(undefined);
|
|
470
|
+
setPlatformOrganizationId(undefined);
|
|
471
|
+
setPlatformUserId(undefined);
|
|
472
|
+
|
|
470
473
|
// Notify connected clients
|
|
471
474
|
broadcastMessage({ type: "platform_disconnected" });
|
|
472
475
|
|
|
@@ -159,3 +159,31 @@ describe("serializeConversationSummary · enabledPlugins", () => {
|
|
|
159
159
|
expect("enabledPlugins" in summary).toBe(false);
|
|
160
160
|
});
|
|
161
161
|
});
|
|
162
|
+
|
|
163
|
+
describe("serializeConversationSummary · title keys", () => {
|
|
164
|
+
test("resolves a stored title key for the locale", () => {
|
|
165
|
+
const summary = serializeConversationSummary({
|
|
166
|
+
conversation: makeConversationRow({
|
|
167
|
+
title: "conversation.title.generating",
|
|
168
|
+
}),
|
|
169
|
+
displayMeta: { displayOrder: null, isPinned: false, groupId: null },
|
|
170
|
+
parentCache: new Map(),
|
|
171
|
+
isProcessing: false,
|
|
172
|
+
locale: "es",
|
|
173
|
+
});
|
|
174
|
+
expect(summary.title).toBe("Generando título...");
|
|
175
|
+
expect("titleState" in summary).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("passes a stored display string through", () => {
|
|
179
|
+
const summary = serialize(
|
|
180
|
+
makeConversationRow({ title: "Untitled Conversation" }),
|
|
181
|
+
);
|
|
182
|
+
expect(summary.title).toBe("Untitled Conversation");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("passes a custom title through", () => {
|
|
186
|
+
const summary = serialize(makeConversationRow({ title: "Weekly planning" }));
|
|
187
|
+
expect(summary.title).toBe("Weekly planning");
|
|
188
|
+
});
|
|
189
|
+
});
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
import { parseChannelId } from "../../channels/types.js";
|
|
10
10
|
import { normalizeConversationType } from "../../daemon/message-types/shared.js";
|
|
11
|
+
import {
|
|
12
|
+
resolveConversationTitle,
|
|
13
|
+
type SupportedLocale,
|
|
14
|
+
} from "../../i18n/index.js";
|
|
11
15
|
import { buildChannelBindingMetadata } from "../../messaging/channel-binding-metadata.js";
|
|
12
16
|
import {
|
|
13
17
|
type AttentionState,
|
|
@@ -78,6 +82,7 @@ interface ForkLineage {
|
|
|
78
82
|
function buildForkLineage(
|
|
79
83
|
conversation: ConversationRow,
|
|
80
84
|
parentCache: Map<string, ConversationRow | null>,
|
|
85
|
+
locale?: SupportedLocale,
|
|
81
86
|
): ForkLineage {
|
|
82
87
|
const parentConversationId = conversation.forkParentConversationId;
|
|
83
88
|
const parentMessageId = conversation.forkParentMessageId;
|
|
@@ -101,7 +106,7 @@ function buildForkLineage(
|
|
|
101
106
|
forkParent: {
|
|
102
107
|
conversationId: parentConversationId,
|
|
103
108
|
messageId: parentMessageId,
|
|
104
|
-
title: parentConversation.title
|
|
109
|
+
title: resolveConversationTitle(parentConversation.title, locale),
|
|
105
110
|
},
|
|
106
111
|
};
|
|
107
112
|
}
|
|
@@ -178,6 +183,11 @@ export function serializeConversationSummary(params: {
|
|
|
178
183
|
* with no daemon-store coupling.
|
|
179
184
|
*/
|
|
180
185
|
isProcessing: boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Locale used to resolve stored title keys. Omitted locale is English
|
|
188
|
+
* inside {@link resolveConversationTitle}.
|
|
189
|
+
*/
|
|
190
|
+
locale?: SupportedLocale;
|
|
181
191
|
}) {
|
|
182
192
|
const {
|
|
183
193
|
conversation,
|
|
@@ -186,14 +196,15 @@ export function serializeConversationSummary(params: {
|
|
|
186
196
|
displayMeta,
|
|
187
197
|
parentCache,
|
|
188
198
|
isProcessing,
|
|
199
|
+
locale,
|
|
189
200
|
} = params;
|
|
190
201
|
const originChannel = parseChannelId(conversation.originChannel);
|
|
191
202
|
const assistantAttention = buildAssistantAttention(attentionState);
|
|
192
|
-
const forkLineage = buildForkLineage(conversation, parentCache);
|
|
203
|
+
const forkLineage = buildForkLineage(conversation, parentCache, locale);
|
|
193
204
|
|
|
194
205
|
return {
|
|
195
206
|
id: conversation.id,
|
|
196
|
-
title: conversation.title
|
|
207
|
+
title: resolveConversationTitle(conversation.title, locale),
|
|
197
208
|
createdAt: conversation.createdAt,
|
|
198
209
|
updatedAt: conversation.updatedAt,
|
|
199
210
|
lastMessageAt: conversation.lastMessageAt,
|
|
@@ -253,6 +264,7 @@ export function serializeConversationSummary(params: {
|
|
|
253
264
|
*/
|
|
254
265
|
export function buildConversationDetailResponse(
|
|
255
266
|
conversationId: string,
|
|
267
|
+
locale?: SupportedLocale,
|
|
256
268
|
): { conversation: ReturnType<typeof serializeConversationSummary> } | null {
|
|
257
269
|
const conversation = getConversation(conversationId);
|
|
258
270
|
if (!conversation || conversation.conversationType === "private") {
|
|
@@ -274,6 +286,7 @@ export function buildConversationDetailResponse(
|
|
|
274
286
|
// Checks in-memory flag first (hot path), falls back to the
|
|
275
287
|
// persisted `processing_started_at` column for cold conversations.
|
|
276
288
|
isProcessing: isConversationProcessing(conversation.id),
|
|
289
|
+
locale,
|
|
277
290
|
}),
|
|
278
291
|
};
|
|
279
292
|
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
conversationMetadataSyncTag,
|
|
5
5
|
SYNC_TAGS,
|
|
6
6
|
} from "../../daemon/message-types/sync.js";
|
|
7
|
+
import { resolveConversationTitle } from "../../i18n/index.js";
|
|
7
8
|
import { syncAvatarToPlatform } from "../../platform/sync-avatar.js";
|
|
8
9
|
import { getAvatarImagePath } from "../../util/platform.js";
|
|
9
10
|
import { broadcastMessage } from "../assistant-event-hub.js";
|
|
@@ -257,7 +258,7 @@ export function publishConversationTitleChanged(
|
|
|
257
258
|
{
|
|
258
259
|
type: "conversation_title_updated",
|
|
259
260
|
conversationId,
|
|
260
|
-
title,
|
|
261
|
+
title: resolveConversationTitle(title),
|
|
261
262
|
},
|
|
262
263
|
conversationId,
|
|
263
264
|
);
|
package/src/schedule/worker.ts
CHANGED
|
@@ -195,7 +195,7 @@ async function main(): Promise<void> {
|
|
|
195
195
|
//
|
|
196
196
|
// Bounded by MCP_STARTUP_GRACE_MS: unreachable servers must not hold the
|
|
197
197
|
// schedules that do not use them. The connect runs on past the deadline.
|
|
198
|
-
const mcpStartup = startConfiguredMcpServers(
|
|
198
|
+
const mcpStartup = startConfiguredMcpServers();
|
|
199
199
|
await Promise.race([
|
|
200
200
|
mcpStartup,
|
|
201
201
|
// Unref'd so a connect that beats the deadline leaves nothing pending.
|