@vellumai/assistant 0.11.6 → 0.11.7-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +31 -19
- package/Dockerfile +1 -0
- package/docs/architecture/security.md +3 -3
- package/docs/flux-turn-detection-spike.md +8 -7
- package/docs/runbook-trusted-contacts.md +14 -0
- package/docs/stt-provider-onboarding.md +8 -4
- package/knip.json +1 -0
- package/node_modules/@vellumai/avatar-manifest/package.json +18 -0
- package/node_modules/@vellumai/avatar-manifest/src/__tests__/manifest.test.ts +173 -0
- package/node_modules/@vellumai/avatar-manifest/src/__tests__/read.test.ts +114 -0
- package/node_modules/@vellumai/avatar-manifest/src/index.ts +29 -0
- package/node_modules/@vellumai/avatar-manifest/src/layout.ts +18 -0
- package/node_modules/@vellumai/avatar-manifest/src/manifest.ts +156 -0
- package/node_modules/@vellumai/avatar-manifest/src/read.ts +109 -0
- package/node_modules/@vellumai/avatar-manifest/tsconfig.json +20 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
- package/node_modules/@vellumai/ces-client/src/http-credentials.ts +161 -0
- package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
- package/node_modules/@vellumai/environments/package.json +2 -1
- package/node_modules/@vellumai/environments/src/shell.test.ts +56 -0
- package/node_modules/@vellumai/environments/src/shell.ts +65 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +32 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/gateway-client.test.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/inbound-event-kind.test.ts +82 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/plugin-admission-denied-contract.test.ts +56 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +18 -0
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +5 -11
- package/node_modules/@vellumai/gateway-client/src/channel-permission-contract.ts +3 -1
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +9 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +4 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-event-kind.ts +75 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +17 -0
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +8 -0
- package/node_modules/@vellumai/gateway-client/src/plugin-admission-denied-contract.ts +47 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +11 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
- package/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
- package/openapi.yaml +419 -55
- package/package.json +4 -1
- package/scripts/sync-llm-catalog.ts +6 -0
- package/src/__tests__/approval-card-edit-inbound-handoff.test.ts +199 -0
- package/src/__tests__/approval-card-edit.test.ts +153 -0
- package/src/__tests__/attachments-store-heic-normalize.test.ts +1 -1
- package/src/__tests__/available-skills.test.ts +54 -0
- package/src/__tests__/avatar-identity-sync.test.ts +5 -1
- package/src/__tests__/catalog-install-normalize.test.ts +9 -1
- package/src/__tests__/channel-policy.test.ts +1 -3
- package/src/__tests__/channel-readiness-discord.test.ts +9 -70
- package/src/__tests__/compactor-call-site-logging.test.ts +61 -0
- package/src/__tests__/config-loader-backfill.test.ts +69 -0
- package/src/__tests__/config-schema.test.ts +2 -3
- package/src/__tests__/conversation-agent-loop.test.ts +238 -0
- package/src/__tests__/conversation-attachments.test.ts +0 -1
- package/src/__tests__/conversation-error.test.ts +44 -0
- package/src/__tests__/conversation-evictor.test.ts +19 -0
- package/src/__tests__/conversation-fork-referential.test.ts +73 -63
- package/src/__tests__/conversation-fork-retrospective.test.ts +99 -74
- package/src/__tests__/conversation-runtime-assembly.test.ts +23 -0
- package/src/__tests__/conversation-slash.test.ts +9 -0
- package/src/__tests__/conversation-title-service.test.ts +97 -0
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +16 -0
- package/src/__tests__/credential-broker-server-use.test.ts +0 -218
- package/src/__tests__/credential-broker.test.ts +43 -420
- package/src/__tests__/credential-record-write-through.test.ts +78 -0
- package/src/__tests__/credential-routes.test.ts +17 -1
- package/src/__tests__/credential-security-invariants.test.ts +8 -9
- package/src/__tests__/default-profile-catalog-fallback.test.ts +289 -0
- package/src/__tests__/delete-propagation.test.ts +92 -2
- package/src/__tests__/discord-callback-round-trip.test.ts +93 -0
- package/src/__tests__/discord-channel-config.test.ts +237 -0
- package/src/__tests__/edit-propagation.test.ts +42 -2
- package/src/__tests__/evict-conversations-for-reload.test.ts +51 -1
- package/src/__tests__/fallback-breaker.test.ts +1335 -0
- package/src/__tests__/gateway-threshold-reader-mock.ts +6 -0
- package/src/__tests__/guardian-card-withdrawal.test.ts +30 -0
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -2
- package/src/__tests__/image-conversion.test.ts +38 -4
- package/src/__tests__/install-skill-routing.test.ts +25 -0
- package/src/__tests__/llm-catalog-parity.test.ts +4 -0
- package/src/__tests__/llm-resolver.test.ts +74 -0
- package/src/__tests__/llm-schema-fallback-profile.test.ts +359 -0
- package/src/__tests__/managed-fallback-dispatch.test.ts +430 -0
- package/src/__tests__/managed-profile-guard.test.ts +28 -0
- package/src/__tests__/managed-speech-defaults.test.ts +196 -1
- package/src/__tests__/mcp-cli.test.ts +23 -1
- package/src/__tests__/mcp-tool-annotations-risk.test.ts +43 -34
- package/src/__tests__/media-stream-stt-session.test.ts +2 -0
- package/src/__tests__/notification-decision-fallback.test.ts +106 -0
- package/src/__tests__/notification-discord-adapter.test.ts +162 -0
- package/src/__tests__/oauth-connect-orchestrator.test.ts +95 -0
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +6 -8
- package/src/__tests__/persist-unsendable-image.test.ts +3 -3
- package/src/__tests__/platform.test.ts +19 -1
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
- package/src/__tests__/provider-catalog-visibility.test.ts +17 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +8 -1
- package/src/__tests__/provider-usage-tracking.test.ts +56 -0
- package/src/__tests__/require-fresh-approval.test.ts +5 -2
- package/src/__tests__/retry-fallback-escalation.test.ts +1093 -0
- package/src/__tests__/schedule-retry.test.ts +183 -4
- package/src/__tests__/scheduler-reuse-conversation.test.ts +6 -6
- package/src/__tests__/secret-routes-platform-proxy.test.ts +55 -0
- package/src/__tests__/skill-load-tool.test.ts +34 -0
- package/src/__tests__/skill-tool-factory.test.ts +6 -1
- package/src/__tests__/skill-tool-manifest.test.ts +20 -0
- package/src/__tests__/skills.test.ts +25 -0
- package/src/__tests__/subagent-manager-notify.test.ts +38 -0
- package/src/__tests__/terminal-tools.test.ts +2 -0
- package/src/__tests__/tool-approval-handler.test.ts +146 -2
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +108 -2
- package/src/__tests__/tool-audit.test.ts +111 -40
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +228 -18
- package/src/__tests__/ui-shape-teaching.test.ts +1 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +6 -2
- package/src/__tests__/voice-config-update.test.ts +43 -0
- package/src/__tests__/workspace-migration-147-rename-colliding-backup-profile-names.test.ts +480 -0
- package/src/__tests__/workspace-migration-148-strip-unsupported-fallback-profiles.test.ts +167 -0
- package/src/__tests__/workspace-migration-149-repoint-backup-profile-selections.test.ts +144 -0
- package/src/agent/loop.ts +31 -2
- package/src/approvals/guardian-card-withdrawal.ts +22 -0
- package/src/avatar/__tests__/ensure-raster.test.ts +291 -0
- package/src/avatar/avatar-manifest.ts +48 -100
- package/src/avatar/avatar-store.ts +7 -7
- package/src/avatar/ensure-raster.ts +146 -0
- package/src/avatar/resvg-lazy.test.ts +0 -1
- package/src/avatar/traits-png-sync.ts +9 -10
- package/src/background-wake/wake-intent-hooks.test.ts +0 -1
- package/src/backup/__tests__/paths.test.ts +6 -2
- package/src/backup/paths.ts +6 -4
- package/src/bundler/app-compiler.ts +2 -2
- package/src/bundler/compiler-tools.test.ts +36 -0
- package/src/bundler/compiler-tools.ts +54 -18
- package/src/calls/__tests__/telephony-synthesis-language.test.ts +81 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +57 -0
- package/src/calls/media-stream-stt-session.ts +2 -1
- package/src/calls/telephony-synthesis-language.ts +13 -5
- package/src/calls/voice-session-bridge.ts +19 -4
- package/src/channels/config.ts +23 -12
- package/src/cli/AGENTS.md +3 -1
- package/src/cli/commands/backup.help.ts +10 -13
- package/src/cli/commands/contacts.help.ts +16 -4
- package/src/cli/commands/contacts.ts +5 -1
- package/src/cli/commands/credentials.help.ts +1 -1
- package/src/cli/commands/inference-providers.ts +18 -53
- package/src/cli/commands/mcp.help.ts +6 -5
- package/src/cli/commands/mcp.ts +1 -1
- package/src/cli/commands/memory/memory-retrospective.ts +1 -0
- package/src/cli/commands/stt.help.ts +2 -2
- package/src/config/__tests__/backup-schema.test.ts +1 -1
- package/src/config/__tests__/default-profile-catalog.test.ts +83 -2
- package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +1 -1
- package/src/config/__tests__/memory-retrospective-schema.test.ts +12 -15
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -6
- package/src/config/bundled-skills/computer-use/TOOLS.json +9 -6
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +3 -1
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +16 -15
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +2 -1
- package/src/config/bundled-skills/settings/TOOLS.json +11 -5
- package/src/config/bundled-skills/settings/tools/open-system-settings.test.ts +85 -0
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +33 -8
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +54 -3
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +1 -1
- package/src/config/default-profile-catalog.ts +195 -10
- package/src/config/default-profile-names.ts +41 -0
- package/src/config/feature-flag-registry.json +34 -2
- package/src/config/inference-profile-validation.ts +11 -2
- package/src/config/llm-resolver.ts +25 -0
- package/src/config/loader.ts +3 -0
- package/src/config/managed-speech-defaults.ts +160 -10
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/live-voice.test.ts +7 -6
- package/src/config/schemas/__tests__/stt.test.ts +94 -0
- package/src/config/schemas/backup.ts +1 -1
- package/src/config/schemas/channels.ts +32 -0
- package/src/config/schemas/live-voice.ts +13 -4
- package/src/config/schemas/llm.ts +263 -15
- package/src/config/schemas/mcp.ts +10 -2
- package/src/config/schemas/memory-retrospective.ts +1 -19
- package/src/config/schemas/services.ts +24 -0
- package/src/config/schemas/stt.ts +128 -5
- package/src/config/seed-inference-profiles.ts +32 -3
- package/src/config/skill-state.ts +5 -0
- package/src/config/skills.ts +21 -0
- package/src/contacts/notify-contacts-changed.ts +5 -2
- package/src/context/compactor.ts +74 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +138 -1
- package/src/daemon/config-watcher.ts +2 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +27 -0
- package/src/daemon/conversation-agent-loop.ts +86 -10
- package/src/daemon/conversation-error.ts +25 -0
- package/src/daemon/conversation-evictor.ts +2 -4
- package/src/daemon/conversation-runtime-assembly.ts +19 -7
- package/src/daemon/conversation-skill-tools.ts +5 -1
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-store.ts +8 -1
- package/src/daemon/conversation-tool-setup.ts +37 -0
- package/src/daemon/conversation.ts +0 -4
- package/src/daemon/handlers/channel-config-result.ts +30 -0
- package/src/daemon/handlers/config-discord-channel.ts +301 -0
- package/src/daemon/handlers/config-ingress.ts +9 -0
- package/src/daemon/handlers/config-slack-channel.ts +13 -15
- package/src/daemon/handlers/config-telegram.ts +2 -5
- package/src/daemon/handlers/conversations.ts +0 -2
- package/src/daemon/handlers/skills.ts +25 -7
- package/src/daemon/lifecycle.ts +3 -1
- package/src/daemon/message-types/messages.ts +0 -2
- package/src/daemon/tool-setup-types.ts +5 -3
- package/src/daemon/trust-context-types.test.ts +33 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +58 -4
- package/src/live-voice/__tests__/live-voice-managed-speech-fallback.test.ts +8 -3
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +73 -11
- package/src/live-voice/__tests__/live-voice-session-preflight.test.ts +148 -2
- package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +64 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +3 -0
- package/src/live-voice/__tests__/live-voice-text-turn.test.ts +391 -0
- package/src/live-voice/__tests__/protocol.test.ts +224 -0
- package/src/live-voice/live-voice-credential-preflight.ts +5 -1
- package/src/live-voice/live-voice-session-manager.ts +39 -2
- package/src/live-voice/live-voice-session.ts +224 -9
- package/src/live-voice/protocol.ts +187 -1
- package/src/messaging/providers/discord/api.ts +2 -1
- package/src/messaging/providers/discord/withdraw.ts +62 -0
- package/src/messaging/read-provider-metadata.ts +32 -0
- package/src/monitoring/__tests__/file-descriptors.test.ts +32 -0
- package/src/monitoring/__tests__/process-memory.test.ts +34 -1
- package/src/monitoring/db-integrity-sample.ts +1 -0
- package/src/monitoring/file-descriptors.ts +39 -6
- package/src/monitoring/process-memory.ts +37 -5
- package/src/monitoring/resource-sampler.ts +25 -8
- package/src/notifications/__tests__/activity-failed-dedupe.test.ts +161 -0
- package/src/notifications/__tests__/background-failure-signal.test.ts +107 -0
- package/src/notifications/__tests__/connected-channels.test.ts +12 -0
- package/src/notifications/__tests__/copy-composer.test.ts +83 -0
- package/src/notifications/__tests__/destination-resolver.test.ts +38 -0
- package/src/notifications/activity-failed-dedupe.ts +95 -0
- package/src/notifications/adapters/discord.ts +132 -0
- package/src/notifications/adapters/shared.ts +16 -0
- package/src/notifications/adapters/slack.ts +6 -1
- package/src/notifications/adapters/telegram.ts +5 -8
- package/src/notifications/approval-card-data.ts +94 -1
- package/src/notifications/background-failure-signal.ts +116 -0
- package/src/notifications/broadcaster.ts +3 -9
- package/src/notifications/copy-composer.ts +41 -8
- package/src/notifications/decision-engine.ts +55 -0
- package/src/notifications/destination-resolver.ts +45 -5
- package/src/notifications/emit-signal.ts +19 -5
- package/src/notifications/guardian-question-mode.ts +57 -0
- package/src/notifications/types.ts +2 -8
- package/src/oauth/__tests__/seed-providers-managed.test.ts +18 -0
- package/src/oauth/connect-orchestrator.ts +16 -0
- package/src/oauth/seed-providers.ts +262 -0
- package/src/permissions/checker.test.ts +21 -0
- package/src/permissions/checker.ts +6 -0
- package/src/permissions/gateway-threshold-reader.test.ts +184 -0
- package/src/permissions/gateway-threshold-reader.ts +144 -10
- package/src/permissions/prompter.ts +0 -6
- package/src/permissions/types.ts +5 -4
- package/src/persistence/__tests__/bulk-write-gate.test.ts +0 -38
- package/src/persistence/bulk-write-gate.ts +9 -10
- package/src/persistence/conversation-crud.ts +88 -134
- package/src/persistence/conversation-title-service.ts +43 -29
- package/src/persistence/embeddings/embedding-local.ts +14 -85
- package/src/persistence/embeddings/embedding-runtime-manager.ts +1 -0
- package/src/persistence/lifecycle-events-store.test.ts +50 -0
- package/src/persistence/lifecycle-events-store.ts +75 -5
- package/src/platform/platform-patch-queue.test.ts +368 -0
- package/src/platform/platform-patch-queue.ts +190 -0
- package/src/platform/sync-avatar.test.ts +527 -0
- package/src/platform/sync-avatar.ts +209 -0
- package/src/platform/sync-identity.test.ts +75 -0
- package/src/platform/sync-identity.ts +17 -110
- package/src/plugin-api/model-profiles.test.ts +2 -2
- package/src/plugin-api/model-profiles.ts +7 -7
- package/src/plugin-api/transcription-session.ts +1 -1
- package/src/plugins/defaults/compaction/window-manager.ts +4 -0
- package/src/plugins/defaults/image-recovery/recover.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +133 -34
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +21 -31
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +13 -9
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +31 -4
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +0 -11
- package/src/plugins/defaults/memory/memory-retrospective-fork-boundary.ts +27 -13
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +183 -113
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +13 -13
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +2 -2
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +1 -1
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +4 -2
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +9 -42
- package/src/plugins/defaults/memory/v2/rerank-local.ts +1 -0
- package/src/plugins/defaults/memory/worker.ts +7 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +55 -0
- package/src/providers/__tests__/vellum-connection-routing.test.ts +21 -3
- package/src/providers/connection-resolution.ts +2 -17
- package/src/providers/fallback-breaker.ts +389 -0
- package/src/providers/inference/__tests__/adapter-factory-opencode.test.ts +92 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +16 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +12 -0
- package/src/providers/inference/adapter-factory.ts +246 -3
- package/src/providers/inference/auth.ts +15 -14
- package/src/providers/inference/chatgpt-subscription-auth.ts +70 -0
- package/src/providers/inference/chatgpt-subscription-credentials.ts +84 -0
- package/src/providers/inference/resolve-auth.ts +1 -1
- package/src/providers/media-resolve.ts +2 -3
- package/src/providers/model-catalog.ts +100 -0
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +22 -0
- package/src/providers/openai/__tests__/chat-template-flatten.test.ts +198 -0
- package/src/providers/openai/api-error-normalization.ts +13 -0
- package/src/providers/openai/chat-completions-provider.ts +84 -0
- package/src/providers/opencode/client.test.ts +150 -0
- package/src/providers/opencode/client.ts +61 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/provider-resolvability.ts +20 -0
- package/src/providers/provider-secret-catalog.ts +3 -2
- package/src/providers/retry.ts +956 -68
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +42 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +136 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +120 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +316 -12
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +83 -3
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +132 -4
- package/src/providers/speech-to-text/provider-catalog.ts +191 -3
- package/src/providers/speech-to-text/resolve.ts +132 -24
- package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +296 -0
- package/src/providers/types.ts +39 -0
- package/src/providers/usage-tracking.ts +12 -1
- package/src/providers/vellum/client.ts +29 -0
- package/src/providers/vellum-model-routing.test.ts +2 -0
- package/src/providers/vellum-model-routing.ts +3 -3
- package/src/runtime/AGENTS.md +1 -2
- package/src/runtime/__tests__/agent-wake.test.ts +105 -3
- package/src/runtime/__tests__/background-job-runner.test.ts +89 -3
- package/src/runtime/agent-wake.ts +44 -5
- package/src/runtime/background-job-runner.ts +68 -50
- package/src/runtime/channel-readiness-service.ts +0 -39
- package/src/runtime/http-server.ts +12 -4
- package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +18 -18
- package/src/runtime/routes/__tests__/backup-routes.test.ts +9 -5
- package/src/runtime/routes/__tests__/chatgpt-subscription-auth-routes.test.ts +372 -0
- package/src/runtime/routes/__tests__/contact-routes.test.ts +7 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +96 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +37 -0
- package/src/runtime/routes/__tests__/ingress-status-routes.test.ts +2 -1
- package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +87 -0
- package/src/runtime/routes/acp-claude-auth-routes.ts +25 -54
- package/src/runtime/routes/approval-routes.ts +0 -12
- package/src/runtime/routes/avatar-routes.ts +17 -30
- package/src/runtime/routes/backup-routes.ts +2 -2
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +296 -113
- package/src/runtime/routes/contact-prompt-routes.ts +65 -6
- package/src/runtime/routes/contact-routes.ts +20 -15
- package/src/runtime/routes/conversation-query-routes.ts +98 -10
- package/src/runtime/routes/conversation-routes.ts +2 -2
- package/src/runtime/routes/credential-routes.ts +2 -1
- package/src/runtime/routes/guardian-approval-interception.ts +12 -9
- package/src/runtime/routes/inbound-message-handler.ts +47 -48
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +18 -13
- package/src/runtime/routes/inbound-stages/admission-policy.ts +2 -2
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +20 -2
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +9 -8
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +1 -1
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +2 -2
- package/src/runtime/routes/inference-profiles-routes.ts +12 -7
- package/src/runtime/routes/inference-provider-connection-routes.ts +2 -2
- package/src/runtime/routes/inference-send-routes.ts +2 -2
- package/src/runtime/routes/ingress-status-routes.ts +2 -2
- package/src/runtime/routes/integrations/discord.ts +119 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +2 -2
- package/src/runtime/routes/mcp-auth-routes.ts +12 -6
- package/src/runtime/routes/migration-routes.ts +3 -1
- package/src/runtime/routes/oauth-pending-flows.ts +136 -0
- package/src/runtime/routes/secret-routes.ts +7 -0
- package/src/runtime/routes/stt-routes.ts +38 -6
- package/src/runtime/routes/wake-conversation-routes.ts +8 -1
- package/src/runtime/routes/watch-routes.ts +9 -5
- package/src/runtime/sync/resource-sync-events.ts +2 -0
- package/src/runtime/trust-verdict-consumer.ts +3 -3
- package/src/schedule/__tests__/worker-feature-flags.test.ts +58 -0
- package/src/schedule/retry-policy.ts +8 -8
- package/src/schedule/run-script.ts +14 -23
- package/src/schedule/schedule-recovery.ts +0 -1
- package/src/schedule/scheduler.ts +89 -51
- package/src/schedule/worker.ts +57 -0
- package/src/security/__tests__/openai-device-auth.test.ts +355 -0
- package/src/security/ces-rpc-record-backend.ts +123 -0
- package/src/security/oauth2.ts +7 -0
- package/src/security/openai-device-auth.ts +364 -0
- package/src/security/secure-keys.ts +15 -0
- package/src/skills/available-skills.ts +10 -1
- package/src/skills/catalog-install.ts +19 -1
- package/src/skills/inline-command-runner.ts +6 -2
- package/src/skills/platform-compatibility.test.ts +49 -0
- package/src/skills/platform-compatibility.ts +65 -0
- package/src/skills/tool-manifest.ts +20 -0
- package/src/stt/__tests__/roles.test.ts +152 -0
- package/src/stt/daemon-batch-transcriber.ts +4 -1
- package/src/stt/roles.ts +180 -0
- package/src/stt/stt-stream-session.ts +3 -2
- package/src/stt/types.ts +33 -3
- package/src/subagent/manager.ts +12 -0
- package/src/telemetry/__tests__/live-voice-funnel.test.ts +34 -0
- package/src/telemetry/live-voice-funnel.ts +12 -2
- package/src/telemetry/telemetry-wire.generated.ts +6 -0
- package/src/telemetry/tool-audit.ts +83 -30
- package/src/telemetry/tool-executed-events-store.test.ts +0 -1
- package/src/telemetry/turn-outcome.ts +75 -4
- package/src/tools/client-os.ts +115 -0
- package/src/tools/computer-use/definitions.ts +11 -7
- package/src/tools/computer-use/skill-proxy-bridge.ts +2 -2
- package/src/tools/credentials/broker-types.ts +0 -71
- package/src/tools/credentials/broker.ts +6 -201
- package/src/tools/credentials/metadata-store.ts +65 -16
- package/src/tools/credentials/store.ts +2 -0
- package/src/tools/executor.ts +2 -8
- package/src/tools/host-shell.test.ts +75 -0
- package/src/tools/host-shell.ts +24 -0
- package/src/tools/host-terminal/host-shell.ts +15 -44
- package/src/tools/mcp/mcp-tool-factory.ts +44 -9
- package/src/tools/permission-checker.ts +73 -21
- package/src/tools/policy-context.ts +1 -0
- package/src/tools/shared/filesystem/image-read.ts +1 -1
- package/src/tools/skills/find-similar-skills.ts +10 -2
- package/src/tools/skills/load.ts +41 -6
- package/src/tools/skills/sandbox-runner.ts +8 -16
- package/src/tools/skills/skill-tool-factory.ts +1 -0
- package/src/tools/terminal/__tests__/safe-env.test.ts +64 -1
- package/src/tools/terminal/safe-env.ts +39 -9
- package/src/tools/terminal/shell.ts +12 -31
- package/src/tools/tool-approval-handler.ts +64 -10
- package/src/tools/tool-types.ts +10 -0
- package/src/tools/types.ts +19 -3
- package/src/tools/ui-surface/surface-shape-docs.ts +4 -3
- package/src/tools/workflows/manage-workflows.ts +2 -2
- package/src/tools/workflows/run-workflow.test.ts +2 -1
- package/src/util/__tests__/file-use.test.ts +61 -0
- package/src/util/__tests__/process-table.test.ts +66 -0
- package/src/util/__tests__/process-tree.test.ts +46 -0
- package/src/util/errors.ts +1 -0
- package/src/util/file-use.ts +91 -0
- package/src/util/host-process.test.ts +17 -0
- package/src/util/host-process.ts +75 -0
- package/src/util/image-conversion.ts +39 -7
- package/src/util/platform.ts +32 -13
- package/src/util/process-table.ts +249 -0
- package/src/util/process-tree.ts +85 -129
- package/src/util/provider-error-patterns.ts +20 -0
- package/src/util/spawn.ts +9 -2
- package/src/watch/__tests__/watch-retro.test.ts +48 -1
- package/src/watch/watch-retro.ts +46 -4
- package/src/workspace/git-service.ts +4 -14
- package/src/workspace/migrations/147-rename-colliding-backup-profile-names.ts +360 -0
- package/src/workspace/migrations/148-strip-unsupported-fallback-profiles.ts +117 -0
- package/src/workspace/migrations/149-repoint-backup-profile-selections.ts +204 -0
- package/src/workspace/migrations/150-stt-flux-provider-to-model-family.ts +139 -0
- package/src/workspace/migrations/__tests__/150-stt-flux-provider-to-model-family.test.ts +160 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/permission-types.test.ts +0 -17
- package/src/channels/gateway-discord-admission.ts +0 -32
- package/src/persistence/fork-message-copy.ts +0 -239
- package/src/plugins/defaults/memory/__tests__/fork-message-copy.test.ts +0 -221
- package/src/security/__tests__/oauth2-device-code.test.ts +0 -431
- package/src/security/oauth2-device-code.ts +0 -312
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telephony synthesis-language resolution.
|
|
3
|
+
*
|
|
4
|
+
* The pin half of this resolver is gated on whether the provider transcribing
|
|
5
|
+
* the call honors manual language selection, so these cover which provider
|
|
6
|
+
* that gate reads: the telephony role's, which is what the call dials.
|
|
7
|
+
*/
|
|
8
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
9
|
+
|
|
10
|
+
import { setConfig } from "../../__tests__/helpers/set-config.js";
|
|
11
|
+
import { resolveTelephonySynthesisLanguage } from "../telephony-synthesis-language.js";
|
|
12
|
+
|
|
13
|
+
function seedStt(stt: Record<string, unknown>): void {
|
|
14
|
+
setConfig("services", { stt });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
setConfig("services", {});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("resolveTelephonySynthesisLanguage", () => {
|
|
22
|
+
test("a detected caller language outranks the configured pin", () => {
|
|
23
|
+
seedStt({ provider: "deepgram", language: "es" });
|
|
24
|
+
|
|
25
|
+
expect(resolveTelephonySynthesisLanguage("hi-IN")).toBe("hi");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("reads the pin gate from the telephony role, not the global provider", () => {
|
|
29
|
+
// Whisper auto-detects and ignores services.stt.language, so reading the
|
|
30
|
+
// global provider drops the pin. The call is transcribed by the telephony
|
|
31
|
+
// role's deepgram, which is pinned to Hindi and honors it.
|
|
32
|
+
seedStt({
|
|
33
|
+
provider: "openai-whisper",
|
|
34
|
+
language: "hi",
|
|
35
|
+
roles: { telephony: { provider: "deepgram" } },
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(resolveTelephonySynthesisLanguage()).toBe("hi");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("a telephony role that auto-detects drops a pin the global would honor", () => {
|
|
42
|
+
// The inverse: the global honors the pin but no call reaches it, so
|
|
43
|
+
// hinting Hindi would contradict what the caller is actually heard by.
|
|
44
|
+
seedStt({
|
|
45
|
+
provider: "deepgram",
|
|
46
|
+
language: "hi",
|
|
47
|
+
roles: { telephony: { provider: "openai-whisper" } },
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(resolveTelephonySynthesisLanguage()).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("an unset telephony role reads the global provider", () => {
|
|
54
|
+
seedStt({
|
|
55
|
+
provider: "deepgram",
|
|
56
|
+
language: "hi",
|
|
57
|
+
roles: { liveVoice: { provider: "openai-whisper" } },
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(resolveTelephonySynthesisLanguage()).toBe("hi");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('"multi" is auto-detection, not a pin', () => {
|
|
64
|
+
seedStt({
|
|
65
|
+
provider: "openai-whisper",
|
|
66
|
+
language: "multi",
|
|
67
|
+
roles: { telephony: { provider: "deepgram" } },
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(resolveTelephonySynthesisLanguage()).toBeUndefined();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("no configured language yields no hint", () => {
|
|
74
|
+
seedStt({
|
|
75
|
+
provider: "openai-whisper",
|
|
76
|
+
roles: { telephony: { provider: "deepgram" } },
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(resolveTelephonySynthesisLanguage()).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -390,6 +390,7 @@ describe("startVoiceTurn escalation-continuation persistence", () => {
|
|
|
390
390
|
);
|
|
391
391
|
expect(fake.lastPersistOpts()?.metadata).toEqual({
|
|
392
392
|
voiceSessionTurn: true,
|
|
393
|
+
scripted: true,
|
|
393
394
|
hidden: true,
|
|
394
395
|
messageKind: VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND,
|
|
395
396
|
});
|
|
@@ -404,8 +405,11 @@ describe("startVoiceTurn escalation-continuation persistence", () => {
|
|
|
404
405
|
|
|
405
406
|
await startVoiceTurn(makeTurnOptions()); // content: CALL_OPENING_MARKER
|
|
406
407
|
|
|
408
|
+
// Visible AND scripted: the opener is shown, but the assistant wrote it,
|
|
409
|
+
// so it is not the user taking a turn.
|
|
407
410
|
expect(fake.lastPersistOpts()?.metadata).toEqual({
|
|
408
411
|
voiceSessionTurn: true,
|
|
412
|
+
scripted: true,
|
|
409
413
|
});
|
|
410
414
|
});
|
|
411
415
|
|
|
@@ -425,6 +429,7 @@ describe("startVoiceTurn escalation-continuation persistence", () => {
|
|
|
425
429
|
// analytics already read.
|
|
426
430
|
expect(fake.lastPersistOpts()?.metadata).toEqual({
|
|
427
431
|
voiceSessionTurn: true,
|
|
432
|
+
scripted: true,
|
|
428
433
|
client: {
|
|
429
434
|
voice: true,
|
|
430
435
|
voice_session_id: "session-123",
|
|
@@ -444,10 +449,41 @@ describe("startVoiceTurn escalation-continuation persistence", () => {
|
|
|
444
449
|
|
|
445
450
|
expect(fake.lastPersistOpts()?.metadata).toEqual({
|
|
446
451
|
voiceSessionTurn: true,
|
|
452
|
+
scripted: true,
|
|
447
453
|
client: { voice: true, voice_session_id: "session-123" },
|
|
448
454
|
});
|
|
449
455
|
});
|
|
450
456
|
|
|
457
|
+
test("a turn the user really spoke is left unmarked, not marked false", async () => {
|
|
458
|
+
// Absent means UNKNOWN and falls through to the legacy classifier, which
|
|
459
|
+
// is the safe answer here. Stamping `false` would assert this turn was
|
|
460
|
+
// typed by the user, and a wrong `false` is trusted downstream.
|
|
461
|
+
const fake = makeFakeConversation({ processing: false });
|
|
462
|
+
fakeConversation = fake.conversation;
|
|
463
|
+
|
|
464
|
+
await startVoiceTurn({
|
|
465
|
+
...makeTurnOptions(),
|
|
466
|
+
content: "what is on my calendar",
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
expect(fake.lastPersistOpts()?.metadata).not.toHaveProperty("scripted");
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
test("scripted is not derived from hidden", async () => {
|
|
473
|
+
// The two answer different questions, and the opener is the case that
|
|
474
|
+
// separates them: shown to the user, written by the assistant. Deriving
|
|
475
|
+
// one from the other lets every visible-but-scripted turn count as
|
|
476
|
+
// activation, which is the largest single source of funnel inflation.
|
|
477
|
+
const fake = makeFakeConversation({ processing: false });
|
|
478
|
+
fakeConversation = fake.conversation;
|
|
479
|
+
|
|
480
|
+
await startVoiceTurn(makeTurnOptions()); // content: CALL_OPENING_MARKER
|
|
481
|
+
|
|
482
|
+
const metadata = fake.lastPersistOpts()?.metadata;
|
|
483
|
+
expect(metadata?.scripted).toBe(true);
|
|
484
|
+
expect(metadata).not.toHaveProperty("hidden");
|
|
485
|
+
});
|
|
486
|
+
|
|
451
487
|
test("a phone turn carries no client bag", async () => {
|
|
452
488
|
const fake = makeFakeConversation({ processing: false });
|
|
453
489
|
fakeConversation = fake.conversation;
|
|
@@ -501,6 +537,7 @@ describe("startVoiceTurn hiddenSyntheticPrompt", () => {
|
|
|
501
537
|
expect(fake.lastPersistOpts()?.content).toBe(SYNTHETIC_CONTENT);
|
|
502
538
|
expect(fake.lastPersistOpts()?.metadata).toEqual({
|
|
503
539
|
voiceSessionTurn: true,
|
|
540
|
+
scripted: true,
|
|
504
541
|
hidden: true,
|
|
505
542
|
});
|
|
506
543
|
expect(echoes).toHaveLength(0);
|
|
@@ -634,6 +671,26 @@ describe("default call protocol numbered rules", () => {
|
|
|
634
671
|
}
|
|
635
672
|
});
|
|
636
673
|
|
|
674
|
+
test("the pre-speech pin reads the telephony role, not the global provider", async () => {
|
|
675
|
+
// Whisper ignores services.stt.language, so reading the global provider
|
|
676
|
+
// drops the pin and opens in English. The caller is transcribed by the
|
|
677
|
+
// telephony role's deepgram, which is listening in Spanish.
|
|
678
|
+
setConfig("services", {
|
|
679
|
+
stt: {
|
|
680
|
+
provider: "openai-whisper",
|
|
681
|
+
language: "es",
|
|
682
|
+
roles: { telephony: { provider: "deepgram" } },
|
|
683
|
+
},
|
|
684
|
+
});
|
|
685
|
+
try {
|
|
686
|
+
const installed = captureInstalledPrompt();
|
|
687
|
+
await startVoiceTurn(makeTurnOptions());
|
|
688
|
+
expect(installed()).toContain('configured listening language ("es")');
|
|
689
|
+
} finally {
|
|
690
|
+
setConfig("services", {});
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
|
|
637
694
|
test("a language pin on an auto-detecting provider keeps the English fallback", () => {
|
|
638
695
|
// google-gemini and openai-whisper ignore services.stt.language entirely
|
|
639
696
|
// (languageSelection: "auto"), so a persisted "es" pin must not force a
|
|
@@ -432,6 +432,7 @@ export class MediaStreamSttSession {
|
|
|
432
432
|
let transcriber: StreamingTranscriber | null = null;
|
|
433
433
|
try {
|
|
434
434
|
transcriber = await resolveStreamingTranscriber({
|
|
435
|
+
role: "telephony",
|
|
435
436
|
sampleRate: STREAMING_SAMPLE_RATE,
|
|
436
437
|
utteranceBoundaryFinals: true,
|
|
437
438
|
utteranceEndMs: getConfig().calls.voice.utteranceEndMs,
|
|
@@ -688,7 +689,7 @@ export class MediaStreamSttSession {
|
|
|
688
689
|
// Resolve a batch transcriber for the configured provider.
|
|
689
690
|
let transcriber;
|
|
690
691
|
try {
|
|
691
|
-
transcriber = await resolveBatchTranscriber();
|
|
692
|
+
transcriber = await resolveBatchTranscriber({ role: "telephony" });
|
|
692
693
|
} catch (err) {
|
|
693
694
|
if (this.disposed) {
|
|
694
695
|
return;
|
|
@@ -7,14 +7,15 @@
|
|
|
7
7
|
* is a no-op for providers that cannot). Resolution mirrors live voice's
|
|
8
8
|
* per-utterance turn language (live-voice-session.ts): the caller's
|
|
9
9
|
* latest STT-detected language when the transcriber tags finals, else a
|
|
10
|
-
* monolingual `services.stt.language` pin when the
|
|
11
|
-
* honors manual language selection, else undefined (no hint,
|
|
12
|
-
* default behavior).
|
|
10
|
+
* monolingual `services.stt.language` pin when the provider serving the
|
|
11
|
+
* telephony role honors manual language selection, else undefined (no hint,
|
|
12
|
+
* provider default behavior).
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { getConfig } from "../config/loader.js";
|
|
16
16
|
import type { AssistantConfig } from "../config/types.js";
|
|
17
17
|
import { pinnedListeningLanguage } from "../providers/speech-to-text/provider-catalog.js";
|
|
18
|
+
import { sttCatalogKeyForRole } from "../stt/roles.js";
|
|
18
19
|
import { resolveLanguageVoiceOverride } from "../tts/language-voices.js";
|
|
19
20
|
import { resolveTtsConfig } from "../tts/tts-config-resolver.js";
|
|
20
21
|
import type { TtsProviderId } from "../tts/types.js";
|
|
@@ -37,7 +38,7 @@ export function resolveTelephonySynthesisLanguage(
|
|
|
37
38
|
return detected;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
let stt:
|
|
41
|
+
let stt: AssistantConfig["services"]["stt"];
|
|
41
42
|
try {
|
|
42
43
|
stt = getConfig().services.stt;
|
|
43
44
|
} catch {
|
|
@@ -45,7 +46,14 @@ export function resolveTelephonySynthesisLanguage(
|
|
|
45
46
|
return undefined;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
// The pin only counts when the provider transcribing the call honors
|
|
50
|
+
// manual language selection, so the gate reads the telephony role rather
|
|
51
|
+
// than the global provider: those differ whenever a role override is set,
|
|
52
|
+
// and it is the role's transcriber the caller is actually heard by.
|
|
53
|
+
return pinnedListeningLanguage(
|
|
54
|
+
sttCatalogKeyForRole(stt, "telephony"),
|
|
55
|
+
stt.language,
|
|
56
|
+
);
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
/**
|
|
@@ -43,6 +43,7 @@ import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
|
43
43
|
import { getCurrentSeq } from "../runtime/assistant-stream-state.js";
|
|
44
44
|
import { publishConversationMessagesChanged } from "../runtime/sync/resource-sync-events.js";
|
|
45
45
|
import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
|
|
46
|
+
import { sttCatalogKeyForRole } from "../stt/roles.js";
|
|
46
47
|
import { getAllTools } from "../tools/registry.js";
|
|
47
48
|
import { sensitiveToolReach } from "../tools/tool-approval-handler.js";
|
|
48
49
|
import { createAbortReason } from "../util/abort-reasons.js";
|
|
@@ -478,12 +479,13 @@ const PHONE_NO_SETUP_FLOWS_RULE =
|
|
|
478
479
|
* caller's language (the transcriber is already listening in it, see
|
|
479
480
|
* media-stream-stt-session.ts and providers/speech-to-text/resolve.ts), so it
|
|
480
481
|
* outranks the English default; "multi" and unset mean auto-detect, where
|
|
481
|
-
* English remains the fallback. The pin only counts when the
|
|
482
|
+
* English remains the fallback. The pin only counts when the provider
|
|
482
483
|
* honors manual language selection (see pinnedListeningLanguage):
|
|
483
484
|
* auto-detecting providers (gemini, whisper) ignore a persisted language
|
|
484
485
|
* entirely, so greeting in it would contradict what the transcriber
|
|
485
|
-
* actually hears.
|
|
486
|
-
*
|
|
486
|
+
* actually hears. `sttProvider` is the telephony role's catalog key, since
|
|
487
|
+
* that is the transcriber the caller is heard by. Exported for tests: the
|
|
488
|
+
* default test config exercises only the auto-detect branch.
|
|
487
489
|
*/
|
|
488
490
|
export function preSpeechLanguageRuleFragment(
|
|
489
491
|
sttLanguage: string | undefined,
|
|
@@ -590,7 +592,7 @@ function buildVoiceCallControlPrompt(opts: {
|
|
|
590
592
|
"9. After the opening greeting turn, treat the Task field as background context only — do not re-execute its instructions on subsequent turns.",
|
|
591
593
|
'10. Do not make up information. If you are unsure, use [ASK_GUARDIAN: your question] to consult your guardian. For tool permission requests, use [ASK_GUARDIAN_APPROVAL: {"question":"...","toolName":"...","input":{...}}].',
|
|
592
594
|
`11. Your text is sent directly to a text-to-speech engine. Never use markdown formatting (asterisks, headers, backticks, links) or emojis in your spoken responses. Write plain conversational text only. Protocol markers like ${opts.isCallerGuardian ? "[END_CALL]" : "[ASK_GUARDIAN: ...] and [END_CALL]"} are not spoken text and should still be used normally.`,
|
|
593
|
-
`12. Speak the caller's language: reply in the language of the caller's most recent actual speech, and follow them if they switch languages mid-call. Synthetic user turns (parenthetical markers like the call-connected and verification-completed notices) are not caller speech and never set the language. Before the caller has spoken, such as on the opening greeting turn, ${preSpeechLanguageRuleFragment(config.services.stt.language, config.services.stt
|
|
595
|
+
`12. Speak the caller's language: reply in the language of the caller's most recent actual speech, and follow them if they switch languages mid-call. Synthetic user turns (parenthetical markers like the call-connected and verification-completed notices) are not caller speech and never set the language. Before the caller has spoken, such as on the opening greeting turn, ${preSpeechLanguageRuleFragment(config.services.stt.language, sttCatalogKeyForRole(config.services.stt, "telephony"))}.`,
|
|
594
596
|
`13. ${PHONE_NO_SETUP_FLOWS_RULE}`,
|
|
595
597
|
);
|
|
596
598
|
|
|
@@ -1029,6 +1031,19 @@ export async function startVoiceTurn(
|
|
|
1029
1031
|
// Durable "this turn came from an open voice session" marker; see
|
|
1030
1032
|
// `isVoiceSessionUserMessage` for why the channel fields cannot carry it.
|
|
1031
1033
|
voiceSessionTurn: true,
|
|
1034
|
+
// Auto-sent on the user's behalf rather than spoken or typed by them,
|
|
1035
|
+
// so activation metrics exclude it (see the `scripted` contract on the
|
|
1036
|
+
// send route). Keyed off the synthetic set, NOT off
|
|
1037
|
+
// `isHiddenSyntheticPrompt`: the two answer different questions, and
|
|
1038
|
+
// deriving one from the other is what lets a visible-but-scripted turn
|
|
1039
|
+
// through. `hidden` decides whether a human sees the row; `scripted`
|
|
1040
|
+
// decides whether it counts as the user taking a turn.
|
|
1041
|
+
//
|
|
1042
|
+
// Only ever `true` here. A genuine voice turn is left absent rather
|
|
1043
|
+
// than stamped `false`, because absent means UNKNOWN and falls through
|
|
1044
|
+
// to the legacy classifier, while a wrong `false` is trusted
|
|
1045
|
+
// downstream.
|
|
1046
|
+
...(isSyntheticVoicePrompt ? { scripted: true } : {}),
|
|
1032
1047
|
...(isHiddenSyntheticPrompt ? { hidden: true } : {}),
|
|
1033
1048
|
...(isEscalationContinuation
|
|
1034
1049
|
? { messageKind: VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND }
|
package/src/channels/config.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* to compile until a policy is added below.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type
|
|
9
|
+
import { CHANNEL_IDS, type ChannelId } from "./types.js";
|
|
10
10
|
|
|
11
11
|
export type ConversationStrategy =
|
|
12
12
|
| "start_new_conversation"
|
|
@@ -77,12 +77,12 @@ const CHANNEL_POLICIES = {
|
|
|
77
77
|
notification: {
|
|
78
78
|
// Replies to an inbound Discord message do not read this flag: they
|
|
79
79
|
// route by `replyCallbackUrl` through the channel transport. This gates
|
|
80
|
-
// proactive notification
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
deliveryEnabled:
|
|
80
|
+
// proactive notification, which addresses the verified guardian
|
|
81
|
+
// directly: the adapter resolves a DM channel from the guardian
|
|
82
|
+
// binding's user snowflake, so a notification can never land in a
|
|
83
|
+
// guild room whose id merely looks like a DM's (both are bare
|
|
84
|
+
// snowflakes).
|
|
85
|
+
deliveryEnabled: true,
|
|
86
86
|
conversationStrategy: "continue_existing_conversation",
|
|
87
87
|
},
|
|
88
88
|
},
|
|
@@ -110,20 +110,31 @@ export function getChannelPolicy(
|
|
|
110
110
|
return CHANNEL_POLICIES[channelId];
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* The channels whose policy enables proactive delivery, derived from the
|
|
115
|
+
* registry's literal flags: flipping a channel's deliveryEnabled changes
|
|
116
|
+
* this union, and every exhaustive switch over it, at compile time.
|
|
117
|
+
*/
|
|
118
|
+
export type DeliverableChannelId = {
|
|
119
|
+
[K in keyof ChannelPolicies]: ChannelPolicies[K]["notification"]["deliveryEnabled"] extends true
|
|
120
|
+
? K
|
|
121
|
+
: never;
|
|
122
|
+
}[keyof ChannelPolicies];
|
|
123
|
+
|
|
113
124
|
/**
|
|
114
125
|
* Returns the list of channels where notification delivery is enabled.
|
|
115
126
|
*
|
|
116
127
|
* The return type is derived from the registry so downstream consumers
|
|
117
128
|
* get a narrow union rather than the full ChannelId set.
|
|
118
129
|
*/
|
|
119
|
-
export function getDeliverableChannels():
|
|
120
|
-
return
|
|
121
|
-
(id) => CHANNEL_POLICIES[id].notification.deliveryEnabled,
|
|
122
|
-
);
|
|
130
|
+
export function getDeliverableChannels(): DeliverableChannelId[] {
|
|
131
|
+
return CHANNEL_IDS.filter(isNotificationDeliverable);
|
|
123
132
|
}
|
|
124
133
|
|
|
125
134
|
/** Whether notification delivery is enabled for the given channel. */
|
|
126
|
-
export function isNotificationDeliverable(
|
|
135
|
+
export function isNotificationDeliverable(
|
|
136
|
+
channelId: ChannelId,
|
|
137
|
+
): channelId is DeliverableChannelId {
|
|
127
138
|
return CHANNEL_POLICIES[channelId].notification.deliveryEnabled;
|
|
128
139
|
}
|
|
129
140
|
|
package/src/cli/AGENTS.md
CHANGED
|
@@ -12,12 +12,14 @@ Commands here operate on a **single running assistant's** local state — config
|
|
|
12
12
|
|
|
13
13
|
For commands that manage the **lifecycle of assistant instances** (create, start, stop, delete), see `cli/AGENTS.md`.
|
|
14
14
|
|
|
15
|
-
Examples: `config`, `contacts
|
|
15
|
+
Examples: `config`, `contacts` (reads), `memory`, `autonomy`, `conversations` belong here. `hatch`, `wake`, `sleep`, `retire`, `ps`, `ssh` belong in `cli/`. Contact ACL writes belong on `gateway contacts`.
|
|
16
16
|
|
|
17
17
|
## Full CRUD for Resource Namespaces
|
|
18
18
|
|
|
19
19
|
Every namespace that manages a resource (schedules, contacts, tasks, …) must expose the full CRUD surface — create, get/list, update, delete — each wired to a daemon route. Intentional exceptions (e.g. create restricted to one mode) must be documented inline in the namespace help text so agents know the gap is deliberate. Partial surfaces are not a smaller scope, they are a hazard: when a CRUD verb is missing, the model bypasses the CLI and hand-writes SQLite rows instead.
|
|
20
20
|
|
|
21
|
+
**No write CLI for gateway-owned contact ACL.** Do not add `assistant contacts` verbs that persist contact ACL (risk ceilings, and any new ACL write). Those writes live on `gateway contacts`. `assistant contacts` may list and inspect.
|
|
22
|
+
|
|
21
23
|
## Conventions
|
|
22
24
|
|
|
23
25
|
- Commands use [Commander.js](https://github.com/tj/commander.js) and follow the `registerXCommand(program: Command)` pattern.
|
|
@@ -11,8 +11,8 @@ trust rules, hooks, the SQLite database) as a .vbundle file. Credentials are
|
|
|
11
11
|
NOT included — they live in the OS keychain / CES and users re-authenticate
|
|
12
12
|
integrations after a restore (via the gateway). The automated worker runs on a configurable
|
|
13
13
|
interval and writes to a local pool under ~/.vellum/backups/local/, optionally
|
|
14
|
-
mirroring each snapshot to one or more offsite destinations
|
|
15
|
-
default
|
|
14
|
+
mirroring each snapshot to one or more offsite destinations. macOS uses
|
|
15
|
+
encrypted iCloud Drive by default. Windows and Linux require an explicit path.
|
|
16
16
|
|
|
17
17
|
Offsite destinations can be per-destination encrypted (AES-256-GCM) or
|
|
18
18
|
plaintext — plaintext only makes sense when the user owns physical access to
|
|
@@ -70,11 +70,9 @@ Examples:
|
|
|
70
70
|
description: "Manage offsite backup destinations",
|
|
71
71
|
helpText: `
|
|
72
72
|
Offsite destinations are absolute paths the backup worker writes a copy of
|
|
73
|
-
each snapshot to after the local write succeeds.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
'destinations remove' materializes the iCloud default before applying the
|
|
77
|
-
change, so the default is never lost on an accidental "clear all".
|
|
73
|
+
each snapshot to after the local write succeeds. macOS uses the iCloud Drive
|
|
74
|
+
VellumAssistant folder until an explicit destinations array is configured.
|
|
75
|
+
Windows and Linux have no implicit offsite destination.
|
|
78
76
|
|
|
79
77
|
Each destination has an 'encrypt' flag. When true (the default), snapshots
|
|
80
78
|
are written as .vbundle.enc (AES-256-GCM). When false, snapshots are copied
|
|
@@ -90,9 +88,9 @@ Examples:
|
|
|
90
88
|
name: "list",
|
|
91
89
|
description: "List configured offsite destinations",
|
|
92
90
|
helpText: `
|
|
93
|
-
Resolves the current destinations array
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
Resolves the current destinations array and prints each path and encryption
|
|
92
|
+
flag. On macOS this includes the implicit iCloud default when configured paths
|
|
93
|
+
are null.
|
|
96
94
|
|
|
97
95
|
Examples:
|
|
98
96
|
$ assistant backup destinations list`,
|
|
@@ -114,9 +112,8 @@ Arguments:
|
|
|
114
112
|
caller controls; the backup worker writes files inside this
|
|
115
113
|
directory, not the directory itself.
|
|
116
114
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
2-element array rather than replacing the default.
|
|
115
|
+
On macOS, adding the first explicit destination preserves the implicit iCloud
|
|
116
|
+
destination. Windows and Linux start with only the destination supplied here.
|
|
120
117
|
|
|
121
118
|
Examples:
|
|
122
119
|
$ assistant backup destinations add /Volumes/BackupSSD/vellum --plaintext
|
|
@@ -75,9 +75,10 @@ Examples:
|
|
|
75
75
|
Arguments:
|
|
76
76
|
id UUID of the contact to retrieve. Run 'assistant contacts list' to find IDs.
|
|
77
77
|
|
|
78
|
-
Returns the full contact record including role, display name,
|
|
79
|
-
channel memberships (phone numbers, Telegram
|
|
80
|
-
For assistant-type contacts, additional
|
|
78
|
+
Returns the full contact record including role, display name, assistant
|
|
79
|
+
access ceiling, and all channel memberships (phone numbers, Telegram
|
|
80
|
+
IDs, email addresses, etc.). For assistant-type contacts, additional
|
|
81
|
+
assistant metadata is included.
|
|
81
82
|
|
|
82
83
|
Examples:
|
|
83
84
|
$ assistant contacts get 7a3b1c2d-4e5f-6789-abcd-ef0123456789
|
|
@@ -120,11 +121,22 @@ Examples:
|
|
|
120
121
|
"How long to wait for the user to submit (ms). Defaults to match the server-side prompt timeout.",
|
|
121
122
|
defaultValue: String(310_000),
|
|
122
123
|
},
|
|
124
|
+
{
|
|
125
|
+
flags: "--verify",
|
|
126
|
+
description:
|
|
127
|
+
"Mark the submitted channel verified (same attest as Contacts Verify me)",
|
|
128
|
+
},
|
|
123
129
|
],
|
|
124
130
|
helpText: `
|
|
125
131
|
Opens a contact address prompt in the user's app. The user enters a channel
|
|
126
132
|
address (phone number, email, Telegram ID, etc.). The address is saved with
|
|
127
|
-
status "unverified"
|
|
133
|
+
status "unverified" unless --verify is set, which attests the channel the
|
|
134
|
+
same way Contacts Verify me does.
|
|
135
|
+
|
|
136
|
+
Examples:
|
|
137
|
+
$ assistant contacts prompt --channel phone --role guardian
|
|
138
|
+
$ assistant contacts prompt --channel imessage --role guardian --verify \\
|
|
139
|
+
--label "Your iMessage number" --placeholder "+15551234567"
|
|
128
140
|
|
|
129
141
|
Run \`assistant contacts prompt --help\` for full option details.`,
|
|
130
142
|
},
|
|
@@ -35,6 +35,7 @@ interface ContactWithChannels {
|
|
|
35
35
|
createdAt: string | number;
|
|
36
36
|
updatedAt: string | number;
|
|
37
37
|
interactionCount: number | null;
|
|
38
|
+
autoApproveThreshold?: string | null;
|
|
38
39
|
channels: ContactChannel[];
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -131,6 +132,7 @@ function formatContactDetail(
|
|
|
131
132
|
lines.push(`Role: ${c.role}`);
|
|
132
133
|
}
|
|
133
134
|
lines.push(`Type: ${c.contactType}`);
|
|
135
|
+
lines.push(`Access: ${c.autoApproveThreshold ?? "inherit"}`);
|
|
134
136
|
if (c.notes) {
|
|
135
137
|
lines.push(`Notes: ${c.notes}`);
|
|
136
138
|
}
|
|
@@ -262,6 +264,7 @@ export function registerContactsCommand(program: Command): void {
|
|
|
262
264
|
label?: string;
|
|
263
265
|
description?: string;
|
|
264
266
|
timeout?: string;
|
|
267
|
+
verify?: boolean;
|
|
265
268
|
},
|
|
266
269
|
cmd: Command,
|
|
267
270
|
) => {
|
|
@@ -276,6 +279,7 @@ export function registerContactsCommand(program: Command): void {
|
|
|
276
279
|
role: opts.role ?? "unknown",
|
|
277
280
|
label: opts.label,
|
|
278
281
|
description: opts.description,
|
|
282
|
+
verify: opts.verify === true,
|
|
279
283
|
},
|
|
280
284
|
},
|
|
281
285
|
{ timeoutMs },
|
|
@@ -302,7 +306,7 @@ export function registerContactsCommand(program: Command): void {
|
|
|
302
306
|
`Registered ${result.channelType} channel: ${result.address}\n` +
|
|
303
307
|
` Channel ID: ${result.channelId}\n` +
|
|
304
308
|
` Contact ID: ${result.contactId}\n` +
|
|
305
|
-
` Status: unverified\n`,
|
|
309
|
+
` Status: ${opts.verify ? "verified" : "unverified"}\n`,
|
|
306
310
|
);
|
|
307
311
|
}
|
|
308
312
|
},
|
|
@@ -178,7 +178,7 @@ Arguments:
|
|
|
178
178
|
id (optional) Credential UUID for lookup by ID
|
|
179
179
|
|
|
180
180
|
Shows everything known about a credential without revealing the secret value.
|
|
181
|
-
The secret is masked to show only the
|
|
181
|
+
The secret is masked to show only the first 4 characters (e.g. cfat****).
|
|
182
182
|
|
|
183
183
|
Displayed fields include: label, creation/update timestamps, allowed tools,
|
|
184
184
|
allowed domains, OAuth2 scopes, account info, and injection template count.
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
import type { Command } from "commander";
|
|
21
21
|
|
|
22
22
|
import { cliIpcCall } from "../../ipc/cli-client.js";
|
|
23
|
-
import type { OAuth2Config } from "../../security/oauth2.js";
|
|
24
23
|
import { subcommand } from "../lib/cli-command-help.js";
|
|
25
24
|
import { writeCliError } from "../lib/cli-output.js";
|
|
26
25
|
import { openInHostBrowser } from "../lib/open-browser.js";
|
|
@@ -448,19 +447,6 @@ function attachDeleteSubcommand(parent: Command): void {
|
|
|
448
447
|
);
|
|
449
448
|
}
|
|
450
449
|
|
|
451
|
-
// ---------------------------------------------------------------------------
|
|
452
|
-
// OpenAI Codex OAuth config (PKCE, no client secret)
|
|
453
|
-
// ---------------------------------------------------------------------------
|
|
454
|
-
|
|
455
|
-
const OPENAI_CODEX_OAUTH_CONFIG: OAuth2Config = {
|
|
456
|
-
authorizeUrl: "https://auth.openai.com/oauth/authorize",
|
|
457
|
-
tokenExchangeUrl: "https://auth.openai.com/oauth/token",
|
|
458
|
-
clientId: "app_EMoamEEZ73f0CkXaXp7hrann",
|
|
459
|
-
scopes: ["openid", "profile", "email", "offline_access"],
|
|
460
|
-
scopeSeparator: " ",
|
|
461
|
-
authorizeParams: { id_token_add_organizations: "true" },
|
|
462
|
-
};
|
|
463
|
-
|
|
464
450
|
// ---------------------------------------------------------------------------
|
|
465
451
|
// Subcommand: login-chatgpt
|
|
466
452
|
// ---------------------------------------------------------------------------
|
|
@@ -469,10 +455,18 @@ function attachLoginChatgptSubcommand(providers: Command): void {
|
|
|
469
455
|
subcommand(providers, "login-chatgpt").action(
|
|
470
456
|
async (opts: { json?: boolean }) => {
|
|
471
457
|
try {
|
|
472
|
-
// Deferred: loads the OAuth and
|
|
473
|
-
const [
|
|
458
|
+
// Deferred: loads the OAuth and credential graphs on demand.
|
|
459
|
+
const [
|
|
460
|
+
{ startOAuth2Flow },
|
|
461
|
+
{
|
|
462
|
+
CHATGPT_SUBSCRIPTION_AUTH_INPUT,
|
|
463
|
+
CHATGPT_SUBSCRIPTION_CONNECTION_NAME,
|
|
464
|
+
OPENAI_OAUTH_CONFIG,
|
|
465
|
+
storeChatgptSubscriptionCredentials,
|
|
466
|
+
},
|
|
467
|
+
] = await Promise.all([
|
|
474
468
|
import("../../security/oauth2.js"),
|
|
475
|
-
import("../../
|
|
469
|
+
import("../../providers/inference/chatgpt-subscription-credentials.js"),
|
|
476
470
|
]);
|
|
477
471
|
// Step 1: Run browser-based PKCE OAuth flow
|
|
478
472
|
if (!opts.json) {
|
|
@@ -481,7 +475,7 @@ function attachLoginChatgptSubcommand(providers: Command): void {
|
|
|
481
475
|
);
|
|
482
476
|
}
|
|
483
477
|
const result = await startOAuth2Flow(
|
|
484
|
-
|
|
478
|
+
OPENAI_OAUTH_CONFIG,
|
|
485
479
|
{
|
|
486
480
|
openUrl: (url) => {
|
|
487
481
|
openInHostBrowser(url);
|
|
@@ -496,43 +490,14 @@ function attachLoginChatgptSubcommand(providers: Command): void {
|
|
|
496
490
|
loopbackCallbackPath: "/auth/callback",
|
|
497
491
|
},
|
|
498
492
|
);
|
|
499
|
-
const tokens = result.tokens;
|
|
500
|
-
|
|
501
493
|
// Step 2: Store tokens in CES
|
|
502
|
-
|
|
503
|
-
"credential/chatgpt/access_token",
|
|
504
|
-
tokens.accessToken,
|
|
505
|
-
);
|
|
506
|
-
if (!accessStored) {
|
|
507
|
-
writeCliError("Failed to store access token", opts.json);
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
if (tokens.refreshToken) {
|
|
512
|
-
const refreshStored = await setSecureKeyAsync(
|
|
513
|
-
"credential/chatgpt/refresh_token",
|
|
514
|
-
tokens.refreshToken,
|
|
515
|
-
);
|
|
516
|
-
if (!refreshStored) {
|
|
517
|
-
writeCliError("Failed to store refresh token", opts.json);
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
if (tokens.expiresIn) {
|
|
523
|
-
const expiresAt = Math.floor(Date.now() / 1000 + tokens.expiresIn);
|
|
524
|
-
await setSecureKeyAsync(
|
|
525
|
-
"credential/chatgpt/expires_at",
|
|
526
|
-
String(expiresAt),
|
|
527
|
-
);
|
|
528
|
-
}
|
|
494
|
+
await storeChatgptSubscriptionCredentials(result.tokens);
|
|
529
495
|
|
|
530
|
-
// Step 3: Create (or update) the provider entry via IPC
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
};
|
|
496
|
+
// Step 3: Create (or update) the provider entry via IPC. The CLI runs
|
|
497
|
+
// outside the daemon and has no database handle, so the connection
|
|
498
|
+
// upsert goes over IPC rather than through the shared store helper.
|
|
499
|
+
const connectionName = CHATGPT_SUBSCRIPTION_CONNECTION_NAME;
|
|
500
|
+
const authInput = CHATGPT_SUBSCRIPTION_AUTH_INPUT;
|
|
536
501
|
|
|
537
502
|
// Try to update first; if the entry doesn't exist, create it.
|
|
538
503
|
const updateResult = await cliIpcCall<ProviderConnection>(
|
|
@@ -97,8 +97,8 @@ Examples:
|
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
99
|
flags: "-r, --risk <level>",
|
|
100
|
-
description:
|
|
101
|
-
|
|
100
|
+
description:
|
|
101
|
+
"Risk level tools from this server start at: low, medium, or high",
|
|
102
102
|
},
|
|
103
103
|
],
|
|
104
104
|
helpText: `
|
|
@@ -110,9 +110,10 @@ Transport-specific requirements:
|
|
|
110
110
|
sse Requires --url pointing to the SSE endpoint
|
|
111
111
|
streamable-http Requires --url pointing to the HTTP endpoint
|
|
112
112
|
|
|
113
|
-
The --risk flag sets the
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
The --risk flag sets the risk level tools from this server start at. Omit it
|
|
114
|
+
and the server tracks the shipped default, "medium". A tool's own MCP
|
|
115
|
+
annotations move it one step from there: destructiveHint up, readOnlyHint
|
|
116
|
+
down. The server starts enabled unless --disabled is passed.
|
|
116
117
|
|
|
117
118
|
The --header (-H) flag adds custom HTTP headers to sse/streamable-http
|
|
118
119
|
transports. Use it for Bearer Token or API Key authentication. The flag
|