@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,3 +1,5 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
getConfig,
|
|
3
5
|
invalidateConfigCache,
|
|
@@ -26,20 +28,24 @@ import { log as _log } from "./shared.js";
|
|
|
26
28
|
|
|
27
29
|
// -- Result type --
|
|
28
30
|
|
|
29
|
-
export
|
|
30
|
-
success: boolean
|
|
31
|
-
hasBotToken: boolean
|
|
32
|
-
hasAppToken: boolean
|
|
33
|
-
hasUserToken: boolean
|
|
34
|
-
connected: boolean
|
|
35
|
-
teamId
|
|
36
|
-
teamName
|
|
37
|
-
teamUrl
|
|
38
|
-
botUserId
|
|
39
|
-
botUsername
|
|
40
|
-
error
|
|
41
|
-
warning
|
|
42
|
-
}
|
|
31
|
+
export const SlackChannelConfigResultSchema = z.object({
|
|
32
|
+
success: z.boolean(),
|
|
33
|
+
hasBotToken: z.boolean(),
|
|
34
|
+
hasAppToken: z.boolean(),
|
|
35
|
+
hasUserToken: z.boolean(),
|
|
36
|
+
connected: z.boolean(),
|
|
37
|
+
teamId: z.string().optional(),
|
|
38
|
+
teamName: z.string().optional(),
|
|
39
|
+
teamUrl: z.string().optional(),
|
|
40
|
+
botUserId: z.string().optional(),
|
|
41
|
+
botUsername: z.string().optional(),
|
|
42
|
+
error: z.string().optional(),
|
|
43
|
+
warning: z.string().optional(),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export type SlackChannelConfigResult = z.infer<
|
|
47
|
+
typeof SlackChannelConfigResultSchema
|
|
48
|
+
>;
|
|
43
49
|
|
|
44
50
|
// -- Helpers --
|
|
45
51
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
1
3
|
import { getIsPlatform } from "../../config/env-registry.js";
|
|
2
4
|
import {
|
|
3
5
|
invalidateConfigCache,
|
|
@@ -26,7 +28,6 @@ import {
|
|
|
26
28
|
deleteCredentialMetadata,
|
|
27
29
|
upsertCredentialMetadata,
|
|
28
30
|
} from "../../tools/credentials/metadata-store.js";
|
|
29
|
-
import type { TelegramConfigResponse } from "../message-protocol.js";
|
|
30
31
|
import { log } from "./shared.js";
|
|
31
32
|
|
|
32
33
|
const TELEGRAM_BOT_TOKEN_IN_URL_PATTERN =
|
|
@@ -60,7 +61,20 @@ function summarizeTelegramError(err: unknown): string {
|
|
|
60
61
|
|
|
61
62
|
// -- Transport-agnostic result type (omits the `type` discriminant) --
|
|
62
63
|
|
|
63
|
-
export
|
|
64
|
+
export const TelegramConfigResultSchema = z.object({
|
|
65
|
+
success: z.boolean(),
|
|
66
|
+
hasBotToken: z.boolean(),
|
|
67
|
+
botId: z.string().optional(),
|
|
68
|
+
botUsername: z.string().optional(),
|
|
69
|
+
connected: z.boolean(),
|
|
70
|
+
hasWebhookSecret: z.boolean(),
|
|
71
|
+
lastError: z.string().optional(),
|
|
72
|
+
error: z.string().optional(),
|
|
73
|
+
commandsRegistered: z.array(z.string()).optional(),
|
|
74
|
+
warning: z.string().optional(),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export type TelegramConfigResult = z.infer<typeof TelegramConfigResultSchema>;
|
|
64
78
|
|
|
65
79
|
// -- Extracted business logic functions --
|
|
66
80
|
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { v4 as uuid } from "uuid";
|
|
2
2
|
|
|
3
|
+
import type {
|
|
4
|
+
ConversationContentBlock,
|
|
5
|
+
ConversationMessageAttachment,
|
|
6
|
+
ConversationMessageSurface,
|
|
7
|
+
ConversationMessageToolCall,
|
|
8
|
+
} from "../../api/responses/conversation-message.js";
|
|
9
|
+
import { ConfirmationDecisionSchema } from "../../api/responses/conversation-message.js";
|
|
3
10
|
import { getConfig } from "../../config/loader.js";
|
|
4
11
|
import type { LLMCallSite, Speed } from "../../config/schemas/llm.js";
|
|
5
12
|
import type { SecretPromptResult } from "../../permissions/secret-prompter.js";
|
|
6
|
-
import { isPlaceholderSentinelText } from "../../providers/
|
|
13
|
+
import { isPlaceholderSentinelText } from "../../providers/placeholder-sentinels.js";
|
|
7
14
|
import { broadcastMessage } from "../../runtime/assistant-event-hub.js";
|
|
8
15
|
import type { AuthContext } from "../../runtime/auth/types.js";
|
|
9
16
|
import { unwrapExternalContentForDisplay } from "../../security/untrusted-content.js";
|
|
@@ -30,74 +37,18 @@ const pendingStandaloneSecrets = new Map<
|
|
|
30
37
|
}
|
|
31
38
|
>();
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
imageData?: string;
|
|
40
|
-
/** Base64-encoded image data from tool contentBlocks (e.g. browser_screenshot, image generation). */
|
|
41
|
-
imageDataList?: string[];
|
|
42
|
-
/** Unix ms when the tool started executing. */
|
|
43
|
-
startedAt?: number;
|
|
44
|
-
/** Unix ms when the tool completed. */
|
|
45
|
-
completedAt?: number;
|
|
46
|
-
/** Confirmation decision for this tool call: "approved" | "denied" | "timed_out". */
|
|
47
|
-
confirmationDecision?: string;
|
|
48
|
-
/** Friendly label for the confirmation (e.g. "Edit File", "Run Command"). */
|
|
49
|
-
confirmationLabel?: string;
|
|
50
|
-
/** Risk level classification at invocation time ("low" | "medium" | "high" | "unknown"). */
|
|
51
|
-
riskLevel?: string;
|
|
52
|
-
/** Human-readable reason for the risk classification. */
|
|
53
|
-
riskReason?: string;
|
|
54
|
-
/** ID of the trust rule that matched this invocation (if any). */
|
|
55
|
-
matchedTrustRuleId?: string;
|
|
56
|
-
/**
|
|
57
|
-
* @deprecated Use `approvalMode` and `approvalReason` instead.
|
|
58
|
-
* Kept for backward compatibility during the migration window.
|
|
59
|
-
*/
|
|
60
|
-
autoApproved?: boolean;
|
|
61
|
-
/** How the approval decision was reached: prompted, auto, blocked, or unknown (legacy). */
|
|
62
|
-
approvalMode?: string;
|
|
63
|
-
/** Why the approval decision was reached (stable enum for client display). */
|
|
64
|
-
approvalReason?: string;
|
|
65
|
-
/** Snapshot of the auto-approve threshold at execution time. */
|
|
66
|
-
riskThreshold?: string;
|
|
67
|
-
/**
|
|
68
|
-
* Display-only regex ladder for the rule editor (narrowest → broadest).
|
|
69
|
-
* Persisted on tool_use blocks by `annotatePersistedAssistantMessage` so
|
|
70
|
-
* historical chips render the same ladder as live tool_result events.
|
|
71
|
-
*/
|
|
72
|
-
riskScopeOptions?: Array<{ pattern: string; label: string }>;
|
|
73
|
-
/** Minimatch save patterns for the rule editor (narrowest → broadest). */
|
|
74
|
-
riskAllowlistOptions?: Array<{
|
|
75
|
-
label: string;
|
|
76
|
-
description: string;
|
|
77
|
-
pattern: string;
|
|
78
|
-
}>;
|
|
79
|
-
/** Directory scope ladder for the rule editor. */
|
|
80
|
-
riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
|
|
81
|
-
}
|
|
40
|
+
/**
|
|
41
|
+
* A single tool call rendered into a history row. Alias of the canonical
|
|
42
|
+
* wire-contract type so `renderHistoryContent` (the producer) cannot drift
|
|
43
|
+
* from what the messages endpoint serializes.
|
|
44
|
+
*/
|
|
45
|
+
export type HistoryToolCall = ConversationMessageToolCall;
|
|
82
46
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
actions?: Array<{
|
|
89
|
-
id: string;
|
|
90
|
-
label: string;
|
|
91
|
-
style?: string;
|
|
92
|
-
data?: Record<string, unknown>;
|
|
93
|
-
}>;
|
|
94
|
-
display?: string;
|
|
95
|
-
persistent?: boolean;
|
|
96
|
-
completed?: boolean;
|
|
97
|
-
completionSummary?: string;
|
|
98
|
-
/** Id of the tool call that produced this surface (the `ui_show` proxy tool). Lets the client gate app previews on the tool result's arrival rather than whole-turn streaming state. */
|
|
99
|
-
toolCallId?: string;
|
|
100
|
-
}
|
|
47
|
+
/**
|
|
48
|
+
* A UI surface (widget) embedded in a history row. Alias of the canonical
|
|
49
|
+
* wire-contract type so the producer matches the serialized shape.
|
|
50
|
+
*/
|
|
51
|
+
export type HistorySurface = ConversationMessageSurface;
|
|
101
52
|
|
|
102
53
|
/**
|
|
103
54
|
* Positional reference to a file attachment captured while walking the
|
|
@@ -131,6 +82,16 @@ export interface RenderedHistoryContent {
|
|
|
131
82
|
* attachment metadata to this ordering for inline placement.
|
|
132
83
|
*/
|
|
133
84
|
attachments: HistoryAttachmentRef[];
|
|
85
|
+
/**
|
|
86
|
+
* Unified ordered content blocks built directly from the model-native
|
|
87
|
+
* content during the single walk — the wire `contentBlocks` projection.
|
|
88
|
+
* `attachment` blocks are inlined for file blocks whose DB-hydrated metadata
|
|
89
|
+
* the caller supplies via the `attachmentBlocks` argument (matched by
|
|
90
|
+
* attachment-ref order); a file block with no supplied metadata produces no
|
|
91
|
+
* block. Every other block type is always complete, so the serializer ships
|
|
92
|
+
* this array as-is with no post-processing.
|
|
93
|
+
*/
|
|
94
|
+
contentBlocks: ConversationContentBlock[];
|
|
134
95
|
}
|
|
135
96
|
|
|
136
97
|
/**
|
|
@@ -256,6 +217,44 @@ function extractFileBlockMetadata(
|
|
|
256
217
|
};
|
|
257
218
|
}
|
|
258
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Build the positional attachment reference for a `file` content block:
|
|
222
|
+
* filename/mime/size from the block's source plus the persisted
|
|
223
|
+
* `_attachmentId` when present (user-uploaded files).
|
|
224
|
+
*/
|
|
225
|
+
function fileBlockToAttachmentRef(
|
|
226
|
+
block: Record<string, unknown>,
|
|
227
|
+
meta: FileBlockMetadata,
|
|
228
|
+
): HistoryAttachmentRef {
|
|
229
|
+
const ref: HistoryAttachmentRef = {
|
|
230
|
+
filename: meta.filename,
|
|
231
|
+
mimeType: meta.mediaType,
|
|
232
|
+
sizeBytes: meta.sizeBytes,
|
|
233
|
+
};
|
|
234
|
+
if (typeof block._attachmentId === "string" && block._attachmentId) {
|
|
235
|
+
ref.attachmentId = block._attachmentId;
|
|
236
|
+
}
|
|
237
|
+
return ref;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Collect file-block attachment references in content-walk order without
|
|
242
|
+
* building the full history projection. The serializer aligns its DB-hydrated
|
|
243
|
+
* attachment rows against this ordering, then feeds the resolved metadata back
|
|
244
|
+
* into `renderHistoryContent` so it inlines `attachment` blocks during the walk.
|
|
245
|
+
*/
|
|
246
|
+
export function collectAttachmentRefs(
|
|
247
|
+
content: unknown,
|
|
248
|
+
): HistoryAttachmentRef[] {
|
|
249
|
+
if (!Array.isArray(content)) return [];
|
|
250
|
+
const refs: HistoryAttachmentRef[] = [];
|
|
251
|
+
for (const block of content) {
|
|
252
|
+
if (!isRecord(block) || block.type !== "file") continue;
|
|
253
|
+
refs.push(fileBlockToAttachmentRef(block, extractFileBlockMetadata(block)));
|
|
254
|
+
}
|
|
255
|
+
return refs;
|
|
256
|
+
}
|
|
257
|
+
|
|
259
258
|
function renderFileBlockForHistory(
|
|
260
259
|
block: Record<string, unknown>,
|
|
261
260
|
meta: FileBlockMetadata,
|
|
@@ -277,7 +276,13 @@ function renderFileBlockForHistory(
|
|
|
277
276
|
)}`;
|
|
278
277
|
}
|
|
279
278
|
|
|
280
|
-
export function renderHistoryContent(
|
|
279
|
+
export function renderHistoryContent(
|
|
280
|
+
content: unknown,
|
|
281
|
+
attachmentBlocks?: ReadonlyArray<
|
|
282
|
+
ConversationMessageAttachment | null | undefined
|
|
283
|
+
>,
|
|
284
|
+
messageId?: string,
|
|
285
|
+
): RenderedHistoryContent {
|
|
281
286
|
if (!Array.isArray(content)) {
|
|
282
287
|
let text: string;
|
|
283
288
|
if (content == null) {
|
|
@@ -296,6 +301,7 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
296
301
|
surfaces: [],
|
|
297
302
|
thinkingSegments: [],
|
|
298
303
|
attachments: [],
|
|
304
|
+
contentBlocks: text ? [{ type: "text", text }] : [],
|
|
299
305
|
};
|
|
300
306
|
}
|
|
301
307
|
|
|
@@ -316,6 +322,13 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
316
322
|
let currentSegmentParts: string[] = [];
|
|
317
323
|
let hasOpenSegment = false;
|
|
318
324
|
|
|
325
|
+
// Unified content blocks built in lockstep with the positional arrays as we
|
|
326
|
+
// walk the model-native content. `attachment` blocks are inlined here when
|
|
327
|
+
// the caller supplied DB-hydrated metadata in `attachmentBlocks`, matched by
|
|
328
|
+
// attachment-ref order; otherwise the file block contributes no block.
|
|
329
|
+
const contentBlocks: ConversationContentBlock[] = [];
|
|
330
|
+
let currentTextBlock: { type: "text"; text: string } | null = null;
|
|
331
|
+
|
|
319
332
|
function joinWithSpacing(parts: string[]): string {
|
|
320
333
|
let result = parts[0] ?? "";
|
|
321
334
|
for (let i = 1; i < parts.length; i++) {
|
|
@@ -341,18 +354,42 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
341
354
|
|
|
342
355
|
function finalizeSegment(): void {
|
|
343
356
|
if (hasOpenSegment) {
|
|
344
|
-
|
|
345
|
-
|
|
357
|
+
const joined = joinWithSpacing(currentSegmentParts);
|
|
358
|
+
textSegments[textSegments.length - 1] = joined;
|
|
359
|
+
if (currentTextBlock) {
|
|
360
|
+
currentTextBlock.text = joined;
|
|
361
|
+
currentTextBlock = null;
|
|
362
|
+
}
|
|
346
363
|
currentSegmentParts = [];
|
|
347
364
|
hasOpenSegment = false;
|
|
348
365
|
}
|
|
349
366
|
}
|
|
350
367
|
|
|
351
|
-
|
|
368
|
+
// Flush the open text segment into its tracked block and stop tracking it,
|
|
369
|
+
// without closing the segment. Used before folding the synthetic attachment
|
|
370
|
+
// description into the trailing segment: it stays in the legacy
|
|
371
|
+
// `textSegments`/`text` body but must not pollute the clean contentBlocks,
|
|
372
|
+
// since `attachment` blocks already carry that metadata.
|
|
373
|
+
function detachTextBlock(): void {
|
|
374
|
+
if (currentTextBlock) {
|
|
375
|
+
currentTextBlock.text = joinWithSpacing(currentSegmentParts);
|
|
376
|
+
currentTextBlock = null;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// `trackBlock` mirrors the segment into `contentBlocks`. The trailing
|
|
381
|
+
// attachment-description segment (legacy `message.text` for clients without
|
|
382
|
+
// attachment UI) sets it false so it isn't duplicated as a text block —
|
|
383
|
+
// attachments surface as `attachment` blocks instead.
|
|
384
|
+
function ensureSegment(trackBlock = true): void {
|
|
352
385
|
if (!hasOpenSegment) {
|
|
353
386
|
textSegments.push("");
|
|
354
387
|
contentOrder.push(`text:${textSegments.length - 1}`);
|
|
355
388
|
hasOpenSegment = true;
|
|
389
|
+
if (trackBlock) {
|
|
390
|
+
currentTextBlock = { type: "text", text: "" };
|
|
391
|
+
contentBlocks.push(currentTextBlock);
|
|
392
|
+
}
|
|
356
393
|
}
|
|
357
394
|
}
|
|
358
395
|
|
|
@@ -383,6 +420,7 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
383
420
|
};
|
|
384
421
|
surfaces.push(surface);
|
|
385
422
|
contentOrder.push(`surface:${surfaces.length - 1}`);
|
|
423
|
+
contentBlocks.push({ type: "surface", surface });
|
|
386
424
|
continue;
|
|
387
425
|
}
|
|
388
426
|
|
|
@@ -390,6 +428,7 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
390
428
|
finalizeSegment();
|
|
391
429
|
thinkingSegments.push(block.thinking);
|
|
392
430
|
contentOrder.push(`thinking:${thinkingSegments.length - 1}`);
|
|
431
|
+
contentBlocks.push({ type: "thinking", thinking: block.thinking });
|
|
393
432
|
continue;
|
|
394
433
|
}
|
|
395
434
|
|
|
@@ -416,16 +455,13 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
416
455
|
const meta = extractFileBlockMetadata(block);
|
|
417
456
|
attachmentParts.push(renderFileBlockForHistory(block, meta));
|
|
418
457
|
finalizeSegment();
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
ref.attachmentId = block._attachmentId;
|
|
458
|
+
attachments.push(fileBlockToAttachmentRef(block, meta));
|
|
459
|
+
const refIndex = attachments.length - 1;
|
|
460
|
+
contentOrder.push(`attachment:${refIndex}`);
|
|
461
|
+
const hydrated = attachmentBlocks?.[refIndex];
|
|
462
|
+
if (hydrated) {
|
|
463
|
+
contentBlocks.push({ type: "attachment", attachment: hydrated });
|
|
426
464
|
}
|
|
427
|
-
attachments.push(ref);
|
|
428
|
-
contentOrder.push(`attachment:${attachments.length - 1}`);
|
|
429
465
|
continue;
|
|
430
466
|
}
|
|
431
467
|
if (block.type === "image") {
|
|
@@ -442,13 +478,18 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
442
478
|
: {};
|
|
443
479
|
const id = typeof block.id === "string" ? block.id : "";
|
|
444
480
|
const entry: HistoryToolCall = { name, input };
|
|
481
|
+
if (id) entry.id = id;
|
|
445
482
|
// Extract persisted timing/confirmation metadata
|
|
446
483
|
if (typeof block._startedAt === "number")
|
|
447
484
|
entry.startedAt = block._startedAt;
|
|
448
485
|
if (typeof block._completedAt === "number")
|
|
449
486
|
entry.completedAt = block._completedAt;
|
|
450
|
-
|
|
451
|
-
|
|
487
|
+
const confirmationDecision = ConfirmationDecisionSchema.safeParse(
|
|
488
|
+
block._confirmationDecision,
|
|
489
|
+
);
|
|
490
|
+
if (confirmationDecision.success) {
|
|
491
|
+
entry.confirmationDecision = confirmationDecision.data;
|
|
492
|
+
}
|
|
452
493
|
if (typeof block._confirmationLabel === "string")
|
|
453
494
|
entry.confirmationLabel = block._confirmationLabel;
|
|
454
495
|
if (typeof block._riskLevel === "string")
|
|
@@ -477,9 +518,18 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
477
518
|
if (Array.isArray(block._riskDirectoryScopeOptions))
|
|
478
519
|
entry.riskDirectoryScopeOptions =
|
|
479
520
|
block._riskDirectoryScopeOptions as HistoryToolCall["riskDirectoryScopeOptions"];
|
|
521
|
+
// Read back tool activity (web_search / web_fetch) persisted by
|
|
522
|
+
// `annotatePersistedAssistantMessage` so the activity card survives a
|
|
523
|
+
// history reopen instead of degrading to the plain result text.
|
|
524
|
+
if (isRecord(block._activityMetadata))
|
|
525
|
+
entry.activityMetadata =
|
|
526
|
+
block._activityMetadata as HistoryToolCall["activityMetadata"];
|
|
480
527
|
toolCalls.push(entry);
|
|
481
528
|
if (id) pendingToolUses.set(id, entry);
|
|
482
529
|
contentOrder.push(`tool:${toolCalls.length - 1}`);
|
|
530
|
+
// Same `entry` reference the block carries: a later tool_result pairs its
|
|
531
|
+
// output onto `entry`, so the content block reflects it automatically.
|
|
532
|
+
contentBlocks.push({ type: "tool_use", toolCall: entry });
|
|
483
533
|
if (!seenToolUse) {
|
|
484
534
|
seenToolUse = true;
|
|
485
535
|
if (!seenText) toolCallsBeforeText = true;
|
|
@@ -494,9 +544,16 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
494
544
|
: {};
|
|
495
545
|
const id = typeof block.id === "string" ? block.id : "";
|
|
496
546
|
const entry: HistoryToolCall = { name, input };
|
|
547
|
+
if (id) entry.id = id;
|
|
548
|
+
// Native server tools (Anthropic web_search) persist their activity on
|
|
549
|
+
// the server_tool_use block, so read it back here too.
|
|
550
|
+
if (isRecord(block._activityMetadata))
|
|
551
|
+
entry.activityMetadata =
|
|
552
|
+
block._activityMetadata as HistoryToolCall["activityMetadata"];
|
|
497
553
|
toolCalls.push(entry);
|
|
498
554
|
if (id) pendingToolUses.set(id, entry);
|
|
499
555
|
contentOrder.push(`tool:${toolCalls.length - 1}`);
|
|
556
|
+
contentBlocks.push({ type: "tool_use", toolCall: entry });
|
|
500
557
|
if (!seenToolUse) {
|
|
501
558
|
seenToolUse = true;
|
|
502
559
|
if (!seenText) toolCallsBeforeText = true;
|
|
@@ -586,14 +643,28 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
586
643
|
// The macOS client handles this by selecting the *first* non-empty text
|
|
587
644
|
// segment in interleaved content, so trailing attachment segments are safe.
|
|
588
645
|
if (attachmentParts.length > 0) {
|
|
646
|
+
detachTextBlock();
|
|
589
647
|
const attachmentText = attachmentParts.join("\n");
|
|
590
648
|
const prefix = textParts.length > 0 ? "\n" : "";
|
|
591
|
-
ensureSegment();
|
|
649
|
+
ensureSegment(false);
|
|
592
650
|
currentSegmentParts.push(prefix + attachmentText);
|
|
593
651
|
}
|
|
594
652
|
|
|
595
653
|
finalizeSegment();
|
|
596
654
|
|
|
655
|
+
// Default any tool call the provider left without an `id` to the same
|
|
656
|
+
// positional id the web client historically synthesized, so every wire tool
|
|
657
|
+
// call is self-identifying and snapshot/stream ids line up. `idx` indexes the
|
|
658
|
+
// final `toolCalls` array (the client keys off the same positions); the
|
|
659
|
+
// shared `entry` references mean `contentBlocks` reflect this for free.
|
|
660
|
+
if (messageId !== undefined) {
|
|
661
|
+
toolCalls.forEach((toolCall, idx) => {
|
|
662
|
+
if (toolCall.id === undefined) {
|
|
663
|
+
toolCall.id = `tool-history-${messageId}-${idx}`;
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
597
668
|
const text = joinWithSpacing(textParts);
|
|
598
669
|
let rendered: string;
|
|
599
670
|
if (attachmentParts.length === 0) {
|
|
@@ -613,6 +684,7 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
613
684
|
surfaces,
|
|
614
685
|
thinkingSegments,
|
|
615
686
|
attachments,
|
|
687
|
+
contentBlocks,
|
|
616
688
|
};
|
|
617
689
|
}
|
|
618
690
|
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
isTextMimeType as isTextMime,
|
|
32
32
|
MAX_INLINE_TEXT_SIZE,
|
|
33
33
|
} from "../../runtime/routes/workspace-utils.js";
|
|
34
|
-
import { getCatalog } from "../../skills/catalog-cache.js";
|
|
34
|
+
import { getCachedCatalogSync, getCatalog } from "../../skills/catalog-cache.js";
|
|
35
35
|
import type { SkillFileEntry } from "../../skills/catalog-files.js";
|
|
36
36
|
import {
|
|
37
37
|
catalogSkillToSlim,
|
|
@@ -48,7 +48,6 @@ import {
|
|
|
48
48
|
installSkillLocally,
|
|
49
49
|
} from "../../skills/catalog-install.js";
|
|
50
50
|
import { filterByQuery } from "../../skills/catalog-search.js";
|
|
51
|
-
import { inferCategory } from "../../skills/category-inference.js";
|
|
52
51
|
import type { ClawhubInspectResult } from "../../skills/clawhub.js";
|
|
53
52
|
import {
|
|
54
53
|
clawhubCheckUpdates,
|
|
@@ -285,6 +284,25 @@ function postInstallSkill(skillId: string): void {
|
|
|
285
284
|
refreshSkillCapabilityMemories(getConfig());
|
|
286
285
|
}
|
|
287
286
|
|
|
287
|
+
// ─── Catalog category lookup ────────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
let _catalogCategoryMap: Map<string, string> | null = null;
|
|
290
|
+
let _catalogCategoryRef: readonly CatalogSkill[] | null = null;
|
|
291
|
+
|
|
292
|
+
function getCatalogCategoryMap(): Map<string, string> {
|
|
293
|
+
const catalog = getCachedCatalogSync();
|
|
294
|
+
if (_catalogCategoryMap && _catalogCategoryRef === catalog) {
|
|
295
|
+
return _catalogCategoryMap;
|
|
296
|
+
}
|
|
297
|
+
_catalogCategoryMap = new Map();
|
|
298
|
+
for (const s of catalog) {
|
|
299
|
+
const cat = s.metadata?.vellum?.category;
|
|
300
|
+
if (cat) _catalogCategoryMap.set(s.id, cat);
|
|
301
|
+
}
|
|
302
|
+
_catalogCategoryRef = catalog;
|
|
303
|
+
return _catalogCategoryMap;
|
|
304
|
+
}
|
|
305
|
+
|
|
288
306
|
// ─── Kind / origin / status derivation ───────────────────────────────────────
|
|
289
307
|
|
|
290
308
|
/** Map the old `source` field to the new `kind` axis. */
|
|
@@ -328,11 +346,12 @@ function toSlimSkillResponse(
|
|
|
328
346
|
const origin = deriveOrigin(kind, summary.directoryPath, installMeta);
|
|
329
347
|
const status: SlimSkillResponse["status"] = state;
|
|
330
348
|
|
|
331
|
-
const category =
|
|
349
|
+
const category = getCatalogCategoryMap().get(summary.id) ?? "system";
|
|
332
350
|
const base = {
|
|
333
351
|
id: summary.id,
|
|
334
352
|
name: summary.displayName,
|
|
335
353
|
description: summary.description,
|
|
354
|
+
icon: summary.icon,
|
|
336
355
|
emoji: summary.emoji,
|
|
337
356
|
kind,
|
|
338
357
|
status,
|
|
@@ -395,14 +414,20 @@ export function listSkills(): SlimSkillResponse[] {
|
|
|
395
414
|
* Installed skills take precedence when deduplicating by ID.
|
|
396
415
|
*/
|
|
397
416
|
async function listSkillsWithCatalog(): Promise<SlimSkillResponse[]> {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
417
|
+
// Warm the catalog cache before converting installed skills so
|
|
418
|
+
// getCatalogCategoryMap() in toSlimSkillResponse() sees real categories
|
|
419
|
+
// instead of falling back to "system" on a cold cache.
|
|
401
420
|
let catalogSkills: CatalogSkill[];
|
|
402
421
|
try {
|
|
403
422
|
catalogSkills = await getCatalog();
|
|
404
423
|
} catch {
|
|
405
|
-
|
|
424
|
+
catalogSkills = [];
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const installed = listSkills();
|
|
428
|
+
const installedIds = new Set(installed.map((s) => s.id));
|
|
429
|
+
|
|
430
|
+
if (catalogSkills.length === 0) {
|
|
406
431
|
return installed;
|
|
407
432
|
}
|
|
408
433
|
|
|
@@ -605,6 +630,7 @@ export async function getSkill(
|
|
|
605
630
|
id: slim.id,
|
|
606
631
|
name: slim.name,
|
|
607
632
|
description: slim.description,
|
|
633
|
+
icon: slim.icon,
|
|
608
634
|
emoji: slim.emoji,
|
|
609
635
|
kind: slim.kind,
|
|
610
636
|
origin: slim.origin,
|
|
@@ -645,6 +671,7 @@ export async function getSkill(
|
|
|
645
671
|
id: slim.id,
|
|
646
672
|
name: slim.name,
|
|
647
673
|
description: slim.description,
|
|
674
|
+
icon: slim.icon,
|
|
648
675
|
emoji: slim.emoji,
|
|
649
676
|
kind: slim.kind,
|
|
650
677
|
origin: slim.origin,
|
|
@@ -676,6 +703,7 @@ export async function getSkill(
|
|
|
676
703
|
id: slim.id,
|
|
677
704
|
name: slim.name,
|
|
678
705
|
description: slim.description,
|
|
706
|
+
icon: slim.icon,
|
|
679
707
|
emoji: slim.emoji,
|
|
680
708
|
kind: slim.kind,
|
|
681
709
|
origin: slim.origin,
|
|
@@ -1365,11 +1393,12 @@ export async function searchSkills(
|
|
|
1365
1393
|
id: s.id,
|
|
1366
1394
|
name: s.displayName,
|
|
1367
1395
|
description: s.description,
|
|
1396
|
+
icon: s.icon,
|
|
1368
1397
|
emoji: s.emoji,
|
|
1369
1398
|
kind: "catalog" as const,
|
|
1370
1399
|
origin: "vellum" as const,
|
|
1371
1400
|
status: "available" as const,
|
|
1372
|
-
category:
|
|
1401
|
+
category: getCatalogCategoryMap().get(s.id) ?? "system",
|
|
1373
1402
|
};
|
|
1374
1403
|
});
|
|
1375
1404
|
|
|
@@ -1388,7 +1417,7 @@ export async function searchSkills(
|
|
|
1388
1417
|
kind: "catalog" as const,
|
|
1389
1418
|
origin: "clawhub" as const,
|
|
1390
1419
|
status: "available" as const,
|
|
1391
|
-
category:
|
|
1420
|
+
category: "integrations",
|
|
1392
1421
|
slug: s.slug,
|
|
1393
1422
|
author: s.author,
|
|
1394
1423
|
stars: s.stars,
|
|
@@ -1415,7 +1444,7 @@ export async function searchSkills(
|
|
|
1415
1444
|
kind: "catalog" as const,
|
|
1416
1445
|
origin: "skillssh" as const,
|
|
1417
1446
|
status: "available" as const,
|
|
1418
|
-
category:
|
|
1447
|
+
category: "integrations",
|
|
1419
1448
|
slug: r.id,
|
|
1420
1449
|
sourceRepo: r.source,
|
|
1421
1450
|
installs: r.installs,
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -117,6 +117,7 @@ import {
|
|
|
117
117
|
maybeRebuildMemoryV2Concepts,
|
|
118
118
|
rebuildBm25CorpusStatsAndReseedSkills,
|
|
119
119
|
} from "./memory-v2-startup.js";
|
|
120
|
+
import { startOrphanReaper, stopOrphanReaper } from "./orphan-reaper.js";
|
|
120
121
|
import { processMessage } from "./process-message.js";
|
|
121
122
|
import { runProfilerSweep } from "./profiler-run-store.js";
|
|
122
123
|
import {
|
|
@@ -728,6 +729,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
728
729
|
await server.start();
|
|
729
730
|
log.info("Daemon startup: DaemonServer started");
|
|
730
731
|
startDiskPressureGuardForLifecycle();
|
|
732
|
+
startOrphanReaper();
|
|
731
733
|
|
|
732
734
|
// Kick off the update bulletin background job AFTER `server.start()`
|
|
733
735
|
// resolves. The conversation store must be initialized before wake
|
|
@@ -1324,6 +1326,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
1324
1326
|
cleanupPidFile: () => {
|
|
1325
1327
|
stopGatewayFlagListener();
|
|
1326
1328
|
stopDiskPressureGuardForLifecycle();
|
|
1329
|
+
stopOrphanReaper();
|
|
1327
1330
|
cleanupPidFile();
|
|
1328
1331
|
},
|
|
1329
1332
|
});
|
|
@@ -1338,6 +1341,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
1338
1341
|
} catch (err) {
|
|
1339
1342
|
log.error({ err }, "Daemon startup failed — cleaning up");
|
|
1340
1343
|
stopDiskPressureGuardForLifecycle();
|
|
1344
|
+
stopOrphanReaper();
|
|
1341
1345
|
cleanupPidFileIfOwner(process.pid);
|
|
1342
1346
|
throw err;
|
|
1343
1347
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
// App management,
|
|
2
|
-
|
|
3
|
-
import type { GalleryManifest } from "../../gallery/gallery-manifest.js";
|
|
1
|
+
// App management, publishing, and sharing types.
|
|
4
2
|
|
|
5
3
|
// === Client → Server ===
|
|
6
4
|
|
|
@@ -81,15 +79,6 @@ export interface GetSigningIdentityResponse {
|
|
|
81
79
|
error?: string;
|
|
82
80
|
}
|
|
83
81
|
|
|
84
|
-
export interface GalleryListRequest {
|
|
85
|
-
type: "gallery_list";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export interface GalleryInstallRequest {
|
|
89
|
-
type: "gallery_install";
|
|
90
|
-
galleryAppId: string;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
82
|
export interface AppHistoryRequest {
|
|
94
83
|
type: "app_history_request";
|
|
95
84
|
appId: string;
|
|
@@ -271,19 +260,6 @@ export interface ShareAppCloudResponse {
|
|
|
271
260
|
error?: string;
|
|
272
261
|
}
|
|
273
262
|
|
|
274
|
-
export interface GalleryListResponse {
|
|
275
|
-
type: "gallery_list_response";
|
|
276
|
-
gallery: GalleryManifest;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export interface GalleryInstallResponse {
|
|
280
|
-
type: "gallery_install_response";
|
|
281
|
-
success: boolean;
|
|
282
|
-
appId?: string;
|
|
283
|
-
name?: string;
|
|
284
|
-
error?: string;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
263
|
export interface AppHistoryResponse {
|
|
288
264
|
type: "app_history_response";
|
|
289
265
|
appId: string;
|
|
@@ -347,8 +323,6 @@ export type _AppsClientMessages =
|
|
|
347
323
|
| OpenBundleRequest
|
|
348
324
|
| SignBundlePayloadResponse
|
|
349
325
|
| GetSigningIdentityResponse
|
|
350
|
-
| GalleryListRequest
|
|
351
|
-
| GalleryInstallRequest
|
|
352
326
|
| AppHistoryRequest
|
|
353
327
|
| AppDiffRequest
|
|
354
328
|
| AppFileAtVersionRequest
|
|
@@ -371,8 +345,6 @@ export type _AppsServerMessages =
|
|
|
371
345
|
| SignBundlePayloadRequest
|
|
372
346
|
| GetSigningIdentityRequest
|
|
373
347
|
| ShareAppCloudResponse
|
|
374
|
-
| GalleryListResponse
|
|
375
|
-
| GalleryInstallResponse
|
|
376
348
|
| AppHistoryResponse
|
|
377
349
|
| AppDiffResponse
|
|
378
350
|
| AppFileAtVersionResponse
|