@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
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* injection is bit-for-bit identical — the only difference is the
|
|
10
10
|
* side-effect telemetry write.
|
|
11
11
|
* - `memory-v3-live`: live injection. The injector (`memoryV3Injector` in
|
|
12
|
-
* `./injector.ts`) additionally renders
|
|
12
|
+
* `./injector.ts`) additionally renders this turn's selections into a
|
|
13
13
|
* `<memory>` block and returns it at v2's dynamic-memory placement
|
|
14
14
|
* (`after-memory-prefix`). Selections are still logged.
|
|
15
15
|
* - both OFF: orchestration is skipped entirely.
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
* On each turn (either flag on):
|
|
18
18
|
* 1. Lazy-init the v3 lanes ONCE across the whole process (section index,
|
|
19
19
|
* section-grain BM25 needle, dense lane config, link-graph edge graph,
|
|
20
|
-
*
|
|
21
|
-
* first turns share a single build.
|
|
20
|
+
* curated core set, frecency hot set), memoizing the init promise so
|
|
21
|
+
* concurrent first turns share a single build.
|
|
22
22
|
* 2. Build a {@link MemoryRoutingTurn} from the conversation's recent messages.
|
|
23
23
|
* 3. Run {@link orchestrate} and record its selection set to
|
|
24
24
|
* `memory_v3_selections` with a best-effort lane attribution.
|
|
@@ -46,8 +46,11 @@ import {
|
|
|
46
46
|
} from "../../../util/platform.js";
|
|
47
47
|
import { stripCommentLines } from "../../../util/strip-comment-lines.js";
|
|
48
48
|
import { capabilityOrDiskBody } from "./capabilities.js";
|
|
49
|
+
import { renderCard } from "./card.js";
|
|
50
|
+
import { loadCoreSet } from "./core-set.js";
|
|
49
51
|
import type { EdgeGraph } from "./edge.js";
|
|
50
52
|
import { buildEdgeGraph } from "./edge.js";
|
|
53
|
+
import { computeHotSet } from "./hot-set.js";
|
|
51
54
|
import type { OrchestrateResult } from "./orchestrate.js";
|
|
52
55
|
import { orchestrate } from "./orchestrate.js";
|
|
53
56
|
import { ensureSectionCollection } from "./section-dense-store.js";
|
|
@@ -60,7 +63,6 @@ import {
|
|
|
60
63
|
type SelectionSource,
|
|
61
64
|
type Slug,
|
|
62
65
|
} from "./types.js";
|
|
63
|
-
import { WorkingSet } from "./working-set.js";
|
|
64
66
|
|
|
65
67
|
export const MEMORY_V3_SHADOW = "memory-v3-shadow" as const;
|
|
66
68
|
export const MEMORY_V3_LIVE = "memory-v3-live" as const;
|
|
@@ -71,10 +73,12 @@ const log = getLogger("memory-v3-shadow");
|
|
|
71
73
|
const RECENT_CONTEXT_MESSAGES = 6;
|
|
72
74
|
|
|
73
75
|
/**
|
|
74
|
-
* The lazily-built, process-lifetime v3 lanes. The
|
|
75
|
-
* (
|
|
76
|
-
*
|
|
77
|
-
*
|
|
76
|
+
* The lazily-built, process-lifetime v3 lanes. The core and hot sets are
|
|
77
|
+
* computed here (not per turn) because they are the candidate pool's STABLE
|
|
78
|
+
* PREFIX — recomputing them mid-conversation would reorder the prefix and bust
|
|
79
|
+
* the selector's KV cache. Lane memoization is the recompute cadence:
|
|
80
|
+
* `invalidateLanes()` (called by the maintain job at consolidation) forces a
|
|
81
|
+
* rebuild on the next turn.
|
|
78
82
|
*/
|
|
79
83
|
export interface ShadowLanes {
|
|
80
84
|
sectionIndex: SectionIndex;
|
|
@@ -83,9 +87,20 @@ export interface ShadowLanes {
|
|
|
83
87
|
* collection. */
|
|
84
88
|
denseConfig: AssistantConfig;
|
|
85
89
|
edgeGraph: EdgeGraph;
|
|
86
|
-
|
|
90
|
+
/** Curated core set in file order, filtered to pages in the section index. */
|
|
91
|
+
coreSlugs: string[];
|
|
92
|
+
/** Frecency hot set in score order: core excluded, filtered to pages in the
|
|
93
|
+
* section index. */
|
|
94
|
+
hotSlugs: string[];
|
|
95
|
+
/** Pre-rendered FULL cards for the stable-prefix (core+hot) slugs, keyed by
|
|
96
|
+
* slug. Frozen at lane build so the selector's stable prefix is
|
|
97
|
+
* byte-identical across turns until the next invalidation. */
|
|
98
|
+
prefixCards: Map<Slug, string>;
|
|
87
99
|
}
|
|
88
100
|
|
|
101
|
+
/** Milliseconds per day — converts `hotSet.halfLifeDays` config to ms. */
|
|
102
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
103
|
+
|
|
89
104
|
/**
|
|
90
105
|
* Memoized init promise. Caching the PROMISE (not the resolved value) means
|
|
91
106
|
* concurrent first turns all await the same build instead of racing several
|
|
@@ -151,11 +166,49 @@ async function initLanes(config: AssistantConfig): Promise<ShadowLanes> {
|
|
|
151
166
|
|
|
152
167
|
const sectionIndex = await buildSectionIndex(slugs, pageBody);
|
|
153
168
|
const needle = buildSectionNeedle(sectionIndex);
|
|
169
|
+
|
|
170
|
+
// The stable-prefix lanes. Core is the maintainer-curated file (file order
|
|
171
|
+
// preserved — it is the prefix's stable sort), filtered to pages that exist
|
|
172
|
+
// in the live section index so a dangling entry can never reach the pool.
|
|
173
|
+
// Hot is the frecency top-K over `memory_v3_selections` with core excluded
|
|
174
|
+
// (hot never duplicates core), filtered the same way — selection rows can
|
|
175
|
+
// outlive their pages. Both are recomputed only on lane invalidation (the
|
|
176
|
+
// consolidation cadence), keeping the prefix stable between rebuilds.
|
|
177
|
+
const coreSlugs = loadCoreSet(getWorkspaceDir()).filter((slug) =>
|
|
178
|
+
sectionIndex.byArticle.has(slug),
|
|
179
|
+
);
|
|
180
|
+
const hotSlugs = computeHotSet(
|
|
181
|
+
{ db: getDb() },
|
|
182
|
+
{
|
|
183
|
+
k: config.memory.v3.hotSet.k,
|
|
184
|
+
halfLifeMs: config.memory.v3.hotSet.halfLifeDays * DAY_MS,
|
|
185
|
+
now: Date.now(),
|
|
186
|
+
excludeSlugs: new Set(coreSlugs),
|
|
187
|
+
},
|
|
188
|
+
)
|
|
189
|
+
.map((entry) => entry.slug)
|
|
190
|
+
.filter((slug) => sectionIndex.byArticle.has(slug));
|
|
191
|
+
|
|
192
|
+
// Pre-render the stable-prefix cards ONCE per lane build: the selector's
|
|
193
|
+
// stable prefix must be byte-identical across turns to ride the provider KV
|
|
194
|
+
// cache, so the cards are frozen here (lane invalidation at consolidation is
|
|
195
|
+
// the recompute point) instead of being re-read per turn. Capability slugs
|
|
196
|
+
// render their capability content; disk pages render raw (frontmatter +
|
|
197
|
+
// body) so `kind: index` pages surface their `links:` map in the card TOC.
|
|
198
|
+
const prefixCards = new Map<Slug, string>();
|
|
199
|
+
for (const slug of [...coreSlugs, ...hotSlugs]) {
|
|
200
|
+
const raw = await capabilityOrDiskBody(
|
|
201
|
+
slug,
|
|
202
|
+
async (s) => (await loadPage(s))?.raw ?? "",
|
|
203
|
+
);
|
|
204
|
+
prefixCards.set(slug, renderCard(slug, raw));
|
|
205
|
+
}
|
|
206
|
+
|
|
154
207
|
const edgeGraph = await buildEdgeGraph(pageIndex.entries, pageRaw, {
|
|
155
208
|
hubDegree: config.memory.v3.edge.hubDegree,
|
|
156
209
|
});
|
|
157
210
|
// Ensuring the dense collection is best-effort: the needle + edge lanes and
|
|
158
|
-
//
|
|
211
|
+
// the core/hot prefix are in-memory and independent of Qdrant, so a Qdrant outage
|
|
159
212
|
// must NOT reject lane init (which would return `null` from observeTurn and
|
|
160
213
|
// disable ALL of v3, plus poison the memoized lanes until invalidation). On
|
|
161
214
|
// failure we log and continue with the dense lane degraded — denseLane already
|
|
@@ -170,17 +223,14 @@ async function initLanes(config: AssistantConfig): Promise<ShadowLanes> {
|
|
|
170
223
|
);
|
|
171
224
|
}
|
|
172
225
|
|
|
173
|
-
const workingSet = new WorkingSet(
|
|
174
|
-
config.memory.v3.workingSet.maxPages,
|
|
175
|
-
config.memory.v3.workingSet.evictWindow,
|
|
176
|
-
);
|
|
177
|
-
|
|
178
226
|
return {
|
|
179
227
|
sectionIndex,
|
|
180
228
|
needle,
|
|
181
229
|
denseConfig: config,
|
|
182
230
|
edgeGraph,
|
|
183
|
-
|
|
231
|
+
coreSlugs,
|
|
232
|
+
hotSlugs,
|
|
233
|
+
prefixCards,
|
|
184
234
|
};
|
|
185
235
|
}
|
|
186
236
|
|
|
@@ -273,33 +323,31 @@ interface SelectionRow {
|
|
|
273
323
|
}
|
|
274
324
|
|
|
275
325
|
/**
|
|
276
|
-
* Map an orchestrate result onto telemetry rows with
|
|
277
|
-
* attribution
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
326
|
+
* Map an orchestrate result onto telemetry rows with per-lane source
|
|
327
|
+
* attribution, by pool position: a selection of a stable-prefix page is
|
|
328
|
+
* attributed `"core"` / `"hot"` (the lane that placed it in the pool), and any
|
|
329
|
+
* other selection is attributed the finder lane that FIRST surfaced it
|
|
330
|
+
* (`"needle"` / `"dense"` / `"edge"`, recorded at pool-build time). A finder
|
|
331
|
+
* hit on a core/hot page therefore still logs as core/hot — the prefix is
|
|
332
|
+
* where the candidate lived. (`"needle"` is the fallback if a selected slug is
|
|
333
|
+
* somehow absent from every lane, which should not happen since every pooled
|
|
334
|
+
* candidate comes from one.)
|
|
285
335
|
*/
|
|
286
336
|
export function attributeSelections(result: OrchestrateResult): SelectionRow[] {
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
return rows;
|
|
337
|
+
const core = new Set<Slug>(result.lanes.core);
|
|
338
|
+
const hot = new Set<Slug>(result.lanes.hot);
|
|
339
|
+
const finderLane = new Map(
|
|
340
|
+
result.lanes.finder.map((c) => [c.slug, c.lane] as const),
|
|
341
|
+
);
|
|
342
|
+
return result.selections.map((sel) => ({
|
|
343
|
+
slug: sel.slug,
|
|
344
|
+
source: core.has(sel.slug)
|
|
345
|
+
? ("core" as const)
|
|
346
|
+
: hot.has(sel.slug)
|
|
347
|
+
? ("hot" as const)
|
|
348
|
+
: (finderLane.get(sel.slug) ?? "needle"),
|
|
349
|
+
pinned: sel.pinned ? 1 : 0,
|
|
350
|
+
}));
|
|
303
351
|
}
|
|
304
352
|
|
|
305
353
|
/** Write the attributed selection rows to `memory_v3_selections`. */
|
|
@@ -338,6 +386,7 @@ export async function observeTurn(
|
|
|
338
386
|
if (!turn) return null;
|
|
339
387
|
|
|
340
388
|
const cfg = getConfig();
|
|
389
|
+
if (cfg.memory.enabled === false) return null;
|
|
341
390
|
const lanes = await getLanes(cfg);
|
|
342
391
|
const v3 = cfg.memory.v3;
|
|
343
392
|
const result = await orchestrate(turn, {
|
|
@@ -345,7 +394,9 @@ export async function observeTurn(
|
|
|
345
394
|
needle: lanes.needle,
|
|
346
395
|
denseConfig: lanes.denseConfig,
|
|
347
396
|
edgeGraph: lanes.edgeGraph,
|
|
348
|
-
|
|
397
|
+
coreSlugs: lanes.coreSlugs,
|
|
398
|
+
hotSlugs: lanes.hotSlugs,
|
|
399
|
+
prefixCards: lanes.prefixCards,
|
|
349
400
|
needleK: v3.needleK,
|
|
350
401
|
denseK: v3.denseK,
|
|
351
402
|
edgeSeeds: v3.edge.seedCount,
|
|
@@ -377,6 +428,8 @@ export async function runShadowObservation(
|
|
|
377
428
|
conversationId: string,
|
|
378
429
|
turnIndex: number,
|
|
379
430
|
): Promise<void> {
|
|
380
|
-
|
|
431
|
+
const config = getConfig();
|
|
432
|
+
if (config.memory.enabled === false) return;
|
|
433
|
+
if (!isAssistantFeatureFlagEnabled(MEMORY_V3_SHADOW, config)) return;
|
|
381
434
|
await observeTurn(conversationId, turnIndex);
|
|
382
435
|
}
|
|
@@ -10,6 +10,26 @@ export type Slug = string;
|
|
|
10
10
|
*/
|
|
11
11
|
export const MEMORY_V3_BLOCK_ID = "memory-v3" as const;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* `meta` key under which the v3 cards block carries its attachment-commit
|
|
15
|
+
* callback. The injector defers its everInjected-store write (and the
|
|
16
|
+
* prune-valve schedule) into this callback; runtime assembly invokes it only
|
|
17
|
+
* when the turn's tail is a user message — the same gate as metadata capture
|
|
18
|
+
* — so a block that silently fails to attach never claims its cards in the
|
|
19
|
+
* dedup store. Shared between the producer (`injector.ts`) and the consumer
|
|
20
|
+
* (`conversation-runtime-assembly.ts`) so a rename is a compile error on both
|
|
21
|
+
* sides instead of a silent never-commit.
|
|
22
|
+
*/
|
|
23
|
+
export const MEMORY_V3_COMMIT_META_KEY = "memoryV3Commit" as const;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Injection-block id for the v3 ephemeral `<memory_spotlight>` block (the
|
|
27
|
+
* current window's matched sections, re-rendered at the user tail each turn).
|
|
28
|
+
* Distinct from {@link MEMORY_V3_BLOCK_ID}: the spotlight never participates
|
|
29
|
+
* in v2 suppression and is never persisted to message metadata.
|
|
30
|
+
*/
|
|
31
|
+
export const MEMORY_V3_SPOTLIGHT_BLOCK_ID = "memory-v3-spotlight" as const;
|
|
32
|
+
|
|
13
33
|
/**
|
|
14
34
|
* A single section of a page: the lead (text before the first `## heading`,
|
|
15
35
|
* ordinal 0) or a heading-delimited block. Over-long sections are split into
|
|
@@ -40,13 +60,6 @@ export interface SelectedPage {
|
|
|
40
60
|
pinned: boolean;
|
|
41
61
|
}
|
|
42
62
|
|
|
43
|
-
export interface WorkingSetEntry {
|
|
44
|
-
slug: Slug;
|
|
45
|
-
selectedAtTurn: number;
|
|
46
|
-
pinned: boolean;
|
|
47
|
-
lastSeenTurn: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
63
|
export interface MemoryRoutingTurn {
|
|
51
64
|
conversationId: string;
|
|
52
65
|
turnNumber: number;
|
|
@@ -68,25 +81,29 @@ export interface MemoryRoutingTurn {
|
|
|
68
81
|
* exactly one place and the runtime list (used for telemetry roll-ups and
|
|
69
82
|
* source validation) can never drift from the type.
|
|
70
83
|
*
|
|
84
|
+
* `core` / `hot` are the stable-prefix lanes (curated core set, frecency hot
|
|
85
|
+
* set); `needle` / `dense` / `edge` are the per-turn finder lanes.
|
|
86
|
+
*
|
|
71
87
|
* The `memory_v3_selections.source` column is free-text, so tightening this set
|
|
72
|
-
* needs no migration: any historical rows with
|
|
73
|
-
* fine via the permissive `z.string()`
|
|
88
|
+
* needs no migration: any historical rows with retired labels (e.g. the old
|
|
89
|
+
* per-turn carry source) still read back fine via the permissive `z.string()`
|
|
90
|
+
* row schema — they just don't aggregate into a named bucket.
|
|
74
91
|
*/
|
|
75
92
|
export const SELECTION_SOURCES = [
|
|
93
|
+
"core",
|
|
94
|
+
"hot",
|
|
76
95
|
"needle",
|
|
77
96
|
"dense",
|
|
78
97
|
"edge",
|
|
79
|
-
"carry-forward",
|
|
80
98
|
] as const;
|
|
81
99
|
|
|
82
100
|
export type SelectionSource = (typeof SELECTION_SOURCES)[number];
|
|
83
101
|
|
|
84
102
|
/**
|
|
85
|
-
* The
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* automatically.
|
|
103
|
+
* The per-turn finder lanes — the strict subset of {@link SelectionSource} a
|
|
104
|
+
* finder candidate can be tagged with at pool-build time. (`core` / `hot` are
|
|
105
|
+
* assigned by stable-prefix membership, not by a finder.) Defined via
|
|
106
|
+
* `Exclude` so it can never drift from {@link SELECTION_SOURCES}: adding a
|
|
107
|
+
* finder lane there widens this automatically.
|
|
91
108
|
*/
|
|
92
|
-
export type
|
|
109
|
+
export type FinderLane = Exclude<SelectionSource, "core" | "hot">;
|
|
@@ -50,23 +50,21 @@ function countUserTurns(messages: ReadonlyArray<Message>): number {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const stop: PluginHookFn<StopContext> = async (ctx) => {
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
if (ctx.
|
|
53
|
+
// Re-title only at a genuine successful turn end (the model returned a reply
|
|
54
|
+
// with no tool calls). Any other terminal — a provider rejection, abort, or
|
|
55
|
+
// an output-limit cutoff — produced no new topic to re-title from.
|
|
56
|
+
if (ctx.exitReason !== "no_tool_calls") return;
|
|
57
57
|
|
|
58
58
|
if (getConfig().conversations.skipAutoRetitling) return;
|
|
59
59
|
|
|
60
60
|
if (countUserTurns(ctx.messages) !== SECOND_PASS_USER_TURN) return;
|
|
61
61
|
|
|
62
62
|
const { conversationId } = ctx;
|
|
63
|
-
// Deferred to a later macrotask so the just-completed turn
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
// fire-and-forget and re-checks replaceability, owning provider resolution,
|
|
69
|
-
// persistence, and the resulting broadcast.
|
|
63
|
+
// Deferred to a later macrotask so the just-completed turn's persistence
|
|
64
|
+
// settles first. The service regenerates from the most recent stored
|
|
65
|
+
// messages, so it must run after the reply is persisted to reflect it. The
|
|
66
|
+
// service is itself fire-and-forget and re-checks replaceability, owning
|
|
67
|
+
// provider resolution, persistence, and the resulting broadcast.
|
|
70
68
|
setTimeout(() => {
|
|
71
69
|
queueRegenerateConversationTitle({ conversationId });
|
|
72
70
|
}, 0);
|
package/src/plugins/pipeline.ts
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* A "hook" is a named lifecycle event (`user-prompt-submit`, `post-tool-use`,
|
|
5
5
|
* …) that every registered plugin may handle. The runner walks each plugin's
|
|
6
6
|
* hook for a given event in registration order, threading a context value
|
|
7
|
-
* through the chain so hooks can observe and transform it.
|
|
7
|
+
* through the chain so hooks can observe and transform it. A hook either
|
|
8
|
+
* mutates the context in place (returning `void`) or returns a partial
|
|
9
|
+
* context whose fields are merged onto the threaded value.
|
|
8
10
|
*
|
|
9
11
|
* Design doc: `.private/plans/agent-plugin-system.md`.
|
|
10
12
|
*/
|
|
@@ -17,9 +19,10 @@ import { getHooksFor } from "./registry.js";
|
|
|
17
19
|
/**
|
|
18
20
|
* Execute a hook chain: walk every registered plugin's hook for `name` in
|
|
19
21
|
* registration order, threading `initialCtx` through each. Hooks may either
|
|
20
|
-
* mutate the context in place (returning `void`) or return a
|
|
21
|
-
*
|
|
22
|
-
*
|
|
22
|
+
* mutate the context in place (returning `void`) or return a partial context
|
|
23
|
+
* whose fields are merged onto the threaded value — keys the hook returns
|
|
24
|
+
* overwrite the running context, every other field is preserved. The final
|
|
25
|
+
* context after the chain settles is returned.
|
|
23
26
|
*
|
|
24
27
|
* @param name The hook identifier — pick one from {@link HOOKS}.
|
|
25
28
|
* @param initialCtx Context the first hook receives.
|
|
@@ -35,7 +38,7 @@ export async function runHook<TCtx>(
|
|
|
35
38
|
for (const hook of getHooksFor<TCtx>(name)) {
|
|
36
39
|
const result = await hook(active);
|
|
37
40
|
if (result !== undefined) {
|
|
38
|
-
active = result;
|
|
41
|
+
active = { ...active, ...result };
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
return active;
|
package/src/plugins/types.ts
CHANGED
|
@@ -317,12 +317,11 @@ export interface Injector {
|
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
// ─── Model-visible capability slots ──────────────────────────────────────────
|
|
320
|
-
// Concrete shapes are defined by the tool/route
|
|
321
|
-
// contributions
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
//
|
|
325
|
-
// catalog-discoverable skills today.
|
|
320
|
+
// Concrete shapes are defined by the tool/route registries. Tool
|
|
321
|
+
// contributions use the canonical `Tool` interface; route contributions use
|
|
322
|
+
// the `SkillRoute` shape from the skill-route registry. Skills ship on disk
|
|
323
|
+
// inside an installed plugin (`plugins/<name>/skills/<id>/SKILL.md`) and are
|
|
324
|
+
// discovered by the skill catalog loader, so they need no contribution slot.
|
|
326
325
|
|
|
327
326
|
/**
|
|
328
327
|
* HTTP route registration contributed by a plugin. Plugins express routes as
|
|
@@ -336,49 +335,6 @@ export interface Injector {
|
|
|
336
335
|
*/
|
|
337
336
|
export type PluginRouteRegistration = SkillRoute;
|
|
338
337
|
|
|
339
|
-
/**
|
|
340
|
-
* A skill contributed by a plugin.
|
|
341
|
-
*
|
|
342
|
-
* When a plugin declares {@link Plugin.skills}, the bootstrap registers each
|
|
343
|
-
* entry into an in-memory side catalog that {@link loadSkillCatalog} merges
|
|
344
|
-
* into its output. The entry is then discoverable by the model's `skill_load`
|
|
345
|
-
* / `skill_execute` flow under `source: "plugin"` — the same code paths used
|
|
346
|
-
* for filesystem-backed skills.
|
|
347
|
-
*
|
|
348
|
-
* The fields mirror the subset of `SkillSummary` / `SkillDefinition` that
|
|
349
|
-
* makes sense for an in-memory contribution. Inline commands and reference
|
|
350
|
-
* files are out of scope for plugin skills in this PR — add them later if a
|
|
351
|
-
* real plugin needs them.
|
|
352
|
-
*/
|
|
353
|
-
export interface PluginSkillRegistration {
|
|
354
|
-
/** Stable skill id (kebab-case). Must be unique across the catalog. */
|
|
355
|
-
id: string;
|
|
356
|
-
/**
|
|
357
|
-
* Skill "name" as surfaced to the model. Matches the SKILL.md frontmatter
|
|
358
|
-
* `name` field for filesystem skills.
|
|
359
|
-
*/
|
|
360
|
-
name: string;
|
|
361
|
-
/**
|
|
362
|
-
* Human-readable display name shown in UI lists. Defaults to `name` when
|
|
363
|
-
* omitted — matches the filesystem-skill default.
|
|
364
|
-
*/
|
|
365
|
-
displayName?: string;
|
|
366
|
-
/** One-line description shown by `skill_load` / UI. */
|
|
367
|
-
description: string;
|
|
368
|
-
/** Full skill body returned when `skill_load` fires for this skill. */
|
|
369
|
-
body: string;
|
|
370
|
-
/** Optional emoji shown beside the skill in UI surfaces. */
|
|
371
|
-
emoji?: string;
|
|
372
|
-
/** Optional assistant feature-flag key — when set and the flag is OFF, the skill is filtered out. */
|
|
373
|
-
featureFlag?: string;
|
|
374
|
-
/** Compact routing cues injected into `<available_skills>` to guide selection. */
|
|
375
|
-
activationHints?: string[];
|
|
376
|
-
/** Conditions under which this skill should NOT be loaded. */
|
|
377
|
-
avoidWhen?: string[];
|
|
378
|
-
/** IDs of child skills that this skill includes (metadata-only, not auto-activated). */
|
|
379
|
-
includes?: string[];
|
|
380
|
-
}
|
|
381
|
-
|
|
382
338
|
// ─── Plugin ──────────────────────────────────────────────────────────────────
|
|
383
339
|
|
|
384
340
|
/**
|
|
@@ -420,8 +376,6 @@ export interface Plugin {
|
|
|
420
376
|
tools?: Tool[];
|
|
421
377
|
/** HTTP route registrations served by the assistant. */
|
|
422
378
|
routes?: PluginRouteRegistration[];
|
|
423
|
-
/** Skill registrations loaded at startup. */
|
|
424
|
-
skills?: PluginSkillRegistration[];
|
|
425
379
|
}
|
|
426
380
|
|
|
427
381
|
// ─── Errors ──────────────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ContentBlock } from "./types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build a text content block carrying an ephemeral `cache_control` breakpoint
|
|
5
|
+
* with a 1h TTL, marking a byte-stable prefix the provider KV cache should
|
|
6
|
+
* persist across calls.
|
|
7
|
+
*
|
|
8
|
+
* The Anthropic SDK accepts the field as an extra property on text blocks, but
|
|
9
|
+
* the internal `TextContent` type intentionally omits it (only the Anthropic
|
|
10
|
+
* provider transforms it onto the wire — block-level `cache_control` is
|
|
11
|
+
* preserved through `toAnthropicBlockSafe`), so we reach through a `Record`
|
|
12
|
+
* cast for the same reason `anthropic/client.ts` does — it keeps the core
|
|
13
|
+
* types provider-agnostic. The 1h TTL matches the provider's auto-applied
|
|
14
|
+
* breakpoints (see `cacheTtl` in `providers/anthropic/client.ts`); the
|
|
15
|
+
* `extended-cache-ttl-2025-04-11` beta header is added unconditionally for
|
|
16
|
+
* non-Haiku models in `client.ts` (Haiku models have the `ttl` stripped
|
|
17
|
+
* provider-side), so this works without any call-site config.
|
|
18
|
+
*/
|
|
19
|
+
export function cachedTextBlock(text: string): ContentBlock {
|
|
20
|
+
const block: ContentBlock = { type: "text", text };
|
|
21
|
+
(block as unknown as Record<string, unknown>).cache_control = {
|
|
22
|
+
type: "ephemeral",
|
|
23
|
+
ttl: "1h",
|
|
24
|
+
};
|
|
25
|
+
return block;
|
|
26
|
+
}
|
|
@@ -37,8 +37,7 @@ mock.module("../../../memory/db-connection.js", () => ({
|
|
|
37
37
|
}));
|
|
38
38
|
|
|
39
39
|
mock.module("../../../config/assistant-feature-flags.js", () => ({
|
|
40
|
-
isAssistantFeatureFlagEnabled: (
|
|
41
|
-
flag === "openai-compatible-endpoints",
|
|
40
|
+
isAssistantFeatureFlagEnabled: () => false,
|
|
42
41
|
}));
|
|
43
42
|
|
|
44
43
|
mock.module("../../../config/loader.js", () => ({
|
|
@@ -1040,6 +1040,19 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
|
|
|
1040
1040
|
pricing: { inputPer1mTokens: 0.6, outputPer1mTokens: 2.5 },
|
|
1041
1041
|
},
|
|
1042
1042
|
// MiniMax
|
|
1043
|
+
{
|
|
1044
|
+
id: "minimax/minimax-m3",
|
|
1045
|
+
displayName: "MiniMax M3",
|
|
1046
|
+
// The model supports 1M context, but OpenRouter's only route
|
|
1047
|
+
// (MiniMax) accepts 524,288 tokens; advertise the routed limit.
|
|
1048
|
+
contextWindowTokens: 524288,
|
|
1049
|
+
maxOutputTokens: 512000,
|
|
1050
|
+
supportsThinking: true,
|
|
1051
|
+
supportsCaching: false,
|
|
1052
|
+
supportsVision: true,
|
|
1053
|
+
supportsToolUse: true,
|
|
1054
|
+
pricing: { inputPer1mTokens: 0.3, outputPer1mTokens: 1.2 },
|
|
1055
|
+
},
|
|
1043
1056
|
{
|
|
1044
1057
|
id: "minimax/minimax-m2.7",
|
|
1045
1058
|
displayName: "MiniMax M2.7",
|
|
@@ -1212,7 +1225,6 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
|
|
|
1212
1225
|
setupHint:
|
|
1213
1226
|
"Enter the base URL of your endpoint and at least one model identifier.",
|
|
1214
1227
|
apiKeyPlaceholder: "Your provider's API key",
|
|
1215
|
-
featureFlag: "openai-compatible-endpoints",
|
|
1216
1228
|
models: [],
|
|
1217
1229
|
defaultModel: "",
|
|
1218
1230
|
},
|