@vellumai/assistant 0.12.2 → 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/.env.example +2 -0
- package/AGENTS.md +1 -1
- package/ARCHITECTURE.md +43 -29
- package/Dockerfile +63 -0
- package/docs/architecture/integrations.md +7 -0
- package/docs/architecture/memory.md +17 -2
- package/docs/architecture/security.md +10 -5
- package/docs/architecture/turn-actor.md +2 -0
- package/docs/credential-execution-service.md +1 -1
- package/docs/desktop-browser-cli.md +50 -5
- 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/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
- package/node_modules/@vellumai/environments/src/shell.ts +24 -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/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
- 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/__tests__/secret-detection.test.ts +1 -0
- 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/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
- package/openapi.yaml +716 -16
- package/package.json +1 -1
- package/scripts/smoke-desktop-browser-cli.ts +11 -26
- package/scripts/smoke-desktop-window-theme.ts +2 -3
- package/scripts/sync-llm-catalog.ts +3 -0
- package/scripts/voice-ttft-spike.ts +2 -2
- 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__/agent-loop.test.ts +259 -0
- package/src/__tests__/agent-wake-delegation-prompt.test.ts +64 -2
- 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__/anthropic-provider.test.ts +55 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +40 -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__/attachments-store.test.ts +22 -3
- 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-approval.test.ts +9 -14
- package/src/__tests__/channel-reply-delivery.test.ts +56 -0
- package/src/__tests__/channel-retry-sweep.test.ts +9 -0
- package/src/__tests__/chat-credential-redaction.test.ts +23 -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-screenshot-attachments.test.ts +411 -0
- package/src/__tests__/computer-use-screenshot-selection.test.ts +50 -0
- 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-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +797 -16
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
- package/src/__tests__/conversation-attachments.test.ts +106 -0
- package/src/__tests__/conversation-evictor.test.ts +62 -37
- package/src/__tests__/conversation-fork-crud.test.ts +191 -0
- 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-rendered-delegation-state.test.ts +276 -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 +72 -55
- package/src/__tests__/credential-prompt-route.test.ts +35 -3
- package/src/__tests__/cu-unified-flow.test.ts +82 -1
- package/src/__tests__/db-conversation-tool-surface.test.ts +221 -0
- 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 +58 -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__/history-repair.test.ts +53 -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 +26 -0
- package/src/__tests__/interrupt-on-send.test.ts +57 -43
- package/src/__tests__/interrupt-turn-note.test.ts +5 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +85 -1
- package/src/__tests__/llm-catalog-parity.test.ts +27 -4
- 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-apps-routes.test.ts +1 -0
- package/src/__tests__/oauth-commands-routes.test.ts +114 -101
- package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +13 -0
- package/src/__tests__/oauth-providers-routes.test.ts +3 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/persist-media-references.test.ts +50 -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 -1
- 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__/run-conversation-turn-persistence.test.ts +138 -1
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +20 -0
- package/src/__tests__/scheduler-result-notification.test.ts +23 -4
- package/src/__tests__/script-proxy-certs.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__/secret-routes-platform-proxy.test.ts +86 -31
- package/src/__tests__/secret-routes-scrub.test.ts +22 -27
- package/src/__tests__/secret-scanner.test.ts +20 -0
- package/src/__tests__/secure-keys-managed-failover.test.ts +8 -0
- package/src/__tests__/secure-keys.test.ts +50 -4
- package/src/__tests__/send-endpoint-busy.test.ts +163 -1
- package/src/__tests__/server-history-render.test.ts +91 -1
- package/src/__tests__/server-tool-pairing.test.ts +107 -0
- package/src/__tests__/settings-routes.test.ts +50 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
- package/src/__tests__/skills.test.ts +5 -4
- 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__/subagent-tool-gate-mode.test.ts +226 -0
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
- package/src/__tests__/terminal-tools.test.ts +8 -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-follow-up.test.ts +99 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +66 -1
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/twilio-routes.test.ts +1 -0
- package/src/__tests__/unicode.test.ts +36 -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 +136 -53
- package/src/agent/tool-result-follow-up.ts +70 -0
- package/src/api/attachment-provenance.test.ts +68 -0
- package/src/api/computer-use-tool.test.ts +55 -0
- package/src/api/computer-use-tool.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +3 -0
- package/src/api/events/assistant-turn-start.ts +3 -0
- package/src/api/events/desktop-activity-changed.ts +10 -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/question-request.ts +1 -0
- 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 +42 -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 +9 -0
- package/src/approvals/AGENTS.md +4 -2
- package/src/approvals/approval-primitive.ts +5 -2
- package/src/approvals/scoped-approval-grants.ts +6 -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 -9
- 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__/cli-test-harness.ts +21 -3
- package/src/cli/commands/__tests__/notifications.test.ts +35 -10
- package/src/cli/commands/__tests__/plugins.test.ts +20 -1
- package/src/cli/commands/__tests__/schedules.test.ts +14 -0
- package/src/cli/commands/bash.help.ts +4 -3
- package/src/cli/commands/browser.help.ts +9 -6
- 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 +9 -4
- package/src/cli/commands/notifications.help.ts +16 -2
- package/src/cli/commands/notifications.ts +30 -8
- package/src/cli/commands/oauth/index.help.ts +10 -0
- package/src/cli/commands/oauth/providers.ts +12 -0
- package/src/cli/commands/oauth/request.test.ts +179 -2
- package/src/cli/commands/oauth/request.ts +41 -10
- package/src/cli/commands/plugins.ts +12 -5
- package/src/cli/commands/roadmap.help.ts +18 -21
- package/src/cli/commands/roadmap.ts +4 -21
- package/src/cli/commands/schedules.ts +2 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +41 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
- package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +133 -51
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +8 -2
- package/src/cli/lib/bundled-marketplace.json +906 -1
- package/src/cli/lib/bundled-plugin-packages.json +783 -1
- package/src/cli/lib/inspect-plugin.ts +11 -4
- package/src/cli/lib/plugin-marketplace.ts +8 -0
- package/src/cli/lib/publish-plugin.ts +1 -2
- package/src/cli/lib/upgrade-plugin.ts +19 -11
- package/src/cli/output.ts +18 -4
- package/src/config/__tests__/default-provider.test.ts +6 -0
- 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/schedule/SKILL.md +6 -6
- 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/loader.ts +9 -17
- package/src/config/platform-identity.ts +8 -8
- package/src/config/profile-text-generation.test.ts +51 -0
- package/src/config/profile-text-generation.ts +51 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +12 -0
- 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 +9 -2
- package/src/config/schemas/mcp.ts +6 -1
- package/src/config/schemas/memory-retrospective.ts +11 -2
- package/src/config/schemas/memory-v3.ts +12 -0
- 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 +34 -142
- package/src/credential-execution/process-manager.test.ts +20 -24
- package/src/credential-execution/process-manager.ts +24 -19
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +43 -0
- package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +36 -0
- package/src/daemon/assistant-attachments.ts +20 -12
- package/src/daemon/browser-mode-session.test.ts +402 -0
- package/src/daemon/browser-mode-session.ts +186 -0
- package/src/daemon/chat-credential-redaction.ts +16 -1
- 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 +132 -13
- package/src/daemon/conversation-agent-loop.ts +231 -25
- package/src/daemon/conversation-attachments.ts +93 -12
- 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 +79 -6
- package/src/daemon/conversation-turn-finalize.ts +26 -13
- package/src/daemon/conversation.ts +215 -58
- package/src/daemon/daemon-control.ts +3 -7
- 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/mcp-reload-service.ts +1 -1
- package/src/daemon/message-protocol.ts +0 -1
- package/src/daemon/message-provenance.ts +28 -4
- package/src/daemon/message-types/shared.ts +1 -0
- package/src/daemon/mode-session-startup-recovery.ts +23 -0
- package/src/daemon/mode-session-tracking.ts +54 -0
- package/src/daemon/orphan-reaper.ts +4 -3
- package/src/daemon/persist-media-references.ts +20 -3
- package/src/daemon/process-message.ts +13 -4
- package/src/daemon/tool-setup-types.ts +6 -0
- package/src/daemon/virtual-desktop-context.ts +21 -0
- package/src/daemon/wake-conversation-ops.ts +50 -15
- 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 +302 -64
- package/src/desktop/desktop-automation-lease.ts +129 -54
- 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-help.ts +15 -0
- 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 +76 -132
- package/src/desktop/desktop-stream-bridge.ts +9 -11
- package/src/desktop/desktop-wallpaper-renderer.ts +132 -0
- package/src/desktop/desktop-wallpaper-worker.ts +17 -0
- package/src/desktop/desktop-wallpaper.test.ts +48 -7
- package/src/desktop/desktop-wallpaper.ts +34 -102
- package/src/desktop/desktop-window-theme.ts +5 -25
- package/src/desktop/virtual-desktop-feature.ts +53 -3
- 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 +156 -0
- package/src/mcp/__tests__/startup.test.ts +30 -7
- package/src/mcp/__tests__/tool-caps.test.ts +134 -0
- package/src/mcp/manager.ts +171 -101
- package/src/mcp/startup.ts +33 -13
- package/src/mcp/tool-caps.ts +184 -0
- 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/provider-message-metadata.ts +3 -3
- 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 +71 -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 +11 -26
- 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/schedule-result-producer.ts +4 -6
- package/src/notifications/signal.ts +4 -19
- package/src/notifications/types.ts +15 -0
- package/src/oauth/AGENTS.md +2 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +36 -1
- package/src/oauth/connection-resolver.ts +1 -2
- package/src/oauth/identity-verifier.ts +24 -0
- package/src/oauth/oauth-store.ts +12 -4
- package/src/oauth/provider-serializer.ts +8 -0
- package/src/oauth/seed-providers.ts +42 -0
- package/src/onboarding/onboarding-events-store.ts +99 -12
- package/src/permissions/confirmation-guardian-request.test.ts +16 -0
- package/src/permissions/confirmation-guardian-request.ts +2 -3
- package/src/permissions/question-prompter.test.ts +31 -0
- package/src/permissions/question-prompter.ts +2 -0
- package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
- package/src/persistence/attachments-store.ts +84 -44
- package/src/persistence/client-connection-events-store.ts +377 -0
- package/src/persistence/conversation-crud.ts +166 -26
- package/src/persistence/conversation-mode-sessions.test.ts +424 -0
- package/src/persistence/conversation-mode-sessions.ts +460 -0
- package/src/persistence/conversation-plugin-facade.ts +30 -0
- package/src/persistence/conversation-queries.ts +6 -19
- package/src/persistence/conversation-tool-surface.ts +135 -0
- package/src/persistence/conversation-types.test.ts +32 -0
- package/src/persistence/conversation-types.ts +26 -4
- package/src/persistence/llm-usage-store.ts +3 -9
- package/src/persistence/message-metadata.ts +25 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
- package/src/persistence/migrations/379-oauth-providers-response-ok-field.test.ts +92 -0
- package/src/persistence/migrations/379-oauth-providers-response-ok-field.ts +32 -0
- package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.test.ts +90 -0
- package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.ts +34 -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/conversation-tool-surfaces.ts +32 -0
- package/src/persistence/schema/conversations.ts +67 -0
- package/src/persistence/schema/index.ts +1 -0
- package/src/persistence/schema/infrastructure.ts +29 -0
- package/src/persistence/schema/oauth.ts +1 -0
- package/src/persistence/steps.ts +41 -3
- package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
- package/src/plugin-api/conversation-turn.ts +31 -7
- package/src/plugin-api/effective-context-window.ts +33 -0
- package/src/plugin-api/index.ts +35 -6
- package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
- package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
- 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/AGENTS.md +39 -5
- package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
- package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +365 -0
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
- package/src/plugins/defaults/memory/__tests__/conversation-memory-purge.test.ts +1 -0
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +2 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +74 -0
- package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
- package/src/plugins/defaults/memory/__tests__/relocated-memory-test-rows.ts +10 -0
- package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
- package/src/plugins/defaults/memory/buffer-file.ts +354 -0
- package/src/plugins/defaults/memory/buffer-format.ts +40 -0
- package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +77 -22
- package/src/plugins/defaults/memory/context-search/format.ts +53 -8
- 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/sources/memory-v2.ts +2 -1
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +2 -1
- package/src/plugins/defaults/memory/context-search/types.ts +1 -11
- package/src/plugins/defaults/memory/conversation-memory-purge.ts +4 -0
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
- package/src/plugins/defaults/memory/graph/capability-seed.ts +1 -2
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +13 -63
- package/src/plugins/defaults/memory/graph/tools.ts +35 -64
- package/src/plugins/defaults/memory/host-utils.ts +0 -10
- package/src/plugins/defaults/memory/injectors.ts +4 -3
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +72 -183
- package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
- package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +6 -1
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
- package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +2 -1
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +91 -51
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
- package/src/plugins/defaults/memory/tools.test.ts +124 -9
- package/src/plugins/defaults/memory/tools.ts +38 -11
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +2 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +2 -1
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
- package/src/plugins/defaults/memory/v2/reranker.ts +2 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
- package/src/plugins/defaults/memory/v3/__tests__/plugin-schema.test.ts +12 -0
- package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +332 -15
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +148 -28
- package/src/plugins/defaults/memory/v3/card.ts +2 -1
- package/src/plugins/defaults/memory/v3/injector.ts +212 -178
- package/src/plugins/defaults/memory/v3/orchestrate.ts +159 -32
- package/src/plugins/defaults/memory/v3/plugin-schema.ts +54 -4
- package/src/plugins/defaults/memory/v3/pool-log-store.ts +275 -37
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +47 -5
- package/src/plugins/defaults/memory/v3/pool-select.ts +710 -59
- package/src/plugins/defaults/memory/v3/sections.ts +2 -1
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +41 -14
- 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/plugins/defaults/tool-error/hooks/post-tool-use.ts +4 -1
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
- package/src/prompts/__tests__/parallel-tasks-section.test.ts +25 -0
- package/src/prompts/delegation-gate.ts +57 -0
- package/src/prompts/system-prompt.ts +14 -32
- 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 +6 -0
- package/src/providers/jev/client.test.ts +270 -0
- package/src/providers/jev/client.ts +534 -0
- package/src/providers/model-catalog.ts +59 -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/server-tool-pairing.ts +16 -7
- 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 +6 -4
- package/src/runtime/__tests__/agent-wake.test.ts +94 -1
- package/src/runtime/actor-trust-resolver.ts +3 -3
- package/src/runtime/agent-wake.ts +32 -5
- 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-action-service.ts +2 -17
- package/src/runtime/guardian-reply-router.ts +29 -40
- package/src/runtime/http-server.ts +2 -2
- 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/__tests__/vbundle-import-policy.test.ts +89 -0
- 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 +43 -11
- 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 +24 -2
- 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/channel-route-shared.ts +1 -9
- 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 +125 -14
- 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 +8 -7
- 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/guardian-approval-interception.ts +24 -0
- 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 +37 -41
- 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 +39 -10
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +9 -9
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +11 -1
- package/src/runtime/routes/inference-profiles-routes.ts +9 -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-commands-routes.ts +57 -54
- package/src/runtime/routes/oauth-providers.ts +11 -0
- package/src/runtime/routes/oauth-request-hints.test.ts +246 -0
- package/src/runtime/routes/oauth-request-hints.ts +149 -0
- package/src/runtime/routes/plugins-routes.ts +6 -0
- package/src/runtime/routes/roadmap-routes.ts +47 -8
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/secret-routes.ts +99 -119
- 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/__tests__/worker-mcp-bootstrap.test.ts +107 -0
- package/src/schedule/__tests__/worker-mcp-readiness.test.ts +173 -0
- package/src/schedule/__tests__/worker-mcp-tools.test.ts +13 -47
- package/src/schedule/run-script.ts +2 -2
- package/src/schedule/scheduler.ts +47 -11
- package/src/schedule/tool-surface-readiness.ts +65 -0
- package/src/schedule/worker-control.ts +15 -5
- package/src/schedule/worker-mcp.ts +85 -0
- package/src/schedule/worker.ts +9 -31
- package/src/security/secure-keys.ts +74 -112
- 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.test.ts +167 -5
- package/src/tools/ask-question/ask-question-tool.ts +120 -22
- package/src/tools/browser/browser-execution.ts +29 -60
- 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 +16 -7
- 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/shared/filesystem/file-ops-service.ts +1 -31
- package/src/tools/shared/shell-output.test.ts +10 -0
- package/src/tools/shared/shell-output.ts +14 -2
- package/src/tools/skills/load.ts +2 -1
- package/src/tools/skills/sandbox-runner.ts +24 -4
- package/src/tools/skills/scaffold-managed.ts +2 -1
- 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 +44 -4
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -14
- package/src/tools/terminal/safe-env.ts +39 -24
- package/src/tools/terminal/sanitized-bash.ts +15 -2
- package/src/tools/terminal/shell-launch.test.ts +162 -0
- package/src/tools/terminal/shell.test.ts +29 -0
- package/src/tools/terminal/shell.ts +15 -7
- 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/browser-human-verification.ts +14 -0
- 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/host-process.test.ts +17 -1
- package/src/util/host-process.ts +24 -0
- package/src/util/provider-error-patterns.ts +3 -0
- package/src/util/unicode.ts +29 -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
|
@@ -173,15 +173,22 @@ export function memoryV3TurnMemoSizeForTests(): number {
|
|
|
173
173
|
return observedTurns.size;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
/** What the turn still got when the selector could not run: nothing (the
|
|
177
|
+
* orchestration itself failed) or the stable prefix unjudged. */
|
|
178
|
+
type MemoryV3DegradedScope = "none" | "stable-prefix";
|
|
179
|
+
|
|
176
180
|
function queueMemoryV3ConversationNotice(
|
|
177
181
|
err: MemoryV3RetrievalUnavailableError,
|
|
178
182
|
ctx: TurnContext,
|
|
183
|
+
scope: MemoryV3DegradedScope,
|
|
179
184
|
): void {
|
|
180
185
|
const notice: PendingConversationNotice = err.conversationNotice ?? {
|
|
181
186
|
source: "memory_v3",
|
|
182
187
|
code: "UNKNOWN",
|
|
183
188
|
userMessage:
|
|
184
|
-
|
|
189
|
+
scope === "stable-prefix"
|
|
190
|
+
? "Memory selection is temporarily unavailable, so this response draws only on your core memories. You can retry in a moment."
|
|
191
|
+
: "Memory is temporarily unavailable, so this response may not use your saved memories. You can retry in a moment.",
|
|
185
192
|
errorCategory: "memory_v3_degraded",
|
|
186
193
|
};
|
|
187
194
|
queueConversationNotice(
|
|
@@ -324,7 +331,7 @@ export const memoryV3Injector: Injector = {
|
|
|
324
331
|
observed = await observeTurnOnce(ctx.conversationId, ctx.turnIndex);
|
|
325
332
|
} catch (err) {
|
|
326
333
|
if (err instanceof MemoryV3RetrievalUnavailableError) {
|
|
327
|
-
queueMemoryV3ConversationNotice(err, ctx);
|
|
334
|
+
queueMemoryV3ConversationNotice(err, ctx, "none");
|
|
328
335
|
log.error(
|
|
329
336
|
{
|
|
330
337
|
err: err.message,
|
|
@@ -336,194 +343,221 @@ export const memoryV3Injector: Injector = {
|
|
|
336
343
|
}
|
|
337
344
|
return null;
|
|
338
345
|
}
|
|
339
|
-
|
|
340
|
-
// hook skipped v2 retrieval under live, so a turn with nothing selected
|
|
341
|
-
// simply gets no v3 `<memory>` block (prior turns' frozen sections still
|
|
342
|
-
// ride history).
|
|
343
|
-
if (!observed || observed.selections.length === 0) {
|
|
346
|
+
if (!observed) {
|
|
344
347
|
return null;
|
|
345
348
|
}
|
|
346
|
-
|
|
347
|
-
//
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
// entry the first produce rendered is re-emitted from the memo byte
|
|
358
|
-
// for byte: the store counts it active, but its only copy rode the
|
|
359
|
-
// tail the re-injection strip cleared, so the store alone would
|
|
360
|
-
// read it as resident and drop it for the rest of the turn. A
|
|
361
|
-
// re-entry block carries no commit (and runtime assembly withholds
|
|
362
|
-
// one on a `reinjection` assembly besides), so a turn's sections
|
|
363
|
-
// are recorded once, at the first-call site; after a compaction they
|
|
364
|
-
// stay unclaimed until the next turn injects them net-new onto its
|
|
365
|
-
// own persisted message, and the newest-copy rule
|
|
366
|
-
// (`stripPrunedSectionsFromMessages`) retires the re-entry copy.
|
|
367
|
-
// - A pair active in the store is resident: a pointer entry, stamped
|
|
368
|
-
// with the turn's selection time below. Capability slugs are
|
|
369
|
-
// stamped too but left out of the pointer (no `memory/concepts/`
|
|
370
|
-
// path to point at).
|
|
371
|
-
// - Every other pair renders net-new, including one the first produce
|
|
372
|
-
// saw resident whose copy a compaction's store reset has since
|
|
373
|
-
// unclaimed (neither active nor tombstoned), in memory only.
|
|
374
|
-
// Under a run-messages replacement (`ctx.replacesRunMessages`: the
|
|
375
|
-
// Slack chronological transcript, rendered from persisted rows, so it
|
|
376
|
-
// carries no earlier turn's block) residency means nothing. The
|
|
377
|
-
// store's active set is not consulted, every pair renders or
|
|
378
|
-
// re-emits, none is pointed at, and the block carries no commit, so
|
|
379
|
-
// nothing is recorded or scheduled and runtime assembly attaches the
|
|
380
|
-
// block in memory only as the prompt's single copy. A Slack
|
|
381
|
-
// conversation whose transcript injector is absent is not replaced and
|
|
382
|
-
// injects as an ordinary committed turn.
|
|
383
|
-
const rendered = observedTurn(
|
|
384
|
-
ctx.conversationId,
|
|
385
|
-
ctx.turnIndex,
|
|
386
|
-
)?.rendered;
|
|
387
|
-
const firstProduce = rendered === undefined;
|
|
388
|
-
const replaced = ctx.replacesRunMessages === true;
|
|
389
|
-
const active = replaced ? null : getActiveSections(ctx.conversationId);
|
|
390
|
-
const pruned = firstProduce
|
|
391
|
-
? undefined
|
|
392
|
-
: getPrunedSections(ctx.conversationId);
|
|
393
|
-
const resident: SectionRef[] = [];
|
|
394
|
-
const slots: BlockSlot[] = [];
|
|
395
|
-
for (const { slug, key, matched } of injectionUnits(result.selections)) {
|
|
396
|
-
if (pruned && sectionRefSetHas(pruned, slug, key)) {
|
|
397
|
-
continue;
|
|
398
|
-
}
|
|
399
|
-
const reemitted = rendered?.get(slug)?.get(key);
|
|
400
|
-
if (reemitted !== undefined) {
|
|
401
|
-
slots.push({ slug, key, matched, text: reemitted });
|
|
402
|
-
continue;
|
|
403
|
-
}
|
|
404
|
-
if (active && sectionRefSetHas(active, slug, key)) {
|
|
405
|
-
resident.push({ slug, key });
|
|
406
|
-
continue;
|
|
407
|
-
}
|
|
408
|
-
slots.push({ slug, key, matched, text: undefined });
|
|
409
|
-
}
|
|
410
|
-
rememberPointerEntries(
|
|
411
|
-
ctx.conversationId,
|
|
412
|
-
ctx.turnIndex,
|
|
413
|
-
resident.filter(({ slug }) => !isCapabilitySlug(slug)),
|
|
349
|
+
const block = await renderSelections(ctx, observed);
|
|
350
|
+
// A selector that could not run left the stable prefix unjudged in
|
|
351
|
+
// `selections`. The person is told what this turn drew on only once the
|
|
352
|
+
// render is known: the prefix when a block carries it (an empty-text
|
|
353
|
+
// block means the sections already ride history), nothing when no block
|
|
354
|
+
// attaches.
|
|
355
|
+
if (observed.selectorFailure) {
|
|
356
|
+
queueMemoryV3ConversationNotice(
|
|
357
|
+
observed.selectorFailure,
|
|
358
|
+
ctx,
|
|
359
|
+
block === null ? "none" : "stable-prefix",
|
|
414
360
|
);
|
|
415
|
-
// The turn's selection time, stamped on the resident pairs NOW, in the
|
|
416
|
-
// same synchronous segment as the classification above: the page reads
|
|
417
|
-
// below yield to the event loop, and a prune valve queued by an earlier
|
|
418
|
-
// turn's commit fires on a timer, so it can run while they are awaited
|
|
419
|
-
// and would otherwise rank a pair this turn is about by its stale
|
|
420
|
-
// stamp and evict it. The stamp is a recency bump, not a claim, so a
|
|
421
|
-
// turn whose block never attaches (or that returns null below because
|
|
422
|
-
// every net-new pair rendered empty) bumps harmlessly. Only the first
|
|
423
|
-
// produce stamps: a re-entry re-emits the turn's selections, and a
|
|
424
|
-
// run-messages replacement claims nothing (`resident` is empty there).
|
|
425
|
-
// The net-new pairs take the same time with their record in the commit.
|
|
426
|
-
const selectedAt = Date.now();
|
|
427
|
-
if (firstProduce) {
|
|
428
|
-
touchSelected(ctx.conversationId, resident, selectedAt);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// Render net-new sections (each an independent page read, so in
|
|
432
|
-
// parallel), skipping pairs that resolve to no content (deleted pages,
|
|
433
|
-
// unresolvable capabilities, empty sections): nothing is attached for
|
|
434
|
-
// them, so nothing is recorded either.
|
|
435
|
-
const netNew = slots.filter((slot) => slot.text === undefined);
|
|
436
|
-
const renderedNow = await Promise.all(
|
|
437
|
-
netNew.map(({ slug, matched }) =>
|
|
438
|
-
renderV3InjectionEntry(slug, matched),
|
|
439
|
-
),
|
|
440
|
-
);
|
|
441
|
-
for (const [i, slot] of netNew.entries()) {
|
|
442
|
-
slot.text = renderedNow[i]!;
|
|
443
|
-
}
|
|
444
|
-
const entries: Array<SectionRef & { text: string }> = [];
|
|
445
|
-
for (const { slug, key, text } of slots) {
|
|
446
|
-
if (text !== undefined && text.trim().length > 0) {
|
|
447
|
-
entries.push({ slug, key, text });
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
// Every net-new section rendered empty: return null rather than an
|
|
451
|
-
// empty-text block. Under live there is no v2 block, so the turn simply
|
|
452
|
-
// gets no new memory. Distinct from the all-repeat case (empty
|
|
453
|
-
// `netNew`), where the empty block correctly keeps v2 suppressed
|
|
454
|
-
// because the sections already ride history.
|
|
455
|
-
if (netNew.length > 0 && entries.length === 0) {
|
|
456
|
-
return null;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Empty net-new → empty-text block: assembly attaches no content
|
|
460
|
-
// (`applyInjectionBlock` no-ops empty text) but the block's presence
|
|
461
|
-
// still marks v3 as this turn's `<memory>` source for v2 suppression.
|
|
462
|
-
const inner = renderInjectionBlockInner(entries.map((e) => e.text));
|
|
463
|
-
const block: InjectionBlock = {
|
|
464
|
-
id: MEMORY_V3_BLOCK_ID,
|
|
465
|
-
text: inner.length === 0 ? "" : wrapMemoryBlock(inner),
|
|
466
|
-
// Mirror v2's dynamic `<memory>` block placement.
|
|
467
|
-
placement: "after-memory-prefix",
|
|
468
|
-
};
|
|
469
|
-
if (!firstProduce) {
|
|
470
|
-
return block;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
rememberRendered(ctx.conversationId, ctx.turnIndex, entries);
|
|
474
|
-
// A block rendered for a run-messages replacement rides that prompt
|
|
475
|
-
// only: no copy of it persists, so the store must not claim its
|
|
476
|
-
// sections and the valve has nothing new to account for.
|
|
477
|
-
if (replaced) {
|
|
478
|
-
return block;
|
|
479
|
-
}
|
|
480
|
-
// The net-new record and the prune-valve schedule are DEFERRED to this
|
|
481
|
-
// commit callback, invoked by runtime assembly at the point where
|
|
482
|
-
// attachment is guaranteed (the turn's tail is a user message, the
|
|
483
|
-
// same gate as metadata capture). Recording here in `produce()` would
|
|
484
|
-
// let a never-attached turn (non-user tail) claim sections in the
|
|
485
|
-
// store, suppressing them until compaction. Only the turn's first
|
|
486
|
-
// produce carries it: a re-entry block re-emits what this one rendered
|
|
487
|
-
// and is never persisted, so it must not record anything. The valve is
|
|
488
|
-
// scheduled after the record so the resident accounting, and the
|
|
489
|
-
// recency it ranks by, include this turn's sections (the resident
|
|
490
|
-
// pairs carry their stamp from the classification above); it evicts by
|
|
491
|
-
// recency with no lane exemptions. It runs on a timer, so this turn's
|
|
492
|
-
// block may not have folded back into the live history when it strips;
|
|
493
|
-
// a section it prunes from this very turn is stripped by assembly Step
|
|
494
|
-
// 0 on the next turn, which applies the store's full tombstone set
|
|
495
|
-
// every turn.
|
|
496
|
-
const commit = (): void => {
|
|
497
|
-
recordInjected(
|
|
498
|
-
ctx.conversationId,
|
|
499
|
-
entries.map(({ slug, key, text }) => ({
|
|
500
|
-
slug,
|
|
501
|
-
key,
|
|
502
|
-
// Capability content (skills / CLI commands) renders with its own
|
|
503
|
-
// `# Skill:` / `# CLI command:` header, which the prune valve's
|
|
504
|
-
// section grammar can never locate to free. Record it at zero
|
|
505
|
-
// bytes so it never inflates the freeable resident accounting
|
|
506
|
-
// (the valve would otherwise loop-fire on bytes it cannot free).
|
|
507
|
-
bytes: isCapabilitySlug(slug) ? 0 : renderedBytes(text),
|
|
508
|
-
})),
|
|
509
|
-
selectedAt,
|
|
510
|
-
);
|
|
511
|
-
schedulePruneValve(ctx.conversationId);
|
|
512
|
-
};
|
|
513
|
-
return { ...block, meta: { [MEMORY_V3_COMMIT_META_KEY]: commit } };
|
|
514
|
-
} catch (err) {
|
|
515
361
|
log.warn(
|
|
516
362
|
{
|
|
517
|
-
err:
|
|
363
|
+
err: observed.selectorFailure.message,
|
|
518
364
|
conversationId: ctx.conversationId,
|
|
365
|
+
stableCount: observed.selections.length,
|
|
366
|
+
attached: block !== null,
|
|
367
|
+
mode: "live",
|
|
519
368
|
},
|
|
520
|
-
"memory-v3
|
|
369
|
+
"memory-v3 selector unavailable; the stable prefix stands in unjudged",
|
|
521
370
|
);
|
|
522
|
-
return null;
|
|
523
371
|
}
|
|
372
|
+
return block;
|
|
524
373
|
},
|
|
525
374
|
};
|
|
526
375
|
|
|
376
|
+
/**
|
|
377
|
+
* Render a turn's selections into its `<memory>` block, or `null` when the
|
|
378
|
+
* turn attaches nothing: an empty selection (the user-prompt-submit hook
|
|
379
|
+
* skipped v2 retrieval under live, so the turn simply gets no v3 block while
|
|
380
|
+
* prior turns' frozen sections still ride history), every net-new section
|
|
381
|
+
* rendering empty, or a render failure (non-fatal, logged).
|
|
382
|
+
*/
|
|
383
|
+
async function renderSelections(
|
|
384
|
+
ctx: TurnContext,
|
|
385
|
+
result: OrchestrateResult,
|
|
386
|
+
): Promise<InjectionBlock | null> {
|
|
387
|
+
if (result.selections.length === 0) {
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
// Partition this turn's injection units: each selected section under
|
|
392
|
+
// its own key, a page selected with none under `""` (its lead;
|
|
393
|
+
// capability content injects whole under `""` too).
|
|
394
|
+
// - A pair tombstoned since the turn's first produce is skipped: a
|
|
395
|
+
// re-entry never revives what the valve pruned.
|
|
396
|
+
// - On a re-entry assembly (`rendered` set by the first produce) an
|
|
397
|
+
// entry the first produce rendered is re-emitted from the memo byte
|
|
398
|
+
// for byte: the store counts it active, but its only copy rode the
|
|
399
|
+
// tail the re-injection strip cleared, so the store alone would
|
|
400
|
+
// read it as resident and drop it for the rest of the turn. A
|
|
401
|
+
// re-entry block carries no commit (and runtime assembly withholds
|
|
402
|
+
// one on a `reinjection` assembly besides), so a turn's sections
|
|
403
|
+
// are recorded once, at the first-call site; after a compaction they
|
|
404
|
+
// stay unclaimed until the next turn injects them net-new onto its
|
|
405
|
+
// own persisted message, and the newest-copy rule
|
|
406
|
+
// (`stripPrunedSectionsFromMessages`) retires the re-entry copy.
|
|
407
|
+
// - A pair active in the store is resident: a pointer entry, stamped
|
|
408
|
+
// with the turn's selection time below. Capability slugs are
|
|
409
|
+
// stamped too but left out of the pointer (no `memory/concepts/`
|
|
410
|
+
// path to point at).
|
|
411
|
+
// - Every other pair renders net-new, including one the first produce
|
|
412
|
+
// saw resident whose copy a compaction's store reset has since
|
|
413
|
+
// unclaimed (neither active nor tombstoned), in memory only.
|
|
414
|
+
// Under a run-messages replacement (`ctx.replacesRunMessages`: the
|
|
415
|
+
// Slack chronological transcript, rendered from persisted rows, so it
|
|
416
|
+
// carries no earlier turn's block) residency means nothing. The
|
|
417
|
+
// store's active set is not consulted, every pair renders or
|
|
418
|
+
// re-emits, none is pointed at, and the block carries no commit, so
|
|
419
|
+
// nothing is recorded or scheduled and runtime assembly attaches the
|
|
420
|
+
// block in memory only as the prompt's single copy. A Slack
|
|
421
|
+
// conversation whose transcript injector is absent is not replaced and
|
|
422
|
+
// injects as an ordinary committed turn.
|
|
423
|
+
const rendered = observedTurn(ctx.conversationId, ctx.turnIndex)?.rendered;
|
|
424
|
+
const firstProduce = rendered === undefined;
|
|
425
|
+
const replaced = ctx.replacesRunMessages === true;
|
|
426
|
+
const active = replaced ? null : getActiveSections(ctx.conversationId);
|
|
427
|
+
const pruned = firstProduce
|
|
428
|
+
? undefined
|
|
429
|
+
: getPrunedSections(ctx.conversationId);
|
|
430
|
+
const resident: SectionRef[] = [];
|
|
431
|
+
const slots: BlockSlot[] = [];
|
|
432
|
+
for (const { slug, key, matched } of injectionUnits(result.selections)) {
|
|
433
|
+
if (pruned && sectionRefSetHas(pruned, slug, key)) {
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
const reemitted = rendered?.get(slug)?.get(key);
|
|
437
|
+
if (reemitted !== undefined) {
|
|
438
|
+
slots.push({ slug, key, matched, text: reemitted });
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
if (active && sectionRefSetHas(active, slug, key)) {
|
|
442
|
+
resident.push({ slug, key });
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
slots.push({ slug, key, matched, text: undefined });
|
|
446
|
+
}
|
|
447
|
+
rememberPointerEntries(
|
|
448
|
+
ctx.conversationId,
|
|
449
|
+
ctx.turnIndex,
|
|
450
|
+
resident.filter(({ slug }) => !isCapabilitySlug(slug)),
|
|
451
|
+
);
|
|
452
|
+
// The turn's selection time, stamped on the resident pairs NOW, in the
|
|
453
|
+
// same synchronous segment as the classification above: the page reads
|
|
454
|
+
// below yield to the event loop, and a prune valve queued by an earlier
|
|
455
|
+
// turn's commit fires on a timer, so it can run while they are awaited
|
|
456
|
+
// and would otherwise rank a pair this turn is about by its stale
|
|
457
|
+
// stamp and evict it. The stamp is a recency bump, not a claim, so a
|
|
458
|
+
// turn whose block never attaches (or that returns null below because
|
|
459
|
+
// every net-new pair rendered empty) bumps harmlessly. Only the first
|
|
460
|
+
// produce stamps: a re-entry re-emits the turn's selections, and a
|
|
461
|
+
// run-messages replacement claims nothing (`resident` is empty there).
|
|
462
|
+
// The net-new pairs take the same time with their record in the commit.
|
|
463
|
+
const selectedAt = Date.now();
|
|
464
|
+
if (firstProduce) {
|
|
465
|
+
touchSelected(ctx.conversationId, resident, selectedAt);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Render net-new sections (each an independent page read, so in
|
|
469
|
+
// parallel), skipping pairs that resolve to no content (deleted pages,
|
|
470
|
+
// unresolvable capabilities, empty sections): nothing is attached for
|
|
471
|
+
// them, so nothing is recorded either.
|
|
472
|
+
const netNew = slots.filter((slot) => slot.text === undefined);
|
|
473
|
+
const renderedNow = await Promise.all(
|
|
474
|
+
netNew.map(({ slug, matched }) => renderV3InjectionEntry(slug, matched)),
|
|
475
|
+
);
|
|
476
|
+
for (const [i, slot] of netNew.entries()) {
|
|
477
|
+
slot.text = renderedNow[i]!;
|
|
478
|
+
}
|
|
479
|
+
const entries: Array<SectionRef & { text: string }> = [];
|
|
480
|
+
for (const { slug, key, text } of slots) {
|
|
481
|
+
if (text !== undefined && text.trim().length > 0) {
|
|
482
|
+
entries.push({ slug, key, text });
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
// Every net-new section rendered empty: return null rather than an
|
|
486
|
+
// empty-text block. Under live there is no v2 block, so the turn simply
|
|
487
|
+
// gets no new memory. Distinct from the all-repeat case (empty
|
|
488
|
+
// `netNew`), where the empty block correctly keeps v2 suppressed
|
|
489
|
+
// because the sections already ride history.
|
|
490
|
+
if (netNew.length > 0 && entries.length === 0) {
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Empty net-new → empty-text block: assembly attaches no content
|
|
495
|
+
// (`applyInjectionBlock` no-ops empty text) but the block's presence
|
|
496
|
+
// still marks v3 as this turn's `<memory>` source for v2 suppression.
|
|
497
|
+
const inner = renderInjectionBlockInner(entries.map((e) => e.text));
|
|
498
|
+
const block: InjectionBlock = {
|
|
499
|
+
id: MEMORY_V3_BLOCK_ID,
|
|
500
|
+
text: inner.length === 0 ? "" : wrapMemoryBlock(inner),
|
|
501
|
+
// Mirror v2's dynamic `<memory>` block placement.
|
|
502
|
+
placement: "after-memory-prefix",
|
|
503
|
+
};
|
|
504
|
+
if (!firstProduce) {
|
|
505
|
+
return block;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
rememberRendered(ctx.conversationId, ctx.turnIndex, entries);
|
|
509
|
+
// A block rendered for a run-messages replacement rides that prompt
|
|
510
|
+
// only: no copy of it persists, so the store must not claim its
|
|
511
|
+
// sections and the valve has nothing new to account for.
|
|
512
|
+
if (replaced) {
|
|
513
|
+
return block;
|
|
514
|
+
}
|
|
515
|
+
// The net-new record and the prune-valve schedule are DEFERRED to this
|
|
516
|
+
// commit callback, invoked by runtime assembly at the point where
|
|
517
|
+
// attachment is guaranteed (the turn's tail is a user message, the
|
|
518
|
+
// same gate as metadata capture). Recording here in `produce()` would
|
|
519
|
+
// let a never-attached turn (non-user tail) claim sections in the
|
|
520
|
+
// store, suppressing them until compaction. Only the turn's first
|
|
521
|
+
// produce carries it: a re-entry block re-emits what this one rendered
|
|
522
|
+
// and is never persisted, so it must not record anything. The valve is
|
|
523
|
+
// scheduled after the record so the resident accounting, and the
|
|
524
|
+
// recency it ranks by, include this turn's sections (the resident
|
|
525
|
+
// pairs carry their stamp from the classification above); it evicts by
|
|
526
|
+
// recency with no lane exemptions. It runs on a timer, so this turn's
|
|
527
|
+
// block may not have folded back into the live history when it strips;
|
|
528
|
+
// a section it prunes from this very turn is stripped by assembly Step
|
|
529
|
+
// 0 on the next turn, which applies the store's full tombstone set
|
|
530
|
+
// every turn.
|
|
531
|
+
const commit = (): void => {
|
|
532
|
+
recordInjected(
|
|
533
|
+
ctx.conversationId,
|
|
534
|
+
entries.map(({ slug, key, text }) => ({
|
|
535
|
+
slug,
|
|
536
|
+
key,
|
|
537
|
+
// Capability content (skills / CLI commands) renders with its own
|
|
538
|
+
// `# Skill:` / `# CLI command:` header, which the prune valve's
|
|
539
|
+
// section grammar can never locate to free. Record it at zero
|
|
540
|
+
// bytes so it never inflates the freeable resident accounting
|
|
541
|
+
// (the valve would otherwise loop-fire on bytes it cannot free).
|
|
542
|
+
bytes: isCapabilitySlug(slug) ? 0 : renderedBytes(text),
|
|
543
|
+
})),
|
|
544
|
+
selectedAt,
|
|
545
|
+
);
|
|
546
|
+
schedulePruneValve(ctx.conversationId);
|
|
547
|
+
};
|
|
548
|
+
return { ...block, meta: { [MEMORY_V3_COMMIT_META_KEY]: commit } };
|
|
549
|
+
} catch (err) {
|
|
550
|
+
log.warn(
|
|
551
|
+
{
|
|
552
|
+
err: err instanceof Error ? err.message : String(err),
|
|
553
|
+
conversationId: ctx.conversationId,
|
|
554
|
+
},
|
|
555
|
+
"memory-v3 live render failed (non-fatal) — returning null (no v3 block this turn)",
|
|
556
|
+
);
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
527
561
|
export const memoryV3PointerInjector: Injector = {
|
|
528
562
|
name: "memory-v3-pointer",
|
|
529
563
|
// After the sections injector, whose produce records the resident
|