@vellumai/assistant 0.11.3 → 0.11.4-dev.202608190019.b94dbf2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -3
- package/ARCHITECTURE.md +32 -10
- package/docs/architecture/memory.md +43 -5
- package/docs/architecture/security.md +96 -152
- package/docs/architecture/turn-actor.md +70 -0
- package/docs/browser-use-architecture-phase2.md +128 -56
- package/docs/flux-turn-detection-spike.md +248 -0
- package/docs/guardian-request-flow.md +35 -0
- package/docs/stt-provider-onboarding.md +3 -1
- package/knip.json +3 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +34 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
- package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/openapi.yaml +289 -113
- package/package.json +1 -1
- package/scripts/voice-ttft-spike.ts +3 -3
- package/scripts/write-plugin-api-shim.ts +10 -0
- package/src/__tests__/app-compiler.test.ts +38 -3
- package/src/__tests__/app-control-flow.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -2
- package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
- package/src/__tests__/attachments-store.test.ts +21 -12
- package/src/__tests__/byok-default-profile-ensure.test.ts +17 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +0 -1
- package/src/__tests__/call-site-routing-provider.test.ts +1 -1
- package/src/__tests__/channel-availability-routes.test.ts +14 -1
- package/src/__tests__/channel-capabilities-dedupe.test.ts +214 -0
- package/src/__tests__/channel-delivery-store.test.ts +14 -14
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +4 -4
- package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
- package/src/__tests__/checker.test.ts +20 -314
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
- package/src/__tests__/compaction-events.test.ts +8 -10
- package/src/__tests__/config-loader-backfill.test.ts +3 -3
- package/src/__tests__/config-schema.test.ts +25 -10
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop.test.ts +32 -21
- package/src/__tests__/conversation-attachments.test.ts +0 -1
- package/src/__tests__/conversation-attention-store.test.ts +63 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -4
- package/src/__tests__/conversation-fork-crud.test.ts +69 -0
- package/src/__tests__/conversation-fork-referential.test.ts +67 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +24 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +209 -0
- package/src/__tests__/conversation-notifiers-provenance.test.ts +59 -0
- package/src/__tests__/conversation-queue.test.ts +154 -4
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +187 -102
- package/src/__tests__/conversation-runtime-workspace.test.ts +14 -10
- package/src/__tests__/conversation-slash-queue.test.ts +3 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +7 -10
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/custom-profile-ensure.test.ts +5 -1
- package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +5 -1
- package/src/__tests__/discord-requester-notice-privacy.test.ts +3 -3
- package/src/__tests__/document-append-idempotency.test.ts +233 -0
- package/src/__tests__/document-sync-tags.test.ts +0 -75
- package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
- package/src/__tests__/edit-propagation.test.ts +107 -11
- package/src/__tests__/file-ops-service.test.ts +163 -30
- package/src/__tests__/filesystem-tools.test.ts +23 -24
- package/src/__tests__/gateway-only-guard.test.ts +2 -5
- package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
- package/src/__tests__/helpers/mock-actor-context.ts +49 -0
- package/src/__tests__/helpers/mock-conversation.ts +13 -1
- package/src/__tests__/host-file-read-tool.test.ts +16 -19
- package/src/__tests__/http-user-message-parity.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
- package/src/__tests__/injector-chain.test.ts +63 -41
- package/src/__tests__/injector-disk-pressure.test.ts +11 -23
- package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
- package/src/__tests__/llm-context-resolution.test.ts +73 -1
- package/src/__tests__/llm-schema.test.ts +5 -2
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
- package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
- package/src/__tests__/media-generate-image.test.ts +131 -21
- package/src/__tests__/memory-retrieval-hook.test.ts +100 -7
- package/src/__tests__/messages-read-boundary-guard.test.ts +134 -0
- package/src/__tests__/mtime-cache.test.ts +3 -1
- package/src/__tests__/non-member-access-request.test.ts +0 -20
- package/src/__tests__/outbound-slack-persistence.test.ts +40 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
- package/src/__tests__/plugin-api-store-credential.test.ts +261 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
- package/src/__tests__/plugin-disabled-state.test.ts +2 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
- package/src/__tests__/plugin-execution-context.test.ts +73 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -4
- package/src/__tests__/plugin-secret-pattern-contribution.test.ts +1 -1
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +14 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +20 -0
- package/src/__tests__/proxy-approval-callback.test.ts +1 -0
- package/src/__tests__/qdrant-manager.test.ts +14 -1
- package/src/__tests__/reaction-persistence.test.ts +200 -7
- package/src/__tests__/require-fresh-approval.test.ts +0 -4
- package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +460 -105
- package/src/__tests__/run-due-schedules.test.ts +21 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
- package/src/__tests__/schedule-routes.test.ts +23 -0
- package/src/__tests__/schedule-store.test.ts +17 -0
- package/src/__tests__/scoped-approval-grants.test.ts +11 -6
- package/src/__tests__/secret-ingress-channel.test.ts +0 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -3
- package/src/__tests__/skills.test.ts +32 -0
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +0 -1
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/subagent-call-site-routing.test.ts +31 -19
- package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
- package/src/__tests__/subagent-spawn-and-await.test.ts +18 -17
- package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +81 -101
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
- package/src/__tests__/tool-executor.test.ts +68 -39
- package/src/__tests__/turn-events-store.test.ts +43 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
- package/src/__tests__/ui-shape-teaching.test.ts +33 -0
- package/src/__tests__/ui-visual-surface.test.ts +1 -1
- package/src/__tests__/ui-voice-picker-surface.test.ts +128 -0
- package/src/__tests__/ui-work-result-surface.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +3 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/visible-app-context.test.ts +16 -9
- package/src/__tests__/voice-config-update.test.ts +40 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
- package/src/__tests__/voice-session-bridge.test.ts +85 -29
- package/src/__tests__/worker-entrypoint-guards.test.ts +54 -0
- package/src/__tests__/worker-plugin-surface.test.ts +77 -0
- package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +158 -0
- package/src/__tests__/workspace-migration-143-repair-deprecated-codex-model-id.test.ts +133 -0
- package/src/__tests__/workspace-migration-144-convert-stranded-subscription-openai-profiles.test.ts +316 -0
- package/src/__tests__/workspace-migration-145-collapse-profile-bindings-to-entries.test.ts +325 -0
- package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +235 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +10 -2
- package/src/acp/__tests__/auth-required.test.ts +161 -0
- package/src/acp/acp-claude-oauth.ts +19 -2
- package/src/acp/agent-process.test.ts +100 -0
- package/src/acp/agent-process.ts +29 -26
- package/src/acp/auth-required.ts +102 -0
- package/src/acp/session-manager.test.ts +119 -0
- package/src/acp/session-manager.ts +76 -3
- package/src/api/events/acp-auth-required.ts +55 -0
- package/src/api/events/host-file.ts +2 -2
- package/src/api/index.ts +7 -0
- package/src/api/surfaces.ts +12 -3
- package/src/apps/app-store.ts +3 -0
- package/src/bundler/package-resolver.ts +2 -30
- package/src/calls/__tests__/voice-session-bridge.test.ts +194 -11
- package/src/calls/__tests__/voice-triage-escalate.test.ts +102 -0
- package/src/calls/call-controller.ts +19 -3
- package/src/calls/call-setup-flow.ts +0 -1
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/calls/voice-session-bridge.ts +115 -41
- package/src/calls/voice-triage-escalate.ts +105 -2
- package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
- package/src/channels/config.ts +13 -0
- package/src/channels/plugin-channel-declarations.ts +108 -0
- package/src/channels/types.ts +30 -0
- package/src/cli/AGENTS.md +5 -2
- package/src/cli/bundled-modules.ts +29 -0
- package/src/cli/commands/credentials.help.ts +2 -2
- package/src/cli/commands/db/repair.ts +4 -8
- package/src/cli/commands/domain.ts +6 -3
- package/src/cli/commands/email.ts +6 -3
- package/src/cli/commands/inference-providers.ts +1 -1
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.help.ts +13 -4
- package/src/cli/commands/mcp.ts +9 -0
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +128 -5
- package/src/cli/commands/memory/index.help.ts +84 -28
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/memory-v2.ts +58 -54
- package/src/cli/commands/memory/memory-v3.ts +64 -0
- package/src/cli/commands/memory/memory-validate.ts +18 -0
- package/src/cli/commands/plugins.ts +85 -36
- package/src/cli/commands/schedules.ts +35 -1
- package/src/cli/commands/stt.help.ts +27 -2
- package/src/cli/commands/trust.ts +3 -14
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +39 -0
- package/src/cli/lib/bundled-marketplace.json +14 -1
- package/src/cli/lib/upgrade-plugin.ts +42 -0
- package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
- package/src/config/__tests__/default-profile-catalog.test.ts +34 -2
- package/src/config/__tests__/default-provider.test.ts +6 -1
- package/src/config/__tests__/profile-materialization.test.ts +75 -19
- package/src/config/assistant-feature-flags.ts +36 -15
- package/src/config/balanced-model-experiment.ts +35 -0
- package/src/config/bundled-skills/acp/SKILL.md +6 -7
- package/src/config/bundled-skills/document-editor/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.test.ts +65 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +7 -1
- package/src/config/bundled-skills/settings/tools/shared.ts +16 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -12
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
- package/src/config/call-site-defaults.ts +11 -5
- package/src/config/default-profile-catalog.ts +179 -16
- package/src/config/default-profile-names.ts +4 -1
- package/src/config/default-provider-resolution.ts +4 -0
- package/src/config/feature-flag-registry.json +12 -12
- package/src/config/llm-context-resolution.ts +11 -3
- package/src/config/llm-resolver.ts +28 -1
- package/src/config/profile-materialization.ts +70 -22
- package/src/config/schemas/__tests__/live-voice.test.ts +107 -4
- package/src/config/schemas/call-site-catalog.ts +4 -4
- package/src/config/schemas/live-voice.ts +57 -23
- package/src/config/schemas/llm.ts +59 -32
- package/src/config/schemas/mcp.ts +23 -0
- package/src/config/schemas/plugin-updates.ts +6 -2
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/skills.ts +9 -2
- package/src/context/outbound-sanitize.ts +96 -1
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +82 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +15 -10
- package/src/daemon/conversation-agent-loop.ts +31 -19
- package/src/daemon/conversation-messaging.ts +5 -1
- package/src/daemon/conversation-notifiers.ts +20 -10
- package/src/daemon/conversation-process.ts +20 -6
- package/src/daemon/conversation-runtime-assembly.ts +12 -6
- package/src/daemon/conversation-store.ts +14 -4
- package/src/daemon/conversation-surfaces.ts +75 -26
- package/src/daemon/conversation-tool-setup.ts +3 -6
- package/src/daemon/conversation.ts +154 -51
- package/src/daemon/doordash-steps.ts +2 -2
- package/src/daemon/lifecycle.ts +14 -1
- package/src/daemon/mcp-reload-service.ts +36 -6
- package/src/daemon/process-message.ts +13 -26
- package/src/daemon/providers-setup.ts +6 -3
- package/src/daemon/trust-context-types.ts +29 -0
- package/src/daemon/trust-context.ts +12 -7
- package/src/daemon/wake-conversation-ops.ts +3 -2
- package/src/daemon/windows-compiled-entry.ts +4 -0
- package/src/documents/document-store.ts +143 -240
- package/src/hooks/hook-loader.ts +3 -3
- package/src/hooks/registry.ts +103 -45
- package/src/hooks/types.ts +5 -0
- package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
- package/src/inbound/oauth-callback-url.ts +61 -0
- package/src/ipc/gateway-client.test.ts +1 -1
- package/src/ipc/gateway-client.ts +14 -21
- package/src/ipc/gateway-flag-listener.ts +17 -3
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
- package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +1050 -0
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
- package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +60 -194
- package/src/live-voice/__tests__/live-voice-stt.test.ts +14 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +29 -0
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
- package/src/live-voice/__tests__/live-voice-vad.test.ts +0 -16
- package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
- package/src/live-voice/live-voice-archive.ts +2 -0
- package/src/live-voice/live-voice-manager.ts +16 -3
- package/src/live-voice/live-voice-metrics.ts +57 -32
- package/src/live-voice/live-voice-photo.ts +1 -2
- package/src/live-voice/live-voice-session.ts +598 -323
- package/src/live-voice/progress-narration.ts +277 -0
- package/src/live-voice/protocol.ts +21 -1
- package/src/live-voice/windows-compiled-live-voice.ts +4 -0
- package/src/mcp/__tests__/effective-config.test.ts +238 -0
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +200 -0
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
- package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +95 -0
- package/src/mcp/client.ts +16 -11
- package/src/mcp/effective-config.ts +113 -0
- package/src/mcp/manager.ts +11 -6
- package/src/mcp/mcp-auth-orchestrator.ts +13 -22
- package/src/mcp/mcp-oauth-provider.ts +205 -240
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +166 -3
- package/src/monitoring/control.ts +1 -0
- package/src/monitoring/db-integrity-sample.ts +4 -5
- package/src/monitoring/plugin-auto-update.ts +128 -24
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/approval-card-data.ts +33 -0
- package/src/notifications/signal.ts +1 -0
- package/src/permissions/AGENTS.md +16 -0
- package/src/permissions/checker.test.ts +75 -122
- package/src/permissions/checker.ts +44 -560
- package/src/permissions/confirmation-guardian-request.test.ts +15 -11
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/prompter.ts +1 -5
- package/src/permissions/question-guardian-request.test.ts +14 -6
- package/src/permissions/question-guardian-request.ts +1 -2
- package/src/persistence/attachments-store.ts +8 -1
- package/src/persistence/bookmark-crud.ts +3 -7
- package/src/persistence/conversation-attention-store.ts +16 -45
- package/src/persistence/conversation-crud.ts +33 -4
- package/src/persistence/conversation-lineage.ts +9 -0
- package/src/persistence/conversation-queries.ts +182 -52
- package/src/persistence/delivery-crud.ts +150 -36
- package/src/persistence/embeddings/qdrant-manager.ts +84 -49
- package/src/persistence/external-conversation-store.ts +32 -4
- package/src/persistence/llm-request-log-store.ts +4 -10
- package/src/persistence/llm-usage-store.ts +8 -3
- package/src/persistence/message-reads.test.ts +197 -0
- package/src/persistence/message-reads.ts +211 -0
- package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.test.ts +120 -0
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.ts +62 -0
- package/src/persistence/real-user-turn-filter.ts +27 -3
- package/src/persistence/schema/documents.ts +4 -4
- package/src/persistence/steps.ts +9 -0
- package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
- package/src/plugin-api/constants.ts +8 -0
- package/src/plugin-api/conversation-turn.ts +195 -5
- package/src/plugin-api/index.ts +38 -6
- package/src/plugin-api/resolve-credential.ts +3 -2
- package/src/plugin-api/store-credential.ts +146 -0
- package/src/plugin-api/vision-support.test.ts +1 -1
- package/src/plugin-api/webhook-url.ts +13 -11
- package/src/plugins/__tests__/mcp-servers.test.ts +371 -0
- package/src/plugins/defaults/main.ts +21 -7
- package/src/plugins/defaults/memory/AGENTS.md +15 -3
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +204 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +72 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
- package/src/plugins/defaults/memory/buffer-format.ts +165 -0
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +6 -0
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
- package/src/plugins/defaults/memory/graph/image-ref-utils.ts +3 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -30
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +34 -0
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +17 -24
- package/src/plugins/defaults/memory/hooks/post-compact.ts +1 -4
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
- package/src/plugins/defaults/memory/indexer.ts +3 -1
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +19 -7
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
- package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +281 -0
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
- package/src/plugins/defaults/memory/src/memory-v3-routes.ts +207 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +147 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
- package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
- package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
- package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
- package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
- package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +195 -58
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +93 -24
- package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
- package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
- package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
- package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
- package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
- package/src/plugins/defaults/memory/substrate/static-context.ts +160 -33
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +2 -4
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +3 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
- package/src/plugins/defaults/memory/v3/card.ts +9 -9
- package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
- package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
- package/src/plugins/defaults/memory/v3/edge.ts +13 -57
- package/src/plugins/defaults/memory/v3/injector.ts +8 -0
- package/src/plugins/defaults/memory/v3/prune.ts +2 -0
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +2 -0
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
- package/src/plugins/defaults/memory/worker-control.ts +1 -0
- package/src/plugins/defaults/memory/worker.ts +6 -3
- package/src/plugins/defaults/worker-entrypoints.ts +3 -0
- package/src/plugins/external-plugin-loader.ts +47 -0
- package/src/plugins/mcp-servers.ts +361 -0
- package/src/plugins/mtime-cache.ts +37 -46
- package/src/plugins/pipeline.ts +14 -7
- package/src/plugins/plugin-execution-context.ts +35 -11
- package/src/plugins/worker-plugin-surface.ts +33 -0
- package/src/prompts/templates/system-sections.ts +0 -7
- package/src/providers/__tests__/connection-model-compat.test.ts +1 -1
- package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +214 -2
- package/src/providers/__tests__/preflight-resolved-config.test.ts +57 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -2
- package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
- package/src/providers/anthropic/client.ts +332 -241
- package/src/providers/call-site-routing.ts +30 -3
- package/src/providers/connection-resolution.ts +194 -11
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +4 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/inference/auth.ts +6 -0
- package/src/providers/inference/connection-availability.ts +24 -2
- package/src/providers/inference/connections.ts +2 -0
- package/src/providers/model-catalog.ts +3 -3
- package/src/providers/model-intents.ts +28 -8
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +163 -40
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
- package/src/providers/openai/chat-completions-provider.ts +133 -36
- package/src/providers/openai/codex-models.ts +2 -1
- package/src/providers/provider-send-message.ts +32 -3
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +625 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +285 -6
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +679 -0
- package/src/providers/speech-to-text/provider-catalog.ts +99 -8
- package/src/providers/speech-to-text/resolve.ts +25 -2
- package/src/routes/control.ts +1 -0
- package/src/routes/route-host-client.ts +1 -0
- package/src/routes/route-host-protocol.ts +7 -0
- package/src/routes/worker.ts +48 -15
- package/src/runtime/AGENTS.md +16 -17
- package/src/runtime/access-request-helper.ts +9 -12
- package/src/runtime/agent-wake.ts +18 -15
- package/src/runtime/effective-capabilities.test.ts +43 -0
- package/src/runtime/effective-capabilities.ts +27 -0
- package/src/runtime/guardian-reply-router.ts +6 -2
- package/src/runtime/pre-first-message-gate.ts +4 -0
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +12 -4
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +522 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +52 -0
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +61 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +44 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +102 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +132 -35
- package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +133 -1
- package/src/runtime/routes/channel-availability-routes.ts +32 -14
- package/src/runtime/routes/channel-route-shared.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +6 -6
- package/src/runtime/routes/conversation-list-routes.ts +181 -23
- package/src/runtime/routes/conversation-management-routes.ts +17 -12
- package/src/runtime/routes/conversation-query-routes.ts +40 -27
- package/src/runtime/routes/conversation-routes.ts +43 -29
- package/src/runtime/routes/credential-prompt-routes.ts +4 -7
- package/src/runtime/routes/credential-routes.ts +26 -82
- package/src/runtime/routes/default-provider-routes.ts +15 -0
- package/src/runtime/routes/documents-routes.ts +3 -222
- package/src/runtime/routes/inbound-message-handler.ts +21 -45
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -9
- package/src/runtime/routes/inbound-stages/admission-policy.ts +1 -17
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -79
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +12 -7
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -8
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -79
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +2 -3
- package/src/runtime/routes/inference-profiles-routes.ts +20 -11
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -15
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/mcp-auth-routes.ts +148 -57
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -2
- package/src/runtime/routes/playground/reset-circuit.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +38 -8
- package/src/runtime/routes/schedule-routes.ts +94 -7
- package/src/runtime/routes/settings-routes.ts +6 -6
- package/src/runtime/routes/stt-routes.ts +31 -25
- package/src/runtime/routes/surface-action-routes.ts +20 -19
- package/src/runtime/routes/surface-conversation-resolver.ts +3 -0
- package/src/runtime/routes/user-route-dispatcher.ts +69 -15
- package/src/runtime/routes/user-route-import.ts +108 -0
- package/src/runtime/routes/user-route-resolution.ts +18 -1
- package/src/runtime/routes/workspace-routes.ts +0 -9
- package/src/runtime/routes/workspace-utils.ts +3 -13
- package/src/runtime/services/conversation-serializer.ts +7 -2
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
- package/src/schedule/plugin-schedule-availability.ts +58 -0
- package/src/schedule/plugin-schedule-declarations.ts +23 -27
- package/src/schedule/plugin-schedule-reconciler.ts +12 -3
- package/src/schedule/schedule-store.ts +5 -1
- package/src/schedule/scheduler.ts +9 -4
- package/src/schedule/worker-control.ts +1 -0
- package/src/schedule/worker.ts +6 -0
- package/src/security/oauth2.ts +6 -22
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
- package/src/stt/__tests__/types.test.ts +94 -0
- package/src/stt/daemon-batch-transcriber.ts +10 -0
- package/src/stt/stt-stream-session.ts +8 -4
- package/src/stt/types.ts +103 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
- package/src/subagent/consult-context.ts +11 -11
- package/src/subagent/consult-prompt.ts +26 -35
- package/src/subagent/manager.ts +21 -40
- package/src/subagent/notify.ts +7 -1
- package/src/subagent/types.ts +15 -12
- package/src/tools/__tests__/tool-input-schemas.test.ts +7 -7
- package/src/tools/acp/spawn.test.ts +97 -0
- package/src/tools/acp/spawn.ts +38 -4
- package/src/tools/credentials/ref-parse.ts +35 -0
- package/src/tools/credentials/resolve.ts +4 -10
- package/src/tools/credentials/store.ts +168 -0
- package/src/tools/document/document-tool.ts +12 -3
- package/src/tools/executor.ts +53 -15
- package/src/tools/filesystem/read.ts +27 -10
- package/src/tools/host-filesystem/read.ts +27 -15
- package/src/tools/network/url-safety.ts +9 -16
- package/src/tools/permission-checker.ts +43 -52
- package/src/tools/registry.ts +2 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +63 -35
- package/src/tools/shared/filesystem/legacy-read-args.ts +22 -0
- package/src/tools/shared/filesystem/types.ts +5 -5
- package/src/tools/skills/scaffold-managed.ts +25 -7
- package/src/tools/subagent/spawn.ts +28 -88
- package/src/tools/tool-types.ts +26 -13
- package/src/tools/types.ts +6 -6
- package/src/tools/ui-surface/surface-shape-docs.ts +12 -1
- package/src/tools/workflows/run-workflow.ts +1 -2
- package/src/tts/__tests__/reasoning-tag-filter.test.ts +78 -0
- package/src/tts/reasoning-tag-filter.ts +89 -0
- package/src/util/__tests__/worker-process-command.test.ts +37 -0
- package/src/util/logger.ts +16 -0
- package/src/util/think-tag-stream.ts +95 -0
- package/src/util/worker-process.ts +37 -4
- package/src/windows-compiled-cli.ts +32 -0
- package/src/windows-compiled-entry.ts +4 -0
- package/src/windows-compiled-logger.ts +6 -0
- package/src/windows-compiled-worker-entry.ts +29 -0
- package/src/workspace/byok-default-profile-ensure.ts +76 -24
- package/src/workspace/custom-profile-ensure.ts +4 -24
- package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
- package/src/workspace/migrations/143-repair-deprecated-codex-model-id.ts +134 -0
- package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +265 -0
- package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +328 -0
- package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +195 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +0 -10
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/provider-commit-message-generator.ts +7 -5
- package/src/__tests__/document-workspace-file.test.ts +0 -467
- package/src/live-voice/__tests__/front-decision.test.ts +0 -645
- package/src/live-voice/front-decision.ts +0 -476
- package/src/permissions/ipc-risk-types.ts +0 -143
- package/src/permissions/risk-types.ts +0 -76
- package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
- package/src/subagent/consult-transcript.ts +0 -90
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
ConversationStreamingMode,
|
|
15
15
|
SttBoundaryId,
|
|
16
16
|
SttProviderId,
|
|
17
|
+
SttTurnDetectionMode,
|
|
17
18
|
TelephonySttMode,
|
|
18
19
|
} from "../../stt/types.js";
|
|
19
20
|
import { baseLanguageSubtag } from "../../util/language-subtag.js";
|
|
@@ -87,6 +88,14 @@ interface SttProviderEntry {
|
|
|
87
88
|
*/
|
|
88
89
|
readonly conversationStreamingMode: ConversationStreamingMode;
|
|
89
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Whether the provider decides end-of-turn itself, in-band with the audio
|
|
93
|
+
* it transcribes, or leaves the boundary to the session's local silence
|
|
94
|
+
* timer. A live-voice session reads this to decide whether to arm its
|
|
95
|
+
* provider turn-end path; it never names a provider directly.
|
|
96
|
+
*/
|
|
97
|
+
readonly turnDetection: SttTurnDetectionMode;
|
|
98
|
+
|
|
90
99
|
/**
|
|
91
100
|
* Whether the provider can attribute transcribed speech to distinct
|
|
92
101
|
* speakers (speaker diarization). When `true`, callers may opt in to
|
|
@@ -105,8 +114,9 @@ interface SttProviderEntry {
|
|
|
105
114
|
*
|
|
106
115
|
* - `"manual"`: the provider accepts an explicit language parameter and
|
|
107
116
|
* defaults to English when omitted; a language picker is meaningful.
|
|
108
|
-
* - `"auto"`: the provider
|
|
109
|
-
*
|
|
117
|
+
* - `"auto"`: the provider takes no language parameter, either because it
|
|
118
|
+
* detects the language natively or because its model is monolingual; a
|
|
119
|
+
* picker would be a no-op, so clients must hide it.
|
|
110
120
|
*/
|
|
111
121
|
readonly languageSelection: "manual" | "auto";
|
|
112
122
|
|
|
@@ -118,6 +128,17 @@ interface SttProviderEntry {
|
|
|
118
128
|
// Catalog data
|
|
119
129
|
// ---------------------------------------------------------------------------
|
|
120
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Shared by every provider that authenticates against a Deepgram account.
|
|
133
|
+
* The key is the same one, so the instructions must not drift apart.
|
|
134
|
+
*/
|
|
135
|
+
const DEEPGRAM_CREDENTIALS_GUIDE: SttCredentialsGuide = {
|
|
136
|
+
description:
|
|
137
|
+
"Sign in to the Deepgram console, navigate to API Keys, and create a new key.",
|
|
138
|
+
url: "https://console.deepgram.com/",
|
|
139
|
+
linkLabel: "Open Deepgram Console",
|
|
140
|
+
};
|
|
141
|
+
|
|
121
142
|
/**
|
|
122
143
|
* Provider catalog entries, keyed by provider ID.
|
|
123
144
|
*
|
|
@@ -147,14 +168,41 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
|
|
|
147
168
|
]),
|
|
148
169
|
telephonyMode: "realtime-ws",
|
|
149
170
|
conversationStreamingMode: "realtime-ws",
|
|
171
|
+
turnDetection: "none",
|
|
150
172
|
supportsDiarization: true,
|
|
151
173
|
languageSelection: "manual",
|
|
152
|
-
credentialsGuide:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
174
|
+
credentialsGuide: DEEPGRAM_CREDENTIALS_GUIDE,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
[
|
|
178
|
+
"deepgram-flux",
|
|
179
|
+
{
|
|
180
|
+
id: "deepgram-flux",
|
|
181
|
+
displayName: "Deepgram Flux",
|
|
182
|
+
subtitle:
|
|
183
|
+
"Conversational speech-to-text with model-native turn detection. Uses your Deepgram API key.",
|
|
184
|
+
setupMode: "api-key",
|
|
185
|
+
setupHint:
|
|
186
|
+
"Enter your Deepgram API key. Flux shares the same key as Deepgram.",
|
|
187
|
+
// Shared with the `deepgram` provider: Flux is a model on the same
|
|
188
|
+
// account, not a separate credential.
|
|
189
|
+
credentialProvider: "deepgram",
|
|
190
|
+
// Streaming only: Flux has no batch endpoint.
|
|
191
|
+
supportedBoundaries: new Set<SttBoundaryId>(["daemon-streaming"]),
|
|
192
|
+
// Telephony is out of scope for the spike. Nothing reroutes a call to
|
|
193
|
+
// another provider, so a Flux-configured assistant does not transcribe
|
|
194
|
+
// calls at all.
|
|
195
|
+
telephonyMode: "none",
|
|
196
|
+
conversationStreamingMode: "realtime-ws",
|
|
197
|
+
// Flux emits turn lifecycle events on its transcript stream and numbers
|
|
198
|
+
// them, so a live-voice session may let them commit the turn.
|
|
199
|
+
turnDetection: "provider",
|
|
200
|
+
supportsDiarization: false,
|
|
201
|
+
// "no picker", not native detection: the Flux model is English-only and
|
|
202
|
+
// takes no language parameter, so audio in another language transcribes
|
|
203
|
+
// as English rather than being detected.
|
|
204
|
+
languageSelection: "auto",
|
|
205
|
+
credentialsGuide: DEEPGRAM_CREDENTIALS_GUIDE,
|
|
158
206
|
},
|
|
159
207
|
],
|
|
160
208
|
[
|
|
@@ -174,6 +222,7 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
|
|
|
174
222
|
]),
|
|
175
223
|
telephonyMode: "batch-only",
|
|
176
224
|
conversationStreamingMode: "realtime-ws",
|
|
225
|
+
turnDetection: "none",
|
|
177
226
|
supportsDiarization: false,
|
|
178
227
|
languageSelection: "auto",
|
|
179
228
|
credentialsGuide: {
|
|
@@ -200,6 +249,7 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
|
|
|
200
249
|
]),
|
|
201
250
|
telephonyMode: "batch-only",
|
|
202
251
|
conversationStreamingMode: "incremental-batch",
|
|
252
|
+
turnDetection: "none",
|
|
203
253
|
supportsDiarization: false,
|
|
204
254
|
languageSelection: "auto",
|
|
205
255
|
credentialsGuide: {
|
|
@@ -226,6 +276,7 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
|
|
|
226
276
|
]),
|
|
227
277
|
telephonyMode: "realtime-ws",
|
|
228
278
|
conversationStreamingMode: "realtime-ws",
|
|
279
|
+
turnDetection: "none",
|
|
229
280
|
supportsDiarization: false,
|
|
230
281
|
// The relay dials Deepgram nova-3 server-side, which takes an explicit
|
|
231
282
|
// language parameter.
|
|
@@ -248,6 +299,7 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
|
|
|
248
299
|
]),
|
|
249
300
|
telephonyMode: "batch-only",
|
|
250
301
|
conversationStreamingMode: "realtime-ws",
|
|
302
|
+
turnDetection: "none",
|
|
251
303
|
supportsDiarization: true,
|
|
252
304
|
languageSelection: "manual",
|
|
253
305
|
credentialsGuide: {
|
|
@@ -342,6 +394,32 @@ export function supportsBoundary(
|
|
|
342
394
|
return CATALOG.get(id)?.supportedBoundaries.has(boundary) ?? false;
|
|
343
395
|
}
|
|
344
396
|
|
|
397
|
+
/**
|
|
398
|
+
* Message explaining why a provider cannot serve the `daemon-batch` boundary.
|
|
399
|
+
*
|
|
400
|
+
* Streaming-only providers are selected through the same
|
|
401
|
+
* `services.stt.provider` key as batch-capable ones, so a batch caller that
|
|
402
|
+
* reports only "nothing is configured" points the operator at the wrong
|
|
403
|
+
* problem. This names the provider and, where one exists, the batch-capable
|
|
404
|
+
* provider on the same credential, so acting on it needs no catalog reading.
|
|
405
|
+
*/
|
|
406
|
+
export function batchBoundaryGapReason(id: SttProviderId): string {
|
|
407
|
+
const entry = CATALOG.get(id);
|
|
408
|
+
const label = entry?.displayName ?? id;
|
|
409
|
+
const alternative = entry
|
|
410
|
+
? [...CATALOG.values()].find(
|
|
411
|
+
(candidate) =>
|
|
412
|
+
candidate.id !== entry.id &&
|
|
413
|
+
candidate.credentialProvider === entry.credentialProvider &&
|
|
414
|
+
candidate.supportedBoundaries.has("daemon-batch"),
|
|
415
|
+
)
|
|
416
|
+
: undefined;
|
|
417
|
+
const remedy = alternative
|
|
418
|
+
? `Batch transcription requires the ${alternative.id} provider: set services.stt.provider to "${alternative.id}".`
|
|
419
|
+
: "Set services.stt.provider to a provider that supports batch transcription.";
|
|
420
|
+
return `${label} is streaming-only. ${remedy}`;
|
|
421
|
+
}
|
|
422
|
+
|
|
345
423
|
/**
|
|
346
424
|
* Check whether a provider supports speaker diarization.
|
|
347
425
|
*
|
|
@@ -353,6 +431,19 @@ export function supportsDiarization(id: SttProviderId): boolean {
|
|
|
353
431
|
return CATALOG.get(id)?.supportsDiarization ?? false;
|
|
354
432
|
}
|
|
355
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Check whether a provider decides end-of-turn itself.
|
|
436
|
+
*
|
|
437
|
+
* Returns `false` for unknown provider IDs, which keeps an unrecognized
|
|
438
|
+
* provider on the local silence boundary rather than waiting for turn events
|
|
439
|
+
* that will never arrive. A live-voice session reads this instead of naming a
|
|
440
|
+
* provider, so a new turn-detecting provider is a catalog entry rather than a
|
|
441
|
+
* session change.
|
|
442
|
+
*/
|
|
443
|
+
export function supportsProviderTurnDetection(id: SttProviderId): boolean {
|
|
444
|
+
return CATALOG.get(id)?.turnDetection === "provider";
|
|
445
|
+
}
|
|
446
|
+
|
|
356
447
|
/**
|
|
357
448
|
* Return all canonical provider IDs in deterministic (insertion) order.
|
|
358
449
|
*/
|
|
@@ -6,8 +6,10 @@ import type {
|
|
|
6
6
|
StreamingTranscriber,
|
|
7
7
|
SttProviderId,
|
|
8
8
|
} from "../../stt/types.js";
|
|
9
|
+
import { SttError } from "../../stt/types.js";
|
|
9
10
|
import { getLogger } from "../../util/logger.js";
|
|
10
11
|
import {
|
|
12
|
+
batchBoundaryGapReason,
|
|
11
13
|
getCredentialProvider,
|
|
12
14
|
getProviderEntry,
|
|
13
15
|
supportsBoundary,
|
|
@@ -88,8 +90,13 @@ export function effectiveSttLanguage(
|
|
|
88
90
|
*
|
|
89
91
|
* Returns `null` when:
|
|
90
92
|
* - The configured provider is not in the catalog.
|
|
91
|
-
* - The configured provider doesn't support the `daemon-batch` boundary.
|
|
92
93
|
* - No credentials are configured for the resolved provider.
|
|
94
|
+
*
|
|
95
|
+
* Throws an {@link SttError} when the configured provider is in the catalog
|
|
96
|
+
* but has no `daemon-batch` boundary. That is a configuration mismatch the
|
|
97
|
+
* resolver can name, and returning `null` for it would reach the user as the
|
|
98
|
+
* "no speech-to-text provider is configured" copy every caller pairs with
|
|
99
|
+
* `null`, which is the opposite of what happened.
|
|
93
100
|
*/
|
|
94
101
|
export async function resolveBatchTranscriber(): Promise<BatchTranscriber | null> {
|
|
95
102
|
// Snapshot the stt config once, before any await, so a concurrent config
|
|
@@ -111,7 +118,9 @@ export async function resolveBatchTranscriber(): Promise<BatchTranscriber | null
|
|
|
111
118
|
|
|
112
119
|
// Verify the provider supports the daemon-batch boundary.
|
|
113
120
|
if (!supportsBoundary(provider as SttProviderId, "daemon-batch")) {
|
|
114
|
-
|
|
121
|
+
const reason = batchBoundaryGapReason(provider as SttProviderId);
|
|
122
|
+
log.warn({ providerId: provider }, reason);
|
|
123
|
+
throw new SttError("provider-error", reason, { userFacing: true });
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
if (provider === "vellum") {
|
|
@@ -632,6 +641,20 @@ async function createStreamingTranscriber(
|
|
|
632
641
|
: {}),
|
|
633
642
|
});
|
|
634
643
|
}
|
|
644
|
+
case "deepgram-flux": {
|
|
645
|
+
// Flux is streaming-only and dials Deepgram's /v2/listen conversational
|
|
646
|
+
// endpoint. Turn-detection tuning comes from `liveVoice.flux`, which
|
|
647
|
+
// the adapter reads itself, so only the transport-level sample rate is
|
|
648
|
+
// passed here. No language is forwarded: the spike pins the
|
|
649
|
+
// English-only `flux-general-en`, and `language_hint` means nothing to
|
|
650
|
+
// a monolingual model. Diarization is off in the catalog, so a
|
|
651
|
+
// `"required"` caller never reaches this case.
|
|
652
|
+
const { DeepgramFluxRealtimeTranscriber } =
|
|
653
|
+
await import("./deepgram-flux-realtime.js");
|
|
654
|
+
return new DeepgramFluxRealtimeTranscriber(apiKey, {
|
|
655
|
+
sampleRate: options.sampleRate,
|
|
656
|
+
});
|
|
657
|
+
}
|
|
635
658
|
default: {
|
|
636
659
|
const _exhaustive: never = providerId;
|
|
637
660
|
return null;
|
package/src/routes/control.ts
CHANGED
|
@@ -149,6 +149,7 @@ export class RouteHostClient {
|
|
|
149
149
|
({ pid } = await spawnWorkerProcess({
|
|
150
150
|
pidPath: this.pidPath,
|
|
151
151
|
entry: this.workerEntryUrl,
|
|
152
|
+
packagedEntry: "routes",
|
|
152
153
|
workerLabel: "Route host",
|
|
153
154
|
// Owned by the daemon (appears in its process tree, torn down with it);
|
|
154
155
|
// kill it if it hangs during startup so a failed spawn leaves nothing.
|
|
@@ -33,6 +33,13 @@ export interface RouteInvokeParams {
|
|
|
33
33
|
readonly url: string;
|
|
34
34
|
/** Request header entries as `[name, value]` pairs (preserves duplicates). */
|
|
35
35
|
readonly headers: ReadonlyArray<readonly [string, string]>;
|
|
36
|
+
/**
|
|
37
|
+
* Manifest name of the plugin whose namespace the route falls in, absent for
|
|
38
|
+
* a workspace route. The host marks it as the plugin in context for the
|
|
39
|
+
* handler's execution, so plugin-scoped host APIs behave the same whether the
|
|
40
|
+
* handler runs in the host or in-thread on the daemon.
|
|
41
|
+
*/
|
|
42
|
+
readonly pluginName?: string;
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
/**
|
package/src/routes/worker.ts
CHANGED
|
@@ -24,7 +24,13 @@ import { createServer, type Server, type Socket } from "node:net";
|
|
|
24
24
|
import type { IpcEnvelope } from "@vellumai/ipc-server-utils";
|
|
25
25
|
import { IpcFrameReader, writeMessage } from "@vellumai/ipc-server-utils";
|
|
26
26
|
|
|
27
|
+
import { runInPluginContext } from "../plugins/plugin-execution-context.js";
|
|
27
28
|
import { disableStreamSeqStamping } from "../runtime/assistant-stream-state.js";
|
|
29
|
+
import {
|
|
30
|
+
evictRouteSourceTree,
|
|
31
|
+
importRouteModule,
|
|
32
|
+
sourceRootForHandler,
|
|
33
|
+
} from "../runtime/routes/user-route-import.js";
|
|
28
34
|
import { getLogger } from "../util/logger.js";
|
|
29
35
|
import {
|
|
30
36
|
ensureProcDir,
|
|
@@ -43,6 +49,9 @@ import {
|
|
|
43
49
|
|
|
44
50
|
const log = getLogger("route-host");
|
|
45
51
|
|
|
52
|
+
/** Last entry-file mtime imported in this process, keyed by handler path. */
|
|
53
|
+
const lastHandlerMtime = new Map<string, number>();
|
|
54
|
+
|
|
46
55
|
const socketPath = getProcSocketPath(ROUTE_HOST_PROC_NAME);
|
|
47
56
|
const pidPath = getProcPidPath(ROUTE_HOST_PROC_NAME);
|
|
48
57
|
|
|
@@ -110,30 +119,54 @@ async function handleInvoke(
|
|
|
110
119
|
params: RouteInvokeParams,
|
|
111
120
|
body: Uint8Array | undefined,
|
|
112
121
|
): Promise<void> {
|
|
113
|
-
// Each worker has its own module cache
|
|
114
|
-
// handler
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
// Each worker has its own module cache. When the entry file's mtime
|
|
123
|
+
// moves, evict the whole source tree so a new handler cannot bind to a
|
|
124
|
+
// stale helper, then re-import.
|
|
125
|
+
const lastMtime = lastHandlerMtime.get(params.filePath);
|
|
126
|
+
if (lastMtime !== params.mtimeMs) {
|
|
127
|
+
evictRouteSourceTree(sourceRootForHandler(params.filePath));
|
|
128
|
+
lastHandlerMtime.set(params.filePath, params.mtimeMs);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// A plugin's own routes execute as that plugin, matching the daemon's
|
|
132
|
+
// in-thread path, so plugin-scoped host APIs a handler reaches
|
|
133
|
+
// (`resolveCredential`, `indexDocument`) scope to the owning plugin rather
|
|
134
|
+
// than falling through to their unscoped branch. The context covers the
|
|
135
|
+
// import as well as the call: a route module can reach a scoped API at
|
|
136
|
+
// evaluation time, and it is imported once per mtime.
|
|
137
|
+
const serve = async (): Promise<
|
|
138
|
+
{ ok: true; response: Response } | { ok: false; allowed: string[] }
|
|
139
|
+
> => {
|
|
140
|
+
const mod = await importRouteModule(params.filePath);
|
|
141
|
+
const handler = mod[params.method];
|
|
142
|
+
if (typeof handler !== "function") {
|
|
143
|
+
return {
|
|
144
|
+
ok: false,
|
|
145
|
+
allowed: HTTP_METHODS.filter((m) => typeof mod[m] === "function"),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const request = reconstructRequest(params, body);
|
|
149
|
+
const response = (await (handler as (req: Request) => unknown)(
|
|
150
|
+
request,
|
|
151
|
+
)) as Response;
|
|
152
|
+
return { ok: true, response };
|
|
153
|
+
};
|
|
154
|
+
const outcome = await (params.pluginName
|
|
155
|
+
? runInPluginContext(params.pluginName, serve)
|
|
156
|
+
: serve());
|
|
157
|
+
|
|
158
|
+
if (!outcome.ok) {
|
|
122
159
|
replyResult(
|
|
123
160
|
socket,
|
|
124
161
|
id,
|
|
125
162
|
405,
|
|
126
|
-
allowed.length ? [["allow", allowed.join(", ")]] : [],
|
|
163
|
+
outcome.allowed.length ? [["allow", outcome.allowed.join(", ")]] : [],
|
|
127
164
|
null,
|
|
128
165
|
);
|
|
129
166
|
return;
|
|
130
167
|
}
|
|
131
168
|
|
|
132
|
-
const
|
|
133
|
-
const response = (await (handler as (req: Request) => unknown)(
|
|
134
|
-
request,
|
|
135
|
-
)) as Response;
|
|
136
|
-
|
|
169
|
+
const { response } = outcome;
|
|
137
170
|
const buffer = new Uint8Array(await response.arrayBuffer());
|
|
138
171
|
const headers: [string, string][] = [];
|
|
139
172
|
response.headers.forEach((value, name) => {
|
package/src/runtime/AGENTS.md
CHANGED
|
@@ -93,39 +93,38 @@ Host app-control allows the assistant to proxy app-control actions (target a spe
|
|
|
93
93
|
- `POST /v1/host-app-control-result` — `{ requestId, state, pngBase64?, windowBounds?, executionResult?, executionError? }`. `state` is one of `"running" | "missing" | "minimized"`.
|
|
94
94
|
- **Tracking**: Uses the same `pending-interactions` tracker as the other host proxy types, with `kind: "host_app_control"`. The route handler is in `host-app-control-routes.ts` and forwards the payload to the owning conversation's `hostAppControlProxy.resolve()`. Late delivery is tolerated — the route returns 200 even when no pending interaction matches (e.g. the conversation was disposed before the client reported back).
|
|
95
95
|
|
|
96
|
-
### `chrome-extension` interface
|
|
96
|
+
### `chrome-extension` interface
|
|
97
97
|
|
|
98
98
|
The `chrome-extension` interface in `INTERFACE_IDS` is a non-interactive transport that supports only the `host_browser` capability — it does NOT support `host_bash`, `host_file`, or `host_cu`. This is encoded in `supportsHostProxy(id, capability)`: passing a capability argument returns `true` for `chrome-extension` only when the capability is `host_browser`; the no-arg form returns `false` for `chrome-extension` (so legacy desktop-only call sites that assume full-desktop proxy availability continue to gate correctly).
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
The extension reaches the daemon over the same two doors every client uses. Self-hosted, it pairs once through the gateway's `POST /v1/pair` (`gateway/src/http/routes/pair.ts`: loopback-only, rate-limited, mints an `actor_client_v1` JWT for the `X-Vellum-Interface-Id: chrome-extension` caller); cloud deployments issue the guardian-bound JWT through the gateway's WorkOS-backed flow. It then subscribes to `GET /v1/events` with `X-Vellum-Interface-Id: chrome-extension`, which registers it on `assistantEventHub` with the single `host_browser` capability, and it answers work by POSTing to `POST /v1/host-browser-result`.
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
`HostBrowserProxy` (`daemon/host-browser-proxy.ts`, a lazily-created singleton) is the only sender: it publishes `host_browser_request` frames to the hub with `targetCapability: "host_browser"` and an explicit target client, choosing that client at send time from the hub's live roster (`resolveTargetClient`). Both the extension and the macOS desktop bridge register `host_browser`, so ordering is method-aware rather than pure recency: `Vellum.*` pseudo-methods (tabs, attach, detach) go only to a chrome-extension client, the only transport that implements them; raw CDP methods prefer a chrome-extension client over the macOS bridge, most recently active first within each group; an explicit `targetClientId` pins one client; and when a `sourceActorPrincipalId` is supplied only that actor's clients are eligible. Several extension installs for one guardian are simply several `host_browser` clients on the roster. A dispatch that lands during a brief MV3 service-worker reconnect waits up to `EXTENSION_RECONNECT_GRACE_MS` before failing.
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
Nothing in the turn layer wires the proxy: it reads the roster on every send, and the conversation's own event sink is fixed for its life (see `assistant/AGENTS.md`, "Conversation event delivery and turn presence"), so a queued or drained turn reaches the extension exactly like a live one.
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
See `docs/browser-use-architecture-phase2.md` for the full wire diagram and component inventory.
|
|
106
|
+
See `docs/browser-use-architecture-phase2.md` for the backend scenarios and the manual QA checklist.
|
|
109
107
|
|
|
110
108
|
### Canonical browser backend precedence (macOS)
|
|
111
109
|
|
|
112
110
|
On macOS-originated turns, the CDP factory (`tools/browser/cdp-client/factory.ts`) evaluates three browser backends in strict priority order. Each candidate is tried lazily; if the first command fails with a transport-level error, the factory falls over to the next candidate. CDP protocol errors (the browser understood the command but rejected it) do NOT trigger failover.
|
|
113
111
|
|
|
114
|
-
| Priority | Backend | Condition
|
|
115
|
-
| -------- | -------------------------- |
|
|
116
|
-
| 1 | **Extension / host proxy** | `
|
|
117
|
-
| 2 | **cdp-inspect** | (a) `hostBrowser.cdpInspect.enabled` is `true` in config, OR (b) `transportInterface === "macos"` AND `desktopAuto.enabled` is `true` (default) AND the cooldown from a prior failure is not active
|
|
118
|
-
| 3 | **Local** | Always present as the final fallback
|
|
112
|
+
| Priority | Backend | Condition | Transport |
|
|
113
|
+
| -------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
|
|
114
|
+
| 1 | **Extension / host proxy** | Two candidates from the always-present `HostBrowserProxy` singleton: `extension` when `hasExtensionClient(actor)` finds a chrome-extension client on the hub; otherwise `host-bridge` when `isAvailable(actor)` finds any `host_browser` client (the macOS desktop bridge) and that actor's host-bridge cooldown is not active | SSE via `assistantEventHub` with `targetCapability: "host_browser"`, to the chosen client |
|
|
115
|
+
| 2 | **cdp-inspect** | (a) `hostBrowser.cdpInspect.enabled` is `true` in config, OR (b) `transportInterface === "macos"` AND `desktopAuto.enabled` is `true` (default) AND the cooldown from a prior failure is not active | Direct CDP WebSocket to `localhost:9222` |
|
|
116
|
+
| 3 | **Local** | Always present as the final fallback | In-process Playwright CDP via `browserManager` |
|
|
119
117
|
|
|
120
118
|
**Transport selection for the extension/host-proxy backend:**
|
|
121
119
|
|
|
122
|
-
The "extension" backend label
|
|
120
|
+
The "extension" backend label predates the macOS bridge; two SSE transports power it, both through the same `HostBrowserProxy` → `ExtensionCdpClient` pipeline:
|
|
121
|
+
|
|
122
|
+
- **Chrome extension**: `HostBrowserProxy.send()` publishes to `assistantEventHub` with `targetCapability: "host_browser"`, targeting the chrome-extension client `resolveTargetClient` chose (see the interface section above); the extension executes the CDP command via `chrome.debugger` and POSTs the result to `/v1/host-browser-result`.
|
|
123
|
+
- **macOS SSE bridge**: when no chrome-extension client is eligible, the same publish targets the macOS subscriber (which registers every host-proxy capability); the desktop client executes the command against the local Chrome and POSTs the result the same way.
|
|
123
124
|
|
|
124
|
-
|
|
125
|
-
- **Extension SSE** (cloud/platform): When no WebSocket entry exists, `HostBrowserProxy.send()` publishes to `assistantEventHub` with `targetCapability: "host_browser"`. The hub delivers the event to the chrome-extension subscriber (which registered with that capability via SSE). The extension POSTs results back to `/v1/host-browser-result`. This path is used for any `canServiceSseBrowser()` interface (`web`, `chrome-extension`, `macos`).
|
|
126
|
-
- **macOS SSE bridge**: When the macOS desktop client is connected but no extension is present, the same hub publish with `targetCapability: "host_browser"` delivers to the macOS subscriber (which has all host-proxy capabilities). The desktop client executes CDP commands against the local Chrome and POSTs results back to `/v1/host-browser-result`.
|
|
125
|
+
In the CDP factory the bridge is the internal `"host-bridge"` candidate kind (`InternalBrowserMode`, never a caller-pinnable `browser_mode`). `browser_status` labels the extension path `details.transport: "extension-ws"`; the label predates the SSE transport and is kept as-is.
|
|
127
126
|
|
|
128
|
-
|
|
127
|
+
**Host-bridge cooldown:** a `host-bridge` transport failure records a per-actor cooldown (`recordHostBridgeCooldown`, keyed by `sourceActorPrincipalId`, `__default__` when unresolved) for the same `desktopAuto.cooldownMs` window; while it is active the factory skips the bridge candidate (log `CDP factory: host-bridge skipped (cooldown active)`) and the turn drops straight to cdp-inspect/local. Per-actor because on a multi-actor cloud daemon the bridge reaches a different desktop per actor, so one actor's missing debug port must not suppress another's only route to their Chrome. Never applies to the `extension` candidate.
|
|
129
128
|
|
|
130
129
|
**Fallback criteria for cdp-inspect (desktop-auto):**
|
|
131
130
|
|
|
@@ -29,6 +29,7 @@ import { buildVellumCardAffinity } from "../notifications/vellum-card-affinity.j
|
|
|
29
29
|
import { IntegrityError } from "../util/errors.js";
|
|
30
30
|
import { getLogger } from "../util/logger.js";
|
|
31
31
|
import { resolveAnchoredGuardian } from "./anchored-guardian.js";
|
|
32
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "./assistant-scope.js";
|
|
32
33
|
import { CHALLENGE_TTL_MS } from "./channel-verification-service.js";
|
|
33
34
|
import {
|
|
34
35
|
type AccessRequestTrigger,
|
|
@@ -46,7 +47,6 @@ const log = getLogger("access-request-helper");
|
|
|
46
47
|
export type { AccessRequestTrigger } from "./introduction-policy.js";
|
|
47
48
|
|
|
48
49
|
export interface AccessRequestParams {
|
|
49
|
-
canonicalAssistantId: string;
|
|
50
50
|
sourceChannel: ChannelId;
|
|
51
51
|
conversationExternalId: string;
|
|
52
52
|
actorExternalId?: string;
|
|
@@ -93,15 +93,18 @@ export type AccessRequestResult =
|
|
|
93
93
|
// ---------------------------------------------------------------------------
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
96
|
+
* Conversation id for an actor's access requests. Stable key that dedupes
|
|
97
|
+
* pending prompts for the same (channel, actor).
|
|
98
|
+
*
|
|
99
|
+
* The `self` segment is part of a persisted id format: guardian request rows
|
|
100
|
+
* carry these ids, so the shape is fixed even though the daemon scopes all its
|
|
101
|
+
* storage to the one assistant (`DAEMON_INTERNAL_ASSISTANT_ID`).
|
|
98
102
|
*/
|
|
99
103
|
export function accessRequestConversationId(
|
|
100
|
-
canonicalAssistantId: string,
|
|
101
104
|
sourceChannel: string,
|
|
102
105
|
actorExternalId: string,
|
|
103
106
|
): string {
|
|
104
|
-
return `access-req-${
|
|
107
|
+
return `access-req-${DAEMON_INTERNAL_ASSISTANT_ID}-${sourceChannel}-${actorExternalId}`;
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
/**
|
|
@@ -126,7 +129,6 @@ export function accessRequestConversationId(
|
|
|
126
129
|
* fail-closed.
|
|
127
130
|
*/
|
|
128
131
|
export async function isApprovalHandshakeInProgress(params: {
|
|
129
|
-
canonicalAssistantId: string;
|
|
130
132
|
sourceChannel: string;
|
|
131
133
|
actorExternalId: string;
|
|
132
134
|
}): Promise<boolean> {
|
|
@@ -134,7 +136,6 @@ export async function isApprovalHandshakeInProgress(params: {
|
|
|
134
136
|
return false;
|
|
135
137
|
}
|
|
136
138
|
const conversationId = accessRequestConversationId(
|
|
137
|
-
params.canonicalAssistantId,
|
|
138
139
|
params.sourceChannel,
|
|
139
140
|
params.actorExternalId,
|
|
140
141
|
);
|
|
@@ -171,7 +172,6 @@ export async function notifyGuardianOfAccessRequest(
|
|
|
171
172
|
params: AccessRequestParams,
|
|
172
173
|
): Promise<AccessRequestResult> {
|
|
173
174
|
const {
|
|
174
|
-
canonicalAssistantId,
|
|
175
175
|
sourceChannel,
|
|
176
176
|
conversationExternalId,
|
|
177
177
|
actorExternalId,
|
|
@@ -219,7 +219,6 @@ export async function notifyGuardianOfAccessRequest(
|
|
|
219
219
|
// from assistant A could be returned for assistant B, allowing the caller
|
|
220
220
|
// to piggyback on A's guardian approval.
|
|
221
221
|
const conversationId = accessRequestConversationId(
|
|
222
|
-
canonicalAssistantId,
|
|
223
222
|
sourceChannel,
|
|
224
223
|
actorExternalId,
|
|
225
224
|
);
|
|
@@ -270,7 +269,6 @@ export async function notifyGuardianOfAccessRequest(
|
|
|
270
269
|
// re-prompting is allowed again.
|
|
271
270
|
if (
|
|
272
271
|
await isApprovalHandshakeInProgress({
|
|
273
|
-
canonicalAssistantId,
|
|
274
272
|
sourceChannel,
|
|
275
273
|
actorExternalId,
|
|
276
274
|
})
|
|
@@ -283,7 +281,7 @@ export async function notifyGuardianOfAccessRequest(
|
|
|
283
281
|
}
|
|
284
282
|
|
|
285
283
|
const senderIdentifier = actorDisplayName || actorUsername || actorExternalId;
|
|
286
|
-
const requestId = `access-req-${
|
|
284
|
+
const requestId = `access-req-${DAEMON_INTERNAL_ASSISTANT_ID}-${sourceChannel}-${actorExternalId}-${Date.now()}`;
|
|
287
285
|
|
|
288
286
|
// Access requests are decisionable: without a bound principal nobody could
|
|
289
287
|
// ever decide them (mirrors the gateway create's integrity guard).
|
|
@@ -461,7 +459,6 @@ export async function maybeNotifyGuardianOfAdmittedContact(
|
|
|
461
459
|
}
|
|
462
460
|
|
|
463
461
|
const conversationId = accessRequestConversationId(
|
|
464
|
-
params.canonicalAssistantId,
|
|
465
462
|
params.sourceChannel,
|
|
466
463
|
params.actorExternalId,
|
|
467
464
|
);
|
|
@@ -360,7 +360,7 @@ export interface WakeOptions {
|
|
|
360
360
|
* the conversation belongs to. Used by fork-based memory retrospectives to
|
|
361
361
|
* render the SOURCE conversation's persona sections — both for review
|
|
362
362
|
* quality and for byte-parity with the source's cached system-prompt
|
|
363
|
-
* prefix. May also pin
|
|
363
|
+
* prefix. May also pin presence for the prompt build (see
|
|
364
364
|
* {@link SystemPromptPersonaOverride}). Prompt-build selection only; trust
|
|
365
365
|
* class and approval semantics are governed solely by `trustContext`.
|
|
366
366
|
*/
|
|
@@ -400,14 +400,14 @@ export interface WakeOptions {
|
|
|
400
400
|
*/
|
|
401
401
|
cronRunId?: string;
|
|
402
402
|
/**
|
|
403
|
-
* Run the woken turn clientless: pin
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
* `
|
|
408
|
-
* `
|
|
409
|
-
*
|
|
410
|
-
*
|
|
403
|
+
* Run the woken turn clientless: pin the per-turn presence
|
|
404
|
+
* (`currentTurnIsNonInteractive = true`, which `hasNoClient` reads) for the
|
|
405
|
+
* duration of the agent-loop run (restored after). Wakes bypass the
|
|
406
|
+
* orchestrator's turn-start interactivity setup, so the pin is what makes
|
|
407
|
+
* `conversation-tool-setup` derive `isInteractive: false`, which
|
|
408
|
+
* `policy-context` maps to `background` (guardian) / `headless` (unknown),
|
|
409
|
+
* so a side-effecting tool that would prompt is denied instead of stalling
|
|
410
|
+
* on a client that isn't there.
|
|
411
411
|
*/
|
|
412
412
|
clientless?: boolean;
|
|
413
413
|
}
|
|
@@ -718,9 +718,9 @@ export async function wakeAgentForOpportunity(
|
|
|
718
718
|
return runWakeSingleFlight(conversationId, async () => {
|
|
719
719
|
// Snapshot the conversation's resting trust before the resolver runs, so
|
|
720
720
|
// it can be restored after. The resolver leaves the wake's trust on the
|
|
721
|
-
// conversation, and a following no-trust wake would otherwise
|
|
722
|
-
//
|
|
723
|
-
//
|
|
721
|
+
// conversation, and a following no-trust wake would otherwise pick it up
|
|
722
|
+
// from the resting trust its consumers fall back to. Null when the
|
|
723
|
+
// conversation isn't resident yet (a fresh hydrate or a fork).
|
|
724
724
|
let priorPersistentTrust: TrustContext | null = null;
|
|
725
725
|
if (opts.trustContext) {
|
|
726
726
|
const { findConversation } =
|
|
@@ -1454,7 +1454,8 @@ export async function wakeAgentForOpportunity(
|
|
|
1454
1454
|
const priorCallSite = conversation.currentCallSite;
|
|
1455
1455
|
const priorTurnOverrideProfile = conversation.currentTurnOverrideProfile;
|
|
1456
1456
|
const priorTurnCronRunId = conversation.currentTurnCronRunId;
|
|
1457
|
-
const
|
|
1457
|
+
const priorTurnIsNonInteractive =
|
|
1458
|
+
conversation.currentTurnIsNonInteractive;
|
|
1458
1459
|
const priorTurnTrust = conversation.currentTurnTrustContext;
|
|
1459
1460
|
conversation.currentCallSite = callSite;
|
|
1460
1461
|
conversation.currentTurnOverrideProfile = overrideProfile;
|
|
@@ -1462,7 +1463,9 @@ export async function wakeAgentForOpportunity(
|
|
|
1462
1463
|
// delegates work to subagents whose usage must attribute to that firing.
|
|
1463
1464
|
conversation.currentTurnCronRunId = opts.cronRunId ?? null;
|
|
1464
1465
|
if (opts.clientless) {
|
|
1465
|
-
|
|
1466
|
+
// Presence is per-turn state; a clientless wake declares no human is
|
|
1467
|
+
// present for the duration of its dispatch.
|
|
1468
|
+
conversation.currentTurnIsNonInteractive = true;
|
|
1466
1469
|
}
|
|
1467
1470
|
// Per-turn guardian elevation for the wake's tools, set after the pre-run
|
|
1468
1471
|
// reads so a pre-run failure can't leak it; restored in the finally.
|
|
@@ -1550,7 +1553,7 @@ export async function wakeAgentForOpportunity(
|
|
|
1550
1553
|
conversation.currentCallSite = priorCallSite;
|
|
1551
1554
|
conversation.currentTurnOverrideProfile = priorTurnOverrideProfile;
|
|
1552
1555
|
conversation.currentTurnCronRunId = priorTurnCronRunId;
|
|
1553
|
-
conversation.
|
|
1556
|
+
conversation.currentTurnIsNonInteractive = priorTurnIsNonInteractive;
|
|
1554
1557
|
conversation.currentTurnTrustContext = priorTurnTrust;
|
|
1555
1558
|
}
|
|
1556
1559
|
|