@vellumai/assistant 0.12.1 → 0.12.2-staging.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/ARCHITECTURE.md +20 -21
- package/docs/architecture/turn-actor.md +15 -8
- package/docs/guardian-request-flow.md +16 -0
- package/openapi.yaml +327 -52
- package/package.json +3 -1
- package/scripts/smoke-desktop-window-theme.ts +186 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
- package/src/__tests__/anthropic-provider.test.ts +0 -63
- package/src/__tests__/app-compiler.test.ts +6 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
- package/src/__tests__/app-dir-path-guard.test.ts +1 -3
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +6 -7
- package/src/__tests__/assistant-event-hub.test.ts +44 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
- package/src/__tests__/computer-use-tools.test.ts +19 -7
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +28 -29
- package/src/__tests__/config-watcher.test.ts +23 -8
- package/src/__tests__/connection-model-compat.test.ts +2 -2
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +26 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
- package/src/__tests__/conversation-queue.test.ts +48 -207
- package/src/__tests__/conversation-retry-discard.test.ts +54 -1
- package/src/__tests__/conversation-skill-tools.test.ts +27 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
- package/src/__tests__/conversation-title-service.test.ts +14 -10
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
- package/src/__tests__/credential-record-retire.test.ts +171 -1
- package/src/__tests__/credential-routes.test.ts +212 -3
- package/src/__tests__/credential-security-invariants.test.ts +4 -2
- package/src/__tests__/cu-unified-flow.test.ts +8 -2
- package/src/__tests__/document-sync-tags.test.ts +25 -0
- package/src/__tests__/drain-kick-guard.test.ts +0 -2
- package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
- package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
- package/src/__tests__/git-porcelain.test.ts +47 -0
- package/src/__tests__/heartbeat-service.test.ts +56 -40
- package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
- package/src/__tests__/host-bash-proxy.test.ts +26 -45
- package/src/__tests__/host-browser-proxy.test.ts +6 -17
- package/src/__tests__/host-cu-proxy.test.ts +539 -0
- package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
- package/src/__tests__/host-file-proxy.test.ts +11 -23
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
- package/src/__tests__/list-messages-camera-frame.test.ts +121 -0
- package/src/__tests__/llm-catalog-parity.test.ts +25 -0
- package/src/__tests__/mcp-auth-routes.test.ts +6 -9
- package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
- package/src/__tests__/mcp-health-check.test.ts +8 -11
- package/src/__tests__/mcp-list-plugin-servers.test.ts +8 -10
- package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
- package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
- package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +355 -548
- package/src/__tests__/model-intents.test.ts +3 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
- package/src/__tests__/oauth-commands-routes.test.ts +113 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
- package/src/__tests__/openai-provider.test.ts +1 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
- package/src/__tests__/platform-callback-registration.test.ts +8 -16
- package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +14 -0
- package/src/__tests__/qdrant-manager.test.ts +132 -0
- package/src/__tests__/resolve-app.test.ts +135 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +229 -6
- package/src/__tests__/script-proxy-certs.test.ts +35 -0
- package/src/__tests__/service-account-token.test.ts +247 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skills.test.ts +9 -4
- package/src/__tests__/source-fingerprint.test.ts +184 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +19 -3
- package/src/__tests__/subagent-tools.test.ts +3 -2
- package/src/__tests__/telephony-tts-guard.test.ts +38 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/unicode.test.ts +13 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
- package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
- package/src/__tests__/workspace-git-service.test.ts +26 -0
- package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
- package/src/acp/__tests__/agent-process.test.ts +258 -4
- package/src/acp/__tests__/auth-required.test.ts +96 -0
- package/src/acp/__tests__/client-handler.test.ts +90 -2
- package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
- package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
- package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
- package/src/acp/__tests__/session-manager.test.ts +895 -4
- package/src/acp/agent-process.test.ts +4 -1
- package/src/acp/agent-process.ts +96 -10
- package/src/acp/auth-required.ts +50 -1
- package/src/acp/auto-install.test.ts +9 -7
- package/src/acp/client-handler.ts +16 -3
- package/src/acp/model-config.test.ts +166 -0
- package/src/acp/model-config.ts +138 -0
- package/src/acp/resolve-agent.test.ts +220 -6
- package/src/acp/resolve-agent.ts +88 -23
- package/src/acp/session-manager.test.ts +196 -3
- package/src/acp/session-manager.ts +441 -18
- package/src/acp/types.ts +50 -5
- package/src/agent/loop.ts +1 -0
- package/src/api/events/acp-session-model-update.test.ts +88 -0
- package/src/api/events/acp-session-model-update.ts +46 -0
- package/src/api/events/app-files-changed.ts +4 -3
- package/src/api/events/notification-intent.ts +2 -0
- package/src/api/events/user-message-echo.ts +7 -1
- package/src/api/index.ts +6 -0
- package/src/api/responses/conversation-message.ts +5 -0
- package/src/apps/app-store.ts +1 -1
- package/src/apps/resolve-app.ts +81 -0
- package/src/apps/source-fingerprint.ts +266 -0
- package/src/avatar/identity-avatar.ts +7 -2
- package/src/bundler/app-compiler.ts +15 -0
- package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
- package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
- package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
- package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
- package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
- package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
- package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
- package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
- package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +4 -4
- package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
- package/src/calls/__tests__/voice-control-protocol.test.ts +58 -25
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
- package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
- package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
- package/src/calls/__tests__/voice-session-bridge.test.ts +37 -1
- package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
- package/src/calls/barge-in-guard.ts +118 -0
- package/src/calls/call-constants.ts +24 -4
- package/src/calls/call-controller.ts +499 -199
- package/src/calls/call-transport.ts +16 -0
- package/src/calls/media-stream-output.ts +32 -0
- package/src/calls/media-stream-server.ts +82 -30
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/{live-voice → calls}/progress-narration.ts +2 -2
- package/src/calls/resolve-call-tts-provider.ts +33 -2
- package/src/calls/tts-call-strategy.ts +9 -5
- package/src/calls/types.ts +2 -0
- package/src/calls/voice-control-protocol.ts +53 -21
- package/src/calls/voice-leg-coordinator.ts +189 -0
- package/src/calls/voice-progress-cadence.ts +423 -0
- package/src/calls/voice-session-bridge.ts +59 -46
- package/src/calls/voice-triage-escalate.ts +175 -56
- package/src/cli/commands/__tests__/apps.test.ts +245 -0
- package/src/cli/commands/__tests__/bash.test.ts +53 -0
- package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
- package/src/cli/commands/apps.help.ts +67 -13
- package/src/cli/commands/apps.ts +183 -0
- package/src/cli/commands/bash.help.ts +8 -13
- package/src/cli/commands/bash.ts +7 -25
- package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
- package/src/cli/commands/channels/index.help.ts +70 -2
- package/src/cli/commands/channels/index.ts +16 -3
- package/src/cli/commands/channels/send.ts +128 -0
- package/src/cli/commands/credentials.help.ts +6 -2
- package/src/cli/commands/credentials.ts +2 -2
- package/src/cli/commands/mcp.help.ts +8 -8
- package/src/cli/commands/mcp.ts +1 -1
- package/src/cli/commands/roadmap.help.ts +5 -1
- package/src/cli/commands/roadmap.ts +1 -1
- package/src/cli/lib/bundled-marketplace.json +103 -90
- package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
- package/src/config/__tests__/platform-identity.test.ts +255 -0
- package/src/config/__tests__/platform-rehydration.test.ts +99 -9
- package/src/config/acp-agent-write.ts +43 -0
- package/src/config/acp-defaults.test.ts +13 -3
- package/src/config/acp-defaults.ts +23 -6
- package/src/config/acp-schema.test.ts +81 -0
- package/src/config/acp-schema.ts +30 -2
- package/src/config/bundled-skills/acp/SKILL.md +22 -14
- package/src/config/bundled-skills/acp/TOOLS.json +5 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +20 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +99 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-sequence.ts +12 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -1
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -1
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -1
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +67 -139
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -1
- package/src/config/bundled-skills/schedule/SKILL.md +3 -4
- package/src/config/bundled-skills/screen-annotation/SKILL.md +8 -1
- package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +6 -2
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -2
- package/src/config/default-profile-catalog.ts +1 -1
- package/src/config/env.ts +2 -2
- package/src/config/feature-flag-registry.json +24 -12
- package/src/config/loader.ts +1 -0
- package/src/config/memory-v3-gate.test.ts +31 -0
- package/src/config/memory-v3-gate.ts +20 -16
- package/src/config/platform-identity.ts +201 -0
- package/src/config/platform-rehydration.ts +11 -27
- package/src/config/schema.ts +2 -2
- package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
- package/src/config/schemas/__tests__/voice.test.ts +148 -0
- package/src/config/schemas/calls.ts +1 -28
- package/src/config/schemas/live-voice.ts +1 -173
- package/src/config/schemas/mcp.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +10 -0
- package/src/config/schemas/services.ts +8 -0
- package/src/config/schemas/skills.ts +0 -14
- package/src/config/schemas/voice.ts +150 -0
- package/src/credential-execution/process-manager.test.ts +18 -19
- package/src/credential-health/credential-health-service.ts +11 -17
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -121
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +4 -1
- package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
- package/src/daemon/app-change-notify.ts +45 -0
- package/src/daemon/config-watcher.ts +13 -194
- package/src/daemon/conversation-error.ts +3 -2
- package/src/daemon/conversation-media-retry.ts +2 -1
- package/src/daemon/conversation-process.ts +35 -64
- package/src/daemon/conversation-runtime-assembly.ts +2 -1
- package/src/daemon/conversation-skill-tools.ts +13 -31
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +15 -9
- package/src/daemon/conversation-tool-setup.ts +37 -43
- package/src/daemon/conversation.ts +0 -3
- package/src/daemon/dictation-profile-store.ts +2 -1
- package/src/daemon/handlers/shared.ts +2 -1
- package/src/daemon/handlers/skills.ts +6 -3
- package/src/daemon/host-bash-proxy.ts +8 -12
- package/src/daemon/host-browser-proxy.ts +15 -1
- package/src/daemon/host-cu-proxy.ts +186 -19
- package/src/daemon/host-file-proxy.ts +8 -10
- package/src/daemon/host-proxy-preactivation.ts +2 -1
- package/src/daemon/host-transfer-proxy.ts +14 -18
- package/src/daemon/lifecycle.ts +0 -5
- package/src/daemon/mcp-reload-service.ts +5 -5
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/orphan-reaper.ts +1 -1
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/reaction-history-render.ts +2 -1
- package/src/daemon/shutdown-handlers.ts +1 -9
- package/src/daemon/skill-memory-refresh.ts +64 -0
- package/src/daemon/tool-side-effects.ts +7 -18
- package/src/desktop/__tests__/fake-desktop.ts +122 -0
- package/src/desktop/desktop-chrome-policy.test.ts +79 -0
- package/src/desktop/desktop-chrome-policy.ts +47 -0
- package/src/desktop/desktop-chrome-session.ts +37 -0
- package/src/desktop/desktop-dependencies.test.ts +102 -0
- package/src/desktop/desktop-dependencies.ts +308 -0
- package/src/desktop/desktop-feature.test.ts +18 -0
- package/src/desktop/desktop-feature.ts +19 -0
- package/src/desktop/desktop-panel-config.test.ts +135 -0
- package/src/desktop/desktop-panel-config.ts +149 -0
- package/src/desktop/desktop-session-manager.test.ts +730 -0
- package/src/desktop/desktop-session-manager.ts +850 -0
- package/src/desktop/desktop-stream-bridge.test.ts +395 -0
- package/src/desktop/desktop-stream-bridge.ts +214 -0
- package/src/desktop/desktop-wallpaper.test.ts +191 -0
- package/src/desktop/desktop-wallpaper.ts +113 -0
- package/src/desktop/desktop-window-drag.ts +177 -0
- package/src/desktop/desktop-window-manager-config.test.ts +230 -0
- package/src/desktop/desktop-window-manager-config.ts +238 -0
- package/src/desktop/desktop-window-theme.ts +170 -0
- package/src/heartbeat/heartbeat-service.ts +21 -3
- package/src/home/__tests__/feed-writer.test.ts +22 -0
- package/src/home/feed-writer.ts +11 -2
- package/src/hooks/types.ts +33 -0
- package/src/i18n/AGENTS.md +22 -0
- package/src/i18n/__tests__/i18n.test.ts +108 -0
- package/src/i18n/index.ts +16 -0
- package/src/i18n/locales.ts +93 -0
- package/src/i18n/messages.ts +61 -0
- package/src/i18n/title.ts +25 -0
- package/src/inbound/platform-callback-registration.ts +4 -5
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
- package/src/live-voice/live-voice-photo.ts +25 -6
- package/src/live-voice/live-voice-session.ts +213 -693
- package/src/live-voice/protocol.ts +0 -2
- package/src/mcp/__tests__/effective-config.test.ts +2 -2
- package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
- package/src/mcp/effective-config.ts +3 -3
- package/src/mcp/mcp-header-store.ts +29 -45
- package/src/mcp/spec-schema.ts +111 -0
- package/src/mcp/startup.ts +8 -4
- package/src/mcp/workspace-mcp-config.ts +188 -0
- package/src/messaging/provider.ts +10 -3
- package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
- package/src/messaging/providers/callback-routing.ts +18 -0
- package/src/messaging/providers/channel-transport.ts +56 -0
- package/src/messaging/providers/discord/transport.ts +17 -0
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
- package/src/messaging/providers/slack/adapter.ts +7 -44
- package/src/messaging/providers/slack/transport.ts +16 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
- package/src/messaging/providers/telegram-bot/client.ts +0 -26
- package/src/messaging/providers/telegram-bot/transport.ts +20 -0
- package/src/messaging/providers/whatsapp/adapter.ts +1 -48
- package/src/messaging/providers/whatsapp/transport.ts +18 -0
- package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
- package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
- package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
- package/src/notifications/adapters/macos.ts +3 -0
- package/src/notifications/assistant-reply-producer.ts +8 -3
- package/src/notifications/conversation-pairing.ts +36 -16
- package/src/notifications/delivered-post-record.ts +11 -1
- package/src/notifications/guardian-feed-projection.ts +125 -5
- package/src/notifications/home-feed-side-effect.ts +55 -7
- package/src/notifications/schedule-result-producer.ts +66 -22
- package/src/oauth/AGENTS.md +2 -0
- package/src/oauth/__tests__/seed-providers-managed.test.ts +54 -0
- package/src/oauth/byo-connection.test.ts +105 -0
- package/src/oauth/byo-connection.ts +36 -6
- package/src/oauth/connection-resolver.test.ts +73 -0
- package/src/oauth/connection-resolver.ts +95 -2
- package/src/oauth/scope-utils.ts +24 -0
- package/src/oauth/seed-providers.ts +204 -25
- package/src/outbound-proxy/certs.ts +3 -5
- package/src/permissions/checker.test.ts +11 -6
- package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
- package/src/persistence/conversation-crud.ts +71 -63
- package/src/persistence/conversation-lineage.ts +12 -4
- package/src/persistence/conversation-queries.ts +2 -2
- package/src/persistence/conversation-title-placeholders.ts +23 -0
- package/src/persistence/conversation-title-service.ts +9 -26
- package/src/persistence/embeddings/qdrant-manager.ts +163 -18
- package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
- package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
- package/src/persistence/message-cursor.ts +78 -0
- package/src/persistence/message-reads.ts +30 -0
- package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
- package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
- package/src/persistence/schema/memory-core.ts +5 -0
- package/src/platform/client.test.ts +4 -2
- package/src/platform/client.ts +2 -10
- package/src/plugin-api/constants.ts +2 -0
- package/src/plugin-api/index.ts +1 -0
- package/src/plugin-api/types.ts +2 -0
- package/src/plugins/defaults/index.ts +2 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +20 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +5 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -2
- package/src/plugins/defaults/memory/context-search/format.ts +3 -2
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +6 -3
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +3 -2
- package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -7
- package/src/plugins/defaults/memory/hooks/init.ts +10 -0
- package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
- package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
- package/src/plugins/defaults/memory/host-utils.ts +10 -0
- package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
- package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
- package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
- package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +12 -3
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
- package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
- package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
- package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
- package/src/plugins/defaults/memory/startup.ts +28 -2
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
- package/src/plugins/defaults/memory/substrate/page-index.ts +6 -1
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
- package/src/plugins/defaults/memory/v2/reranker.ts +6 -1
- package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -0
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +125 -0
- package/src/plugins/defaults/memory/v3/__tests__/sections.test.ts +26 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +30 -0
- package/src/plugins/defaults/memory/v3/card.ts +3 -2
- package/src/plugins/defaults/memory/v3/pool-select.ts +5 -3
- package/src/plugins/defaults/memory/v3/sections.ts +9 -3
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +5 -2
- package/src/plugins/defaults/memory/worker.ts +6 -0
- package/src/plugins/mcp-servers.ts +15 -75
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
- package/src/providers/__tests__/retry-callsite.test.ts +41 -0
- package/src/providers/__tests__/retry-outbound-sanitize.test.ts +176 -0
- package/src/providers/anthropic/client.ts +0 -47
- package/src/providers/gemini/client.ts +9 -23
- package/src/providers/gemini-thought-signature.test.ts +63 -0
- package/src/providers/gemini-thought-signature.ts +44 -0
- package/src/providers/inference/__tests__/endpoint-probe.test.ts +42 -3
- package/src/providers/inference/auth.ts +2 -3
- package/src/providers/inference/connection-availability.ts +27 -8
- package/src/providers/inference/endpoint-probe.ts +10 -1
- package/src/providers/inference/resolve-auth.ts +22 -4
- package/src/providers/inference/service-account-token.ts +248 -0
- package/src/providers/model-catalog.ts +34 -0
- package/src/providers/model-intents.ts +10 -5
- package/src/providers/openai/__tests__/chat-completions-output-token-limit.test.ts +141 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
- package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
- package/src/providers/openai/chat-completions-provider.ts +212 -79
- package/src/providers/openai/codex-models.ts +0 -4
- package/src/providers/openai/google-thought-signature.ts +320 -0
- package/src/providers/opencode/client.test.ts +73 -4
- package/src/providers/opencode/client.ts +60 -3
- package/src/providers/openrouter/client.ts +20 -0
- package/src/providers/outbound-request-sanitize.ts +96 -0
- package/src/providers/retry.ts +30 -19
- package/src/providers/unparseable-tool-args.ts +5 -1
- package/src/runtime/AGENTS.md +3 -1
- package/src/runtime/__tests__/channel-send.test.ts +443 -0
- package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +89 -0
- package/src/runtime/__tests__/host-observe.test.ts +40 -1
- package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
- package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
- package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
- package/src/runtime/agent-wake.ts +2 -1
- package/src/runtime/assistant-event-hub.ts +21 -3
- package/src/runtime/auth/same-actor.ts +38 -3
- package/src/runtime/channel-send.ts +316 -0
- package/src/runtime/host-observe.ts +11 -1
- package/src/runtime/http-server.ts +160 -151
- package/src/runtime/routes/__tests__/acp-routes.test.ts +159 -4
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +205 -0
- package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
- package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
- package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
- package/src/runtime/routes/acp-routes.test.ts +15 -0
- package/src/runtime/routes/acp-routes.ts +72 -9
- package/src/runtime/routes/app-management-routes.ts +73 -0
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/channel-send-routes.ts +85 -0
- package/src/runtime/routes/conversation-list-routes.ts +14 -3
- package/src/runtime/routes/conversation-query-routes.ts +40 -0
- package/src/runtime/routes/conversation-routes.ts +16 -3
- package/src/runtime/routes/credential-routes.ts +19 -10
- package/src/runtime/routes/desktop-setup-routes.test.ts +74 -0
- package/src/runtime/routes/desktop-setup-routes.ts +35 -0
- package/src/runtime/routes/diagnostics-routes.ts +61 -4
- package/src/runtime/routes/events-routes.ts +4 -0
- package/src/runtime/routes/host-cu-routes.ts +6 -0
- package/src/runtime/routes/index.ts +4 -2
- package/src/runtime/routes/log-export-routes.ts +2 -0
- package/src/runtime/routes/mcp-auth-routes.ts +39 -47
- package/src/runtime/routes/migration-routes.ts +6 -20
- package/src/runtime/routes/oauth-commands-routes.ts +36 -0
- package/src/runtime/routes/platform-routes.ts +18 -15
- package/src/runtime/routes/workspace-routes.test.ts +55 -26
- package/src/runtime/routes/workspace-routes.ts +46 -63
- package/src/runtime/routes/workspace-tree-walk.test.ts +244 -0
- package/src/runtime/routes/workspace-tree-walk.ts +240 -0
- package/src/runtime/routes/workspace-utils.ts +17 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +16 -3
- package/src/runtime/sync/resource-sync-events.ts +2 -1
- package/src/schedule/run-script.ts +2 -1
- package/src/schedule/schedule-store.ts +9 -2
- package/src/schedule/worker.ts +1 -1
- package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
- package/src/security/ces-http-record-backend.ts +120 -0
- package/src/security/ces-rpc-record-backend.ts +7 -0
- package/src/security/untrusted-content.ts +3 -1
- package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
- package/src/skills/workspace-skill-md-signature.ts +50 -0
- package/src/subagent/consult-context.ts +12 -25
- package/src/tools/__tests__/side-effect-abort-guard.test.ts +1 -0
- package/src/tools/acp/list-agents.test.ts +3 -1
- package/src/tools/acp/spawn.test.ts +146 -11
- package/src/tools/acp/spawn.ts +21 -3
- package/src/tools/acp/status.test.ts +94 -0
- package/src/tools/acp/status.ts +40 -3
- package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +3 -2
- package/src/tools/browser/network-recorder.ts +2 -1
- package/src/tools/capability-offer.test.ts +22 -2
- package/src/tools/capability-offer.ts +16 -1
- package/src/tools/computer-use/definitions.ts +121 -2
- package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
- package/src/tools/credentials/metadata-store.ts +100 -0
- package/src/tools/filesystem/search.ts +2 -1
- package/src/tools/host-filesystem/edit.test.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +2 -2
- package/src/tools/host-filesystem/read.test.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/transfer.test.ts +2 -1
- package/src/tools/host-filesystem/transfer.ts +2 -2
- package/src/tools/host-filesystem/write.test.ts +2 -1
- package/src/tools/host-filesystem/write.ts +2 -2
- package/src/tools/host-terminal/host-shell.test.ts +16 -0
- package/src/tools/host-terminal/host-shell.ts +4 -20
- package/src/tools/network/web-search.ts +6 -1
- package/src/tools/policy-context.ts +6 -7
- package/src/tools/skills/scaffold-managed.ts +61 -3
- package/src/tools/subagent/spawn.ts +5 -8
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +57 -0
- package/src/tools/terminal/sanitized-bash.ts +105 -0
- package/src/tools/watch/watch-retro-report.ts +0 -8
- package/src/types/host-capabilities.ts +5 -3
- package/src/util/__tests__/language-subtag.test.ts +23 -1
- package/src/util/ca-bundle.ts +13 -0
- package/src/util/language-subtag.ts +16 -0
- package/src/util/platform.ts +8 -0
- package/src/util/unicode.ts +15 -1
- package/src/watch/watch-timeline.ts +2 -2
- package/src/workflows/run-manager.ts +2 -1
- package/src/workspace/git-porcelain.ts +66 -0
- package/src/workspace/git-service.ts +6 -55
- package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
- package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
- package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
- package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/app-source-watcher.test.ts +0 -218
- package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
- package/src/__tests__/speaker-identification.test.ts +0 -56
- package/src/calls/speaker-identification.ts +0 -233
- package/src/daemon/app-source-watcher.ts +0 -218
- package/src/messaging/providers/whatsapp/client.ts +0 -29
- package/src/runtime/routes/debug-bash-routes.ts +0 -173
- package/src/util/fs-watcher-error.ts +0 -36
- /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterAll,
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
spyOn,
|
|
8
|
+
test,
|
|
9
|
+
} from "bun:test";
|
|
10
|
+
|
|
11
|
+
import { setOverridesForTesting } from "../../__tests__/feature-flag-test-helpers.js";
|
|
12
|
+
import { desktopDependencyInstaller } from "../../desktop/desktop-dependencies.js";
|
|
13
|
+
import { ROUTES } from "./desktop-setup-routes.js";
|
|
14
|
+
import { NotFoundError } from "./errors.js";
|
|
15
|
+
|
|
16
|
+
const originalContainerized = process.env.IS_CONTAINERIZED;
|
|
17
|
+
const status = spyOn(desktopDependencyInstaller, "getStatus");
|
|
18
|
+
const start = spyOn(desktopDependencyInstaller, "start");
|
|
19
|
+
|
|
20
|
+
afterAll(() => {
|
|
21
|
+
status.mockRestore();
|
|
22
|
+
start.mockRestore();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
27
|
+
status.mockReturnValue({ state: "required" });
|
|
28
|
+
start.mockReturnValue({ state: "installing", stage: "packages" });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
if (originalContainerized === undefined) {
|
|
33
|
+
delete process.env.IS_CONTAINERIZED;
|
|
34
|
+
} else {
|
|
35
|
+
process.env.IS_CONTAINERIZED = originalContainerized;
|
|
36
|
+
}
|
|
37
|
+
setOverridesForTesting({});
|
|
38
|
+
status.mockClear();
|
|
39
|
+
start.mockClear();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("desktop setup route feature gate", () => {
|
|
43
|
+
for (const route of ROUTES) {
|
|
44
|
+
for (const flag of [false, undefined]) {
|
|
45
|
+
test(`${route.method} refuses a disabled or missing flag (${flag}) without touching setup`, () => {
|
|
46
|
+
setOverridesForTesting(
|
|
47
|
+
flag === undefined ? {} : { "assistant-desktop": flag },
|
|
48
|
+
);
|
|
49
|
+
expect(() => route.handler({})).toThrow(NotFoundError);
|
|
50
|
+
expect(status).not.toHaveBeenCalled();
|
|
51
|
+
expect(start).not.toHaveBeenCalled();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
test(`${route.method} refuses non-containerized assistants even with the flag enabled`, () => {
|
|
56
|
+
process.env.IS_CONTAINERIZED = "false";
|
|
57
|
+
setOverridesForTesting({ "assistant-desktop": true });
|
|
58
|
+
expect(() => route.handler({})).toThrow(NotFoundError);
|
|
59
|
+
expect(status).not.toHaveBeenCalled();
|
|
60
|
+
expect(start).not.toHaveBeenCalled();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test(`${route.method} serves setup only with the flag enabled in a container`, () => {
|
|
64
|
+
setOverridesForTesting({ "assistant-desktop": true });
|
|
65
|
+
expect(route.handler({})).toEqual(
|
|
66
|
+
route.method === "GET"
|
|
67
|
+
? { state: "required" }
|
|
68
|
+
: { state: "installing", stage: "packages" },
|
|
69
|
+
);
|
|
70
|
+
expect(route.method === "GET" ? status : start).toHaveBeenCalledTimes(1);
|
|
71
|
+
expect(route.method === "GET" ? start : status).not.toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { getConfig } from "../../config/loader.js";
|
|
4
|
+
import { desktopDependencyInstaller } from "../../desktop/desktop-dependencies.js";
|
|
5
|
+
import { isAssistantDesktopEnabled } from "../../desktop/desktop-feature.js";
|
|
6
|
+
import { GATEWAY_PRINCIPALS } from "../auth/route-policy.js";
|
|
7
|
+
import { NotFoundError } from "./errors.js";
|
|
8
|
+
import type { RouteDefinition } from "./types.js";
|
|
9
|
+
|
|
10
|
+
const statusSchema = z.object({
|
|
11
|
+
state: z.enum(["required", "installing", "ready", "failed", "unsupported"]),
|
|
12
|
+
stage: z.enum(["packages", "chrome", "checking"]).optional(),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const ROUTES: RouteDefinition[] = ["GET", "POST"].map((method) => ({
|
|
16
|
+
operationId:
|
|
17
|
+
method === "GET" ? "desktop_setup_status" : "desktop_setup_install",
|
|
18
|
+
endpoint: "desktop/setup",
|
|
19
|
+
method,
|
|
20
|
+
policy: { requiredScopes: [], allowedPrincipalTypes: GATEWAY_PRINCIPALS },
|
|
21
|
+
handler: () => {
|
|
22
|
+
if (!isAssistantDesktopEnabled(getConfig())) {
|
|
23
|
+
throw new NotFoundError("Desktop is not available on this assistant");
|
|
24
|
+
}
|
|
25
|
+
return method === "GET"
|
|
26
|
+
? desktopDependencyInstaller.getStatus()
|
|
27
|
+
: desktopDependencyInstaller.start();
|
|
28
|
+
},
|
|
29
|
+
summary:
|
|
30
|
+
method === "GET"
|
|
31
|
+
? "Get desktop setup status"
|
|
32
|
+
: "Install desktop components",
|
|
33
|
+
tags: ["desktop"],
|
|
34
|
+
responseBody: statusSchema,
|
|
35
|
+
}));
|
|
@@ -22,7 +22,9 @@ 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";
|
|
27
|
+
import { safeStringSlice } from "../../util/unicode.js";
|
|
26
28
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
27
29
|
import { BadRequestError } from "./errors.js";
|
|
28
30
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
@@ -48,7 +50,11 @@ function sanitizeWindowTitle(title: string | undefined): string {
|
|
|
48
50
|
if (!title) {
|
|
49
51
|
return "";
|
|
50
52
|
}
|
|
51
|
-
return
|
|
53
|
+
return safeStringSlice(
|
|
54
|
+
title.replace(/[<>]/g, ""),
|
|
55
|
+
0,
|
|
56
|
+
MAX_WINDOW_TITLE_LENGTH,
|
|
57
|
+
);
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
interface DictationBody {
|
|
@@ -176,9 +182,44 @@ function buildCommandPrompt(body: DictationBody, stylePrompt?: string): string {
|
|
|
176
182
|
return sections.join("\n");
|
|
177
183
|
}
|
|
178
184
|
|
|
179
|
-
function computeMaxTokens(inputLength: number): number {
|
|
185
|
+
export function computeMaxTokens(inputLength: number): number {
|
|
180
186
|
const estimatedInputTokens = Math.ceil(inputLength / 3);
|
|
181
|
-
|
|
187
|
+
// The cleanup tool call carries the whole transcript back in its `text`
|
|
188
|
+
// argument, plus a `reasoning` string and the JSON scaffolding around both,
|
|
189
|
+
// so the budget has to cover well more than the input alone. `max_tokens` is
|
|
190
|
+
// a ceiling rather than a target: a call that stops short of it costs no
|
|
191
|
+
// extra latency.
|
|
192
|
+
return Math.max(512, estimatedInputTokens * 2 + 256);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export type CleanupRejection = "truncated";
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Decide whether the cleanup model's rewrite is safe to use as the payload.
|
|
199
|
+
*
|
|
200
|
+
* The rewrite replaces what the user actually said. A token-cap stop means the
|
|
201
|
+
* tool JSON was cut mid-argument, so however complete the `text` argument
|
|
202
|
+
* happens to look, it is a fragment; the raw transcript is the safer payload
|
|
203
|
+
* then. Unpolished beats wrong.
|
|
204
|
+
*
|
|
205
|
+
* Whether a shorter rewrite still preserved the meaning is the model's call
|
|
206
|
+
* (the prompt asks it to drop fillers and tighten phrasing), so there is no
|
|
207
|
+
* length check here: a deterministic ratio cannot tell a concise cleanup from
|
|
208
|
+
* a summary.
|
|
209
|
+
*/
|
|
210
|
+
export function resolveCleanedDictation(
|
|
211
|
+
raw: string,
|
|
212
|
+
cleaned: string,
|
|
213
|
+
stopReason: string | null | undefined,
|
|
214
|
+
): { text: string; rejected: CleanupRejection | null } {
|
|
215
|
+
const trimmed = cleaned.trim();
|
|
216
|
+
if (!trimmed) {
|
|
217
|
+
return { text: raw, rejected: null };
|
|
218
|
+
}
|
|
219
|
+
if (isMaxTokensStopReason(stopReason)) {
|
|
220
|
+
return { text: raw, rejected: "truncated" };
|
|
221
|
+
}
|
|
222
|
+
return { text: trimmed, rejected: null };
|
|
182
223
|
}
|
|
183
224
|
|
|
184
225
|
interface DictationResult {
|
|
@@ -329,7 +370,23 @@ async function handleDictation(body: DictationBody): Promise<DictationResult> {
|
|
|
329
370
|
...profileMeta,
|
|
330
371
|
};
|
|
331
372
|
}
|
|
332
|
-
const cleanedText =
|
|
373
|
+
const { text: cleanedText, rejected } = resolveCleanedDictation(
|
|
374
|
+
transcription,
|
|
375
|
+
input.text ?? "",
|
|
376
|
+
response.stopReason,
|
|
377
|
+
);
|
|
378
|
+
if (rejected) {
|
|
379
|
+
// Lengths only -- transcript content must never be logged.
|
|
380
|
+
log.warn(
|
|
381
|
+
{
|
|
382
|
+
rejected,
|
|
383
|
+
stopReason: response.stopReason,
|
|
384
|
+
rawChars: transcription.length,
|
|
385
|
+
cleanedChars: input.text?.trim().length ?? 0,
|
|
386
|
+
},
|
|
387
|
+
"Dictation cleanup rejected, using raw transcription",
|
|
388
|
+
);
|
|
389
|
+
}
|
|
333
390
|
const normalizedText = applyDictionary(cleanedText, profile.dictionary);
|
|
334
391
|
return {
|
|
335
392
|
text: normalizedText,
|
|
@@ -445,6 +445,10 @@ export function handleSubscribeAssistantEvents(
|
|
|
445
445
|
? ["host_cu_window_capture" as const]
|
|
446
446
|
: []),
|
|
447
447
|
...(interfaceId === "macos" &&
|
|
448
|
+
headers?.["x-vellum-cu-sequence"] === "1"
|
|
449
|
+
? ["host_cu_sequence" as const]
|
|
450
|
+
: []),
|
|
451
|
+
...(interfaceId === "macos" &&
|
|
448
452
|
headers?.["x-vellum-cu-annotate"] === "1"
|
|
449
453
|
? ["host_cu_annotate" as const]
|
|
450
454
|
: []),
|
|
@@ -36,6 +36,10 @@ const HostCuResultBodySchema = z.object({
|
|
|
36
36
|
executionError: z.string().optional(),
|
|
37
37
|
secondaryWindows: z.string().optional(),
|
|
38
38
|
userGuidance: z.string().optional(),
|
|
39
|
+
timings: z
|
|
40
|
+
.record(z.string(), z.number())
|
|
41
|
+
.describe("Per-phase helper timings in milliseconds")
|
|
42
|
+
.optional(),
|
|
39
43
|
});
|
|
40
44
|
|
|
41
45
|
// ---------------------------------------------------------------------------
|
|
@@ -56,6 +60,7 @@ async function handleHostCuResult({ body, headers }: RouteHandlerArgs) {
|
|
|
56
60
|
executionError,
|
|
57
61
|
secondaryWindows,
|
|
58
62
|
userGuidance,
|
|
63
|
+
timings,
|
|
59
64
|
} = parseBody(HostCuResultBodySchema, body);
|
|
60
65
|
|
|
61
66
|
const peeked = pendingInteractions.get(requestId);
|
|
@@ -119,6 +124,7 @@ async function handleHostCuResult({ body, headers }: RouteHandlerArgs) {
|
|
|
119
124
|
executionError,
|
|
120
125
|
secondaryWindows,
|
|
121
126
|
userGuidance,
|
|
127
|
+
timings,
|
|
122
128
|
});
|
|
123
129
|
|
|
124
130
|
return { accepted: true };
|
|
@@ -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
|
}
|
|
@@ -41,9 +41,11 @@ import {
|
|
|
41
41
|
listConnections,
|
|
42
42
|
type OAuthProviderRow,
|
|
43
43
|
} from "../../oauth/oauth-store.js";
|
|
44
|
+
import { missingScopesForStoredToken } from "../../oauth/scope-utils.js";
|
|
44
45
|
import { VellumPlatformClient } from "../../platform/client.js";
|
|
45
46
|
import { withValidToken } from "../../security/token-manager.js";
|
|
46
47
|
import { matchHostPattern } from "../../tools/credentials/host-pattern-match.js";
|
|
48
|
+
import { parseJsonSafe } from "../../util/json.js";
|
|
47
49
|
import { getLogger } from "../../util/logger.js";
|
|
48
50
|
import {
|
|
49
51
|
findContentTypeHeader,
|
|
@@ -230,6 +232,31 @@ function assertOAuthRequestUrlAllowed(
|
|
|
230
232
|
}
|
|
231
233
|
}
|
|
232
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Required scopes the resolved connection's stored grant lacks. Credential
|
|
237
|
+
* health measures the same thing on the heartbeat; measuring it on the
|
|
238
|
+
* request names the gap at the moment a call may depend on it, since a
|
|
239
|
+
* connection made before a scope was required keeps working for every call
|
|
240
|
+
* that does not need it. A managed connection has no local row and reports
|
|
241
|
+
* nothing.
|
|
242
|
+
*/
|
|
243
|
+
function missingScopesForConnection(
|
|
244
|
+
providerRow: OAuthProviderRow,
|
|
245
|
+
connectionId: string,
|
|
246
|
+
): string[] {
|
|
247
|
+
const row = getConnection(connectionId);
|
|
248
|
+
if (!row) {
|
|
249
|
+
return [];
|
|
250
|
+
}
|
|
251
|
+
return missingScopesForStoredToken(
|
|
252
|
+
parseJsonSafe<string[]>(providerRow.defaultScopes ?? "[]") ?? [],
|
|
253
|
+
parseJsonSafe<Record<string, string>>(providerRow.authorizeParams ?? "") ??
|
|
254
|
+
undefined,
|
|
255
|
+
providerRow.scopeSeparator,
|
|
256
|
+
parseJsonSafe<string[]>(row.grantedScopes ?? "[]") ?? [],
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
233
260
|
// ---------------------------------------------------------------------------
|
|
234
261
|
// Disconnect handler
|
|
235
262
|
// ---------------------------------------------------------------------------
|
|
@@ -1002,6 +1029,15 @@ export async function handleRequest({ body = {} }: RouteHandlerArgs) {
|
|
|
1002
1029
|
`(e.g. https://host/full/path) so the host and full path are set explicitly.`;
|
|
1003
1030
|
}
|
|
1004
1031
|
|
|
1032
|
+
const missingScopes = missingScopesForConnection(providerRow, connection.id);
|
|
1033
|
+
if (missingScopes.length > 0) {
|
|
1034
|
+
const scopeHint =
|
|
1035
|
+
`The ${b.provider} connection is missing required scopes: ${missingScopes.join(", ")}. ` +
|
|
1036
|
+
`It was connected before they were required, so calls that need them fail. ` +
|
|
1037
|
+
`Reconnect it from Integrations, or run 'assistant oauth connect ${b.provider}', to grant them.`;
|
|
1038
|
+
result.hint = result.hint ? `${scopeHint}\n\n${result.hint}` : scopeHint;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1005
1041
|
return result;
|
|
1006
1042
|
}
|
|
1007
1043
|
|
|
@@ -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
|
|