@vellumai/assistant 0.8.10 → 0.8.11-staging.1
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/bun.lock +62 -1
- package/docs/workspace-tools.md +196 -0
- package/examples/plugins/echo/README.md +3 -3
- package/knip.json +1 -0
- package/openapi.yaml +460 -128
- package/package.json +2 -1
- package/scripts/build-plugin-api.ts +299 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +7 -0
- package/src/__tests__/agent-loop-compaction-events.test.ts +197 -0
- package/src/__tests__/agent-loop-exit-reason.test.ts +93 -96
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +2 -0
- package/src/__tests__/agent-loop-output-hooks.test.ts +274 -1
- package/src/__tests__/agent-loop-override-profile.test.ts +3 -0
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +4 -0
- package/src/__tests__/agent-loop-thinking.test.ts +4 -0
- package/src/__tests__/agent-loop.test.ts +578 -5
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -1
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -1
- package/src/__tests__/build-persisted-content.test.ts +75 -1
- package/src/__tests__/catalog-install-normalize.test.ts +141 -0
- package/src/__tests__/ces-startup-timeout.test.ts +60 -0
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
- package/src/__tests__/context-overflow-reducer.test.ts +264 -124
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +351 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -5
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +284 -455
- package/src/__tests__/conversation-agent-loop.test.ts +131 -551
- package/src/__tests__/conversation-app-control-instantiation.test.ts +13 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-fork-crud.test.ts +259 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-lifecycle.test.ts +257 -1
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +38 -377
- package/src/__tests__/conversation-queue.test.ts +1 -39
- package/src/__tests__/conversation-runtime-assembly.test.ts +119 -8
- package/src/__tests__/conversation-skill-tools.test.ts +491 -5
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-store.test.ts +74 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +4 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +323 -0
- package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +34 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -0
- package/src/__tests__/corrected-target.test.ts +93 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -5
- package/src/__tests__/credential-execution-tools.test.ts +23 -11
- package/src/__tests__/credential-security-invariants.test.ts +6 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
- package/src/__tests__/device-id.test.ts +70 -1
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
- package/src/__tests__/empty-response-hook.test.ts +242 -66
- package/src/__tests__/external-plugin-loader.test.ts +0 -31
- package/src/__tests__/get-skill-detail-audit.test.ts +43 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +91 -0
- package/src/__tests__/history-repair-hook.test.ts +228 -3
- package/src/__tests__/host-app-control-proxy.test.ts +45 -0
- package/src/__tests__/host-browser-proxy.test.ts +254 -9
- package/src/__tests__/identity-routes.test.ts +1 -0
- package/src/__tests__/image-recovery-hook.test.ts +387 -0
- package/src/__tests__/injector-chain.test.ts +5 -4
- package/src/__tests__/injector-v3-suppression.test.ts +373 -47
- package/src/__tests__/intent-routing.test.ts +7 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +117 -15
- package/src/__tests__/notification-decision-strategy.test.ts +3 -3
- package/src/__tests__/oauth-store.test.ts +0 -85
- package/src/__tests__/{context-overflow-policy.test.ts → overflow-policy.test.ts} +1 -1
- package/src/__tests__/parallel-tool.benchmark.test.ts +4 -0
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +29 -9
- package/src/__tests__/persist-unsendable-image.test.ts +4 -4
- package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
- package/src/__tests__/plugin-bootstrap.test.ts +82 -73
- package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
- package/src/__tests__/plugin-types.test.ts +0 -8
- package/src/__tests__/provider-catalog-visibility.test.ts +1 -9
- package/src/__tests__/prune-old-conversations-job.test.ts +99 -0
- package/src/__tests__/registry.test.ts +240 -1
- package/src/__tests__/require-fresh-approval.test.ts +3 -0
- package/src/__tests__/schedule-routes.test.ts +116 -1
- package/src/__tests__/schedule-store.test.ts +28 -0
- package/src/__tests__/schedule-tools.test.ts +94 -1
- package/src/__tests__/server-history-render.test.ts +39 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +13 -0
- package/src/__tests__/skill-projection.benchmark.test.ts +25 -7
- package/src/__tests__/skills.test.ts +202 -0
- package/src/__tests__/slim-skill-category.test.ts +195 -0
- package/src/__tests__/strip-memory-injections.test.ts +33 -39
- package/src/__tests__/test-support/tool-invocation-seed.ts +79 -0
- package/src/__tests__/title-generate-hook.test.ts +9 -7
- package/src/__tests__/tool-audit-listener.test.ts +264 -1
- package/src/__tests__/tool-error-hook.test.ts +4 -3
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +273 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
- package/src/__tests__/tool-start-timestamp.test.ts +218 -0
- package/src/__tests__/tools-get-route.test.ts +202 -0
- package/src/__tests__/workspace-tool-loader.test.ts +319 -0
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +569 -319
- package/src/api/events/tool-result.ts +9 -0
- package/src/api/events/tool-use-start.ts +7 -0
- package/src/api/index.ts +10 -0
- package/src/api/responses/conversation-message.ts +135 -27
- package/src/api/responses/memory-v3-selection-log.ts +4 -4
- package/src/approvals/guardian-request-resolvers.ts +26 -0
- package/src/browser-session/backends/host-bridge.ts +29 -0
- package/src/browser-session/index.ts +1 -0
- package/src/browser-session/types.ts +5 -1
- package/src/cli/commands/__tests__/schedules.test.ts +62 -4
- package/src/cli/commands/__tests__/skills.test.ts +53 -0
- package/src/cli/commands/channel-verification-sessions.ts +6 -6
- package/src/cli/commands/inference-providers.ts +0 -8
- package/src/cli/commands/plugins.ts +2 -2
- package/src/cli/commands/schedules.ts +27 -4
- package/src/cli/commands/skills.ts +187 -146
- package/src/cli/commands/tools.ts +106 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +256 -328
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +6 -2
- package/src/cli/lib/__tests__/plugin-details.test.ts +10 -16
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +2 -2
- package/src/cli/lib/__tests__/search-plugins.test.ts +145 -240
- package/src/cli/lib/install-from-github.ts +187 -117
- package/src/cli/lib/plugin-catalog-cache.ts +9 -9
- package/src/cli/lib/plugin-details.ts +38 -68
- package/src/cli/lib/plugin-marketplace.ts +42 -14
- package/src/cli/lib/search-plugins.ts +29 -129
- package/src/cli/program.ts +2 -0
- package/src/config/bundled-skills/acp/SKILL.md +1 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -0
- package/src/config/bundled-skills/app-control/SKILL.md +1 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +1 -0
- package/src/config/bundled-skills/contacts/SKILL.md +1 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +1 -0
- package/src/config/bundled-skills/followups/SKILL.md +1 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +1 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +1 -0
- package/src/config/bundled-skills/messaging/SKILL.md +1 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -0
- package/src/config/bundled-skills/playbooks/SKILL.md +1 -0
- package/src/config/bundled-skills/schedule/SKILL.md +1 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
- package/src/config/bundled-skills/sequences/SKILL.md +1 -0
- package/src/config/bundled-skills/settings/SKILL.md +1 -0
- package/src/config/bundled-skills/skill-management/SKILL.md +101 -1
- package/src/config/bundled-skills/subagent/SKILL.md +1 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +1 -0
- package/src/config/env-registry.ts +23 -0
- package/src/config/feature-flag-registry.json +17 -81
- package/src/config/loader.ts +5 -22
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/compaction-logs.test.ts +56 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
- package/src/config/schemas/__tests__/memory-v3.test.ts +61 -1
- package/src/config/schemas/compaction-logs.ts +79 -0
- package/src/config/schemas/memory-v2.ts +0 -8
- package/src/config/schemas/memory-v3.ts +104 -33
- package/src/config/seed-inference-profiles.ts +1 -1
- package/src/config/skills.ts +117 -47
- package/src/context/compactor.ts +11 -0
- package/src/context/strip-injections.ts +38 -4
- package/src/credential-execution/feature-gates.ts +0 -21
- package/src/credential-execution/startup-timeout.ts +32 -4
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +140 -91
- package/src/daemon/conversation-agent-loop.ts +123 -658
- package/src/daemon/conversation-error.ts +6 -33
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-runtime-assembly.ts +183 -22
- package/src/daemon/conversation-skill-tools.ts +137 -8
- package/src/daemon/conversation-slash.ts +0 -14
- package/src/daemon/conversation-store.ts +2 -19
- package/src/daemon/conversation-tool-setup.ts +87 -1
- package/src/daemon/conversation.ts +119 -50
- package/src/daemon/external-plugins-bootstrap.ts +36 -95
- package/src/daemon/handlers/config-channels.ts +11 -2
- package/src/daemon/handlers/shared.ts +9 -1
- package/src/daemon/handlers/skills.ts +10 -4
- package/src/daemon/host-app-control-proxy.ts +72 -57
- package/src/daemon/host-browser-proxy.ts +117 -22
- package/src/daemon/lifecycle.ts +34 -5
- package/src/daemon/message-protocol.ts +0 -7
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/skills.ts +17 -0
- package/src/daemon/providers-setup.ts +3 -0
- package/src/daemon/server.ts +3 -3
- package/src/daemon/tool-setup-types.ts +9 -3
- package/src/daemon/trust-context.ts +23 -0
- package/src/daemon/workspace-tools-watcher.ts +324 -0
- package/src/events/tool-audit-listener.ts +78 -16
- package/src/events/tool-metrics-listener.ts +2 -5
- package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +227 -0
- package/src/memory/__tests__/conversation-queries.test.ts +176 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
- package/src/memory/compaction-log-writer-clickhouse.ts +418 -0
- package/src/memory/conversation-crud.ts +134 -3
- package/src/memory/conversation-queries.ts +64 -7
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.test.ts +130 -1
- package/src/memory/embedding-backend.ts +79 -106
- package/src/memory/embedding-gemini.ts +5 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +12 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
- package/src/memory/graph/conversation-graph-memory.ts +36 -25
- package/src/memory/graph/tool-handlers.ts +3 -0
- package/src/memory/job-handlers/cleanup.ts +3 -1
- package/src/memory/jobs-store.ts +0 -28
- package/src/memory/jobs-worker.ts +10 -22
- package/src/memory/memory-marker.ts +29 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +1 -1
- package/src/memory/migrations/268-add-memory-v3-selections.ts +6 -0
- package/src/memory/migrations/270-schedule-description.ts +36 -0
- package/src/memory/migrations/275-tool-invocations-add-skill-id.test.ts +81 -0
- package/src/memory/migrations/275-tool-invocations-add-skill-id.ts +20 -0
- package/src/memory/migrations/276-tool-invocations-created-at-id-index.test.ts +68 -0
- package/src/memory/migrations/276-tool-invocations-created-at-id-index.ts +20 -0
- package/src/memory/migrations/277-add-memory-v3-ever-injected.ts +29 -0
- package/src/memory/migrations/278-tool-invocations-telemetry-columns.test.ts +96 -0
- package/src/memory/migrations/278-tool-invocations-telemetry-columns.ts +39 -0
- package/src/memory/migrations/279-create-skill-loaded-events.test.ts +84 -0
- package/src/memory/migrations/279-create-skill-loaded-events.ts +26 -0
- package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
- package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +16 -0
- package/src/memory/schema/infrastructure.ts +26 -0
- package/src/memory/skill-loaded-events-store.test.ts +160 -0
- package/src/memory/skill-loaded-events-store.ts +95 -0
- package/src/memory/tool-executed-events-store.test.ts +219 -0
- package/src/memory/tool-executed-events-store.ts +102 -0
- package/src/memory/tool-usage-store.ts +15 -3
- package/src/memory/v2/__tests__/consolidation-job.test.ts +117 -12
- package/src/memory/v2/__tests__/consolidation-prompt-flag-gating-guard.test.ts +189 -0
- package/src/memory/v2/__tests__/injected-block-slugs.test.ts +90 -0
- package/src/memory/v2/__tests__/page-store.test.ts +33 -0
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +88 -15
- package/src/memory/v2/activation-store.ts +50 -1
- package/src/memory/v2/consolidation-job.ts +113 -29
- package/src/memory/v2/injected-block-slugs.ts +79 -0
- package/src/memory/v2/injection.ts +6 -1
- package/src/memory/v2/prompts/consolidation.ts +414 -13
- package/src/memory/v2/router.ts +2 -28
- package/src/memory/v2/static-context.ts +1 -1
- package/src/memory/v2/types.ts +16 -0
- package/src/notifications/__tests__/copy-composer.test.ts +244 -0
- package/src/notifications/access-request-copy.ts +298 -0
- package/src/notifications/adapters/slack.ts +3 -3
- package/src/notifications/adapters/telegram.ts +2 -1
- package/src/notifications/copy-composer.ts +49 -267
- package/src/notifications/decision-engine.ts +16 -35
- package/src/notifications/home-feed-side-effect.ts +1 -6
- package/src/oauth/oauth-store.ts +0 -9
- package/src/permissions/checker.test.ts +83 -1
- package/src/permissions/checker.ts +25 -2
- package/src/permissions/gateway-threshold-reader.test.ts +182 -0
- package/src/permissions/gateway-threshold-reader.ts +80 -0
- package/src/platform/client.ts +1 -3
- package/src/platform/feature-gate.ts +3 -12
- package/src/plugin-api/constants.ts +4 -2
- package/src/plugin-api/index.ts +63 -11
- package/src/plugin-api/types.ts +236 -71
- package/src/plugins/defaults/compaction/compact.ts +66 -2
- package/src/plugins/defaults/compaction/context-overflow-reducer.ts +240 -32
- package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
- package/src/{daemon/context-overflow-policy.ts → plugins/defaults/compaction/overflow-policy.ts} +1 -1
- package/src/plugins/defaults/compaction/window-manager.ts +303 -1
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +173 -0
- package/src/plugins/defaults/empty-response/hooks/stop.ts +11 -115
- package/src/plugins/defaults/empty-response/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +50 -0
- package/src/plugins/defaults/history-repair/hooks/stop.ts +22 -0
- package/src/plugins/defaults/history-repair/repair-state-store.ts +51 -0
- package/src/plugins/defaults/history-repair/terminal.ts +39 -2
- package/src/plugins/defaults/image-recovery/detect.ts +25 -0
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +73 -0
- package/src/plugins/defaults/image-recovery/hooks/stop.ts +22 -0
- package/src/plugins/defaults/image-recovery/image-recovery-state-store.ts +48 -0
- package/src/plugins/defaults/image-recovery/package.json +14 -0
- package/src/{daemon/persist-unsendable-image.ts → plugins/defaults/image-recovery/recover.ts} +67 -14
- package/src/plugins/defaults/index.ts +71 -5
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +76 -112
- package/src/plugins/defaults/memory-retrieval/hooks/{user-prompt-submit-temp.ts → user-prompt-submit.ts} +83 -74
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +14 -8
- package/src/plugins/defaults/memory-retrieval/injectors.ts +2 -18
- package/src/plugins/defaults/memory-retrieval/package.json +14 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1157 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +683 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +161 -140
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +160 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +335 -316
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +145 -53
- package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +38 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +18 -8
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +112 -71
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +192 -51
- package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +4 -16
- package/src/plugins/defaults/memory-v3-shadow/card.test.ts +173 -0
- package/src/plugins/defaults/memory-v3-shadow/card.ts +116 -0
- package/src/plugins/defaults/memory-v3-shadow/core-set.test.ts +104 -0
- package/src/plugins/defaults/memory-v3-shadow/core-set.ts +59 -0
- package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.test.ts +305 -0
- package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.ts +278 -0
- package/src/plugins/defaults/memory-v3-shadow/hot-set.test.ts +138 -0
- package/src/plugins/defaults/memory-v3-shadow/hot-set.ts +85 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +331 -24
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +119 -13
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +169 -114
- package/src/plugins/defaults/memory-v3-shadow/page-content.ts +47 -16
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +144 -66
- package/src/plugins/defaults/memory-v3-shadow/prune.test.ts +758 -0
- package/src/plugins/defaults/memory-v3-shadow/prune.ts +471 -0
- package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +68 -16
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +19 -12
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +96 -43
- package/src/plugins/defaults/memory-v3-shadow/types.ts +34 -17
- package/src/plugins/defaults/title-generate/hooks/stop.ts +9 -11
- package/src/plugins/pipeline.ts +8 -5
- package/src/plugins/types.ts +5 -51
- package/src/providers/cache-control.ts +26 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -2
- package/src/providers/model-catalog.ts +13 -1
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +147 -0
- package/src/providers/openai/chat-completions-provider.ts +46 -0
- package/src/providers/openai/responses-provider.ts +45 -0
- package/src/providers/registry.ts +0 -8
- package/src/runtime/__tests__/agent-wake.test.ts +0 -1
- package/src/runtime/agent-wake.ts +13 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +151 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -62
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +31 -11
- package/src/runtime/routes/acp-routes.test.ts +106 -0
- package/src/runtime/routes/acp-routes.ts +248 -2
- package/src/runtime/routes/browser-tabs-routes.ts +1 -1
- package/src/runtime/routes/channel-verification-routes.ts +14 -5
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +0 -14
- package/src/runtime/routes/consolidation-routes.ts +6 -82
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +71 -0
- package/src/runtime/routes/identity-routes.ts +8 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -45
- package/src/runtime/routes/plugins-routes.ts +34 -45
- package/src/runtime/routes/schedule-routes.ts +43 -5
- package/src/runtime/routes/settings-routes.ts +140 -15
- package/src/runtime/routes/skills-routes.ts +18 -6
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
- package/src/runtime/services/conversation-serializer.ts +38 -1
- package/src/runtime/verification-outbound-actions.ts +147 -2
- package/src/runtime/verification-templates.ts +29 -3
- package/src/schedule/schedule-store.ts +19 -0
- package/src/skills/catalog-install.ts +77 -13
- package/src/tasks/task-scheduler.ts +1 -0
- package/src/telemetry/types.ts +66 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +542 -13
- package/src/telemetry/usage-telemetry-reporter.ts +213 -20
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +49 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +29 -5
- package/src/tools/browser/browser-execution.ts +27 -9
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +380 -4
- package/src/tools/browser/cdp-client/__tests__/host-bridge-cdp-client.test.ts +107 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +6 -1
- package/src/tools/browser/cdp-client/factory.ts +217 -17
- package/src/tools/browser/cdp-client/host-bridge-cdp-client.ts +67 -0
- package/src/tools/browser/cdp-client/types.ts +22 -2
- package/src/tools/credential-execution/make-authenticated-request.ts +2 -1
- package/src/tools/credential-execution/manage-secure-command-tool.ts +169 -164
- package/src/tools/credential-execution/run-authenticated-command.ts +2 -1
- package/src/tools/executor.ts +39 -7
- package/src/tools/registry.ts +387 -5
- package/src/tools/schedule/create.ts +16 -0
- package/src/tools/schedule/list.ts +12 -4
- package/src/tools/schedule/update.ts +12 -0
- package/src/tools/skills/load.ts +11 -6
- package/src/tools/terminal/safe-env.ts +2 -0
- package/src/tools/types.ts +65 -9
- package/src/tools/workspace-tools/loader.ts +673 -0
- package/src/usage/attribution.ts +28 -0
- package/src/util/device-id.ts +17 -3
- package/src/util/platform.ts +16 -0
- package/tsconfig.plugin-api.json +13 -0
- package/src/__tests__/plugin-external-api.test.ts +0 -68
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -355
- package/src/daemon/message-types/browser.ts +0 -10
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +0 -36
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +0 -37
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +0 -106
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +0 -44
- package/src/plugins/defaults/memory-v3-shadow/working-set.ts +0 -91
- package/src/plugins/external-api.ts +0 -114
- package/src/plugins/plugin-skill-contributions.ts +0 -292
|
@@ -1,54 +1,57 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Memory v3 — orchestrator composing the
|
|
2
|
+
* Memory v3 — orchestrator composing the candidate lanes into one turn.
|
|
3
3
|
*
|
|
4
4
|
* Each turn runs:
|
|
5
|
-
* 1. Candidate generation over three deterministic lanes:
|
|
5
|
+
* 1. Candidate generation over three deterministic finder lanes:
|
|
6
6
|
* - the section-grain BM25 needle (`SectionNeedle.query`, KB articles),
|
|
7
7
|
* - the dense lane (`denseLane`, KD articles), and
|
|
8
8
|
* - link-graph edge expansion (`edgeExpand`) over the top needle+dense
|
|
9
9
|
* article seeds.
|
|
10
10
|
* Each lane only ever ADDS candidates, so the pool is recall-safe by
|
|
11
11
|
* construction.
|
|
12
|
-
* 2. Build the
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* the
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
12
|
+
* 2. Build the candidate pool in CACHE ORDER: the stable prefix —
|
|
13
|
+
* `[...core (file order), ...hot (score order)]`, both computed at lane
|
|
14
|
+
* init — followed by the finder candidates (needle → dense → edge
|
|
15
|
+
* surfacing order). The stable prefix is identical across consecutive
|
|
16
|
+
* turns while the lanes are unchanged (lane invalidation at consolidation
|
|
17
|
+
* is the recompute cadence), so the selector input's leading segment
|
|
18
|
+
* rides the provider KV cache (the cache breakpoint itself lives in
|
|
19
|
+
* `pool-select.ts`).
|
|
20
|
+
*
|
|
21
|
+
* Stable-prefix candidates render as FULL CARDS (`renderCard` — head
|
|
22
|
+
* section + TOC), pre-rendered at lane init (`prefixCards`) so the
|
|
23
|
+
* rendered prefix is byte-identical across turns. Finder candidates
|
|
24
|
+
* render as compact snippet lines: the matched section's text (or the
|
|
25
|
+
* curated `links` description for an edge hit), falling back to the
|
|
26
|
+
* page's lead-section text when no match text exists.
|
|
27
|
+
*
|
|
28
|
+
* The finder tail is NOT deduped against the stable prefix: a finder hit
|
|
29
|
+
* on a core/hot page keeps its matched-section line (and its
|
|
30
|
+
* `matchedSections` ref + `lanes.finder` entry), so the selector and the
|
|
31
|
+
* section spotlight see that page's CURRENT relevance even though the
|
|
32
|
+
* page itself sits in the stable prefix. The selector dedupes selections
|
|
33
|
+
* by slug.
|
|
22
34
|
* 3. A SINGLE forced-tool select (`selectPool`) over the whole pool. The
|
|
23
|
-
* result is this turn's selections.
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* EARLIER turns.
|
|
27
|
-
* 5. Final injection = unique union of this turn's selected slugs and that
|
|
28
|
-
* carried-forward set, so pages selected on earlier turns carry forward
|
|
29
|
-
* even when this turn does not re-select them.
|
|
30
|
-
* 6. Record this turn's selections into the working set for LATER turns. This
|
|
31
|
-
* runs AFTER the snapshot so the cap is spent on genuinely carried pages,
|
|
32
|
-
* not on this turn's selections (which are injected directly) — otherwise a
|
|
33
|
-
* turn selecting more pages than the cap would evict the entire carry.
|
|
35
|
+
* result is this turn's selections — current turn only. Cross-turn
|
|
36
|
+
* persistence is the injector's job (net-new blocks frozen into history),
|
|
37
|
+
* not a per-turn re-rendered carry set.
|
|
34
38
|
*/
|
|
35
39
|
|
|
36
40
|
import type { AssistantConfig } from "../../../config/schema.js";
|
|
37
41
|
import { denseLane } from "./dense.js";
|
|
38
42
|
import type { EdgeGraph } from "./edge.js";
|
|
39
43
|
import { edgeExpand } from "./edge.js";
|
|
40
|
-
import type { PoolCandidate } from "./pool-select.js";
|
|
44
|
+
import type { PoolCandidate, StableCandidate } from "./pool-select.js";
|
|
41
45
|
import { selectPool } from "./pool-select.js";
|
|
42
46
|
import type { SectionNeedle } from "./section-needle.js";
|
|
43
47
|
import type {
|
|
44
|
-
|
|
48
|
+
FinderLane,
|
|
45
49
|
MemoryRoutingTurn,
|
|
46
50
|
Section,
|
|
47
51
|
SectionIndex,
|
|
48
52
|
SelectedPage,
|
|
49
53
|
Slug,
|
|
50
54
|
} from "./types.js";
|
|
51
|
-
import { WorkingSet } from "./working-set.js";
|
|
52
55
|
|
|
53
56
|
/** Default number of BM25 needle articles to fold into the pool. */
|
|
54
57
|
export const DEFAULT_NEEDLE_K = 100;
|
|
@@ -62,7 +65,18 @@ export interface OrchestrateDeps {
|
|
|
62
65
|
* collection. */
|
|
63
66
|
denseConfig: AssistantConfig;
|
|
64
67
|
edgeGraph: EdgeGraph;
|
|
65
|
-
|
|
68
|
+
/** The curated core set in file order (existence-filtered at lane init).
|
|
69
|
+
* Heads the stable prefix of the candidate pool. */
|
|
70
|
+
coreSlugs: Slug[];
|
|
71
|
+
/** The frecency hot set in score order (computed at lane init with the core
|
|
72
|
+
* set excluded). Follows core in the stable prefix. */
|
|
73
|
+
hotSlugs: Slug[];
|
|
74
|
+
/** Pre-rendered FULL cards for the stable-prefix slugs, keyed by slug.
|
|
75
|
+
* Rendered ONCE at lane init so the selector's stable prefix is
|
|
76
|
+
* byte-identical across turns (the cache contract). Every core/hot slug
|
|
77
|
+
* MUST have an entry — a missing card is a lane-init bug and throws
|
|
78
|
+
* (silently degrading would violate the byte-stable-prefix contract). */
|
|
79
|
+
prefixCards: ReadonlyMap<Slug, string>;
|
|
66
80
|
/** Number of BM25 needle articles. Defaults to {@link DEFAULT_NEEDLE_K}. */
|
|
67
81
|
needleK?: number;
|
|
68
82
|
/** Number of dense-lane articles. Defaults to {@link DEFAULT_DENSE_K}. */
|
|
@@ -78,23 +92,43 @@ export interface OrchestrateDeps {
|
|
|
78
92
|
edgeCap?: number;
|
|
79
93
|
}
|
|
80
94
|
|
|
95
|
+
/** A finder-lane candidate: the slug, the descriptor that justified it, and
|
|
96
|
+
* the finder lane that FIRST surfaced it (needle → dense → edge precedence). */
|
|
97
|
+
export interface FinderCandidate {
|
|
98
|
+
slug: Slug;
|
|
99
|
+
descriptor: string;
|
|
100
|
+
lane: FinderLane;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The three candidate lanes in cache order. `core` and `hot` are the stable
|
|
105
|
+
* prefix (byte-identical across turns while lanes are unchanged); `finder` is
|
|
106
|
+
* the dynamic tail and MAY repeat a stable-prefix slug (a finder hit on a
|
|
107
|
+
* core/hot page is kept so its current relevance stays visible downstream).
|
|
108
|
+
*/
|
|
109
|
+
export interface OrchestrateLanes {
|
|
110
|
+
/** Curated core set, file order. */
|
|
111
|
+
core: Slug[];
|
|
112
|
+
/** Frecency hot set, score order (never overlaps core). */
|
|
113
|
+
hot: Slug[];
|
|
114
|
+
/** Finder candidates in surfacing order, deduped among themselves only. */
|
|
115
|
+
finder: FinderCandidate[];
|
|
116
|
+
}
|
|
117
|
+
|
|
81
118
|
export interface OrchestrateResult {
|
|
82
|
-
/** This turn's selections, deduped by slug (pinned flags ORed
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
* one lane records the highest-precedence one. Consumed by the selection
|
|
96
|
-
* telemetry to attribute each selection to its true lane. */
|
|
97
|
-
laneBySlug: Map<Slug, CandidateLane>;
|
|
119
|
+
/** This turn's selections, deduped by slug (pinned flags ORed; the dedup is
|
|
120
|
+
* `selectPool`'s contract). Current turn only — there is no
|
|
121
|
+
* carried-forward set unioned in. */
|
|
122
|
+
selections: SelectedPage[];
|
|
123
|
+
/** The matched `Section` for each candidate slug that had one, keyed by slug.
|
|
124
|
+
* Populated from the finder-lane hits — including hits on core/hot pages —
|
|
125
|
+
* and consumed by the injector to render each selected slug's matched
|
|
126
|
+
* section (progressive disclosure). */
|
|
127
|
+
matchedSections: Map<Slug, Section>;
|
|
128
|
+
/** The candidate lanes in cache order; see {@link OrchestrateLanes}. Consumed
|
|
129
|
+
* by the selection telemetry (lane attribution) and the downstream selector
|
|
130
|
+
* rendering/spotlight. */
|
|
131
|
+
lanes: OrchestrateLanes;
|
|
98
132
|
}
|
|
99
133
|
|
|
100
134
|
/** Stable-order de-duplication preserving first occurrence. */
|
|
@@ -110,6 +144,13 @@ export async function orchestrate(
|
|
|
110
144
|
const denseK = deps.denseK ?? DEFAULT_DENSE_K;
|
|
111
145
|
const { sections } = deps.sectionIndex;
|
|
112
146
|
|
|
147
|
+
// The stable prefix: core (file order) then hot (score order). Hot is
|
|
148
|
+
// computed with core excluded at lane init; the filter here is a cheap
|
|
149
|
+
// defensive dedup so a misbehaving lane can never double-list a slug.
|
|
150
|
+
const core = deps.coreSlugs;
|
|
151
|
+
const hot = deps.hotSlugs.filter((slug) => !core.includes(slug));
|
|
152
|
+
const stablePrefix = new Set<Slug>([...core, ...hot]);
|
|
153
|
+
|
|
113
154
|
// Step 1: needle (sync BM25) and dense (async embed + Qdrant) lanes run in
|
|
114
155
|
// parallel. Both return distinct articles each tagged with their best-scoring
|
|
115
156
|
// section index/ordinal.
|
|
@@ -118,43 +159,42 @@ export async function orchestrate(
|
|
|
118
159
|
denseLane(deps.denseConfig, turn.currentMessage, denseK),
|
|
119
160
|
]);
|
|
120
161
|
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
// `
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
162
|
+
// `matchedSections` records the matched `Section` (when one is known) for
|
|
163
|
+
// every finder hit — INCLUDING hits on stable-prefix slugs — for downstream
|
|
164
|
+
// injection/spotlight. `finder` accumulates one entry per distinct
|
|
165
|
+
// finder-surfaced article; the first lane to surface a slug wins the entry,
|
|
166
|
+
// so the needle → dense → edge call order encodes lane precedence.
|
|
167
|
+
const matchedSections = new Map<Slug, Section>();
|
|
168
|
+
const finder: FinderCandidate[] = [];
|
|
169
|
+
const finderSeen = new Set<Slug>();
|
|
127
170
|
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
// a curated `links` description). The first lane to surface a slug wins the
|
|
132
|
-
// pool entry, the recorded section, AND the recorded lane — so the
|
|
133
|
-
// needle → dense → edge call order encodes lane precedence.
|
|
134
|
-
const addCandidate = (
|
|
171
|
+
// `descriptor` overrides the section text when supplied (the edge lane
|
|
172
|
+
// prefers a curated `links` description).
|
|
173
|
+
const addFinder = (
|
|
135
174
|
slug: Slug,
|
|
136
175
|
section: Section | undefined,
|
|
137
176
|
descriptor: string | undefined,
|
|
138
|
-
lane:
|
|
177
|
+
lane: FinderLane,
|
|
139
178
|
): void => {
|
|
140
|
-
if (section && !
|
|
141
|
-
|
|
179
|
+
if (section && !matchedSections.has(slug)) {
|
|
180
|
+
matchedSections.set(slug, section);
|
|
142
181
|
}
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
|
|
182
|
+
if (finderSeen.has(slug)) return;
|
|
183
|
+
finderSeen.add(slug);
|
|
184
|
+
finder.push({
|
|
146
185
|
slug,
|
|
147
186
|
descriptor: descriptor ?? section?.text ?? "",
|
|
187
|
+
lane,
|
|
148
188
|
});
|
|
149
189
|
};
|
|
150
190
|
|
|
151
|
-
// Step
|
|
191
|
+
// Step 1a: needle hits — descriptor is the matched section's text. `section`
|
|
152
192
|
// is an index into `sections`.
|
|
153
193
|
for (const hit of needled) {
|
|
154
|
-
|
|
194
|
+
addFinder(hit.article, sections[hit.section], undefined, "needle");
|
|
155
195
|
}
|
|
156
196
|
|
|
157
|
-
// Step
|
|
197
|
+
// Step 1b: dense hits — `section` is the matched ORDINAL; resolve it to the
|
|
158
198
|
// concrete `Section` via the section index. Falls back to undefined (blank
|
|
159
199
|
// descriptor) if the ordinal is not in the in-memory index.
|
|
160
200
|
for (const hit of densed) {
|
|
@@ -163,7 +203,7 @@ export async function orchestrate(
|
|
|
163
203
|
// so `byArticle` holds exactly the live pages (synthetic capability slugs
|
|
164
204
|
// included) — only truly-deleted pages are dropped here.
|
|
165
205
|
if (!deps.sectionIndex.byArticle.has(hit.article)) continue;
|
|
166
|
-
|
|
206
|
+
addFinder(
|
|
167
207
|
hit.article,
|
|
168
208
|
sectionByOrdinal(deps.sectionIndex, hit.article, hit.section),
|
|
169
209
|
undefined,
|
|
@@ -171,16 +211,19 @@ export async function orchestrate(
|
|
|
171
211
|
);
|
|
172
212
|
}
|
|
173
213
|
|
|
174
|
-
// Step
|
|
175
|
-
// skips slugs already
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
//
|
|
214
|
+
// Step 1c: edge expansion over the top needle+dense article seeds. `alive`
|
|
215
|
+
// skips slugs already in the pool — finder-surfaced AND stable-prefix slugs
|
|
216
|
+
// (an edge hit carries no matched section, so re-surfacing a core/hot page
|
|
217
|
+
// adds nothing; needle/dense hits on those pages ARE kept for their
|
|
218
|
+
// sections). An edge-only page was surfaced because its NEIGHBOUR matched —
|
|
219
|
+
// the query did not lexically hit the page itself, so `bestSection` returns
|
|
220
|
+
// its first/lead section on a zero-score match. That lead is often empty for
|
|
221
|
+
// heading-structured pages, and it is the curated `links` description (not
|
|
222
|
+
// the lead) that made the candidate relevant. So we record NO matched
|
|
223
|
+
// section for edge-only pages (pass `undefined`), which makes injection fall
|
|
224
|
+
// back to the FULL page — where the link-relevant content lives.
|
|
225
|
+
// `bestSection`'s text is kept only as the select-pool DESCRIPTOR fallback
|
|
226
|
+
// for when the traversed edge carried no curated `links` description.
|
|
184
227
|
const seeds = unique<Slug>([
|
|
185
228
|
...needled.map((h) => h.article),
|
|
186
229
|
...densed.map((h) => h.article),
|
|
@@ -189,12 +232,12 @@ export async function orchestrate(
|
|
|
189
232
|
seedCount: deps.edgeSeeds,
|
|
190
233
|
perSeed: deps.edgePerSeed,
|
|
191
234
|
cap: deps.edgeCap,
|
|
192
|
-
alive: (slug) => !
|
|
235
|
+
alive: (slug) => !finderSeen.has(slug) && !stablePrefix.has(slug),
|
|
193
236
|
});
|
|
194
237
|
for (const neighbor of surfaced) {
|
|
195
238
|
const best = deps.needle.bestSection(neighbor.article, turn.currentMessage);
|
|
196
239
|
const fallbackDescriptor = best >= 0 ? sections[best]?.text : undefined;
|
|
197
|
-
|
|
240
|
+
addFinder(
|
|
198
241
|
neighbor.article,
|
|
199
242
|
undefined,
|
|
200
243
|
neighbor.description ?? fallbackDescriptor,
|
|
@@ -202,45 +245,45 @@ export async function orchestrate(
|
|
|
202
245
|
);
|
|
203
246
|
}
|
|
204
247
|
|
|
205
|
-
// Step
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
248
|
+
// Step 2: assemble the selector pool in cache order — the stable prefix
|
|
249
|
+
// (core then hot) as FULL CARDS, then the finder tail. Cards are
|
|
250
|
+
// pre-rendered at lane init (`prefixCards`): query- AND
|
|
251
|
+
// conversation-state-INDEPENDENT by design, so the rendered prefix is
|
|
252
|
+
// byte-identical across turns while the lanes are unchanged. The tail is
|
|
253
|
+
// NOT deduped against the prefix — a finder hit on a core/hot page renders
|
|
254
|
+
// its own snippet line so its CURRENT relevance stays visible; `selectPool`
|
|
255
|
+
// dedupes selections by slug. Finder candidates with no match text fall
|
|
256
|
+
// back to the page's lead-section snippet.
|
|
257
|
+
const stable: StableCandidate[] = [...core, ...hot].map((slug) => {
|
|
258
|
+
const card = deps.prefixCards.get(slug);
|
|
259
|
+
if (card === undefined) {
|
|
260
|
+
// Lane init renders a card for every core/hot slug; a hole here means
|
|
261
|
+
// the lanes and the card map are out of sync. Throw rather than render
|
|
262
|
+
// a degraded card — the caller (observeTurn) logs and skips the turn,
|
|
263
|
+
// which is better than silently breaking the byte-stable prefix.
|
|
264
|
+
throw new Error(
|
|
265
|
+
`memory-v3: no pre-rendered card for stable-prefix slug "${slug}"`,
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return { slug, card };
|
|
269
|
+
});
|
|
270
|
+
const finderTail: PoolCandidate[] = finder.map((c) => ({
|
|
271
|
+
slug: c.slug,
|
|
272
|
+
descriptor:
|
|
273
|
+
c.descriptor.trim().length > 0
|
|
274
|
+
? c.descriptor
|
|
275
|
+
: leadSectionText(deps.sectionIndex, c.slug),
|
|
276
|
+
}));
|
|
232
277
|
|
|
233
|
-
// Step
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
278
|
+
// Step 3: a SINGLE forced-tool select over the cache-ordered pool. The
|
|
279
|
+
// selections come back slug-deduped (pinned flags ORed) — `selectPool`'s
|
|
280
|
+
// contract.
|
|
281
|
+
const selections = await selectPool({ stable, finder: finderTail }, turn);
|
|
237
282
|
|
|
238
283
|
return {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
sectionBySlug,
|
|
243
|
-
laneBySlug,
|
|
284
|
+
selections,
|
|
285
|
+
matchedSections,
|
|
286
|
+
lanes: { core, hot, finder },
|
|
244
287
|
};
|
|
245
288
|
}
|
|
246
289
|
|
|
@@ -264,3 +307,15 @@ function sectionByOrdinal(
|
|
|
264
307
|
}
|
|
265
308
|
return undefined;
|
|
266
309
|
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* The text of an article's LEAD (first) section, or `""` when the article has
|
|
313
|
+
* no indexed sections. Used as the finder-line snippet fallback when a
|
|
314
|
+
* candidate carries no match text (e.g. an edge hit with neither a curated
|
|
315
|
+
* description nor a scoring section) — the lead is the closest free
|
|
316
|
+
* approximation of the card head.
|
|
317
|
+
*/
|
|
318
|
+
function leadSectionText(index: SectionIndex, article: Slug): string {
|
|
319
|
+
const first = index.byArticle.get(article)?.[0];
|
|
320
|
+
return first === undefined ? "" : (index.sections[first]?.text ?? "");
|
|
321
|
+
}
|
|
@@ -1,22 +1,24 @@
|
|
|
1
|
+
import { injectedConceptHeader } from "../../../memory/v2/injected-block-slugs.js";
|
|
1
2
|
import { readPage, renderPageContent } from "../../../memory/v2/page-store.js";
|
|
2
3
|
import { getWorkspaceDir } from "../../../util/platform.js";
|
|
3
4
|
import { renderCapabilityContent } from "./capabilities.js";
|
|
5
|
+
import { renderCard } from "./card.js";
|
|
4
6
|
import type { Section, Slug } from "./types.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Prefix `body` with the `# memory/concepts/<slug>.md` header marker the v3
|
|
8
|
-
* `<memory>` block uses
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* `<memory>` block uses (shared builder: `injectedConceptHeader`, so the
|
|
11
|
+
* renderers, the card renderer, and the read-side parsers all agree on the
|
|
12
|
+
* exact bytes).
|
|
11
13
|
*/
|
|
12
14
|
function withConceptHeader(slug: Slug, body: string): string {
|
|
13
|
-
return
|
|
15
|
+
return `${injectedConceptHeader(slug)}\n${body}`;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Render a selected page's full content for the v3 `<memory>` block. Mirrors
|
|
18
20
|
* the v2 dynamic-memory layout (`# memory/concepts/<slug>.md\n<frontmatter+body>`)
|
|
19
|
-
* so the
|
|
21
|
+
* so the v3 block reads like v2's. A missing page (or any read
|
|
20
22
|
* failure) degrades to "" — `renderMemoryBlock` still emits a line for the
|
|
21
23
|
* slug, and a blank section is preferable to throwing into the turn.
|
|
22
24
|
*
|
|
@@ -25,9 +27,11 @@ function withConceptHeader(slug: Slug, body: string): string {
|
|
|
25
27
|
* `readPage`. A non-null result (including "") means the slug was a capability
|
|
26
28
|
* slug and was handled here.
|
|
27
29
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
30
|
+
* INSPECTOR-ONLY (as the `renderV3SectionContent` fallback): live injection
|
|
31
|
+
* freezes compact CARDS into history via {@link renderV3CardContent} — it no
|
|
32
|
+
* longer renders full pages, so this output is an APPROXIMATE reconstruction
|
|
33
|
+
* for the inspector selection log (`selection-log-store.ts`), not what the
|
|
34
|
+
* model saw.
|
|
31
35
|
*/
|
|
32
36
|
export async function renderV3PageContent(slug: Slug): Promise<string> {
|
|
33
37
|
const capability = renderCapabilityContent(slug);
|
|
@@ -44,18 +48,45 @@ export async function renderV3PageContent(slug: Slug): Promise<string> {
|
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
/**
|
|
47
|
-
* Render a
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
51
|
+
* Render a selected page's compact CARD for the v3 frozen-injection layer:
|
|
52
|
+
* the `# memory/concepts/<slug>.md` header, the page's head section, and a
|
|
53
|
+
* one-line section TOC (see `card.ts`). Cards are the persistent injection
|
|
54
|
+
* unit — frozen into history once and deduped by the everInjected store.
|
|
55
|
+
*
|
|
56
|
+
* - Capability slugs (skills, `assistant` CLI commands) have no on-disk page
|
|
57
|
+
* and no meaningful head/TOC split, so they render their full capability
|
|
58
|
+
* content via {@link renderCapabilityContent} (its own `# Skill:` /
|
|
59
|
+
* `# CLI command:` header) instead of a card.
|
|
60
|
+
* - A missing page or any read failure degrades to "" — the injector skips
|
|
61
|
+
* empty cards rather than throwing into the turn.
|
|
62
|
+
*/
|
|
63
|
+
export async function renderV3CardContent(slug: Slug): Promise<string> {
|
|
64
|
+
const capability = renderCapabilityContent(slug);
|
|
65
|
+
if (capability !== null) return capability;
|
|
66
|
+
try {
|
|
67
|
+
const page = await readPage(getWorkspaceDir(), slug);
|
|
68
|
+
if (!page) return "";
|
|
69
|
+
return renderCard(slug, renderPageContent(page));
|
|
70
|
+
} catch {
|
|
71
|
+
return "";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Render a slug's matched section under the `# memory/concepts/<slug>.md`
|
|
77
|
+
* header marker, the same marker as {@link renderV3PageContent}.
|
|
78
|
+
*
|
|
79
|
+
* INSPECTOR-ONLY: live injection freezes cards ({@link renderV3CardContent})
|
|
80
|
+
* and re-renders the ephemeral spotlight separately; this per-section render
|
|
81
|
+
* remains for the inspector selection log (`selection-log-store.ts`), which
|
|
82
|
+
* reconstructs an approximate view of a turn's selection after the fact.
|
|
52
83
|
*
|
|
53
84
|
* - Capability slugs (skills, `assistant` CLI commands) have no on-disk
|
|
54
85
|
* section, so they always render their capability content via
|
|
55
86
|
* {@link renderCapabilityContent}, never a section.
|
|
56
|
-
* - When `section` is undefined (e.g.
|
|
57
|
-
* match), fall back to {@link renderV3PageContent} (the full/lead
|
|
58
|
-
* slug still contributes content.
|
|
87
|
+
* - When `section` is undefined (e.g. an edge-only or stable-prefix page with
|
|
88
|
+
* no current match), fall back to {@link renderV3PageContent} (the full/lead
|
|
89
|
+
* page) so the slug still contributes content.
|
|
59
90
|
*/
|
|
60
91
|
export async function renderV3SectionContent(
|
|
61
92
|
slug: Slug,
|