@vellumai/assistant 0.8.7 → 0.8.8-dev.202606052332.17fc8ea
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/bun.lock +2 -2
- 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/examples/plugins/echo/README.md +61 -66
- package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
- package/examples/plugins/echo/hooks/stop.ts +16 -0
- package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
- package/examples/plugins/echo/package.json +1 -2
- package/examples/plugins/echo/src/emit.ts +19 -0
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
- package/openapi.yaml +3378 -335
- package/package.json +2 -2
- package/scripts/generate-openapi.ts +68 -41
- package/src/__tests__/agent-loop-exit-reason.test.ts +35 -93
- 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__/app-control-flow.test.ts +1 -1
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +4 -1
- 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__/channel-approval-routes.test.ts +1 -1
- package/src/__tests__/channel-approvals.test.ts +1 -1
- package/src/__tests__/clawhub-files.test.ts +1 -1
- package/src/__tests__/compaction-circuit.test.ts +258 -0
- package/src/__tests__/compaction-direct.test.ts +132 -0
- 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 -5
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -7
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +316 -1143
- package/src/__tests__/conversation-agent-loop.test.ts +638 -1655
- package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
- package/src/__tests__/conversation-clean-command.test.ts +5 -2
- 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 +30 -10
- 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 +310 -300
- package/src/__tests__/conversation-runtime-workspace.test.ts +105 -45
- package/src/__tests__/conversation-slash-commands.test.ts +8 -42
- package/src/__tests__/conversation-slash-queue.test.ts +6 -1
- package/src/__tests__/conversation-starter-routes.test.ts +14 -6
- 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-cache-state.test.ts +17 -16
- package/src/__tests__/conversation-workspace-injection.test.ts +67 -2
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +7 -6
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
- package/src/__tests__/cross-provider-web-search.test.ts +214 -1
- package/src/__tests__/db-acp-history.test.ts +101 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
- package/src/__tests__/dm-persistence.test.ts +5 -1
- package/src/__tests__/dynamic-page-surface.test.ts +31 -0
- package/src/__tests__/empty-response-hook.test.ts +304 -0
- package/src/__tests__/feature-flag-test-helpers.ts +2 -2
- package/src/__tests__/file-write-tool.test.ts +63 -0
- package/src/__tests__/gateway-only-guard.test.ts +12 -2
- package/src/__tests__/gemini-image-service.test.ts +13 -0
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -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__/host-app-control-routes.test.ts +1 -1
- package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
- 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 +3 -9
- package/src/__tests__/injector-chain.test.ts +139 -275
- package/src/__tests__/injector-disk-pressure.test.ts +75 -41
- package/src/__tests__/injector-document-comments.test.ts +3 -3
- 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-hidden-metadata.test.ts +38 -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__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -284
- package/src/__tests__/persist-unsendable-image.test.ts +215 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
- package/src/__tests__/pkb-autoinject.test.ts +2 -5
- package/src/__tests__/plugin-api-shim.test.ts +3 -6
- package/src/__tests__/plugin-bootstrap.test.ts +14 -40
- package/src/__tests__/plugin-registry.test.ts +3 -76
- package/src/__tests__/plugin-types.test.ts +0 -193
- package/src/__tests__/process-message-display-content.test.ts +6 -2
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- 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__/send-endpoint-busy.test.ts +4 -1
- package/src/__tests__/server-history-render.test.ts +314 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +33 -0
- package/src/__tests__/skillssh-files.test.ts +1 -1
- package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
- package/src/__tests__/subagent-manager-notify.test.ts +1 -3
- package/src/__tests__/subagent-notify-parent.test.ts +1 -3
- package/src/__tests__/subagent-spawn-tool-fork.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 +54 -286
- package/src/__tests__/voice-session-bridge.test.ts +6 -3
- package/src/__tests__/web-search-backend-failure.test.ts +166 -0
- package/src/acp/__tests__/agent-process.test.ts +161 -0
- package/src/acp/__tests__/client-handler.test.ts +40 -0
- package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
- package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +137 -0
- package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
- package/src/acp/__tests__/session-manager-resume.test.ts +736 -0
- package/src/acp/agent-process.ts +61 -1
- package/src/acp/auto-install.test.ts +196 -0
- package/src/acp/auto-install.ts +177 -0
- package/src/acp/client-handler.ts +31 -0
- package/src/acp/feature-gate.test.ts +48 -0
- package/src/acp/feature-gate.ts +34 -0
- package/src/acp/prepare-agent-env.ts +83 -29
- package/src/acp/resolve-agent.test.ts +320 -7
- package/src/acp/resolve-agent.ts +182 -18
- package/src/acp/resume-hint.ts +25 -0
- package/src/acp/session-manager.ts +495 -73
- package/src/acp/types.ts +8 -0
- package/src/agent/compaction-circuit.ts +60 -102
- package/src/agent/loop.ts +362 -485
- 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 +374 -0
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/avatar/__tests__/avatar-store.test.ts +34 -29
- package/src/background-wake/next-wake.ts +1 -0
- package/src/cli/commands/__tests__/notifications.test.ts +58 -14
- package/src/cli/commands/notifications.ts +112 -60
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/acp-defaults.test.ts +10 -0
- package/src/config/acp-defaults.ts +6 -0
- package/src/config/assistant-feature-flags.ts +22 -11
- package/src/config/bundled-skills/acp/SKILL.md +83 -31
- package/src/config/bundled-skills/acp/TOOLS.json +4 -4
- package/src/config/bundled-skills/app-builder/SKILL.md +224 -398
- package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
- package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
- 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/app-builder/tools/app-list.ts +62 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
- package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +0 -7
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/feature-flag-cache.ts +3 -3
- package/src/config/feature-flag-registry.json +48 -7
- 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/heartbeat.ts +9 -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 +128 -0
- package/src/context/token-estimator.ts +23 -0
- package/src/context/tool-result-truncation.ts +0 -23
- package/src/context/window-manager.ts +5 -7
- 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 +594 -153
- package/src/daemon/conversation-agent-loop.ts +301 -997
- 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-registry.ts +159 -0
- package/src/daemon/conversation-runtime-assembly.ts +218 -398
- package/src/daemon/conversation-slash.ts +6 -25
- package/src/daemon/conversation-store.ts +9 -90
- package/src/daemon/conversation-surfaces.ts +222 -4
- package/src/daemon/conversation-tool-setup.ts +2 -29
- package/src/daemon/conversation-workspace.ts +17 -0
- package/src/daemon/conversation.ts +32 -20
- package/src/daemon/external-plugins-bootstrap.ts +17 -18
- 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/conversations.ts +3 -1
- package/src/daemon/handlers/shared.ts +156 -84
- package/src/daemon/handlers/skills.ts +42 -10
- package/src/daemon/lifecycle.ts +25 -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/overflow-reduction-loop.ts +230 -0
- package/src/daemon/persist-unsendable-image.ts +117 -0
- package/src/daemon/process-message.ts +1 -3
- package/src/daemon/server.ts +2 -0
- 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/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
- package/src/heartbeat/heartbeat-run-store.ts +23 -1
- package/src/heartbeat/heartbeat-service.ts +26 -0
- package/src/home/home-greeting-cache.ts +24 -1
- package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
- package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
- package/src/ipc/gateway-client.test.ts +2 -2
- package/src/ipc/gateway-client.ts +3 -3
- package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
- package/src/ipc/skill-routes/memory.ts +4 -2
- 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-starter-checkpoints.ts +1 -0
- package/src/memory/conversation-title-service.ts +65 -41
- package/src/memory/db-init.ts +6 -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/job-handlers/conversation-starters.ts +13 -2
- package/src/memory/jobs-store.ts +33 -0
- package/src/memory/jobs-worker.ts +32 -5
- 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/272-acp-session-history-cwd.ts +36 -0
- package/src/memory/migrations/index.ts +3 -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/acp.ts +4 -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 +4 -4
- package/src/memory/v2/consolidation-job.ts +14 -5
- 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 +7 -5
- package/src/plugin-api/types.ts +151 -1
- package/src/plugins/defaults/compaction/compact.ts +59 -0
- package/src/plugins/defaults/compaction/package.json +1 -1
- package/src/plugins/defaults/compaction/register.ts +8 -19
- 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 +2 -18
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -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/{injectors/register.ts → memory-retrieval/injectors.ts} +288 -81
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/health.test.ts +16 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +48 -12
- package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +104 -32
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +96 -30
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +34 -16
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/health.ts +0 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
- package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +8 -8
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +26 -14
- package/src/plugins/defaults/{llm-call → memory-v3-shadow}/package.json +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +3 -3
- package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +51 -45
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +61 -46
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +69 -99
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +8 -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/external-api.ts +2 -2
- package/src/plugins/pipeline.ts +6 -305
- package/src/plugins/registry.ts +10 -55
- package/src/plugins/types.ts +62 -797
- package/src/plugins/user-loader.ts +30 -127
- package/src/proactive-artifact/aux-message-injector.ts +4 -4
- package/src/proactive-artifact/job.test.ts +8 -13
- package/src/prompts/__tests__/system-prompt.test.ts +42 -0
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -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 +10 -6
- package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
- package/src/runtime/agent-wake.ts +2 -5
- package/src/runtime/assistant-event-hub.ts +37 -7
- package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
- package/src/runtime/channel-approvals.ts +1 -1
- package/src/runtime/http-router.ts +16 -21
- package/src/runtime/http-types.ts +16 -70
- package/src/runtime/interactive-ui.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +283 -55
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- 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__/surface-action-routes.test.ts +5 -4
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/acp-routes.test.ts +89 -25
- package/src/runtime/routes/acp-routes.ts +81 -29
- package/src/runtime/routes/app-management-routes.ts +6 -117
- package/src/runtime/routes/app-routes.ts +13 -15
- package/src/runtime/routes/approval-routes.ts +1 -1
- package/src/runtime/routes/attachment-routes.ts +26 -15
- package/src/runtime/routes/avatar-routes.ts +26 -0
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/browser-tabs-routes.ts +6 -10
- package/src/runtime/routes/btw-routes.ts +29 -23
- package/src/runtime/routes/consolidation-routes.ts +120 -20
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +1 -1
- package/src/runtime/routes/conversation-query-routes.ts +3 -1
- package/src/runtime/routes/conversation-routes.ts +372 -185
- package/src/runtime/routes/conversation-starter-routes.ts +13 -7
- package/src/runtime/routes/conversations-import-routes.ts +24 -7
- 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/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-cu-routes.ts +1 -1
- package/src/runtime/routes/identity-intro-cache.ts +11 -34
- package/src/runtime/routes/identity-routes.ts +224 -18
- package/src/runtime/routes/image-generation-routes.ts +40 -2
- package/src/runtime/routes/inbound-message-handler.ts +1 -1
- 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 +66 -34
- 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/playground/helpers.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/surface-conversation-resolver.ts +4 -3
- 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/work-items-routes.ts +2 -4
- 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/runtime/services/conversation-serializer.ts +1 -1
- 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/signals/cancel.ts +2 -4
- 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/subagent/manager.ts +17 -5
- 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/acp/context.ts +20 -0
- package/src/tools/acp/list-agents.test.ts +7 -1
- package/src/tools/acp/spawn.test.ts +158 -55
- package/src/tools/acp/spawn.ts +47 -72
- package/src/tools/acp/steer.test.ts +105 -8
- package/src/tools/acp/steer.ts +48 -17
- package/src/tools/apps/executors.ts +13 -8
- package/src/tools/executor.ts +1 -53
- package/src/tools/filesystem/write.ts +34 -0
- 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/subagent/spawn.ts +2 -4
- package/src/tools/terminal/safe-env.ts +10 -1
- package/src/tools/ui-surface/definitions.ts +34 -5
- 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/051-seed-conversation-summarization-callsite.ts +4 -5
- 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 +117 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/docs/plugins.md +0 -836
- package/examples/plugins/echo/register.ts +0 -184
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
- package/src/__tests__/compaction-pipeline.test.ts +0 -210
- package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
- 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__/pipeline-runner.test.ts +0 -564
- 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/memory/v3/provider-blocks.ts +0 -16
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
- package/src/plugins/defaults/circuit-breaker/package.json +0 -15
- package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
- package/src/plugins/defaults/compaction/terminal.ts +0 -73
- 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/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/overflow-reduce/middlewares/overflowReduce.ts +0 -126
- package/src/plugins/defaults/overflow-reduce/package.json +0 -15
- package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
- package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
- package/src/plugins/defaults/persistence/package.json +0 -15
- package/src/plugins/defaults/persistence/register.ts +0 -38
- package/src/plugins/defaults/persistence/terminal.ts +0 -83
- package/src/plugins/defaults/title-generate/terminal.ts +0 -31
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
- package/src/plugins/defaults/token-estimate/package.json +0 -15
- package/src/plugins/defaults/token-estimate/register.ts +0 -34
- package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
- package/src/plugins/defaults/tool-error/terminal.ts +0 -47
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
- package/src/plugins/defaults/tool-execute/package.json +0 -15
- package/src/plugins/defaults/tool-execute/register.ts +0 -49
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
- package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
- package/src/skills/category-inference.ts +0 -111
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/needle.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/core.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/needle.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +0 -0
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
getPlatformUserId,
|
|
16
16
|
} from "../config/env.js";
|
|
17
17
|
import { getConfig } from "../config/loader.js";
|
|
18
|
+
import { queryUnreportedAuthFallbackEvents } from "../memory/auth-fallback-events-store.js";
|
|
18
19
|
import {
|
|
19
20
|
getMemoryCheckpoint,
|
|
20
21
|
setMemoryCheckpoint,
|
|
@@ -47,6 +48,10 @@ const CHECKPOINT_KEY_ONBOARDING_WATERMARK =
|
|
|
47
48
|
"telemetry:onboarding:last_reported_at";
|
|
48
49
|
const CHECKPOINT_KEY_ONBOARDING_WATERMARK_ID =
|
|
49
50
|
"telemetry:onboarding:last_reported_id";
|
|
51
|
+
const CHECKPOINT_KEY_AUTH_FALLBACK_WATERMARK =
|
|
52
|
+
"telemetry:auth_fallback:last_reported_at";
|
|
53
|
+
const CHECKPOINT_KEY_AUTH_FALLBACK_WATERMARK_ID =
|
|
54
|
+
"telemetry:auth_fallback:last_reported_id";
|
|
50
55
|
const REPORT_INTERVAL_MS = 5 * 60 * 1000;
|
|
51
56
|
const INITIAL_FLUSH_DELAY_MS = 30_000; // Delay first flush to let CES handshake complete
|
|
52
57
|
const BATCH_SIZE = 500;
|
|
@@ -139,6 +144,7 @@ export class UsageTelemetryReporter {
|
|
|
139
144
|
setMemoryCheckpoint(CHECKPOINT_KEY_TURN_WATERMARK, now);
|
|
140
145
|
setMemoryCheckpoint(CHECKPOINT_KEY_LIFECYCLE_WATERMARK, now);
|
|
141
146
|
setMemoryCheckpoint(CHECKPOINT_KEY_ONBOARDING_WATERMARK, now);
|
|
147
|
+
setMemoryCheckpoint(CHECKPOINT_KEY_AUTH_FALLBACK_WATERMARK, now);
|
|
142
148
|
return;
|
|
143
149
|
}
|
|
144
150
|
|
|
@@ -171,6 +177,14 @@ export class UsageTelemetryReporter {
|
|
|
171
177
|
getMemoryCheckpoint(CHECKPOINT_KEY_ONBOARDING_WATERMARK_ID) ??
|
|
172
178
|
undefined;
|
|
173
179
|
|
|
180
|
+
// Read auth-fallback watermark (compound cursor: createdAt + id)
|
|
181
|
+
const authFallbackWatermark = Number(
|
|
182
|
+
getMemoryCheckpoint(CHECKPOINT_KEY_AUTH_FALLBACK_WATERMARK) ?? "0",
|
|
183
|
+
);
|
|
184
|
+
const authFallbackWatermarkId =
|
|
185
|
+
getMemoryCheckpoint(CHECKPOINT_KEY_AUTH_FALLBACK_WATERMARK_ID) ??
|
|
186
|
+
undefined;
|
|
187
|
+
|
|
174
188
|
// Query unreported events
|
|
175
189
|
const events = queryUnreportedUsageEvents(
|
|
176
190
|
watermark,
|
|
@@ -192,12 +206,18 @@ export class UsageTelemetryReporter {
|
|
|
192
206
|
onboardingWatermarkId,
|
|
193
207
|
BATCH_SIZE,
|
|
194
208
|
);
|
|
209
|
+
const authFallbackEvents = queryUnreportedAuthFallbackEvents(
|
|
210
|
+
authFallbackWatermark,
|
|
211
|
+
authFallbackWatermarkId,
|
|
212
|
+
BATCH_SIZE,
|
|
213
|
+
);
|
|
195
214
|
|
|
196
215
|
if (
|
|
197
216
|
events.length === 0 &&
|
|
198
217
|
turnEvents.length === 0 &&
|
|
199
218
|
lifecycleEvents.length === 0 &&
|
|
200
|
-
onboardingEvents.length === 0
|
|
219
|
+
onboardingEvents.length === 0 &&
|
|
220
|
+
authFallbackEvents.length === 0
|
|
201
221
|
)
|
|
202
222
|
return;
|
|
203
223
|
|
|
@@ -211,6 +231,7 @@ export class UsageTelemetryReporter {
|
|
|
211
231
|
turnCount: turnEvents.length,
|
|
212
232
|
lifecycleCount: lifecycleEvents.length,
|
|
213
233
|
onboardingCount: onboardingEvents.length,
|
|
234
|
+
authFallbackCount: authFallbackEvents.length,
|
|
214
235
|
},
|
|
215
236
|
"Telemetry flush: resolved auth context",
|
|
216
237
|
);
|
|
@@ -337,6 +358,25 @@ export class UsageTelemetryReporter {
|
|
|
337
358
|
assistant_version: APP_VERSION,
|
|
338
359
|
}),
|
|
339
360
|
),
|
|
361
|
+
...authFallbackEvents.map(
|
|
362
|
+
(e): TelemetryEvent => ({
|
|
363
|
+
type: "auth_fallback",
|
|
364
|
+
daemon_event_id: e.id,
|
|
365
|
+
recorded_at: e.createdAt,
|
|
366
|
+
guard: e.guard,
|
|
367
|
+
path: e.path,
|
|
368
|
+
failure_kind: e.failureKind,
|
|
369
|
+
count: e.count,
|
|
370
|
+
window_start: e.windowStart,
|
|
371
|
+
window_end: e.windowEnd,
|
|
372
|
+
// Aggregated counts forwarded by the gateway carry no record-time
|
|
373
|
+
// binary version; stamp the running binary's `APP_VERSION` so the
|
|
374
|
+
// wire value is concrete rather than an explicit null that would
|
|
375
|
+
// override the envelope under the platform's per-event-wins
|
|
376
|
+
// contract.
|
|
377
|
+
assistant_version: APP_VERSION,
|
|
378
|
+
}),
|
|
379
|
+
),
|
|
340
380
|
];
|
|
341
381
|
|
|
342
382
|
const organizationId = getPlatformOrganizationId() || undefined;
|
|
@@ -422,12 +462,27 @@ export class UsageTelemetryReporter {
|
|
|
422
462
|
);
|
|
423
463
|
}
|
|
424
464
|
|
|
465
|
+
// Advance auth-fallback watermark (compound cursor)
|
|
466
|
+
if (authFallbackEvents.length > 0) {
|
|
467
|
+
const lastAuthFallback =
|
|
468
|
+
authFallbackEvents[authFallbackEvents.length - 1];
|
|
469
|
+
setMemoryCheckpoint(
|
|
470
|
+
CHECKPOINT_KEY_AUTH_FALLBACK_WATERMARK,
|
|
471
|
+
String(lastAuthFallback.createdAt),
|
|
472
|
+
);
|
|
473
|
+
setMemoryCheckpoint(
|
|
474
|
+
CHECKPOINT_KEY_AUTH_FALLBACK_WATERMARK_ID,
|
|
475
|
+
lastAuthFallback.id,
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
|
|
425
479
|
// If we got a full batch of any type, there may be more — recurse
|
|
426
480
|
if (
|
|
427
481
|
events.length === BATCH_SIZE ||
|
|
428
482
|
turnEvents.length === BATCH_SIZE ||
|
|
429
483
|
lifecycleEvents.length === BATCH_SIZE ||
|
|
430
|
-
onboardingEvents.length === BATCH_SIZE
|
|
484
|
+
onboardingEvents.length === BATCH_SIZE ||
|
|
485
|
+
authFallbackEvents.length === BATCH_SIZE
|
|
431
486
|
) {
|
|
432
487
|
await this._doFlush(batchCount + 1);
|
|
433
488
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared ToolContext accessors for the ACP tools.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ServerMessage } from "../../daemon/message-protocol.js";
|
|
6
|
+
import type { ToolContext } from "../types.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Narrows `ToolContext.sendToClient` to the `ServerMessage` sender the ACP
|
|
10
|
+
* session manager expects. ToolContext types the callback against an
|
|
11
|
+
* index-signature message shape (`{ type: string; [key: string]: unknown }`)
|
|
12
|
+
* that ServerMessage's union members don't structurally satisfy, so the
|
|
13
|
+
* cast lives here once instead of being duplicated at every ACP tool call
|
|
14
|
+
* site.
|
|
15
|
+
*/
|
|
16
|
+
export function getSendToClient(
|
|
17
|
+
context: ToolContext,
|
|
18
|
+
): ((msg: ServerMessage) => void) | undefined {
|
|
19
|
+
return context.sendToClient as ((msg: ServerMessage) => void) | undefined;
|
|
20
|
+
}
|
|
@@ -47,7 +47,7 @@ describe("executeAcpListAgents", () => {
|
|
|
47
47
|
expect(parsed.hint).toContain("config.json");
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
test("enabled, no user config:
|
|
50
|
+
test("enabled, no user config: all defaults present with source 'default' and available based on Bun.which", async () => {
|
|
51
51
|
config.setConfig({ agents: {} });
|
|
52
52
|
|
|
53
53
|
const result = await executeAcpListAgents({}, makeContext());
|
|
@@ -58,6 +58,7 @@ describe("executeAcpListAgents", () => {
|
|
|
58
58
|
expect(parsed.agents.map((a: { id: string }) => a.id)).toEqual([
|
|
59
59
|
"claude",
|
|
60
60
|
"codex",
|
|
61
|
+
"gemini",
|
|
61
62
|
]);
|
|
62
63
|
for (const entry of parsed.agents) {
|
|
63
64
|
expect(entry.source).toBe("default");
|
|
@@ -108,6 +109,11 @@ describe("executeAcpListAgents", () => {
|
|
|
108
109
|
expect(codex.unavailableReason).toBe("'codex-acp' is not on PATH");
|
|
109
110
|
expect(codex.setupHint).toBe("npm i -g @zed-industries/codex-acp");
|
|
110
111
|
|
|
112
|
+
const gemini = parsed.agents.find((a: { id: string }) => a.id === "gemini");
|
|
113
|
+
expect(gemini.available).toBe(false);
|
|
114
|
+
expect(gemini.unavailableReason).toBe("'gemini' is not on PATH");
|
|
115
|
+
expect(gemini.setupHint).toBe("npm i -g @google/gemini-cli");
|
|
116
|
+
|
|
111
117
|
const claude = parsed.agents.find((a: { id: string }) => a.id === "claude");
|
|
112
118
|
expect(claude.available).toBe(true);
|
|
113
119
|
expect(claude.setupHint).toBeUndefined();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as realChildProcess from "node:child_process";
|
|
2
1
|
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
3
2
|
|
|
4
3
|
import { installAcpConfigStub } from "../../acp/__tests__/helpers/acp-config-stub.js";
|
|
4
|
+
import { installExecFileStub } from "../../acp/__tests__/helpers/exec-file-stub.js";
|
|
5
5
|
import { installWhichStub } from "../../acp/__tests__/helpers/which-stub.js";
|
|
6
6
|
import type { ToolContext } from "../types.js";
|
|
7
7
|
|
|
@@ -9,55 +9,11 @@ import type { ToolContext } from "../types.js";
|
|
|
9
9
|
// Mock infrastructure
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
interface ExecScript {
|
|
19
|
-
/** When set, the call rejects with this error. */
|
|
20
|
-
error?: Error;
|
|
21
|
-
/** When set, the call resolves with this stdout. */
|
|
22
|
-
stdout?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Per-call scripted responses for `execFile`. Keyed by `${command} ${args[0]}`
|
|
27
|
-
* so tests can target `npm ls` and `npm view` independently.
|
|
28
|
-
*/
|
|
29
|
-
const execScripts: Map<string, ExecScript> = new Map();
|
|
30
|
-
|
|
31
|
-
const execFileMock = mock(
|
|
32
|
-
(
|
|
33
|
-
command: string,
|
|
34
|
-
args: string[],
|
|
35
|
-
_options: unknown,
|
|
36
|
-
callback?: ExecCallback,
|
|
37
|
-
) => {
|
|
38
|
-
const key = `${command} ${args[0]}`;
|
|
39
|
-
const script = execScripts.get(key);
|
|
40
|
-
queueMicrotask(() => {
|
|
41
|
-
if (!callback) return;
|
|
42
|
-
if (!script) {
|
|
43
|
-
callback(new Error(`No script for ${key}`), "", "");
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
if (script.error) {
|
|
47
|
-
callback(script.error, "", "");
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
callback(null, script.stdout ?? "", "");
|
|
51
|
-
});
|
|
52
|
-
// Return value is not used by execFileWithTimeout.
|
|
53
|
-
return {} as ReturnType<typeof realChildProcess.execFile>;
|
|
54
|
-
},
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
mock.module("node:child_process", () => ({
|
|
58
|
-
...realChildProcess,
|
|
59
|
-
execFile: execFileMock,
|
|
60
|
-
}));
|
|
12
|
+
const {
|
|
13
|
+
execScripts,
|
|
14
|
+
execFileMock,
|
|
15
|
+
reset: resetExecFileStub,
|
|
16
|
+
} = installExecFileStub();
|
|
61
17
|
|
|
62
18
|
// Default ACP config used by these tests: the `unknown-agent` entry is here
|
|
63
19
|
// to give the "no version check" test a configured agent whose binary isn't
|
|
@@ -189,6 +145,9 @@ mock.module("../../acp/index.js", () => ({
|
|
|
189
145
|
|
|
190
146
|
const { executeAcpSpawn, _resetAdapterVersionCacheForTests } =
|
|
191
147
|
await import("./spawn.js");
|
|
148
|
+
const { _resetAdapterInstallCacheForTests } = await import(
|
|
149
|
+
"../../acp/auto-install.js"
|
|
150
|
+
);
|
|
192
151
|
|
|
193
152
|
// ---------------------------------------------------------------------------
|
|
194
153
|
// Helpers
|
|
@@ -204,10 +163,10 @@ function makeContext(): ToolContext {
|
|
|
204
163
|
}
|
|
205
164
|
|
|
206
165
|
beforeEach(() => {
|
|
207
|
-
|
|
208
|
-
execFileMock.mockClear();
|
|
166
|
+
resetExecFileStub();
|
|
209
167
|
spawnMock.mockClear();
|
|
210
168
|
_resetAdapterVersionCacheForTests();
|
|
169
|
+
_resetAdapterInstallCacheForTests();
|
|
211
170
|
config.setConfig({ agents: DEFAULT_TEST_AGENTS });
|
|
212
171
|
which.setWhich((cmd) => `/usr/local/bin/${cmd}`);
|
|
213
172
|
// Default: vault has a claude token so the preflight in `prepareAgentEnv`
|
|
@@ -391,8 +350,9 @@ describe("executeAcpSpawn — input validation", () => {
|
|
|
391
350
|
expect(result.content).toContain("acp.enabled");
|
|
392
351
|
});
|
|
393
352
|
|
|
394
|
-
test("missing binary returns install hint", async () => {
|
|
353
|
+
test("missing binary returns install hint when auto-install fails", async () => {
|
|
395
354
|
which.setWhich({});
|
|
355
|
+
execScripts.set("npm i", { error: new Error("npm not installed") });
|
|
396
356
|
const result = await executeAcpSpawn(
|
|
397
357
|
{ agent: "claude", task: "do something" },
|
|
398
358
|
makeContext(),
|
|
@@ -426,6 +386,149 @@ describe("executeAcpSpawn — input validation", () => {
|
|
|
426
386
|
});
|
|
427
387
|
});
|
|
428
388
|
|
|
389
|
+
describe("executeAcpSpawn: auto-install on missing binary", () => {
|
|
390
|
+
test("known command: installs the mapped package and spawn proceeds with a note", async () => {
|
|
391
|
+
// Binary appears on PATH only after `npm i -g` runs, simulating a
|
|
392
|
+
// successful global install.
|
|
393
|
+
let binaryOnPath = false;
|
|
394
|
+
which.setWhich((cmd) => (binaryOnPath ? `/usr/local/bin/${cmd}` : null));
|
|
395
|
+
execScripts.set("npm i", {
|
|
396
|
+
stdout: "",
|
|
397
|
+
onCall: () => {
|
|
398
|
+
binaryOnPath = true;
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
// Version probes after the install: best-effort, scripted to skip.
|
|
402
|
+
execScripts.set("npm ls", { error: new Error("skip") });
|
|
403
|
+
execScripts.set("npm view", { error: new Error("skip") });
|
|
404
|
+
|
|
405
|
+
const result = await executeAcpSpawn(
|
|
406
|
+
{ agent: "claude", task: "do something" },
|
|
407
|
+
makeContext(),
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
expect(result.isError).toBe(false);
|
|
411
|
+
expect(spawnMock).toHaveBeenCalledTimes(1);
|
|
412
|
+
const [payloadJson] = result.content.split("\n\n");
|
|
413
|
+
const payload = JSON.parse(payloadJson);
|
|
414
|
+
expect(payload.message).toContain(
|
|
415
|
+
"Installed @agentclientprotocol/claude-agent-acp automatically.",
|
|
416
|
+
);
|
|
417
|
+
const installCalls = execFileMock.mock.calls.filter(
|
|
418
|
+
(call) => (call[1] as string[])[0] === "i",
|
|
419
|
+
);
|
|
420
|
+
expect(installCalls).toHaveLength(1);
|
|
421
|
+
expect(installCalls[0][1]).toEqual([
|
|
422
|
+
"i",
|
|
423
|
+
"-g",
|
|
424
|
+
"@agentclientprotocol/claude-agent-acp",
|
|
425
|
+
]);
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
test("unknown command: no install attempted, plain hint returned", async () => {
|
|
429
|
+
which.setWhich({});
|
|
430
|
+
|
|
431
|
+
const result = await executeAcpSpawn(
|
|
432
|
+
{ agent: "unknown-agent", task: "do something" },
|
|
433
|
+
makeContext(),
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
expect(result.isError).toBe(true);
|
|
437
|
+
expect(result.content).toContain("some-other-binary is not on PATH");
|
|
438
|
+
expect(result.content).toContain("Install 'some-other-binary'");
|
|
439
|
+
expect(result.content).not.toContain("auto-install failed");
|
|
440
|
+
expect(execFileMock).not.toHaveBeenCalled();
|
|
441
|
+
expect(spawnMock).not.toHaveBeenCalled();
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
test("no client connected: no install attempted even when the binary is missing", async () => {
|
|
445
|
+
// The no-client guard is a pure precondition and must run BEFORE the
|
|
446
|
+
// auto-install side effect: without a client the spawn fails anyway, so
|
|
447
|
+
// the host must not be mutated by `npm i -g` (which can also block for
|
|
448
|
+
// up to the install timeout).
|
|
449
|
+
which.setWhich({});
|
|
450
|
+
|
|
451
|
+
const result = await executeAcpSpawn(
|
|
452
|
+
{ agent: "claude", task: "do something" },
|
|
453
|
+
{ ...makeContext(), sendToClient: undefined },
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
expect(result.isError).toBe(true);
|
|
457
|
+
expect(result.content).toContain("No client connected");
|
|
458
|
+
expect(execFileMock).not.toHaveBeenCalled();
|
|
459
|
+
expect(spawnMock).not.toHaveBeenCalled();
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
test("npm failure: hint and install failure both surface", async () => {
|
|
463
|
+
which.setWhich({});
|
|
464
|
+
execScripts.set("npm i", {
|
|
465
|
+
error: new Error("EACCES: permission denied"),
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
const result = await executeAcpSpawn(
|
|
469
|
+
{ agent: "claude", task: "do something" },
|
|
470
|
+
makeContext(),
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
expect(result.isError).toBe(true);
|
|
474
|
+
expect(result.content).toContain("claude-agent-acp is not on PATH");
|
|
475
|
+
expect(result.content).toContain(
|
|
476
|
+
"npm i -g @agentclientprotocol/claude-agent-acp",
|
|
477
|
+
);
|
|
478
|
+
expect(result.content).toContain("auto-install failed");
|
|
479
|
+
expect(result.content).toContain("EACCES");
|
|
480
|
+
expect(spawnMock).not.toHaveBeenCalled();
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
describe("executeAcpSpawn - bunx fallback when binary missing", () => {
|
|
485
|
+
test("binary missing + bun present: spawns via `bun x` with env injection and resume hint, no npm calls", async () => {
|
|
486
|
+
// Only bun is on PATH - the platform-hosted image (bun, no node/npm).
|
|
487
|
+
which.setWhich({ bun: "/usr/local/bin/bun" });
|
|
488
|
+
|
|
489
|
+
const result = await executeAcpSpawn(
|
|
490
|
+
{ agent: "claude", task: "do something" },
|
|
491
|
+
makeContext(),
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
expect(result.isError).toBe(false);
|
|
495
|
+
// No npm install AND no npm version probe: bunx fetches the package on
|
|
496
|
+
// first use and there is no global install to compare.
|
|
497
|
+
expect(execFileMock).not.toHaveBeenCalled();
|
|
498
|
+
expect(result.content).not.toContain("outdated");
|
|
499
|
+
|
|
500
|
+
expect(spawnMock).toHaveBeenCalledTimes(1);
|
|
501
|
+
const agentConfigArg = spawnMock.mock.calls[0][1] as {
|
|
502
|
+
command: string;
|
|
503
|
+
args: string[];
|
|
504
|
+
adapterCommand?: string;
|
|
505
|
+
env?: Record<string, string>;
|
|
506
|
+
};
|
|
507
|
+
expect(agentConfigArg.command).toBe("bun");
|
|
508
|
+
expect(agentConfigArg.args).toEqual([
|
|
509
|
+
"x",
|
|
510
|
+
"--bun",
|
|
511
|
+
"@agentclientprotocol/claude-agent-acp",
|
|
512
|
+
]);
|
|
513
|
+
expect(agentConfigArg.adapterCommand).toBe("claude-agent-acp");
|
|
514
|
+
// CLAUDE_CODE_OAUTH_TOKEN injection still applies to the bunx-resolved
|
|
515
|
+
// claude adapter (gated on adapterCommand, not the spawn command).
|
|
516
|
+
expect(agentConfigArg.env?.CLAUDE_CODE_OAUTH_TOKEN).toBe(
|
|
517
|
+
"default-test-token",
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
const [payloadJson] = result.content.split("\n\n");
|
|
521
|
+
const payload = JSON.parse(payloadJson);
|
|
522
|
+
// No auto-install happened; the claude resume hint still fires.
|
|
523
|
+
expect(payload.message).not.toContain("Installed");
|
|
524
|
+
expect(payload.message).toContain("claude --resume");
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
// The bun-absent npm fallback is covered by the existing auto-install
|
|
528
|
+
// suite below ("known command: installs the mapped package..."), whose
|
|
529
|
+
// which-stub leaves bun off PATH until the install completes.
|
|
530
|
+
});
|
|
531
|
+
|
|
429
532
|
describe("executeAcpSpawn — per-agent resume hint", () => {
|
|
430
533
|
test("claude payload includes the `claude --resume` hint", async () => {
|
|
431
534
|
execScripts.set("npm ls", { error: new Error("npm not installed") });
|
|
@@ -440,7 +543,7 @@ describe("executeAcpSpawn — per-agent resume hint", () => {
|
|
|
440
543
|
const [payloadJson] = result.content.split("\n\n");
|
|
441
544
|
const payload = JSON.parse(payloadJson);
|
|
442
545
|
expect(payload.message).toContain("claude --resume");
|
|
443
|
-
expect(payload.message).toContain("To resume
|
|
546
|
+
expect(payload.message).toContain("To resume:");
|
|
444
547
|
});
|
|
445
548
|
|
|
446
549
|
test("non-claude payload omits the `claude --resume` hint", async () => {
|
|
@@ -458,7 +561,7 @@ describe("executeAcpSpawn — per-agent resume hint", () => {
|
|
|
458
561
|
const [payloadJson] = result.content.split("\n\n");
|
|
459
562
|
const payload = JSON.parse(payloadJson);
|
|
460
563
|
expect(payload.message).not.toContain("claude --resume");
|
|
461
|
-
expect(payload.message).not.toContain("To resume
|
|
564
|
+
expect(payload.message).not.toContain("To resume:");
|
|
462
565
|
});
|
|
463
566
|
});
|
|
464
567
|
|
package/src/tools/acp/spawn.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
execFileWithTimeout,
|
|
3
|
+
resolveAgentWithAutoInstall,
|
|
4
|
+
} from "../../acp/auto-install.js";
|
|
3
5
|
import { getAcpSessionManager } from "../../acp/index.js";
|
|
4
6
|
import { prepareAgentEnv } from "../../acp/prepare-agent-env.js";
|
|
5
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
adapterCommandOf,
|
|
9
|
+
formatResolveFailure,
|
|
10
|
+
runsViaBunx,
|
|
11
|
+
} from "../../acp/resolve-agent.js";
|
|
12
|
+
import { claudeResumeHint } from "../../acp/resume-hint.js";
|
|
6
13
|
import { DEFAULT_AGENT_NPM_PACKAGES } from "../../config/acp-defaults.js";
|
|
7
14
|
import { getLogger } from "../../util/logger.js";
|
|
8
15
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
16
|
+
import { getSendToClient } from "./context.js";
|
|
9
17
|
|
|
10
18
|
const log = getLogger("acp:spawn");
|
|
11
19
|
|
|
@@ -25,35 +33,6 @@ interface AdapterVersionInfo {
|
|
|
25
33
|
packageName: string;
|
|
26
34
|
}
|
|
27
35
|
|
|
28
|
-
/**
|
|
29
|
-
* Run `execFile` with an AbortController-driven timeout. Returns the stdout
|
|
30
|
-
* on success; throws on error or timeout. Caller treats any throw as a
|
|
31
|
-
* best-effort skip.
|
|
32
|
-
*/
|
|
33
|
-
function execFileWithTimeout(
|
|
34
|
-
command: string,
|
|
35
|
-
args: string[],
|
|
36
|
-
timeoutMs: number,
|
|
37
|
-
): Promise<string> {
|
|
38
|
-
return new Promise((resolve, reject) => {
|
|
39
|
-
const controller = new AbortController();
|
|
40
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
41
|
-
execFile(
|
|
42
|
-
command,
|
|
43
|
-
args,
|
|
44
|
-
{ signal: controller.signal, encoding: "utf8" },
|
|
45
|
-
(err, stdout) => {
|
|
46
|
-
clearTimeout(timer);
|
|
47
|
-
if (err) {
|
|
48
|
-
reject(err);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
resolve(stdout);
|
|
52
|
-
},
|
|
53
|
-
);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
36
|
/**
|
|
58
37
|
* Checks if the globally-installed ACP adapter for `command` is outdated.
|
|
59
38
|
* Best-effort: any error or timeout returns `null` (skipped). Unknown
|
|
@@ -135,34 +114,10 @@ export async function executeAcpSpawn(
|
|
|
135
114
|
return { content: '"task" is required.', isError: true };
|
|
136
115
|
}
|
|
137
116
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return { content: resolved.hint, isError: true };
|
|
143
|
-
case "unknown_agent":
|
|
144
|
-
return {
|
|
145
|
-
content: `Unknown agent "${agent}". Available: ${resolved.available.join(
|
|
146
|
-
", ",
|
|
147
|
-
)}.`,
|
|
148
|
-
isError: true,
|
|
149
|
-
};
|
|
150
|
-
case "binary_not_found":
|
|
151
|
-
return {
|
|
152
|
-
content: `${resolved.command} is not on PATH. ${resolved.hint}`,
|
|
153
|
-
isError: true,
|
|
154
|
-
};
|
|
155
|
-
default: {
|
|
156
|
-
const _exhaustive: never = resolved;
|
|
157
|
-
throw new Error(
|
|
158
|
-
`Unexpected acp resolver reason: ${(_exhaustive as { reason: string }).reason}`,
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
const sendToClient = context.sendToClient as
|
|
164
|
-
| ((msg: { type: string; [key: string]: unknown }) => void)
|
|
165
|
-
| undefined;
|
|
117
|
+
// Pure precondition: check for a connected client BEFORE any side effects
|
|
118
|
+
// (auto-install mutates the host via `npm i -g` and can block for up to
|
|
119
|
+
// the install timeout). Without a client the spawn cannot succeed anyway.
|
|
120
|
+
const sendToClient = getSendToClient(context);
|
|
166
121
|
if (!sendToClient) {
|
|
167
122
|
return {
|
|
168
123
|
content: "No client connected - cannot spawn ACP agent.",
|
|
@@ -170,6 +125,17 @@ export async function executeAcpSpawn(
|
|
|
170
125
|
};
|
|
171
126
|
}
|
|
172
127
|
|
|
128
|
+
// Resolve the agent, silently auto-installing a missing allowlisted
|
|
129
|
+
// adapter binary (see acp/auto-install.ts). Shared with the HTTP route.
|
|
130
|
+
const { resolved, autoInstalledPackage, failureMessage } =
|
|
131
|
+
await resolveAgentWithAutoInstall(agent);
|
|
132
|
+
if (failureMessage) {
|
|
133
|
+
return { content: failureMessage, isError: true };
|
|
134
|
+
}
|
|
135
|
+
if (!resolved.ok) {
|
|
136
|
+
return { content: formatResolveFailure(agent, resolved), isError: true };
|
|
137
|
+
}
|
|
138
|
+
|
|
173
139
|
// Inject required env vars and preflight via the shared helper. Mirrors
|
|
174
140
|
// the HTTP route at `runtime/routes/acp-routes.ts:spawnSession` — both
|
|
175
141
|
// call sites MUST go through `prepareAgentEnv` before `manager.spawn`,
|
|
@@ -185,8 +151,12 @@ export async function executeAcpSpawn(
|
|
|
185
151
|
}
|
|
186
152
|
|
|
187
153
|
// Best-effort version check — never blocks the spawn. If outdated, we
|
|
188
|
-
// append a non-blocking warning to the success payload.
|
|
189
|
-
|
|
154
|
+
// append a non-blocking warning to the success payload. Skipped for
|
|
155
|
+
// bunx-resolved agents: there is no global npm install to compare (bun
|
|
156
|
+
// fetches the package on first use), and npm may not exist on the host.
|
|
157
|
+
const versionInfo = runsViaBunx(agentConfig)
|
|
158
|
+
? null
|
|
159
|
+
: await checkAdapterVersion(adapterCommandOf(agentConfig));
|
|
190
160
|
|
|
191
161
|
try {
|
|
192
162
|
const manager = getAcpSessionManager();
|
|
@@ -197,17 +167,21 @@ export async function executeAcpSpawn(
|
|
|
197
167
|
task,
|
|
198
168
|
cwd,
|
|
199
169
|
context.conversationId,
|
|
200
|
-
sendToClient
|
|
170
|
+
sendToClient,
|
|
201
171
|
);
|
|
202
172
|
|
|
203
|
-
//
|
|
204
|
-
// adapter
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
173
|
+
// Claude Code-only resume hint; empty for other adapters. Keyed off the
|
|
174
|
+
// canonical adapter command so it survives the bunx rewrite. See
|
|
175
|
+
// acp/resume-hint.ts for the gating rationale.
|
|
176
|
+
const hint = claudeResumeHint(
|
|
177
|
+
adapterCommandOf(agentConfig),
|
|
178
|
+
cwd,
|
|
179
|
+
protocolSessionId,
|
|
180
|
+
);
|
|
181
|
+
const resumeHint = hint ? ` ${hint}` : "";
|
|
182
|
+
const installNote = autoInstalledPackage
|
|
183
|
+
? ` Installed ${autoInstalledPackage} automatically.`
|
|
184
|
+
: "";
|
|
211
185
|
const payload = JSON.stringify({
|
|
212
186
|
acpSessionId,
|
|
213
187
|
protocolSessionId,
|
|
@@ -216,7 +190,8 @@ export async function executeAcpSpawn(
|
|
|
216
190
|
status: "running",
|
|
217
191
|
message:
|
|
218
192
|
`ACP agent "${agent}" spawned (session: ${protocolSessionId}). ` +
|
|
219
|
-
`Results stream back via SSE. You will be notified when it completes
|
|
193
|
+
`Results stream back via SSE. You will be notified when it completes.` +
|
|
194
|
+
`${installNote}${resumeHint}`,
|
|
220
195
|
});
|
|
221
196
|
|
|
222
197
|
let content = payload;
|