@vellumai/assistant 0.8.7 → 0.8.8-dev.202606052332.17fc8ea
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/Dockerfile +20 -4
- package/bun.lock +2 -2
- package/docker-entrypoint.sh +4 -2
- package/docker-init-apt-root.sh +3 -1
- package/docker-kata-apt-env.sh +3 -1
- package/docker-kata-runtime-family.sh +12 -0
- package/docs/architecture/memory.md +1 -1
- package/examples/plugins/echo/README.md +61 -66
- package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
- package/examples/plugins/echo/hooks/stop.ts +16 -0
- package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
- package/examples/plugins/echo/package.json +1 -2
- package/examples/plugins/echo/src/emit.ts +19 -0
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
- package/openapi.yaml +3378 -335
- package/package.json +2 -2
- package/scripts/generate-openapi.ts +68 -41
- package/src/__tests__/agent-loop-exit-reason.test.ts +35 -93
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +37 -87
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -3
- package/src/__tests__/anthropic-provider.test.ts +95 -2
- package/src/__tests__/app-control-flow.test.ts +1 -1
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +4 -1
- package/src/__tests__/assistant-event-hub.test.ts +25 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
- package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
- package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
- package/src/__tests__/btw-routes.test.ts +62 -3
- package/src/__tests__/build-persisted-content.test.ts +184 -0
- package/src/__tests__/catalog-files.test.ts +1 -1
- package/src/__tests__/channel-approval-routes.test.ts +1 -1
- package/src/__tests__/channel-approvals.test.ts +1 -1
- package/src/__tests__/clawhub-files.test.ts +1 -1
- package/src/__tests__/compaction-circuit.test.ts +258 -0
- package/src/__tests__/compaction-direct.test.ts +132 -0
- package/src/__tests__/compaction.benchmark.test.ts +0 -30
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -5
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -7
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +316 -1143
- package/src/__tests__/conversation-agent-loop.test.ts +638 -1655
- package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
- package/src/__tests__/conversation-clean-command.test.ts +5 -2
- package/src/__tests__/conversation-history-web-search.test.ts +11 -1
- package/src/__tests__/conversation-pairing.test.ts +4 -31
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -10
- package/src/__tests__/conversation-queue.test.ts +2 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
- package/src/__tests__/conversation-runtime-assembly.test.ts +310 -300
- package/src/__tests__/conversation-runtime-workspace.test.ts +105 -45
- package/src/__tests__/conversation-slash-commands.test.ts +8 -42
- package/src/__tests__/conversation-slash-queue.test.ts +6 -1
- package/src/__tests__/conversation-starter-routes.test.ts +14 -6
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
- package/src/__tests__/conversation-sync-tags.test.ts +27 -15
- package/src/__tests__/conversation-title-service.test.ts +135 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +17 -16
- package/src/__tests__/conversation-workspace-injection.test.ts +67 -2
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +7 -6
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
- package/src/__tests__/cross-provider-web-search.test.ts +214 -1
- package/src/__tests__/db-acp-history.test.ts +101 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
- package/src/__tests__/dm-persistence.test.ts +5 -1
- package/src/__tests__/dynamic-page-surface.test.ts +31 -0
- package/src/__tests__/empty-response-hook.test.ts +304 -0
- package/src/__tests__/feature-flag-test-helpers.ts +2 -2
- package/src/__tests__/file-write-tool.test.ts +63 -0
- package/src/__tests__/gateway-only-guard.test.ts +12 -2
- package/src/__tests__/gemini-image-service.test.ts +13 -0
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/mock-provider.ts +110 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
- package/src/__tests__/history-repair-hook.test.ts +1 -0
- package/src/__tests__/host-app-control-routes.test.ts +1 -1
- package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
- package/src/__tests__/identity-intro-cache.test.ts +12 -100
- package/src/__tests__/identity-routes.test.ts +248 -7
- package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
- package/src/__tests__/injector-background-turn.test.ts +3 -9
- package/src/__tests__/injector-chain.test.ts +139 -275
- package/src/__tests__/injector-disk-pressure.test.ts +75 -41
- package/src/__tests__/injector-document-comments.test.ts +3 -3
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
- package/src/__tests__/injector-v3-suppression.test.ts +31 -37
- package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
- package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
- package/src/__tests__/list-messages-page-latest.test.ts +60 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
- package/src/__tests__/llm-usage-store.test.ts +223 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
- package/src/__tests__/native-web-search.test.ts +191 -0
- package/src/__tests__/onboarding-template-contract.test.ts +2 -0
- package/src/__tests__/openai-image-service.test.ts +17 -0
- package/src/__tests__/openai-provider.test.ts +31 -1
- package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -284
- package/src/__tests__/persist-unsendable-image.test.ts +215 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
- package/src/__tests__/pkb-autoinject.test.ts +2 -5
- package/src/__tests__/plugin-api-shim.test.ts +3 -6
- package/src/__tests__/plugin-bootstrap.test.ts +14 -40
- package/src/__tests__/plugin-registry.test.ts +3 -76
- package/src/__tests__/plugin-types.test.ts +0 -193
- package/src/__tests__/process-message-display-content.test.ts +6 -2
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
- package/src/__tests__/resolve-trust-class.test.ts +4 -4
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
- package/src/__tests__/schedule-routes.test.ts +603 -2
- package/src/__tests__/schedule-store.test.ts +41 -0
- package/src/__tests__/schedule-tools.test.ts +35 -0
- package/src/__tests__/send-endpoint-busy.test.ts +4 -1
- package/src/__tests__/server-history-render.test.ts +314 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +33 -0
- package/src/__tests__/skillssh-files.test.ts +1 -1
- package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
- package/src/__tests__/subagent-manager-notify.test.ts +1 -3
- package/src/__tests__/subagent-notify-parent.test.ts +1 -3
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
- package/src/__tests__/system-prompt.test.ts +20 -0
- package/src/__tests__/task-scheduler.test.ts +162 -1
- package/src/__tests__/terminal-tools.test.ts +6 -1
- package/src/__tests__/title-generate-hook.test.ts +319 -0
- package/src/__tests__/tool-error-hook.test.ts +278 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -2
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
- package/src/__tests__/ui-work-result-surface.test.ts +159 -0
- package/src/__tests__/usage-routes.test.ts +285 -1
- package/src/__tests__/user-plugin-loader.test.ts +54 -286
- package/src/__tests__/voice-session-bridge.test.ts +6 -3
- package/src/__tests__/web-search-backend-failure.test.ts +166 -0
- package/src/acp/__tests__/agent-process.test.ts +161 -0
- package/src/acp/__tests__/client-handler.test.ts +40 -0
- package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
- package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +137 -0
- package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
- package/src/acp/__tests__/session-manager-resume.test.ts +736 -0
- package/src/acp/agent-process.ts +61 -1
- package/src/acp/auto-install.test.ts +196 -0
- package/src/acp/auto-install.ts +177 -0
- package/src/acp/client-handler.ts +31 -0
- package/src/acp/feature-gate.test.ts +48 -0
- package/src/acp/feature-gate.ts +34 -0
- package/src/acp/prepare-agent-env.ts +83 -29
- package/src/acp/resolve-agent.test.ts +320 -7
- package/src/acp/resolve-agent.ts +182 -18
- package/src/acp/resume-hint.ts +25 -0
- package/src/acp/session-manager.ts +495 -73
- package/src/acp/types.ts +8 -0
- package/src/agent/compaction-circuit.ts +60 -102
- package/src/agent/loop.ts +362 -485
- package/src/api/events/assistant-thinking-delta.ts +33 -0
- package/src/api/events/tool-output-chunk.ts +45 -0
- package/src/api/events/tool-use-preview-start.ts +32 -0
- package/src/api/events/trace-event.ts +69 -0
- package/src/api/index.ts +48 -13
- package/src/api/responses/conversation-message.ts +374 -0
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/avatar/__tests__/avatar-store.test.ts +34 -29
- package/src/background-wake/next-wake.ts +1 -0
- package/src/cli/commands/__tests__/notifications.test.ts +58 -14
- package/src/cli/commands/notifications.ts +112 -60
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/acp-defaults.test.ts +10 -0
- package/src/config/acp-defaults.ts +6 -0
- package/src/config/assistant-feature-flags.ts +22 -11
- package/src/config/bundled-skills/acp/SKILL.md +83 -31
- package/src/config/bundled-skills/acp/TOOLS.json +4 -4
- package/src/config/bundled-skills/app-builder/SKILL.md +224 -398
- package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
- package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
- package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
- package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
- package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
- package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
- package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +0 -7
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/feature-flag-cache.ts +3 -3
- package/src/config/feature-flag-registry.json +48 -7
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-v2.ts +8 -0
- package/src/config/schemas/memory-v3.ts +8 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills.ts +13 -0
- package/src/context/compactor.ts +1 -1
- package/src/context/strip-injections.ts +128 -0
- package/src/context/token-estimator.ts +23 -0
- package/src/context/tool-result-truncation.ts +0 -23
- package/src/context/window-manager.ts +5 -7
- package/src/credential-execution/executable-discovery.ts +16 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
- package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
- package/src/daemon/assistant-attachments.ts +1 -1
- package/src/daemon/config-watcher.ts +2 -2
- package/src/daemon/context-overflow-reducer.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +594 -153
- package/src/daemon/conversation-agent-loop.ts +301 -997
- package/src/daemon/conversation-history.ts +5 -4
- package/src/daemon/conversation-lifecycle.ts +3 -4
- package/src/daemon/conversation-messaging.ts +7 -6
- package/src/daemon/conversation-process.ts +11 -16
- package/src/daemon/conversation-registry.ts +159 -0
- package/src/daemon/conversation-runtime-assembly.ts +218 -398
- package/src/daemon/conversation-slash.ts +6 -25
- package/src/daemon/conversation-store.ts +9 -90
- package/src/daemon/conversation-surfaces.ts +222 -4
- package/src/daemon/conversation-tool-setup.ts +2 -29
- package/src/daemon/conversation-workspace.ts +17 -0
- package/src/daemon/conversation.ts +32 -20
- package/src/daemon/external-plugins-bootstrap.ts +17 -18
- package/src/daemon/handlers/config-a2a.ts +51 -36
- package/src/daemon/handlers/config-slack-channel.ts +20 -14
- package/src/daemon/handlers/config-telegram.ts +16 -2
- package/src/daemon/handlers/conversations.ts +3 -1
- package/src/daemon/handlers/shared.ts +156 -84
- package/src/daemon/handlers/skills.ts +42 -10
- package/src/daemon/lifecycle.ts +25 -0
- package/src/daemon/message-types/apps.ts +1 -29
- package/src/daemon/message-types/messages.ts +9 -57
- package/src/daemon/message-types/skills.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +136 -3
- package/src/daemon/now-scratchpad.ts +21 -0
- package/src/daemon/orphan-reaper.test.ts +210 -0
- package/src/daemon/orphan-reaper.ts +240 -0
- package/src/daemon/overflow-reduction-loop.ts +230 -0
- package/src/daemon/persist-unsendable-image.ts +117 -0
- package/src/daemon/process-message.ts +1 -3
- package/src/daemon/server.ts +2 -0
- package/src/daemon/trace-emitter.ts +6 -4
- package/src/daemon/trust-context.ts +19 -0
- package/src/daemon/wake-target-adapter.ts +3 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
- package/src/heartbeat/heartbeat-run-store.ts +23 -1
- package/src/heartbeat/heartbeat-service.ts +26 -0
- package/src/home/home-greeting-cache.ts +24 -1
- package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
- package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
- package/src/ipc/gateway-client.test.ts +2 -2
- package/src/ipc/gateway-client.ts +3 -3
- package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
- package/src/ipc/skill-routes/memory.ts +4 -2
- package/src/media/gemini-image-service.ts +15 -0
- package/src/media/openai-image-service.ts +14 -0
- package/src/media/types.ts +34 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
- package/src/memory/auth-fallback-events-store.ts +94 -0
- package/src/memory/conversation-starter-checkpoints.ts +1 -0
- package/src/memory/conversation-title-service.ts +65 -41
- package/src/memory/db-init.ts +6 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
- package/src/memory/graph/conversation-graph-memory.ts +65 -0
- package/src/memory/job-handlers/conversation-starters.ts +13 -2
- package/src/memory/jobs-store.ts +33 -0
- package/src/memory/jobs-worker.ts +32 -5
- package/src/memory/llm-usage-store.ts +224 -50
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
- package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
- package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
- package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
- package/src/memory/migrations/index.ts +3 -0
- package/src/memory/pkb/autoinject.ts +61 -0
- package/src/memory/pkb/context.ts +50 -0
- package/src/memory/pkb/types.ts +14 -0
- package/src/memory/schedule-attribution-sql.ts +104 -0
- package/src/memory/schema/acp.ts +4 -0
- package/src/memory/schema/infrastructure.ts +16 -0
- package/src/memory/usage-grouped-buckets.ts +6 -1
- package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -4
- package/src/memory/v2/consolidation-job.ts +14 -5
- package/src/notifications/conversation-pairing.ts +8 -15
- package/src/notifications/decision-engine.ts +6 -3
- package/src/notifications/home-feed-side-effect.ts +12 -1
- package/src/permissions/prompter.ts +4 -0
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +7 -5
- package/src/plugin-api/types.ts +151 -1
- package/src/plugins/defaults/compaction/compact.ts +59 -0
- package/src/plugins/defaults/compaction/package.json +1 -1
- package/src/plugins/defaults/compaction/register.ts +8 -19
- package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
- package/src/plugins/defaults/empty-response/register.ts +8 -13
- package/src/plugins/defaults/index.ts +2 -18
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
- package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +288 -81
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/health.test.ts +16 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +48 -12
- package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +104 -32
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +96 -30
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +34 -16
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/health.ts +0 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
- package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +8 -8
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +26 -14
- package/src/plugins/defaults/{llm-call → memory-v3-shadow}/package.json +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +3 -3
- package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +51 -45
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +61 -46
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +69 -99
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +8 -0
- package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/title-generate/package.json +1 -1
- package/src/plugins/defaults/title-generate/register.ts +18 -18
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
- package/src/plugins/defaults/tool-error/package.json +1 -1
- package/src/plugins/defaults/tool-error/register.ts +9 -21
- package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
- package/src/plugins/external-api.ts +2 -2
- package/src/plugins/pipeline.ts +6 -305
- package/src/plugins/registry.ts +10 -55
- package/src/plugins/types.ts +62 -797
- package/src/plugins/user-loader.ts +30 -127
- package/src/proactive-artifact/aux-message-injector.ts +4 -4
- package/src/proactive-artifact/job.test.ts +8 -13
- package/src/prompts/__tests__/system-prompt.test.ts +42 -0
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
- package/src/prompts/templates/BOOTSTRAP.md +2 -2
- package/src/prompts/templates/system-sections.ts +15 -0
- package/src/providers/anthropic/client.ts +37 -29
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
- package/src/providers/openai/chat-completions-provider.ts +44 -0
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/placeholder-sentinels.ts +35 -0
- package/src/runtime/__tests__/agent-wake.test.ts +10 -6
- package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
- package/src/runtime/agent-wake.ts +2 -5
- package/src/runtime/assistant-event-hub.ts +37 -7
- package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
- package/src/runtime/channel-approvals.ts +1 -1
- package/src/runtime/http-router.ts +16 -21
- package/src/runtime/http-types.ts +16 -70
- package/src/runtime/interactive-ui.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +283 -55
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/acp-routes.test.ts +89 -25
- package/src/runtime/routes/acp-routes.ts +81 -29
- package/src/runtime/routes/app-management-routes.ts +6 -117
- package/src/runtime/routes/app-routes.ts +13 -15
- package/src/runtime/routes/approval-routes.ts +1 -1
- package/src/runtime/routes/attachment-routes.ts +26 -15
- package/src/runtime/routes/avatar-routes.ts +26 -0
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/browser-tabs-routes.ts +6 -10
- package/src/runtime/routes/btw-routes.ts +29 -23
- package/src/runtime/routes/consolidation-routes.ts +120 -20
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +1 -1
- package/src/runtime/routes/conversation-query-routes.ts +3 -1
- package/src/runtime/routes/conversation-routes.ts +372 -185
- package/src/runtime/routes/conversation-starter-routes.ts +13 -7
- package/src/runtime/routes/conversations-import-routes.ts +24 -7
- package/src/runtime/routes/documents-routes.ts +4 -0
- package/src/runtime/routes/domain-routes.ts +51 -37
- package/src/runtime/routes/epoch-millis-range.ts +34 -0
- package/src/runtime/routes/events-routes.ts +28 -34
- package/src/runtime/routes/gateway-log-routes.ts +26 -4
- package/src/runtime/routes/heartbeat-routes.ts +32 -12
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-cu-routes.ts +1 -1
- package/src/runtime/routes/identity-intro-cache.ts +11 -34
- package/src/runtime/routes/identity-routes.ts +224 -18
- package/src/runtime/routes/image-generation-routes.ts +40 -2
- package/src/runtime/routes/inbound-message-handler.ts +1 -1
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/a2a.ts +12 -10
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
- package/src/runtime/routes/integrations/slack/channel.ts +4 -0
- package/src/runtime/routes/integrations/slack/share.ts +27 -6
- package/src/runtime/routes/integrations/telegram.ts +6 -0
- package/src/runtime/routes/integrations/twilio.ts +42 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
- package/src/runtime/routes/log-export-routes.ts +8 -0
- package/src/runtime/routes/memory-v2-routes.ts +15 -8
- package/src/runtime/routes/memory-v3-routes.ts +66 -34
- package/src/runtime/routes/oauth-apps.ts +66 -12
- package/src/runtime/routes/oauth-providers.ts +44 -5
- package/src/runtime/routes/platform-routes.ts +81 -5
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
- package/src/runtime/routes/playground/force-compact.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +1 -1
- package/src/runtime/routes/rename-conversation-routes.ts +5 -0
- package/src/runtime/routes/schedule-routes.ts +152 -42
- package/src/runtime/routes/secret-routes.ts +14 -2
- package/src/runtime/routes/skills-routes.ts +43 -14
- package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
- package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
- package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
- package/src/runtime/routes/trust-rules-routes.ts +26 -2
- package/src/runtime/routes/tts-routes.ts +35 -0
- package/src/runtime/routes/types.ts +66 -8
- package/src/runtime/routes/usage-routes.ts +47 -39
- package/src/runtime/routes/webhook-routes.ts +41 -2
- package/src/runtime/routes/work-items-routes.ts +2 -4
- package/src/runtime/routes/workspace-routes.ts +4 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
- package/src/runtime/services/analyze-conversation.ts +2 -2
- package/src/runtime/services/conversation-serializer.ts +1 -1
- package/src/schedule/schedule-store.ts +20 -1
- package/src/schedule/schedule-usage-store.ts +83 -0
- package/src/schedule/scheduler.ts +12 -5
- package/src/signals/cancel.ts +2 -4
- package/src/skills/catalog-files.ts +2 -2
- package/src/skills/catalog-install.ts +3 -0
- package/src/skills/categories-cache.ts +118 -0
- package/src/skills/clawhub-files.ts +1 -2
- package/src/skills/skillssh-files.ts +1 -2
- package/src/subagent/manager.ts +17 -5
- package/src/telemetry/types.ts +29 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
- package/src/telemetry/usage-telemetry-reporter.ts +57 -2
- package/src/tools/acp/context.ts +20 -0
- package/src/tools/acp/list-agents.test.ts +7 -1
- package/src/tools/acp/spawn.test.ts +158 -55
- package/src/tools/acp/spawn.ts +47 -72
- package/src/tools/acp/steer.test.ts +105 -8
- package/src/tools/acp/steer.ts +48 -17
- package/src/tools/apps/executors.ts +13 -8
- package/src/tools/executor.ts +1 -53
- package/src/tools/filesystem/write.ts +34 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
- package/src/tools/network/__tests__/web-search.test.ts +11 -3
- package/src/tools/network/web-search-error.test.ts +248 -0
- package/src/tools/network/web-search-error.ts +267 -0
- package/src/tools/network/web-search.ts +207 -48
- package/src/tools/schedule/create.ts +2 -0
- package/src/tools/subagent/spawn.ts +2 -4
- package/src/tools/terminal/safe-env.ts +10 -1
- package/src/tools/ui-surface/definitions.ts +34 -5
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
- package/src/tts/provider-catalog.ts +76 -1
- package/src/util/mutex.ts +47 -0
- package/src/workspace/git-service.ts +1 -42
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
- package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
- package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/docs/plugins.md +0 -836
- package/examples/plugins/echo/register.ts +0 -184
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
- package/src/__tests__/compaction-pipeline.test.ts +0 -210
- package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
- package/src/__tests__/empty-response-pipeline.test.ts +0 -423
- package/src/__tests__/llm-call-pipeline.test.ts +0 -287
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
- package/src/__tests__/persistence-pipeline.test.ts +0 -503
- package/src/__tests__/pipeline-runner.test.ts +0 -564
- package/src/__tests__/title-generate-pipeline.test.ts +0 -211
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
- package/src/__tests__/tool-error-pipeline.test.ts +0 -241
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
- package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
- package/src/gallery/default-gallery.ts +0 -1359
- package/src/gallery/gallery-manifest.ts +0 -28
- package/src/home/feature-gate.ts +0 -22
- package/src/memory/v3/provider-blocks.ts +0 -16
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
- package/src/plugins/defaults/circuit-breaker/package.json +0 -15
- package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
- package/src/plugins/defaults/compaction/terminal.ts +0 -73
- package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
- package/src/plugins/defaults/empty-response/terminal.ts +0 -106
- package/src/plugins/defaults/injectors/package.json +0 -15
- package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
- package/src/plugins/defaults/llm-call/register.ts +0 -45
- package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
- package/src/plugins/defaults/memory-retrieval/package.json +0 -15
- package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
- package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
- package/src/plugins/defaults/overflow-reduce/package.json +0 -15
- package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
- package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
- package/src/plugins/defaults/persistence/package.json +0 -15
- package/src/plugins/defaults/persistence/register.ts +0 -38
- package/src/plugins/defaults/persistence/terminal.ts +0 -83
- package/src/plugins/defaults/title-generate/terminal.ts +0 -31
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
- package/src/plugins/defaults/token-estimate/package.json +0 -15
- package/src/plugins/defaults/token-estimate/register.ts +0 -34
- package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
- package/src/plugins/defaults/tool-error/terminal.ts +0 -47
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
- package/src/plugins/defaults/tool-execute/package.json +0 -15
- package/src/plugins/defaults/tool-execute/register.ts +0 -49
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
- package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
- package/src/skills/category-inference.ts +0 -111
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/needle.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/core.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/needle.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +0 -0
|
@@ -32,35 +32,49 @@
|
|
|
32
32
|
* closer to the memory prefix themselves. For appends, ascending `order` is
|
|
33
33
|
* the natural left-to-right append sequence. The runtime-injection applier
|
|
34
34
|
* sorts and applies blocks declaratively so this invariant holds even when
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* explicitly from `daemon/external-plugins-bootstrap.ts` or lazily via the
|
|
45
|
-
* registry's default registrar the first time a query reads the registry.
|
|
35
|
+
* injectors slot additional blocks at fractional order values.
|
|
36
|
+
*
|
|
37
|
+
* This module exports the default injectors as a plain ordered array
|
|
38
|
+
* ({@link defaultInjectors}). The chain assembler in
|
|
39
|
+
* `plugins/defaults/memory-retrieval/injector-chain.ts` sorts them by `order`
|
|
40
|
+
* (alongside the memory-v3 injector) into the single sequence
|
|
41
|
+
* `applyRuntimeInjections` walks each turn — injection is not a plugin
|
|
42
|
+
* contribution, so injectors are imported directly rather than aggregated
|
|
43
|
+
* through the registry.
|
|
46
44
|
*/
|
|
47
45
|
|
|
48
46
|
import { resolve } from "node:path";
|
|
49
47
|
|
|
50
48
|
import { getConfig } from "../../../config/loader.js";
|
|
49
|
+
import type { InjectionMatcher } from "../../../context/strip-injections.js";
|
|
50
|
+
import { findConversationOrSubagent } from "../../../daemon/conversation-registry.js";
|
|
51
|
+
import { resolveWorkspaceTopLevelContext } from "../../../daemon/conversation-workspace.js";
|
|
52
|
+
import { readNowScratchpad } from "../../../daemon/now-scratchpad.js";
|
|
51
53
|
import { getInContextPkbPaths } from "../../../daemon/pkb-context-tracker.js";
|
|
52
54
|
import { buildPkbReminder } from "../../../daemon/pkb-reminder-builder.js";
|
|
55
|
+
import {
|
|
56
|
+
resolveTrustClass,
|
|
57
|
+
type TrustContext,
|
|
58
|
+
} from "../../../daemon/trust-context.js";
|
|
53
59
|
import { listComments } from "../../../documents/document-comments-store.js";
|
|
60
|
+
import { getLiveGraphMemory } from "../../../memory/graph/conversation-graph-memory.js";
|
|
61
|
+
import { getPkbAutoInjectList } from "../../../memory/pkb/autoinject.js";
|
|
62
|
+
import { readPkbContext } from "../../../memory/pkb/context.js";
|
|
54
63
|
import { searchPkbFiles } from "../../../memory/pkb/pkb-search.js";
|
|
64
|
+
import { getPkbRoot, PKB_WORKSPACE_SCOPE } from "../../../memory/pkb/types.js";
|
|
65
|
+
import {
|
|
66
|
+
readMemoryV2StaticContent,
|
|
67
|
+
shouldExposePersonalMemory,
|
|
68
|
+
} from "../../../memory/v2/static-context.js";
|
|
69
|
+
import type { Message } from "../../../providers/types.js";
|
|
55
70
|
import { getLogger } from "../../../util/logger.js";
|
|
71
|
+
import { getSandboxWorkingDir } from "../../../util/platform.js";
|
|
56
72
|
import {
|
|
57
73
|
type InjectionBlock,
|
|
58
74
|
type Injector,
|
|
59
|
-
type Plugin,
|
|
60
75
|
type TurnContext,
|
|
61
76
|
type TurnInjectionInputs,
|
|
62
77
|
} from "../../types.js";
|
|
63
|
-
import pkg from "./package.json" with { type: "json" };
|
|
64
78
|
|
|
65
79
|
const pkbReminderLog = getLogger("pkb-reminder");
|
|
66
80
|
|
|
@@ -79,7 +93,7 @@ const PKB_HINT_ARCHIVE_THRESHOLD = 0.7;
|
|
|
79
93
|
* and any future integration code — can assert ordering without re-deriving
|
|
80
94
|
* the constants.
|
|
81
95
|
*
|
|
82
|
-
* Gaps of 10 between slots leave room for
|
|
96
|
+
* Gaps of 10 between slots leave room for future injectors to slot in
|
|
83
97
|
* at granular positions (e.g. `25` between unified-turn-context and pkb)
|
|
84
98
|
* without renumbering the defaults.
|
|
85
99
|
*/
|
|
@@ -113,12 +127,22 @@ Then help the user clean up storage. Prefer safe inspection steps first, such as
|
|
|
113
127
|
Do not work on unrelated tasks until enough space is freed to clear the lock or the user explicitly overrides it. Background processes and messages from trusted contacts are blocked while this cleanup mode is active.
|
|
114
128
|
</disk_pressure_warning>`;
|
|
115
129
|
|
|
130
|
+
/**
|
|
131
|
+
* `disk-pressure-warning` injector — order 5, prepend-user-tail.
|
|
132
|
+
*
|
|
133
|
+
* Emits the storage cleanup-mode warning at the very top of the user tail when
|
|
134
|
+
* the turn is restricted to disk-pressure cleanup. Reads the cleanup-mode flag
|
|
135
|
+
* off the live `Conversation` looked up by conversation id — the agent loop
|
|
136
|
+
* sets `diskPressureCleanupModeActive` when it classifies the turn's
|
|
137
|
+
* disk-pressure policy — rather than having the loop thread it as an injection
|
|
138
|
+
* input.
|
|
139
|
+
*/
|
|
116
140
|
const diskPressureWarningInjector: Injector = {
|
|
117
141
|
name: "disk-pressure-warning",
|
|
118
142
|
order: DEFAULT_INJECTOR_ORDER.diskPressureWarning,
|
|
119
143
|
async produce(ctx: TurnContext): Promise<InjectionBlock | null> {
|
|
120
|
-
const
|
|
121
|
-
if (!
|
|
144
|
+
const conversation = findConversationOrSubagent(ctx.conversationId);
|
|
145
|
+
if (!conversation?.diskPressureCleanupModeActive) return null;
|
|
122
146
|
return {
|
|
123
147
|
id: "disk-pressure-warning",
|
|
124
148
|
text: DISK_PRESSURE_WARNING_PROMPT,
|
|
@@ -138,26 +162,52 @@ function isPkbInjectionSilencedByV2(): boolean {
|
|
|
138
162
|
return getConfig().memory.v2.enabled;
|
|
139
163
|
}
|
|
140
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Matchers that mark a persisted `<workspace>` top-level injection. Uses the
|
|
167
|
+
* `{ prefix, suffix }` wrapper shape so user-authored text merely starting with
|
|
168
|
+
* `<workspace>\n` is never mistaken for an injection — matching the full-wrapper
|
|
169
|
+
* requirement the compaction strip uses for this block. The legacy
|
|
170
|
+
* `<workspace_top_level>` tag (pre-rename history) counts as present too.
|
|
171
|
+
*/
|
|
172
|
+
const WORKSPACE_BLOCK_MATCHERS: readonly InjectionMatcher[] = [
|
|
173
|
+
{ prefix: "<workspace>\n", suffix: "\n</workspace>" },
|
|
174
|
+
"<workspace_top_level>",
|
|
175
|
+
];
|
|
176
|
+
|
|
141
177
|
/**
|
|
142
178
|
* `workspace-context` injector — order 10, prepend-user-tail.
|
|
143
179
|
*
|
|
144
180
|
* Injects the workspace top-level directory context at the very top of the
|
|
145
|
-
* user tail's content so the assistant sees a workspace grounding block
|
|
146
|
-
*
|
|
181
|
+
* user tail's content so the assistant sees a workspace grounding block before
|
|
182
|
+
* any other per-turn context.
|
|
183
|
+
*
|
|
184
|
+
* Sources the dirty-guarded top-level cache itself via
|
|
185
|
+
* {@link resolveWorkspaceTopLevelContext} (keyed by conversation id) rather than
|
|
186
|
+
* having the agent loop compute and thread it. Decides inject/skip by presence
|
|
187
|
+
* detection: the block is (re)injected only when it is absent from the working
|
|
188
|
+
* messages — true on the first turn and right after compaction strips it — and
|
|
189
|
+
* skipped on normal cached turns where it already persists in history. This
|
|
190
|
+
* keeps the conversation prefix stable for Anthropic's prefix caching.
|
|
147
191
|
*
|
|
148
192
|
* Gating:
|
|
149
193
|
* - `mode === "full"` (skipped in minimal mode).
|
|
150
|
-
* -
|
|
194
|
+
* - the rendered workspace context is a non-null, non-empty string.
|
|
195
|
+
* - no `<workspace>` block is already present in `runMessages`.
|
|
151
196
|
*/
|
|
152
197
|
const workspaceContextInjector: Injector = {
|
|
153
198
|
name: "workspace-context",
|
|
154
199
|
order: DEFAULT_INJECTOR_ORDER.workspaceContext,
|
|
155
|
-
async produce(
|
|
200
|
+
async produce(
|
|
201
|
+
ctx: TurnContext,
|
|
202
|
+
runMessages?: Message[],
|
|
203
|
+
): Promise<InjectionBlock | null> {
|
|
156
204
|
const inputs = readInjectionInputs(ctx);
|
|
157
205
|
const mode = inputs.mode ?? "full";
|
|
158
206
|
if (mode !== "full") return null;
|
|
159
|
-
const text =
|
|
207
|
+
const text = resolveWorkspaceTopLevelContext(ctx.conversationId);
|
|
160
208
|
if (!text) return null;
|
|
209
|
+
if (hasInjectedUserTextBlock(runMessages, WORKSPACE_BLOCK_MATCHERS))
|
|
210
|
+
return null;
|
|
161
211
|
return {
|
|
162
212
|
id: "workspace-context",
|
|
163
213
|
text,
|
|
@@ -241,20 +291,33 @@ const unifiedTurnContextInjector: Injector = {
|
|
|
241
291
|
*
|
|
242
292
|
* Gating:
|
|
243
293
|
* - `mode === "full"`.
|
|
244
|
-
* -
|
|
294
|
+
* - The personal-memory trust gate admits the actor and the workspace has
|
|
295
|
+
* PKB content (see {@link readGatedPkbContext}).
|
|
296
|
+
* - The `<knowledge_base>` block is not already present in the turn's working
|
|
297
|
+
* messages. The big block is injected once and then persists in history, so
|
|
298
|
+
* it only needs (re)injecting on the first turn and right after compaction
|
|
299
|
+
* strips it — both of which leave the working messages without the block.
|
|
300
|
+
* Skipping when it is present keeps the conversation prefix stable for
|
|
301
|
+
* Anthropic's prefix caching and avoids a duplicate splice.
|
|
245
302
|
*/
|
|
246
303
|
const pkbContextInjector: Injector = {
|
|
247
304
|
name: "pkb-context",
|
|
248
305
|
order: DEFAULT_INJECTOR_ORDER.pkbContext,
|
|
249
|
-
async produce(
|
|
306
|
+
async produce(
|
|
307
|
+
ctx: TurnContext,
|
|
308
|
+
runMessages?: Message[],
|
|
309
|
+
): Promise<InjectionBlock | null> {
|
|
250
310
|
const inputs = readInjectionInputs(ctx);
|
|
251
311
|
const mode = inputs.mode ?? "full";
|
|
252
312
|
if (mode !== "full") return null;
|
|
253
313
|
if (isPkbInjectionSilencedByV2()) return null;
|
|
254
|
-
|
|
314
|
+
const content = readGatedPkbContext(ctx.trust);
|
|
315
|
+
if (!content) return null;
|
|
316
|
+
if (hasInjectedUserTextBlock(runMessages, KNOWLEDGE_BASE_BLOCK_PREFIXES))
|
|
317
|
+
return null;
|
|
255
318
|
return {
|
|
256
319
|
id: "pkb-context",
|
|
257
|
-
text: buildPkbContextBlock(
|
|
320
|
+
text: buildPkbContextBlock(content),
|
|
258
321
|
placement: "after-memory-prefix",
|
|
259
322
|
};
|
|
260
323
|
},
|
|
@@ -271,18 +334,21 @@ const pkbContextInjector: Injector = {
|
|
|
271
334
|
*
|
|
272
335
|
* Gating:
|
|
273
336
|
* - `mode === "full"`.
|
|
274
|
-
* -
|
|
337
|
+
* - PKB is active for the turn (see {@link isPkbActive}).
|
|
275
338
|
*/
|
|
276
339
|
const pkbReminderInjector: Injector = {
|
|
277
340
|
name: "pkb-reminder",
|
|
278
341
|
order: DEFAULT_INJECTOR_ORDER.pkbReminder,
|
|
279
|
-
async produce(
|
|
342
|
+
async produce(
|
|
343
|
+
ctx: TurnContext,
|
|
344
|
+
runMessages?: Message[],
|
|
345
|
+
): Promise<InjectionBlock | null> {
|
|
280
346
|
const inputs = readInjectionInputs(ctx);
|
|
281
347
|
const mode = inputs.mode ?? "full";
|
|
282
348
|
if (mode !== "full") return null;
|
|
283
|
-
if (!
|
|
349
|
+
if (!isPkbActive(ctx.trust)) return null;
|
|
284
350
|
if (isPkbInjectionSilencedByV2()) return null;
|
|
285
|
-
const reminder = await buildPkbReminderWithHints(
|
|
351
|
+
const reminder = await buildPkbReminderWithHints(ctx, runMessages);
|
|
286
352
|
return {
|
|
287
353
|
id: "pkb-reminder",
|
|
288
354
|
text: reminder,
|
|
@@ -291,6 +357,125 @@ const pkbReminderInjector: Injector = {
|
|
|
291
357
|
},
|
|
292
358
|
};
|
|
293
359
|
|
|
360
|
+
/**
|
|
361
|
+
* Whether personal-memory content (PKB, NOW.md) may be surfaced this turn: the
|
|
362
|
+
* trust gate admits the actor (guardian-class, or an internal/local flow). All
|
|
363
|
+
* memory-domain injectors share this gate so they apply identical exposure
|
|
364
|
+
* rules without it being threaded in from the agent loop.
|
|
365
|
+
*/
|
|
366
|
+
function isPersonalMemoryAllowed(trust: TrustContext): boolean {
|
|
367
|
+
return shouldExposePersonalMemory({
|
|
368
|
+
sourceChannel: trust.sourceChannel,
|
|
369
|
+
isTrustedActor: resolveTrustClass(trust) === "guardian",
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Read the auto-injected PKB content for the turn, gated behind the
|
|
375
|
+
* personal-memory trust gate. Returns the content string when the gate admits
|
|
376
|
+
* the actor and the workspace has PKB content, otherwise `null`. Both the gate
|
|
377
|
+
* and the content are sourced from the turn's trust context and the PKB files
|
|
378
|
+
* directly, so the memory-domain injectors source their own inputs rather than
|
|
379
|
+
* having them threaded in from the agent loop.
|
|
380
|
+
*/
|
|
381
|
+
function readGatedPkbContext(trust: TrustContext): string | null {
|
|
382
|
+
return isPersonalMemoryAllowed(trust) ? readPkbContext() : null;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Read the NOW.md scratchpad content for the turn, gated behind the
|
|
387
|
+
* personal-memory trust gate and the `scratchpadInjection` config toggle.
|
|
388
|
+
* Returns the trimmed content when both gates admit and the file is non-empty,
|
|
389
|
+
* otherwise `null`. Sourced from the trust context and the NOW.md file directly
|
|
390
|
+
* so the `now-md` injector owns its input rather than having it threaded in.
|
|
391
|
+
*/
|
|
392
|
+
function readGatedNowScratchpad(trust: TrustContext): string | null {
|
|
393
|
+
if (!isPersonalMemoryAllowed(trust)) return null;
|
|
394
|
+
if (!getConfig().memory.retrieval.scratchpadInjection.enabled) return null;
|
|
395
|
+
return readNowScratchpad();
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Read the v2 static memory content for the turn, gated behind the
|
|
400
|
+
* personal-memory trust gate. Returns the content (essentials/threads/recent/
|
|
401
|
+
* buffer concatenated) when the gate admits and v2 memory is enabled,
|
|
402
|
+
* otherwise `null`. {@link readMemoryV2StaticContent} self-gates on the v2
|
|
403
|
+
* flag + config, so the `memory-v2-static` injector owns its input rather than
|
|
404
|
+
* having it threaded in from the agent loop.
|
|
405
|
+
*/
|
|
406
|
+
function readGatedMemoryV2Static(trust: TrustContext): string | null {
|
|
407
|
+
return isPersonalMemoryAllowed(trust) ? readMemoryV2StaticContent() : null;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Whether PKB is active for the turn: the personal-memory trust gate admits
|
|
412
|
+
* the actor and the workspace has PKB content to surface.
|
|
413
|
+
*/
|
|
414
|
+
function isPkbActive(trust: TrustContext): boolean {
|
|
415
|
+
return readGatedPkbContext(trust) !== null;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/** Block prefixes that mark a persisted `<knowledge_base>` injection. */
|
|
419
|
+
const KNOWLEDGE_BASE_BLOCK_PREFIXES = [
|
|
420
|
+
"<knowledge_base>",
|
|
421
|
+
"<pkb>", // backward-compat: pre-rename history
|
|
422
|
+
] as const;
|
|
423
|
+
|
|
424
|
+
/** Block prefixes that mark a persisted NOW.md injection. */
|
|
425
|
+
const NOW_MD_BLOCK_PREFIXES = [
|
|
426
|
+
"<NOW.md Always keep this up to date",
|
|
427
|
+
"<now_scratchpad>", // backward-compat: pre-rename history
|
|
428
|
+
] as const;
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Matchers that mark a persisted `memory-v2-static` injection. Uses the
|
|
432
|
+
* `{ prefix, suffix }` wrapper shape (not a bare prefix) so user-authored text
|
|
433
|
+
* merely starting with `<info>\n` is never mistaken for an injection — matching
|
|
434
|
+
* the full-wrapper requirement the compaction strip uses for this block.
|
|
435
|
+
*
|
|
436
|
+
* The static block is wrapped in `<info>…</info>` today, but rows persisted
|
|
437
|
+
* before that switch rehydrate verbatim as `<memory>…</memory>` (see
|
|
438
|
+
* `conversation-lifecycle`), so the legacy wrapper counts as present too.
|
|
439
|
+
* Matching `<memory>` cannot wrongly skip a needed injection: the static block
|
|
440
|
+
* is only (re)injected on the first turn (empty history) and right after
|
|
441
|
+
* compaction (which strips both wrappers), and on neither is a `<memory>` block
|
|
442
|
+
* present — the dynamic activation `<memory>` block only survives on normal
|
|
443
|
+
* cached turns, which is exactly when this injector must skip anyway.
|
|
444
|
+
*/
|
|
445
|
+
const MEMORY_V2_STATIC_BLOCK_MATCHERS: readonly InjectionMatcher[] = [
|
|
446
|
+
{ prefix: "<info>\n", suffix: "\n</info>" },
|
|
447
|
+
{ prefix: "<memory>\n", suffix: "\n</memory>" },
|
|
448
|
+
];
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Whether a block matching any of the given matchers is already present in the
|
|
452
|
+
* turn's working messages. Mirrors `stripUserTextBlocksByPrefix` (a
|
|
453
|
+
* user-message text block whose content matches a bare-prefix or a
|
|
454
|
+
* `{ prefix, suffix }` wrapper matcher), so presence detection stays in
|
|
455
|
+
* lockstep with what compaction strips: a block is present here exactly when
|
|
456
|
+
* compaction would strip it.
|
|
457
|
+
*/
|
|
458
|
+
function hasInjectedUserTextBlock(
|
|
459
|
+
runMessages: Message[] | undefined,
|
|
460
|
+
matchers: readonly InjectionMatcher[],
|
|
461
|
+
): boolean {
|
|
462
|
+
if (!runMessages) return false;
|
|
463
|
+
return runMessages.some(
|
|
464
|
+
(message) =>
|
|
465
|
+
message.role === "user" &&
|
|
466
|
+
message.content.some(
|
|
467
|
+
(block) =>
|
|
468
|
+
block.type === "text" &&
|
|
469
|
+
matchers.some((m) =>
|
|
470
|
+
typeof m === "string"
|
|
471
|
+
? block.text.startsWith(m)
|
|
472
|
+
: block.text.startsWith(m.prefix) &&
|
|
473
|
+
block.text.endsWith(m.suffix),
|
|
474
|
+
),
|
|
475
|
+
),
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
|
|
294
479
|
/**
|
|
295
480
|
* Render the PKB context block — wraps the raw content in
|
|
296
481
|
* `<knowledge_base>...</knowledge_base>` while escaping any closing tags
|
|
@@ -305,38 +490,40 @@ function buildPkbContextBlock(content: string): string {
|
|
|
305
490
|
}
|
|
306
491
|
|
|
307
492
|
/**
|
|
308
|
-
* Build the PKB `<system_reminder>` text. When a dense query vector
|
|
309
|
-
*
|
|
493
|
+
* Build the PKB `<system_reminder>` text. When a dense query vector and the
|
|
494
|
+
* turn's working messages are available, run the hybrid PKB search to
|
|
310
495
|
* surface up to three relevance hints; fall back to the flat static
|
|
311
496
|
* reminder on empty results or any error.
|
|
497
|
+
*
|
|
498
|
+
* The dense/sparse query pair is read off the conversation's live graph
|
|
499
|
+
* handle ({@link getLiveGraphMemory}) — the memory-retrieval hook records it
|
|
500
|
+
* there during the turn's retrieval. In-context PKB paths are computed from
|
|
501
|
+
* the turn's working messages (`runMessages`, supplied by the injector chain)
|
|
502
|
+
* resolved against the workspace working directory, so the reminder sources
|
|
503
|
+
* its inputs itself rather than having them threaded through the agent loop.
|
|
312
504
|
*/
|
|
313
505
|
async function buildPkbReminderWithHints(
|
|
314
|
-
|
|
506
|
+
ctx: TurnContext,
|
|
507
|
+
runMessages?: Message[],
|
|
315
508
|
): Promise<string> {
|
|
316
509
|
let hints: string[] = [];
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
queryVector.length > 0 &&
|
|
321
|
-
inputs.pkbScopeId &&
|
|
322
|
-
inputs.pkbConversation &&
|
|
323
|
-
inputs.pkbRoot
|
|
324
|
-
) {
|
|
510
|
+
const graphMemory = getLiveGraphMemory(ctx.conversationId);
|
|
511
|
+
const queryVector = graphMemory?.pkbQueryVector;
|
|
512
|
+
if (queryVector && queryVector.length > 0 && runMessages) {
|
|
325
513
|
try {
|
|
514
|
+
const pkbRoot = getPkbRoot();
|
|
326
515
|
const results = await searchPkbFiles(
|
|
327
516
|
queryVector,
|
|
328
|
-
|
|
517
|
+
graphMemory?.pkbSparseVector,
|
|
329
518
|
8,
|
|
330
|
-
[
|
|
519
|
+
[PKB_WORKSPACE_SCOPE],
|
|
331
520
|
);
|
|
332
|
-
const workingDir = inputs.pkbWorkingDir ?? inputs.pkbRoot;
|
|
333
521
|
const inContext = getInContextPkbPaths(
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
522
|
+
{ messages: runMessages },
|
|
523
|
+
getPkbAutoInjectList(pkbRoot),
|
|
524
|
+
pkbRoot,
|
|
525
|
+
getSandboxWorkingDir(),
|
|
338
526
|
);
|
|
339
|
-
const pkbRoot = inputs.pkbRoot;
|
|
340
527
|
// Gate on `denseScore` (cosine, [0, 1]) so the quality bar is stable
|
|
341
528
|
// regardless of whether sparse was provided. Rank by `hybridScore`
|
|
342
529
|
// (RRF) when available — that captures the sparse signal for
|
|
@@ -395,18 +582,30 @@ async function buildPkbReminderWithHints(
|
|
|
395
582
|
* the memory prefix so `now-md` (40) splices after it.
|
|
396
583
|
*
|
|
397
584
|
* Gating:
|
|
398
|
-
* - `mode === "full"
|
|
399
|
-
* -
|
|
585
|
+
* - `mode === "full"` (skipped in minimal mode).
|
|
586
|
+
* - The personal-memory trust gate admits the actor and v2 static memory has
|
|
587
|
+
* content (see {@link readGatedMemoryV2Static}).
|
|
588
|
+
* - The `<info>` block is not already present in the turn's working messages.
|
|
589
|
+
* Like `<knowledge_base>`, the block is injected once and then persists in
|
|
590
|
+
* history, so it only needs (re)injecting on the first turn and right after
|
|
591
|
+
* compaction strips it — both of which leave the working messages without
|
|
592
|
+
* the block. Skipping when it is present keeps the conversation prefix
|
|
593
|
+
* stable for Anthropic's prefix caching and avoids a duplicate splice.
|
|
400
594
|
*/
|
|
401
595
|
const memoryV2StaticInjector: Injector = {
|
|
402
596
|
name: "memory-v2-static",
|
|
403
597
|
order: DEFAULT_INJECTOR_ORDER.memoryV2Static,
|
|
404
|
-
async produce(
|
|
598
|
+
async produce(
|
|
599
|
+
ctx: TurnContext,
|
|
600
|
+
runMessages?: Message[],
|
|
601
|
+
): Promise<InjectionBlock | null> {
|
|
405
602
|
const inputs = readInjectionInputs(ctx);
|
|
406
603
|
const mode = inputs.mode ?? "full";
|
|
407
604
|
if (mode !== "full") return null;
|
|
408
|
-
const content =
|
|
605
|
+
const content = readGatedMemoryV2Static(ctx.trust);
|
|
409
606
|
if (!content) return null;
|
|
607
|
+
if (hasInjectedUserTextBlock(runMessages, MEMORY_V2_STATIC_BLOCK_MATCHERS))
|
|
608
|
+
return null;
|
|
410
609
|
return {
|
|
411
610
|
id: "memory-v2-static",
|
|
412
611
|
text: buildMemoryV2StaticBlock(content),
|
|
@@ -438,17 +637,30 @@ function buildMemoryV2StaticBlock(content: string): string {
|
|
|
438
637
|
*
|
|
439
638
|
* Gating:
|
|
440
639
|
* - `mode === "full"` (skipped in minimal mode).
|
|
441
|
-
* -
|
|
640
|
+
* - The personal-memory trust gate admits the actor, the `scratchpadInjection`
|
|
641
|
+
* config toggle is on, and NOW.md has content (see
|
|
642
|
+
* {@link readGatedNowScratchpad}).
|
|
643
|
+
* - The NOW.md block is not already present in the turn's working messages.
|
|
644
|
+
* Like `<knowledge_base>`, the block is injected once and then persists in
|
|
645
|
+
* history, so it only needs (re)injecting on the first turn and right after
|
|
646
|
+
* compaction strips it — both of which leave the working messages without
|
|
647
|
+
* the block. Skipping when it is present keeps the conversation prefix
|
|
648
|
+
* stable for Anthropic's prefix caching and avoids a duplicate splice.
|
|
442
649
|
*/
|
|
443
650
|
const nowMdInjector: Injector = {
|
|
444
651
|
name: "now-md",
|
|
445
652
|
order: DEFAULT_INJECTOR_ORDER.nowMd,
|
|
446
|
-
async produce(
|
|
653
|
+
async produce(
|
|
654
|
+
ctx: TurnContext,
|
|
655
|
+
runMessages?: Message[],
|
|
656
|
+
): Promise<InjectionBlock | null> {
|
|
447
657
|
const inputs = readInjectionInputs(ctx);
|
|
448
658
|
const mode = inputs.mode ?? "full";
|
|
449
659
|
if (mode !== "full") return null;
|
|
450
|
-
const content =
|
|
660
|
+
const content = readGatedNowScratchpad(ctx.trust);
|
|
451
661
|
if (!content) return null;
|
|
662
|
+
if (hasInjectedUserTextBlock(runMessages, NOW_MD_BLOCK_PREFIXES))
|
|
663
|
+
return null;
|
|
452
664
|
const text = `<NOW.md Always keep this up to date; keep under 10 lines>\n${content}\n</NOW.md>`;
|
|
453
665
|
return {
|
|
454
666
|
id: "now-md",
|
|
@@ -675,31 +887,26 @@ const threadFocusInjector: Injector = {
|
|
|
675
887
|
};
|
|
676
888
|
|
|
677
889
|
/**
|
|
678
|
-
*
|
|
679
|
-
*
|
|
890
|
+
* Every default injector in ascending `order`. This is the canonical
|
|
891
|
+
* first-party injection sequence consumed by `applyRuntimeInjections` via the
|
|
892
|
+
* assembled injector chain.
|
|
680
893
|
*
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
*
|
|
894
|
+
* `order` is the source of truth for sequencing (see {@link DEFAULT_INJECTOR_ORDER});
|
|
895
|
+
* the chain assembler sorts by it, so this array's literal order is only a
|
|
896
|
+
* readability convenience.
|
|
684
897
|
*/
|
|
685
|
-
export const
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
documentCommentsInjector,
|
|
701
|
-
subagentStatusInjector,
|
|
702
|
-
slackMessagesInjector,
|
|
703
|
-
threadFocusInjector,
|
|
704
|
-
],
|
|
705
|
-
};
|
|
898
|
+
export const defaultInjectors: Injector[] = [
|
|
899
|
+
diskPressureWarningInjector,
|
|
900
|
+
workspaceContextInjector,
|
|
901
|
+
backgroundTurnInjector,
|
|
902
|
+
unifiedTurnContextInjector,
|
|
903
|
+
pkbContextInjector,
|
|
904
|
+
pkbReminderInjector,
|
|
905
|
+
memoryV2StaticInjector,
|
|
906
|
+
nowMdInjector,
|
|
907
|
+
activeDocumentsInjector,
|
|
908
|
+
documentCommentsInjector,
|
|
909
|
+
subagentStatusInjector,
|
|
910
|
+
slackMessagesInjector,
|
|
911
|
+
threadFocusInjector,
|
|
912
|
+
];
|
|
@@ -8,15 +8,15 @@ import { tmpdir } from "node:os";
|
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
10
10
|
|
|
11
|
+
import { readPage, writePage } from "../../../../memory/v2/page-store.js";
|
|
12
|
+
import type { ConceptPageFrontmatter } from "../../../../memory/v2/types.js";
|
|
11
13
|
import type {
|
|
12
14
|
Message,
|
|
13
15
|
Provider,
|
|
14
16
|
ProviderResponse,
|
|
15
17
|
SendMessageOptions,
|
|
16
18
|
ToolUseContent,
|
|
17
|
-
} from "
|
|
18
|
-
import { readPage, writePage } from "../../v2/page-store.js";
|
|
19
|
-
import type { ConceptPageFrontmatter } from "../../v2/types.js";
|
|
19
|
+
} from "../../../../providers/types.js";
|
|
20
20
|
import type { LeafNode, LeafTree } from "../types.js";
|
|
21
21
|
|
|
22
22
|
// Stub the provider layer before importing `assign.js` so its static import
|
|
@@ -24,7 +24,7 @@ import type { LeafNode, LeafTree } from "../types.js";
|
|
|
24
24
|
// aren't built in a fresh worktree) never loads. The classifier is
|
|
25
25
|
// provider-injectable, so every test passes its own stub provider — the real
|
|
26
26
|
// `getConfiguredProvider` is never exercised here.
|
|
27
|
-
mock.module("
|
|
27
|
+
mock.module("../../../../providers/provider-send-message.js", () => ({
|
|
28
28
|
getConfiguredProvider: async () => null,
|
|
29
29
|
extractToolUse: (response: ProviderResponse) =>
|
|
30
30
|
response.content.find((b): b is ToolUseContent => b.type === "tool_use"),
|
|
@@ -42,6 +42,22 @@ describe("computeV3Health", () => {
|
|
|
42
42
|
expect(report.unassigned).toEqual(["page-b", "page-c"]);
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
+
test("excludes synthetic capability slugs from unassigned / novel clusters", () => {
|
|
46
|
+
const t = tree({ "domain-a/topic-x": ["page-a"] });
|
|
47
|
+
const report = computeV3Health({
|
|
48
|
+
tree: t,
|
|
49
|
+
allSlugs: ["page-a", "page-b", "cli-commands/example", "skills/example"],
|
|
50
|
+
});
|
|
51
|
+
// Capability slugs are handled by the always-on capabilities leaf (injected
|
|
52
|
+
// into the live lane tree, absent here), not the persisted tree — so they must
|
|
53
|
+
// not be reported as unassigned or grouped into novel clusters. page-b is the
|
|
54
|
+
// one real unassigned concept page.
|
|
55
|
+
expect(report.unassigned).toEqual(["page-b"]);
|
|
56
|
+
expect(report.novelClusters).toEqual([
|
|
57
|
+
{ prefix: "page-b", slugs: ["page-b"], count: 1 },
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
|
|
45
61
|
test("flags dangling page refs pointing at missing leaves", () => {
|
|
46
62
|
const t = tree({ "domain-a/topic-x": ["page-a"] });
|
|
47
63
|
const report = computeV3Health({
|
package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts
RENAMED
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
|
|
26
26
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
27
27
|
|
|
28
|
+
import { stripAllMemoryInjections } from "../../../../memory/graph/conversation-graph-memory.js";
|
|
28
29
|
import type {
|
|
29
30
|
ContentBlock,
|
|
30
31
|
Message,
|
|
31
32
|
Provider,
|
|
32
33
|
ProviderResponse,
|
|
33
|
-
} from "
|
|
34
|
-
import { stripAllMemoryInjections } from "../../graph/conversation-graph-memory.js";
|
|
34
|
+
} from "../../../../providers/types.js";
|
|
35
35
|
import type { NeedleIndex } from "../needle.js";
|
|
36
36
|
import type {
|
|
37
37
|
LeafNode,
|
|
@@ -49,13 +49,13 @@ import liveTurns from "./fixtures/live-turns.json" with { type: "json" };
|
|
|
49
49
|
|
|
50
50
|
let providerStub: Provider | null = null;
|
|
51
51
|
|
|
52
|
-
mock.module("
|
|
52
|
+
mock.module("../../../../providers/provider-send-message.js", () => ({
|
|
53
53
|
getConfiguredProvider: async () => providerStub,
|
|
54
54
|
extractToolUse: (response: ProviderResponse) =>
|
|
55
55
|
response.content.find((b) => b.type === "tool_use"),
|
|
56
56
|
}));
|
|
57
57
|
|
|
58
|
-
mock.module("
|
|
58
|
+
mock.module("../../../../util/logger.js", () => ({
|
|
59
59
|
getLogger: () =>
|
|
60
60
|
new Proxy({} as Record<string, unknown>, {
|
|
61
61
|
get: (_t, prop) => (prop === "child" ? () => ({}) : () => {}),
|
|
@@ -3,11 +3,11 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
5
5
|
|
|
6
|
-
import { setOverridesForTesting } from "
|
|
7
|
-
import type { AssistantConfig } from "
|
|
8
|
-
import type { MemoryJob } from "
|
|
9
|
-
import { readPage, writePage } from "
|
|
10
|
-
import type { ConceptPage } from "
|
|
6
|
+
import { setOverridesForTesting } from "../../../../__tests__/feature-flag-test-helpers.js";
|
|
7
|
+
import type { AssistantConfig } from "../../../../config/types.js";
|
|
8
|
+
import type { MemoryJob } from "../../../../memory/jobs-store.js";
|
|
9
|
+
import { readPage, writePage } from "../../../../memory/v2/page-store.js";
|
|
10
|
+
import type { ConceptPage } from "../../../../memory/v2/types.js";
|
|
11
11
|
import type { AssignPageResult, AssignPagesOptions } from "../assign.js";
|
|
12
12
|
import {
|
|
13
13
|
type ClassifyCandidate,
|