@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
package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/rpc.ts
CHANGED
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
* - `delete_credential` — Delete a credential by account name
|
|
17
17
|
* - `list_credentials` — List all credential account names
|
|
18
18
|
* - `bulk_set_credentials` — Store multiple credentials at once
|
|
19
|
+
*
|
|
20
|
+
* **Credential records** (non-secret identity + policy)
|
|
21
|
+
* - `get_credential_record` — Retrieve a credential record by account name
|
|
22
|
+
* - `set_credential_record` — Store or update a credential record
|
|
23
|
+
* - `delete_credential_record` — Delete a credential record by account name
|
|
24
|
+
* - `list_credential_records` — List all credential records
|
|
25
|
+
* - `bulk_set_credential_records` — Store multiple credential records at once
|
|
19
26
|
*/
|
|
20
27
|
|
|
21
28
|
import { z } from "zod";
|
|
@@ -38,6 +45,16 @@ export const CesRpcMethod = {
|
|
|
38
45
|
ListCredentials: "list_credentials",
|
|
39
46
|
/** Bulk-import credentials (set multiple at once). */
|
|
40
47
|
BulkSetCredentials: "bulk_set_credentials",
|
|
48
|
+
/** Retrieve a single credential record (identity + policy) by account name. */
|
|
49
|
+
GetCredentialRecord: "get_credential_record",
|
|
50
|
+
/** Store or update a credential record by account name. */
|
|
51
|
+
SetCredentialRecord: "set_credential_record",
|
|
52
|
+
/** Delete a credential record by account name. */
|
|
53
|
+
DeleteCredentialRecord: "delete_credential_record",
|
|
54
|
+
/** List all credential records. */
|
|
55
|
+
ListCredentialRecords: "list_credential_records",
|
|
56
|
+
/** Bulk-import credential records. */
|
|
57
|
+
BulkSetCredentialRecords: "bulk_set_credential_records",
|
|
41
58
|
} as const;
|
|
42
59
|
|
|
43
60
|
export type CesRpcMethod = (typeof CesRpcMethod)[keyof typeof CesRpcMethod];
|
|
@@ -168,6 +185,123 @@ export type BulkSetCredentialsResponse = z.infer<
|
|
|
168
185
|
typeof BulkSetCredentialsResponseSchema
|
|
169
186
|
>;
|
|
170
187
|
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
// Credential records (identity + policy, never secret values)
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
|
|
192
|
+
export const CredentialInjectionTemplateSchema = z.object({
|
|
193
|
+
hostPattern: z.string(),
|
|
194
|
+
injectionType: z.enum(["header", "query"]),
|
|
195
|
+
headerName: z.string().optional(),
|
|
196
|
+
valuePrefix: z.string().optional(),
|
|
197
|
+
queryParamName: z.string().optional(),
|
|
198
|
+
composeWith: z
|
|
199
|
+
.object({
|
|
200
|
+
service: z.string(),
|
|
201
|
+
field: z.string(),
|
|
202
|
+
separator: z.string(),
|
|
203
|
+
})
|
|
204
|
+
.optional(),
|
|
205
|
+
valueTransform: z.enum(["base64"]).optional(),
|
|
206
|
+
});
|
|
207
|
+
export type CredentialInjectionTemplate = z.infer<
|
|
208
|
+
typeof CredentialInjectionTemplateSchema
|
|
209
|
+
>;
|
|
210
|
+
|
|
211
|
+
export const CredentialRecordSchema = z.object({
|
|
212
|
+
credentialId: z.string(),
|
|
213
|
+
service: z.string(),
|
|
214
|
+
field: z.string(),
|
|
215
|
+
allowedTools: z.array(z.string()),
|
|
216
|
+
allowedDomains: z.array(z.string()),
|
|
217
|
+
usageDescription: z.string().optional(),
|
|
218
|
+
alias: z.string().optional(),
|
|
219
|
+
injectionTemplates: z.array(CredentialInjectionTemplateSchema).optional(),
|
|
220
|
+
createdAt: z.number(),
|
|
221
|
+
updatedAt: z.number(),
|
|
222
|
+
});
|
|
223
|
+
export type CredentialRecord = z.infer<typeof CredentialRecordSchema>;
|
|
224
|
+
|
|
225
|
+
export const GetCredentialRecordSchema = z.object({
|
|
226
|
+
/** The account name to look up (`credential/{service}/{field}`). */
|
|
227
|
+
account: z.string(),
|
|
228
|
+
});
|
|
229
|
+
export type GetCredentialRecord = z.infer<typeof GetCredentialRecordSchema>;
|
|
230
|
+
|
|
231
|
+
export const GetCredentialRecordResponseSchema = z.object({
|
|
232
|
+
found: z.boolean(),
|
|
233
|
+
record: CredentialRecordSchema.optional(),
|
|
234
|
+
});
|
|
235
|
+
export type GetCredentialRecordResponse = z.infer<
|
|
236
|
+
typeof GetCredentialRecordResponseSchema
|
|
237
|
+
>;
|
|
238
|
+
|
|
239
|
+
export const SetCredentialRecordSchema = z.object({
|
|
240
|
+
account: z.string(),
|
|
241
|
+
record: CredentialRecordSchema,
|
|
242
|
+
});
|
|
243
|
+
export type SetCredentialRecord = z.infer<typeof SetCredentialRecordSchema>;
|
|
244
|
+
|
|
245
|
+
export const SetCredentialRecordResponseSchema = z.object({
|
|
246
|
+
ok: z.boolean(),
|
|
247
|
+
});
|
|
248
|
+
export type SetCredentialRecordResponse = z.infer<
|
|
249
|
+
typeof SetCredentialRecordResponseSchema
|
|
250
|
+
>;
|
|
251
|
+
|
|
252
|
+
export const DeleteCredentialRecordSchema = z.object({
|
|
253
|
+
account: z.string(),
|
|
254
|
+
});
|
|
255
|
+
export type DeleteCredentialRecord = z.infer<
|
|
256
|
+
typeof DeleteCredentialRecordSchema
|
|
257
|
+
>;
|
|
258
|
+
|
|
259
|
+
export const DeleteCredentialRecordResponseSchema = z.object({
|
|
260
|
+
result: z.enum(["deleted", "not-found", "error"]),
|
|
261
|
+
});
|
|
262
|
+
export type DeleteCredentialRecordResponse = z.infer<
|
|
263
|
+
typeof DeleteCredentialRecordResponseSchema
|
|
264
|
+
>;
|
|
265
|
+
|
|
266
|
+
export const ListCredentialRecordsSchema = z.object({});
|
|
267
|
+
export type ListCredentialRecords = z.infer<typeof ListCredentialRecordsSchema>;
|
|
268
|
+
|
|
269
|
+
export const ListCredentialRecordsResponseSchema = z.object({
|
|
270
|
+
records: z.array(
|
|
271
|
+
z.object({
|
|
272
|
+
account: z.string(),
|
|
273
|
+
record: CredentialRecordSchema,
|
|
274
|
+
}),
|
|
275
|
+
),
|
|
276
|
+
});
|
|
277
|
+
export type ListCredentialRecordsResponse = z.infer<
|
|
278
|
+
typeof ListCredentialRecordsResponseSchema
|
|
279
|
+
>;
|
|
280
|
+
|
|
281
|
+
export const BulkSetCredentialRecordsSchema = z.object({
|
|
282
|
+
records: z.array(
|
|
283
|
+
z.object({
|
|
284
|
+
account: z.string(),
|
|
285
|
+
record: CredentialRecordSchema,
|
|
286
|
+
}),
|
|
287
|
+
),
|
|
288
|
+
});
|
|
289
|
+
export type BulkSetCredentialRecords = z.infer<
|
|
290
|
+
typeof BulkSetCredentialRecordsSchema
|
|
291
|
+
>;
|
|
292
|
+
|
|
293
|
+
export const BulkSetCredentialRecordsResponseSchema = z.object({
|
|
294
|
+
results: z.array(
|
|
295
|
+
z.object({
|
|
296
|
+
account: z.string(),
|
|
297
|
+
ok: z.boolean(),
|
|
298
|
+
}),
|
|
299
|
+
),
|
|
300
|
+
});
|
|
301
|
+
export type BulkSetCredentialRecordsResponse = z.infer<
|
|
302
|
+
typeof BulkSetCredentialRecordsResponseSchema
|
|
303
|
+
>;
|
|
304
|
+
|
|
171
305
|
// ---------------------------------------------------------------------------
|
|
172
306
|
// Full RPC contract type map
|
|
173
307
|
// ---------------------------------------------------------------------------
|
|
@@ -201,6 +335,26 @@ export interface CesRpcContract {
|
|
|
201
335
|
request: BulkSetCredentials;
|
|
202
336
|
response: BulkSetCredentialsResponse;
|
|
203
337
|
};
|
|
338
|
+
[CesRpcMethod.GetCredentialRecord]: {
|
|
339
|
+
request: GetCredentialRecord;
|
|
340
|
+
response: GetCredentialRecordResponse;
|
|
341
|
+
};
|
|
342
|
+
[CesRpcMethod.SetCredentialRecord]: {
|
|
343
|
+
request: SetCredentialRecord;
|
|
344
|
+
response: SetCredentialRecordResponse;
|
|
345
|
+
};
|
|
346
|
+
[CesRpcMethod.DeleteCredentialRecord]: {
|
|
347
|
+
request: DeleteCredentialRecord;
|
|
348
|
+
response: DeleteCredentialRecordResponse;
|
|
349
|
+
};
|
|
350
|
+
[CesRpcMethod.ListCredentialRecords]: {
|
|
351
|
+
request: ListCredentialRecords;
|
|
352
|
+
response: ListCredentialRecordsResponse;
|
|
353
|
+
};
|
|
354
|
+
[CesRpcMethod.BulkSetCredentialRecords]: {
|
|
355
|
+
request: BulkSetCredentialRecords;
|
|
356
|
+
response: BulkSetCredentialRecordsResponse;
|
|
357
|
+
};
|
|
204
358
|
}
|
|
205
359
|
|
|
206
360
|
/**
|
|
@@ -231,4 +385,24 @@ export const CesRpcSchemas = {
|
|
|
231
385
|
request: BulkSetCredentialsSchema,
|
|
232
386
|
response: BulkSetCredentialsResponseSchema,
|
|
233
387
|
},
|
|
388
|
+
[CesRpcMethod.GetCredentialRecord]: {
|
|
389
|
+
request: GetCredentialRecordSchema,
|
|
390
|
+
response: GetCredentialRecordResponseSchema,
|
|
391
|
+
},
|
|
392
|
+
[CesRpcMethod.SetCredentialRecord]: {
|
|
393
|
+
request: SetCredentialRecordSchema,
|
|
394
|
+
response: SetCredentialRecordResponseSchema,
|
|
395
|
+
},
|
|
396
|
+
[CesRpcMethod.DeleteCredentialRecord]: {
|
|
397
|
+
request: DeleteCredentialRecordSchema,
|
|
398
|
+
response: DeleteCredentialRecordResponseSchema,
|
|
399
|
+
},
|
|
400
|
+
[CesRpcMethod.ListCredentialRecords]: {
|
|
401
|
+
request: ListCredentialRecordsSchema,
|
|
402
|
+
response: ListCredentialRecordsResponseSchema,
|
|
403
|
+
},
|
|
404
|
+
[CesRpcMethod.BulkSetCredentialRecords]: {
|
|
405
|
+
request: BulkSetCredentialRecordsSchema,
|
|
406
|
+
response: BulkSetCredentialRecordsResponseSchema,
|
|
407
|
+
},
|
|
234
408
|
} as const;
|
|
@@ -20,6 +20,7 @@ describe("contact read contracts", () => {
|
|
|
20
20
|
contactType: "human",
|
|
21
21
|
lastInteraction: 1700000000,
|
|
22
22
|
interactionCount: 12,
|
|
23
|
+
autoApproveThreshold: "medium",
|
|
23
24
|
createdAt: 1699000000,
|
|
24
25
|
updatedAt: 1700000000,
|
|
25
26
|
channels: [
|
|
@@ -46,6 +47,7 @@ describe("contact read contracts", () => {
|
|
|
46
47
|
const parsed = ContactReadSchema.parse(contact);
|
|
47
48
|
expect(parsed.createdAt).toBe(1699000000);
|
|
48
49
|
expect(parsed.updatedAt).toBe(1700000000);
|
|
50
|
+
expect(parsed.autoApproveThreshold).toBe("medium");
|
|
49
51
|
});
|
|
50
52
|
|
|
51
53
|
test("ContactReadSchema accepts null interactionCount (daemon-native gateway-telemetry outage fail-soft)", () => {
|
|
@@ -82,6 +84,36 @@ describe("contact read contracts", () => {
|
|
|
82
84
|
const parsed = ContactReadSchema.parse(contact);
|
|
83
85
|
expect(parsed.interactionCount).toBeNull();
|
|
84
86
|
expect(parsed.channels[0].interactionCount).toBeNull();
|
|
87
|
+
expect(parsed.autoApproveThreshold).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("ContactReadSchema accepts a null auto-approve threshold", () => {
|
|
91
|
+
const contact = {
|
|
92
|
+
id: "c1",
|
|
93
|
+
displayName: "Example User",
|
|
94
|
+
role: "contact",
|
|
95
|
+
interactionCount: 0,
|
|
96
|
+
autoApproveThreshold: null,
|
|
97
|
+
createdAt: 1699000000,
|
|
98
|
+
updatedAt: 1700000000,
|
|
99
|
+
channels: [],
|
|
100
|
+
};
|
|
101
|
+
expect(ContactReadSchema.parse(contact).autoApproveThreshold).toBeNull();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("ContactReadSchema rejects an unknown auto-approve threshold", () => {
|
|
105
|
+
expect(() =>
|
|
106
|
+
ContactReadSchema.parse({
|
|
107
|
+
id: "c1",
|
|
108
|
+
displayName: "Example User",
|
|
109
|
+
role: "contact",
|
|
110
|
+
interactionCount: 0,
|
|
111
|
+
autoApproveThreshold: "full",
|
|
112
|
+
createdAt: 1699000000,
|
|
113
|
+
updatedAt: 1700000000,
|
|
114
|
+
channels: [],
|
|
115
|
+
}),
|
|
116
|
+
).toThrow();
|
|
85
117
|
});
|
|
86
118
|
|
|
87
119
|
test("ContactReadSchema requires createdAt/updatedAt", () => {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind derivation is the single reader of the field encodings, so its
|
|
3
|
+
* matrix is the compatibility contract: every shape an unstamped replayed
|
|
4
|
+
* retry payload can carry must classify exactly as the consumers that read
|
|
5
|
+
* those fields directly would classify it.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, test } from "bun:test";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
inboundEventRefersToAnotherMessage,
|
|
11
|
+
resolveInboundEventKind,
|
|
12
|
+
} from "../inbound-event-kind.js";
|
|
13
|
+
|
|
14
|
+
describe("resolveInboundEventKind", () => {
|
|
15
|
+
test("a stamped kind wins over every legacy field", () => {
|
|
16
|
+
expect(
|
|
17
|
+
resolveInboundEventKind({
|
|
18
|
+
eventKind: "edit",
|
|
19
|
+
callbackData: "message_deleted",
|
|
20
|
+
}),
|
|
21
|
+
).toBe("edit");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("an unrecognized stamp falls back to legacy derivation", () => {
|
|
25
|
+
expect(
|
|
26
|
+
resolveInboundEventKind({ eventKind: "future-kind", isEdit: true }),
|
|
27
|
+
).toBe("edit");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("legacy isEdit classifies as edit", () => {
|
|
31
|
+
expect(resolveInboundEventKind({ isEdit: true })).toBe("edit");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("the delete sentinel classifies as delete", () => {
|
|
35
|
+
expect(resolveInboundEventKind({ callbackData: "message_deleted" })).toBe(
|
|
36
|
+
"delete",
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("reaction prefixes classify as reaction, both directions", () => {
|
|
41
|
+
expect(resolveInboundEventKind({ callbackData: "reaction:+1" })).toBe(
|
|
42
|
+
"reaction",
|
|
43
|
+
);
|
|
44
|
+
expect(
|
|
45
|
+
resolveInboundEventKind({ callbackData: "reaction_removed:+1" }),
|
|
46
|
+
).toBe("reaction");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("any other callbackData classifies as button", () => {
|
|
50
|
+
expect(
|
|
51
|
+
resolveInboundEventKind({ callbackData: "apr:req-1:approve_once" }),
|
|
52
|
+
).toBe("button");
|
|
53
|
+
expect(resolveInboundEventKind({ callbackData: "some-action-id" })).toBe(
|
|
54
|
+
"button",
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("an empty callbackData is not a family", () => {
|
|
59
|
+
// Mirrors the old hasCallbackData predicate, which required length > 0.
|
|
60
|
+
expect(resolveInboundEventKind({ callbackData: "" })).toBe("message");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("callbackQueryId alone classifies as button", () => {
|
|
64
|
+
expect(resolveInboundEventKind({ callbackQueryId: "cbq-1" })).toBe(
|
|
65
|
+
"button",
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("nothing stated is a plain message", () => {
|
|
70
|
+
expect(resolveInboundEventKind({})).toBe("message");
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe("inboundEventRefersToAnotherMessage", () => {
|
|
75
|
+
test("only a plain message stands alone", () => {
|
|
76
|
+
expect(inboundEventRefersToAnotherMessage("message")).toBe(false);
|
|
77
|
+
expect(inboundEventRefersToAnotherMessage("edit")).toBe(true);
|
|
78
|
+
expect(inboundEventRefersToAnotherMessage("delete")).toBe(true);
|
|
79
|
+
expect(inboundEventRefersToAnotherMessage("reaction")).toBe(true);
|
|
80
|
+
expect(inboundEventRefersToAnotherMessage("button")).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
});
|
package/node_modules/@vellumai/gateway-client/src/__tests__/plugin-admission-denied-contract.test.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ACCESS_DENIED_NOT_APPROVED_REPLY,
|
|
5
|
+
PLUGIN_ADMISSION_DENIED_NOTICE_PATH,
|
|
6
|
+
PluginAdmissionDeniedNoticeSchema,
|
|
7
|
+
} from "../plugin-admission-denied-contract.js";
|
|
8
|
+
|
|
9
|
+
describe("plugin admission-denied contract", () => {
|
|
10
|
+
test("keeps the not-approved copy stable", () => {
|
|
11
|
+
expect(ACCESS_DENIED_NOT_APPROVED_REPLY).toBe(
|
|
12
|
+
"Sorry, you haven't been approved to message this assistant.",
|
|
13
|
+
);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("names the internal plugin notice path", () => {
|
|
17
|
+
expect(PLUGIN_ADMISSION_DENIED_NOTICE_PATH).toBe(
|
|
18
|
+
"notices/admission-denied",
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("round-trips a floor-deny notice", () => {
|
|
23
|
+
const notice = {
|
|
24
|
+
reason: "admission_floor" as const,
|
|
25
|
+
plugin: "imessage",
|
|
26
|
+
ingressRoute: "events-linq",
|
|
27
|
+
admissionPolicy: "guardian_only" as const,
|
|
28
|
+
trustClass: "unknown" as const,
|
|
29
|
+
conversationExternalId: "chat-1",
|
|
30
|
+
actorExternalId: "+15550100",
|
|
31
|
+
externalMessageId: "msg-1",
|
|
32
|
+
replyText: ACCESS_DENIED_NOT_APPROVED_REPLY,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
expect(PluginAdmissionDeniedNoticeSchema.parse(notice)).toEqual(notice);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("rejects a notice that still carries a plugin-scoped id as the chat", () => {
|
|
39
|
+
// The send API addresses vendor chats. An empty chat id is the failure
|
|
40
|
+
// that matters; the schema only requires a non-empty string, so this
|
|
41
|
+
// asserts the required fields rather than the prefix rule.
|
|
42
|
+
expect(() =>
|
|
43
|
+
PluginAdmissionDeniedNoticeSchema.parse({
|
|
44
|
+
reason: "admission_floor",
|
|
45
|
+
plugin: "imessage",
|
|
46
|
+
ingressRoute: "events-linq",
|
|
47
|
+
admissionPolicy: "guardian_only",
|
|
48
|
+
trustClass: "unknown",
|
|
49
|
+
conversationExternalId: "",
|
|
50
|
+
actorExternalId: "+15550100",
|
|
51
|
+
externalMessageId: "msg-1",
|
|
52
|
+
replyText: ACCESS_DENIED_NOT_APPROVED_REPLY,
|
|
53
|
+
}),
|
|
54
|
+
).toThrow();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -31,6 +31,7 @@ const fullVerdict: TrustVerdict = {
|
|
|
31
31
|
verifiedAt: 1699999999,
|
|
32
32
|
interactionCount: 12,
|
|
33
33
|
memberDisplayName: "Member Name",
|
|
34
|
+
autoApproveThreshold: "high",
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
describe("TrustVerdictSchema", () => {
|
|
@@ -38,6 +39,23 @@ describe("TrustVerdictSchema", () => {
|
|
|
38
39
|
expect(TrustVerdictSchema.parse(fullVerdict)).toEqual(fullVerdict);
|
|
39
40
|
});
|
|
40
41
|
|
|
42
|
+
test("parses a verdict with a null contact auto-approve threshold", () => {
|
|
43
|
+
const verdict = {
|
|
44
|
+
...fullVerdict,
|
|
45
|
+
autoApproveThreshold: null,
|
|
46
|
+
} satisfies TrustVerdict;
|
|
47
|
+
expect(TrustVerdictSchema.parse(verdict)).toEqual(verdict);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("rejects an unknown contact auto-approve threshold", () => {
|
|
51
|
+
expect(() =>
|
|
52
|
+
TrustVerdictSchema.parse({
|
|
53
|
+
...fullVerdict,
|
|
54
|
+
autoApproveThreshold: "full",
|
|
55
|
+
}),
|
|
56
|
+
).toThrow();
|
|
57
|
+
});
|
|
58
|
+
|
|
41
59
|
test("parses a minimal verdict", () => {
|
|
42
60
|
const minimal = {
|
|
43
61
|
trustClass: "unknown",
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Both the gateway (channel admission policy storage + kill switch) and the
|
|
5
5
|
* runtime (admission-policy stage) consume these values. Keeping the type
|
|
6
|
-
* here avoids the runtime importing from `gateway/src` and
|
|
7
|
-
*
|
|
8
|
-
* `trustClass` enum.
|
|
6
|
+
* here avoids the runtime importing from `gateway/src` and keeps both
|
|
7
|
+
* sides on a single shared vocabulary.
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
10
|
import { z } from "zod";
|
|
@@ -15,7 +14,7 @@ import type { TrustClass } from "./trust-verdict-contract.js";
|
|
|
15
14
|
/**
|
|
16
15
|
* Per-channel inbound admission policy — ordered from most-restrictive
|
|
17
16
|
* (`no_one`, hard kill switch) to most-permissive (`strangers`, admits any
|
|
18
|
-
* sender).
|
|
17
|
+
* sender).
|
|
19
18
|
*/
|
|
20
19
|
export const ADMISSION_POLICY_VALUES = [
|
|
21
20
|
"no_one",
|
|
@@ -32,14 +31,14 @@ export const AdmissionPolicySchema = z.enum(ADMISSION_POLICY_VALUES);
|
|
|
32
31
|
/**
|
|
33
32
|
* Read-side default applied when a channel has no row in the DB. Matches
|
|
34
33
|
* today's effective semantics: guardian + active contacts admitted,
|
|
35
|
-
* strangers denied.
|
|
34
|
+
* strangers denied.
|
|
36
35
|
*/
|
|
37
36
|
export const ADMISSION_POLICY_DEFAULT: AdmissionPolicy = "trusted_contacts";
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
39
|
* Minimum trust rank required for each policy. Higher rank = more trusted.
|
|
41
40
|
* `no_one` is 5 — above the maximum guardian rank (4) — so no class is ever
|
|
42
|
-
* admitted.
|
|
41
|
+
* admitted.
|
|
43
42
|
*/
|
|
44
43
|
export const ADMISSION_FLOOR: Record<AdmissionPolicy, number> = {
|
|
45
44
|
no_one: 5,
|
|
@@ -82,15 +81,10 @@ export function isAdmissionPolicyExemptChannel(channelType: string): boolean {
|
|
|
82
81
|
* `vellum` is the local desktop/web client surface; the guardian is always
|
|
83
82
|
* max-rank there, so the seed default admits them regardless of the floor.
|
|
84
83
|
*
|
|
85
|
-
* `discord` has no ingress implementation, so there is nothing for a floor to
|
|
86
|
-
* gate and nothing for the user to configure. Hiding keeps it pinned at the
|
|
87
|
-
* seed default rather than offering a Channel Trust Floors row for a channel
|
|
88
|
-
* that receives nothing.
|
|
89
84
|
*/
|
|
90
85
|
export const ADMISSION_POLICY_HIDDEN_CHANNELS: ReadonlySet<string> = new Set([
|
|
91
86
|
"vellum",
|
|
92
87
|
"whatsapp",
|
|
93
|
-
"discord",
|
|
94
88
|
]);
|
|
95
89
|
|
|
96
90
|
export function isAdmissionPolicyHiddenChannel(channelType: string): boolean {
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Storage lives in the gateway DB (`channel_permission_overrides`) so the
|
|
12
12
|
* assistant cannot tamper with it, matching `channel_admission_policy` and
|
|
13
|
-
* `auto_approve_thresholds`.
|
|
13
|
+
* `auto_approve_thresholds`. A contact-level ceiling can live on
|
|
14
|
+
* `contacts.auto_approve_threshold` and is stamped on the trust verdict;
|
|
15
|
+
* that override is not a matrix cell.
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
import { z } from "zod";
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
import { CHANNEL_IDS } from "@vellumai/service-contracts/channels";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
|
|
8
|
+
import { RiskThresholdSchema } from "./channel-permission-contract.js";
|
|
9
|
+
|
|
8
10
|
export const GATEWAY_LOG_LEVEL_NAMES = [
|
|
9
11
|
"trace",
|
|
10
12
|
"debug",
|
|
@@ -275,6 +277,11 @@ export const ContactReadSchema = z.object({
|
|
|
275
277
|
contactType: z.string().nullable().optional(),
|
|
276
278
|
lastInteraction: z.number().nullable().optional(),
|
|
277
279
|
interactionCount: z.number().nullable(),
|
|
280
|
+
/**
|
|
281
|
+
* Per-contact auto-approve ceiling. Null when unset (inherit cascade).
|
|
282
|
+
* Optional on the wire for version skew; gateway reads always emit it.
|
|
283
|
+
*/
|
|
284
|
+
autoApproveThreshold: RiskThresholdSchema.nullable().optional(),
|
|
278
285
|
createdAt: z.number(),
|
|
279
286
|
updatedAt: z.number(),
|
|
280
287
|
channels: z.array(ContactReadChannelSchema),
|
|
@@ -401,6 +408,8 @@ export type ClassifyRiskSkillMetadata = z.infer<
|
|
|
401
408
|
export const ClassifyRiskIpcParamsSchema = z.object({
|
|
402
409
|
tool: z.string().min(1),
|
|
403
410
|
command: z.string().optional(),
|
|
411
|
+
/** Shell grammar used by host_bash on the target desktop. */
|
|
412
|
+
shell: z.enum(["bash", "powershell"]).optional(),
|
|
404
413
|
url: z.string().optional(),
|
|
405
414
|
path: z.string().optional(),
|
|
406
415
|
/**
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* it in `handleChannelInbound()`.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { INBOUND_EVENT_KINDS } from "./inbound-event-kind.js";
|
|
13
14
|
import { z } from "zod";
|
|
14
15
|
|
|
15
16
|
import { ChannelConversationTypeSchema } from "./channel-permission-contract.js";
|
|
@@ -168,6 +169,9 @@ export const RuntimeInboundPayloadSchema = z.object({
|
|
|
168
169
|
conversationExternalId: z.string(),
|
|
169
170
|
externalMessageId: z.string(),
|
|
170
171
|
content: z.string(),
|
|
172
|
+
/** The named event family; absent only on replayed retry payloads,
|
|
173
|
+
* where resolveInboundEventKind derives it from the legacy fields. */
|
|
174
|
+
eventKind: z.enum(INBOUND_EVENT_KINDS).optional(),
|
|
171
175
|
isEdit: z.boolean().optional(),
|
|
172
176
|
callbackQueryId: z.string().optional(),
|
|
173
177
|
callbackData: z.string().optional(),
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inbound event families, named.
|
|
3
|
+
*
|
|
4
|
+
* Every inbound event is one of these, and the kind decides which pipeline
|
|
5
|
+
* stages apply: only user-authored text (message, edit) can carry a
|
|
6
|
+
* verification code or an invite, only a message starts an agent turn, and
|
|
7
|
+
* edit/delete/reaction/button all refer to another message rather than
|
|
8
|
+
* standing alone. A payload can also encode its family in the field that
|
|
9
|
+
* carries it: `isEdit`, the sentinel string `"message_deleted"`, the
|
|
10
|
+
* `"reaction:"` prefix, the presence of `callbackData` at all. Replayed
|
|
11
|
+
* retry payloads arrive with only those encodings, so
|
|
12
|
+
* {@link resolveInboundEventKind} derives the kind from them exactly once;
|
|
13
|
+
* nothing else may sniff them.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const INBOUND_EVENT_KINDS = [
|
|
17
|
+
"message",
|
|
18
|
+
"edit",
|
|
19
|
+
"delete",
|
|
20
|
+
"reaction",
|
|
21
|
+
"button",
|
|
22
|
+
] as const;
|
|
23
|
+
|
|
24
|
+
export type InboundEventKind = (typeof INBOUND_EVENT_KINDS)[number];
|
|
25
|
+
|
|
26
|
+
export function isInboundEventKind(value: string): value is InboundEventKind {
|
|
27
|
+
return (INBOUND_EVENT_KINDS as readonly string[]).includes(value);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The one place the field encodings are read. A payload stamped with a
|
|
32
|
+
* kind wins outright; an unstamped one (a replayed retry payload) is
|
|
33
|
+
* classified by the fields that carry its family. The fallback order is
|
|
34
|
+
* specific-before-generic: reaction prefixes and the delete sentinel are
|
|
35
|
+
* particular `callbackData` values, so they are tested before the generic
|
|
36
|
+
* button reading.
|
|
37
|
+
*/
|
|
38
|
+
export function resolveInboundEventKind(fields: {
|
|
39
|
+
eventKind?: string;
|
|
40
|
+
isEdit?: boolean;
|
|
41
|
+
callbackData?: string;
|
|
42
|
+
callbackQueryId?: string;
|
|
43
|
+
}): InboundEventKind {
|
|
44
|
+
if (fields.eventKind !== undefined && isInboundEventKind(fields.eventKind)) {
|
|
45
|
+
return fields.eventKind;
|
|
46
|
+
}
|
|
47
|
+
if (fields.isEdit === true) {
|
|
48
|
+
return "edit";
|
|
49
|
+
}
|
|
50
|
+
const cb = fields.callbackData;
|
|
51
|
+
if (cb !== undefined && cb.length > 0) {
|
|
52
|
+
if (cb === "message_deleted") {
|
|
53
|
+
return "delete";
|
|
54
|
+
}
|
|
55
|
+
if (cb.startsWith("reaction:") || cb.startsWith("reaction_removed:")) {
|
|
56
|
+
return "reaction";
|
|
57
|
+
}
|
|
58
|
+
return "button";
|
|
59
|
+
}
|
|
60
|
+
if (fields.callbackQueryId !== undefined) {
|
|
61
|
+
return "button";
|
|
62
|
+
}
|
|
63
|
+
return "message";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Whether an event of this kind refers to another message rather than
|
|
68
|
+
* standing alone as new content. Referring events never mint a
|
|
69
|
+
* conversation of their own and never carry ingestable attachments.
|
|
70
|
+
*/
|
|
71
|
+
export function inboundEventRefersToAnotherMessage(
|
|
72
|
+
kind: InboundEventKind,
|
|
73
|
+
): boolean {
|
|
74
|
+
return kind !== "message";
|
|
75
|
+
}
|
|
@@ -83,6 +83,23 @@ export {
|
|
|
83
83
|
|
|
84
84
|
export type { AdmissionPolicy } from "./admission-policy-contract.js";
|
|
85
85
|
|
|
86
|
+
export {
|
|
87
|
+
INBOUND_EVENT_KINDS,
|
|
88
|
+
inboundEventRefersToAnotherMessage,
|
|
89
|
+
isInboundEventKind,
|
|
90
|
+
resolveInboundEventKind,
|
|
91
|
+
} from "./inbound-event-kind.js";
|
|
92
|
+
export type { InboundEventKind } from "./inbound-event-kind.js";
|
|
93
|
+
|
|
94
|
+
// Plugin admission-denied notice (gateway → plugin) — canned deny copy + envelope
|
|
95
|
+
export {
|
|
96
|
+
ACCESS_DENIED_NOT_APPROVED_REPLY,
|
|
97
|
+
PLUGIN_ADMISSION_DENIED_NOTICE_PATH,
|
|
98
|
+
PluginAdmissionDeniedNoticeSchema,
|
|
99
|
+
} from "./plugin-admission-denied-contract.js";
|
|
100
|
+
|
|
101
|
+
export type { PluginAdmissionDeniedNotice } from "./plugin-admission-denied-contract.js";
|
|
102
|
+
|
|
86
103
|
// Trust verdict contract (gateway → daemon) — Zod schemas + derived types
|
|
87
104
|
export {
|
|
88
105
|
isTrustClass,
|
|
@@ -61,6 +61,14 @@ export const ApprovalUIMetadataSchema = z.object({
|
|
|
61
61
|
actions: z.array(ApprovalActionOptionSchema),
|
|
62
62
|
plainTextFallback: z.string(),
|
|
63
63
|
permissionDetails: PermissionRequestDetailsSchema.optional(),
|
|
64
|
+
/**
|
|
65
|
+
* What the recipient is being asked to do, so a renderer can head the card
|
|
66
|
+
* with the right verb. Resolved once by the producer; a renderer that reads
|
|
67
|
+
* the actions to work it out would be parsing a payload it is meant only to
|
|
68
|
+
* draw. Absent means an approval, which is what every existing producer
|
|
69
|
+
* sends and what a renderer without this field already assumes.
|
|
70
|
+
*/
|
|
71
|
+
intent: z.enum(["approval", "question"]).optional(),
|
|
64
72
|
});
|
|
65
73
|
|
|
66
74
|
export type ApprovalUIMetadata = z.infer<typeof ApprovalUIMetadataSchema>;
|