@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
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the `toolResultTruncate` plugin pipeline (PR 17).
|
|
3
|
-
*
|
|
4
|
-
* Covers:
|
|
5
|
-
* - The default terminal delegates to `truncateToolResultText`, producing
|
|
6
|
-
* byte-for-byte identical output to calling the helper directly across
|
|
7
|
-
* short, long, and newline-bounded inputs (property-style).
|
|
8
|
-
* - The pipeline routes through `runPipeline` with the
|
|
9
|
-
* `DEFAULT_TIMEOUTS.toolResultTruncate` budget and returns a
|
|
10
|
-
* `{ content, truncated }` pair whose `truncated` flag matches whether
|
|
11
|
-
* the content actually changed.
|
|
12
|
-
* - Plugins registered alongside the default can short-circuit or decorate
|
|
13
|
-
* the terminal's output.
|
|
14
|
-
* - A user plugin registered AFTER the default still runs — the default
|
|
15
|
-
* plugin's middleware is a passthrough, so the onion composition cannot
|
|
16
|
-
* shadow late-registered middleware.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { beforeEach, describe, expect, test } from "bun:test";
|
|
20
|
-
|
|
21
|
-
import type { TrustContext } from "../daemon/trust-context.js";
|
|
22
|
-
import { defaultToolResultTruncatePlugin } from "../plugins/defaults/tool-result-truncate/register.js";
|
|
23
|
-
import {
|
|
24
|
-
defaultToolResultTruncateTerminal,
|
|
25
|
-
MIN_KEEP_CHARS,
|
|
26
|
-
truncateToolResultText,
|
|
27
|
-
TRUNCATION_SUFFIX,
|
|
28
|
-
} from "../plugins/defaults/tool-result-truncate/terminal.js";
|
|
29
|
-
import type {
|
|
30
|
-
ToolResultTruncateArgs,
|
|
31
|
-
ToolResultTruncateResult,
|
|
32
|
-
} from "../plugins/defaults/tool-result-truncate/types.js";
|
|
33
|
-
import { DEFAULT_TIMEOUTS, runPipeline } from "../plugins/pipeline.js";
|
|
34
|
-
import {
|
|
35
|
-
getMiddlewaresFor,
|
|
36
|
-
registerPlugin,
|
|
37
|
-
resetPluginRegistryForTests,
|
|
38
|
-
} from "../plugins/registry.js";
|
|
39
|
-
import { type Middleware, type TurnContext } from "../plugins/types.js";
|
|
40
|
-
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
// Fixtures
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
|
-
|
|
45
|
-
const trust: TrustContext = {
|
|
46
|
-
sourceChannel: "vellum",
|
|
47
|
-
trustClass: "guardian",
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
function makeCtx(overrides: Partial<TurnContext> = {}): TurnContext {
|
|
51
|
-
return {
|
|
52
|
-
requestId: "req-test",
|
|
53
|
-
conversationId: "conv-test",
|
|
54
|
-
turnIndex: 0,
|
|
55
|
-
trust,
|
|
56
|
-
...overrides,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
describe("toolResultTruncate pipeline", () => {
|
|
61
|
-
beforeEach(() => {
|
|
62
|
-
resetPluginRegistryForTests();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// -------------------------------------------------------------------------
|
|
66
|
-
// Default terminal — isolated (no pipeline runner)
|
|
67
|
-
// -------------------------------------------------------------------------
|
|
68
|
-
|
|
69
|
-
describe("default terminal", () => {
|
|
70
|
-
test("passes short content through unchanged with truncated=false", () => {
|
|
71
|
-
const content = "hello world";
|
|
72
|
-
const result = defaultToolResultTruncateTerminal({
|
|
73
|
-
content,
|
|
74
|
-
maxChars: 100,
|
|
75
|
-
});
|
|
76
|
-
expect(result.content).toBe(content);
|
|
77
|
-
expect(result.truncated).toBe(false);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("truncates oversize content and reports truncated=true", () => {
|
|
81
|
-
const content = "a".repeat(10_000);
|
|
82
|
-
const maxChars = 5_000;
|
|
83
|
-
const expected = truncateToolResultText(content, maxChars);
|
|
84
|
-
const result = defaultToolResultTruncateTerminal({ content, maxChars });
|
|
85
|
-
expect(result.content).toBe(expected);
|
|
86
|
-
expect(result.truncated).toBe(true);
|
|
87
|
-
expect(result.content).toContain(TRUNCATION_SUFFIX);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test("snaps to newline boundary identically to truncateToolResultText", () => {
|
|
91
|
-
const lines = Array.from(
|
|
92
|
-
{ length: 1_000 },
|
|
93
|
-
(_, i) => `line ${i}: ${"x".repeat(20)}`,
|
|
94
|
-
).join("\n");
|
|
95
|
-
const maxChars = 5_000;
|
|
96
|
-
const expected = truncateToolResultText(lines, maxChars);
|
|
97
|
-
const result = defaultToolResultTruncateTerminal({
|
|
98
|
-
content: lines,
|
|
99
|
-
maxChars,
|
|
100
|
-
});
|
|
101
|
-
expect(result.content).toBe(expected);
|
|
102
|
-
expect(result.truncated).toBe(true);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test("returns truncated=false when effectiveMax keeps the full text (maxChars < MIN_KEEP_CHARS case)", () => {
|
|
106
|
-
const textLength = MIN_KEEP_CHARS - TRUNCATION_SUFFIX.length - 10;
|
|
107
|
-
const content = "a".repeat(textLength);
|
|
108
|
-
const maxChars = 100;
|
|
109
|
-
const expected = truncateToolResultText(content, maxChars);
|
|
110
|
-
const result = defaultToolResultTruncateTerminal({ content, maxChars });
|
|
111
|
-
// Helper returns the original text unchanged in this case.
|
|
112
|
-
expect(expected).toBe(content);
|
|
113
|
-
expect(result.content).toBe(content);
|
|
114
|
-
expect(result.truncated).toBe(false);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// -------------------------------------------------------------------------
|
|
119
|
-
// End-to-end: default plugin routed through runPipeline
|
|
120
|
-
// -------------------------------------------------------------------------
|
|
121
|
-
|
|
122
|
-
describe("runPipeline with the default plugin registered", () => {
|
|
123
|
-
async function runDefault(
|
|
124
|
-
content: string,
|
|
125
|
-
maxChars: number,
|
|
126
|
-
): Promise<ToolResultTruncateResult> {
|
|
127
|
-
registerPlugin(defaultToolResultTruncatePlugin);
|
|
128
|
-
const middlewares = getMiddlewaresFor("toolResultTruncate");
|
|
129
|
-
return runPipeline<ToolResultTruncateArgs, ToolResultTruncateResult>(
|
|
130
|
-
"toolResultTruncate",
|
|
131
|
-
middlewares,
|
|
132
|
-
async (args) => defaultToolResultTruncateTerminal(args),
|
|
133
|
-
{ content, maxChars },
|
|
134
|
-
makeCtx(),
|
|
135
|
-
DEFAULT_TIMEOUTS.toolResultTruncate,
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
test("short content round-trip matches truncateToolResultText", async () => {
|
|
140
|
-
const content = "quick brown fox";
|
|
141
|
-
const maxChars = 200;
|
|
142
|
-
const expected = truncateToolResultText(content, maxChars);
|
|
143
|
-
const result = await runDefault(content, maxChars);
|
|
144
|
-
expect(result.content).toBe(expected);
|
|
145
|
-
expect(result.truncated).toBe(false);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test("long content round-trip matches truncateToolResultText", async () => {
|
|
149
|
-
const content = "z".repeat(50_000);
|
|
150
|
-
const maxChars = 10_000;
|
|
151
|
-
const expected = truncateToolResultText(content, maxChars);
|
|
152
|
-
const result = await runDefault(content, maxChars);
|
|
153
|
-
expect(result.content).toBe(expected);
|
|
154
|
-
expect(result.truncated).toBe(true);
|
|
155
|
-
expect(result.content).toContain(TRUNCATION_SUFFIX);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test("newline-bounded content round-trip matches truncateToolResultText", async () => {
|
|
159
|
-
const lines = Array.from(
|
|
160
|
-
{ length: 500 },
|
|
161
|
-
(_, i) => `line ${i}: ${"y".repeat(40)}`,
|
|
162
|
-
).join("\n");
|
|
163
|
-
const maxChars = 4_000;
|
|
164
|
-
const expected = truncateToolResultText(lines, maxChars);
|
|
165
|
-
const result = await runDefault(lines, maxChars);
|
|
166
|
-
expect(result.content).toBe(expected);
|
|
167
|
-
expect(result.truncated).toBe(true);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
test("property test: default pipeline output equals direct truncateToolResultText across varied inputs", async () => {
|
|
171
|
-
// Deterministic pseudo-random over a fixed seed — bun's test runner
|
|
172
|
-
// doesn't ship a property-test library, so we hand-roll a tiny LCG
|
|
173
|
-
// that produces enough spread for a meaningful regression signal
|
|
174
|
-
// without introducing a dependency.
|
|
175
|
-
let seed = 0xc0ffee;
|
|
176
|
-
const rand = () => {
|
|
177
|
-
seed = (seed * 1664525 + 1013904223) & 0xffffffff;
|
|
178
|
-
return (seed >>> 0) / 0x100000000;
|
|
179
|
-
};
|
|
180
|
-
const alphabet = "abcdefghijklmnopqrstuvwxyz \n";
|
|
181
|
-
|
|
182
|
-
const cases: Array<{ content: string; maxChars: number }> = [];
|
|
183
|
-
for (let i = 0; i < 40; i++) {
|
|
184
|
-
// Lengths span short, boundary, and long relative to the maxChars
|
|
185
|
-
// budget so the property covers pass-through, newline-snap, and
|
|
186
|
-
// pure tail-drop paths.
|
|
187
|
-
const length = Math.floor(rand() * 20_000);
|
|
188
|
-
let content = "";
|
|
189
|
-
for (let j = 0; j < length; j++) {
|
|
190
|
-
content += alphabet[Math.floor(rand() * alphabet.length)];
|
|
191
|
-
}
|
|
192
|
-
const maxChars = 1_000 + Math.floor(rand() * 9_000);
|
|
193
|
-
cases.push({ content, maxChars });
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Register once outside the loop — registry is reset in `beforeEach`,
|
|
197
|
-
// so the per-case reset lives in the loop instead.
|
|
198
|
-
for (const { content, maxChars } of cases) {
|
|
199
|
-
resetPluginRegistryForTests();
|
|
200
|
-
registerPlugin(defaultToolResultTruncatePlugin);
|
|
201
|
-
const middlewares = getMiddlewaresFor("toolResultTruncate");
|
|
202
|
-
const result = await runPipeline<
|
|
203
|
-
ToolResultTruncateArgs,
|
|
204
|
-
ToolResultTruncateResult
|
|
205
|
-
>(
|
|
206
|
-
"toolResultTruncate",
|
|
207
|
-
middlewares,
|
|
208
|
-
async (args) => defaultToolResultTruncateTerminal(args),
|
|
209
|
-
{ content, maxChars },
|
|
210
|
-
makeCtx(),
|
|
211
|
-
DEFAULT_TIMEOUTS.toolResultTruncate,
|
|
212
|
-
);
|
|
213
|
-
const expected = truncateToolResultText(content, maxChars);
|
|
214
|
-
expect(result.content).toBe(expected);
|
|
215
|
-
expect(result.truncated).toBe(expected !== content);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
// -------------------------------------------------------------------------
|
|
221
|
-
// Middleware composition — an outer plugin can intercept / transform
|
|
222
|
-
// -------------------------------------------------------------------------
|
|
223
|
-
|
|
224
|
-
describe("middleware composition", () => {
|
|
225
|
-
test("an outer plugin can short-circuit the default with its own content", async () => {
|
|
226
|
-
const shortCircuit: Middleware<
|
|
227
|
-
ToolResultTruncateArgs,
|
|
228
|
-
ToolResultTruncateResult
|
|
229
|
-
> = async (_args, _next, _ctx) => {
|
|
230
|
-
return { content: "SUMMARY", truncated: true };
|
|
231
|
-
};
|
|
232
|
-
registerPlugin({
|
|
233
|
-
manifest: {
|
|
234
|
-
name: "short-circuit",
|
|
235
|
-
version: "1.0.0",
|
|
236
|
-
},
|
|
237
|
-
middleware: { toolResultTruncate: shortCircuit },
|
|
238
|
-
});
|
|
239
|
-
registerPlugin(defaultToolResultTruncatePlugin);
|
|
240
|
-
|
|
241
|
-
const middlewares = getMiddlewaresFor("toolResultTruncate");
|
|
242
|
-
const result = await runPipeline<
|
|
243
|
-
ToolResultTruncateArgs,
|
|
244
|
-
ToolResultTruncateResult
|
|
245
|
-
>(
|
|
246
|
-
"toolResultTruncate",
|
|
247
|
-
middlewares,
|
|
248
|
-
async (args) => defaultToolResultTruncateTerminal(args),
|
|
249
|
-
{ content: "a".repeat(10_000), maxChars: 5_000 },
|
|
250
|
-
makeCtx(),
|
|
251
|
-
DEFAULT_TIMEOUTS.toolResultTruncate,
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
expect(result.content).toBe("SUMMARY");
|
|
255
|
-
expect(result.truncated).toBe(true);
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
test("an outer plugin can observe and mutate the default's output", async () => {
|
|
259
|
-
const prefixer: Middleware<
|
|
260
|
-
ToolResultTruncateArgs,
|
|
261
|
-
ToolResultTruncateResult
|
|
262
|
-
> = async (args, next, _ctx) => {
|
|
263
|
-
const inner = await next(args);
|
|
264
|
-
return { ...inner, content: `[wrapped] ${inner.content}` };
|
|
265
|
-
};
|
|
266
|
-
registerPlugin({
|
|
267
|
-
manifest: {
|
|
268
|
-
name: "prefixer",
|
|
269
|
-
version: "1.0.0",
|
|
270
|
-
},
|
|
271
|
-
middleware: { toolResultTruncate: prefixer },
|
|
272
|
-
});
|
|
273
|
-
registerPlugin(defaultToolResultTruncatePlugin);
|
|
274
|
-
|
|
275
|
-
const middlewares = getMiddlewaresFor("toolResultTruncate");
|
|
276
|
-
const content = "hello";
|
|
277
|
-
const result = await runPipeline<
|
|
278
|
-
ToolResultTruncateArgs,
|
|
279
|
-
ToolResultTruncateResult
|
|
280
|
-
>(
|
|
281
|
-
"toolResultTruncate",
|
|
282
|
-
middlewares,
|
|
283
|
-
async (args) => defaultToolResultTruncateTerminal(args),
|
|
284
|
-
{ content, maxChars: 100 },
|
|
285
|
-
makeCtx(),
|
|
286
|
-
DEFAULT_TIMEOUTS.toolResultTruncate,
|
|
287
|
-
);
|
|
288
|
-
|
|
289
|
-
expect(result.content).toBe(`[wrapped] ${content}`);
|
|
290
|
-
expect(result.truncated).toBe(false);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
test("user plugin registered AFTER the default still runs (no shadowing)", async () => {
|
|
294
|
-
// Production registration order: defaults load first via the
|
|
295
|
-
// side-effect imports in `defaults/index.ts`, then user plugins
|
|
296
|
-
// register on top (via `bootstrapPlugins()` or hot-reload). The
|
|
297
|
-
// user's middleware ends up at a deeper onion layer than the
|
|
298
|
-
// default. If the default's middleware were to bypass `next` and
|
|
299
|
-
// call the terminal directly, the user middleware would never run
|
|
300
|
-
// — this test guards against that regression.
|
|
301
|
-
registerPlugin(defaultToolResultTruncatePlugin);
|
|
302
|
-
|
|
303
|
-
let userMiddlewareRan = false;
|
|
304
|
-
const userMiddleware: Middleware<
|
|
305
|
-
ToolResultTruncateArgs,
|
|
306
|
-
ToolResultTruncateResult
|
|
307
|
-
> = async (args, next) => {
|
|
308
|
-
userMiddlewareRan = true;
|
|
309
|
-
return next(args);
|
|
310
|
-
};
|
|
311
|
-
registerPlugin({
|
|
312
|
-
manifest: {
|
|
313
|
-
name: "late-user-plugin",
|
|
314
|
-
version: "0.0.1",
|
|
315
|
-
},
|
|
316
|
-
middleware: { toolResultTruncate: userMiddleware },
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
const middlewares = getMiddlewaresFor("toolResultTruncate");
|
|
320
|
-
const content = "a".repeat(10_000);
|
|
321
|
-
const maxChars = 5_000;
|
|
322
|
-
const result = await runPipeline<
|
|
323
|
-
ToolResultTruncateArgs,
|
|
324
|
-
ToolResultTruncateResult
|
|
325
|
-
>(
|
|
326
|
-
"toolResultTruncate",
|
|
327
|
-
middlewares,
|
|
328
|
-
async (args) => defaultToolResultTruncateTerminal(args),
|
|
329
|
-
{ content, maxChars },
|
|
330
|
-
makeCtx(),
|
|
331
|
-
DEFAULT_TIMEOUTS.toolResultTruncate,
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
expect(userMiddlewareRan).toBe(true);
|
|
335
|
-
// Terminal still runs after the user passthrough, so output matches
|
|
336
|
-
// the direct helper.
|
|
337
|
-
expect(result.content).toBe(truncateToolResultText(content, maxChars));
|
|
338
|
-
expect(result.truncated).toBe(true);
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
});
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { getMessages, type MessageRow } from "../memory/conversation-crud.js";
|
|
2
|
-
import { cleanupBootstrapFiles } from "../prompts/bootstrap-cleanup.js";
|
|
3
|
-
import { getLogger } from "../util/logger.js";
|
|
4
|
-
|
|
5
|
-
export const BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD = 4;
|
|
6
|
-
|
|
7
|
-
const log = getLogger("bootstrap-turn-cleanup");
|
|
8
|
-
|
|
9
|
-
function isWakeUpGreetingMessage(content: string): boolean {
|
|
10
|
-
return content.toLowerCase().includes("wake up, my friend");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function countBootstrapUserTurns(
|
|
14
|
-
messages: Pick<MessageRow, "role" | "content">[],
|
|
15
|
-
): number {
|
|
16
|
-
return messages.filter(
|
|
17
|
-
(message) =>
|
|
18
|
-
message.role === "user" && !isWakeUpGreetingMessage(message.content),
|
|
19
|
-
).length;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function shouldCleanupBootstrapAfterTurn(
|
|
23
|
-
messages: Pick<MessageRow, "role" | "content">[],
|
|
24
|
-
threshold = BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD,
|
|
25
|
-
): boolean {
|
|
26
|
-
return countBootstrapUserTurns(messages) >= threshold;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function cleanupBootstrapAfterTurnThreshold(
|
|
30
|
-
conversationId: string,
|
|
31
|
-
): boolean {
|
|
32
|
-
let messages: MessageRow[];
|
|
33
|
-
try {
|
|
34
|
-
messages = getMessages(conversationId);
|
|
35
|
-
} catch (err) {
|
|
36
|
-
log.warn({ err, conversationId }, "Failed to inspect bootstrap turn count");
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (!shouldCleanupBootstrapAfterTurn(messages)) return false;
|
|
41
|
-
|
|
42
|
-
return cleanupBootstrapFiles(
|
|
43
|
-
`first conversation reached ${BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD} user turns`,
|
|
44
|
-
);
|
|
45
|
-
}
|