@vellumai/assistant 0.8.6 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -4
- package/Dockerfile +1 -0
- package/bun.lock +11 -2
- package/docker-entrypoint.sh +8 -6
- package/docs/plugins.md +63 -28
- package/examples/plugins/echo/register.ts +4 -7
- package/knip.json +1 -0
- package/node_modules/@vellumai/environments/bun.lock +24 -0
- package/node_modules/@vellumai/environments/package.json +18 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
- package/node_modules/@vellumai/environments/src/index.ts +11 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
- package/node_modules/@vellumai/environments/src/types.ts +70 -0
- package/node_modules/@vellumai/environments/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +6 -2
- package/openapi.yaml +3735 -353
- package/package.json +7 -3
- package/scripts/generate-openapi.ts +20 -13
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
- package/src/__tests__/agent-loop-exit-reason.test.ts +240 -39
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +6 -4
- package/src/__tests__/agent-loop-thinking.test.ts +17 -12
- package/src/__tests__/agent-loop.test.ts +207 -341
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +4 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
- package/src/__tests__/anthropic-provider.test.ts +201 -55
- package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
- package/src/__tests__/app-control-flow.test.ts +5 -0
- package/src/__tests__/approval-cascade.test.ts +4 -11
- package/src/__tests__/approval-routes-http.test.ts +4 -2
- package/src/__tests__/assistant-event.test.ts +15 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +7 -37
- package/src/__tests__/avatar-generator.test.ts +12 -42
- package/src/__tests__/avatar-identity-sync.test.ts +28 -3
- package/src/__tests__/background-shell-bash.test.ts +3 -7
- package/src/__tests__/btw-routes.test.ts +7 -12
- package/src/__tests__/call-pointer-messages.test.ts +5 -3
- package/src/__tests__/call-site-routing-provider.test.ts +22 -40
- package/src/__tests__/catalog-files.test.ts +1 -0
- package/src/__tests__/channel-approval-routes.test.ts +48 -20
- package/src/__tests__/channel-approvals.test.ts +3 -1
- package/src/__tests__/channel-invite-transport.test.ts +1 -5
- package/src/__tests__/channel-readiness-routes.test.ts +0 -4
- package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
- package/src/__tests__/channel-retry-sweep.test.ts +71 -79
- package/src/__tests__/circuit-breaker-pipeline.test.ts +3 -3
- package/src/__tests__/clawhub-files.test.ts +1 -0
- package/src/__tests__/compaction-events.test.ts +5 -17
- package/src/__tests__/compaction-pipeline.test.ts +1 -1
- package/src/__tests__/compaction-timeout-recovery.test.ts +37 -48
- package/src/__tests__/compaction-trail-store.test.ts +1 -79
- package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
- package/src/__tests__/computer-use-tools.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +28 -0
- package/src/__tests__/context-search-agent-runner.test.ts +6 -3
- package/src/__tests__/context-token-estimator.test.ts +34 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +14 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +12 -27
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +430 -90
- package/src/__tests__/conversation-agent-loop.test.ts +581 -62
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clear-safety.test.ts +20 -10
- package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-disk-view.test.ts +10 -17
- package/src/__tests__/conversation-fork-crud.test.ts +86 -172
- package/src/__tests__/conversation-fork-route.test.ts +16 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
- package/src/__tests__/conversation-lifecycle.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
- package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
- package/src/__tests__/conversation-pairing.test.ts +34 -4
- package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -0
- package/src/__tests__/conversation-process-callsite.test.ts +27 -30
- package/src/__tests__/conversation-provider-retry-repair.test.ts +53 -44
- package/src/__tests__/conversation-queue.test.ts +270 -164
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -2
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +20 -22
- package/src/__tests__/conversation-runtime-workspace.test.ts +19 -1
- package/src/__tests__/conversation-slash-queue.test.ts +37 -31
- package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
- package/src/__tests__/conversation-speed-override.test.ts +8 -22
- package/src/__tests__/conversation-stream-state.test.ts +484 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +6 -15
- package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
- package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
- package/src/__tests__/conversation-unread-route.test.ts +14 -2
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-wipe.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +3 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +48 -22
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +27 -7
- package/src/__tests__/credential-execution-tools.test.ts +1 -2
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/cross-provider-web-search.test.ts +6 -2
- package/src/__tests__/cu-unified-flow.test.ts +26 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +11 -0
- package/src/__tests__/disk-pressure-guard.test.ts +66 -0
- package/src/__tests__/disk-pressure-routes.test.ts +9 -2
- package/src/__tests__/dm-persistence.test.ts +7 -2
- package/src/__tests__/dynamic-page-surface.test.ts +68 -0
- package/src/__tests__/edit-propagation.test.ts +1 -2
- package/src/__tests__/empty-response-pipeline.test.ts +127 -5
- package/src/__tests__/filing-service.test.ts +2 -2
- package/src/__tests__/first-greeting.test.ts +55 -14
- package/src/__tests__/gemini-inline-media.test.ts +78 -0
- package/src/__tests__/gemini-provider.test.ts +351 -28
- package/src/__tests__/guardian-routing-state.test.ts +60 -71
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +9 -7
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +2 -1
- package/src/__tests__/history-repair-hook.test.ts +161 -0
- package/src/__tests__/history-repair-observability.test.ts +1 -1
- package/src/__tests__/history-repair.test.ts +2 -1
- package/src/__tests__/host-app-control-proxy.test.ts +2 -0
- package/src/__tests__/host-cu-proxy.test.ts +2 -0
- package/src/__tests__/host-file-edit-tool.test.ts +4 -2
- package/src/__tests__/host-file-proxy.test.ts +31 -0
- package/src/__tests__/host-file-read-tool.test.ts +4 -2
- package/src/__tests__/host-file-write-tool.test.ts +9 -3
- package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
- package/src/__tests__/host-shell-tool.test.ts +9 -4
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/identity-intro-cache.test.ts +35 -14
- package/src/__tests__/inbound-slack-persistence.test.ts +7 -2
- package/src/__tests__/injector-background-turn.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-disk-pressure.test.ts +1 -1
- package/src/__tests__/injector-document-comments.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +1 -1
- package/src/__tests__/injector-v3-suppression.test.ts +220 -0
- package/src/__tests__/list-messages-attachments.test.ts +7 -8
- package/src/__tests__/list-messages-hidden-metadata.test.ts +17 -15
- package/src/__tests__/list-messages-page-latest.test.ts +0 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +36 -6
- package/src/__tests__/llm-call-pipeline.test.ts +21 -15
- package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
- package/src/__tests__/llm-resolver.test.ts +23 -47
- package/src/__tests__/llm-usage-store.test.ts +45 -0
- package/src/__tests__/log-export-routes.test.ts +59 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
- package/src/__tests__/mcp-auth-routes.test.ts +15 -10
- package/src/__tests__/mcp-health-check.test.ts +18 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +1 -1
- package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +8 -4
- package/src/__tests__/migration-export-http.test.ts +12 -12
- package/src/__tests__/migration-import-commit-http.test.ts +8 -8
- package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +14 -20
- package/src/__tests__/notification-decision-identity.test.ts +9 -18
- package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
- package/src/__tests__/oauth-commands-routes.test.ts +1 -1
- package/src/__tests__/onboarding-template-contract.test.ts +10 -0
- package/src/__tests__/openai-provider.test.ts +66 -70
- package/src/__tests__/openai-responses-provider.test.ts +21 -77
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
- package/src/__tests__/overflow-reduce-pipeline.test.ts +2 -4
- package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
- package/src/__tests__/persistence-pipeline.test.ts +15 -26
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -1
- package/src/__tests__/pipeline-runner.test.ts +2 -3
- package/src/__tests__/plugin-bootstrap.test.ts +51 -25
- package/src/__tests__/plugin-route-contribution.test.ts +6 -16
- package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
- package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
- package/src/__tests__/plugin-types.test.ts +7 -14
- package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
- package/src/__tests__/process-message-background-slack.test.ts +17 -16
- package/src/__tests__/process-message-display-content.test.ts +30 -42
- package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
- package/src/__tests__/provider-error-scenarios.test.ts +7 -6
- package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
- package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
- package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
- package/src/__tests__/provider-usage-tracking.test.ts +0 -6
- package/src/__tests__/ratelimit.test.ts +9 -4
- package/src/__tests__/relay-server.test.ts +20 -13
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
- package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
- package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +353 -0
- package/src/__tests__/schedule-routes.test.ts +80 -10
- package/src/__tests__/schedule-store.test.ts +67 -0
- package/src/__tests__/schedule-tools.test.ts +125 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
- package/src/__tests__/secret-response-routing.test.ts +13 -11
- package/src/__tests__/send-endpoint-busy.test.ts +2 -1
- package/src/__tests__/shell-observability.test.ts +249 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +11 -11
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
- package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
- package/src/__tests__/skillssh-files.test.ts +1 -0
- package/src/__tests__/starter-task-flow.test.ts +6 -6
- package/src/__tests__/strip-memory-injections.test.ts +102 -14
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +19 -16
- package/src/__tests__/system-prompt.test.ts +54 -0
- package/src/__tests__/terminal-tools.test.ts +3 -24
- package/src/__tests__/thread-backfill.test.ts +4 -9
- package/src/__tests__/title-generate-pipeline.test.ts +1 -1
- package/src/__tests__/token-estimate-pipeline.test.ts +2 -4
- package/src/__tests__/tool-error-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execute-pipeline.test.ts +1 -1
- package/src/__tests__/tool-preview-lifecycle.test.ts +13 -11
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +9 -12
- package/src/__tests__/tool-result-truncation.test.ts +3 -1
- package/src/__tests__/tools-audio-read.test.ts +113 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
- package/src/__tests__/turn-events-store.test.ts +11 -7
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
- package/src/__tests__/voice-session-bridge.test.ts +13 -7
- package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
- package/src/acp/prepare-agent-env.ts +52 -11
- package/src/agent/compaction-circuit.ts +140 -0
- package/src/agent/loop.ts +409 -85
- package/src/api/README.md +19 -17
- package/src/api/constants/tool-execution.ts +21 -0
- package/src/api/events/assistant-activity-state.ts +75 -0
- package/src/api/events/assistant-outbound-attachment.ts +25 -27
- package/src/api/events/assistant-text-delta.ts +6 -8
- package/src/api/events/assistant-turn-start.ts +5 -7
- package/src/api/events/avatar-updated.ts +24 -0
- package/src/api/events/compaction-circuit-closed.ts +26 -0
- package/src/api/events/compaction-circuit-open.ts +28 -0
- package/src/api/events/confirmation-request.ts +114 -0
- package/src/api/events/contact-request.ts +33 -0
- package/src/api/events/conversation-error.ts +77 -0
- package/src/api/events/conversation-list-invalidated.ts +38 -0
- package/src/api/events/conversation-title-updated.ts +24 -0
- package/src/api/events/disk-pressure-status-changed.ts +61 -0
- package/src/api/events/document-comment-created.ts +24 -28
- package/src/api/events/document-comment-deleted.ts +6 -8
- package/src/api/events/document-comment-reopened.ts +6 -8
- package/src/api/events/document-comment-resolved.ts +8 -10
- package/src/api/events/document-editor-update.ts +27 -0
- package/src/api/events/error.ts +32 -0
- package/src/api/events/generation-cancelled.ts +4 -6
- package/src/api/events/generation-handoff.ts +13 -15
- package/src/api/events/home-feed-updated.ts +26 -0
- package/src/api/events/identity-changed.ts +32 -0
- package/src/api/events/interaction-resolved.ts +50 -0
- package/src/api/events/message-complete.ts +10 -12
- package/src/api/events/message-dequeued.ts +21 -0
- package/src/api/events/message-queued-deleted.ts +23 -0
- package/src/api/events/message-queued.ts +22 -0
- package/src/api/events/message-request-complete.ts +29 -0
- package/src/api/events/navigate-settings.ts +20 -0
- package/src/api/events/notification-intent.ts +33 -0
- package/src/api/events/open-url.ts +6 -8
- package/src/api/events/question-request.ts +67 -0
- package/src/api/events/relationship-state-updated.ts +4 -6
- package/src/api/events/secret-request.ts +42 -0
- package/src/api/events/subagent-event.ts +79 -0
- package/src/api/events/subagent-spawned.ts +40 -0
- package/src/api/events/subagent-status-changed.ts +65 -0
- package/src/api/events/sync-changed.ts +29 -0
- package/src/api/events/tool-result.ts +129 -0
- package/src/api/events/tool-use-start.ts +8 -10
- package/src/api/events/turn-profile-auto-routed.ts +28 -0
- package/src/api/events/ui-surface-complete.ts +30 -0
- package/src/api/events/ui-surface-dismiss.ts +22 -0
- package/src/api/events/ui-surface-show.ts +67 -0
- package/src/api/events/ui-surface-update.ts +26 -0
- package/src/api/events/usage-update.ts +34 -0
- package/src/api/events/user-message-echo.ts +35 -0
- package/src/api/index.ts +354 -0
- package/src/api/requests/dictation.ts +45 -0
- package/src/api/responses/disk-pressure-status.ts +26 -0
- package/src/api/responses/home.ts +217 -0
- package/src/api/responses/llm-context-response.ts +2 -0
- package/src/api/responses/memory-v3-selection-log.ts +50 -0
- package/src/api/responses/subagent-detail.ts +48 -0
- package/src/approvals/guardian-decision-primitive.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +6 -9
- package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
- package/src/avatar/__tests__/avatar-store.test.ts +193 -0
- package/src/avatar/avatar-manifest.ts +195 -0
- package/src/avatar/avatar-store.ts +113 -0
- package/src/avatar/traits-png-sync.ts +8 -2
- package/src/background-wake/next-wake.test.ts +31 -1
- package/src/background-wake/next-wake.ts +4 -1
- package/src/calls/call-conversation-messages.ts +6 -4
- package/src/calls/guardian-action-sweep.ts +6 -4
- package/src/calls/relay-server.ts +12 -8
- package/src/calls/voice-session-bridge.ts +13 -27
- package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
- package/src/cli/commands/avatar.ts +17 -11
- package/src/cli/commands/conversations.ts +15 -1
- package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
- package/src/cli/commands/db/__tests__/status.test.ts +253 -0
- package/src/cli/commands/db/format.ts +48 -0
- package/src/cli/commands/db/index.ts +29 -0
- package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
- package/src/cli/commands/db/repair-step-integrity.ts +146 -0
- package/src/cli/commands/db/repair-steps.ts +164 -0
- package/src/cli/commands/db/repair.ts +141 -0
- package/src/cli/commands/db/status.ts +366 -0
- package/src/cli/commands/memory-v3.ts +159 -445
- package/src/cli/lib/cli-colors.ts +24 -6
- package/src/cli/program.ts +4 -5
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/assistant-feature-flags.ts +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -3
- package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/call-site-defaults.ts +2 -7
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -226
- package/src/config/schemas/call-site-catalog.ts +8 -15
- package/src/config/schemas/llm.ts +2 -3
- package/src/config/schemas/memory-lifecycle.ts +24 -0
- package/src/config/schemas/memory-v2.ts +0 -253
- package/src/config/schemas/memory-v3.ts +39 -0
- package/src/config/schemas/memory.ts +6 -1
- package/src/config/schemas/timeouts.ts +3 -1
- package/src/context/compactor.ts +54 -31
- package/src/context/token-estimator.ts +19 -0
- package/src/context/tool-result-truncation.ts +1 -43
- package/src/context/window-manager.ts +138 -20
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
- package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
- package/src/daemon/approval-generators.ts +4 -4
- package/src/daemon/config-watcher.ts +7 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +225 -88
- package/src/daemon/conversation-agent-loop.ts +284 -584
- package/src/daemon/conversation-error.ts +7 -7
- package/src/daemon/conversation-history.ts +22 -6
- package/src/daemon/conversation-launch.ts +4 -8
- package/src/daemon/conversation-lifecycle.ts +10 -38
- package/src/daemon/conversation-messaging.ts +1 -3
- package/src/daemon/conversation-notifiers.ts +7 -5
- package/src/daemon/conversation-process.ts +100 -79
- package/src/daemon/conversation-runtime-assembly.ts +47 -21
- package/src/daemon/conversation-store.ts +6 -5
- package/src/daemon/conversation-surfaces.ts +55 -69
- package/src/daemon/conversation-tool-setup.ts +3 -0
- package/src/daemon/conversation.ts +91 -126
- package/src/daemon/daemon-skill-host.ts +2 -6
- package/src/daemon/disk-pressure-guard.ts +35 -29
- package/src/daemon/external-plugins-bootstrap.ts +46 -24
- package/src/daemon/first-greeting.ts +26 -4
- package/src/daemon/guardian-action-generators.ts +2 -2
- package/src/daemon/handlers/conversations.ts +6 -22
- package/src/daemon/handlers/shared.ts +4 -0
- package/src/daemon/handlers/skills.ts +15 -14
- package/src/daemon/host-app-control-proxy.ts +54 -1
- package/src/daemon/host-cu-proxy.ts +46 -22
- package/src/daemon/host-file-proxy.ts +25 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -6
- package/src/daemon/lifecycle.ts +28 -55
- package/src/daemon/message-protocol.ts +2 -3
- package/src/daemon/message-provenance.ts +49 -0
- package/src/daemon/message-types/contacts.ts +3 -20
- package/src/daemon/message-types/conversations.ts +13 -111
- package/src/daemon/message-types/documents.ts +3 -9
- package/src/daemon/message-types/home.ts +4 -17
- package/src/daemon/message-types/integrations.ts +2 -6
- package/src/daemon/message-types/messages.ts +28 -343
- package/src/daemon/message-types/notifications.ts +2 -32
- package/src/daemon/message-types/settings.ts +3 -8
- package/src/daemon/message-types/skills.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/sync.ts +12 -25
- package/src/daemon/message-types/workspace.ts +3 -11
- package/src/daemon/process-message.ts +49 -46
- package/src/daemon/server.ts +12 -0
- package/src/daemon/tool-side-effects.ts +10 -7
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +11 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -1
- package/src/heartbeat/heartbeat-run-store.ts +31 -0
- package/src/heartbeat/heartbeat-service.ts +16 -0
- package/src/home/feature-gate.ts +22 -0
- package/src/home/feed-types.ts +36 -221
- package/src/ipc/__tests__/email-ipc.test.ts +0 -9
- package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
- package/src/ipc/routes/route-adapter.ts +45 -6
- package/src/ipc/skill-routes/__tests__/memory.test.ts +18 -9
- package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
- package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
- package/src/ipc/skill-routes/memory.ts +26 -13
- package/src/ipc/skill-routes/providers.ts +5 -6
- package/src/ipc/skill-routes/registries.ts +13 -61
- package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
- package/src/memory/__tests__/conversation-queries.test.ts +192 -8
- package/src/memory/__tests__/db-maintenance.test.ts +128 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
- package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
- package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
- package/src/memory/context-search/agent-runner.ts +2 -4
- package/src/memory/conversation-crud.ts +39 -8
- package/src/memory/conversation-queries.ts +78 -22
- package/src/memory/db-init.ts +8 -0
- package/src/memory/db-maintenance.ts +18 -2
- package/src/memory/graph/consolidation.ts +8 -11
- package/src/memory/graph/conversation-graph-memory.ts +41 -8
- package/src/memory/graph/extraction.ts +6 -9
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.ts +20 -26
- package/src/memory/graph/tools.ts +4 -4
- package/src/memory/job-handlers/conversation-starters.ts +32 -32
- package/src/memory/job-handlers/summarization.ts +1 -2
- package/src/memory/jobs-store.ts +3 -1
- package/src/memory/jobs-worker.ts +51 -39
- package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
- package/src/memory/llm-request-log-source-local.ts +0 -11
- package/src/memory/llm-request-log-source.ts +9 -25
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +10 -0
- package/src/memory/memory-marker.ts +17 -0
- package/src/memory/memory-retrospective-job.ts +6 -2
- package/src/memory/memory-v2-activation-log-store.ts +1 -83
- package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
- package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
- package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
- package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
- package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/schema/infrastructure.ts +11 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +124 -0
- package/src/memory/v2/__tests__/migration.test.ts +11 -3
- package/src/memory/v2/__tests__/page-index.test.ts +37 -1
- package/src/memory/v2/__tests__/router.test.ts +14 -4
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
- package/src/memory/v2/backfill-jobs.ts +6 -0
- package/src/memory/v2/consolidation-job.ts +89 -9
- package/src/memory/v2/migration.ts +5 -3
- package/src/memory/v2/page-index.ts +11 -0
- package/src/memory/v2/router.ts +8 -11
- package/src/memory/v2/sweep-job.ts +8 -11
- package/src/memory/v2/types.ts +1 -0
- package/src/memory/v3/__tests__/assign.test.ts +242 -0
- package/src/memory/v3/__tests__/capabilities.test.ts +118 -0
- package/src/memory/v3/__tests__/core.test.ts +39 -0
- package/src/memory/v3/__tests__/fixtures/eval-turns.json +36 -0
- package/src/memory/v3/__tests__/fixtures/live-turns.json +37 -0
- package/src/memory/v3/__tests__/health.test.ts +203 -0
- package/src/memory/v3/__tests__/live-integration.test.ts +330 -0
- package/src/memory/v3/__tests__/maintain-job.test.ts +288 -0
- package/src/memory/v3/__tests__/needle.test.ts +107 -0
- package/src/memory/v3/__tests__/orchestrate.test.ts +400 -0
- package/src/memory/v3/__tests__/reconcile.test.ts +274 -0
- package/src/memory/v3/__tests__/render-injection.test.ts +61 -0
- package/src/memory/v3/__tests__/router.test.ts +260 -0
- package/src/memory/v3/__tests__/selection-log-store.test.ts +179 -0
- package/src/memory/v3/__tests__/selector.test.ts +404 -0
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +414 -0
- package/src/memory/v3/__tests__/snapshot.test.ts +168 -0
- package/src/memory/v3/__tests__/tree.test.ts +192 -0
- package/src/memory/v3/__tests__/types.test.ts +54 -0
- package/src/memory/v3/__tests__/working-set-eviction.test.ts +106 -0
- package/src/memory/v3/__tests__/working-set-skeleton.test.ts +44 -0
- package/src/memory/v3/assign.ts +268 -0
- package/src/memory/v3/capabilities.ts +124 -0
- package/src/memory/v3/core.ts +26 -0
- package/src/memory/v3/data/README.md +84 -0
- package/src/memory/v3/data/assignments.json +5 -0
- package/src/memory/v3/data/core.json +1 -0
- package/src/memory/v3/data/leaves/domain-a/topic-x.md +9 -0
- package/src/memory/v3/data/leaves/domain-a/topic-y.md +9 -0
- package/src/memory/v3/data/leaves/domain-b/topic-z.md +9 -0
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/maintain-job.ts +314 -0
- package/src/memory/v3/needle.ts +115 -0
- package/src/memory/v3/orchestrate.ts +114 -0
- package/src/memory/v3/page-content.ts +34 -0
- package/src/memory/v3/provider-blocks.ts +16 -0
- package/src/memory/v3/reconcile.ts +523 -0
- package/src/memory/v3/render-injection.ts +32 -0
- package/src/memory/v3/router.ts +184 -0
- package/src/memory/v3/selection-log-store.ts +84 -0
- package/src/memory/v3/selector.ts +211 -0
- package/src/memory/v3/shadow-plugin.ts +379 -0
- package/src/memory/v3/snapshot.ts +209 -0
- package/src/memory/v3/tree.ts +174 -0
- package/src/memory/v3/types.ts +46 -60
- package/src/memory/v3/working-set.ts +88 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
- package/src/messaging/providers/slack/render-transcript.ts +2 -2
- package/src/messaging/style-analyzer.ts +8 -11
- package/src/notifications/conversation-pairing.ts +8 -6
- package/src/notifications/decision-engine.ts +10 -13
- package/src/notifications/preference-extractor.ts +11 -14
- package/src/permissions/prompter.ts +42 -36
- package/src/permissions/question-prompter.test.ts +35 -26
- package/src/permissions/question-prompter.ts +6 -10
- package/src/plugin-api/index.ts +2 -0
- package/src/plugin-api/types.ts +25 -3
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +93 -0
- package/src/plugins/defaults/circuit-breaker/package.json +15 -0
- package/src/plugins/defaults/circuit-breaker/register.ts +39 -0
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +25 -0
- package/src/plugins/defaults/compaction/package.json +15 -0
- package/src/plugins/defaults/compaction/register.ts +35 -0
- package/src/plugins/defaults/compaction/terminal.ts +73 -0
- package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +22 -0
- package/src/plugins/defaults/empty-response/package.json +15 -0
- package/src/plugins/defaults/empty-response/register.ts +28 -0
- package/src/plugins/defaults/empty-response/terminal.ts +106 -0
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/history-repair/package.json +15 -0
- package/src/plugins/defaults/history-repair/register.ts +24 -0
- package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
- package/src/plugins/defaults/index.ts +29 -40
- package/src/plugins/defaults/injectors/package.json +15 -0
- package/src/plugins/defaults/{injectors.ts → injectors/register.ts} +14 -38
- package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +17 -0
- package/src/plugins/defaults/llm-call/package.json +15 -0
- package/src/plugins/defaults/{llm-call.ts → llm-call/register.ts} +6 -38
- package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +17 -0
- package/src/plugins/defaults/memory-retrieval/package.json +15 -0
- package/src/plugins/defaults/{memory-retrieval.ts → memory-retrieval/register.ts} +10 -48
- package/src/plugins/defaults/{overflow-reduce.ts → overflow-reduce/middlewares/overflowReduce.ts} +18 -77
- package/src/plugins/defaults/overflow-reduce/package.json +15 -0
- package/src/plugins/defaults/overflow-reduce/register.ts +42 -0
- package/src/plugins/defaults/persistence/middlewares/persistence.ts +19 -0
- package/src/plugins/defaults/persistence/package.json +15 -0
- package/src/plugins/defaults/persistence/register.ts +38 -0
- package/src/plugins/defaults/persistence/terminal.ts +83 -0
- package/src/plugins/defaults/title-generate/package.json +15 -0
- package/src/plugins/defaults/title-generate/register.ts +35 -0
- package/src/plugins/defaults/title-generate/terminal.ts +31 -0
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +23 -0
- package/src/plugins/defaults/token-estimate/package.json +15 -0
- package/src/plugins/defaults/token-estimate/register.ts +34 -0
- package/src/plugins/defaults/token-estimate/terminal.ts +40 -0
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +21 -0
- package/src/plugins/defaults/tool-error/package.json +15 -0
- package/src/plugins/defaults/tool-error/register.ts +35 -0
- package/src/plugins/defaults/tool-error/terminal.ts +47 -0
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +23 -0
- package/src/plugins/defaults/tool-execute/package.json +15 -0
- package/src/plugins/defaults/{tool-execute.ts → tool-execute/register.ts} +8 -46
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +23 -0
- package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +35 -0
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +113 -0
- package/src/plugins/defaults/tool-result-truncate/types.ts +22 -0
- package/src/plugins/external-plugin-loader.ts +2 -2
- package/src/plugins/pipeline.ts +0 -12
- package/src/plugins/types.ts +51 -90
- package/src/plugins/user-loader.ts +4 -3
- package/src/proactive-artifact/aux-message-injector.ts +0 -1
- package/src/proactive-artifact/job.test.ts +20 -8
- package/src/proactive-artifact/job.ts +3 -1
- package/src/prompts/sections.ts +20 -7
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
- package/src/prompts/templates/BOOTSTRAP.md +5 -1
- package/src/prompts/templates/system-sections.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -25
- package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
- package/src/providers/anthropic/client.ts +24 -5
- package/src/providers/call-site-routing.ts +1 -9
- package/src/providers/gemini/client.ts +152 -34
- package/src/providers/gemini/inline-media.ts +74 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +0 -2
- package/src/providers/openai/chat-completions-provider.ts +1 -4
- package/src/providers/openai/responses-provider.ts +1 -4
- package/src/providers/openrouter/client.ts +1 -6
- package/src/providers/provider-send-message.ts +6 -6
- package/src/providers/ratelimit.ts +1 -9
- package/src/providers/retry.ts +0 -5
- package/src/providers/types.ts +11 -2
- package/src/providers/usage-tracking.ts +1 -9
- package/src/runtime/__tests__/agent-wake.test.ts +131 -26
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
- package/src/runtime/agent-wake.ts +93 -18
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
- package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
- package/src/runtime/auth/route-policy.ts +42 -1079
- package/src/runtime/background-job-runner.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -1
- package/src/runtime/channel-approvals.ts +3 -14
- package/src/runtime/channel-invite-transport.ts +5 -6
- package/src/runtime/channel-readiness-service.ts +2 -5
- package/src/runtime/channel-retry-sweep.ts +12 -16
- package/src/runtime/conversation-stream-state.ts +294 -0
- package/src/runtime/http-router.ts +19 -22
- package/src/runtime/http-types.ts +12 -6
- package/src/runtime/invite-instruction-generator.ts +3 -3
- package/src/runtime/pending-interactions.ts +2 -2
- package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
- package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
- package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
- package/src/runtime/routes/__tests__/tts-routes.test.ts +3 -3
- package/src/runtime/routes/acp-routes.test.ts +97 -75
- package/src/runtime/routes/acp-routes.ts +29 -6
- package/src/runtime/routes/app-management-routes.ts +97 -24
- package/src/runtime/routes/app-routes.ts +25 -5
- package/src/runtime/routes/approval-routes.ts +16 -4
- package/src/runtime/routes/attachment-routes.ts +25 -1
- package/src/runtime/routes/audio-routes.ts +1 -0
- package/src/runtime/routes/audit-routes.ts +5 -0
- package/src/runtime/routes/auth-routes.ts +5 -0
- package/src/runtime/routes/avatar-routes.ts +238 -59
- package/src/runtime/routes/background-tool-routes.ts +9 -0
- package/src/runtime/routes/background-wake-routes.ts +13 -3
- package/src/runtime/routes/backup-routes.ts +45 -0
- package/src/runtime/routes/bookmark-routes.ts +13 -0
- package/src/runtime/routes/brain-graph-routes.ts +9 -0
- package/src/runtime/routes/browser-routes.ts +5 -0
- package/src/runtime/routes/browser-tabs-routes.ts +5 -0
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/cache-routes.ts +13 -0
- package/src/runtime/routes/call-routes.ts +21 -10
- package/src/runtime/routes/channel-availability-routes.ts +5 -1
- package/src/runtime/routes/channel-readiness-routes.ts +37 -4
- package/src/runtime/routes/channel-route-definitions.ts +21 -0
- package/src/runtime/routes/channel-verification-routes.ts +21 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
- package/src/runtime/routes/client-routes.ts +9 -0
- package/src/runtime/routes/consolidation-routes.ts +13 -5
- package/src/runtime/routes/contact-prompt-routes.ts +9 -0
- package/src/runtime/routes/contact-routes.ts +90 -23
- package/src/runtime/routes/content-source-routes.ts +5 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
- package/src/runtime/routes/conversation-attention-routes.ts +5 -0
- package/src/runtime/routes/conversation-cli-routes.ts +54 -7
- package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
- package/src/runtime/routes/conversation-list-routes.ts +81 -12
- package/src/runtime/routes/conversation-management-routes.ts +57 -14
- package/src/runtime/routes/conversation-query-routes.ts +88 -41
- package/src/runtime/routes/conversation-routes.ts +74 -19
- package/src/runtime/routes/conversation-starter-routes.ts +22 -13
- package/src/runtime/routes/conversations-import-routes.ts +6 -1
- package/src/runtime/routes/credential-prompt-routes.ts +5 -0
- package/src/runtime/routes/credential-routes.ts +25 -6
- package/src/runtime/routes/debug-bash-routes.ts +5 -0
- package/src/runtime/routes/debug-routes.ts +11 -2
- package/src/runtime/routes/defer-routes.ts +13 -0
- package/src/runtime/routes/diagnostics-routes.ts +37 -46
- package/src/runtime/routes/disk-pressure-routes.ts +17 -31
- package/src/runtime/routes/document-comments-routes.ts +46 -27
- package/src/runtime/routes/documents-routes.ts +21 -10
- package/src/runtime/routes/domain-routes.ts +61 -28
- package/src/runtime/routes/email-routes.ts +33 -0
- package/src/runtime/routes/events-routes.ts +114 -9
- package/src/runtime/routes/filing-routes.ts +9 -4
- package/src/runtime/routes/gateway-log-routes.ts +5 -0
- package/src/runtime/routes/global-search-routes.ts +53 -50
- package/src/runtime/routes/group-routes.ts +21 -5
- package/src/runtime/routes/guardian-action-routes.ts +9 -0
- package/src/runtime/routes/guardian-approval-interception.ts +0 -31
- package/src/runtime/routes/heartbeat-routes.ts +25 -9
- package/src/runtime/routes/home-feed-routes.ts +23 -19
- package/src/runtime/routes/home-state-routes.ts +8 -40
- package/src/runtime/routes/host-app-control-routes.ts +5 -0
- package/src/runtime/routes/host-bash-routes.ts +5 -0
- package/src/runtime/routes/host-browser-routes.ts +13 -0
- package/src/runtime/routes/host-cu-routes.ts +5 -0
- package/src/runtime/routes/host-file-routes.ts +26 -6
- package/src/runtime/routes/host-transfer-routes.ts +13 -2
- package/src/runtime/routes/http-adapter.ts +1 -2
- package/src/runtime/routes/identity-intro-cache.ts +17 -6
- package/src/runtime/routes/identity-routes.ts +12 -2
- package/src/runtime/routes/image-generation-routes.ts +5 -0
- package/src/runtime/routes/inbound-message-handler.ts +15 -11
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
- package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
- package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
- package/src/runtime/routes/inference-send-routes.ts +11 -11
- package/src/runtime/routes/integrations/a2a.ts +30 -7
- package/src/runtime/routes/integrations/slack/channel.ts +19 -3
- package/src/runtime/routes/integrations/slack/share.ts +9 -2
- package/src/runtime/routes/integrations/telegram.ts +28 -9
- package/src/runtime/routes/integrations/twilio.ts +35 -7
- package/src/runtime/routes/integrations/vercel.ts +3 -3
- package/src/runtime/routes/internal-oauth-routes.ts +5 -0
- package/src/runtime/routes/internal-twilio-routes.ts +13 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
- package/src/runtime/routes/log-export-routes.ts +28 -10
- package/src/runtime/routes/mcp-auth-routes.ts +25 -0
- package/src/runtime/routes/memory-item-routes.ts +21 -10
- package/src/runtime/routes/memory-v2-routes.ts +90 -36
- package/src/runtime/routes/memory-v3-routes.ts +273 -407
- package/src/runtime/routes/migration-rollback-routes.ts +5 -1
- package/src/runtime/routes/migration-routes.ts +29 -0
- package/src/runtime/routes/notification-routes.ts +17 -1
- package/src/runtime/routes/oauth-apps.ts +33 -11
- package/src/runtime/routes/oauth-commands-routes.ts +37 -14
- package/src/runtime/routes/oauth-connect-routes.ts +9 -0
- package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
- package/src/runtime/routes/oauth-providers.ts +35 -10
- package/src/runtime/routes/platform-routes.ts +21 -0
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +3 -2
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
- package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
- package/src/runtime/routes/playground/force-compact.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +0 -1
- package/src/runtime/routes/playground/inject-failures.ts +13 -8
- package/src/runtime/routes/playground/reset-circuit.ts +14 -9
- package/src/runtime/routes/playground/seed-conversation.ts +1 -1
- package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
- package/src/runtime/routes/playground/state.ts +4 -3
- package/src/runtime/routes/plugins-routes.ts +22 -19
- package/src/runtime/routes/profiler-routes.ts +17 -4
- package/src/runtime/routes/ps-routes.ts +5 -0
- package/src/runtime/routes/publish-routes.ts +13 -3
- package/src/runtime/routes/question-routes.ts +5 -0
- package/src/runtime/routes/recording-routes.ts +25 -12
- package/src/runtime/routes/rename-conversation-routes.ts +5 -0
- package/src/runtime/routes/sanity-routes.ts +9 -2
- package/src/runtime/routes/schedule-routes.ts +137 -47
- package/src/runtime/routes/secret-routes.ts +17 -4
- package/src/runtime/routes/sequence-routes.ts +33 -0
- package/src/runtime/routes/settings-routes.ts +65 -19
- package/src/runtime/routes/skills-routes.ts +133 -69
- package/src/runtime/routes/slack-channel-routes.ts +5 -0
- package/src/runtime/routes/stt-routes.ts +13 -6
- package/src/runtime/routes/subagents-routes.ts +24 -18
- package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
- package/src/runtime/routes/surface-action-routes.ts +9 -0
- package/src/runtime/routes/surface-content-routes.ts +10 -2
- package/src/runtime/routes/task-routes.ts +37 -0
- package/src/runtime/routes/telemetry-routes.ts +9 -0
- package/src/runtime/routes/trace-event-routes.ts +42 -1
- package/src/runtime/routes/trust-rules-routes.ts +5 -0
- package/src/runtime/routes/tts-routes.ts +13 -6
- package/src/runtime/routes/types.ts +17 -8
- package/src/runtime/routes/ui-request-routes.ts +5 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
- package/src/runtime/routes/usage-routes.ts +71 -3
- package/src/runtime/routes/user-routes-cli.ts +9 -0
- package/src/runtime/routes/user-routes.ts +5 -1
- package/src/runtime/routes/wake-conversation-routes.ts +5 -0
- package/src/runtime/routes/watcher-routes.ts +21 -0
- package/src/runtime/routes/webhook-routes.ts +9 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
- package/src/runtime/routes/work-items-routes.ts +47 -19
- package/src/runtime/routes/workspace-commit-routes.ts +5 -0
- package/src/runtime/routes/workspace-routes.test.ts +42 -0
- package/src/runtime/routes/workspace-routes.ts +120 -9
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -4
- package/src/runtime/services/analyze-conversation.ts +3 -6
- package/src/runtime/services/conversation-serializer.ts +24 -2
- package/src/runtime/sync/resource-sync-events.ts +16 -2
- package/src/runtime/sync/sync-publisher.ts +2 -2
- package/src/schedule/run-script.ts +28 -3
- package/src/schedule/schedule-store.ts +8 -0
- package/src/schedule/scheduler.ts +3 -1
- package/src/signals/user-message.ts +5 -8
- package/src/skills/catalog-files.ts +4 -1
- package/src/skills/clawhub-files.ts +2 -0
- package/src/skills/skillssh-files.ts +2 -0
- package/src/subagent/manager.ts +3 -6
- package/src/telemetry/types.ts +26 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +138 -1
- package/src/telemetry/usage-telemetry-reporter.ts +31 -0
- package/src/tools/acp/spawn.test.ts +88 -38
- package/src/tools/apps/definitions.ts +8 -4
- package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
- package/src/tools/ask-question/ask-question-tool.ts +85 -90
- package/src/tools/computer-use/definitions.ts +28 -24
- package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
- package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
- package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
- package/src/tools/credentials/vault.ts +112 -111
- package/src/tools/execution-target.ts +1 -1
- package/src/tools/execution-timeout.ts +3 -4
- package/src/tools/filesystem/edit.ts +45 -42
- package/src/tools/filesystem/list.ts +33 -30
- package/src/tools/filesystem/read.ts +54 -35
- package/src/tools/filesystem/write.ts +34 -31
- package/src/tools/host-filesystem/edit.ts +44 -42
- package/src/tools/host-filesystem/read.ts +49 -35
- package/src/tools/host-filesystem/transfer.ts +121 -108
- package/src/tools/host-filesystem/write.ts +33 -31
- package/src/tools/host-terminal/host-shell.ts +50 -48
- package/src/tools/memory/register.ts +23 -24
- package/src/tools/network/web-fetch.ts +49 -46
- package/src/tools/network/web-search.ts +16 -13
- package/src/tools/registry.ts +39 -16
- package/src/tools/schedule/create.ts +11 -0
- package/src/tools/schedule/update.ts +16 -0
- package/src/tools/shared/filesystem/audio-read.ts +122 -0
- package/src/tools/shared/filesystem/image-read.ts +1 -1
- package/src/tools/skills/execute.ts +34 -31
- package/src/tools/skills/load.ts +29 -23
- package/src/tools/subagent/notify-parent.ts +35 -32
- package/src/tools/system/avatar-generator.ts +13 -22
- package/src/tools/system/request-permission.ts +30 -27
- package/src/tools/terminal/shell.ts +190 -61
- package/src/tools/tool-defaults.ts +20 -9
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +74 -23
- package/src/tools/ui-surface/definitions.ts +69 -9
- package/src/usage/types.ts +10 -0
- package/src/util/errors.ts +2 -2
- package/src/util/map-limit.ts +27 -0
- package/src/util/platform.ts +15 -12
- package/src/work-items/work-item-runner.ts +7 -2
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
- package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
- package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
- package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
- package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
- package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/provider-commit-message-generator.ts +15 -17
- package/tsconfig.json +4 -1
- package/src/__tests__/history-repair-pipeline.test.ts +0 -396
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
- package/src/cli/commands/memory-v3-render.ts +0 -491
- package/src/daemon/message-types/disk-pressure.ts +0 -9
- package/src/email/feature-gate.ts +0 -23
- package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
- package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
- package/src/memory/v3/__tests__/edges.test.ts +0 -706
- package/src/memory/v3/__tests__/filter.test.ts +0 -560
- package/src/memory/v3/__tests__/gate.test.ts +0 -637
- package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
- package/src/memory/v3/__tests__/loop.test.ts +0 -775
- package/src/memory/v3/__tests__/retriever.test.ts +0 -226
- package/src/memory/v3/__tests__/scouts.test.ts +0 -489
- package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
- package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
- package/src/memory/v3/__tests__/traversal.test.ts +0 -508
- package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
- package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
- package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
- package/src/memory/v3/__tests__/validate.test.ts +0 -277
- package/src/memory/v3/auto-edges.ts +0 -223
- package/src/memory/v3/coactivation-store.ts +0 -124
- package/src/memory/v3/consolidation-job.ts +0 -323
- package/src/memory/v3/coretrieval-seed.ts +0 -240
- package/src/memory/v3/edge-learning-job.ts +0 -160
- package/src/memory/v3/edges.ts +0 -286
- package/src/memory/v3/filter.ts +0 -286
- package/src/memory/v3/gate.ts +0 -349
- package/src/memory/v3/index-composition.ts +0 -126
- package/src/memory/v3/llm-capture.ts +0 -46
- package/src/memory/v3/loop.ts +0 -430
- package/src/memory/v3/maintenance.ts +0 -144
- package/src/memory/v3/prompt-context.ts +0 -33
- package/src/memory/v3/prompts/consolidation.ts +0 -458
- package/src/memory/v3/prompts/system-prompts.ts +0 -196
- package/src/memory/v3/retriever.ts +0 -33
- package/src/memory/v3/scouts.ts +0 -431
- package/src/memory/v3/shadow-diff.ts +0 -287
- package/src/memory/v3/shadow-middleware.ts +0 -347
- package/src/memory/v3/traversal.ts +0 -211
- package/src/memory/v3/tree-index.ts +0 -237
- package/src/memory/v3/tree-store.ts +0 -394
- package/src/memory/v3/tree-walk.ts +0 -356
- package/src/memory/v3/validate.ts +0 -323
- package/src/plugins/defaults/circuit-breaker.ts +0 -141
- package/src/plugins/defaults/compaction.ts +0 -141
- package/src/plugins/defaults/empty-response.ts +0 -124
- package/src/plugins/defaults/history-repair.ts +0 -83
- package/src/plugins/defaults/persistence.ts +0 -146
- package/src/plugins/defaults/title-generate.ts +0 -90
- package/src/plugins/defaults/token-estimate.ts +0 -101
- package/src/plugins/defaults/tool-error.ts +0 -119
- package/src/plugins/defaults/tool-result-truncate.ts +0 -84
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory v3 — L1 leaf router.
|
|
3
|
+
*
|
|
4
|
+
* One forced-tool LLM call per turn that picks which leaves of the topic tree
|
|
5
|
+
* to open for the next reply. The design mirrors `../v2/router.ts`:
|
|
6
|
+
* - resolve the configured provider via `getConfiguredProvider`,
|
|
7
|
+
* - call `provider.sendMessage` with a forced `tool_choice`,
|
|
8
|
+
* - validate the tool input via Zod,
|
|
9
|
+
* - map numbered IDs back to leaf paths.
|
|
10
|
+
*
|
|
11
|
+
* Cache strategy. The numbered leaf block is the single largest input and is
|
|
12
|
+
* STABLE across turns — it changes only when leaves are added/removed/edited.
|
|
13
|
+
* We render it first in the user message and tag it with an ephemeral
|
|
14
|
+
* `cache_control` breakpoint so the provider can serve it from the prompt
|
|
15
|
+
* cache turn after turn. The trailing recent-context / current-message block
|
|
16
|
+
* changes every turn, so it carries no breakpoint.
|
|
17
|
+
*
|
|
18
|
+
* Recall-safe fallbacks. The router exists to widen recall, so every failure
|
|
19
|
+
* mode degrades toward opening MORE leaves, never fewer:
|
|
20
|
+
* - omitted `ids` (model didn't pass the field) → open ALL leaves,
|
|
21
|
+
* - missing/failed tool_use, provider unavailable, or any throw → ALL leaves.
|
|
22
|
+
* The one path that returns nothing is an explicit empty array (`ids: []`),
|
|
23
|
+
* which is the model deliberately abstaining.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { z } from "zod";
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
extractToolUse,
|
|
30
|
+
getConfiguredProvider,
|
|
31
|
+
} from "../../providers/provider-send-message.js";
|
|
32
|
+
import type { Message, ToolDefinition } from "../../providers/types.js";
|
|
33
|
+
import { getLogger } from "../../util/logger.js";
|
|
34
|
+
import { cachedTextBlock } from "./provider-blocks.js";
|
|
35
|
+
import type { LeafPath, LeafTree, TurnContext } from "./types.js";
|
|
36
|
+
|
|
37
|
+
const log = getLogger("memory-v3-router");
|
|
38
|
+
|
|
39
|
+
/** Tool name forced via `tool_choice`. Shared constant so tests can match it. */
|
|
40
|
+
const OPEN_LEAVES_TOOL_NAME = "open_leaves";
|
|
41
|
+
|
|
42
|
+
const OpenLeavesSchema = z.object({
|
|
43
|
+
// Optional: an omitted `ids` field is the recall-safe "open everything"
|
|
44
|
+
// signal, distinct from an explicit empty array (deliberate abstention).
|
|
45
|
+
ids: z.array(z.number().int()).optional(),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const OPEN_LEAVES_TOOL: ToolDefinition = {
|
|
49
|
+
name: OPEN_LEAVES_TOOL_NAME,
|
|
50
|
+
description:
|
|
51
|
+
"Open the leaves whose contents could plausibly bear on the next reply. " +
|
|
52
|
+
"Lean toward inclusion — a missed relevant leaf is a worse error than an " +
|
|
53
|
+
"unused one. Omit `ids` entirely to open every leaf; return `[]` only " +
|
|
54
|
+
"when nothing in the tree could possibly help.",
|
|
55
|
+
input_schema: {
|
|
56
|
+
type: "object",
|
|
57
|
+
properties: {
|
|
58
|
+
ids: {
|
|
59
|
+
type: "array",
|
|
60
|
+
items: { type: "integer" },
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const SYSTEM_PROMPT = `You route a conversation turn to the leaves of a topic tree that should be opened for the next reply.
|
|
67
|
+
|
|
68
|
+
Each leaf has a numbered ID, a path, and a description of what it holds. Decide which leaves to open by weighing three signals:
|
|
69
|
+
|
|
70
|
+
- Topic — entities, projects, and events named or implied by the turn.
|
|
71
|
+
- Register — the affect and mode of the message (e.g. playful, distressed, formal). A register signal is enough to open a leaf even when no entity is named.
|
|
72
|
+
- Recent context — the immediately preceding exchange, which resolves references like "this", "that", or "the same thing" to concrete topics.
|
|
73
|
+
|
|
74
|
+
Include on doubt: open every leaf that could plausibly hold something useful. Missing a relevant leaf is a worse error than opening an unused one. Call \`open_leaves\` with the chosen IDs. Omit \`ids\` to open every leaf; return \`[]\` only when nothing in the tree could possibly help.`;
|
|
75
|
+
|
|
76
|
+
/** Leaves sorted deterministically by path so the numbered block is stable. */
|
|
77
|
+
function sortedLeaves(tree: LeafTree): LeafPath[] {
|
|
78
|
+
return [...tree.leaves.keys()].sort();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Render the STATIC numbered leaf block from a pre-sorted path list. Identical
|
|
83
|
+
* across turns for any given tree, which is what makes the prompt-cache
|
|
84
|
+
* breakpoint pay off.
|
|
85
|
+
*/
|
|
86
|
+
function renderLeafBlockFromPaths(tree: LeafTree, paths: LeafPath[]): string {
|
|
87
|
+
const lines = paths.map((path, i) => {
|
|
88
|
+
const description = tree.leaves.get(path)?.description ?? "";
|
|
89
|
+
// Collapse the (possibly multi-line) description to a single line so each
|
|
90
|
+
// leaf is exactly one numbered entry.
|
|
91
|
+
const oneLine = description.replace(/\s+/g, " ").trim();
|
|
92
|
+
return `[${i + 1}] ${path} — ${oneLine}`;
|
|
93
|
+
});
|
|
94
|
+
return `<leaves>\n${lines.join("\n")}\n</leaves>`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Render the static numbered leaf block for a tree. Exported for the test that
|
|
99
|
+
* locks the byte-identical cache invariant; `routeL1` renders from its already
|
|
100
|
+
* sorted path list to avoid sorting twice.
|
|
101
|
+
*/
|
|
102
|
+
export function renderLeafBlock(tree: LeafTree): string {
|
|
103
|
+
return renderLeafBlockFromPaths(tree, sortedLeaves(tree));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Run the L1 router for one turn. Returns the leaf paths to open.
|
|
108
|
+
*
|
|
109
|
+
* Recall-safe: any failure to obtain an explicit selection returns ALL leaves.
|
|
110
|
+
* Only an explicit empty `ids` array returns no leaves.
|
|
111
|
+
*/
|
|
112
|
+
export async function routeL1(
|
|
113
|
+
turn: TurnContext,
|
|
114
|
+
tree: LeafTree,
|
|
115
|
+
): Promise<LeafPath[]> {
|
|
116
|
+
const paths = sortedLeaves(tree);
|
|
117
|
+
if (paths.length === 0) return [];
|
|
118
|
+
|
|
119
|
+
const provider = await getConfiguredProvider("memoryV3RouteL1");
|
|
120
|
+
if (!provider) {
|
|
121
|
+
log.warn("memoryV3RouteL1 provider unavailable; opening all leaves");
|
|
122
|
+
return paths;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const userMsg: Message = {
|
|
126
|
+
role: "user",
|
|
127
|
+
content: [
|
|
128
|
+
cachedTextBlock(renderLeafBlockFromPaths(tree, paths)),
|
|
129
|
+
{
|
|
130
|
+
type: "text",
|
|
131
|
+
text:
|
|
132
|
+
`<recent_context>${turn.recentContext}</recent_context>\n` +
|
|
133
|
+
`<current_message>${turn.currentMessage}</current_message>`,
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
let response;
|
|
139
|
+
try {
|
|
140
|
+
response = await provider.sendMessage([userMsg], {
|
|
141
|
+
tools: [OPEN_LEAVES_TOOL],
|
|
142
|
+
systemPrompt: SYSTEM_PROMPT,
|
|
143
|
+
config: {
|
|
144
|
+
callSite: "memoryV3RouteL1" as const,
|
|
145
|
+
tool_choice: { type: "tool" as const, name: OPEN_LEAVES_TOOL_NAME },
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
} catch (err) {
|
|
149
|
+
log.warn({ err }, "L1 router call threw; opening all leaves");
|
|
150
|
+
return paths;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const toolBlock = extractToolUse(response);
|
|
154
|
+
if (!toolBlock || toolBlock.name !== OPEN_LEAVES_TOOL_NAME) {
|
|
155
|
+
log.warn(
|
|
156
|
+
{ stopReason: response.stopReason },
|
|
157
|
+
"L1 router returned no open_leaves tool_use; opening all leaves",
|
|
158
|
+
);
|
|
159
|
+
return paths;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const parsed = OpenLeavesSchema.safeParse(toolBlock.input);
|
|
163
|
+
if (!parsed.success) {
|
|
164
|
+
log.warn(
|
|
165
|
+
{ error: parsed.error.message },
|
|
166
|
+
"L1 router tool input did not match schema; opening all leaves",
|
|
167
|
+
);
|
|
168
|
+
return paths;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Omitted `ids` is the recall-safe "open everything" signal.
|
|
172
|
+
if (parsed.data.ids === undefined) return paths;
|
|
173
|
+
|
|
174
|
+
// Map 1-based IDs back to leaf paths, dropping out-of-range IDs without
|
|
175
|
+
// throwing. De-duplicate while preserving model-returned order.
|
|
176
|
+
const seen = new Set<number>();
|
|
177
|
+
const selected: LeafPath[] = [];
|
|
178
|
+
for (const id of parsed.data.ids) {
|
|
179
|
+
if (id < 1 || id > paths.length || seen.has(id)) continue;
|
|
180
|
+
seen.add(id);
|
|
181
|
+
selected.push(paths[id - 1]);
|
|
182
|
+
}
|
|
183
|
+
return selected;
|
|
184
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-side store for the inspector's Memory V3 section. Reads the persisted
|
|
3
|
+
* `memory_v3_selections` rows for a turn and re-renders the `<memory>` block
|
|
4
|
+
* the v3 working set selected, so the inspector can show what v3 chose (and,
|
|
5
|
+
* in live mode, what it actually injected) without re-running orchestration —
|
|
6
|
+
* which would be wrong anyway, since the working set is stateful (carry-forward
|
|
7
|
+
* across turns) and can't be reproduced after the fact.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { MemoryV3SelectionLog } from "../../api/responses/memory-v3-selection-log.js";
|
|
11
|
+
import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
|
|
12
|
+
import { getConfig } from "../../config/loader.js";
|
|
13
|
+
import { getDb, getSqliteFrom } from "../db-connection.js";
|
|
14
|
+
import { renderV3PageContent } from "./page-content.js";
|
|
15
|
+
import { renderMemoryBlock } from "./render-injection.js";
|
|
16
|
+
import type { Slug } from "./types.js";
|
|
17
|
+
|
|
18
|
+
const MEMORY_V3_SHADOW = "memory-v3-shadow" as const;
|
|
19
|
+
const MEMORY_V3_LIVE = "memory-v3-live" as const;
|
|
20
|
+
|
|
21
|
+
interface SelectionRow {
|
|
22
|
+
slug: string;
|
|
23
|
+
source: string;
|
|
24
|
+
pinned: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function rowsForTurn(conversationId: string, turn: number): SelectionRow[] {
|
|
28
|
+
return getSqliteFrom(getDb())
|
|
29
|
+
.query(
|
|
30
|
+
/*sql*/ `
|
|
31
|
+
SELECT slug, source, pinned FROM memory_v3_selections
|
|
32
|
+
WHERE conversation_id = ? AND turn = ?
|
|
33
|
+
ORDER BY rowid
|
|
34
|
+
`,
|
|
35
|
+
)
|
|
36
|
+
.all(conversationId, turn) as SelectionRow[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build the inspector's v3 selection log for one turn of a conversation.
|
|
41
|
+
*
|
|
42
|
+
* `turn` is the inspected message's turn (the v2-activation log's turn). The
|
|
43
|
+
* selection is returned ONLY for that exact turn; when there are no v3 rows for
|
|
44
|
+
* it — including when `turn` is null (the message has no v2-activation turn) —
|
|
45
|
+
* this returns `null` rather than falling back to a different turn. A fallback
|
|
46
|
+
* would attribute another turn's selection (e.g. a later turn's pages and
|
|
47
|
+
* rendered block) to the inspected message, which corrupts shadow validation.
|
|
48
|
+
*
|
|
49
|
+
* Caveat: v3 rows are keyed by the orchestrator turn counter (`ctx.turnCount`)
|
|
50
|
+
* while `turn` here is the v2 memory-tracker turn. They coincide for normal
|
|
51
|
+
* turns, but if they diverge this simply yields `null` (no section) rather than
|
|
52
|
+
* wrong data. Tying v3 rows to a message id for exact per-message attribution
|
|
53
|
+
* regardless of counter drift is a documented follow-up.
|
|
54
|
+
*
|
|
55
|
+
* Selection rows are stored in `finalInjection` order (this turn's L2
|
|
56
|
+
* selections, then carry-forward), so rendering them in row order reproduces
|
|
57
|
+
* the block v3 would inject.
|
|
58
|
+
*/
|
|
59
|
+
export async function getMemoryV3SelectionForInspector(
|
|
60
|
+
conversationId: string,
|
|
61
|
+
turn: number | null | undefined,
|
|
62
|
+
): Promise<MemoryV3SelectionLog | null> {
|
|
63
|
+
if (turn == null) return null;
|
|
64
|
+
|
|
65
|
+
const rows = rowsForTurn(conversationId, turn);
|
|
66
|
+
if (rows.length === 0) return null;
|
|
67
|
+
|
|
68
|
+
const config = getConfig();
|
|
69
|
+
const selections = rows.map((r) => ({
|
|
70
|
+
slug: r.slug,
|
|
71
|
+
source: r.source,
|
|
72
|
+
pinned: r.pinned === 1,
|
|
73
|
+
}));
|
|
74
|
+
const slugs: Slug[] = selections.map((s) => s.slug);
|
|
75
|
+
const injectedText = await renderMemoryBlock(slugs, renderV3PageContent);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
turn,
|
|
79
|
+
live: isAssistantFeatureFlagEnabled(MEMORY_V3_LIVE, config),
|
|
80
|
+
shadow: isAssistantFeatureFlagEnabled(MEMORY_V3_SHADOW, config),
|
|
81
|
+
selections,
|
|
82
|
+
injectedText,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory v3 — L2 per-leaf page selector.
|
|
3
|
+
*
|
|
4
|
+
* After the L1 router (`./router.ts`) decides which leaves to open, the L2
|
|
5
|
+
* selector runs ONE forced-tool LLM call PER opened leaf to pick which pages
|
|
6
|
+
* inside that leaf are relevant for the next reply. `selectAcrossLeaves` fans
|
|
7
|
+
* the per-leaf calls out with bounded concurrency.
|
|
8
|
+
*
|
|
9
|
+
* Cache strategy. Each leaf's `<pages>` block — the numbered list of its member
|
|
10
|
+
* pages with their full summaries — is STABLE for that leaf: it changes only
|
|
11
|
+
* when pages are added/removed or a summary is rewritten, never per turn. We
|
|
12
|
+
* render it FIRST in the per-leaf user message and tag it with an ephemeral
|
|
13
|
+
* `cache_control` breakpoint so the provider serves it from the prompt cache
|
|
14
|
+
* turn after turn. The trailing recent-context / current-message block changes
|
|
15
|
+
* every turn and carries no breakpoint. This mirrors `./router.ts`.
|
|
16
|
+
*
|
|
17
|
+
* Recall-safe fallbacks. Like the router, the selector exists to widen recall,
|
|
18
|
+
* so every failure degrades toward selecting MORE pages, never fewer:
|
|
19
|
+
* - omitted `ids` → select ALL members of the leaf,
|
|
20
|
+
* - missing/failed tool_use, provider unavailable, or any throw → ALL members.
|
|
21
|
+
* Only an explicit empty `ids: []` returns nothing (deliberate abstention).
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { z } from "zod";
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
extractToolUse,
|
|
28
|
+
getConfiguredProvider,
|
|
29
|
+
} from "../../providers/provider-send-message.js";
|
|
30
|
+
import type { Message, ToolDefinition } from "../../providers/types.js";
|
|
31
|
+
import { getLogger } from "../../util/logger.js";
|
|
32
|
+
import { mapLimit } from "../../util/map-limit.js";
|
|
33
|
+
import { cachedTextBlock } from "./provider-blocks.js";
|
|
34
|
+
import { membersOf } from "./tree.js";
|
|
35
|
+
import type { LeafPath, LeafTree, Slug, TurnContext } from "./types.js";
|
|
36
|
+
|
|
37
|
+
const log = getLogger("memory-v3-selector");
|
|
38
|
+
|
|
39
|
+
/** A page selected from an opened leaf, with whether the turn centers on it. */
|
|
40
|
+
export interface SelectedPage {
|
|
41
|
+
slug: Slug;
|
|
42
|
+
pinned: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Tool name forced via `tool_choice`. Shared constant so tests can match it. */
|
|
46
|
+
const SELECT_PAGES_TOOL_NAME = "select_pages";
|
|
47
|
+
|
|
48
|
+
const SelectPagesSchema = z.object({
|
|
49
|
+
// Optional: an omitted `ids` field is the recall-safe "select everything"
|
|
50
|
+
// signal, distinct from an explicit empty array (deliberate abstention).
|
|
51
|
+
ids: z.array(z.number().int()).optional(),
|
|
52
|
+
pinned_ids: z.array(z.number().int()).optional(),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const SELECT_PAGES_TOOL: ToolDefinition = {
|
|
56
|
+
name: SELECT_PAGES_TOOL_NAME,
|
|
57
|
+
description:
|
|
58
|
+
"Select the pages in this leaf whose content is relevant or useful for " +
|
|
59
|
+
"the next reply. Lean toward inclusion — a missed relevant page is a " +
|
|
60
|
+
"worse error than an unused one. Pass `pinned_ids` for pages the " +
|
|
61
|
+
"conversation is centrally about. Omit `ids` entirely to select every " +
|
|
62
|
+
"page; return `[]` only when none of the pages could possibly help.",
|
|
63
|
+
input_schema: {
|
|
64
|
+
type: "object",
|
|
65
|
+
properties: {
|
|
66
|
+
ids: {
|
|
67
|
+
type: "array",
|
|
68
|
+
items: { type: "integer" },
|
|
69
|
+
},
|
|
70
|
+
pinned_ids: {
|
|
71
|
+
type: "array",
|
|
72
|
+
items: { type: "integer" },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const SYSTEM_PROMPT = `This leaf of the topic tree is potentially relevant to the conversation. Select the pages whose content is relevant or useful for responding.
|
|
79
|
+
|
|
80
|
+
Be inclusive — include frame and affect matches, not just literal-topic matches. A page that shares the conversation's mode or register can be as useful as one that names the same entity. Missing a relevant page is a worse error than selecting an unused one.
|
|
81
|
+
|
|
82
|
+
If the conversation is centrally ABOUT a page (rather than only peripherally relevant to it), mark that page as pinned. Call \`select_pages\` with the chosen IDs. Omit \`ids\` to select every page; return \`[]\` only when none of the pages could possibly help.`;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Render the STATIC numbered `<pages>` block for a leaf from its member slugs.
|
|
86
|
+
* Identical across turns for a given leaf, which is what makes the per-leaf
|
|
87
|
+
* prompt-cache breakpoint pay off. Summaries are rendered in full (no
|
|
88
|
+
* truncation) so the selector sees each page's complete description.
|
|
89
|
+
*/
|
|
90
|
+
async function renderPagesBlock(
|
|
91
|
+
members: Slug[],
|
|
92
|
+
pageSummary: (slug: Slug) => Promise<string>,
|
|
93
|
+
): Promise<string> {
|
|
94
|
+
const lines = await Promise.all(
|
|
95
|
+
members.map(async (slug, i) => {
|
|
96
|
+
const summary = await pageSummary(slug);
|
|
97
|
+
return `[${i + 1}] ${slug} — ${summary}`;
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
return `<pages>\n${lines.join("\n")}\n</pages>`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Run the L2 selector for a single opened leaf. Returns the pages to inject.
|
|
105
|
+
*
|
|
106
|
+
* Recall-safe: any failure to obtain an explicit selection returns ALL members
|
|
107
|
+
* of the leaf. Only an explicit empty `ids` array returns no pages.
|
|
108
|
+
*/
|
|
109
|
+
export async function selectFromLeaf(
|
|
110
|
+
leaf: LeafPath,
|
|
111
|
+
turn: TurnContext,
|
|
112
|
+
tree: LeafTree,
|
|
113
|
+
pageSummary: (slug: Slug) => Promise<string>,
|
|
114
|
+
): Promise<SelectedPage[]> {
|
|
115
|
+
const members = membersOf(tree, leaf);
|
|
116
|
+
if (members.length === 0) return [];
|
|
117
|
+
|
|
118
|
+
const allMembers = (): SelectedPage[] =>
|
|
119
|
+
members.map((slug) => ({ slug, pinned: false }));
|
|
120
|
+
|
|
121
|
+
const provider = await getConfiguredProvider("memoryV3SelectL2");
|
|
122
|
+
if (!provider) {
|
|
123
|
+
log.warn({ leaf }, "memoryV3SelectL2 provider unavailable; selecting all");
|
|
124
|
+
return allMembers();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const userMsg: Message = {
|
|
128
|
+
role: "user",
|
|
129
|
+
content: [
|
|
130
|
+
cachedTextBlock(
|
|
131
|
+
`<leaf>${leaf}</leaf>\n` +
|
|
132
|
+
(await renderPagesBlock(members, pageSummary)),
|
|
133
|
+
),
|
|
134
|
+
{
|
|
135
|
+
type: "text",
|
|
136
|
+
text:
|
|
137
|
+
`<recent_context>${turn.recentContext}</recent_context>\n` +
|
|
138
|
+
`<current_message>${turn.currentMessage}</current_message>`,
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
let response;
|
|
144
|
+
try {
|
|
145
|
+
response = await provider.sendMessage([userMsg], {
|
|
146
|
+
tools: [SELECT_PAGES_TOOL],
|
|
147
|
+
systemPrompt: SYSTEM_PROMPT,
|
|
148
|
+
config: {
|
|
149
|
+
callSite: "memoryV3SelectL2" as const,
|
|
150
|
+
tool_choice: { type: "tool" as const, name: SELECT_PAGES_TOOL_NAME },
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
} catch (err) {
|
|
154
|
+
log.warn({ err, leaf }, "L2 selector call threw; selecting all");
|
|
155
|
+
return allMembers();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const toolBlock = extractToolUse(response);
|
|
159
|
+
if (!toolBlock || toolBlock.name !== SELECT_PAGES_TOOL_NAME) {
|
|
160
|
+
log.warn(
|
|
161
|
+
{ stopReason: response.stopReason, leaf },
|
|
162
|
+
"L2 selector returned no select_pages tool_use; selecting all",
|
|
163
|
+
);
|
|
164
|
+
return allMembers();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const parsed = SelectPagesSchema.safeParse(toolBlock.input);
|
|
168
|
+
if (!parsed.success) {
|
|
169
|
+
log.warn(
|
|
170
|
+
{ error: parsed.error.message, leaf },
|
|
171
|
+
"L2 selector tool input did not match schema; selecting all",
|
|
172
|
+
);
|
|
173
|
+
return allMembers();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Omitted `ids` is the recall-safe "select everything" signal.
|
|
177
|
+
if (parsed.data.ids === undefined) return allMembers();
|
|
178
|
+
|
|
179
|
+
const pinned = new Set(parsed.data.pinned_ids ?? []);
|
|
180
|
+
|
|
181
|
+
// Map 1-based IDs back to member slugs, dropping out-of-range IDs without
|
|
182
|
+
// throwing. De-duplicate while preserving model-returned order.
|
|
183
|
+
const seen = new Set<number>();
|
|
184
|
+
const selected: SelectedPage[] = [];
|
|
185
|
+
for (const id of parsed.data.ids) {
|
|
186
|
+
if (id < 1 || id > members.length || seen.has(id)) continue;
|
|
187
|
+
seen.add(id);
|
|
188
|
+
selected.push({ slug: members[id - 1]!, pinned: pinned.has(id) });
|
|
189
|
+
}
|
|
190
|
+
return selected;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Run the L2 selector across every opened leaf with bounded concurrency and
|
|
195
|
+
* flatten the per-leaf selections.
|
|
196
|
+
*
|
|
197
|
+
* A page assigned to more than one opened leaf may appear more than once in the
|
|
198
|
+
* result; de-duplication across leaves is the orchestrator's job in a later PR.
|
|
199
|
+
*/
|
|
200
|
+
export async function selectAcrossLeaves(
|
|
201
|
+
leaves: LeafPath[],
|
|
202
|
+
turn: TurnContext,
|
|
203
|
+
tree: LeafTree,
|
|
204
|
+
pageSummary: (slug: Slug) => Promise<string>,
|
|
205
|
+
concurrency = 4,
|
|
206
|
+
): Promise<SelectedPage[]> {
|
|
207
|
+
const perLeaf = await mapLimit(leaves, concurrency, (leaf) =>
|
|
208
|
+
selectFromLeaf(leaf, turn, tree, pageSummary),
|
|
209
|
+
);
|
|
210
|
+
return perLeaf.flat();
|
|
211
|
+
}
|