@vellumai/assistant 0.10.12 → 0.11.0-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/AGENTS.md +1 -1
- package/ARCHITECTURE.md +4 -5
- package/README.md +1 -1
- package/docs/architecture/memory.md +60 -23
- package/docs/error-handling.md +3 -3
- package/docs/guardian-request-flow.md +112 -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__/channels.test.ts +9 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
- 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__/channels.test.ts +9 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -1
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/openapi.yaml +264 -14
- package/package.json +2 -2
- package/src/__tests__/acp-session.test.ts +3 -3
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
- package/src/__tests__/anthropic-provider.test.ts +40 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +33 -2
- package/src/__tests__/app-conversation-ids.test.ts +204 -0
- package/src/__tests__/approval-cascade.test.ts +5 -5
- package/src/__tests__/approval-routes-http.test.ts +3 -3
- package/src/__tests__/ask-question-resolver.test.ts +207 -0
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
- package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
- package/src/__tests__/assistant-event-hub.test.ts +13 -11
- package/src/__tests__/assistant-event.test.ts +12 -9
- package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
- package/src/__tests__/assistant-stream-state.test.ts +17 -7
- package/src/__tests__/avatar-identity-sync.test.ts +3 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-conversation-messages.test.ts +134 -18
- package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
- package/src/__tests__/channel-approvals.test.ts +0 -27
- package/src/__tests__/channel-guardian.test.ts +85 -512
- package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
- package/src/__tests__/channel-retry-sweep.test.ts +88 -1
- package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
- package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
- package/src/__tests__/compaction-events.test.ts +8 -8
- package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
- package/src/__tests__/config-model-image-provider.test.ts +20 -0
- package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
- package/src/__tests__/config-schema.test.ts +14 -2
- package/src/__tests__/config-set-platform-guard.test.ts +11 -12
- package/src/__tests__/config-sounds-sync.test.ts +4 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
- package/src/__tests__/context-search-memory-source.test.ts +1 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
- package/src/__tests__/context-token-estimator.test.ts +54 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
- package/src/__tests__/conversation-agent-loop.test.ts +39 -30
- package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
- package/src/__tests__/conversation-evictor.test.ts +49 -0
- package/src/__tests__/conversation-fork-crud.test.ts +1 -1
- package/src/__tests__/conversation-group-tools.test.ts +279 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
- package/src/__tests__/conversation-lineage.test.ts +235 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
- package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +81 -81
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
- package/src/__tests__/conversation-slash-queue.test.ts +11 -11
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
- package/src/__tests__/conversation-speed-override.test.ts +2 -2
- package/src/__tests__/conversation-summarize-route.test.ts +9 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
- package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
- package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
- package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
- package/src/__tests__/conversation-sync-tags.test.ts +5 -5
- package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
- package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/daemon-assistant-events.test.ts +14 -15
- package/src/__tests__/db-test-helpers.ts +13 -27
- package/src/__tests__/disk-pressure-routes.test.ts +12 -3
- package/src/__tests__/document-tool-security.test.ts +95 -0
- package/src/__tests__/drain-kick-guard.test.ts +232 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
- package/src/__tests__/emit-event-signal.test.ts +5 -6
- package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
- package/src/__tests__/events-tail-route.test.ts +6 -4
- package/src/__tests__/feature-flag-test-helpers.ts +10 -20
- package/src/__tests__/file-edit-tool.test.ts +24 -4
- package/src/__tests__/file-list-tool.test.ts +2 -1
- package/src/__tests__/file-read-tool.test.ts +62 -10
- package/src/__tests__/file-write-tool.test.ts +24 -5
- package/src/__tests__/followup-tools.test.ts +58 -0
- package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
- package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
- package/src/__tests__/guardian-question-mode.test.ts +42 -3
- package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
- package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
- package/src/__tests__/host-browser-proxy.test.ts +1 -1
- package/src/__tests__/host-file-edit-tool.test.ts +3 -3
- package/src/__tests__/host-file-read-tool.test.ts +2 -2
- package/src/__tests__/host-file-write-tool.test.ts +7 -3
- package/src/__tests__/host-shell-tool.test.ts +17 -5
- package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
- package/src/__tests__/image-credentials.test.ts +65 -8
- package/src/__tests__/injection-block.test.ts +4 -4
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
- package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
- package/src/__tests__/injector-v3-suppression.test.ts +6 -4
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
- package/src/__tests__/list-messages-page-latest.test.ts +2 -2
- package/src/__tests__/llm-usage-store.test.ts +67 -4
- package/src/__tests__/log-redact.test.ts +18 -0
- package/src/__tests__/managed-profile-guard.test.ts +27 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +62 -11
- package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
- package/src/__tests__/notification-decision-strategy.test.ts +115 -11
- package/src/__tests__/notification-deep-link.test.ts +12 -12
- package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
- package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
- package/src/__tests__/path-policy.test.ts +315 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
- package/src/__tests__/persistence-layering-guard.test.ts +2 -2
- package/src/__tests__/pkb-autoinject.test.ts +1 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
- package/src/__tests__/platform-callback-registration.test.ts +10 -10
- package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
- package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
- package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
- package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
- package/src/__tests__/require-fresh-approval.test.ts +38 -38
- package/src/__tests__/resolve-app-id.test.ts +32 -0
- package/src/__tests__/run-due-schedules.test.ts +72 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +44 -5
- package/src/__tests__/schedule-store.test.ts +3 -3
- package/src/__tests__/schedule-tools.test.ts +176 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
- package/src/__tests__/secret-response-routing.test.ts +3 -3
- package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
- package/src/__tests__/secret-scanner.test.ts +36 -0
- package/src/__tests__/send-endpoint-busy.test.ts +7 -7
- package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
- package/src/__tests__/starter-task-flow.test.ts +26 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/subagent-disposal.test.ts +40 -11
- package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
- package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
- package/src/__tests__/subagent-manager-notify.test.ts +73 -14
- package/src/__tests__/subagent-notify-parent.test.ts +48 -4
- package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
- package/src/__tests__/subagent-tools.test.ts +64 -0
- package/src/__tests__/sync-message-contract.test.ts +3 -3
- package/src/__tests__/terminal-tools.test.ts +12 -3
- package/src/__tests__/test-preload.ts +9 -0
- package/src/__tests__/tool-approval-handler.test.ts +587 -43
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
- package/src/__tests__/tool-executor.test.ts +116 -0
- package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-start-timestamp.test.ts +4 -4
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
- package/src/__tests__/ui-work-result-surface.test.ts +3 -3
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
- package/src/__tests__/voice-session-bridge.test.ts +44 -44
- package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
- package/src/__tests__/workspace-policy.test.ts +482 -2
- package/src/acp/__tests__/client-handler.test.ts +3 -3
- package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
- package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
- package/src/acp/client-handler.ts +3 -3
- package/src/acp/session-manager.ts +8 -8
- package/src/api/events/subagent-event.ts +2 -2
- package/src/api/responses/memory-v2-activation-log.ts +2 -2
- package/src/api/responses/subagent-detail.ts +13 -0
- package/src/approvals/AGENTS.md +2 -0
- package/src/approvals/guardian-request-resolvers.ts +118 -24
- package/src/apps/app-store.ts +95 -4
- package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +229 -7
- package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
- package/src/calls/call-controller.ts +27 -27
- package/src/calls/call-conversation-messages.ts +58 -18
- package/src/calls/voice-control-protocol.ts +56 -0
- package/src/calls/voice-session-bridge.ts +178 -65
- package/src/calls/voice-triage-escalate.ts +2 -3
- package/src/channels/config.ts +8 -0
- package/src/channels/types.ts +1 -0
- package/src/cli/commands/config.ts +49 -13
- package/src/cli/commands/memory/index.help.ts +4 -2
- package/src/cli/commands/memory/memory-retrospective.ts +5 -0
- package/src/cli/commands/webhooks.help.ts +9 -4
- package/src/cli/lib/bundled-marketplace.json +12 -0
- package/src/cli.ts +2 -109
- package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
- package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
- package/src/config/assistant-feature-flags.ts +1 -1
- package/src/config/bundled-skills/conversation-groups/SKILL.md +29 -0
- package/src/config/bundled-skills/conversation-groups/TOOLS.json +58 -0
- package/src/config/bundled-skills/conversation-groups/tools/group-create.ts +12 -0
- package/src/config/bundled-skills/conversation-groups/tools/group-list.ts +12 -0
- package/src/config/bundled-skills/conversation-groups/tools/move-to-group.ts +12 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
- package/src/config/bundled-skills/schedule/SKILL.md +2 -0
- package/src/config/feature-flag-cache.ts +6 -16
- package/src/config/feature-flag-registry.json +14 -38
- package/src/config/loader.ts +7 -1
- package/src/config/memory-tier.ts +15 -10
- package/src/config/memory-v3-gate.test.ts +278 -1
- package/src/config/memory-v3-gate.ts +88 -26
- package/src/config/raw-config-utils.ts +1 -1
- package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/live-voice.ts +33 -7
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-retrospective.ts +13 -0
- package/src/config/schemas/memory-substrate.ts +183 -0
- package/src/config/schemas/memory-v2.ts +3 -2
- package/src/config/schemas/memory-v3.ts +11 -4
- package/src/config/schemas/memory.ts +35 -1
- package/src/config/schemas/services.ts +10 -2
- package/src/config/substrate-twin-shadowing.ts +195 -0
- package/src/config/webhook-routing.ts +67 -0
- package/src/context/compactor.ts +10 -3
- package/src/context/token-estimator.ts +21 -0
- package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
- package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
- package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
- package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
- package/src/daemon/channel-ui-capability.ts +70 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
- package/src/daemon/conversation-agent-loop.ts +12 -5
- package/src/daemon/conversation-evictor.ts +26 -4
- package/src/daemon/conversation-launch.ts +11 -14
- package/src/daemon/conversation-lineage.ts +76 -0
- package/src/daemon/conversation-messaging.ts +14 -14
- package/src/daemon/conversation-notifiers.ts +2 -2
- package/src/daemon/conversation-process.ts +133 -21
- package/src/daemon/conversation-queue-manager.ts +7 -7
- package/src/daemon/conversation-runtime-assembly.ts +16 -0
- package/src/daemon/conversation-store.ts +11 -3
- package/src/daemon/conversation-surfaces.ts +8 -14
- package/src/daemon/conversation-tool-setup.ts +13 -7
- package/src/daemon/conversation-usage.ts +12 -11
- package/src/daemon/conversation.ts +38 -15
- package/src/daemon/disk-pressure-guard.ts +5 -12
- package/src/daemon/embedding-reconcile.ts +14 -9
- package/src/daemon/handlers/config-channels.ts +40 -134
- package/src/daemon/handlers/config-model.ts +15 -7
- package/src/daemon/handlers/conversations.ts +4 -2
- package/src/daemon/handlers/shared.ts +29 -0
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/lifecycle.ts +13 -0
- package/src/daemon/message-protocol.ts +8 -144
- package/src/daemon/message-types/computer-use.ts +0 -12
- package/src/daemon/message-types/conversations.ts +9 -345
- package/src/daemon/message-types/host-app-control.ts +0 -9
- package/src/daemon/message-types/host-browser.ts +0 -7
- package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
- package/src/daemon/message-types/messages.ts +0 -48
- package/src/daemon/message-types/notifications.ts +0 -7
- package/src/daemon/message-types/skills.ts +0 -5
- package/src/daemon/message-types/surfaces.ts +0 -9
- package/src/daemon/message-types/sync.ts +0 -2
- package/src/daemon/process-message.ts +5 -5
- package/src/daemon/skill-memory-refresh.ts +5 -5
- package/src/daemon/tool-side-effects.ts +32 -16
- package/src/daemon/trust-context.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +4 -4
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
- package/src/heartbeat/heartbeat-run-store.ts +81 -4
- package/src/heartbeat/heartbeat-service.ts +32 -1
- package/src/home/__tests__/feed-writer.test.ts +7 -7
- package/src/home/__tests__/home-content-refresh.test.ts +3 -0
- package/src/home/__tests__/suggested-prompts.test.ts +1 -0
- package/src/home/feed-writer.ts +6 -13
- package/src/home/home-content-refresh.ts +6 -9
- package/src/home/relationship-state-writer.ts +5 -12
- package/src/home/suggested-prompts-cache.ts +6 -19
- package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
- package/src/ipc/events-publish-client.ts +44 -0
- package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
- package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
- package/src/ipc/routes/events-ipc-routes.ts +11 -31
- package/src/live-voice/__tests__/front-decision.test.ts +4 -176
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
- package/src/live-voice/__tests__/live-voice-continuation-fork-hydration.test.ts +286 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
- package/src/live-voice/__tests__/live-voice-vad.test.ts +1154 -636
- package/src/live-voice/front-decision.ts +5 -155
- package/src/live-voice/live-voice-metrics.ts +4 -1
- package/src/live-voice/live-voice-session.ts +1288 -439
- package/src/live-voice/progress-phrases.ts +17 -0
- package/src/live-voice/protocol.ts +15 -0
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +9 -5
- package/src/media/image-credentials.ts +42 -10
- package/src/media/image-service.ts +1 -13
- package/src/media/types.ts +26 -3
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/__tests__/broadcaster.test.ts +95 -0
- package/src/notifications/adapters/macos.ts +3 -3
- package/src/notifications/broadcaster.ts +57 -0
- package/src/notifications/copy-composer.ts +0 -15
- package/src/notifications/decision-engine.ts +21 -22
- package/src/notifications/guardian-question-mode.ts +57 -2
- package/src/notifications/home-feed-side-effect.ts +4 -0
- package/src/notifications/signal.ts +6 -4
- package/src/notifications/trusted-contact-payloads.ts +3 -4
- package/src/notifications/vellum-card-affinity.ts +39 -0
- package/src/oauth/AGENTS.md +1 -1
- package/src/permissions/channel-permission-query.test.ts +69 -0
- package/src/permissions/channel-permission-query.ts +73 -1
- package/src/permissions/checker.test.ts +298 -15
- package/src/permissions/checker.ts +102 -36
- package/src/permissions/confirmation-guardian-request.test.ts +2 -2
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/gateway-threshold-reader.test.ts +224 -17
- package/src/permissions/gateway-threshold-reader.ts +82 -10
- package/src/permissions/ipc-risk-types.ts +8 -0
- package/src/permissions/prompter.ts +5 -5
- package/src/permissions/question-guardian-request.test.ts +222 -0
- package/src/permissions/question-guardian-request.ts +179 -0
- package/src/permissions/question-prompter.test.ts +8 -8
- package/src/permissions/question-prompter.ts +18 -0
- package/src/permissions/secret-prompter.ts +2 -4
- package/src/permissions/workspace-policy.ts +269 -34
- package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
- package/src/persistence/__tests__/message-content-file.test.ts +58 -3
- package/src/persistence/conversation-crud.ts +93 -0
- package/src/persistence/conversation-key-store.ts +63 -0
- package/src/persistence/conversation-parent.ts +27 -0
- package/src/persistence/db-async-query.ts +1 -1
- package/src/persistence/db-singleton.ts +14 -27
- package/src/persistence/delivery-crud.ts +45 -0
- package/src/persistence/embeddings/embedding-backend.ts +2 -1
- package/src/persistence/embeddings/embedding-identity.ts +7 -3
- package/src/persistence/job-utils.ts +32 -27
- package/src/persistence/jobs-store.ts +92 -3
- package/src/persistence/lifecycle-quiesce.ts +80 -0
- package/src/persistence/llm-usage-store.ts +45 -8
- package/src/persistence/message-content-file.ts +4 -4
- package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
- package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
- package/src/persistence/migrations/354-backfill-app-conversation-lineage.ts +41 -0
- package/src/persistence/schema/infrastructure.ts +11 -0
- package/src/persistence/steps.ts +9 -1
- package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
- package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
- package/src/plugin-api/conversation-turn.ts +4 -4
- package/src/plugin-api/event-hub-facade.ts +15 -6
- package/src/plugin-api/index.ts +10 -4
- package/src/plugin-api/publish-event.ts +36 -0
- package/src/plugins/AGENTS.md +2 -0
- package/src/plugins/defaults/compaction/window-manager.ts +9 -0
- package/src/plugins/defaults/index.ts +9 -13
- package/src/plugins/defaults/memory/AGENTS.md +775 -0
- package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
- package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
- package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
- package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
- package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
- package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
- package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
- package/src/plugins/defaults/memory/graph/store.ts +1 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
- package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
- package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
- package/src/plugins/defaults/memory/indexer.ts +146 -89
- package/src/plugins/defaults/memory/injectors.ts +86 -41
- package/src/plugins/defaults/memory/job-handlers.ts +130 -39
- package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
- package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
- package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
- package/src/plugins/defaults/memory/startup.ts +58 -21
- package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
- package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
- package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
- package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
- package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
- package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
- package/src/plugins/defaults/memory/tools.test.ts +1 -1
- package/src/plugins/defaults/memory/tools.ts +1 -1
- package/src/plugins/defaults/memory/v1/README.md +5 -0
- package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
- package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
- package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
- package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
- package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
- package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
- package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
- package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
- package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
- package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
- package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
- package/src/plugins/defaults/memory/v2/activation.ts +30 -163
- package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
- package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
- package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
- package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
- package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/injection.ts +36 -26
- package/src/plugins/defaults/memory/v2/migration.ts +2 -2
- package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
- package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
- package/src/plugins/defaults/memory/v2/router.ts +38 -15
- package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
- package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
- package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
- package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
- package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
- package/src/plugins/defaults/memory/v3/card.ts +25 -9
- package/src/plugins/defaults/memory/v3/edge.ts +52 -18
- package/src/plugins/defaults/memory/v3/gate.ts +4 -4
- package/src/plugins/defaults/memory/v3/injector.ts +10 -3
- package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
- package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
- package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
- package/src/plugins/defaults/memory/v3/prune.ts +40 -16
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
- package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
- package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
- package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
- package/src/plugins/defaults/memory/v3/types.ts +4 -1
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
- package/src/plugins/defaults/memory/validation.ts +1 -1
- package/src/plugins/defaults/memory/worker.ts +2 -1
- package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
- package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
- package/src/plugins/types.ts +2 -2
- package/src/prompts/sections.ts +4 -16
- package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
- package/src/providers/anthropic/client.ts +15 -6
- package/src/providers/content-block-schema.ts +26 -0
- package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +30 -14
- package/src/providers/model-catalog.ts +77 -0
- package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
- package/src/providers/openai/chat-completions-provider.ts +65 -17
- package/src/providers/openai/input-audio.ts +76 -0
- package/src/providers/openrouter/client.ts +0 -2
- package/src/providers/platform-proxy/constants.ts +4 -0
- package/src/providers/poolside/client.ts +42 -0
- package/src/providers/registry.ts +40 -8
- package/src/providers/retry.ts +2 -0
- package/src/providers/types.ts +39 -1
- package/src/providers/vercel-ai-gateway/client.ts +0 -2
- package/src/runtime/AGENTS.md +7 -5
- package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
- package/src/runtime/__tests__/question-resolution.test.ts +111 -0
- package/src/runtime/access-request-helper.ts +7 -15
- package/src/runtime/assistant-event-hub.ts +43 -31
- package/src/runtime/assistant-event-publish-options.ts +31 -0
- package/src/runtime/assistant-event.ts +19 -30
- package/src/runtime/assistant-stream-state.ts +4 -4
- package/src/runtime/channel-approvals.ts +0 -25
- package/src/runtime/channel-readiness-service.ts +99 -40
- package/src/runtime/channel-retry-sweep.ts +38 -15
- package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
- package/src/runtime/guardian-reply-router.ts +108 -0
- package/src/runtime/http-server.ts +8 -0
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/process-role.ts +42 -0
- package/src/runtime/question-request-guardian-bridge.ts +184 -0
- package/src/runtime/question-resolution.ts +153 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/subagents-routes.test.ts +250 -0
- package/src/runtime/routes/__tests__/webhook-routes.test.ts +201 -0
- package/src/runtime/routes/acp-routes.ts +2 -2
- package/src/runtime/routes/bookmark-routes.ts +3 -15
- package/src/runtime/routes/canned-message-complete.ts +2 -2
- package/src/runtime/routes/consolidation-routes.ts +8 -2
- package/src/runtime/routes/conversation-list-routes.ts +3 -19
- package/src/runtime/routes/conversation-management-routes.ts +1 -5
- package/src/runtime/routes/conversation-query-routes.ts +52 -8
- package/src/runtime/routes/conversation-routes.ts +36 -22
- package/src/runtime/routes/credential-request-routes.ts +0 -1
- package/src/runtime/routes/filing-routes.ts +7 -7
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
- package/src/runtime/routes/image-generation-routes.ts +12 -9
- package/src/runtime/routes/inbound-message-handler.ts +17 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
- package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
- package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/lifecycle-routes.ts +199 -0
- package/src/runtime/routes/platform-routes.ts +3 -8
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
- package/src/runtime/routes/question-routes.ts +34 -87
- package/src/runtime/routes/secret-routes.ts +11 -1
- package/src/runtime/routes/settings-routes.ts +8 -18
- package/src/runtime/routes/subagents-routes.ts +35 -8
- package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
- package/src/runtime/routes/webhook-routes.ts +89 -30
- package/src/runtime/routes/workspace-routes.test.ts +7 -4
- package/src/runtime/slack-reply-session.test.ts +12 -12
- package/src/runtime/slack-reply-session.ts +17 -17
- package/src/runtime/sync/sync-publisher.test.ts +7 -5
- package/src/runtime/tool-grant-request-helper.ts +4 -0
- package/src/schedule/schedule-store.ts +70 -0
- package/src/schedule/scheduler.ts +27 -0
- package/src/security/AGENTS.md +1 -1
- package/src/security/credential-key.ts +17 -0
- package/src/security/secret-ingress.ts +14 -105
- package/src/security/secret-patterns.ts +8 -139
- package/src/security/secret-scanner.ts +8 -3
- package/src/security/store-path-override.ts +6 -16
- package/src/sequence/store.ts +8 -0
- package/src/signals/emit-event.ts +5 -10
- package/src/signals/event-stream.ts +20 -10
- package/src/subagent/manager.ts +76 -25
- package/src/subagent/notify.ts +8 -0
- package/src/subagent/types.ts +13 -3
- package/src/telegram/__tests__/webhook-health.test.ts +442 -0
- package/src/telegram/webhook-health.ts +478 -0
- package/src/telemetry/AGENTS.md +6 -0
- package/src/telemetry/memory-corpus-size.test.ts +129 -0
- package/src/telemetry/memory-corpus-size.ts +184 -0
- package/src/telemetry/memory-tier-reporter.test.ts +67 -2
- package/src/telemetry/memory-tier-reporter.ts +30 -3
- package/src/tools/__tests__/conversation-group-tool-input-schemas.test.ts +61 -0
- package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
- package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
- package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
- package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
- package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
- package/src/tools/acp/abort.ts +21 -1
- package/src/tools/acp/context.ts +5 -5
- package/src/tools/acp/spawn.test.ts +15 -5
- package/src/tools/acp/spawn.ts +26 -3
- package/src/tools/acp/status.ts +20 -1
- package/src/tools/acp/steer.test.ts +20 -0
- package/src/tools/acp/steer.ts +23 -2
- package/src/tools/apps/resolve-app-id.ts +15 -3
- package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
- package/src/tools/ask-question/ask-question-tool.ts +68 -92
- package/src/tools/browser/browser-screencast.ts +6 -6
- package/src/tools/calls/call-end.ts +24 -3
- package/src/tools/calls/call-start.ts +35 -11
- package/src/tools/calls/call-status.ts +20 -1
- package/src/tools/conversation-groups/group_create.ts +63 -0
- package/src/tools/conversation-groups/group_list.ts +20 -0
- package/src/tools/conversation-groups/group_shared.ts +52 -0
- package/src/tools/conversation-groups/move_to_group.ts +106 -0
- package/src/tools/document/document-comment-tool.test.ts +49 -0
- package/src/tools/document/document-comment-tool.ts +45 -6
- package/src/tools/document/document-tool.ts +142 -24
- package/src/tools/executor.ts +27 -13
- package/src/tools/filesystem/edit.ts +62 -60
- package/src/tools/filesystem/list.ts +36 -29
- package/src/tools/filesystem/read.ts +56 -39
- package/src/tools/filesystem/write.ts +44 -38
- package/src/tools/followups/followup_create.ts +41 -12
- package/src/tools/followups/followup_list.ts +34 -6
- package/src/tools/followups/followup_resolve.ts +26 -4
- package/src/tools/host-filesystem/edit.ts +50 -60
- package/src/tools/host-filesystem/read.ts +45 -39
- package/src/tools/host-filesystem/write.ts +31 -36
- package/src/tools/host-terminal/host-shell.ts +76 -62
- package/src/tools/policy-context.ts +27 -10
- package/src/tools/schedule/create.ts +76 -33
- package/src/tools/schedule/delete.ts +21 -2
- package/src/tools/schedule/list.ts +25 -3
- package/src/tools/schedule/update.ts +105 -48
- package/src/tools/shared/filesystem/path-policy.ts +246 -40
- package/src/tools/shared/zod-tool-schema.ts +117 -0
- package/src/tools/subagent/abort.ts +12 -4
- package/src/tools/subagent/consult-deadline.ts +9 -3
- package/src/tools/subagent/message.ts +21 -5
- package/src/tools/subagent/notify-parent.ts +44 -23
- package/src/tools/subagent/read.ts +15 -4
- package/src/tools/subagent/resolve.ts +26 -4
- package/src/tools/subagent/spawn.ts +37 -13
- package/src/tools/subagent/status.ts +12 -4
- package/src/tools/system/request-permission.ts +35 -26
- package/src/tools/terminal/shell.ts +68 -55
- package/src/tools/tool-approval-handler.ts +327 -53
- package/src/tools/tool-input-schemas.ts +85 -0
- package/src/tools/tool-types.ts +7 -0
- package/src/tools/types.ts +8 -0
- package/src/tools/workflows/manage-workflows.ts +30 -2
- package/src/tools/workflows/run-workflow.test.ts +54 -2
- package/src/tools/workflows/run-workflow.ts +32 -4
- package/src/util/fs-symlinks.ts +30 -0
- package/src/util/log-redact.ts +7 -3
- package/src/util/platform.ts +15 -0
- package/src/vellum-assistant-namespace.d.ts +80 -0
- package/src/watcher/watcher-store.ts +8 -0
- package/src/workflows/leaf-runner.test.ts +104 -2
- package/src/workflows/leaf-runner.ts +31 -6
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
- package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
- package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
- package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
- package/src/workspace/migrations/registry.ts +4 -0
- package/tsconfig.plugin-api.json +1 -1
- package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
- package/src/__tests__/secret-patterns.test.ts +0 -27
- package/src/config/__tests__/proc-to-skills.test.ts +0 -21
- package/src/config/memory-tier.test.ts +0 -44
- package/src/daemon/message-types/acp.ts +0 -20
- package/src/daemon/message-types/apps.ts +0 -11
- package/src/daemon/message-types/background-tools.ts +0 -14
- package/src/daemon/message-types/bookmarks.ts +0 -13
- package/src/daemon/message-types/contacts.ts +0 -13
- package/src/daemon/message-types/document-comments.ts +0 -14
- package/src/daemon/message-types/documents.ts +0 -13
- package/src/daemon/message-types/home.ts +0 -15
- package/src/daemon/message-types/host-bash.ts +0 -12
- package/src/daemon/message-types/host-cu.ts +0 -10
- package/src/daemon/message-types/host-file.ts +0 -12
- package/src/daemon/message-types/host-transfer.ts +0 -12
- package/src/daemon/message-types/integrations.ts +0 -90
- package/src/daemon/message-types/memory.ts +0 -10
- package/src/daemon/message-types/schedules.ts +0 -14
- package/src/daemon/message-types/settings.ts +0 -17
- package/src/daemon/message-types/subagents.ts +0 -63
- package/src/daemon/message-types/upgrades.ts +0 -14
- package/src/daemon/message-types/workflows.ts +0 -25
- package/src/daemon/message-types/workspace.ts +0 -137
- package/src/live-voice/ack-phrases.ts +0 -58
- package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
- package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
- package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
- package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
|
@@ -33,7 +33,7 @@ mock.module("../../daemon/conversation-store.js", () => ({
|
|
|
33
33
|
|
|
34
34
|
// Conversation-CRUD doubles for the teardown transcript-hygiene pass. The
|
|
35
35
|
// real module is spread so every other export keeps its production behavior;
|
|
36
|
-
// only the
|
|
36
|
+
// only the functions the hygiene pass (and discard) touch are recorded.
|
|
37
37
|
import * as realConversationCrud from "../../persistence/conversation-crud.js";
|
|
38
38
|
|
|
39
39
|
let getMessageByIdImpl: (
|
|
@@ -65,10 +65,14 @@ mock.module("../../persistence/conversation-crud.js", () => ({
|
|
|
65
65
|
crudLog.deletes.push(messageId);
|
|
66
66
|
return { segmentIds: [], deletedSummaryIds: [] };
|
|
67
67
|
},
|
|
68
|
+
// The echo path advances the snapshot anchor for a real-user turn; the
|
|
69
|
+
// fake conversation has no row in SQLite, so stub the write out.
|
|
70
|
+
recordConversationPersistedSeq: () => {},
|
|
68
71
|
}));
|
|
69
72
|
|
|
70
73
|
import { setConfig } from "../../__tests__/helpers/set-config.js";
|
|
71
74
|
import { ABORT_WATCHDOG_MS } from "../../daemon/abort-watchdog.js";
|
|
75
|
+
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
72
76
|
import { CALL_OPENING_MARKER } from "../voice-control-protocol.js";
|
|
73
77
|
import {
|
|
74
78
|
cutFrontDoorContentAtVerdict,
|
|
@@ -347,6 +351,67 @@ describe("startVoiceTurn escalation-continuation persistence", () => {
|
|
|
347
351
|
});
|
|
348
352
|
});
|
|
349
353
|
|
|
354
|
+
describe("startVoiceTurn hiddenSyntheticPrompt", () => {
|
|
355
|
+
// A caller whose internal instruction is composed per call carries no
|
|
356
|
+
// sentinel for the content comparisons to recognize, so it declares itself.
|
|
357
|
+
const SYNTHETIC_CONTENT =
|
|
358
|
+
"(the background task finished — announce the result)";
|
|
359
|
+
|
|
360
|
+
/** The `user_message_echo` events `turn` publishes to hub subscribers. */
|
|
361
|
+
async function collectUserMessageEchoes(
|
|
362
|
+
turn: () => Promise<unknown>,
|
|
363
|
+
): Promise<Array<{ type: string }>> {
|
|
364
|
+
const published: Array<{ type: string }> = [];
|
|
365
|
+
const subscription = assistantEventHub.subscribe({
|
|
366
|
+
type: "process",
|
|
367
|
+
filter: { conversationId: "conv-voice-bridge-test" },
|
|
368
|
+
callback: (event) => {
|
|
369
|
+
published.push(event.message);
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
try {
|
|
373
|
+
await turn();
|
|
374
|
+
} finally {
|
|
375
|
+
subscription.dispose();
|
|
376
|
+
}
|
|
377
|
+
return published.filter((msg) => msg.type === "user_message_echo");
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
test("a declared prompt persists hidden and suppresses its echo", async () => {
|
|
381
|
+
const fake = makeFakeConversation({ processing: false });
|
|
382
|
+
fakeConversation = fake.conversation;
|
|
383
|
+
|
|
384
|
+
const echoes = await collectUserMessageEchoes(() =>
|
|
385
|
+
startVoiceTurn({
|
|
386
|
+
...makeTurnOptions(),
|
|
387
|
+
content: SYNTHETIC_CONTENT,
|
|
388
|
+
hiddenSyntheticPrompt: true,
|
|
389
|
+
}),
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
expect(fake.lastPersistOpts()?.content).toBe(SYNTHETIC_CONTENT);
|
|
393
|
+
expect(fake.lastPersistOpts()?.metadata).toEqual({ hidden: true });
|
|
394
|
+
expect(echoes).toHaveLength(0);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test("the same content without the flag stays a plain user turn", async () => {
|
|
398
|
+
const fake = makeFakeConversation({ processing: false });
|
|
399
|
+
fakeConversation = fake.conversation;
|
|
400
|
+
|
|
401
|
+
const echoes = await collectUserMessageEchoes(() =>
|
|
402
|
+
startVoiceTurn({
|
|
403
|
+
...makeTurnOptions(),
|
|
404
|
+
content: SYNTHETIC_CONTENT,
|
|
405
|
+
}),
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
expect(fake.lastPersistOpts()?.metadata).toBeUndefined();
|
|
409
|
+
expect(echoes).toEqual([
|
|
410
|
+
expect.objectContaining({ text: SYNTHETIC_CONTENT }),
|
|
411
|
+
]);
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
|
|
350
415
|
describe("startVoiceTurn triage-and-escalate control prompt", () => {
|
|
351
416
|
// Live-voice supplies its own voiceControlPrompt, bypassing
|
|
352
417
|
// buildVoiceCallControlPrompt where the routing-leg rule is normally injected.
|
|
@@ -1101,7 +1166,7 @@ describe("startVoiceTurn tool-event forwarding", () => {
|
|
|
1101
1166
|
fakeConversation = fake.conversation;
|
|
1102
1167
|
}
|
|
1103
1168
|
|
|
1104
|
-
test("tool_use_start delivers the tool name and
|
|
1169
|
+
test("tool_use_start delivers the tool name, toolUseId, and input", async () => {
|
|
1105
1170
|
makeEventEmittingConversation([
|
|
1106
1171
|
{
|
|
1107
1172
|
type: "tool_use_start",
|
|
@@ -1121,7 +1186,10 @@ describe("startVoiceTurn tool-event forwarding", () => {
|
|
|
1121
1186
|
await flushMicrotasks();
|
|
1122
1187
|
|
|
1123
1188
|
expect(starts).toEqual([
|
|
1124
|
-
{
|
|
1189
|
+
{
|
|
1190
|
+
toolName: "web_search",
|
|
1191
|
+
detail: { toolUseId: "toolu-1", input: { query: "weather" } },
|
|
1192
|
+
},
|
|
1125
1193
|
]);
|
|
1126
1194
|
});
|
|
1127
1195
|
|
|
@@ -1325,7 +1393,7 @@ describe("cutFrontDoorContentAtVerdict", () => {
|
|
|
1325
1393
|
});
|
|
1326
1394
|
});
|
|
1327
1395
|
|
|
1328
|
-
describe("
|
|
1396
|
+
describe("transcript hygiene (teardown pass)", () => {
|
|
1329
1397
|
beforeEach(resetCrudLog);
|
|
1330
1398
|
|
|
1331
1399
|
function makeRow(text: string) {
|
|
@@ -1415,16 +1483,170 @@ describe("front-door transcript hygiene (teardown pass)", () => {
|
|
|
1415
1483
|
expect(events).not.toContain("loadFromDb");
|
|
1416
1484
|
});
|
|
1417
1485
|
|
|
1418
|
-
test("a
|
|
1419
|
-
makeReservedRowConversation();
|
|
1486
|
+
test("a front-door answer ending with the minimize marker has the marker stripped", async () => {
|
|
1487
|
+
const { events } = makeReservedRowConversation();
|
|
1488
|
+
getMessageByIdImpl = () => makeRow("Here we go, watch the overlay. [-1]");
|
|
1489
|
+
|
|
1490
|
+
await startVoiceTurn({ ...makeTurnOptions(), routingLeg: "front-door" });
|
|
1491
|
+
await flushMicrotasks();
|
|
1492
|
+
|
|
1493
|
+
expect(crudLog.updates).toEqual([
|
|
1494
|
+
{
|
|
1495
|
+
messageId: "assistant-row-1",
|
|
1496
|
+
content: JSON.stringify([
|
|
1497
|
+
{ type: "text", text: "Here we go, watch the overlay." },
|
|
1498
|
+
]),
|
|
1499
|
+
},
|
|
1500
|
+
]);
|
|
1501
|
+
expect(crudLog.deletes).toHaveLength(0);
|
|
1502
|
+
expect(events).toContain("loadFromDb");
|
|
1503
|
+
});
|
|
1504
|
+
|
|
1505
|
+
test("a marker-only front-door answer row is deleted", async () => {
|
|
1506
|
+
const { events } = makeReservedRowConversation();
|
|
1507
|
+
getMessageByIdImpl = () => makeRow("[-1]");
|
|
1508
|
+
|
|
1509
|
+
await startVoiceTurn({ ...makeTurnOptions(), routingLeg: "front-door" });
|
|
1510
|
+
await flushMicrotasks();
|
|
1511
|
+
|
|
1512
|
+
expect(crudLog.updates).toHaveLength(0);
|
|
1513
|
+
expect(crudLog.deletes).toEqual(["assistant-row-1"]);
|
|
1514
|
+
expect(events).toContain("loadFromDb");
|
|
1515
|
+
});
|
|
1516
|
+
|
|
1517
|
+
test("a non-routed leg leaves verdict-token content untouched (verdict cutting is front-door-only)", async () => {
|
|
1518
|
+
const { events } = makeReservedRowConversation();
|
|
1420
1519
|
getMessageByIdImpl = () => makeRow("[1] Anything at all");
|
|
1421
1520
|
|
|
1422
1521
|
await startVoiceTurn(makeTurnOptions());
|
|
1423
1522
|
await flushMicrotasks();
|
|
1424
1523
|
|
|
1425
|
-
expect(crudLog.reads).
|
|
1524
|
+
expect(crudLog.reads).toEqual(["assistant-row-1"]);
|
|
1525
|
+
expect(crudLog.updates).toHaveLength(0);
|
|
1526
|
+
expect(crudLog.deletes).toHaveLength(0);
|
|
1527
|
+
expect(events).not.toContain("loadFromDb");
|
|
1528
|
+
});
|
|
1529
|
+
|
|
1530
|
+
test("a main-leg row containing the minimize marker persists with the marker stripped", async () => {
|
|
1531
|
+
const { events } = makeReservedRowConversation();
|
|
1532
|
+
getMessageByIdImpl = () => makeRow("Done, take a look [-1]");
|
|
1533
|
+
|
|
1534
|
+
await startVoiceTurn(makeTurnOptions());
|
|
1535
|
+
await flushMicrotasks();
|
|
1536
|
+
|
|
1537
|
+
expect(crudLog.updates).toEqual([
|
|
1538
|
+
{
|
|
1539
|
+
messageId: "assistant-row-1",
|
|
1540
|
+
content: JSON.stringify([{ type: "text", text: "Done, take a look" }]),
|
|
1541
|
+
},
|
|
1542
|
+
]);
|
|
1543
|
+
expect(crudLog.deletes).toHaveLength(0);
|
|
1544
|
+
// The clean row must reach in-memory history and sync consumers.
|
|
1545
|
+
expect(events).toContain("loadFromDb");
|
|
1546
|
+
});
|
|
1547
|
+
|
|
1548
|
+
test("a mid-text [-1] (content, not command) leaves the row untouched", async () => {
|
|
1549
|
+
const { events } = makeReservedRowConversation();
|
|
1550
|
+
getMessageByIdImpl = () =>
|
|
1551
|
+
makeRow("The array [-1] sorts first, then the rest.");
|
|
1552
|
+
|
|
1553
|
+
await startVoiceTurn(makeTurnOptions());
|
|
1554
|
+
await flushMicrotasks();
|
|
1555
|
+
|
|
1556
|
+
expect(crudLog.updates).toHaveLength(0);
|
|
1557
|
+
expect(crudLog.deletes).toHaveLength(0);
|
|
1558
|
+
expect(events).not.toContain("loadFromDb");
|
|
1559
|
+
});
|
|
1560
|
+
|
|
1561
|
+
test("a marker-only main-leg row is deleted, not persisted as an empty bubble", async () => {
|
|
1562
|
+
const { events } = makeReservedRowConversation();
|
|
1563
|
+
getMessageByIdImpl = () => makeRow("[-1]");
|
|
1564
|
+
|
|
1565
|
+
await startVoiceTurn(makeTurnOptions());
|
|
1566
|
+
await flushMicrotasks();
|
|
1567
|
+
|
|
1426
1568
|
expect(crudLog.updates).toHaveLength(0);
|
|
1569
|
+
expect(crudLog.deletes).toEqual(["assistant-row-1"]);
|
|
1570
|
+
expect(events).toContain("loadFromDb");
|
|
1571
|
+
});
|
|
1572
|
+
|
|
1573
|
+
test("a terminal marker split across text blocks is stripped whole", async () => {
|
|
1574
|
+
const { events } = makeReservedRowConversation();
|
|
1575
|
+
getMessageByIdImpl = () => ({
|
|
1576
|
+
...makeRow(""),
|
|
1577
|
+
content: [
|
|
1578
|
+
{ type: "text", text: "Done, take a look [-" },
|
|
1579
|
+
{ type: "text", text: "1]" },
|
|
1580
|
+
],
|
|
1581
|
+
});
|
|
1582
|
+
|
|
1583
|
+
await startVoiceTurn(makeTurnOptions());
|
|
1584
|
+
await flushMicrotasks();
|
|
1585
|
+
|
|
1586
|
+
expect(crudLog.updates).toEqual([
|
|
1587
|
+
{
|
|
1588
|
+
messageId: "assistant-row-1",
|
|
1589
|
+
content: JSON.stringify([{ type: "text", text: "Done, take a look" }]),
|
|
1590
|
+
},
|
|
1591
|
+
]);
|
|
1427
1592
|
expect(crudLog.deletes).toHaveLength(0);
|
|
1593
|
+
expect(events).toContain("loadFromDb");
|
|
1594
|
+
});
|
|
1595
|
+
|
|
1596
|
+
test("a marker-only row split across text blocks is deleted", async () => {
|
|
1597
|
+
const { events } = makeReservedRowConversation();
|
|
1598
|
+
getMessageByIdImpl = () => ({
|
|
1599
|
+
...makeRow(""),
|
|
1600
|
+
content: [
|
|
1601
|
+
{ type: "text", text: "[-" },
|
|
1602
|
+
{ type: "text", text: "1]" },
|
|
1603
|
+
],
|
|
1604
|
+
});
|
|
1605
|
+
|
|
1606
|
+
await startVoiceTurn(makeTurnOptions());
|
|
1607
|
+
await flushMicrotasks();
|
|
1608
|
+
|
|
1609
|
+
expect(crudLog.updates).toHaveLength(0);
|
|
1610
|
+
expect(crudLog.deletes).toEqual(["assistant-row-1"]);
|
|
1611
|
+
expect(events).toContain("loadFromDb");
|
|
1612
|
+
});
|
|
1613
|
+
|
|
1614
|
+
test("a marker-only row with a surviving non-text block is rewritten, never deleted", async () => {
|
|
1615
|
+
const { events } = makeReservedRowConversation();
|
|
1616
|
+
getMessageByIdImpl = () => ({
|
|
1617
|
+
...makeRow("[-1]"),
|
|
1618
|
+
content: [
|
|
1619
|
+
{ type: "text", text: "[-1]" },
|
|
1620
|
+
{ type: "tool_use", id: "tool-1", name: "app_create", input: {} },
|
|
1621
|
+
],
|
|
1622
|
+
});
|
|
1623
|
+
|
|
1624
|
+
await startVoiceTurn(makeTurnOptions());
|
|
1625
|
+
await flushMicrotasks();
|
|
1626
|
+
|
|
1627
|
+
expect(crudLog.deletes).toHaveLength(0);
|
|
1628
|
+
expect(crudLog.updates).toEqual([
|
|
1629
|
+
{
|
|
1630
|
+
messageId: "assistant-row-1",
|
|
1631
|
+
content: JSON.stringify([
|
|
1632
|
+
{ type: "tool_use", id: "tool-1", name: "app_create", input: {} },
|
|
1633
|
+
]),
|
|
1634
|
+
},
|
|
1635
|
+
]);
|
|
1636
|
+
expect(events).toContain("loadFromDb");
|
|
1637
|
+
});
|
|
1638
|
+
|
|
1639
|
+
test("a main-leg row without the minimize marker is never rewritten", async () => {
|
|
1640
|
+
const { events } = makeReservedRowConversation();
|
|
1641
|
+
getMessageByIdImpl = () => makeRow("Done, take a look.");
|
|
1642
|
+
|
|
1643
|
+
await startVoiceTurn(makeTurnOptions());
|
|
1644
|
+
await flushMicrotasks();
|
|
1645
|
+
|
|
1646
|
+
expect(crudLog.reads).toEqual(["assistant-row-1"]);
|
|
1647
|
+
expect(crudLog.updates).toHaveLength(0);
|
|
1648
|
+
expect(crudLog.deletes).toHaveLength(0);
|
|
1649
|
+
expect(events).not.toContain("loadFromDb");
|
|
1428
1650
|
});
|
|
1429
1651
|
|
|
1430
1652
|
test("a discarded speculative leg deletes its reserved assistant row at teardown", async () => {
|
|
@@ -316,10 +316,9 @@ describe("escalation continuation content", () => {
|
|
|
316
316
|
|
|
317
317
|
// This module is the surface-agnostic escalation *policy* (profiles, prompt
|
|
318
318
|
// rules, the verdict classifier, the bridge cap/fallback decision). The
|
|
319
|
-
// two-leg *routing* runs on the in-app Voice Mode surface (LiveVoiceSession)
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
// coverage (flag gating, verdict-first hand-off, token suppression, fallback
|
|
319
|
+
// two-leg *routing* runs on the in-app Voice Mode surface (LiveVoiceSession)
|
|
320
|
+
// — see live-voice/__tests__/live-voice-triage-escalate.test.ts for the
|
|
321
|
+
// orchestration coverage (verdict-first hand-off, token suppression, fallback
|
|
323
322
|
// bridge, barge-in). What remains for the manual cli-testing flow is true
|
|
324
323
|
// end-to-end audio: real TTS timing across the bridge, and the residual
|
|
325
324
|
// broadcast raw-token leak (issue #37850, shared by both voice surfaces) once
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* barge-in, state machine, guardian verification).
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
11
12
|
import { revokeScopedApprovalGrantsForContext } from "../approvals/scoped-approval-grants.js";
|
|
12
13
|
import {
|
|
13
14
|
expireGuardianRequest,
|
|
@@ -16,7 +17,6 @@ import {
|
|
|
16
17
|
getRequestByPendingQuestionOrNull,
|
|
17
18
|
listGuardianRequestDeliveriesOrEmpty,
|
|
18
19
|
} from "../channels/gateway-guardian-requests.js";
|
|
19
|
-
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
20
20
|
import type { TrustContext } from "../daemon/trust-context-types.js";
|
|
21
21
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
22
22
|
import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
|
|
@@ -166,7 +166,7 @@ export class CallController {
|
|
|
166
166
|
/** Monotonic run id used to suppress stale turn side effects after interruption. */
|
|
167
167
|
private llmRunVersion = 0;
|
|
168
168
|
/** Optional broadcast function for emitting events to connected clients. */
|
|
169
|
-
private broadcast?: (msg:
|
|
169
|
+
private broadcast?: (msg: AssistantEvent) => void;
|
|
170
170
|
/** Assistant identity for scoping guardian bindings. */
|
|
171
171
|
private assistantId: string;
|
|
172
172
|
/** Guardian trust context for the current caller, when available. */
|
|
@@ -195,7 +195,7 @@ export class CallController {
|
|
|
195
195
|
transport: CallTransport,
|
|
196
196
|
task: string | null,
|
|
197
197
|
opts?: {
|
|
198
|
-
broadcast?: (msg:
|
|
198
|
+
broadcast?: (msg: AssistantEvent) => void;
|
|
199
199
|
assistantId?: string;
|
|
200
200
|
trustContext?: TrustContext;
|
|
201
201
|
},
|
|
@@ -260,8 +260,8 @@ export class CallController {
|
|
|
260
260
|
* Kick off the first outbound call utterance from the assistant.
|
|
261
261
|
*/
|
|
262
262
|
async startInitialGreeting(): Promise<void> {
|
|
263
|
-
if (this.initialGreetingStarted) return;
|
|
264
|
-
if (this.state !== "idle") return;
|
|
263
|
+
if (this.initialGreetingStarted) {return;}
|
|
264
|
+
if (this.state !== "idle") {return;}
|
|
265
265
|
|
|
266
266
|
this.initialGreetingStarted = true;
|
|
267
267
|
this.resetSilenceTimer();
|
|
@@ -275,8 +275,8 @@ export class CallController {
|
|
|
275
275
|
* greet naturally with context that verification just happened.
|
|
276
276
|
*/
|
|
277
277
|
async startPostVerificationGreeting(): Promise<void> {
|
|
278
|
-
if (this.initialGreetingStarted) return;
|
|
279
|
-
if (this.state !== "idle") return;
|
|
278
|
+
if (this.initialGreetingStarted) {return;}
|
|
279
|
+
if (this.state !== "idle") {return;}
|
|
280
280
|
|
|
281
281
|
this.initialGreetingStarted = true;
|
|
282
282
|
this.resetSilenceTimer();
|
|
@@ -473,10 +473,10 @@ export class CallController {
|
|
|
473
473
|
*/
|
|
474
474
|
destroy(): void {
|
|
475
475
|
this.destroyed = true;
|
|
476
|
-
if (this.silenceTimer) clearTimeout(this.silenceTimer);
|
|
476
|
+
if (this.silenceTimer) {clearTimeout(this.silenceTimer);}
|
|
477
477
|
this.cancelPendingEndCall();
|
|
478
|
-
if (this.durationTimer) clearTimeout(this.durationTimer);
|
|
479
|
-
if (this.durationWarningTimer) clearTimeout(this.durationWarningTimer);
|
|
478
|
+
if (this.durationTimer) {clearTimeout(this.durationTimer);}
|
|
479
|
+
if (this.durationWarningTimer) {clearTimeout(this.durationWarningTimer);}
|
|
480
480
|
if (this.pendingGuardianInput) {
|
|
481
481
|
clearTimeout(this.pendingGuardianInput.timer);
|
|
482
482
|
this.pendingGuardianInput = null;
|
|
@@ -559,7 +559,7 @@ export class CallController {
|
|
|
559
559
|
transcript: string,
|
|
560
560
|
speaker?: PromptSpeakerContext,
|
|
561
561
|
): string {
|
|
562
|
-
if (!speaker) return transcript;
|
|
562
|
+
if (!speaker) {return transcript;}
|
|
563
563
|
const safeId = speaker.speakerId.replaceAll('"', "'");
|
|
564
564
|
const safeLabel = speaker.speakerLabel.replaceAll('"', "'");
|
|
565
565
|
const confidencePart =
|
|
@@ -580,7 +580,7 @@ export class CallController {
|
|
|
580
580
|
}
|
|
581
581
|
|
|
582
582
|
private async runTurnInner(content: string): Promise<void> {
|
|
583
|
-
if (this.destroyed) return;
|
|
583
|
+
if (this.destroyed) {return;}
|
|
584
584
|
const runVersion = ++this.llmRunVersion;
|
|
585
585
|
const runSignal = this.abortController.signal;
|
|
586
586
|
|
|
@@ -603,7 +603,7 @@ export class CallController {
|
|
|
603
603
|
runVersion,
|
|
604
604
|
runSignal,
|
|
605
605
|
);
|
|
606
|
-
if (!this.isCurrentRun(runVersion)) return;
|
|
606
|
+
if (!this.isCurrentRun(runVersion)) {return;}
|
|
607
607
|
|
|
608
608
|
await this.handleTurnCompletion(fullResponseText);
|
|
609
609
|
} catch (err: unknown) {
|
|
@@ -838,15 +838,15 @@ export class CallController {
|
|
|
838
838
|
enqueueSynthesisSegments(synthProvider, segments);
|
|
839
839
|
} else {
|
|
840
840
|
const cleaned = sanitizeForTts(safeText);
|
|
841
|
-
if (cleaned.length === 0) return;
|
|
841
|
+
if (cleaned.length === 0) {return;}
|
|
842
842
|
this.beginSpeakingOnAudioStart(runVersion);
|
|
843
843
|
this.transport.sendTextToken(cleaned, false);
|
|
844
844
|
}
|
|
845
845
|
};
|
|
846
846
|
|
|
847
847
|
const flushSafeText = (): void => {
|
|
848
|
-
if (!this.isCurrentRun(runVersion)) return;
|
|
849
|
-
if (ttsBuffer.length === 0) return;
|
|
848
|
+
if (!this.isCurrentRun(runVersion)) {return;}
|
|
849
|
+
if (ttsBuffer.length === 0) {return;}
|
|
850
850
|
const bracketIdx = ttsBuffer.indexOf("[");
|
|
851
851
|
if (bracketIdx === -1) {
|
|
852
852
|
// No bracket at all — safe to flush everything
|
|
@@ -883,7 +883,7 @@ export class CallController {
|
|
|
883
883
|
// Use a promise to track completion of the voice turn
|
|
884
884
|
const turnComplete = new Promise<void>((resolve, reject) => {
|
|
885
885
|
const onTextDelta = (text: string): void => {
|
|
886
|
-
if (!this.isCurrentRun(runVersion)) return;
|
|
886
|
+
if (!this.isCurrentRun(runVersion)) {return;}
|
|
887
887
|
fullResponseText += text;
|
|
888
888
|
ttsBuffer += text;
|
|
889
889
|
ttsBuffer = stripInternalSpeechMarkers(ttsBuffer);
|
|
@@ -989,7 +989,7 @@ export class CallController {
|
|
|
989
989
|
// latency; re-check the run wasn't superseded meanwhile so a stale turn
|
|
990
990
|
// doesn't inject its end-of-turn marker (or fallback text) into the next
|
|
991
991
|
// turn's output stream.
|
|
992
|
-
if (!this.isCurrentRun(runVersion)) return fullResponseText;
|
|
992
|
+
if (!this.isCurrentRun(runVersion)) {return fullResponseText;}
|
|
993
993
|
|
|
994
994
|
// Signal end of this turn's speech. An empty token with `last: true`
|
|
995
995
|
// tells the transport to start listening — it does NOT trigger TTS
|
|
@@ -1447,7 +1447,7 @@ export class CallController {
|
|
|
1447
1447
|
}
|
|
1448
1448
|
|
|
1449
1449
|
private clearPendingGuardianInputForCallEnd(): boolean {
|
|
1450
|
-
if (!this.pendingGuardianInput) return false;
|
|
1450
|
+
if (!this.pendingGuardianInput) {return false;}
|
|
1451
1451
|
|
|
1452
1452
|
clearTimeout(this.pendingGuardianInput.timer);
|
|
1453
1453
|
|
|
@@ -1476,7 +1476,7 @@ export class CallController {
|
|
|
1476
1476
|
// The teardown has run to completion; drop the token so a later utterance
|
|
1477
1477
|
// can't read it as a still-pending end-call.
|
|
1478
1478
|
this.pendingEndCall = null;
|
|
1479
|
-
if (this.destroyed) return;
|
|
1479
|
+
if (this.destroyed) {return;}
|
|
1480
1480
|
|
|
1481
1481
|
const currentSession = getCallSession(this.callSessionId);
|
|
1482
1482
|
if (currentSession && isTerminalState(currentSession.status)) {
|
|
@@ -1518,7 +1518,7 @@ export class CallController {
|
|
|
1518
1518
|
}
|
|
1519
1519
|
|
|
1520
1520
|
private isExpectedAbortError(err: unknown): boolean {
|
|
1521
|
-
if (!(err instanceof Error)) return false;
|
|
1521
|
+
if (!(err instanceof Error)) {return false;}
|
|
1522
1522
|
return err.name === "AbortError" || err.name === "APIUserAbortError";
|
|
1523
1523
|
}
|
|
1524
1524
|
|
|
@@ -1541,7 +1541,7 @@ export class CallController {
|
|
|
1541
1541
|
* waiting for the processing lock or generating with no audio yet.
|
|
1542
1542
|
*/
|
|
1543
1543
|
private beginSpeaking(runVersion: number): void {
|
|
1544
|
-
if (!this.isCurrentRun(runVersion)) return;
|
|
1544
|
+
if (!this.isCurrentRun(runVersion)) {return;}
|
|
1545
1545
|
if (this.state === "processing") {
|
|
1546
1546
|
this.state = "speaking";
|
|
1547
1547
|
}
|
|
@@ -1650,7 +1650,7 @@ export class CallController {
|
|
|
1650
1650
|
!this.pendingGuardianInput ||
|
|
1651
1651
|
this.pendingGuardianInput.questionId !== pendingQuestion.id
|
|
1652
1652
|
)
|
|
1653
|
-
return;
|
|
1653
|
+
{return;}
|
|
1654
1654
|
|
|
1655
1655
|
log.info(
|
|
1656
1656
|
{ callSessionId: this.callSessionId },
|
|
@@ -1727,8 +1727,8 @@ export class CallController {
|
|
|
1727
1727
|
* Drain any instructions that were queued while the LLM was active.
|
|
1728
1728
|
*/
|
|
1729
1729
|
private flushPendingInstructions(): void {
|
|
1730
|
-
if (this.destroyed) return;
|
|
1731
|
-
if (this.pendingInstructions.length === 0) return;
|
|
1730
|
+
if (this.destroyed) {return;}
|
|
1731
|
+
if (this.pendingInstructions.length === 0) {return;}
|
|
1732
1732
|
|
|
1733
1733
|
const parts = this.pendingInstructions.map((instr) =>
|
|
1734
1734
|
instr.startsWith("[") ? instr : `[USER_INSTRUCTION: ${instr}]`,
|
|
@@ -1814,8 +1814,8 @@ export class CallController {
|
|
|
1814
1814
|
}
|
|
1815
1815
|
|
|
1816
1816
|
private resetSilenceTimer(): void {
|
|
1817
|
-
if (this.silenceTimer) clearTimeout(this.silenceTimer);
|
|
1818
|
-
if (this.destroyed) return;
|
|
1817
|
+
if (this.silenceTimer) {clearTimeout(this.silenceTimer);}
|
|
1818
|
+
if (this.destroyed) {return;}
|
|
1819
1819
|
this.silenceTimer = setTimeout(() => {
|
|
1820
1820
|
// During an in-call guardian consultation, suppress the generic
|
|
1821
1821
|
// "Are you still there?" — it is confusing when the caller is
|
|
@@ -31,6 +31,56 @@ export function buildCallCompletionMessage(callSessionId: string): string {
|
|
|
31
31
|
return buildCallSummaryLabel(callSession?.status, duration, events.length);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/** The `data` payload rendered by the `call_summary` surface. */
|
|
35
|
+
interface CallSummaryEvent {
|
|
36
|
+
eventType: string;
|
|
37
|
+
payloadJson: string;
|
|
38
|
+
createdAt: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Build the `[ui_surface, text]` block pair persisted for a finished call.
|
|
43
|
+
*
|
|
44
|
+
* This is the approval-card pattern (see
|
|
45
|
+
* `notifications/approval-card-builder.ts`). Every provider drops `ui_surface`
|
|
46
|
+
* when serializing history, so the card alone left the model unable to tell
|
|
47
|
+
* that a call happened — the turn reached the wire as a "blocks omitted"
|
|
48
|
+
* sentinel (LUM-2869). The `_surfaceFallback` text sibling carries the same
|
|
49
|
+
* copy for the model, search indexing, CLI display, and channel replies, and
|
|
50
|
+
* its flag keeps surface-capable clients from rendering both the card and a
|
|
51
|
+
* duplicate text line.
|
|
52
|
+
*/
|
|
53
|
+
function buildCallSummaryBlocks(
|
|
54
|
+
summaryText: string,
|
|
55
|
+
status: string | undefined,
|
|
56
|
+
duration: number | null,
|
|
57
|
+
events: CallSummaryEvent[],
|
|
58
|
+
): unknown[] {
|
|
59
|
+
return [
|
|
60
|
+
{
|
|
61
|
+
type: "ui_surface",
|
|
62
|
+
surfaceType: "call_summary",
|
|
63
|
+
surfaceId: crypto.randomUUID(),
|
|
64
|
+
completed: true,
|
|
65
|
+
data: {
|
|
66
|
+
summaryText,
|
|
67
|
+
status: status ?? "completed",
|
|
68
|
+
duration,
|
|
69
|
+
events: events.map((e) => ({
|
|
70
|
+
eventType: e.eventType,
|
|
71
|
+
payloadJson: e.payloadJson,
|
|
72
|
+
createdAt: e.createdAt,
|
|
73
|
+
})),
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: "text",
|
|
78
|
+
text: summaryText,
|
|
79
|
+
_surfaceFallback: true,
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
|
|
34
84
|
export async function persistCallCompletionMessage(
|
|
35
85
|
conversationId: string,
|
|
36
86
|
callSessionId: string,
|
|
@@ -50,24 +100,14 @@ export async function persistCallCompletionMessage(
|
|
|
50
100
|
await addMessage(
|
|
51
101
|
conversationId,
|
|
52
102
|
"assistant",
|
|
53
|
-
JSON.stringify(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
status: callSession?.status ?? "completed",
|
|
62
|
-
duration,
|
|
63
|
-
events: events.map((e) => ({
|
|
64
|
-
eventType: e.eventType,
|
|
65
|
-
payloadJson: e.payloadJson,
|
|
66
|
-
createdAt: e.createdAt,
|
|
67
|
-
})),
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
]),
|
|
103
|
+
JSON.stringify(
|
|
104
|
+
buildCallSummaryBlocks(
|
|
105
|
+
summaryText,
|
|
106
|
+
callSession?.status,
|
|
107
|
+
duration,
|
|
108
|
+
events,
|
|
109
|
+
),
|
|
110
|
+
),
|
|
71
111
|
{
|
|
72
112
|
metadata: {
|
|
73
113
|
userMessageChannel: "phone",
|
|
@@ -28,6 +28,15 @@ export const END_CALL_MARKER = "[END_CALL]";
|
|
|
28
28
|
export const HOLD_VERDICT_TOKEN = "[0]";
|
|
29
29
|
export const ESCALATE_VERDICT_TOKEN = "[1]";
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Emitted inline by the main/escalated voice leg to ask the live-voice
|
|
33
|
+
* client to minimize the voice room and reveal the screen behind it
|
|
34
|
+
* (e.g. after creating an app worth showing). Advisory: the daemon
|
|
35
|
+
* translates it into a `minimize_room` server frame after the turn's TTS
|
|
36
|
+
* drains; it is never spoken and never persisted.
|
|
37
|
+
*/
|
|
38
|
+
export const MINIMIZE_ROOM_MARKER = "[-1]";
|
|
39
|
+
|
|
31
40
|
// ---------------------------------------------------------------------------
|
|
32
41
|
// Regexes
|
|
33
42
|
// ---------------------------------------------------------------------------
|
|
@@ -47,6 +56,7 @@ const CALL_OPENING_ACK_MARKER_REGEX = /\[CALL_OPENING_ACK\]/g;
|
|
|
47
56
|
const END_CALL_MARKER_REGEX = /\[END_CALL\]/g;
|
|
48
57
|
const HOLD_VERDICT_TOKEN_REGEX = /\[0\]/g;
|
|
49
58
|
const ESCALATE_VERDICT_TOKEN_REGEX = /\[1\]/g;
|
|
59
|
+
const MINIMIZE_ROOM_MARKER_REGEX = /\[-1\]/g;
|
|
50
60
|
const GUARDIAN_TIMEOUT_MARKER_REGEX = /\[GUARDIAN_TIMEOUT\]/g;
|
|
51
61
|
const GUARDIAN_UNAVAILABLE_MARKER_REGEX = /\[GUARDIAN_UNAVAILABLE\]/g;
|
|
52
62
|
|
|
@@ -163,6 +173,7 @@ export function stripInternalSpeechMarkers(text: string): string {
|
|
|
163
173
|
.replace(END_CALL_MARKER_REGEX, "")
|
|
164
174
|
.replace(HOLD_VERDICT_TOKEN_REGEX, "")
|
|
165
175
|
.replace(ESCALATE_VERDICT_TOKEN_REGEX, "")
|
|
176
|
+
.replace(MINIMIZE_ROOM_MARKER_REGEX, "")
|
|
166
177
|
.replace(GUARDIAN_TIMEOUT_MARKER_REGEX, "")
|
|
167
178
|
.replace(GUARDIAN_UNAVAILABLE_MARKER_REGEX, "");
|
|
168
179
|
return result;
|
|
@@ -187,6 +198,7 @@ const CONTROL_MARKER_STRINGS = [
|
|
|
187
198
|
"[END_CALL]",
|
|
188
199
|
"[0]",
|
|
189
200
|
"[1]",
|
|
201
|
+
"[-1]",
|
|
190
202
|
"[GUARDIAN_TIMEOUT]",
|
|
191
203
|
"[GUARDIAN_UNAVAILABLE]",
|
|
192
204
|
];
|
|
@@ -203,3 +215,47 @@ export function couldBeControlMarker(text: string): boolean {
|
|
|
203
215
|
(marker) => marker.startsWith(text) || text.startsWith(marker),
|
|
204
216
|
);
|
|
205
217
|
}
|
|
218
|
+
|
|
219
|
+
// Colon-style markers whose bodies terminate at the first "]" — their strip
|
|
220
|
+
// regexes are non-greedy (`.+?\]`), so the first bracket IS the terminator.
|
|
221
|
+
// ASK_GUARDIAN_APPROVAL is deliberately absent: its balanced-JSON body may
|
|
222
|
+
// itself contain "]" (arrays, string values), so only the balanced parser can
|
|
223
|
+
// judge it complete.
|
|
224
|
+
const FIRST_BRACKET_TERMINATED_PREFIXES = [
|
|
225
|
+
"[ASK_GUARDIAN:",
|
|
226
|
+
"[USER_ANSWERED:",
|
|
227
|
+
"[USER_INSTRUCTION:",
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
const GUARDIAN_APPROVAL_PREFIX = "[ASK_GUARDIAN_APPROVAL:";
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Whether `tail` (a buffer starting at a `[`) is a control marker that is
|
|
234
|
+
* still streaming — i.e. holding it back is required because
|
|
235
|
+
* {@link stripInternalSpeechMarkers} cannot yet remove it. Returns false for
|
|
236
|
+
* complete markers (safe to flush: stripping removes them) and for text that
|
|
237
|
+
* is not a marker at all (safe to flush: it is speech).
|
|
238
|
+
*
|
|
239
|
+
* Completion is judged per marker family: a strict prefix of any known
|
|
240
|
+
* marker string is always incomplete; an ASK_GUARDIAN_APPROVAL body is
|
|
241
|
+
* complete only when {@link extractBalancedJson} finds the balanced JSON and
|
|
242
|
+
* its closing bracket (a bare "]" inside the JSON does NOT terminate it);
|
|
243
|
+
* the other colon-style markers terminate at their first "]"; the fixed
|
|
244
|
+
* literal markers are complete the moment they match.
|
|
245
|
+
*/
|
|
246
|
+
export function isIncompleteControlMarkerTail(tail: string): boolean {
|
|
247
|
+
if (
|
|
248
|
+
CONTROL_MARKER_STRINGS.some(
|
|
249
|
+
(marker) => marker.length > tail.length && marker.startsWith(tail),
|
|
250
|
+
)
|
|
251
|
+
) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
if (tail.startsWith(GUARDIAN_APPROVAL_PREFIX)) {
|
|
255
|
+
return extractBalancedJson(tail) === null;
|
|
256
|
+
}
|
|
257
|
+
if (FIRST_BRACKET_TERMINATED_PREFIXES.some((p) => tail.startsWith(p))) {
|
|
258
|
+
return !tail.includes("]");
|
|
259
|
+
}
|
|
260
|
+
return false;
|
|
261
|
+
}
|