@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
|
@@ -137,7 +137,7 @@ const VELLUM_PROFILE_IMPLS: ProfileImpls = {
|
|
|
137
137
|
// The managed latency class, also what the live-voice front model runs on.
|
|
138
138
|
// Its leading tokens are the turn-taking verdict, so what this profile
|
|
139
139
|
// optimizes is the tail of time-to-first-token rather than the median: a
|
|
140
|
-
// verdict slower than `
|
|
140
|
+
// verdict slower than `voice.frontModel.endpointDecisionTimeoutMs`
|
|
141
141
|
// trips the speculative fail-open commit in live-voice-session.ts, which
|
|
142
142
|
// is audible dead air.
|
|
143
143
|
//
|
package/src/config/env.ts
CHANGED
|
@@ -229,8 +229,8 @@ export function setPlatformAssistantId(value: string | undefined): void {
|
|
|
229
229
|
* Platform assistant ID — UUID of this assistant on the platform.
|
|
230
230
|
*
|
|
231
231
|
* Resolved from the in-memory override (populated by providers-setup
|
|
232
|
-
* rehydration
|
|
233
|
-
*
|
|
232
|
+
* rehydration via platform validate, or by secret-routes when the
|
|
233
|
+
* platform pushes the value).
|
|
234
234
|
*/
|
|
235
235
|
export function getPlatformAssistantId(): string {
|
|
236
236
|
return _platformAssistantIdOverride ?? "";
|
|
@@ -29,18 +29,6 @@
|
|
|
29
29
|
"description": "Enable user-hosted onboarding flow",
|
|
30
30
|
"defaultEnabled": false
|
|
31
31
|
},
|
|
32
|
-
{
|
|
33
|
-
"id": "proactive-tips",
|
|
34
|
-
"scope": "client",
|
|
35
|
-
"key": "proactive-tips",
|
|
36
|
-
"label": "Proactive Tips",
|
|
37
|
-
"description": "Gates the dismissible proactive tip card in the web sidebar. String-valued so future A/B arms can be added as new values.",
|
|
38
|
-
"defaultEnabled": "off",
|
|
39
|
-
"values": [
|
|
40
|
-
"off",
|
|
41
|
-
"on"
|
|
42
|
-
]
|
|
43
|
-
},
|
|
44
32
|
{
|
|
45
33
|
"id": "vision-mode",
|
|
46
34
|
"scope": "client",
|
|
@@ -454,6 +442,14 @@
|
|
|
454
442
|
"description": "Native notifications show the assistant's avatar as the icon with the assistant's name on line one. Same key the platform reads for APNs/FCM sender blocks.",
|
|
455
443
|
"defaultEnabled": false
|
|
456
444
|
},
|
|
445
|
+
{
|
|
446
|
+
"id": "local-notification-avatar",
|
|
447
|
+
"scope": "client",
|
|
448
|
+
"key": "local-notification-avatar",
|
|
449
|
+
"label": "Local Notification Avatar",
|
|
450
|
+
"description": "Shows the assistant name and avatar in notifications posted locally by native clients and supported browsers. Independent of remote push avatar presentation.",
|
|
451
|
+
"defaultEnabled": false
|
|
452
|
+
},
|
|
457
453
|
{
|
|
458
454
|
"id": "channel-conversation-sidecar",
|
|
459
455
|
"scope": "client",
|
|
@@ -478,6 +474,14 @@
|
|
|
478
474
|
"description": "Gates the seeded Figma OAuth provider. When off, the provider is hidden from GET /v1/oauth/providers, its get-by-id route, and the connect/update routes, so it cannot be listed or connected from the CLI, gateway, or web integrations list. The row is still seeded into oauth_providers on startup, and existing connections keep injecting credentials; only its visibility changes.",
|
|
479
475
|
"defaultEnabled": false
|
|
480
476
|
},
|
|
477
|
+
{
|
|
478
|
+
"id": "shopify-oauth",
|
|
479
|
+
"scope": "assistant",
|
|
480
|
+
"key": "shopify-oauth",
|
|
481
|
+
"label": "Shopify Integration",
|
|
482
|
+
"description": "Gates the seeded Shopify OAuth provider. When off, the provider is hidden from GET /v1/oauth/providers, its get-by-id route, and the connect/update routes, so it cannot be listed or connected from the CLI, gateway, or web integrations list. The row is still seeded into oauth_providers on startup, and existing connections keep injecting credentials; only its visibility changes. Off by default because Shopify is the first per-tenant provider: connecting needs the merchant's myshopify.com domain, and the shop-domain input in the clients ships separately from the seed.",
|
|
483
|
+
"defaultEnabled": false
|
|
484
|
+
},
|
|
481
485
|
{
|
|
482
486
|
"id": "chatgpt-device-code-login",
|
|
483
487
|
"scope": "client",
|
|
@@ -523,6 +527,14 @@
|
|
|
523
527
|
"label": "Send User Message Tool",
|
|
524
528
|
"description": "Route all user-facing assistant text through the send_user_message tool instead of streamed assistant text",
|
|
525
529
|
"defaultEnabled": false
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
"id": "assistant-desktop",
|
|
533
|
+
"scope": "assistant",
|
|
534
|
+
"key": "assistant-desktop",
|
|
535
|
+
"label": "Assistant Desktop",
|
|
536
|
+
"description": "Streams an interactive desktop from a containerized assistant pod to the web client over /v1/desktop/stream. Off: no desktop affordance is rendered. On: the chat header offers a desktop panel that views and controls the pod's display.",
|
|
537
|
+
"defaultEnabled": false
|
|
526
538
|
}
|
|
527
539
|
]
|
|
528
540
|
}
|
package/src/config/loader.ts
CHANGED
|
@@ -180,6 +180,7 @@ export function getDeploymentContextDefaults(): Record<string, unknown> {
|
|
|
180
180
|
"discord-oauth": managed,
|
|
181
181
|
"hubspot-oauth": managed,
|
|
182
182
|
"monday-oauth": managed,
|
|
183
|
+
"shopify-oauth": managed,
|
|
183
184
|
"stripe-link-oauth": managed,
|
|
184
185
|
"figma-oauth": managed,
|
|
185
186
|
"eventbrite-oauth": managed,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
isMemoryV1Active,
|
|
7
7
|
isMemoryV2ExplicitlyDisabled,
|
|
8
8
|
isMemoryV3Live,
|
|
9
|
+
isSkillImprovementActive,
|
|
9
10
|
isV2InjectionEngineActive,
|
|
10
11
|
isV3TierActive,
|
|
11
12
|
usesConceptPageMemory,
|
|
@@ -55,12 +56,16 @@ function makeConfig(
|
|
|
55
56
|
enabled: TriState,
|
|
56
57
|
v2Enabled: TriState,
|
|
57
58
|
v3Live: TriState,
|
|
59
|
+
skillImprovement?: boolean,
|
|
58
60
|
): AssistantConfig {
|
|
59
61
|
return {
|
|
60
62
|
memory: {
|
|
61
63
|
...(enabled === undefined ? {} : { enabled }),
|
|
62
64
|
...(v2Enabled === undefined ? {} : { v2: { enabled: v2Enabled } }),
|
|
63
65
|
...(v3Live === undefined ? {} : { v3: { live: v3Live } }),
|
|
66
|
+
...(skillImprovement === undefined
|
|
67
|
+
? {}
|
|
68
|
+
: { retrospective: { skillImprovement } }),
|
|
64
69
|
},
|
|
65
70
|
} as AssistantConfig;
|
|
66
71
|
}
|
|
@@ -296,6 +301,32 @@ describe("v1-staleness guard is one condition", () => {
|
|
|
296
301
|
* proc-to-skills alias of `isMemoryV3Live` (which did not). One predicate now
|
|
297
302
|
* answers for both features.
|
|
298
303
|
*/
|
|
304
|
+
describe("skill improvement gate", () => {
|
|
305
|
+
test("defaults on for a live v3 tier", () => {
|
|
306
|
+
expect(isSkillImprovementActive(makeConfig(true, undefined, true))).toBe(
|
|
307
|
+
true,
|
|
308
|
+
);
|
|
309
|
+
expect(isSkillImprovementActive(makeConfig(undefined, undefined, true))).toBe(
|
|
310
|
+
true,
|
|
311
|
+
);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
test("explicit opt-out disables skill improvement without disabling v3", () => {
|
|
315
|
+
const config = makeConfig(true, undefined, true, false);
|
|
316
|
+
|
|
317
|
+
expect(isV3TierActive(config)).toBe(true);
|
|
318
|
+
expect(isSkillImprovementActive(config)).toBe(false);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
test("requires the live v3 tier even when explicitly enabled", () => {
|
|
322
|
+
const v2Config = makeConfig(true, true, false, true);
|
|
323
|
+
const memoryOffConfig = makeConfig(false, undefined, true, true);
|
|
324
|
+
|
|
325
|
+
expect(isSkillImprovementActive(v2Config)).toBe(false);
|
|
326
|
+
expect(isSkillImprovementActive(memoryOffConfig)).toBe(false);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
|
|
299
330
|
describe("v3 tier is one condition", () => {
|
|
300
331
|
test("memory off suppresses the v3 tier even with memory.v3.live set", () => {
|
|
301
332
|
const config = makeConfig(false, undefined, true);
|
|
@@ -81,28 +81,32 @@ export function isMemoryV3Live(config: AssistantConfig): boolean {
|
|
|
81
81
|
* FEATURE asks this predicate; only the injection-suppression checks that must
|
|
82
82
|
* mirror the raw `memory.v3.live` key ask {@link isMemoryV3Live} directly.
|
|
83
83
|
*
|
|
84
|
-
* The
|
|
84
|
+
* The memory concept graph is gated on it: both `GET /memory-graph`
|
|
85
|
+
* (`supported`) and the cheap `graph_supported` bit on `GET /memory/stats`
|
|
86
|
+
* must agree with whether the graph can build from the v3 concept-page
|
|
87
|
+
* substrate.
|
|
85
88
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* never drift. The graph builds off the v3 concept-page substrate.
|
|
90
|
-
* - Procedural-memory-as-skills — the retrospective's skill-authoring step and
|
|
91
|
-
* its permission grant. Scoped to the v3 tier because skill retrieval rides
|
|
92
|
-
* the v3 lanes and the usage-prune stage lives in the v3 maintain job. That
|
|
93
|
-
* prune ships observe-first: with `memory.maintenance.skillPruneDays` at its
|
|
94
|
-
* default (`null`) it reports stale assistant-authored skills
|
|
95
|
-
* (`prunableSkills`) but deletes none — so a v3-tier assistant authors skills
|
|
96
|
-
* without an automatic retirement bound until a positive `skillPruneDays` is
|
|
97
|
-
* configured.
|
|
98
|
-
*
|
|
99
|
-
* Both write into memory on the user's behalf, so both honor the Memory
|
|
100
|
-
* opt-out identically: one predicate, one answer.
|
|
89
|
+
* Retrospective skill improvement is a separate optional v3-tier feature.
|
|
90
|
+
* Ask {@link isSkillImprovementActive} for it so an operator can stop managed
|
|
91
|
+
* skill authoring without turning off ordinary retrospective memory capture.
|
|
101
92
|
*/
|
|
102
93
|
export function isV3TierActive(config: AssistantConfig): boolean {
|
|
103
94
|
return isMemoryEnabled(config) && isMemoryV3Live(config);
|
|
104
95
|
}
|
|
105
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Whether a retrospective may turn observed procedures into managed skills.
|
|
99
|
+
* This requires the v3 tier because skills are retrieved through its memory
|
|
100
|
+
* substrate, and it honors the retrospective-specific opt-out without
|
|
101
|
+
* disabling ordinary retrospective fact retention.
|
|
102
|
+
*/
|
|
103
|
+
export function isSkillImprovementActive(config: AssistantConfig): boolean {
|
|
104
|
+
return (
|
|
105
|
+
isV3TierActive(config) &&
|
|
106
|
+
config.memory?.retrospective?.skillImprovement !== false
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
106
110
|
/**
|
|
107
111
|
* Minimal structural view of the memory config the concept-page gate reads.
|
|
108
112
|
* Accepting the shape (rather than the full `MemoryConfig`) lets call sites
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bound platform identity (assistant, organization, user).
|
|
3
|
+
*
|
|
4
|
+
* Django maps an assistant API key to these ids via
|
|
5
|
+
* `POST /v1/internal/assistants/validate/`. Process startup rehydrates from
|
|
6
|
+
* that endpoint into the in-memory overrides. Resolution reads those
|
|
7
|
+
* overrides (and `PLATFORM_ORGANIZATION_ID` / `PLATFORM_USER_ID` when set).
|
|
8
|
+
* When the in-memory assistant id is empty, the next resolve retries
|
|
9
|
+
* validate (single-flight, with a cooldown after a failed attempt).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { credentialKey } from "../security/credential-key.js";
|
|
13
|
+
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
14
|
+
import { getLogger } from "../util/logger.js";
|
|
15
|
+
import {
|
|
16
|
+
getPlatformAssistantId,
|
|
17
|
+
getPlatformBaseUrl,
|
|
18
|
+
getPlatformOrganizationId,
|
|
19
|
+
getPlatformUserId,
|
|
20
|
+
setPlatformAssistantId,
|
|
21
|
+
setPlatformOrganizationId,
|
|
22
|
+
setPlatformUserId,
|
|
23
|
+
} from "./env.js";
|
|
24
|
+
|
|
25
|
+
const log = getLogger("platform-identity");
|
|
26
|
+
|
|
27
|
+
export const PLATFORM_IDENTITY_VALIDATE_PATH =
|
|
28
|
+
"/v1/internal/assistants/validate/";
|
|
29
|
+
|
|
30
|
+
const VALIDATE_TIMEOUT_MS = 5_000;
|
|
31
|
+
const ENSURE_COOLDOWN_MS = 10_000;
|
|
32
|
+
|
|
33
|
+
export type PlatformIdentityIds = {
|
|
34
|
+
assistantId: string;
|
|
35
|
+
organizationId: string;
|
|
36
|
+
userId: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function asNonEmptyString(value: unknown): string | undefined {
|
|
40
|
+
if (typeof value !== "string") {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
const trimmed = value.trim();
|
|
44
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function applyPlatformIdentityIds(ids: PlatformIdentityIds): void {
|
|
48
|
+
if (ids.assistantId) {
|
|
49
|
+
setPlatformAssistantId(ids.assistantId);
|
|
50
|
+
}
|
|
51
|
+
if (ids.organizationId) {
|
|
52
|
+
setPlatformOrganizationId(ids.organizationId);
|
|
53
|
+
}
|
|
54
|
+
if (ids.userId) {
|
|
55
|
+
setPlatformUserId(ids.userId);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Trade an assistant API key for the bound platform ids.
|
|
61
|
+
*
|
|
62
|
+
* Returns null when the platform is unreachable, refuses the key, or the
|
|
63
|
+
* body has no ids. Never throws.
|
|
64
|
+
*/
|
|
65
|
+
export async function fetchPlatformIdentityIds(
|
|
66
|
+
baseUrl: string,
|
|
67
|
+
apiKey: string,
|
|
68
|
+
): Promise<PlatformIdentityIds | null> {
|
|
69
|
+
const url = `${baseUrl.replace(/\/+$/, "")}${PLATFORM_IDENTITY_VALIDATE_PATH}`;
|
|
70
|
+
try {
|
|
71
|
+
const res = await fetch(url, {
|
|
72
|
+
method: "POST",
|
|
73
|
+
headers: {
|
|
74
|
+
Authorization: `Api-Key ${apiKey}`,
|
|
75
|
+
"Content-Type": "application/json",
|
|
76
|
+
},
|
|
77
|
+
body: "{}",
|
|
78
|
+
signal: AbortSignal.timeout(VALIDATE_TIMEOUT_MS),
|
|
79
|
+
});
|
|
80
|
+
if (!res.ok) {
|
|
81
|
+
log.warn(
|
|
82
|
+
{ status: res.status },
|
|
83
|
+
"platform identity validate returned non-2xx",
|
|
84
|
+
);
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const body: unknown = await res.json();
|
|
88
|
+
if (!body || typeof body !== "object") {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const obj = body as Record<string, unknown>;
|
|
92
|
+
const assistantId = asNonEmptyString(obj.assistant_id);
|
|
93
|
+
const organizationId = asNonEmptyString(obj.organization_id);
|
|
94
|
+
const userId = asNonEmptyString(obj.user_id);
|
|
95
|
+
if (!assistantId && !organizationId && !userId) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
assistantId: assistantId ?? "",
|
|
100
|
+
organizationId: organizationId ?? "",
|
|
101
|
+
userId: userId ?? "",
|
|
102
|
+
};
|
|
103
|
+
} catch (err) {
|
|
104
|
+
log.warn({ err }, "platform identity validate failed");
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function readAssistantApiKey(): Promise<string> {
|
|
110
|
+
try {
|
|
111
|
+
const stored = (
|
|
112
|
+
await getSecureKeyAsync(credentialKey("vellum", "assistant_api_key"))
|
|
113
|
+
)?.trim();
|
|
114
|
+
if (stored) {
|
|
115
|
+
return stored;
|
|
116
|
+
}
|
|
117
|
+
} catch (err) {
|
|
118
|
+
log.warn({ err }, "failed to read assistant API key from credential store");
|
|
119
|
+
}
|
|
120
|
+
return process.env.ASSISTANT_API_KEY?.trim() ?? "";
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let ensureInFlight: Promise<void> | null = null;
|
|
124
|
+
let nextEnsureAttemptAt = 0;
|
|
125
|
+
|
|
126
|
+
export function _resetPlatformIdentityEnsureForTests(): void {
|
|
127
|
+
ensureInFlight = null;
|
|
128
|
+
nextEnsureAttemptAt = 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Load in-memory platform ids from validate when they are missing.
|
|
133
|
+
*
|
|
134
|
+
* No-ops when the assistant id is already set, when auth prerequisites are
|
|
135
|
+
* missing, or when a failed attempt is still inside the cooldown window.
|
|
136
|
+
* Concurrent callers share one in-flight request.
|
|
137
|
+
*/
|
|
138
|
+
export async function ensurePlatformIdentityIds(): Promise<void> {
|
|
139
|
+
if (getPlatformAssistantId().trim()) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (Date.now() < nextEnsureAttemptAt) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (!ensureInFlight) {
|
|
146
|
+
ensureInFlight = (async () => {
|
|
147
|
+
try {
|
|
148
|
+
const apiKey = await readAssistantApiKey();
|
|
149
|
+
const baseUrl = getPlatformBaseUrl();
|
|
150
|
+
if (!apiKey || !baseUrl) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const ids = await fetchPlatformIdentityIds(baseUrl, apiKey);
|
|
154
|
+
if (!ids) {
|
|
155
|
+
nextEnsureAttemptAt = Date.now() + ENSURE_COOLDOWN_MS;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
applyPlatformIdentityIds(ids);
|
|
159
|
+
nextEnsureAttemptAt = 0;
|
|
160
|
+
log.info("Loaded platform identity from platform validate");
|
|
161
|
+
} finally {
|
|
162
|
+
ensureInFlight = null;
|
|
163
|
+
}
|
|
164
|
+
})();
|
|
165
|
+
}
|
|
166
|
+
await ensureInFlight;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export async function resolvePlatformAssistantId(): Promise<string> {
|
|
170
|
+
const existing = getPlatformAssistantId().trim();
|
|
171
|
+
if (existing) {
|
|
172
|
+
return existing;
|
|
173
|
+
}
|
|
174
|
+
await ensurePlatformIdentityIds();
|
|
175
|
+
return getPlatformAssistantId().trim();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export async function resolvePlatformAssistantIdOrNull(): Promise<
|
|
179
|
+
string | null
|
|
180
|
+
> {
|
|
181
|
+
const id = await resolvePlatformAssistantId();
|
|
182
|
+
return id || null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export async function resolvePlatformOrganizationId(): Promise<string> {
|
|
186
|
+
const existing = getPlatformOrganizationId().trim();
|
|
187
|
+
if (existing) {
|
|
188
|
+
return existing;
|
|
189
|
+
}
|
|
190
|
+
await ensurePlatformIdentityIds();
|
|
191
|
+
return getPlatformOrganizationId().trim();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export async function resolvePlatformUserId(): Promise<string> {
|
|
195
|
+
const existing = getPlatformUserId().trim();
|
|
196
|
+
if (existing) {
|
|
197
|
+
return existing;
|
|
198
|
+
}
|
|
199
|
+
await ensurePlatformIdentityIds();
|
|
200
|
+
return getPlatformUserId().trim();
|
|
201
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Rehydrate the in-memory platform identity/URL overrides
|
|
3
|
-
* store at process startup.
|
|
2
|
+
* Rehydrate the in-memory platform identity/URL overrides at process startup.
|
|
4
3
|
*
|
|
5
4
|
* These overrides (`setPlatformBaseUrl` and the platform ID setters in
|
|
6
5
|
* `config/env.ts`) are normally only populated at runtime by the secret-routes
|
|
@@ -10,18 +9,17 @@
|
|
|
10
9
|
* environment default (e.g. dev-platform) while the credential store holds the
|
|
11
10
|
* real production values, and requests are sent to the wrong environment.
|
|
12
11
|
*
|
|
12
|
+
* Bound platform ids come from `POST /v1/internal/assistants/validate/`,
|
|
13
|
+
* which trades the assistant API key for assistant/organization/user ids.
|
|
14
|
+
*
|
|
13
15
|
* Each field is best-effort: a credential-store read failure is logged and
|
|
14
16
|
* skipped so a single missing value never blocks startup.
|
|
15
17
|
*/
|
|
16
18
|
import { credentialKey } from "../security/credential-key.js";
|
|
17
19
|
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
18
20
|
import { getLogger } from "../util/logger.js";
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
setPlatformBaseUrl,
|
|
22
|
-
setPlatformOrganizationId,
|
|
23
|
-
setPlatformUserId,
|
|
24
|
-
} from "./env.js";
|
|
21
|
+
import { setPlatformBaseUrl } from "./env.js";
|
|
22
|
+
import { ensurePlatformIdentityIds } from "./platform-identity.js";
|
|
25
23
|
|
|
26
24
|
const log = getLogger("platform-rehydration");
|
|
27
25
|
|
|
@@ -47,30 +45,16 @@ async function rehydrateField(
|
|
|
47
45
|
|
|
48
46
|
/**
|
|
49
47
|
* Rehydrate the platform base URL and the related platform IDs (assistant,
|
|
50
|
-
* organization, user)
|
|
51
|
-
* overrides. Safe to call more than once.
|
|
48
|
+
* organization, user). Safe to call more than once.
|
|
52
49
|
*/
|
|
53
50
|
export async function rehydratePlatformCredentials(): Promise<void> {
|
|
54
|
-
// Base URL first so managed proxy activation
|
|
55
|
-
//
|
|
51
|
+
// Base URL first so managed proxy activation and identity validate resolve
|
|
52
|
+
// the correct environment for every request that follows.
|
|
56
53
|
await rehydrateField(
|
|
57
54
|
"platform_base_url",
|
|
58
55
|
setPlatformBaseUrl,
|
|
59
56
|
"platform base URL",
|
|
60
57
|
);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
setPlatformAssistantId,
|
|
64
|
-
"platform assistant ID",
|
|
65
|
-
);
|
|
66
|
-
await rehydrateField(
|
|
67
|
-
"platform_organization_id",
|
|
68
|
-
setPlatformOrganizationId,
|
|
69
|
-
"platform organization ID",
|
|
70
|
-
);
|
|
71
|
-
await rehydrateField(
|
|
72
|
-
"platform_user_id",
|
|
73
|
-
setPlatformUserId,
|
|
74
|
-
"platform user ID",
|
|
75
|
-
);
|
|
58
|
+
|
|
59
|
+
await ensurePlatformIdentityIds();
|
|
76
60
|
}
|
package/src/config/schema.ts
CHANGED
|
@@ -41,7 +41,6 @@ import {
|
|
|
41
41
|
AuditLogConfigSchema,
|
|
42
42
|
LogFileConfigSchema,
|
|
43
43
|
} from "./schemas/logging.js";
|
|
44
|
-
import { McpConfigSchema } from "./schemas/mcp.js";
|
|
45
44
|
import { MemoryConfigSchema } from "./schemas/memory.js";
|
|
46
45
|
import { MigrationsConfigSchema } from "./schemas/migrations.js";
|
|
47
46
|
import { MonitoringConfigSchema } from "./schemas/monitoring.js";
|
|
@@ -62,6 +61,7 @@ import {
|
|
|
62
61
|
} from "./schemas/timeouts.js";
|
|
63
62
|
import { ToolsConfigSchema } from "./schemas/tools.js";
|
|
64
63
|
import { UserRoutesConfigSchema } from "./schemas/user-routes.js";
|
|
64
|
+
import { VoiceConfigSchema } from "./schemas/voice.js";
|
|
65
65
|
import { WorkflowsConfigSchema } from "./schemas/workflows.js";
|
|
66
66
|
import { WorkspaceGitConfigSchema } from "./schemas/workspace-git.js";
|
|
67
67
|
|
|
@@ -108,7 +108,6 @@ export const AssistantConfigSchema = z.object({
|
|
|
108
108
|
),
|
|
109
109
|
journal: JournalConfigSchema.default(JournalConfigSchema.parse({})),
|
|
110
110
|
backup: BackupConfigSchema.default(BackupConfigSchema.parse({})),
|
|
111
|
-
mcp: McpConfigSchema.default(McpConfigSchema.parse({})),
|
|
112
111
|
acp: AcpConfigSchema.default(AcpConfigSchema.parse({})),
|
|
113
112
|
skills: SkillsConfigSchema.default(SkillsConfigSchema.parse({})),
|
|
114
113
|
workspaceGit: WorkspaceGitConfigSchema.default(
|
|
@@ -119,6 +118,7 @@ export const AssistantConfigSchema = z.object({
|
|
|
119
118
|
twilio: TwilioConfigSchema.default(TwilioConfigSchema.parse({})),
|
|
120
119
|
calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
|
|
121
120
|
liveVoice: LiveVoiceConfigSchema.default(LiveVoiceConfigSchema.parse({})),
|
|
121
|
+
voice: VoiceConfigSchema.default(VoiceConfigSchema.parse({})),
|
|
122
122
|
sight: SightConfigSchema.default(SightConfigSchema.parse({})),
|
|
123
123
|
whatsapp: WhatsAppConfigSchema.default(WhatsAppConfigSchema.parse({})),
|
|
124
124
|
telegram: TelegramConfigSchema.default(TelegramConfigSchema.parse({})),
|