@vellumai/assistant 0.8.7 → 0.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +20 -4
- package/docker-entrypoint.sh +4 -2
- package/docker-init-apt-root.sh +3 -1
- package/docker-kata-apt-env.sh +3 -1
- package/docker-kata-runtime-family.sh +12 -0
- package/docs/architecture/memory.md +1 -1
- package/docs/plugins.md +75 -79
- package/examples/plugins/echo/README.md +6 -12
- package/examples/plugins/echo/register.ts +0 -41
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
- package/openapi.yaml +3381 -348
- package/package.json +1 -1
- package/scripts/generate-openapi.ts +68 -41
- package/src/__tests__/agent-loop-exit-reason.test.ts +34 -39
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +37 -87
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -3
- package/src/__tests__/anthropic-provider.test.ts +95 -2
- package/src/__tests__/assistant-event-hub.test.ts +25 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
- package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
- package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
- package/src/__tests__/btw-routes.test.ts +62 -3
- package/src/__tests__/build-persisted-content.test.ts +184 -0
- package/src/__tests__/catalog-files.test.ts +1 -1
- package/src/__tests__/clawhub-files.test.ts +1 -1
- package/src/__tests__/compaction-pipeline.test.ts +1 -1
- package/src/__tests__/compaction.benchmark.test.ts +0 -30
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +313 -1136
- package/src/__tests__/conversation-agent-loop.test.ts +596 -1616
- package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
- package/src/__tests__/conversation-history-web-search.test.ts +11 -1
- package/src/__tests__/conversation-pairing.test.ts +4 -31
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +26 -5
- package/src/__tests__/conversation-queue.test.ts +2 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
- package/src/__tests__/conversation-runtime-assembly.test.ts +170 -229
- package/src/__tests__/conversation-runtime-workspace.test.ts +3 -24
- package/src/__tests__/conversation-slash-commands.test.ts +8 -42
- package/src/__tests__/conversation-slash-queue.test.ts +6 -1
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
- package/src/__tests__/conversation-sync-tags.test.ts +27 -15
- package/src/__tests__/conversation-title-service.test.ts +135 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
- package/src/__tests__/cross-provider-web-search.test.ts +214 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
- package/src/__tests__/dm-persistence.test.ts +5 -1
- package/src/__tests__/empty-response-hook.test.ts +304 -0
- package/src/__tests__/feature-flag-test-helpers.ts +2 -2
- package/src/__tests__/gemini-image-service.test.ts +13 -0
- package/src/__tests__/helpers/mock-provider.ts +110 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
- package/src/__tests__/history-repair-hook.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +12 -100
- package/src/__tests__/identity-routes.test.ts +248 -7
- package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
- package/src/__tests__/injector-background-turn.test.ts +2 -8
- package/src/__tests__/injector-chain.test.ts +106 -270
- package/src/__tests__/injector-disk-pressure.test.ts +3 -12
- package/src/__tests__/injector-document-comments.test.ts +2 -2
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
- package/src/__tests__/injector-v3-suppression.test.ts +31 -37
- package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
- package/src/__tests__/list-messages-page-latest.test.ts +60 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
- package/src/__tests__/llm-usage-store.test.ts +223 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
- package/src/__tests__/native-web-search.test.ts +191 -0
- package/src/__tests__/onboarding-template-contract.test.ts +2 -0
- package/src/__tests__/openai-image-service.test.ts +17 -0
- package/src/__tests__/openai-provider.test.ts +31 -1
- package/src/__tests__/persist-unsendable-image.test.ts +215 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
- package/src/__tests__/pipeline-runner.test.ts +29 -39
- package/src/__tests__/pkb-autoinject.test.ts +2 -5
- package/src/__tests__/plugin-bootstrap.test.ts +13 -28
- package/src/__tests__/plugin-registry.test.ts +0 -27
- package/src/__tests__/plugin-types.test.ts +2 -125
- package/src/__tests__/process-message-display-content.test.ts +6 -2
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
- package/src/__tests__/resolve-trust-class.test.ts +4 -4
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
- package/src/__tests__/schedule-routes.test.ts +603 -2
- package/src/__tests__/schedule-store.test.ts +41 -0
- package/src/__tests__/schedule-tools.test.ts +35 -0
- package/src/__tests__/server-history-render.test.ts +314 -1
- package/src/__tests__/skillssh-files.test.ts +1 -1
- package/src/__tests__/system-prompt.test.ts +20 -0
- package/src/__tests__/task-scheduler.test.ts +162 -1
- package/src/__tests__/terminal-tools.test.ts +6 -1
- package/src/__tests__/title-generate-hook.test.ts +319 -0
- package/src/__tests__/tool-error-hook.test.ts +278 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -2
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
- package/src/__tests__/ui-work-result-surface.test.ts +159 -0
- package/src/__tests__/usage-routes.test.ts +285 -1
- package/src/__tests__/user-plugin-loader.test.ts +2 -2
- package/src/__tests__/voice-session-bridge.test.ts +6 -3
- package/src/__tests__/web-search-backend-failure.test.ts +166 -0
- package/src/agent/loop.ts +346 -442
- package/src/api/events/assistant-thinking-delta.ts +33 -0
- package/src/api/events/tool-output-chunk.ts +45 -0
- package/src/api/events/tool-use-preview-start.ts +32 -0
- package/src/api/events/trace-event.ts +69 -0
- package/src/api/index.ts +48 -13
- package/src/api/responses/conversation-message.ts +368 -0
- package/src/avatar/__tests__/avatar-store.test.ts +34 -29
- package/src/cli/commands/__tests__/notifications.test.ts +58 -14
- package/src/cli/commands/notifications.ts +112 -60
- package/src/config/assistant-feature-flags.ts +22 -11
- package/src/config/bundled-skills/app-builder/SKILL.md +3 -20
- package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
- package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
- package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
- package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +0 -7
- package/src/config/feature-flag-cache.ts +3 -3
- package/src/config/feature-flag-registry.json +35 -3
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-v2.ts +8 -0
- package/src/config/schemas/memory-v3.ts +8 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills.ts +13 -0
- package/src/context/compactor.ts +1 -1
- package/src/context/strip-injections.ts +122 -0
- package/src/context/token-estimator.ts +23 -0
- package/src/context/tool-result-truncation.ts +0 -23
- package/src/context/window-manager.ts +3 -6
- package/src/credential-execution/executable-discovery.ts +16 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
- package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
- package/src/daemon/assistant-attachments.ts +1 -1
- package/src/daemon/config-watcher.ts +2 -2
- package/src/daemon/context-overflow-reducer.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +605 -153
- package/src/daemon/conversation-agent-loop.ts +281 -760
- package/src/daemon/conversation-history.ts +5 -4
- package/src/daemon/conversation-lifecycle.ts +3 -4
- package/src/daemon/conversation-messaging.ts +7 -6
- package/src/daemon/conversation-process.ts +11 -16
- package/src/daemon/conversation-runtime-assembly.ts +130 -347
- package/src/daemon/conversation-slash.ts +6 -25
- package/src/daemon/conversation-surfaces.ts +222 -4
- package/src/daemon/conversation-tool-setup.ts +2 -29
- package/src/daemon/conversation.ts +32 -14
- package/src/daemon/external-plugins-bootstrap.ts +9 -10
- package/src/daemon/handlers/config-a2a.ts +51 -36
- package/src/daemon/handlers/config-slack-channel.ts +20 -14
- package/src/daemon/handlers/config-telegram.ts +16 -2
- package/src/daemon/handlers/shared.ts +156 -84
- package/src/daemon/handlers/skills.ts +39 -10
- package/src/daemon/lifecycle.ts +4 -0
- package/src/daemon/message-types/apps.ts +1 -29
- package/src/daemon/message-types/messages.ts +9 -57
- package/src/daemon/message-types/skills.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +136 -3
- package/src/daemon/now-scratchpad.ts +21 -0
- package/src/daemon/orphan-reaper.test.ts +210 -0
- package/src/daemon/orphan-reaper.ts +240 -0
- package/src/daemon/persist-unsendable-image.ts +117 -0
- package/src/daemon/process-message.ts +1 -3
- package/src/daemon/trace-emitter.ts +6 -4
- package/src/daemon/trust-context.ts +19 -0
- package/src/daemon/wake-target-adapter.ts +3 -1
- package/src/home/home-greeting-cache.ts +24 -1
- package/src/ipc/gateway-client.test.ts +2 -2
- package/src/ipc/gateway-client.ts +3 -3
- package/src/media/gemini-image-service.ts +15 -0
- package/src/media/openai-image-service.ts +14 -0
- package/src/media/types.ts +34 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
- package/src/memory/auth-fallback-events-store.ts +94 -0
- package/src/memory/conversation-title-service.ts +65 -41
- package/src/memory/db-init.ts +4 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
- package/src/memory/graph/conversation-graph-memory.ts +65 -0
- package/src/memory/jobs-store.ts +33 -0
- package/src/memory/jobs-worker.ts +31 -4
- package/src/memory/llm-usage-store.ts +224 -50
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
- package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
- package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/pkb/autoinject.ts +61 -0
- package/src/memory/pkb/context.ts +50 -0
- package/src/memory/pkb/types.ts +14 -0
- package/src/memory/schedule-attribution-sql.ts +104 -0
- package/src/memory/schema/infrastructure.ts +16 -0
- package/src/memory/usage-grouped-buckets.ts +6 -1
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -1
- package/src/memory/v2/consolidation-job.ts +1 -1
- package/src/memory/v3/__tests__/health.test.ts +16 -0
- package/src/memory/v3/__tests__/orchestrate.test.ts +45 -9
- package/src/memory/v3/__tests__/provider-blocks.test.ts +13 -0
- package/src/memory/v3/__tests__/router.test.ts +101 -29
- package/src/memory/v3/__tests__/selector.test.ts +93 -27
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +23 -5
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/llm-retry.ts +32 -0
- package/src/memory/v3/orchestrate.ts +26 -14
- package/src/memory/v3/provider-blocks.ts +15 -5
- package/src/memory/v3/router.ts +48 -42
- package/src/memory/v3/selector.ts +57 -42
- package/src/memory/v3/shadow-plugin.ts +47 -15
- package/src/memory/v3/types.ts +8 -0
- package/src/notifications/conversation-pairing.ts +8 -15
- package/src/notifications/decision-engine.ts +6 -3
- package/src/notifications/home-feed-side-effect.ts +12 -1
- package/src/permissions/prompter.ts +4 -0
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +8 -1
- package/src/plugin-api/types.ts +151 -1
- package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
- package/src/plugins/defaults/empty-response/register.ts +8 -13
- package/src/plugins/defaults/index.ts +1 -15
- package/src/plugins/defaults/injectors/register.ts +243 -74
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +91 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
- package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/title-generate/package.json +1 -1
- package/src/plugins/defaults/title-generate/register.ts +18 -18
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
- package/src/plugins/defaults/tool-error/package.json +1 -1
- package/src/plugins/defaults/tool-error/register.ts +9 -21
- package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
- package/src/plugins/pipeline.ts +6 -18
- package/src/plugins/registry.ts +8 -25
- package/src/plugins/types.ts +43 -474
- package/src/proactive-artifact/aux-message-injector.ts +3 -3
- package/src/proactive-artifact/job.test.ts +7 -12
- package/src/prompts/__tests__/system-prompt.test.ts +36 -0
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +62 -0
- package/src/prompts/templates/BOOTSTRAP.md +2 -2
- package/src/prompts/templates/system-sections.ts +15 -0
- package/src/providers/anthropic/client.ts +37 -29
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
- package/src/providers/openai/chat-completions-provider.ts +44 -0
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/placeholder-sentinels.ts +35 -0
- package/src/runtime/__tests__/agent-wake.test.ts +5 -1
- package/src/runtime/agent-wake.ts +2 -2
- package/src/runtime/assistant-event-hub.ts +36 -6
- package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
- package/src/runtime/http-router.ts +16 -21
- package/src/runtime/http-types.ts +16 -70
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/app-management-routes.ts +6 -117
- package/src/runtime/routes/app-routes.ts +13 -15
- package/src/runtime/routes/attachment-routes.ts +26 -15
- package/src/runtime/routes/avatar-routes.ts +26 -0
- package/src/runtime/routes/btw-routes.ts +29 -23
- package/src/runtime/routes/consolidation-routes.ts +120 -20
- package/src/runtime/routes/conversation-query-routes.ts +2 -0
- package/src/runtime/routes/conversation-routes.ts +358 -184
- package/src/runtime/routes/documents-routes.ts +4 -0
- package/src/runtime/routes/domain-routes.ts +51 -37
- package/src/runtime/routes/epoch-millis-range.ts +34 -0
- package/src/runtime/routes/events-routes.ts +28 -34
- package/src/runtime/routes/gateway-log-routes.ts +26 -4
- package/src/runtime/routes/heartbeat-routes.ts +32 -12
- package/src/runtime/routes/identity-intro-cache.ts +11 -34
- package/src/runtime/routes/identity-routes.ts +208 -17
- package/src/runtime/routes/image-generation-routes.ts +40 -2
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/a2a.ts +12 -10
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
- package/src/runtime/routes/integrations/slack/channel.ts +4 -0
- package/src/runtime/routes/integrations/slack/share.ts +27 -6
- package/src/runtime/routes/integrations/telegram.ts +6 -0
- package/src/runtime/routes/integrations/twilio.ts +42 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
- package/src/runtime/routes/log-export-routes.ts +8 -0
- package/src/runtime/routes/memory-v2-routes.ts +15 -8
- package/src/runtime/routes/memory-v3-routes.ts +50 -28
- package/src/runtime/routes/oauth-apps.ts +66 -12
- package/src/runtime/routes/oauth-providers.ts +44 -5
- package/src/runtime/routes/platform-routes.ts +81 -5
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
- package/src/runtime/routes/playground/force-compact.ts +1 -1
- package/src/runtime/routes/rename-conversation-routes.ts +5 -0
- package/src/runtime/routes/schedule-routes.ts +152 -42
- package/src/runtime/routes/secret-routes.ts +14 -2
- package/src/runtime/routes/skills-routes.ts +43 -14
- package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
- package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
- package/src/runtime/routes/trust-rules-routes.ts +26 -2
- package/src/runtime/routes/tts-routes.ts +35 -0
- package/src/runtime/routes/types.ts +66 -8
- package/src/runtime/routes/usage-routes.ts +47 -39
- package/src/runtime/routes/webhook-routes.ts +41 -2
- package/src/runtime/routes/workspace-routes.ts +4 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
- package/src/runtime/services/analyze-conversation.ts +2 -2
- package/src/schedule/schedule-store.ts +20 -1
- package/src/schedule/schedule-usage-store.ts +83 -0
- package/src/schedule/scheduler.ts +12 -5
- package/src/skills/catalog-files.ts +2 -2
- package/src/skills/catalog-install.ts +3 -0
- package/src/skills/categories-cache.ts +118 -0
- package/src/skills/clawhub-files.ts +1 -2
- package/src/skills/skillssh-files.ts +1 -2
- package/src/telemetry/types.ts +29 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
- package/src/telemetry/usage-telemetry-reporter.ts +57 -2
- package/src/tools/executor.ts +1 -53
- package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
- package/src/tools/network/__tests__/web-search.test.ts +11 -3
- package/src/tools/network/web-search-error.test.ts +248 -0
- package/src/tools/network/web-search-error.ts +267 -0
- package/src/tools/network/web-search.ts +207 -48
- package/src/tools/schedule/create.ts +2 -0
- package/src/tools/terminal/safe-env.ts +10 -1
- package/src/tools/ui-surface/definitions.ts +9 -1
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
- package/src/tts/provider-catalog.ts +76 -1
- package/src/util/mutex.ts +47 -0
- package/src/workspace/git-service.ts +1 -42
- package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
- package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +93 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
- package/src/__tests__/empty-response-pipeline.test.ts +0 -423
- package/src/__tests__/llm-call-pipeline.test.ts +0 -287
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
- package/src/__tests__/persistence-pipeline.test.ts +0 -503
- package/src/__tests__/title-generate-pipeline.test.ts +0 -211
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
- package/src/__tests__/tool-error-pipeline.test.ts +0 -241
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
- package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
- package/src/gallery/default-gallery.ts +0 -1359
- package/src/gallery/gallery-manifest.ts +0 -28
- package/src/home/feature-gate.ts +0 -22
- package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
- package/src/plugins/defaults/empty-response/terminal.ts +0 -106
- package/src/plugins/defaults/injectors/package.json +0 -15
- package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
- package/src/plugins/defaults/llm-call/package.json +0 -15
- package/src/plugins/defaults/llm-call/register.ts +0 -45
- package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
- package/src/plugins/defaults/memory-retrieval/package.json +0 -15
- package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
- package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
- package/src/plugins/defaults/persistence/package.json +0 -15
- package/src/plugins/defaults/persistence/register.ts +0 -38
- package/src/plugins/defaults/persistence/terminal.ts +0 -83
- package/src/plugins/defaults/title-generate/terminal.ts +0 -31
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
- package/src/plugins/defaults/token-estimate/package.json +0 -15
- package/src/plugins/defaults/token-estimate/register.ts +0 -34
- package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
- package/src/plugins/defaults/tool-error/terminal.ts +0 -47
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
- package/src/plugins/defaults/tool-execute/package.json +0 -15
- package/src/plugins/defaults/tool-execute/register.ts +0 -49
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
- package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
- package/src/skills/category-inference.ts +0 -111
package/src/plugins/types.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* placeholders) and add the pipeline runner, registry, and bootstrap.
|
|
8
8
|
*
|
|
9
9
|
* The assistant composes behavior around a small set of named pipelines
|
|
10
|
-
* (`
|
|
10
|
+
* (`compaction`, `overflowReduce`, ...). Each plugin may contribute one
|
|
11
11
|
* {@link Middleware} per pipeline; the registry composes them in onion
|
|
12
12
|
* order at runtime. Plugins may also contribute {@link Injector}s that emit
|
|
13
13
|
* system-prompt-time content, as well as model-visible capabilities
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import type { CompactionCircuitClosedEvent } from "../api/events/compaction-circuit-closed.js";
|
|
20
20
|
import type { CompactionCircuitOpenEvent } from "../api/events/compaction-circuit-open.js";
|
|
21
21
|
import type { ContextWindowConfig } from "../config/schemas/inference.js";
|
|
22
|
+
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
22
23
|
import type {
|
|
23
24
|
ContextWindowManager,
|
|
24
25
|
ContextWindowResult,
|
|
@@ -30,26 +31,13 @@ import type {
|
|
|
30
31
|
ChannelCommandContext,
|
|
31
32
|
InjectionMode,
|
|
32
33
|
} from "../daemon/conversation-runtime-assembly.js";
|
|
33
|
-
import type { PkbContextConversation } from "../daemon/pkb-context-tracker.js";
|
|
34
34
|
import type { TrustContext } from "../daemon/trust-context.js";
|
|
35
|
-
import type {
|
|
36
|
-
import type { QdrantSparseVector } from "../memory/qdrant-client.js";
|
|
35
|
+
import type { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
|
|
37
36
|
import type { PluginHookFn } from "../plugin-api/types.js";
|
|
38
|
-
import type {
|
|
39
|
-
ContentBlock,
|
|
40
|
-
Message,
|
|
41
|
-
Provider,
|
|
42
|
-
ProviderResponse,
|
|
43
|
-
SendMessageOptions,
|
|
44
|
-
ToolDefinition,
|
|
45
|
-
} from "../providers/types.js";
|
|
37
|
+
import type { Message } from "../providers/types.js";
|
|
46
38
|
import type { SkillRoute } from "../runtime/skill-route-registry.js";
|
|
47
|
-
import type { Tool
|
|
39
|
+
import type { Tool } from "../tools/types.js";
|
|
48
40
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
49
|
-
import type {
|
|
50
|
-
ToolResultTruncateArgs,
|
|
51
|
-
ToolResultTruncateResult,
|
|
52
|
-
} from "./defaults/tool-result-truncate/types.js";
|
|
53
41
|
|
|
54
42
|
// ─── Manifest ────────────────────────────────────────────────────────────────
|
|
55
43
|
|
|
@@ -120,152 +108,22 @@ export type Middleware<A, R> = (
|
|
|
120
108
|
* Exhaustive list of pipeline slot names. New pipelines must be added here
|
|
121
109
|
* and in `DEFAULT_TIMEOUTS` (PR 12). The registry only understands these.
|
|
122
110
|
*/
|
|
123
|
-
export type PipelineName =
|
|
124
|
-
| "turn"
|
|
125
|
-
| "llmCall"
|
|
126
|
-
| "toolExecute"
|
|
127
|
-
| "memoryRetrieval"
|
|
128
|
-
| "tokenEstimate"
|
|
129
|
-
| "compaction"
|
|
130
|
-
| "overflowReduce"
|
|
131
|
-
| "persistence"
|
|
132
|
-
| "titleGenerate"
|
|
133
|
-
| "toolResultTruncate"
|
|
134
|
-
| "emptyResponse"
|
|
135
|
-
| "toolError"
|
|
136
|
-
| "circuitBreaker";
|
|
111
|
+
export type PipelineName = "compaction" | "overflowReduce" | "circuitBreaker";
|
|
137
112
|
|
|
138
113
|
// ─── Per-pipeline args / results (placeholder shapes) ────────────────────────
|
|
139
114
|
// Concrete field-level types land in M2/M3 PRs as each pipeline is wrapped.
|
|
140
115
|
// Until then we expose `unknown`-tagged aliases so downstream code can name
|
|
141
116
|
// the types without depending on unstable internal shapes.
|
|
142
117
|
|
|
143
|
-
export type TurnArgs = { readonly input: unknown };
|
|
144
|
-
export type TurnResult = { readonly output: unknown };
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Pipeline arguments for `llmCall` — mirrors the inputs to
|
|
148
|
-
* {@link Provider.sendMessage}. The terminal handler (the default plugin)
|
|
149
|
-
* delegates straight to `args.provider.sendMessage(args.messages, args.options)`;
|
|
150
|
-
* middleware may observe or rewrite any field before that call, short-circuit
|
|
151
|
-
* with a synthetic {@link LLMCallResult}, or post-process the response on the
|
|
152
|
-
* way out.
|
|
153
|
-
*
|
|
154
|
-
* `provider` is passed in `args` (rather than resolved from the runtime) so
|
|
155
|
-
* middleware can swap it deterministically per-call. `options` carries the
|
|
156
|
-
* full `SendMessageOptions` bag — `tools`, `systemPrompt`, `config`,
|
|
157
|
-
* `onEvent`, and `signal` — so middleware can substitute streaming handlers,
|
|
158
|
-
* tool sets, or cancellation signals without reconstructing them.
|
|
159
|
-
*/
|
|
160
|
-
export type LLMCallArgs = {
|
|
161
|
-
readonly provider: Provider;
|
|
162
|
-
readonly messages: Message[];
|
|
163
|
-
readonly options?: SendMessageOptions;
|
|
164
|
-
};
|
|
165
|
-
export type LLMCallResult = ProviderResponse;
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Arguments passed to the `toolExecute` pipeline — mirrors the public
|
|
169
|
-
* {@link ToolExecutor.execute} signature so middleware can observe (and
|
|
170
|
-
* mutate) the tool name, input payload, and the full {@link ToolContext}
|
|
171
|
-
* before the terminal runs the actual execution.
|
|
172
|
-
*/
|
|
173
|
-
export interface ToolExecuteArgs {
|
|
174
|
-
readonly name: string;
|
|
175
|
-
readonly input: Record<string, unknown>;
|
|
176
|
-
readonly context: ToolContext;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
118
|
/**
|
|
180
|
-
*
|
|
181
|
-
* {@link
|
|
182
|
-
*
|
|
119
|
+
* Full output of a single memory-graph retrieval — the object returned by
|
|
120
|
+
* {@link ConversationGraphMemory.prepareMemory} (injected messages, query
|
|
121
|
+
* vectors, metrics). The agent loop consumes these fields directly to drive
|
|
122
|
+
* PKB hint search and runtime injection.
|
|
183
123
|
*/
|
|
184
|
-
export type
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
* A single retrieved memory artifact.
|
|
188
|
-
*
|
|
189
|
-
* The memory-graph retriever emits complex, tightly-coupled state (content
|
|
190
|
-
* blocks, query vectors, metrics, events, etc.) that downstream code in the
|
|
191
|
-
* agent loop consumes holistically. Representing each memory-graph output as
|
|
192
|
-
* an opaque `MemoryBlock` lets plugins swap in completely different shapes
|
|
193
|
-
* (custom retrievers, mocks for testing) without requiring the plugin surface
|
|
194
|
-
* to re-declare the graph result schema here. Refined by consumers via
|
|
195
|
-
* runtime narrowing — the default retriever attaches a structural marker so
|
|
196
|
-
* the agent loop can safely unwrap its own output.
|
|
197
|
-
*/
|
|
198
|
-
export type MemoryBlock = unknown;
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Inputs to the memory-retrieval pipeline. The pipeline takes only
|
|
202
|
-
* identifiers and the trust context — the actual data sources (PKB files,
|
|
203
|
-
* NOW.md, memory graph) are side-effectful and read by the terminal.
|
|
204
|
-
*
|
|
205
|
-
* `signal` is the per-turn abort signal forwarded to the memory graph's
|
|
206
|
-
* `prepareMemory` call. Carrying it on `args` (rather than on the
|
|
207
|
-
* `DefaultMemoryRetrievalDeps` extra-state bundle) is load-bearing: the
|
|
208
|
-
* pipeline runner's `linkAbortSignal` swaps any `AbortSignal`-typed
|
|
209
|
-
* property on top-level args for an internal linked signal, so a plugin
|
|
210
|
-
* timeout (or external cancel) actually reaches `prepareMemory` and cancels
|
|
211
|
-
* the underlying retrieval instead of letting it run to completion after
|
|
212
|
-
* the pipeline has already errored.
|
|
213
|
-
*/
|
|
214
|
-
export interface MemoryArgs {
|
|
215
|
-
readonly conversationId: string;
|
|
216
|
-
readonly trustContext: TrustContext | undefined;
|
|
217
|
-
readonly turnIndex: number;
|
|
218
|
-
readonly signal: AbortSignal;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Outputs of the memory-retrieval pipeline.
|
|
223
|
-
*
|
|
224
|
-
* - `pkbContent` / `nowContent`: trimmed file contents ready for injection,
|
|
225
|
-
* or `null` when the file is missing/empty.
|
|
226
|
-
* - `memoryGraphBlocks`: zero or one memory-graph retrievals (the default
|
|
227
|
-
* retriever yields exactly one when the actor is trusted and the graph
|
|
228
|
-
* produced output, zero otherwise). Multi-entry arrays are reserved for
|
|
229
|
-
* future multi-source retrievers; the current agent loop consumes only
|
|
230
|
-
* the first entry.
|
|
231
|
-
*/
|
|
232
|
-
export interface MemoryResult {
|
|
233
|
-
readonly pkbContent: string | null;
|
|
234
|
-
readonly nowContent: string | null;
|
|
235
|
-
readonly memoryGraphBlocks: ReadonlyArray<MemoryBlock>;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Inputs to the `tokenEstimate` pipeline. The default middleware delegates
|
|
240
|
-
* these straight to {@link estimatePromptTokensRaw}; custom plugins may
|
|
241
|
-
* substitute an alternate estimator (e.g. provider-native tokenization) by
|
|
242
|
-
* short-circuiting the pipeline with their own {@link EstimateResult}.
|
|
243
|
-
*
|
|
244
|
-
* Fields:
|
|
245
|
-
* - `history` — current message list to estimate over.
|
|
246
|
-
* - `systemPrompt` — system prompt string, or `undefined` when absent.
|
|
247
|
-
* - `tools` — tool definitions visible on this turn. The default plugin
|
|
248
|
-
* sums their token budget via `estimateToolsTokens(tools)` and hands the
|
|
249
|
-
* result to the raw estimator via `toolTokenBudget`. Plugins that want to
|
|
250
|
-
* ignore tool cost can skip that term.
|
|
251
|
-
* - `providerName` — canonical calibration provider key (the value returned
|
|
252
|
-
* by `getCalibrationProviderKey(provider)`). Drives provider-specific
|
|
253
|
-
* heuristics inside the raw estimator (e.g. Anthropic image sizing).
|
|
254
|
-
*/
|
|
255
|
-
export type EstimateArgs = {
|
|
256
|
-
readonly history: Message[];
|
|
257
|
-
readonly systemPrompt: string | undefined;
|
|
258
|
-
readonly tools: ToolDefinition[];
|
|
259
|
-
readonly providerName: string | undefined;
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
/** Result of the `tokenEstimate` pipeline — total estimated prompt tokens. */
|
|
263
|
-
export type EstimateResult = number;
|
|
264
|
-
|
|
265
|
-
/** Alias retained for symmetry with the rest of the pipeline-name family. */
|
|
266
|
-
export type TokenEstimateArgs = EstimateArgs;
|
|
267
|
-
/** Alias retained for symmetry with the rest of the pipeline-name family. */
|
|
268
|
-
export type TokenEstimateResult = EstimateResult;
|
|
124
|
+
export type GraphMemoryResult = Awaited<
|
|
125
|
+
ReturnType<ConversationGraphMemory["prepareMemory"]>
|
|
126
|
+
>;
|
|
269
127
|
|
|
270
128
|
/**
|
|
271
129
|
* Pipeline inputs for the `compaction` slot — the arguments the assistant
|
|
@@ -409,270 +267,6 @@ export interface OverflowReduceResult {
|
|
|
409
267
|
readonly attempts: number;
|
|
410
268
|
}
|
|
411
269
|
|
|
412
|
-
/**
|
|
413
|
-
* Pipeline arguments for `persistence` — a discriminated union over the
|
|
414
|
-
* message-CRUD operations plugins may observe, redirect, or short-circuit:
|
|
415
|
-
*
|
|
416
|
-
* - `add` — append a new message (`addMessage`). Mirrors
|
|
417
|
-
* `addMessage(conversationId, role, content, options?)`.
|
|
418
|
-
* When `syncToDisk` is set, the default plugin also runs
|
|
419
|
-
* {@link syncMessageToDisk} against the just-persisted row
|
|
420
|
-
* so the JSONL disk view stays consistent. The
|
|
421
|
-
* `createdAtMs` field carries the conversation's creation
|
|
422
|
-
* timestamp — needed to resolve the disk-view directory.
|
|
423
|
-
* - `reserve` — pre-allocate an empty assistant anchor row
|
|
424
|
-
* (`reserveMessage`) so the agent loop can stamp streaming
|
|
425
|
-
* events with stable identity before any content is
|
|
426
|
-
* produced. Returns the same row shape as `add`.
|
|
427
|
-
* - `updateContent` — overwrite the content of an existing message
|
|
428
|
-
* (`updateMessageContent`). Used to finalize a previously
|
|
429
|
-
* reserved row, and by consolidation paths.
|
|
430
|
-
* - `update` — shallow-merge metadata into an existing message
|
|
431
|
-
* (`updateMessageMetadata`). Returns `void`.
|
|
432
|
-
* - `delete` — remove a single message (`deleteMessageById`). Returns
|
|
433
|
-
* the {@link DeletedMemoryIds}-shaped segment/summary IDs
|
|
434
|
-
* the caller must clean up out-of-band.
|
|
435
|
-
*
|
|
436
|
-
* The discriminated `op` field lets plugin middleware narrow the union and
|
|
437
|
-
* tailor behavior per-operation (e.g. "only observe deletes", "redirect
|
|
438
|
-
* adds to a mock store").
|
|
439
|
-
*/
|
|
440
|
-
export type PersistAddArgs = {
|
|
441
|
-
readonly op: "add";
|
|
442
|
-
readonly conversationId: string;
|
|
443
|
-
readonly role: MessageRole;
|
|
444
|
-
readonly content: string;
|
|
445
|
-
readonly metadata?: Record<string, unknown>;
|
|
446
|
-
readonly addOptions?: { readonly skipIndexing?: boolean };
|
|
447
|
-
/**
|
|
448
|
-
* When `true`, the default plugin additionally invokes
|
|
449
|
-
* {@link syncMessageToDisk} with the returned message's id. Requires
|
|
450
|
-
* {@link createdAtMs} to resolve the conversation's disk-view directory.
|
|
451
|
-
*/
|
|
452
|
-
readonly syncToDisk?: boolean;
|
|
453
|
-
/** Conversation creation timestamp — only read when `syncToDisk` is true. */
|
|
454
|
-
readonly createdAtMs?: number;
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
export type PersistReserveArgs = {
|
|
458
|
-
readonly op: "reserve";
|
|
459
|
-
readonly conversationId: string;
|
|
460
|
-
readonly role: MessageRole;
|
|
461
|
-
readonly metadata?: Record<string, unknown>;
|
|
462
|
-
};
|
|
463
|
-
|
|
464
|
-
export type PersistUpdateContentArgs = {
|
|
465
|
-
readonly op: "updateContent";
|
|
466
|
-
readonly messageId: string;
|
|
467
|
-
readonly content: string;
|
|
468
|
-
};
|
|
469
|
-
|
|
470
|
-
export type PersistUpdateArgs = {
|
|
471
|
-
readonly op: "update";
|
|
472
|
-
readonly messageId: string;
|
|
473
|
-
readonly updates: Record<string, unknown>;
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
export type PersistDeleteArgs = {
|
|
477
|
-
readonly op: "delete";
|
|
478
|
-
readonly messageId: string;
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
export type PersistArgs =
|
|
482
|
-
| PersistAddArgs
|
|
483
|
-
| PersistReserveArgs
|
|
484
|
-
| PersistUpdateContentArgs
|
|
485
|
-
| PersistUpdateArgs
|
|
486
|
-
| PersistDeleteArgs;
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* Result row returned by an `add` op — matches the shape produced by
|
|
490
|
-
* {@link addMessage}. Kept structural (not imported from `memory/`) so the
|
|
491
|
-
* plugin types module stays decoupled from the storage layer.
|
|
492
|
-
*/
|
|
493
|
-
export type PersistAddResult = {
|
|
494
|
-
readonly op: "add";
|
|
495
|
-
readonly message: {
|
|
496
|
-
readonly id: string;
|
|
497
|
-
readonly conversationId: string;
|
|
498
|
-
readonly role: string;
|
|
499
|
-
readonly content: string;
|
|
500
|
-
readonly createdAt: number;
|
|
501
|
-
readonly metadata?: string;
|
|
502
|
-
};
|
|
503
|
-
};
|
|
504
|
-
|
|
505
|
-
/**
|
|
506
|
-
* Result row returned by a `reserve` op — same row shape as `add` but with
|
|
507
|
-
* empty `content` (`"[]"`) and tagged distinctly so middleware can branch
|
|
508
|
-
* on intent.
|
|
509
|
-
*/
|
|
510
|
-
export type PersistReserveResult = {
|
|
511
|
-
readonly op: "reserve";
|
|
512
|
-
readonly message: {
|
|
513
|
-
readonly id: string;
|
|
514
|
-
readonly conversationId: string;
|
|
515
|
-
readonly role: string;
|
|
516
|
-
readonly content: string;
|
|
517
|
-
readonly createdAt: number;
|
|
518
|
-
readonly metadata?: string;
|
|
519
|
-
};
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
export type PersistUpdateContentResult = { readonly op: "updateContent" };
|
|
523
|
-
|
|
524
|
-
export type PersistUpdateResult = { readonly op: "update" };
|
|
525
|
-
|
|
526
|
-
/** IDs of segments/summaries the caller must remove from Qdrant. */
|
|
527
|
-
export type PersistDeleteResult = {
|
|
528
|
-
readonly op: "delete";
|
|
529
|
-
readonly segmentIds: string[];
|
|
530
|
-
readonly deletedSummaryIds: string[];
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
export type PersistResult =
|
|
534
|
-
| PersistAddResult
|
|
535
|
-
| PersistReserveResult
|
|
536
|
-
| PersistUpdateContentResult
|
|
537
|
-
| PersistUpdateResult
|
|
538
|
-
| PersistDeleteResult;
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* Arguments for the `titleGenerate` pipeline. Mirrors the parameters of
|
|
542
|
-
* `queueGenerateConversationTitle` in `memory/conversation-title-service.ts`
|
|
543
|
-
* so the default plugin can delegate verbatim.
|
|
544
|
-
*
|
|
545
|
-
* `provider` is optional because the underlying service falls back to
|
|
546
|
-
* `getConfiguredProvider("conversationTitle")` when absent. `userMessage`
|
|
547
|
-
* carries the first turn's text — the service uses it as LLM context and
|
|
548
|
-
* also to derive a deterministic fallback title if the call fails.
|
|
549
|
-
*
|
|
550
|
-
* `onTitleUpdated` is a fire-and-forget callback the pipeline invokes when
|
|
551
|
-
* the title is finally persisted. The default implementation is
|
|
552
|
-
* fire-and-forget overall, so the pipeline result (`TitleResult`) carries no
|
|
553
|
-
* payload — callers that need the title must use the callback.
|
|
554
|
-
*/
|
|
555
|
-
export type TitleArgs = {
|
|
556
|
-
readonly conversationId: string;
|
|
557
|
-
readonly provider?: Provider;
|
|
558
|
-
readonly userMessage: string;
|
|
559
|
-
readonly onTitleUpdated?: (title: string) => void;
|
|
560
|
-
};
|
|
561
|
-
/**
|
|
562
|
-
* Result of the `titleGenerate` pipeline. The default implementation is
|
|
563
|
-
* fire-and-forget (it schedules background work and returns immediately),
|
|
564
|
-
* so there is nothing meaningful to return. Defined as an empty object so
|
|
565
|
-
* custom plugins can opt into richer payloads later.
|
|
566
|
-
*/
|
|
567
|
-
export type TitleResult = Readonly<Record<string, never>>;
|
|
568
|
-
|
|
569
|
-
/**
|
|
570
|
-
* @deprecated Alias kept for the M1 scaffolding era. Prefer {@link TitleArgs}.
|
|
571
|
-
*/
|
|
572
|
-
export type TitleGenerateArgs = TitleArgs;
|
|
573
|
-
/**
|
|
574
|
-
* @deprecated Alias kept for the M1 scaffolding era. Prefer {@link TitleResult}.
|
|
575
|
-
*/
|
|
576
|
-
export type TitleGenerateResult = TitleResult;
|
|
577
|
-
|
|
578
|
-
/**
|
|
579
|
-
* Snapshot of the just-completed assistant turn plus retry/context counters
|
|
580
|
-
* the `emptyResponse` pipeline needs to decide whether to nudge, accept, or
|
|
581
|
-
* surface an error.
|
|
582
|
-
*
|
|
583
|
-
* `emptyResponseRetries` is the *current* retry counter — the pipeline may
|
|
584
|
-
* compare it to `maxEmptyResponseRetries` to implement a retry cap. The loop
|
|
585
|
-
* increments the counter only after a `"nudge"` decision; the pipeline is
|
|
586
|
-
* stateless across turns.
|
|
587
|
-
*
|
|
588
|
-
* `priorAssistantHadVisibleText` signals that an earlier turn in the current
|
|
589
|
-
* `run()` invocation already delivered user-visible text. When true, an
|
|
590
|
-
* empty follow-up is the model correctly ending its turn and nudging would
|
|
591
|
-
* mislead it into resending text the user already saw.
|
|
592
|
-
*/
|
|
593
|
-
export interface EmptyResponseArgs {
|
|
594
|
-
/** Content blocks produced by the assistant on this turn. */
|
|
595
|
-
readonly responseContent: ReadonlyArray<ContentBlock>;
|
|
596
|
-
/**
|
|
597
|
-
* Number of `tool_use` blocks in `responseContent`. Mirrors the loop's own
|
|
598
|
-
* count so middleware doesn't have to recompute it. When > 0 the turn is
|
|
599
|
-
* not empty — the model issued tool calls.
|
|
600
|
-
*/
|
|
601
|
-
readonly toolUseBlocksLength: number;
|
|
602
|
-
/** 0-based index of the tool-use turn being evaluated. */
|
|
603
|
-
readonly toolUseTurns: number;
|
|
604
|
-
/** How many empty-response nudges the loop has already issued this run. */
|
|
605
|
-
readonly emptyResponseRetries: number;
|
|
606
|
-
/** Upper bound for `emptyResponseRetries`. The default is 1. */
|
|
607
|
-
readonly maxEmptyResponseRetries: number;
|
|
608
|
-
/**
|
|
609
|
-
* Whether ANY prior assistant turn in the current `run()` call carried
|
|
610
|
-
* visible text. See `agent/loop.ts` for why the whole-run scan matters.
|
|
611
|
-
*/
|
|
612
|
-
readonly priorAssistantHadVisibleText: boolean;
|
|
613
|
-
/**
|
|
614
|
-
* Provider-reported stop reason for the assistant turn being evaluated.
|
|
615
|
-
* `null`/`undefined` when the provider didn't report one (older
|
|
616
|
-
* providers, partial responses). The default terminal uses this to
|
|
617
|
-
* distinguish an explicit safety-classifier refusal (Anthropic's
|
|
618
|
-
* `"refusal"`) from an organically-empty turn — refusals deserve a
|
|
619
|
-
* nudge even on the very first model call of the run, whereas an
|
|
620
|
-
* organically-empty first call usually means the model legitimately
|
|
621
|
-
* had nothing to say.
|
|
622
|
-
*/
|
|
623
|
-
readonly stopReason: string | null | undefined;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
/**
|
|
627
|
-
* Decision produced by the `emptyResponse` pipeline.
|
|
628
|
-
*
|
|
629
|
-
* - `"nudge"` — loop appends `nudgeText` as a `user` message and retries.
|
|
630
|
-
* `nudgeText` MUST be present; it is what the model will see.
|
|
631
|
-
* - `"accept"` — loop treats the turn as complete (pushes the assistant
|
|
632
|
-
* message to history and exits the tool-use chain normally).
|
|
633
|
-
* - `"error"` — loop surfaces a clear error. Reserved for middleware that
|
|
634
|
-
* wants to escalate an empty response rather than absorb it.
|
|
635
|
-
*/
|
|
636
|
-
export interface EmptyResponseDecision {
|
|
637
|
-
readonly action: "nudge" | "accept" | "error";
|
|
638
|
-
/** Nudge text the loop will push to history. Required when `action === "nudge"`. */
|
|
639
|
-
readonly nudgeText?: string;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
/** Alias so the {@link PipelineMiddlewareMap} entry names its own result shape. */
|
|
643
|
-
export type EmptyResponseResult = EmptyResponseDecision;
|
|
644
|
-
|
|
645
|
-
/**
|
|
646
|
-
* Arguments to the `toolError` pipeline — invoked by the agent loop once per
|
|
647
|
-
* turn that produced tool results, BEFORE the turn's tool-result user message
|
|
648
|
-
* is pushed into history.
|
|
649
|
-
*
|
|
650
|
-
* `hasToolError` is true when at least one tool in the current turn returned
|
|
651
|
-
* `isError: true`. `consecutiveErrorTurns` is the running count of
|
|
652
|
-
* back-to-back error turns (reset to 0 on a clean turn, incremented on each
|
|
653
|
-
* error turn). `maxConsecutiveErrorNudges` is the default cap the agent loop
|
|
654
|
-
* currently applies; plugins receive it so they can match the default
|
|
655
|
-
* threshold exactly or compute a relative offset.
|
|
656
|
-
*/
|
|
657
|
-
export type ToolErrorArgs = {
|
|
658
|
-
readonly hasToolError: boolean;
|
|
659
|
-
readonly consecutiveErrorTurns: number;
|
|
660
|
-
readonly maxConsecutiveErrorNudges: number;
|
|
661
|
-
};
|
|
662
|
-
|
|
663
|
-
/**
|
|
664
|
-
* Decision returned by the `toolError` pipeline. When `action` is `"nudge"`,
|
|
665
|
-
* the agent loop appends a text block with `nudgeText` to the turn's tool
|
|
666
|
-
* results so the next LLM turn sees the nudge. When `action` is `"skip"`, no
|
|
667
|
-
* nudge is injected and the tool results pass through unchanged.
|
|
668
|
-
*/
|
|
669
|
-
export type ToolErrorDecision =
|
|
670
|
-
| { readonly action: "nudge"; readonly nudgeText: string }
|
|
671
|
-
| { readonly action: "skip" };
|
|
672
|
-
|
|
673
|
-
/** Alias kept so `PipelineMiddlewareMap.toolError` reads result-shaped. */
|
|
674
|
-
export type ToolErrorResult = ToolErrorDecision;
|
|
675
|
-
|
|
676
270
|
/**
|
|
677
271
|
* Arguments for the `circuitBreaker` pipeline.
|
|
678
272
|
*
|
|
@@ -741,21 +335,8 @@ export type CircuitBreakerResult = {
|
|
|
741
335
|
* `getMiddlewaresFor<P>()` type narrowing in PR 13.
|
|
742
336
|
*/
|
|
743
337
|
export interface PipelineMiddlewareMap {
|
|
744
|
-
turn: Middleware<TurnArgs, TurnResult>;
|
|
745
|
-
llmCall: Middleware<LLMCallArgs, LLMCallResult>;
|
|
746
|
-
toolExecute: Middleware<ToolExecuteArgs, ToolExecuteResult>;
|
|
747
|
-
memoryRetrieval: Middleware<MemoryArgs, MemoryResult>;
|
|
748
|
-
tokenEstimate: Middleware<TokenEstimateArgs, TokenEstimateResult>;
|
|
749
338
|
compaction: Middleware<CompactionArgs, CompactionResult>;
|
|
750
339
|
overflowReduce: Middleware<OverflowReduceArgs, OverflowReduceResult>;
|
|
751
|
-
persistence: Middleware<PersistArgs, PersistResult>;
|
|
752
|
-
titleGenerate: Middleware<TitleArgs, TitleResult>;
|
|
753
|
-
toolResultTruncate: Middleware<
|
|
754
|
-
ToolResultTruncateArgs,
|
|
755
|
-
ToolResultTruncateResult
|
|
756
|
-
>;
|
|
757
|
-
emptyResponse: Middleware<EmptyResponseArgs, EmptyResponseResult>;
|
|
758
|
-
toolError: Middleware<ToolErrorArgs, ToolErrorResult>;
|
|
759
340
|
circuitBreaker: Middleware<CircuitBreakerArgs, CircuitBreakerResult>;
|
|
760
341
|
}
|
|
761
342
|
|
|
@@ -790,43 +371,6 @@ export interface TurnInjectionInputs {
|
|
|
790
371
|
readonly workspaceTopLevelContext?: string | null;
|
|
791
372
|
/** Pre-built unified-turn-context text (`<turn_context>...`) or null to skip. */
|
|
792
373
|
readonly unifiedTurnContext?: string | null;
|
|
793
|
-
/** PKB auto-injected content (`<knowledge_base>...`) or null to skip. */
|
|
794
|
-
readonly pkbContext?: string | null;
|
|
795
|
-
/**
|
|
796
|
-
* Whether PKB is active for this turn — drives the `<system_reminder>` /
|
|
797
|
-
* hybrid-search relevance-hint branch.
|
|
798
|
-
*/
|
|
799
|
-
readonly pkbActive?: boolean;
|
|
800
|
-
/** Dense query vector surfaced from the graph memory retriever for PKB hints. */
|
|
801
|
-
readonly pkbQueryVector?: number[];
|
|
802
|
-
/** Optional sparse vector accompanying `pkbQueryVector`. */
|
|
803
|
-
readonly pkbSparseVector?: QdrantSparseVector;
|
|
804
|
-
/** Memory scope id used to filter PKB search results. */
|
|
805
|
-
readonly pkbScopeId?: string;
|
|
806
|
-
/**
|
|
807
|
-
* Live conversation (or a minimal shape containing `messages`) used to
|
|
808
|
-
* compute which PKB paths are already "in context" and therefore suppressed
|
|
809
|
-
* from hint suggestions.
|
|
810
|
-
*/
|
|
811
|
-
readonly pkbConversation?: PkbContextConversation;
|
|
812
|
-
/** Auto-injected PKB filenames resolved relative to `pkbRoot`. */
|
|
813
|
-
readonly pkbAutoInjectList?: string[];
|
|
814
|
-
/** Absolute path to the PKB directory (e.g. `<workspace>/pkb`). */
|
|
815
|
-
readonly pkbRoot?: string;
|
|
816
|
-
/**
|
|
817
|
-
* Working directory against which relative `file_read` paths resolve.
|
|
818
|
-
* Falls back to `pkbRoot` when omitted.
|
|
819
|
-
*/
|
|
820
|
-
readonly pkbWorkingDir?: string;
|
|
821
|
-
/**
|
|
822
|
-
* Pre-rendered v2 static memory content (essentials/threads/recent/buffer
|
|
823
|
-
* concatenated, header-wrapped) or null to skip. The agent loop only
|
|
824
|
-
* passes this on full-mode turns; the injector wraps it in `<memory>` for
|
|
825
|
-
* the user message.
|
|
826
|
-
*/
|
|
827
|
-
readonly memoryV2Static?: string | null;
|
|
828
|
-
/** NOW.md scratchpad content or null to skip. */
|
|
829
|
-
readonly nowScratchpad?: string | null;
|
|
830
374
|
/** Pre-built `<active_subagents>` block or null to skip. */
|
|
831
375
|
readonly subagentStatusBlock?: string | null;
|
|
832
376
|
/** Channel capabilities — drives slack gating. */
|
|
@@ -937,6 +481,20 @@ export interface TurnContext {
|
|
|
937
481
|
* a context without `injectionInputs` produces an empty injection chain.
|
|
938
482
|
*/
|
|
939
483
|
injectionInputs?: TurnInjectionInputs;
|
|
484
|
+
/**
|
|
485
|
+
* The {@link LLMCallSite} this turn's pipeline work belongs to —
|
|
486
|
+
* `"mainAgent"` for the user-facing conversational reply, or the specific
|
|
487
|
+
* background/utility site (`"compactionAgent"`, `"subagentSpawn"`,
|
|
488
|
+
* `"memoryConsolidation"`, `"conversationTitle"`, …) when the agent loop is
|
|
489
|
+
* driving non-main work that happens to share the same `conversationId`.
|
|
490
|
+
*
|
|
491
|
+
* Lets {@link Injector}s and pipeline middleware scope their behaviour to
|
|
492
|
+
* the main reply and stay out of background turns, which `onEvent` presence
|
|
493
|
+
* alone cannot distinguish (compaction and subagent loops also stream).
|
|
494
|
+
* Omitted by call sites that don't tag a site (synthesized test contexts);
|
|
495
|
+
* consumers should treat absence conservatively.
|
|
496
|
+
*/
|
|
497
|
+
callSite?: LLMCallSite;
|
|
940
498
|
}
|
|
941
499
|
|
|
942
500
|
// ─── Injectors ───────────────────────────────────────────────────────────────
|
|
@@ -1016,8 +574,21 @@ export interface Injector {
|
|
|
1016
574
|
name: string;
|
|
1017
575
|
/** Ascending sort key — lower runs first. */
|
|
1018
576
|
order: number;
|
|
1019
|
-
/**
|
|
1020
|
-
|
|
577
|
+
/**
|
|
578
|
+
* Produce a block, or `null` to contribute nothing on this turn.
|
|
579
|
+
*
|
|
580
|
+
* `runMessages` is the turn's working message array — the same array the
|
|
581
|
+
* chain's blocks are spliced onto — passed explicitly so injectors that
|
|
582
|
+
* need the current prompt contents (e.g. the PKB reminder, which scans for
|
|
583
|
+
* already-loaded `file_read` paths) read it from a parameter rather than a
|
|
584
|
+
* field on the shared {@link TurnContext}. Absent for text-only chain
|
|
585
|
+
* consumers ({@link composeInjectorChain}) that drive injectors without a
|
|
586
|
+
* message array.
|
|
587
|
+
*/
|
|
588
|
+
produce(
|
|
589
|
+
ctx: TurnContext,
|
|
590
|
+
runMessages?: Message[],
|
|
591
|
+
): Promise<InjectionBlock | null>;
|
|
1021
592
|
}
|
|
1022
593
|
|
|
1023
594
|
// ─── Model-visible capability slots ──────────────────────────────────────────
|
|
@@ -1104,7 +675,7 @@ export type PluginHooks = Record<string, PluginHookFn<any>>;
|
|
|
1104
675
|
|
|
1105
676
|
/**
|
|
1106
677
|
* A registered plugin. Every field besides `manifest` is optional — a plugin
|
|
1107
|
-
* may contribute any combination of middleware
|
|
678
|
+
* may contribute any combination of middleware and model-visible
|
|
1108
679
|
* capabilities. Lifecycle hooks live under `hooks`.
|
|
1109
680
|
*/
|
|
1110
681
|
export interface Plugin {
|
|
@@ -1126,8 +697,6 @@ export interface Plugin {
|
|
|
1126
697
|
routes?: PluginRouteRegistration[];
|
|
1127
698
|
/** Skill registrations loaded at startup. */
|
|
1128
699
|
skills?: PluginSkillRegistration[];
|
|
1129
|
-
/** Prompt-time injectors contributed by this plugin. */
|
|
1130
|
-
injectors?: Injector[];
|
|
1131
700
|
/**
|
|
1132
701
|
* Named middleware slots. At most one middleware per slot per plugin.
|
|
1133
702
|
* The registry composes multiple plugins' middleware for a slot in
|
|
@@ -24,7 +24,7 @@ async function waitForIdle(conversationId: string): Promise<boolean> {
|
|
|
24
24
|
const start = Date.now();
|
|
25
25
|
while (Date.now() - start < IDLE_TIMEOUT_MS) {
|
|
26
26
|
const conv = findConversation(conversationId);
|
|
27
|
-
if (!conv || !conv.
|
|
27
|
+
if (!conv || !conv.isProcessing()) return true;
|
|
28
28
|
await new Promise((resolve) => setTimeout(resolve, IDLE_POLL_MS));
|
|
29
29
|
}
|
|
30
30
|
return false;
|
|
@@ -36,7 +36,7 @@ export async function injectAuxAssistantMessage(params: {
|
|
|
36
36
|
broadcastMessage: BroadcastFn;
|
|
37
37
|
}): Promise<void> {
|
|
38
38
|
const conv = findConversation(params.conversationId);
|
|
39
|
-
if (conv?.
|
|
39
|
+
if (conv?.isProcessing()) {
|
|
40
40
|
const reachedIdle = await waitForIdle(params.conversationId);
|
|
41
41
|
if (!reachedIdle) {
|
|
42
42
|
log.warn(
|
|
@@ -54,7 +54,7 @@ export async function injectAuxAssistantMessage(params: {
|
|
|
54
54
|
);
|
|
55
55
|
|
|
56
56
|
const current = findConversation(params.conversationId);
|
|
57
|
-
if (current && !current.
|
|
57
|
+
if (current && !current.isProcessing()) {
|
|
58
58
|
current.getMessages().push(createAssistantMessage(params.text));
|
|
59
59
|
|
|
60
60
|
params.broadcastMessage({
|