@vellumai/assistant 0.12.3-staging.1 → 0.12.3-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +43 -29
- package/Dockerfile +63 -0
- package/docs/architecture/security.md +10 -5
- package/docs/architecture/turn-actor.md +2 -0
- package/docs/desktop-browser-cli.md +45 -4
- package/docs/live-voice-task-outcomes.md +100 -0
- package/docs/mode-sessions.md +183 -0
- package/docs/voice-input-diagnostics.md +58 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- 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/integration-categories.ts +36 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- 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/integration-categories.ts +36 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -1
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +38 -7
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +5 -6
- package/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
- package/openapi.yaml +665 -14
- package/package.json +1 -1
- package/scripts/smoke-desktop-browser-cli.ts +10 -26
- package/scripts/smoke-desktop-window-theme.ts +2 -3
- package/src/__tests__/agent-loop-output-hooks.test.ts +150 -1
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +87 -19
- package/src/__tests__/annotate-activity-metadata.test.ts +3 -1
- package/src/__tests__/annotate-risk-options.test.ts +2 -0
- package/src/__tests__/answered-question-persistence.test.ts +2 -0
- package/src/__tests__/anthropic-gateway-shared.test.ts +22 -0
- package/src/__tests__/approval-message-composer.test.ts +1 -118
- package/src/__tests__/approval-routes-http.test.ts +3 -0
- package/src/__tests__/assistant-event-hub-connection-history.test.ts +111 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +50 -0
- package/src/__tests__/assistant-event-targeting.test.ts +186 -0
- package/src/__tests__/assistant-stream-state.test.ts +29 -9
- package/src/__tests__/browser-fill-credential.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +4 -1
- package/src/__tests__/build-persisted-content.test.ts +1 -1
- package/src/__tests__/call-conversation-messages.test.ts +5 -0
- package/src/__tests__/call-recovery.test.ts +7 -2
- package/src/__tests__/call-routes-http.test.ts +12 -0
- package/src/__tests__/call-store.test.ts +7 -2
- package/src/__tests__/channel-retry-sweep.test.ts +9 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +2 -0
- package/src/__tests__/checker.test.ts +11 -3
- package/src/__tests__/client-os-metadata-persistence.test.ts +35 -1
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -25
- package/src/__tests__/computer-use-tools.test.ts +1 -233
- package/src/__tests__/config-model-image-provider.test.ts +39 -0
- package/src/__tests__/config-schema.test.ts +16 -0
- package/src/__tests__/config-watcher.test.ts +24 -0
- package/src/__tests__/context-search-agent-runner.test.ts +260 -1
- package/src/__tests__/context-search-fanout.test.ts +1 -1
- package/src/__tests__/context-search-types.test.ts +7 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +8 -2
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +546 -16
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
- package/src/__tests__/conversation-evictor.test.ts +62 -37
- package/src/__tests__/conversation-history-boundary-repair-failure.test.ts +174 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +2 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
- package/src/__tests__/conversation-retry-route.test.ts +22 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +2 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +2 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +10 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +2 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -0
- package/src/__tests__/conversation-surface-snapshots.test.ts +543 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +151 -0
- package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +63 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +23 -0
- package/src/__tests__/conversation-undo.test.ts +61 -0
- package/src/__tests__/credential-execution-client.test.ts +6 -6
- package/src/__tests__/credential-prompt-route.test.ts +35 -3
- package/src/__tests__/cu-unified-flow.test.ts +82 -1
- package/src/__tests__/db-mode-sessions-migration.test.ts +175 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -0
- package/src/__tests__/dm-backfill.test.ts +91 -1
- package/src/__tests__/document-create-route.test.ts +88 -0
- package/src/__tests__/document-sync-tags.test.ts +27 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +142 -2
- package/src/__tests__/events-tail-route.test.ts +25 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +57 -8
- package/src/__tests__/guardian-action-sweep.test.ts +16 -0
- package/src/__tests__/guardian-dispatch.test.ts +13 -0
- package/src/__tests__/headless-browser-interactions.test.ts +64 -20
- package/src/__tests__/heartbeat-service.test.ts +2 -59
- package/src/__tests__/helpers/mock-conversation.ts +21 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +2 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +5 -0
- package/src/__tests__/host-cu-proxy.test.ts +46 -2
- package/src/__tests__/http-user-message-parity.test.ts +2 -0
- package/src/__tests__/image-credentials.test.ts +49 -0
- package/src/__tests__/image-service-dispatcher.test.ts +45 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
- package/src/__tests__/interrupt-on-send.test.ts +57 -43
- package/src/__tests__/interrupt-turn-note.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +49 -1
- package/src/__tests__/message-provenance-contact-id.test.ts +69 -0
- package/src/__tests__/migration-export-to-gcs.test.ts +142 -0
- package/src/__tests__/mode-session-history.test.ts +245 -0
- package/src/__tests__/mode-session-recovery.test.ts +222 -0
- package/src/__tests__/mode-session-wire.test.ts +141 -0
- package/src/__tests__/notification-guardian-path.test.ts +7 -0
- package/src/__tests__/notification-telegram-adapter.test.ts +2 -2
- package/src/__tests__/notification-vellum-adapter.test.ts +34 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +12 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
- package/src/__tests__/plugin-api-provider.test.ts +5 -0
- package/src/__tests__/plugin-api-resolve-credential.test.ts +97 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +9 -0
- package/src/__tests__/process-message-display-content.test.ts +56 -0
- package/src/__tests__/reaction-persistence.test.ts +5 -0
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +25 -9
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/scripted-turn-metadata-persistence.test.ts +73 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -0
- package/src/__tests__/secure-keys.test.ts +43 -1
- package/src/__tests__/send-endpoint-busy.test.ts +163 -1
- package/src/__tests__/server-history-render.test.ts +91 -1
- package/src/__tests__/settings-routes.test.ts +50 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -2
- package/src/__tests__/subagent-manager-notify.test.ts +1 -2
- package/src/__tests__/subagent-notify-parent.test.ts +146 -39
- package/src/__tests__/subagent-notify-stale-rebuild.test.ts +2 -4
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
- package/src/__tests__/thread-backfill.test.ts +53 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +3 -1
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/twilio-routes.test.ts +1 -0
- package/src/__tests__/web-search-backend-failure.test.ts +1 -1
- package/src/activation/progress-store.test.ts +12 -7
- package/src/agent/loop.ts +99 -41
- package/src/api/events/assistant-turn-start.ts +3 -0
- package/src/api/events/generation-handoff.ts +2 -0
- package/src/api/events/message-complete.ts +2 -0
- package/src/api/events/notification-conversation-created.ts +14 -16
- package/src/api/events/notification-intent.ts +4 -2
- package/src/api/events/tool-result.ts +85 -0
- package/src/api/events/tool-use-start.ts +3 -0
- package/src/api/events/user-message-echo.ts +3 -0
- package/src/api/index.ts +31 -6
- package/src/api/mode-session.test.ts +131 -0
- package/src/api/mode-session.ts +148 -0
- package/src/api/remember-tool.ts +15 -0
- package/src/api/responses/conversation-message.ts +6 -0
- package/src/approvals/AGENTS.md +4 -2
- package/src/browser/__tests__/operations.test.ts +29 -0
- package/src/browser/operation-meta.ts +2 -1
- package/src/browser/operations.ts +29 -0
- package/src/browser/virtual-desktop-target.ts +2 -8
- package/src/bundler/bundle-signer.ts +1 -3
- package/src/calls/__tests__/barge-in-guard.test.ts +3 -0
- package/src/calls/__tests__/call-controller.test.ts +94 -0
- package/src/calls/__tests__/call-funnel-telemetry.test.ts +204 -0
- package/src/calls/__tests__/voice-control-protocol.test.ts +15 -0
- package/src/calls/__tests__/voice-escalation-judge.test.ts +209 -0
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +168 -0
- package/src/{live-voice/__tests__/live-voice-metrics.test.ts → calls/__tests__/voice-metrics.test.ts} +32 -38
- package/src/calls/__tests__/voice-session-bridge.test.ts +576 -122
- package/src/calls/barge-in-guard.ts +5 -0
- package/src/calls/call-controller.ts +196 -1
- package/src/calls/call-domain.ts +4 -0
- package/src/calls/call-store.ts +87 -2
- package/src/calls/guardian-action-sweep.ts +22 -8
- package/src/calls/media-stream-audio-transcode.ts +1 -3
- package/src/calls/typesafe-noul.ts +156 -0
- package/src/calls/voice-control-protocol.ts +6 -0
- package/src/calls/voice-escalation-judge.ts +145 -0
- package/src/calls/voice-escalation-target.ts +10 -0
- package/src/calls/voice-leg-coordinator.ts +121 -3
- package/src/{live-voice/live-voice-metrics.ts → calls/voice-metrics.ts} +94 -87
- package/src/calls/voice-session-bridge.ts +256 -112
- package/src/calls/voice-triage-escalate.ts +7 -0
- package/src/cli/__tests__/roadmap-cli.test.ts +4 -41
- package/src/cli/commands/__tests__/notifications.test.ts +35 -10
- package/src/cli/commands/browser.help.ts +4 -5
- package/src/cli/commands/browser.ts +0 -1
- package/src/cli/commands/clients.help.ts +46 -0
- package/src/cli/commands/clients.ts +116 -0
- package/src/cli/commands/credentials.help.ts +6 -1
- package/src/cli/commands/notifications.help.ts +16 -2
- package/src/cli/commands/notifications.ts +30 -8
- package/src/cli/commands/roadmap.help.ts +18 -21
- package/src/cli/commands/roadmap.ts +4 -21
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
- package/src/cli/lib/bundled-marketplace.json +84 -34
- package/src/cli/lib/plugin-marketplace.ts +8 -0
- package/src/cli/lib/publish-plugin.ts +1 -2
- package/src/config/__tests__/default-provider.test.ts +3 -1
- package/src/config/__tests__/memory-retrospective-schema.test.ts +14 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +1 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +89 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +17 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -11
- package/src/config/bundled-skills/sequences/TOOLS.json +1 -5
- package/src/config/call-site-defaults.ts +9 -0
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/profile-text-generation.test.ts +2 -2
- package/src/config/schemas/__tests__/tools.test.ts +31 -0
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/channels.ts +0 -18
- package/src/config/schemas/llm.ts +3 -1
- package/src/config/schemas/mcp.ts +2 -1
- package/src/config/schemas/memory-retrospective.ts +11 -2
- package/src/config/schemas/services.ts +15 -6
- package/src/config/schemas/tools.ts +10 -0
- package/src/config/session-groups-gate.ts +21 -0
- package/src/config/skills.ts +2 -6
- package/src/conversations/__tests__/message-consolidation.test.ts +149 -0
- package/src/conversations/message-consolidation.ts +102 -5
- package/src/credential-execution/ces-connect.test.ts +69 -0
- package/src/credential-execution/ces-connect.ts +115 -0
- package/src/credential-execution/ces-runtime.ts +55 -93
- package/src/credential-execution/executable-discovery.ts +1 -11
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
- package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
- package/src/daemon/browser-mode-session.test.ts +402 -0
- package/src/daemon/browser-mode-session.ts +186 -0
- package/src/daemon/computer-use-mode-session.test.ts +210 -0
- package/src/daemon/computer-use-mode-session.ts +105 -0
- package/src/daemon/config-watcher.ts +10 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +58 -10
- package/src/daemon/conversation-agent-loop.ts +219 -25
- package/src/daemon/conversation-evictor.ts +5 -24
- package/src/daemon/conversation-history.ts +10 -0
- package/src/daemon/conversation-interrupt-repair.ts +4 -43
- package/src/daemon/conversation-interrupt.ts +7 -11
- package/src/daemon/conversation-messaging.ts +58 -5
- package/src/daemon/conversation-mode-session.test.ts +1667 -0
- package/src/daemon/conversation-mode-session.ts +1008 -0
- package/src/daemon/conversation-process.ts +5 -0
- package/src/daemon/conversation-runtime-assembly.ts +10 -20
- package/src/daemon/conversation-skill-tools.ts +1 -0
- package/src/daemon/conversation-store.ts +4 -4
- package/src/daemon/conversation-surface-snapshots.ts +135 -0
- package/src/daemon/conversation-surfaces.ts +113 -5
- package/src/daemon/conversation-tool-setup.ts +8 -3
- package/src/daemon/conversation.ts +143 -41
- package/src/daemon/handlers/config-model.ts +7 -5
- package/src/daemon/handlers/shared.ts +55 -16
- package/src/daemon/host-cu-proxy.ts +51 -22
- package/src/daemon/lifecycle.ts +30 -13
- package/src/daemon/message-protocol.ts +0 -1
- package/src/daemon/message-provenance.ts +28 -4
- package/src/daemon/mode-session-startup-recovery.ts +23 -0
- package/src/daemon/mode-session-tracking.ts +54 -0
- package/src/daemon/process-message.ts +13 -4
- package/src/daemon/virtual-desktop-context.ts +21 -0
- package/src/desktop/__tests__/fake-desktop.ts +1 -0
- package/src/desktop/desktop-accessibility-script.ts +88 -0
- package/src/desktop/desktop-accessibility.test.ts +160 -0
- package/src/desktop/desktop-accessibility.ts +169 -0
- package/src/desktop/desktop-automation-lease.test.ts +76 -68
- package/src/desktop/desktop-automation-lease.ts +41 -50
- package/src/desktop/desktop-browser-endpoint.ts +4 -0
- package/src/desktop/desktop-computer-use-routing.test.ts +330 -0
- package/src/desktop/desktop-computer-use.test.ts +449 -0
- package/src/desktop/desktop-computer-use.ts +502 -0
- package/src/desktop/desktop-dependencies.ts +47 -293
- package/src/desktop/desktop-display.ts +2 -2
- package/src/desktop/desktop-panel-config.test.ts +13 -3
- package/src/desktop/desktop-panel-config.ts +109 -15
- package/src/desktop/desktop-session-manager.test.ts +69 -21
- package/src/desktop/desktop-session-manager.ts +76 -22
- package/src/desktop/desktop-stream-bridge.test.ts +11 -122
- package/src/desktop/desktop-stream-bridge.ts +6 -8
- package/src/desktop/desktop-window-theme.ts +5 -25
- package/src/desktop/virtual-desktop-feature.ts +52 -2
- package/src/desktop/virtual-desktop-platform.test.ts +5 -9
- package/src/documents/document-store.ts +23 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +22 -26
- package/src/heartbeat/heartbeat-service.ts +5 -33
- package/src/ipc/__tests__/browser-ipc.test.ts +215 -6
- package/src/ipc/assistant-server.ts +2 -0
- package/src/ipc/routes/__tests__/channel-reply-ipc-routes.test.ts +111 -0
- package/src/ipc/routes/channel-reply-ipc-routes.ts +73 -0
- package/src/live-voice/__tests__/continuation-judge.test.ts +151 -0
- package/src/live-voice/__tests__/live-activity-reporter.test.ts +154 -15
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +743 -31
- package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +191 -10
- package/src/live-voice/__tests__/live-voice-session-groups-gate.test.ts +87 -0
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +5 -1
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +41 -0
- package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +1017 -9
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +224 -1
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +101 -0
- package/src/live-voice/__tests__/live-voice-tts.test.ts +44 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +939 -75
- package/src/live-voice/__tests__/microphone-idle-gate.test.ts +87 -0
- package/src/live-voice/__tests__/session-controls.test.ts +23 -0
- package/src/live-voice/__tests__/task-outcomes.test.ts +117 -0
- package/src/live-voice/__tests__/voice-input-diagnostics.test.ts +117 -0
- package/src/live-voice/camera-mode-session.test.ts +265 -0
- package/src/live-voice/camera-mode-session.ts +277 -0
- package/src/live-voice/continuation-judge.ts +123 -0
- package/src/live-voice/live-activity-reporter.ts +115 -6
- package/src/live-voice/live-voice-manager.ts +36 -1
- package/src/live-voice/live-voice-photo.ts +88 -7
- package/src/live-voice/live-voice-session-manager.ts +15 -0
- package/src/live-voice/live-voice-session.ts +1443 -747
- package/src/live-voice/live-voice-tts.ts +22 -4
- package/src/live-voice/microphone-idle-gate.ts +56 -0
- package/src/live-voice/protocol.ts +171 -4
- package/src/live-voice/session-controls.ts +11 -3
- package/src/live-voice/task-outcomes.ts +131 -0
- package/src/live-voice/voice-input-diagnostics.ts +117 -0
- package/src/mcp/__tests__/manager-tool-caps.test.ts +63 -18
- package/src/mcp/__tests__/tool-caps.test.ts +28 -1
- package/src/mcp/manager.ts +3 -0
- package/src/mcp/tool-caps.ts +12 -4
- package/src/media/__tests__/image-models.test.ts +58 -0
- package/src/media/image-credentials.ts +5 -0
- package/src/media/image-models.ts +52 -0
- package/src/media/image-service.ts +8 -0
- package/src/media/openrouter-image-service.test.ts +133 -0
- package/src/media/openrouter-image-service.ts +153 -0
- package/src/media/types.ts +1 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +65 -11
- package/src/messaging/providers/discord/send.ts +4 -17
- package/src/messaging/providers/discord/transport.ts +2 -2
- package/src/messaging/providers/outlook/client.ts +16 -22
- package/src/messaging/providers/telegram-bot/send.test.ts +236 -1
- package/src/messaging/providers/telegram-bot/send.ts +10 -7
- package/src/messaging/providers/telegram-bot/transport.ts +3 -10
- package/src/messaging/providers/whatsapp/send.test.ts +169 -4
- package/src/monitoring/__tests__/control.test.ts +17 -5
- package/src/monitoring/control.ts +15 -5
- package/src/notifications/AGENTS.md +1 -1
- package/src/notifications/README.md +83 -99
- package/src/notifications/__tests__/broadcaster.test.ts +1 -1
- package/src/notifications/__tests__/channel-allowlist.test.ts +39 -0
- package/src/notifications/__tests__/copy-composer.test.ts +1 -1
- package/src/notifications/__tests__/decision-engine.test.ts +79 -2
- package/src/notifications/__tests__/deterministic-checks.test.ts +10 -10
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +93 -4
- package/src/notifications/__tests__/notification-utils.test.ts +18 -0
- package/src/notifications/adapters/macos.ts +37 -46
- package/src/notifications/broadcaster.ts +5 -6
- package/src/notifications/channel-allowlist.ts +44 -0
- package/src/notifications/copy-composer.ts +0 -23
- package/src/notifications/decision-engine.ts +24 -14
- package/src/notifications/deterministic-checks.ts +1 -1
- package/src/notifications/emit-signal.ts +123 -37
- package/src/notifications/home-feed-side-effect.ts +9 -7
- package/src/notifications/notification-utils.ts +19 -0
- package/src/notifications/signal.ts +4 -19
- package/src/notifications/types.ts +15 -0
- package/src/oauth/connection-resolver.ts +1 -2
- package/src/oauth/oauth-store.ts +1 -3
- package/src/oauth/provider-serializer.ts +7 -0
- package/src/oauth/seed-providers.ts +30 -0
- package/src/onboarding/onboarding-events-store.ts +99 -12
- package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
- package/src/persistence/client-connection-events-store.ts +377 -0
- package/src/persistence/conversation-crud.ts +55 -6
- package/src/persistence/conversation-mode-sessions.test.ts +424 -0
- package/src/persistence/conversation-mode-sessions.ts +460 -0
- package/src/persistence/conversation-queries.ts +6 -19
- package/src/persistence/llm-usage-store.ts +3 -9
- package/src/persistence/message-metadata.ts +25 -0
- package/src/persistence/migrations/381-create-conversation-mode-sessions.ts +41 -0
- package/src/persistence/migrations/382-create-client-connection-events.ts +40 -0
- package/src/persistence/migrations/__tests__/382-create-client-connection-events.test.ts +56 -0
- package/src/persistence/schema/conversations.ts +67 -0
- package/src/persistence/schema/infrastructure.ts +29 -0
- package/src/persistence/steps.ts +17 -0
- package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
- package/src/plugin-api/effective-context-window.ts +33 -0
- package/src/plugin-api/index.ts +24 -5
- package/src/plugin-api/plugin-name-env.ts +125 -0
- package/src/plugin-api/resolve-credential.ts +79 -20
- package/src/plugin-api/vision-support.test.ts +22 -0
- package/src/plugin-api/vision-support.ts +17 -5
- package/src/plugins/__tests__/active-plugin-env.test.ts +136 -0
- package/src/plugins/active-plugin-env.ts +51 -0
- package/src/plugins/defaults/index.ts +24 -0
- package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
- package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
- package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +78 -22
- package/src/plugins/defaults/memory/context-search/format.ts +51 -7
- package/src/plugins/defaults/memory/context-search/limits.ts +10 -12
- package/src/plugins/defaults/memory/context-search/recall-input.ts +38 -0
- package/src/plugins/defaults/memory/context-search/search.ts +8 -14
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +1 -0
- package/src/plugins/defaults/memory/context-search/types.ts +1 -11
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +12 -21
- package/src/plugins/defaults/memory/graph/tools.ts +35 -64
- package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +5 -0
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +2 -2
- package/src/plugins/defaults/memory/tools.test.ts +124 -9
- package/src/plugins/defaults/memory/tools.ts +38 -11
- package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +165 -27
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +46 -27
- package/src/plugins/defaults/memory/v3/orchestrate.ts +78 -38
- package/src/plugins/defaults/memory/v3/pool-log-store.ts +65 -79
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +14 -5
- package/src/plugins/defaults/memory/v3/pool-select.ts +683 -44
- package/src/plugins/defaults/memory/worker-control.ts +15 -5
- package/src/plugins/defaults/task-progress/__tests__/registration.test.ts +70 -0
- package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +380 -0
- package/src/plugins/defaults/task-progress/hooks/post-compact.ts +19 -0
- package/src/plugins/defaults/task-progress/hooks/user-prompt-submit.ts +24 -0
- package/src/plugins/defaults/task-progress/package.json +14 -0
- package/src/plugins/defaults/task-progress/src/apply-task-progress-context.ts +93 -0
- package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +67 -0
- package/src/providers/__tests__/context-overflow-error.test.ts +10 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +18 -0
- package/src/providers/anthropic/client.ts +10 -1
- package/src/providers/anthropic-gateway-shared.ts +6 -0
- package/src/providers/fetch-provider-catalog.ts +11 -0
- package/src/providers/gemini/client.ts +25 -8
- package/src/providers/inference/adapter-factory.ts +1 -1
- package/src/providers/jev/client.test.ts +10 -0
- package/src/providers/jev/client.ts +20 -4
- package/src/providers/model-catalog.ts +4 -3
- package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +94 -1
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +106 -1
- package/src/providers/openai/__tests__/chat-template-flatten.test.ts +24 -0
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +1 -2
- package/src/providers/openai/chat-completions-provider.ts +100 -29
- package/src/providers/openai/google-thought-signature.ts +0 -6
- package/src/providers/openai/responses-provider.ts +23 -1
- package/src/providers/ratelimit.ts +1 -3
- package/src/providers/search-provider-catalog.ts +24 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +24 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +7 -1
- package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +50 -1
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +11 -0
- package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +13 -0
- package/src/providers/types.ts +5 -0
- package/src/routes/control.ts +7 -5
- package/src/runtime/AGENTS.md +4 -2
- package/src/runtime/actor-trust-resolver.ts +3 -3
- package/src/runtime/agent-wake.ts +1 -1
- package/src/runtime/approval-message-composer.ts +3 -69
- package/src/runtime/assistant-event-hub.ts +73 -75
- package/src/runtime/assistant-event-publish-options.ts +7 -0
- package/src/runtime/assistant-event-targeting.ts +79 -0
- package/src/runtime/assistant-stream-state.ts +13 -100
- package/src/runtime/background-job-runner.ts +5 -5
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/guardian-action-message-composer.ts +8 -161
- package/src/runtime/guardian-reply-router.ts +28 -32
- package/src/runtime/http-types.ts +6 -0
- package/src/runtime/message-composer-types.ts +3 -61
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +67 -1
- package/src/runtime/migrations/vbundle-builder.ts +24 -1
- package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +10 -0
- package/src/runtime/migrations/vbundle-importer.ts +4 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +4 -1
- package/src/runtime/migrations/vbundle-validator.ts +1 -0
- package/src/runtime/pending-interactions-mode-session.test.ts +62 -0
- package/src/runtime/pending-interactions.ts +29 -0
- package/src/runtime/routes/__tests__/client-history-routes.test.ts +104 -0
- package/src/runtime/routes/__tests__/image-generation-routes.test.ts +97 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/roadmap-routes.test.ts +29 -6
- package/src/runtime/routes/browser-context.ts +31 -11
- package/src/runtime/routes/browser-routes.ts +43 -4
- package/src/runtime/routes/btw-routes.ts +9 -4
- package/src/runtime/routes/client-routes.ts +108 -0
- package/src/runtime/routes/conversation-management-routes.ts +4 -1
- package/src/runtime/routes/conversation-routes.ts +113 -27
- package/src/runtime/routes/credential-prompt-routes.ts +4 -3
- package/src/runtime/routes/credential-routes.ts +1 -2
- package/src/runtime/routes/desktop-setup-routes.test.ts +9 -18
- package/src/runtime/routes/desktop-setup-routes.ts +4 -6
- package/src/runtime/routes/documents-routes.ts +51 -0
- package/src/runtime/routes/email-routes.ts +3 -7
- package/src/runtime/routes/events-routes.ts +75 -54
- package/src/runtime/routes/identity-routes.ts +1 -5
- package/src/runtime/routes/image-generation-routes.ts +8 -14
- package/src/runtime/routes/inbound-message-handler.ts +35 -38
- package/src/runtime/routes/inbound-stages/backfill-sender-provenance.test.ts +168 -0
- package/src/runtime/routes/inbound-stages/backfill-sender-provenance.ts +96 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +38 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +2 -5
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
- package/src/runtime/routes/llm-context-normalization.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +73 -2
- package/src/runtime/routes/notification-routes.ts +10 -0
- package/src/runtime/routes/oauth-providers.ts +7 -0
- package/src/runtime/routes/plugins-routes.ts +6 -0
- package/src/runtime/routes/roadmap-routes.ts +47 -8
- package/src/runtime/routes/secret-routes.ts +1 -1
- package/src/runtime/routes/settings-routes.ts +10 -4
- package/src/runtime/routes/watcher-routes.ts +1 -3
- package/src/runtime/trust-class.test.ts +7 -6
- package/src/runtime/trust-class.ts +9 -17
- package/src/schedule/__tests__/worker-control.test.ts +36 -5
- package/src/schedule/worker-control.ts +15 -5
- package/src/security/secure-keys.ts +53 -103
- package/src/skills/clawhub.ts +3 -8
- package/src/skills/managed-store.ts +1 -5
- package/src/stt/types.ts +4 -0
- package/src/subagent/notify.ts +54 -34
- package/src/subagent/parent-notification.ts +6 -0
- package/src/telemetry/__tests__/phone-call-funnel.test.ts +72 -0
- package/src/telemetry/phone-call-funnel.ts +144 -0
- package/src/tools/__tests__/tool-schema-root-combinator-guard.test.ts +81 -0
- package/src/tools/ask-question/ask-question-tool.ts +6 -4
- package/src/tools/browser/browser-execution.ts +22 -59
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +561 -39
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +435 -39
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +1 -8
- package/src/tools/client-os.ts +15 -0
- package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
- package/src/tools/computer-use/target.ts +42 -0
- package/src/tools/document/document-tool.ts +13 -18
- package/src/tools/execution-target.ts +14 -16
- package/src/tools/host-terminal/host-shell.ts +4 -1
- package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +250 -0
- package/src/tools/network/__tests__/web-search.test.ts +203 -0
- package/src/tools/network/web-fetch.ts +274 -7
- package/src/tools/network/web-search.ts +468 -6
- package/src/tools/permission-checker.ts +3 -3
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/skills/load.ts +2 -1
- package/src/tools/skills/sandbox-runner.ts +11 -2
- package/src/tools/skills/skill-script-runner.ts +7 -0
- package/src/tools/skills/skill-tool-factory.ts +15 -1
- package/src/tools/terminal/__tests__/safe-env.test.ts +11 -0
- package/src/tools/terminal/safe-env.ts +4 -0
- package/src/tools/terminal/shell.ts +2 -0
- package/src/tools/tool-approval-handler.ts +5 -1
- package/src/tools/tool-types.ts +3 -3
- package/src/tools/types.ts +8 -2
- package/src/util/__tests__/worker-process-command.test.ts +5 -4
- package/src/util/abort-reasons.ts +18 -26
- package/src/util/canonicalize-identity.test.ts +21 -0
- package/src/util/canonicalize-identity.ts +16 -0
- package/src/util/errors.ts +13 -3
- package/src/util/provider-error-patterns.ts +3 -0
- package/src/util/worker-process.ts +77 -35
- package/src/workspace/migrations/157-add-desktop-files-launcher.ts +94 -0
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +4 -10
- package/src/workspace/migrations/__tests__/157-add-desktop-files-launcher.test.ts +113 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/computer-use-window-schema.test.ts +0 -24
- package/src/api/events/heartbeat-alert.ts +0 -20
- package/src/daemon/message-types/web-activity.ts +0 -65
- package/src/desktop/desktop-dependencies.test.ts +0 -131
- package/src/tools/computer-use/definitions.ts +0 -607
|
@@ -164,6 +164,23 @@ const PAGE_2_LEAD: Section = {
|
|
|
164
164
|
text: "y",
|
|
165
165
|
ordinal: 0,
|
|
166
166
|
};
|
|
167
|
+
const DEFAULT_FINDER = [
|
|
168
|
+
{
|
|
169
|
+
slug: "page-1",
|
|
170
|
+
section: PAGE_1_LEAD,
|
|
171
|
+
descriptor: "",
|
|
172
|
+
lane: "needle" as const,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
slug: "page-2",
|
|
176
|
+
section: PAGE_2_LEAD,
|
|
177
|
+
descriptor: "",
|
|
178
|
+
lane: "dense" as const,
|
|
179
|
+
},
|
|
180
|
+
{ slug: "page-3", descriptor: "", lane: "edge" as const },
|
|
181
|
+
{ slug: "page-4", descriptor: "", lane: "reply" as const },
|
|
182
|
+
{ slug: "page-5", descriptor: "", lane: "learned" as const },
|
|
183
|
+
];
|
|
167
184
|
const orchestrateSpy = mock(
|
|
168
185
|
async (): Promise<OrchestrateResult> => ({
|
|
169
186
|
selections: [
|
|
@@ -181,20 +198,18 @@ const orchestrateSpy = mock(
|
|
|
181
198
|
hot: ["page-hot"],
|
|
182
199
|
fresh: ["page-fresh"],
|
|
183
200
|
always: [CAPABILITY_SLUG],
|
|
184
|
-
finder:
|
|
185
|
-
{
|
|
186
|
-
slug: "page-1",
|
|
187
|
-
section: PAGE_1_LEAD,
|
|
188
|
-
descriptor: "",
|
|
189
|
-
lane: "needle",
|
|
190
|
-
},
|
|
191
|
-
{ slug: "page-2", section: PAGE_2_LEAD, descriptor: "", lane: "dense" },
|
|
192
|
-
{ slug: "page-3", descriptor: "", lane: "edge" },
|
|
193
|
-
{ slug: "page-4", descriptor: "", lane: "reply" },
|
|
194
|
-
{ slug: "page-5", descriptor: "", lane: "learned" },
|
|
195
|
-
],
|
|
201
|
+
finder: DEFAULT_FINDER,
|
|
196
202
|
},
|
|
197
203
|
selectorRan: true,
|
|
204
|
+
pool: {
|
|
205
|
+
stable: [
|
|
206
|
+
{ slug: "page-core", card: "core card", lane: "core" },
|
|
207
|
+
{ slug: "page-hot", card: "hot card", lane: "hot" },
|
|
208
|
+
{ slug: "page-fresh", card: "fresh card", lane: "fresh" },
|
|
209
|
+
{ slug: CAPABILITY_SLUG, card: "skill card", lane: "always" },
|
|
210
|
+
],
|
|
211
|
+
finder: DEFAULT_FINDER,
|
|
212
|
+
},
|
|
198
213
|
}),
|
|
199
214
|
);
|
|
200
215
|
|
|
@@ -665,6 +680,11 @@ function chosenBySlug(): Record<string, boolean> {
|
|
|
665
680
|
* needle lane, page-2 via dense, page-3 via edge) whose selector kept exactly
|
|
666
681
|
* `kept`. */
|
|
667
682
|
function poolOf(kept: string[]): OrchestrateResult {
|
|
683
|
+
const finder = [
|
|
684
|
+
{ slug: "page-1", descriptor: "", lane: "needle" as const },
|
|
685
|
+
{ slug: "page-2", descriptor: "", lane: "dense" as const },
|
|
686
|
+
{ slug: "page-3", descriptor: "", lane: "edge" as const },
|
|
687
|
+
];
|
|
668
688
|
return {
|
|
669
689
|
selections: kept.map((slug) => ({ slug, sections: [] })),
|
|
670
690
|
lanes: {
|
|
@@ -672,13 +692,10 @@ function poolOf(kept: string[]): OrchestrateResult {
|
|
|
672
692
|
hot: [],
|
|
673
693
|
fresh: [],
|
|
674
694
|
always: [],
|
|
675
|
-
finder
|
|
676
|
-
{ slug: "page-1", descriptor: "", lane: "needle" },
|
|
677
|
-
{ slug: "page-2", descriptor: "", lane: "dense" },
|
|
678
|
-
{ slug: "page-3", descriptor: "", lane: "edge" },
|
|
679
|
-
],
|
|
695
|
+
finder,
|
|
680
696
|
},
|
|
681
697
|
selectorRan: true,
|
|
698
|
+
pool: { stable: [], finder },
|
|
682
699
|
};
|
|
683
700
|
}
|
|
684
701
|
|
|
@@ -893,6 +910,15 @@ describe("memory-v3 engine", () => {
|
|
|
893
910
|
text: "x",
|
|
894
911
|
ordinal: 1,
|
|
895
912
|
};
|
|
913
|
+
const finder = [
|
|
914
|
+
{
|
|
915
|
+
slug: "page-rare",
|
|
916
|
+
section: inventory,
|
|
917
|
+
terms: ["turnip"],
|
|
918
|
+
descriptor: "",
|
|
919
|
+
lane: "rare" as const,
|
|
920
|
+
},
|
|
921
|
+
];
|
|
896
922
|
orchestrateSpy.mockImplementationOnce(async () => ({
|
|
897
923
|
selections: [{ slug: "page-rare", sections: [inventory] }],
|
|
898
924
|
lanes: {
|
|
@@ -900,17 +926,10 @@ describe("memory-v3 engine", () => {
|
|
|
900
926
|
hot: [],
|
|
901
927
|
fresh: [],
|
|
902
928
|
always: [],
|
|
903
|
-
finder
|
|
904
|
-
{
|
|
905
|
-
slug: "page-rare",
|
|
906
|
-
section: inventory,
|
|
907
|
-
terms: ["turnip"],
|
|
908
|
-
descriptor: "",
|
|
909
|
-
lane: "rare",
|
|
910
|
-
},
|
|
911
|
-
],
|
|
929
|
+
finder,
|
|
912
930
|
},
|
|
913
931
|
selectorRan: true,
|
|
932
|
+
pool: { stable: [], finder },
|
|
914
933
|
}));
|
|
915
934
|
|
|
916
935
|
await observeTurn("conv-1", 2);
|
|
@@ -1023,7 +1042,7 @@ describe("memory-v3 engine", () => {
|
|
|
1023
1042
|
keptAll: false,
|
|
1024
1043
|
gateReason: "dense_pass",
|
|
1025
1044
|
pool: {
|
|
1026
|
-
stable: [{ slug: "page-core", card: "core card" }],
|
|
1045
|
+
stable: [{ slug: "page-core", card: "core card", lane: "core" }],
|
|
1027
1046
|
finder,
|
|
1028
1047
|
},
|
|
1029
1048
|
}));
|
|
@@ -67,7 +67,9 @@
|
|
|
67
67
|
* 3. A SINGLE forced-tool select (`selectPool`) over the whole pool. The
|
|
68
68
|
* result is this turn's selections — current turn only. Cross-turn
|
|
69
69
|
* persistence is the injector's job (net-new blocks frozen into history),
|
|
70
|
-
* not a per-turn re-rendered carry set.
|
|
70
|
+
* not a per-turn re-rendered carry set. When the call site resolves to
|
|
71
|
+
* TypeSafe, `selectPool` asks one System One noul per numbered candidate
|
|
72
|
+
* instead of forcing `select_pages`.
|
|
71
73
|
*/
|
|
72
74
|
|
|
73
75
|
import type { AssistantConfig } from "../../../../config/schema.js";
|
|
@@ -338,30 +340,34 @@ export interface OrchestrateResult {
|
|
|
338
340
|
* carried-forward set unioned in. */
|
|
339
341
|
selections: SelectedPage[];
|
|
340
342
|
/** The candidate lanes in cache order; see {@link OrchestrateLanes}. Consumed
|
|
341
|
-
* by
|
|
342
|
-
*
|
|
343
|
+
* by selection telemetry for lane attribution and retained as the complete
|
|
344
|
+
* retrieval diagnostics even when selector budgeting trims `pool`. */
|
|
343
345
|
lanes: OrchestrateLanes;
|
|
344
346
|
/** Whether the selector LLM judged a non-empty pool this turn (the
|
|
345
347
|
* `selector_ran` telemetry field). False when the pool was empty, when the
|
|
346
348
|
* disabled-selector passthrough kept every candidate, when a closed
|
|
347
349
|
* injection gate hard-skipped selection, and when the selector's provider
|
|
348
|
-
* failed and the stable
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
350
|
+
* failed and the retained stable candidates were kept unjudged
|
|
351
|
+
* (`selectorFailure`). A false value with empty `selections` means the
|
|
352
|
+
* selector was given nothing only when `pool` is absent; a failed attempt
|
|
353
|
+
* can carry a finder-only pool with no fallback selections. */
|
|
352
354
|
selectorRan: boolean;
|
|
353
355
|
/** Set when the selector could not be run this turn (provider unavailable,
|
|
354
356
|
* or no usable tool call after the re-prompt retries). `selections` then
|
|
355
|
-
* holds the stable
|
|
356
|
-
* they are evidence for a judge, not evidence to inject on
|
|
357
|
+
* holds the retained stable candidates unjudged; finder candidates are
|
|
358
|
+
* dropped because they are evidence for a judge, not evidence to inject on
|
|
359
|
+
* their own. The
|
|
357
360
|
* live injector queues a notice so the person knows this turn drew on
|
|
358
361
|
* core memories only. */
|
|
359
362
|
selectorFailure?: MemoryV3RetrievalUnavailableError;
|
|
360
363
|
/** The pool as the selector was given it, in one numbering: the
|
|
361
364
|
* stable-prefix cards, then the finder lines. Absent when no pool was
|
|
362
|
-
* assembled this turn (a closed gate's hard skip). Read by the pool
|
|
363
|
-
* capture (`
|
|
365
|
+
* assembled this turn (a closed gate's hard skip). Read by the pool record
|
|
366
|
+
* and input capture (`pool-log-store.ts`). */
|
|
364
367
|
pool?: SelectorPool;
|
|
368
|
+
/** The exact context strings rendered for the selector request. Absent when
|
|
369
|
+
* no selector pool was assembled. */
|
|
370
|
+
selectorTurn?: MemoryRoutingTurn;
|
|
365
371
|
/** Whether the selector's recall-safe keep-all fallback fired
|
|
366
372
|
* (`selectPool`'s `keptAll`). Absent when no pool was assembled. */
|
|
367
373
|
keptAll?: boolean;
|
|
@@ -404,7 +410,12 @@ export async function orchestrate(
|
|
|
404
410
|
// the byte-stable-prefix contract). Built lazily so the gate's bypass path can
|
|
405
411
|
// reuse the exact same construction as the normal step-2 pool assembly.
|
|
406
412
|
const buildStable = (): StableCandidate[] =>
|
|
407
|
-
[
|
|
413
|
+
[
|
|
414
|
+
...core.map((slug) => ({ slug, lane: "core" as const })),
|
|
415
|
+
...hot.map((slug) => ({ slug, lane: "hot" as const })),
|
|
416
|
+
...fresh.map((slug) => ({ slug, lane: "fresh" as const })),
|
|
417
|
+
...always.map((slug) => ({ slug, lane: "always" as const })),
|
|
418
|
+
].map(({ slug, lane }) => {
|
|
408
419
|
const card = deps.prefixCards.get(slug);
|
|
409
420
|
if (card === undefined) {
|
|
410
421
|
// Lane init renders a card for every core/hot slug; a hole here means
|
|
@@ -415,7 +426,7 @@ export async function orchestrate(
|
|
|
415
426
|
`memory-v3: no pre-rendered card for stable-prefix slug "${slug}"`,
|
|
416
427
|
);
|
|
417
428
|
}
|
|
418
|
-
return { slug, card };
|
|
429
|
+
return { slug, card, lane };
|
|
419
430
|
});
|
|
420
431
|
|
|
421
432
|
// Run the selector over a pool, or pass its candidates straight through when
|
|
@@ -438,39 +449,51 @@ export async function orchestrate(
|
|
|
438
449
|
): Promise<{
|
|
439
450
|
selections: SelectedPage[];
|
|
440
451
|
keptAll: boolean;
|
|
452
|
+
pool: SelectorPool;
|
|
453
|
+
selectorTurn: MemoryRoutingTurn;
|
|
441
454
|
failure?: MemoryV3RetrievalUnavailableError;
|
|
442
455
|
}> =>
|
|
443
456
|
timeLatencySubSpan("v3_selection", "Memory selection", async () => {
|
|
444
457
|
if (deps.selectorEnabled === false) {
|
|
445
|
-
return {
|
|
458
|
+
return {
|
|
459
|
+
selections: selectAllPoolCandidates(pool),
|
|
460
|
+
keptAll: false,
|
|
461
|
+
pool,
|
|
462
|
+
selectorTurn: turn,
|
|
463
|
+
};
|
|
446
464
|
}
|
|
447
465
|
try {
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
466
|
+
const selection = await selectPool(pool, turn, deps.selectorPrompt);
|
|
467
|
+
return {
|
|
468
|
+
selections: selection.pages,
|
|
469
|
+
keptAll: selection.keptAll,
|
|
470
|
+
pool: selection.pool,
|
|
471
|
+
selectorTurn: selection.turn,
|
|
472
|
+
};
|
|
454
473
|
} catch (err) {
|
|
455
474
|
if (!(err instanceof MemoryV3RetrievalUnavailableError)) {
|
|
456
475
|
throw err;
|
|
457
476
|
}
|
|
477
|
+
const attemptedPool = err.pool ?? pool;
|
|
478
|
+
const attemptedTurn = err.turn ?? turn;
|
|
458
479
|
log.warn(
|
|
459
480
|
{
|
|
460
481
|
conversationId: turn.conversationId,
|
|
461
482
|
turnNumber: turn.turnNumber,
|
|
462
|
-
stableCount:
|
|
463
|
-
finderCount:
|
|
483
|
+
stableCount: attemptedPool.stable.length,
|
|
484
|
+
finderCount: attemptedPool.finder.length,
|
|
464
485
|
err: err.message,
|
|
465
486
|
},
|
|
466
487
|
"memory-v3 selector unavailable; keeping the stable prefix unjudged",
|
|
467
488
|
);
|
|
468
489
|
return {
|
|
469
490
|
selections: selectAllPoolCandidates({
|
|
470
|
-
stable:
|
|
491
|
+
stable: attemptedPool.stable,
|
|
471
492
|
finder: [],
|
|
472
493
|
}),
|
|
473
494
|
keptAll: false,
|
|
495
|
+
pool: attemptedPool,
|
|
496
|
+
selectorTurn: attemptedTurn,
|
|
474
497
|
failure: err,
|
|
475
498
|
};
|
|
476
499
|
}
|
|
@@ -910,13 +933,23 @@ export async function orchestrate(
|
|
|
910
933
|
selections: SelectedPage[],
|
|
911
934
|
selectorRan: boolean,
|
|
912
935
|
selectorFailure?: MemoryV3RetrievalUnavailableError,
|
|
913
|
-
judged?: {
|
|
936
|
+
judged?: {
|
|
937
|
+
pool: SelectorPool;
|
|
938
|
+
selectorTurn: MemoryRoutingTurn;
|
|
939
|
+
keptAll: boolean;
|
|
940
|
+
},
|
|
914
941
|
): OrchestrateResult => ({
|
|
915
942
|
selections,
|
|
916
943
|
lanes: { core, hot, fresh, always, finder: [] },
|
|
917
944
|
selectorRan,
|
|
918
945
|
gateReason: gate.reason,
|
|
919
|
-
...(judged
|
|
946
|
+
...(judged
|
|
947
|
+
? {
|
|
948
|
+
pool: judged.pool,
|
|
949
|
+
selectorTurn: judged.selectorTurn,
|
|
950
|
+
keptAll: judged.keptAll,
|
|
951
|
+
}
|
|
952
|
+
: {}),
|
|
920
953
|
...(selectorFailure ? { selectorFailure } : {}),
|
|
921
954
|
});
|
|
922
955
|
if (deps.gateConfig.bypassForCore) {
|
|
@@ -936,19 +969,18 @@ export async function orchestrate(
|
|
|
936
969
|
const {
|
|
937
970
|
selections: bypassed,
|
|
938
971
|
keptAll,
|
|
972
|
+
pool: selectedPool,
|
|
973
|
+
selectorTurn,
|
|
939
974
|
failure,
|
|
940
975
|
} = await runSelection(stableOnly);
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
keptAll,
|
|
945
|
-
failure,
|
|
946
|
-
);
|
|
976
|
+
const selectedPoolSize =
|
|
977
|
+
selectedPool.stable.length + selectedPool.finder.length;
|
|
978
|
+
recordSelection(bypassed, selectedPoolSize, keptAll, failure);
|
|
947
979
|
return closed(
|
|
948
980
|
bypassed,
|
|
949
|
-
selectorRanOver(
|
|
981
|
+
selectorRanOver(selectedPoolSize, failure),
|
|
950
982
|
failure,
|
|
951
|
-
{ pool:
|
|
983
|
+
{ pool: selectedPool, selectorTurn, keptAll },
|
|
952
984
|
);
|
|
953
985
|
}
|
|
954
986
|
// Hard skip: the selector is never consulted, so this is a zero
|
|
@@ -1054,15 +1086,23 @@ export async function orchestrate(
|
|
|
1054
1086
|
"Gate & edge expansion",
|
|
1055
1087
|
Date.now() - expandStartedAt,
|
|
1056
1088
|
);
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1059
|
-
|
|
1089
|
+
const {
|
|
1090
|
+
selections,
|
|
1091
|
+
keptAll,
|
|
1092
|
+
pool: selectedPool,
|
|
1093
|
+
selectorTurn,
|
|
1094
|
+
failure,
|
|
1095
|
+
} = await runSelection(pool);
|
|
1096
|
+
const selectedPoolSize =
|
|
1097
|
+
selectedPool.stable.length + selectedPool.finder.length;
|
|
1098
|
+
recordSelection(selections, selectedPoolSize, keptAll, failure);
|
|
1060
1099
|
|
|
1061
1100
|
return {
|
|
1062
1101
|
selections,
|
|
1063
1102
|
lanes: { core, hot, fresh, always, finder },
|
|
1064
|
-
selectorRan: selectorRanOver(
|
|
1065
|
-
pool,
|
|
1103
|
+
selectorRan: selectorRanOver(selectedPoolSize, failure),
|
|
1104
|
+
pool: selectedPool,
|
|
1105
|
+
selectorTurn,
|
|
1066
1106
|
keptAll,
|
|
1067
1107
|
...(gateOutcome ? { gateReason: gateOutcome.reason } : {}),
|
|
1068
1108
|
...(failure ? { selectorFailure: failure } : {}),
|
|
@@ -106,30 +106,39 @@ interface StoredPool {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
|
-
* Build the turn's pool record from
|
|
110
|
-
* comes first in cache order
|
|
111
|
-
* whole-page cards with no section; the finder tail follows in
|
|
112
|
-
* order, each line tagged with the lane that surfaced it and the
|
|
113
|
-
* carries. A finder hit on a stable-prefix page therefore appears
|
|
114
|
-
* a page hit on several sections once per section, exactly as the
|
|
115
|
-
* saw it. A card or a section-less line reads chosen when its page
|
|
109
|
+
* Build the turn's pool record from the exact selector pool carried by the
|
|
110
|
+
* orchestrate result. The stable prefix comes first in retained cache order as
|
|
111
|
+
* whole-page cards with no section; the finder tail follows in retained
|
|
112
|
+
* surfacing order, each line tagged with the lane that surfaced it and the
|
|
113
|
+
* section it carries. A finder hit on a stable-prefix page therefore appears
|
|
114
|
+
* twice, and a page hit on several sections once per section, exactly as the
|
|
115
|
+
* selector saw it. A card or a section-less line reads chosen when its page
|
|
116
|
+
* was kept;
|
|
116
117
|
* a line carrying a section reads chosen when that section was selected.
|
|
117
118
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* disabled-selector passthrough keeps every pooled candidate as a selection,
|
|
124
|
-
* so it still records its pool.
|
|
119
|
+
* A result without `pool` records no candidates: the injection gate either
|
|
120
|
+
* hard-skipped selection or no pool was assembled. A failed selector attempt
|
|
121
|
+
* still carries the exact pool it received, with retained stable cards chosen
|
|
122
|
+
* by the unjudged fallback and finder lines unchosen. The disabled-selector
|
|
123
|
+
* passthrough also carries and records its pool.
|
|
125
124
|
*/
|
|
126
125
|
export function buildPoolRecord(result: OrchestrateResult): PoolRecord {
|
|
127
|
-
|
|
126
|
+
const pool = result.pool;
|
|
127
|
+
if (pool === undefined) {
|
|
128
|
+
if (result.selections.length > 0) {
|
|
129
|
+
log.warn(
|
|
130
|
+
{
|
|
131
|
+
selectorRan: result.selectorRan,
|
|
132
|
+
selectedCount: result.selections.length,
|
|
133
|
+
},
|
|
134
|
+
"memory-v3 pool record: result has selections but no selector pool",
|
|
135
|
+
);
|
|
136
|
+
}
|
|
128
137
|
return {
|
|
129
138
|
candidates: [],
|
|
130
139
|
pool_size: 0,
|
|
131
|
-
selected_count:
|
|
132
|
-
selector_ran:
|
|
140
|
+
selected_count: result.selections.length,
|
|
141
|
+
selector_ran: result.selectorRan,
|
|
133
142
|
};
|
|
134
143
|
}
|
|
135
144
|
const selected = new Map<Slug, Set<string>>(
|
|
@@ -138,30 +147,27 @@ export function buildPoolRecord(result: OrchestrateResult): PoolRecord {
|
|
|
138
147
|
new Set(s.sections.map((section) => sectionKey(section))),
|
|
139
148
|
]),
|
|
140
149
|
);
|
|
141
|
-
const card = (slug: Slug, lane: PoolLane): PoolCandidateRecord => ({
|
|
142
|
-
slug,
|
|
143
|
-
lane,
|
|
144
|
-
section_title: null,
|
|
145
|
-
section_key: null,
|
|
146
|
-
chosen: selected.has(slug),
|
|
147
|
-
});
|
|
148
|
-
const { core, hot, fresh, always, finder } = result.lanes;
|
|
149
150
|
const candidates: PoolCandidateRecord[] = [
|
|
150
|
-
...
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
...pool.stable.map(
|
|
152
|
+
(candidate): PoolCandidateRecord => ({
|
|
153
|
+
slug: candidate.slug,
|
|
154
|
+
lane: candidate.lane,
|
|
155
|
+
section_title: null,
|
|
156
|
+
section_key: null,
|
|
157
|
+
chosen: selected.has(candidate.slug),
|
|
158
|
+
}),
|
|
159
|
+
),
|
|
160
|
+
...pool.finder.map((candidate): PoolCandidateRecord => {
|
|
161
|
+
const key = candidate.section ? sectionKey(candidate.section) : null;
|
|
156
162
|
return {
|
|
157
|
-
slug,
|
|
158
|
-
lane,
|
|
159
|
-
section_title: section?.title ?? null,
|
|
163
|
+
slug: candidate.slug,
|
|
164
|
+
lane: candidate.lane,
|
|
165
|
+
section_title: candidate.section?.title ?? null,
|
|
160
166
|
section_key: key,
|
|
161
167
|
chosen:
|
|
162
168
|
key === null
|
|
163
|
-
? selected.has(slug)
|
|
164
|
-
: (selected.get(slug)?.has(key) ?? false),
|
|
169
|
+
? selected.has(candidate.slug)
|
|
170
|
+
: (selected.get(candidate.slug)?.has(key) ?? false),
|
|
165
171
|
};
|
|
166
172
|
}),
|
|
167
173
|
];
|
|
@@ -348,15 +354,15 @@ export interface PoolInputCapture {
|
|
|
348
354
|
|
|
349
355
|
/**
|
|
350
356
|
* Build the turn's input capture from an orchestrate result and the turn it
|
|
351
|
-
* ran on.
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
357
|
+
* ran on. When selector budgeting trimmed the context, the result's
|
|
358
|
+
* `selectorTurn` is the source of truth. Each candidate text is exactly what
|
|
359
|
+
* the selector was shown minus its pool number: a stable-prefix candidate's
|
|
360
|
+
* pre-rendered card, a finder candidate's rendered line
|
|
361
|
+
* ({@link renderFinderLine}), in the pool
|
|
362
|
+
* record's order ({@link buildPoolRecord}). A result that carries no selector
|
|
363
|
+
* pool captures the turn context and no candidate texts, so the hashes stay
|
|
364
|
+
* aligned with the empty record. Failed attempts carry their exact attempted
|
|
365
|
+
* pool and trimmed context even though `selectorRan` is false.
|
|
360
366
|
*/
|
|
361
367
|
export function buildPoolInput(
|
|
362
368
|
result: OrchestrateResult,
|
|
@@ -365,44 +371,24 @@ export function buildPoolInput(
|
|
|
365
371
|
): PoolInputCapture {
|
|
366
372
|
const texts = new Map<string, string>();
|
|
367
373
|
const hashes: string[] = [];
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
const rendered
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
...result.pool.stable.map((candidate) => candidate.card),
|
|
378
|
-
...result.pool.finder.map((candidate) =>
|
|
379
|
-
renderFinderLine(candidate),
|
|
380
|
-
),
|
|
381
|
-
];
|
|
382
|
-
if (rendered === undefined || rendered.length !== expected) {
|
|
383
|
-
log.warn(
|
|
384
|
-
{
|
|
385
|
-
conversationId: turn.conversationId,
|
|
386
|
-
turnNumber: turn.turnNumber,
|
|
387
|
-
rendered: rendered?.length ?? null,
|
|
388
|
-
expected,
|
|
389
|
-
},
|
|
390
|
-
"memory-v3 pool input capture: the result's pool does not match its lanes; capturing no candidate texts",
|
|
391
|
-
);
|
|
392
|
-
} else {
|
|
393
|
-
for (const text of rendered) {
|
|
394
|
-
const hash = hashPoolText(text);
|
|
395
|
-
hashes.push(hash);
|
|
396
|
-
texts.set(hash, text);
|
|
397
|
-
}
|
|
374
|
+
if (result.pool !== undefined) {
|
|
375
|
+
const rendered = [
|
|
376
|
+
...result.pool.stable.map((candidate) => candidate.card),
|
|
377
|
+
...result.pool.finder.map((candidate) => renderFinderLine(candidate)),
|
|
378
|
+
];
|
|
379
|
+
for (const text of rendered) {
|
|
380
|
+
const hash = hashPoolText(text);
|
|
381
|
+
hashes.push(hash);
|
|
382
|
+
texts.set(hash, text);
|
|
398
383
|
}
|
|
399
384
|
}
|
|
385
|
+
const selectorTurn = result.selectorTurn ?? turn;
|
|
400
386
|
return {
|
|
401
387
|
input: {
|
|
402
|
-
situational_context:
|
|
403
|
-
recent_context:
|
|
404
|
-
current_message:
|
|
405
|
-
previous_assistant_message:
|
|
388
|
+
situational_context: selectorTurn.situationalContext ?? null,
|
|
389
|
+
recent_context: selectorTurn.recentContext,
|
|
390
|
+
current_message: selectorTurn.currentMessage,
|
|
391
|
+
previous_assistant_message: selectorTurn.previousAssistantMessage ?? null,
|
|
406
392
|
selector_prompt_hash:
|
|
407
393
|
result.selectorRan && selectorPrompt !== undefined
|
|
408
394
|
? hashPoolText(selectorPrompt)
|
|
@@ -72,9 +72,11 @@ const turn: MemoryRoutingTurn = {
|
|
|
72
72
|
recentContext: "",
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
-
const pool = {
|
|
75
|
+
const pool: Parameters<typeof selectPool>[0] = {
|
|
76
76
|
stable: [],
|
|
77
|
-
finder: [
|
|
77
|
+
finder: [
|
|
78
|
+
{ slug: "page-a" as Slug, descriptor: "a descriptor", lane: "needle" },
|
|
79
|
+
],
|
|
78
80
|
};
|
|
79
81
|
|
|
80
82
|
describe("selectPool", () => {
|
|
@@ -133,6 +135,8 @@ describe("selectPool", () => {
|
|
|
133
135
|
expect(await selectPool(pool, turn)).toEqual({
|
|
134
136
|
pages: [{ slug: "page-a", sections: [] }],
|
|
135
137
|
keptAll: false,
|
|
138
|
+
pool,
|
|
139
|
+
turn,
|
|
136
140
|
});
|
|
137
141
|
});
|
|
138
142
|
|
|
@@ -144,6 +148,8 @@ describe("selectPool", () => {
|
|
|
144
148
|
expect(await selectPool(pool, turn)).toEqual({
|
|
145
149
|
pages: [{ slug: "page-a", sections: [] }],
|
|
146
150
|
keptAll: true,
|
|
151
|
+
pool,
|
|
152
|
+
turn,
|
|
147
153
|
});
|
|
148
154
|
});
|
|
149
155
|
|
|
@@ -157,14 +163,14 @@ describe("selectPool", () => {
|
|
|
157
163
|
input: { ids: [] },
|
|
158
164
|
},
|
|
159
165
|
]);
|
|
160
|
-
const candidate = {
|
|
166
|
+
const candidate: Parameters<typeof renderFinderLine>[0] = {
|
|
161
167
|
slug: "page-a" as Slug,
|
|
162
168
|
descriptor: "a descriptor",
|
|
163
169
|
lane: "needle",
|
|
164
170
|
};
|
|
165
171
|
await selectPool(
|
|
166
172
|
{
|
|
167
|
-
stable: [{ slug: "page-s" as Slug, card: "card s" }],
|
|
173
|
+
stable: [{ slug: "page-s" as Slug, card: "card s", lane: "core" }],
|
|
168
174
|
finder: [candidate],
|
|
169
175
|
},
|
|
170
176
|
turn,
|
|
@@ -177,9 +183,12 @@ describe("selectPool", () => {
|
|
|
177
183
|
});
|
|
178
184
|
|
|
179
185
|
test("an empty candidate pool returns no selections", async () => {
|
|
180
|
-
|
|
186
|
+
const emptyPool = { stable: [], finder: [] };
|
|
187
|
+
expect(await selectPool(emptyPool, turn)).toEqual({
|
|
181
188
|
pages: [],
|
|
182
189
|
keptAll: false,
|
|
190
|
+
pool: emptyPool,
|
|
191
|
+
turn,
|
|
183
192
|
});
|
|
184
193
|
});
|
|
185
194
|
});
|