@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
|
@@ -4,136 +4,100 @@
|
|
|
4
4
|
* After the agent loop compacts a conversation mid-turn it must re-apply the
|
|
5
5
|
* runtime injections compaction stripped — the NOW.md scratchpad, PKB context,
|
|
6
6
|
* memory-v2 static block, workspace top-level context, and Slack chronological
|
|
7
|
-
* snapshot — onto the compacted history before the turn continues. This hook
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* snapshot — onto the compacted history before the turn continues. This hook is
|
|
8
|
+
* the memory system's home for that transform: it re-applies the injections via
|
|
9
|
+
* {@link applyRuntimeInjections}, writes the edited history back onto the
|
|
10
|
+
* context, and re-tracks the memory graph's cached nodes against the re-injected
|
|
11
|
+
* history. The injection blocks the transform captures are not needed by the
|
|
12
|
+
* re-injection caller, so only the messages propagate.
|
|
12
13
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* The
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* Every per-turn input the live conversation can supply is self-resolved from
|
|
15
|
+
* it (looked up by id) rather than threaded in by the loop:
|
|
16
|
+
* - The trust snapshot comes from the conversation's turn-start trust snapshot
|
|
17
|
+
* ({@link Conversation.currentTurnTrustContext}), and the inbound actor
|
|
18
|
+
* context from the turn-start actor snapshot
|
|
19
|
+
* ({@link Conversation.currentTurnInboundActorContext}) — both frozen at turn
|
|
20
|
+
* start, not read live. Post-compaction runs mid-turn in a later tool
|
|
21
|
+
* iteration, where the live trust can be overwritten by a concurrent
|
|
22
|
+
* request's actor and the contact/member registry the actor context derives
|
|
23
|
+
* from can be mutated by contact tools; reading the frozen snapshots re-emits
|
|
24
|
+
* the values the turn's initial assembly resolved.
|
|
25
|
+
* - The memory graph handle comes from the plugin's own conversation-keyed
|
|
26
|
+
* registry ({@link getLiveGraphMemory}).
|
|
27
|
+
* - The call site and transcript inputs self-resolve inside
|
|
28
|
+
* {@link applyRuntimeInjections}.
|
|
18
29
|
*
|
|
19
|
-
* The
|
|
20
|
-
*
|
|
21
|
-
* threaded in by the loop — it is memory-retrieval-specific state, not
|
|
22
|
-
* something the generic loop should carry.
|
|
30
|
+
* The loop supplies only the irreducible turn-identity fields on the public
|
|
31
|
+
* {@link PostCompactContext}.
|
|
23
32
|
*/
|
|
24
33
|
|
|
34
|
+
import type { PluginHookFn, PostCompactContext } from "@vellumai/plugin-api";
|
|
35
|
+
|
|
36
|
+
import { getConfig } from "../../../../config/loader.js";
|
|
37
|
+
import { findConversationOrSubagent } from "../../../../daemon/conversation-registry.js";
|
|
25
38
|
import {
|
|
26
39
|
applyRuntimeInjections,
|
|
27
|
-
|
|
28
|
-
type InjectionMode,
|
|
29
|
-
type RuntimeInjectionResult,
|
|
40
|
+
resolveTurnModelProfileLabel,
|
|
30
41
|
} from "../../../../daemon/conversation-runtime-assembly.js";
|
|
31
42
|
import {
|
|
43
|
+
FALLBACK_TURN_TRUST,
|
|
32
44
|
resolveTrustClass,
|
|
33
|
-
type TrustContext,
|
|
34
45
|
} from "../../../../daemon/trust-context.js";
|
|
35
46
|
import { getLiveGraphMemory } from "../../../../memory/graph/conversation-graph-memory.js";
|
|
36
|
-
import type { Message } from "../../../../providers/types.js";
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Everything the post-compaction hook needs, supplied by the agent loop from
|
|
40
|
-
* its own working state. Re-injection inputs migrate loop-ward by growing this
|
|
41
|
-
* type; the loop hands the hook an object of this shape when it calls
|
|
42
|
-
* {@link postCompact} directly.
|
|
43
|
-
*
|
|
44
|
-
* The turn-identity fields are flat here: `conversationId` is the key the
|
|
45
|
-
* re-injection resolves the live conversation through (and the only one that,
|
|
46
|
-
* together with `requestId` and `trust`, cannot be recovered from that live
|
|
47
|
-
* conversation), while `turnIndex` and `callSite` are intentionally omitted so
|
|
48
|
-
* {@link applyRuntimeInjections} self-resolves them from the live conversation.
|
|
49
|
-
* The memory graph handle is likewise sourced internally via
|
|
50
|
-
* {@link getLiveGraphMemory} rather than threaded in.
|
|
51
|
-
*/
|
|
52
|
-
export interface PostCompactContext {
|
|
53
|
-
/** Compacted message history to re-inject onto. */
|
|
54
|
-
history: Message[];
|
|
55
|
-
/**
|
|
56
|
-
* Stable ID for the current request, forwarded onto the injector turn
|
|
57
|
-
* context. The one turn-identity field that cannot be recovered from the
|
|
58
|
-
* live conversation, so the loop supplies it.
|
|
59
|
-
*/
|
|
60
|
-
requestId: string | undefined;
|
|
61
|
-
/**
|
|
62
|
-
* Conversation the turn is scoped to. The key the re-injection resolves the
|
|
63
|
-
* live conversation (and its channel/trust/transcript state) through, so the
|
|
64
|
-
* loop always supplies it.
|
|
65
|
-
*/
|
|
66
|
-
conversationId: string;
|
|
67
|
-
/**
|
|
68
|
-
* Trust classification and channel identity for the inbound actor, forwarded
|
|
69
|
-
* onto the injector turn context and used to gate the memory-graph re-track.
|
|
70
|
-
* Supplied by the loop as the turn-start snapshot rather than re-resolved
|
|
71
|
-
* mid-turn.
|
|
72
|
-
*/
|
|
73
|
-
trust: TrustContext;
|
|
74
|
-
/**
|
|
75
|
-
* Whether the in-flight turn has no human present to answer clarification
|
|
76
|
-
* questions. Resolved once by the agent loop at turn start (from its
|
|
77
|
-
* `isInteractive` option, which can fall back to mutable client/headless
|
|
78
|
-
* state that flips mid-turn on SSE reconnect) and handed to the hook here, so
|
|
79
|
-
* re-injection uses the loop's turn-start snapshot rather than re-reading
|
|
80
|
-
* live conversation state.
|
|
81
|
-
*/
|
|
82
|
-
isNonInteractive: boolean;
|
|
83
|
-
/**
|
|
84
|
-
* Injection volume for the re-applied blocks. Owned by the agent loop, which
|
|
85
|
-
* drops to `"minimal"` when overflow reduction trims the prompt; handed to
|
|
86
|
-
* the hook here so re-injection matches the loop's committed decision instead
|
|
87
|
-
* of re-deriving it.
|
|
88
|
-
*/
|
|
89
|
-
mode: InjectionMode;
|
|
90
|
-
/**
|
|
91
|
-
* The `model_profile:` turn-context label, or `null` when the active
|
|
92
|
-
* inference profile is unchanged since the last notified one. The agent loop
|
|
93
|
-
* resolves it once at turn start from config and the turn's profile override,
|
|
94
|
-
* and notifies the model only on change — a decision that flips mid-turn once
|
|
95
|
-
* the notification is persisted, so it cannot be re-derived. Handed to the
|
|
96
|
-
* hook here so re-injection re-emits the loop's turn-start value.
|
|
97
|
-
*/
|
|
98
|
-
modelProfile: string | null;
|
|
99
|
-
/**
|
|
100
|
-
* Inbound actor identity and trust fields for the unified `<turn_context>`
|
|
101
|
-
* block, or `null` on guardian turns (which suppress the actor section). The
|
|
102
|
-
* agent loop resolves it once at turn start via the actor-trust resolver,
|
|
103
|
-
* whose contact/member registry inputs can be mutated mid-turn by contact
|
|
104
|
-
* tools, so it cannot be re-derived. Handed to the hook here so re-injection
|
|
105
|
-
* re-emits the loop's turn-start value.
|
|
106
|
-
*/
|
|
107
|
-
actorContext: InboundActorContext | null;
|
|
108
|
-
}
|
|
109
47
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
48
|
+
const postCompact: PluginHookFn<PostCompactContext> = async (ctx) => {
|
|
49
|
+
const {
|
|
50
|
+
history,
|
|
51
|
+
requestId,
|
|
52
|
+
conversationId,
|
|
53
|
+
isNonInteractive,
|
|
54
|
+
modelProfileKey,
|
|
55
|
+
injectionMode,
|
|
56
|
+
} = ctx;
|
|
57
|
+
const mode = injectionMode ?? "full";
|
|
58
|
+
const config = getConfig();
|
|
59
|
+
const conversation = findConversationOrSubagent(conversationId);
|
|
60
|
+
// Trust and the inbound actor context are read from the conversation's
|
|
61
|
+
// turn-start snapshots rather than live state: post-compaction runs mid-turn
|
|
62
|
+
// in a later tool iteration, where the live trust can be overwritten by a
|
|
63
|
+
// concurrent request's actor and the contact/member registry the actor
|
|
64
|
+
// context derives from can be mutated by contact tools. The snapshots are the
|
|
65
|
+
// values the turn's initial assembly resolved.
|
|
66
|
+
const trust =
|
|
67
|
+
conversation?.currentTurnTrustContext ??
|
|
68
|
+
conversation?.trustContext ??
|
|
69
|
+
FALLBACK_TURN_TRUST;
|
|
70
|
+
const actorContext = conversation?.currentTurnInboundActorContext ?? null;
|
|
71
|
+
// Render the `model_profile:` label from the turn's resolved profile key,
|
|
72
|
+
// using the call site self-resolved from the live conversation — the same
|
|
73
|
+
// derivation the first-call user-prompt-submit assembly uses.
|
|
74
|
+
const modelProfile = resolveTurnModelProfileLabel(
|
|
75
|
+
modelProfileKey,
|
|
76
|
+
conversation?.currentCallSite ?? "mainAgent",
|
|
77
|
+
config.llm,
|
|
78
|
+
conversationId,
|
|
79
|
+
);
|
|
120
80
|
const result = await applyRuntimeInjections(history, {
|
|
121
|
-
|
|
81
|
+
isNonInteractive,
|
|
82
|
+
modelProfile,
|
|
83
|
+
actorContext,
|
|
84
|
+
mode,
|
|
122
85
|
requestId,
|
|
123
86
|
conversationId,
|
|
124
87
|
trust,
|
|
125
88
|
});
|
|
89
|
+
// Write the re-injected history back onto the threaded context; the loop
|
|
90
|
+
// reads it from there once the hook settles.
|
|
91
|
+
ctx.history = result.messages;
|
|
126
92
|
// Re-track the nodes the memory graph last injected so they survive against
|
|
127
|
-
// the re-injected history. Untrusted actors
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
// from the plugin's own registry by the turn's conversation id — the same
|
|
132
|
-
// instance the turn's retrieval mutated, so re-tracking sees the real
|
|
133
|
-
// cached-node state.
|
|
93
|
+
// the re-injected history. Untrusted actors never received a memory-graph
|
|
94
|
+
// injection, so there is nothing to re-track. The live graph handle is looked
|
|
95
|
+
// up from the plugin's own registry by the turn's conversation id — the same
|
|
96
|
+
// instance the turn's retrieval mutated.
|
|
134
97
|
const isTrustedActor = resolveTrustClass(trust) === "guardian";
|
|
135
|
-
if (isTrustedActor
|
|
98
|
+
if (isTrustedActor) {
|
|
136
99
|
getLiveGraphMemory(conversationId)?.retrackCachedNodes();
|
|
137
100
|
}
|
|
138
|
-
|
|
139
|
-
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default postCompact;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Default `user-prompt-submit
|
|
3
|
-
*
|
|
2
|
+
* Default `user-prompt-submit` hook: prepares a turn's prompt before the first
|
|
3
|
+
* provider call by running memory-graph retrieval and then applying the
|
|
4
4
|
* runtime injections that assemble the turn.
|
|
5
5
|
*
|
|
6
6
|
* **Memory graph** via {@link ConversationGraphMemory.prepareMemory} —
|
|
@@ -22,88 +22,52 @@
|
|
|
22
22
|
* post-compaction hook, which re-applies the same injections after a mid-loop
|
|
23
23
|
* compaction.
|
|
24
24
|
*
|
|
25
|
-
*
|
|
26
|
-
* ahead of
|
|
27
|
-
*
|
|
28
|
-
* transform that runs between the two moments. The `-temp` suffix marks this as
|
|
29
|
-
* a transitional staging point that folds into `user-prompt-submit` once
|
|
30
|
-
* compaction is cleared from the gap between the two call sites.
|
|
25
|
+
* Registered first in the `user-prompt-submit` chain, so it heads the chain
|
|
26
|
+
* ahead of history repair and title generation: those later hooks see the
|
|
27
|
+
* fully assembled, memory-injected history.
|
|
31
28
|
*/
|
|
32
29
|
|
|
33
|
-
import type {
|
|
34
|
-
|
|
30
|
+
import type {
|
|
31
|
+
PluginHookFn,
|
|
32
|
+
UserPromptSubmitContext,
|
|
33
|
+
} from "@vellumai/plugin-api";
|
|
35
34
|
|
|
36
35
|
import { getConfig } from "../../../../config/loader.js";
|
|
37
36
|
import { findConversationOrSubagent } from "../../../../daemon/conversation-registry.js";
|
|
38
37
|
import {
|
|
39
38
|
applyRuntimeInjections,
|
|
40
39
|
resolveTurnInboundActorContext,
|
|
40
|
+
resolveTurnModelProfileLabel,
|
|
41
41
|
type RuntimeInjectionResult,
|
|
42
42
|
} from "../../../../daemon/conversation-runtime-assembly.js";
|
|
43
|
-
import type { ServerMessage } from "../../../../daemon/message-protocol.js";
|
|
44
43
|
import type { MemoryRecalled } from "../../../../daemon/message-types/memory.js";
|
|
45
44
|
import { resolveTrustClass } from "../../../../daemon/trust-context.js";
|
|
46
45
|
import { updateMessageMetadata } from "../../../../memory/conversation-crud.js";
|
|
47
46
|
import { recordMemoryRecallLog } from "../../../../memory/memory-recall-log-store.js";
|
|
48
|
-
import
|
|
47
|
+
import { broadcastMessage } from "../../../../runtime/assistant-event-hub.js";
|
|
49
48
|
import type { GraphMemoryResult } from "../../../types.js";
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Context threaded through the `user-prompt-submit-temp` hook. The
|
|
53
|
-
* conversation-scoped retrieval state (graph handle, abort signal, trust
|
|
54
|
-
* class) is self-resolved from the live conversation by id; the readonly
|
|
55
|
-
* fields here carry the event sink and the turn-start injection snapshot,
|
|
56
|
-
* while `latestMessages` straddles input and output — the loop seeds it with
|
|
57
|
-
* the pre-injection array and the hook overwrites it with the injected result.
|
|
58
|
-
*/
|
|
59
|
-
export interface MemoryRetrievalHookContext {
|
|
60
|
-
/** Event sink used by the graph retriever and `memory_recalled` emission. */
|
|
61
|
-
readonly onEvent: (msg: ServerMessage) => void;
|
|
62
|
-
/** Conversation the turn belongs to — keys the recall-log row. */
|
|
63
|
-
readonly conversationId: string;
|
|
64
|
-
/** User message the injected memory block is persisted onto. */
|
|
65
|
-
readonly userMessageId: string;
|
|
66
|
-
/** Turn-scoped logger for non-fatal persistence warnings. */
|
|
67
|
-
readonly logger: Logger;
|
|
68
|
-
/**
|
|
69
|
-
* Working message list for the turn. Seeded by the loop with the
|
|
70
|
-
* pre-injection messages and consumed as the retrieval input; the hook
|
|
71
|
-
* overwrites it with the fully injected result (the memory-graph block, when
|
|
72
|
-
* the actor is trusted, plus the runtime injections). Read back by the loop.
|
|
73
|
-
*/
|
|
74
|
-
latestMessages: Message[];
|
|
75
|
-
/**
|
|
76
|
-
* Stable ID for the current request, forwarded onto the injector turn
|
|
77
|
-
* context. The one turn-identity field the live conversation can't recover.
|
|
78
|
-
*/
|
|
79
|
-
readonly requestId: string | undefined;
|
|
80
|
-
/**
|
|
81
|
-
* Whether the in-flight turn has no human present to answer clarification
|
|
82
|
-
* questions. Resolved once at turn start and threaded in so injection uses
|
|
83
|
-
* the turn-start snapshot rather than live state that can flip mid-turn.
|
|
84
|
-
*/
|
|
85
|
-
readonly isNonInteractive: boolean;
|
|
86
|
-
/**
|
|
87
|
-
* The `model_profile:` turn-context label, or `null` when the active
|
|
88
|
-
* inference profile is unchanged since the last notified one. Resolved once
|
|
89
|
-
* at turn start, so it is threaded in rather than re-derived.
|
|
90
|
-
*/
|
|
91
|
-
readonly modelProfile: string | null;
|
|
92
|
-
}
|
|
49
|
+
import { MEMORY_V3_INJECTED_BLOCK_METADATA_KEY } from "../../memory-v3-shadow/ever-injected-store.js";
|
|
93
50
|
|
|
94
51
|
/**
|
|
95
52
|
* Persist and broadcast the retrieval's side effects: the injected block on
|
|
96
53
|
* the user message's metadata (so it survives reloads), a recall-log row, and
|
|
97
|
-
* the `memory_recalled` debug event. All three are best-effort — a failure
|
|
98
|
-
*
|
|
54
|
+
* the `memory_recalled` debug event. All three are best-effort — a failure
|
|
55
|
+
* must not abort the turn.
|
|
56
|
+
*
|
|
57
|
+
* The injected-block persist runs HERE, immediately after retrieval — not
|
|
58
|
+
* after runtime assembly. v2's activation store marks the block's pages
|
|
59
|
+
* `everInjected` during retrieval, so deferring the metadata write would open
|
|
60
|
+
* a window (which includes memory-v3's selector LLM call when the shadow flag
|
|
61
|
+
* is on) where a crash/abort leaves pages claimed-but-never-persisted: absent
|
|
62
|
+
* from history on reload AND suppressed until compaction. When memory-v3
|
|
63
|
+
* supersedes (strips) the block later this turn, {@link
|
|
64
|
+
* persistInjectionBlocks} REMOVES this key again in its combined update — a
|
|
65
|
+
* transient both-keys state mid-turn is acceptable; a v2 loss window is not.
|
|
99
66
|
*/
|
|
100
67
|
function recordRecallSideEffects(
|
|
101
68
|
graphResult: GraphMemoryResult,
|
|
102
|
-
ctx:
|
|
69
|
+
ctx: UserPromptSubmitContext,
|
|
103
70
|
): void {
|
|
104
|
-
// Persist the injected block text in message metadata so it survives
|
|
105
|
-
// conversation reloads (eviction, restart, fork). loadFromDb re-injects
|
|
106
|
-
// from metadata.
|
|
107
71
|
if (graphResult.injectedBlockText) {
|
|
108
72
|
try {
|
|
109
73
|
updateMessageMetadata(ctx.userMessageId, {
|
|
@@ -174,7 +138,7 @@ function recordRecallSideEffects(
|
|
|
174
138
|
recency: c.recencyBoost,
|
|
175
139
|
})),
|
|
176
140
|
};
|
|
177
|
-
|
|
141
|
+
broadcastMessage(memoryRecalledEvent);
|
|
178
142
|
}
|
|
179
143
|
}
|
|
180
144
|
|
|
@@ -186,23 +150,50 @@ function recordRecallSideEffects(
|
|
|
186
150
|
* correspond to `userMessageId`. All present blocks are written in a single
|
|
187
151
|
* update to avoid doubling SQLite SELECT+UPDATE work each turn. Best-effort — a
|
|
188
152
|
* persistence failure must not abort the turn.
|
|
153
|
+
*
|
|
154
|
+
* The two `<memory>` layers end the turn mutually exclusive per row:
|
|
155
|
+
* - v2's block (`memoryInjectedBlock`) was already persisted right after
|
|
156
|
+
* retrieval (see {@link recordRecallSideEffects} — no loss window). When
|
|
157
|
+
* memory-v3 superseded it this turn (`blocks.memoryV3Active`), assembly
|
|
158
|
+
* stripped the v2 block from the tail, so this combined update REMOVES the
|
|
159
|
+
* key again (persisting it would rehydrate a block that is not in the live
|
|
160
|
+
* history — a reload cache-bust and duplicated memory). `v2BlockPersisted`
|
|
161
|
+
* tells this function whether there is anything to remove.
|
|
162
|
+
* - `blocks.memoryV3InjectedBlock` (the frozen net-new card block, unwrapped)
|
|
163
|
+
* persists under `MEMORY_V3_INJECTED_BLOCK_METADATA_KEY`; `loadFromDb`
|
|
164
|
+
* re-wraps and splices it on load, freezing the cards into history.
|
|
189
165
|
*/
|
|
190
166
|
function persistInjectionBlocks(
|
|
191
167
|
blocks: RuntimeInjectionResult["blocks"],
|
|
192
|
-
ctx:
|
|
168
|
+
ctx: UserPromptSubmitContext,
|
|
169
|
+
v2BlockPersisted: boolean,
|
|
193
170
|
): void {
|
|
171
|
+
const removeV2Block = Boolean(blocks.memoryV3Active) && v2BlockPersisted;
|
|
194
172
|
if (
|
|
195
173
|
!blocks.unifiedTurnContext &&
|
|
196
174
|
!blocks.pkbSystemReminder &&
|
|
197
175
|
!blocks.workspaceBlock &&
|
|
198
176
|
!blocks.nowScratchpadBlock &&
|
|
199
177
|
!blocks.pkbContextBlock &&
|
|
200
|
-
!blocks.memoryV2StaticBlock
|
|
178
|
+
!blocks.memoryV2StaticBlock &&
|
|
179
|
+
!blocks.memoryV3InjectedBlock &&
|
|
180
|
+
!removeV2Block
|
|
201
181
|
) {
|
|
202
182
|
return;
|
|
203
183
|
}
|
|
204
184
|
try {
|
|
205
185
|
const metadataUpdates: Record<string, unknown> = {};
|
|
186
|
+
if (removeV2Block) {
|
|
187
|
+
// An explicit `undefined` overrides the value persisted after retrieval
|
|
188
|
+
// and is dropped by `updateMessageMetadata`'s JSON.stringify, deleting
|
|
189
|
+
// the key — the metadata schema types the field `string | absent`, so
|
|
190
|
+
// removal must drop the key rather than write null.
|
|
191
|
+
metadataUpdates.memoryInjectedBlock = undefined;
|
|
192
|
+
}
|
|
193
|
+
if (blocks.memoryV3InjectedBlock) {
|
|
194
|
+
metadataUpdates[MEMORY_V3_INJECTED_BLOCK_METADATA_KEY] =
|
|
195
|
+
blocks.memoryV3InjectedBlock;
|
|
196
|
+
}
|
|
206
197
|
if (blocks.unifiedTurnContext) {
|
|
207
198
|
metadataUpdates.turnContextBlock = blocks.unifiedTurnContext;
|
|
208
199
|
}
|
|
@@ -243,13 +234,14 @@ function persistInjectionBlocks(
|
|
|
243
234
|
* into `prepareMemory`.
|
|
244
235
|
*/
|
|
245
236
|
const userPromptSubmitMemoryRetrieval: PluginHookFn<
|
|
246
|
-
|
|
237
|
+
UserPromptSubmitContext
|
|
247
238
|
> = async (ctx) => {
|
|
248
239
|
// The conversation-scoped retrieval state — graph handle, abort signal, and
|
|
249
240
|
// trust class — is resolved from the live conversation by id rather than
|
|
250
241
|
// threaded in, mirroring how `applyRuntimeInjections` self-resolves its
|
|
251
242
|
// per-turn inputs.
|
|
252
243
|
const conversation = findConversationOrSubagent(ctx.conversationId);
|
|
244
|
+
const config = getConfig();
|
|
253
245
|
const abortSignal = conversation?.abortController?.signal;
|
|
254
246
|
const isTrustedActor =
|
|
255
247
|
resolveTrustClass(conversation?.trustContext) === "guardian";
|
|
@@ -258,15 +250,24 @@ const userPromptSubmitMemoryRetrieval: PluginHookFn<
|
|
|
258
250
|
conversation?.assistantId,
|
|
259
251
|
);
|
|
260
252
|
|
|
253
|
+
let v2BlockPersisted = false;
|
|
261
254
|
if (conversation && isTrustedActor && abortSignal) {
|
|
255
|
+
// Retrieval progress (`memory_status`) and the `memory_recalled` summary
|
|
256
|
+
// publish to the shared `broadcastMessage` hub — the sink every turn
|
|
257
|
+
// publisher converges to — rather than a threaded event callback. This
|
|
258
|
+
// keeps any raw client-emit capability off the hook contract.
|
|
262
259
|
const graphResult = await conversation.graphMemory.prepareMemory(
|
|
263
260
|
ctx.latestMessages,
|
|
264
|
-
|
|
261
|
+
config,
|
|
265
262
|
abortSignal,
|
|
266
|
-
|
|
263
|
+
broadcastMessage,
|
|
267
264
|
);
|
|
268
265
|
|
|
269
266
|
recordRecallSideEffects(graphResult, ctx);
|
|
267
|
+
// The v2 block is persisted inside `recordRecallSideEffects`. If
|
|
268
|
+
// memory-v3 supersedes it later this turn, `persistInjectionBlocks`
|
|
269
|
+
// removes the key in its combined post-assembly update.
|
|
270
|
+
v2BlockPersisted = Boolean(graphResult.injectedBlockText);
|
|
270
271
|
|
|
271
272
|
ctx.latestMessages = graphResult.runMessages;
|
|
272
273
|
// Select dense+sparse as a matched pair so RRF fusion combines two signals
|
|
@@ -300,21 +301,29 @@ const userPromptSubmitMemoryRetrieval: PluginHookFn<
|
|
|
300
301
|
// input — the Slack chronological transcript, the unified `<turn_context>`
|
|
301
302
|
// block, channel/voice/transport hints, and the turn's trust/index/call-site
|
|
302
303
|
// — from the live conversation, so we hand in only the request id and
|
|
303
|
-
// conversation id plus the
|
|
304
|
-
// (`isNonInteractive
|
|
305
|
-
//
|
|
306
|
-
//
|
|
307
|
-
//
|
|
304
|
+
// conversation id plus the field resolved once at turn start
|
|
305
|
+
// (`isNonInteractive`). The `model_profile` label is rendered here from the
|
|
306
|
+
// turn's resolved profile key, using the call site self-resolved from the
|
|
307
|
+
// live conversation. The unified `<turn_context>` actor input is
|
|
308
|
+
// self-resolved from the live conversation's trust context. This first-call
|
|
309
|
+
// assembly always runs at `"full"` volume; overflow reduction only downgrades
|
|
310
|
+
// the mode on later re-injection.
|
|
311
|
+
const modelProfile = resolveTurnModelProfileLabel(
|
|
312
|
+
ctx.modelProfileKey,
|
|
313
|
+
conversation?.currentCallSite ?? "mainAgent",
|
|
314
|
+
config.llm,
|
|
315
|
+
ctx.conversationId,
|
|
316
|
+
);
|
|
308
317
|
const injection = await applyRuntimeInjections(ctx.latestMessages, {
|
|
309
318
|
isNonInteractive: ctx.isNonInteractive,
|
|
310
|
-
modelProfile
|
|
319
|
+
modelProfile,
|
|
311
320
|
actorContext,
|
|
312
321
|
mode: "full",
|
|
313
322
|
requestId: ctx.requestId,
|
|
314
323
|
conversationId: ctx.conversationId,
|
|
315
324
|
});
|
|
316
325
|
ctx.latestMessages = injection.messages;
|
|
317
|
-
persistInjectionBlocks(injection.blocks, ctx);
|
|
326
|
+
persistInjectionBlocks(injection.blocks, ctx, v2BlockPersisted);
|
|
318
327
|
};
|
|
319
328
|
|
|
320
329
|
export default userPromptSubmitMemoryRetrieval;
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
* injectors out of the plugin registry.
|
|
9
9
|
*
|
|
10
10
|
* The chain combines the default injectors ({@link defaultInjectors}) with the
|
|
11
|
-
* memory-v3
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* memory-v3 injectors ({@link memoryV3Injector} — frozen net-new cards — and
|
|
12
|
+
* {@link memoryV3SpotlightInjector} — the ephemeral section spotlight). The
|
|
13
|
+
* sort mirrors the previous registry aggregation (`Array.prototype.sort` is
|
|
14
|
+
* stable, so injectors sharing an `order` keep their listed order), so the
|
|
15
|
+
* produced sequence — and therefore the injected content — is identical.
|
|
15
16
|
*
|
|
16
17
|
* The chain is assembled lazily on first access and memoized, so the sort runs
|
|
17
18
|
* once per process rather than per turn and module evaluation stays free of any
|
|
@@ -19,7 +20,10 @@
|
|
|
19
20
|
*/
|
|
20
21
|
|
|
21
22
|
import type { Injector } from "../../types.js";
|
|
22
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
memoryV3Injector,
|
|
25
|
+
memoryV3SpotlightInjector,
|
|
26
|
+
} from "../memory-v3-shadow/injector.js";
|
|
23
27
|
import { defaultInjectors } from "./injectors.js";
|
|
24
28
|
|
|
25
29
|
let cachedChain: Injector[] | null = null;
|
|
@@ -27,9 +31,11 @@ let cachedChain: Injector[] | null = null;
|
|
|
27
31
|
/** The order-sorted runtime injector chain, assembled once and memoized. */
|
|
28
32
|
export function getInjectorChain(): Injector[] {
|
|
29
33
|
if (cachedChain === null) {
|
|
30
|
-
cachedChain = [
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
cachedChain = [
|
|
35
|
+
...defaultInjectors,
|
|
36
|
+
memoryV3Injector,
|
|
37
|
+
memoryV3SpotlightInjector,
|
|
38
|
+
].sort((a, b) => a.order - b.order);
|
|
33
39
|
}
|
|
34
40
|
return cachedChain;
|
|
35
41
|
}
|
|
@@ -53,7 +53,7 @@ import { readNowScratchpad } from "../../../daemon/now-scratchpad.js";
|
|
|
53
53
|
import { getInContextPkbPaths } from "../../../daemon/pkb-context-tracker.js";
|
|
54
54
|
import { buildPkbReminder } from "../../../daemon/pkb-reminder-builder.js";
|
|
55
55
|
import {
|
|
56
|
-
|
|
56
|
+
isPersonalMemoryAllowed,
|
|
57
57
|
type TrustContext,
|
|
58
58
|
} from "../../../daemon/trust-context.js";
|
|
59
59
|
import { listComments } from "../../../documents/document-comments-store.js";
|
|
@@ -62,10 +62,7 @@ import { getPkbAutoInjectList } from "../../../memory/pkb/autoinject.js";
|
|
|
62
62
|
import { readPkbContext } from "../../../memory/pkb/context.js";
|
|
63
63
|
import { searchPkbFiles } from "../../../memory/pkb/pkb-search.js";
|
|
64
64
|
import { getPkbRoot, PKB_WORKSPACE_SCOPE } from "../../../memory/pkb/types.js";
|
|
65
|
-
import {
|
|
66
|
-
readMemoryV2StaticContent,
|
|
67
|
-
shouldExposePersonalMemory,
|
|
68
|
-
} from "../../../memory/v2/static-context.js";
|
|
65
|
+
import { readMemoryV2StaticContent } from "../../../memory/v2/static-context.js";
|
|
69
66
|
import type { Message } from "../../../providers/types.js";
|
|
70
67
|
import { getLogger } from "../../../util/logger.js";
|
|
71
68
|
import { getSandboxWorkingDir } from "../../../util/platform.js";
|
|
@@ -360,19 +357,6 @@ const pkbReminderInjector: Injector = {
|
|
|
360
357
|
},
|
|
361
358
|
};
|
|
362
359
|
|
|
363
|
-
/**
|
|
364
|
-
* Whether personal-memory content (PKB, NOW.md) may be surfaced this turn: the
|
|
365
|
-
* trust gate admits the actor (guardian-class, or an internal/local flow). All
|
|
366
|
-
* memory-domain injectors share this gate so they apply identical exposure
|
|
367
|
-
* rules without it being threaded in from the agent loop.
|
|
368
|
-
*/
|
|
369
|
-
function isPersonalMemoryAllowed(trust: TrustContext): boolean {
|
|
370
|
-
return shouldExposePersonalMemory({
|
|
371
|
-
sourceChannel: trust.sourceChannel,
|
|
372
|
-
isTrustedActor: resolveTrustClass(trust) === "guardian",
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
|
|
376
360
|
/**
|
|
377
361
|
* Read the auto-injected PKB content for the turn, gated behind the
|
|
378
362
|
* personal-memory trust gate. Returns the content string when the gate admits
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "default-memory-retrieval",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "First-party default plugin running memory-graph retrieval and runtime injection at the front of the user-prompt-submit chain.",
|
|
5
|
+
"private": true,
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=20.12.0"
|
|
10
|
+
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"@vellumai/plugin-api": "^0.8.0"
|
|
13
|
+
}
|
|
14
|
+
}
|