@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091853.fbaa2ae
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/ARCHITECTURE.md +6 -6
- package/bun.lock +2 -2
- package/docs/activation-funnel-telemetry.md +310 -0
- package/examples/plugins/echo/README.md +61 -60
- 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/skill-host.ts +7 -6
- package/openapi.yaml +263 -121
- package/package.json +2 -2
- package/src/__tests__/activation-early-marking.test.ts +120 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
- package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
- package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
- package/src/__tests__/agent-loop-thinking.test.ts +36 -20
- package/src/__tests__/agent-loop.test.ts +441 -96
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
- package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
- package/src/__tests__/anthropic-provider.test.ts +23 -8
- package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
- package/src/__tests__/app-control-flow.test.ts +1 -1
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +132 -0
- package/src/__tests__/approval-cascade.test.ts +6 -5
- package/src/__tests__/approval-routes-http.test.ts +4 -1
- package/src/__tests__/background-workers-disk-pressure.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__/compaction-circuit.test.ts +258 -0
- package/src/__tests__/compaction-direct.test.ts +146 -0
- package/src/__tests__/compaction-events.test.ts +7 -7
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
- package/src/__tests__/context-overflow-reducer.test.ts +265 -125
- package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
- package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
- package/src/__tests__/conversation-agent-loop.test.ts +342 -623
- package/src/__tests__/conversation-clean-command.test.ts +5 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
- package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
- package/src/__tests__/conversation-error.test.ts +15 -1
- package/src/__tests__/conversation-history-web-search.test.ts +6 -1
- package/src/__tests__/conversation-media-retry.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
- package/src/__tests__/conversation-process-callsite.test.ts +15 -15
- package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
- package/src/__tests__/conversation-queue.test.ts +10 -10
- package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
- package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
- package/src/__tests__/conversation-slash-queue.test.ts +7 -5
- package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
- package/src/__tests__/conversation-speed-override.test.ts +11 -10
- package/src/__tests__/conversation-starter-routes.test.ts +14 -6
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
- package/src/__tests__/conversation-undo.test.ts +2 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
- package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
- package/src/__tests__/corrected-target.test.ts +93 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +36 -0
- package/src/__tests__/db-acp-history.test.ts +101 -0
- package/src/__tests__/dynamic-page-surface.test.ts +31 -0
- package/src/__tests__/empty-response-hook.test.ts +1 -1
- package/src/__tests__/file-write-tool.test.ts +63 -0
- package/src/__tests__/gateway-only-guard.test.ts +17 -2
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -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__/history-repair-hook.test.ts +5 -1
- package/src/__tests__/host-app-control-proxy.test.ts +45 -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__/inference-profile-reaper.test.ts +62 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
- package/src/__tests__/injector-background-turn.test.ts +13 -23
- package/src/__tests__/injector-chain.test.ts +268 -44
- package/src/__tests__/injector-disk-pressure.test.ts +210 -52
- package/src/__tests__/injector-document-comments.test.ts +97 -114
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
- package/src/__tests__/injector-v3-suppression.test.ts +4 -4
- package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
- package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
- package/src/__tests__/llm-resolver.test.ts +73 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
- package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
- package/src/__tests__/notification-decision-strategy.test.ts +3 -3
- package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
- package/src/__tests__/persist-unsendable-image.test.ts +97 -1
- package/src/__tests__/plugin-api-shim.test.ts +6 -9
- package/src/__tests__/plugin-bootstrap.test.ts +91 -81
- package/src/__tests__/plugin-registry.test.ts +3 -49
- package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
- package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
- package/src/__tests__/plugin-types.test.ts +0 -70
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
- package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
- package/src/__tests__/published-app-updater.test.ts +138 -0
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +4 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
- package/src/__tests__/steer-tool-repair.test.ts +1 -1
- package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
- package/src/__tests__/subagent-detail.test.ts +25 -7
- 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__/title-generate-hook.test.ts +5 -1
- package/src/__tests__/tool-error-hook.test.ts +1 -1
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +54 -286
- package/src/__tests__/web-fetch.test.ts +45 -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-config-stub.ts +0 -2
- package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
- package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
- package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
- package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
- package/src/acp/agent-process.ts +61 -1
- package/src/acp/auto-install.test.ts +280 -0
- package/src/acp/auto-install.ts +232 -0
- package/src/acp/client-handler.ts +31 -0
- package/src/acp/prepare-agent-env.ts +80 -27
- package/src/acp/resolve-agent.test.ts +188 -28
- package/src/acp/resolve-agent.ts +119 -42
- package/src/acp/resume-hint.ts +23 -0
- package/src/acp/session-manager.ts +507 -73
- package/src/agent/compaction-circuit.ts +60 -102
- package/src/agent/loop.ts +403 -251
- package/src/api/responses/conversation-message.ts +22 -2
- package/src/api/responses/memory-v3-selection-log.ts +19 -10
- package/src/approvals/guardian-request-resolvers.ts +27 -1
- package/src/background-wake/next-wake.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
- package/src/cli/commands/channel-verification-sessions.ts +6 -6
- package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
- package/src/cli/commands/memory-v3.ts +57 -199
- package/src/cli/commands/plugins.ts +43 -37
- package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
- package/src/cli/lib/install-from-github.ts +797 -60
- package/src/cli/lib/plugin-catalog-cache.ts +84 -0
- package/src/cli/lib/plugin-details.ts +416 -0
- package/src/cli/lib/plugin-marketplace.ts +215 -0
- package/src/cli/lib/search-plugins.ts +201 -29
- 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 +9 -3
- package/src/config/acp-schema.ts +1 -7
- package/src/config/bundled-skills/acp/SKILL.md +80 -41
- package/src/config/bundled-skills/acp/TOOLS.json +4 -4
- package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
- package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
- 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/tools/app-list.ts +62 -0
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -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-tool-registry.ts +4 -0
- package/src/config/call-site-defaults.ts +0 -3
- package/src/config/feature-flag-registry.json +10 -16
- package/src/config/llm-resolver.ts +39 -7
- package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
- package/src/config/schemas/call-site-catalog.ts +0 -21
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm.ts +17 -3
- package/src/config/schemas/memory-v3.ts +58 -8
- package/src/config/seed-inference-profiles.ts +18 -0
- package/src/context/compactor.ts +22 -4
- package/src/context/post-turn-tool-result-truncation.ts +39 -1
- package/src/context/strip-injections.ts +8 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +18 -36
- package/src/daemon/conversation-agent-loop.ts +308 -1297
- package/src/daemon/conversation-error.ts +31 -4
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +11 -255
- package/src/daemon/conversation-media-retry.ts +19 -6
- package/src/daemon/conversation-messaging.ts +17 -0
- package/src/daemon/conversation-process.ts +22 -141
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-registry.ts +159 -0
- package/src/daemon/conversation-runtime-assembly.ts +361 -393
- package/src/daemon/conversation-store.ts +9 -90
- package/src/daemon/conversation-surfaces.ts +165 -11
- package/src/daemon/conversation-workspace.ts +17 -0
- package/src/daemon/conversation.ts +444 -62
- package/src/daemon/disk-pressure-policy.ts +0 -1
- package/src/daemon/external-plugins-bootstrap.ts +36 -46
- package/src/daemon/handlers/config-channels.ts +11 -2
- package/src/daemon/handlers/conversations.ts +3 -1
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-app-control-proxy.ts +72 -57
- package/src/daemon/host-proxy-preactivation.ts +1 -3
- package/src/daemon/lifecycle.ts +21 -7
- package/src/daemon/persist-unsendable-image.ts +62 -25
- package/src/daemon/process-message.ts +1 -1
- package/src/daemon/server.ts +2 -0
- package/src/daemon/tool-side-effects.ts +15 -0
- package/src/daemon/wake-conversation-ops.ts +269 -0
- package/src/embedded/plugin-api.ts +2 -2
- package/src/export/__tests__/transcript-formatter.test.ts +5 -0
- 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/ipc/__tests__/browser-ipc.test.ts +1 -1
- package/src/ipc/__tests__/ui-request-route.test.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/memory/__tests__/activation-session-store.test.ts +41 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
- package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
- package/src/memory/activation-session-store.ts +43 -0
- package/src/memory/conversation-crud.ts +29 -19
- package/src/memory/conversation-starter-checkpoints.ts +1 -0
- package/src/memory/db-init.ts +6 -0
- package/src/memory/job-handlers/conversation-starters.ts +13 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
- package/src/memory/jobs-worker.ts +25 -1
- package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
- package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
- package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
- package/src/memory/migrations/index.ts +3 -0
- package/src/memory/onboarding-events-store.ts +66 -18
- package/src/memory/schema/acp.ts +4 -0
- package/src/memory/schema/infrastructure.ts +13 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
- package/src/memory/v2/__tests__/page-store.test.ts +22 -0
- package/src/memory/v2/consolidation-job.ts +2 -63
- package/src/memory/v2/types.ts +5 -0
- package/src/messaging/providers/telegram-bot/api.ts +14 -5
- package/src/notifications/__tests__/copy-composer.test.ts +244 -0
- package/src/notifications/access-request-copy.ts +298 -0
- package/src/notifications/adapters/slack.ts +3 -3
- package/src/notifications/adapters/telegram.ts +9 -2
- package/src/notifications/copy-composer.ts +49 -267
- package/src/notifications/decision-engine.ts +16 -35
- package/src/notifications/home-feed-side-effect.ts +1 -6
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +40 -11
- package/src/plugin-api/types.ts +108 -0
- package/src/plugins/defaults/compaction/compact.ts +106 -0
- package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
- package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
- package/src/plugins/defaults/compaction/manager-store.ts +57 -0
- package/src/plugins/defaults/compaction/package.json +1 -2
- package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
- package/src/plugins/defaults/empty-response/package.json +0 -1
- package/src/plugins/defaults/history-repair/package.json +0 -1
- package/src/plugins/defaults/index.ts +156 -26
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
- package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
- package/src/plugins/defaults/memory-retrieval/package.json +14 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
- package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
- package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
- package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -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 +76 -0
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
- package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
- package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
- package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
- package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
- package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
- package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
- package/src/plugins/defaults/title-generate/package.json +0 -1
- package/src/plugins/defaults/tool-error/package.json +0 -1
- package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
- package/src/plugins/external-api.ts +12 -2
- package/src/plugins/pipeline.ts +6 -293
- package/src/plugins/registry.ts +9 -37
- package/src/plugins/types.ts +76 -381
- package/src/plugins/user-loader.ts +30 -127
- package/src/prompts/__tests__/system-prompt.test.ts +6 -0
- package/src/prompts/system-prompt.ts +61 -10
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
- package/src/providers/anthropic/client.ts +9 -10
- package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
- package/src/providers/inference/logit-bias.ts +55 -0
- package/src/providers/model-catalog.ts +34 -0
- package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
- package/src/providers/openai/chat-completions-provider.ts +44 -1
- package/src/providers/retry.ts +22 -0
- package/src/providers/types.ts +6 -0
- package/src/runtime/__tests__/agent-wake.test.ts +555 -691
- package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
- package/src/runtime/agent-wake.ts +108 -209
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/channel-approvals.ts +1 -1
- package/src/runtime/interactive-ui.ts +1 -1
- package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
- package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
- 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/acp-routes.test.ts +185 -32
- package/src/runtime/routes/acp-routes.ts +328 -30
- package/src/runtime/routes/app-management-routes.ts +3 -0
- package/src/runtime/routes/approval-routes.ts +1 -1
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/browser-tabs-routes.ts +6 -10
- package/src/runtime/routes/channel-verification-routes.ts +14 -5
- 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 +1 -1
- package/src/runtime/routes/conversation-routes.ts +30 -2
- package/src/runtime/routes/conversation-starter-routes.ts +13 -7
- package/src/runtime/routes/conversations-import-routes.ts +24 -7
- 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-routes.ts +18 -3
- package/src/runtime/routes/inbound-message-handler.ts +1 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
- package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
- package/src/runtime/routes/memory-v3-routes.ts +65 -305
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +337 -35
- package/src/runtime/routes/stt-routes.ts +45 -12
- package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
- package/src/runtime/routes/work-items-routes.ts +2 -4
- package/src/runtime/routes/workspace-routes.ts +50 -15
- package/src/runtime/services/conversation-serializer.ts +1 -1
- package/src/runtime/verification-outbound-actions.ts +147 -2
- package/src/runtime/verification-templates.ts +29 -3
- package/src/services/published-app-updater.ts +30 -8
- package/src/signals/cancel.ts +2 -4
- package/src/subagent/manager.ts +21 -5
- package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
- package/src/telemetry/activation-funnel.ts +167 -0
- package/src/telemetry/types.ts +13 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
- package/src/telemetry/usage-telemetry-reporter.ts +26 -1
- package/src/tools/acp/context.ts +20 -0
- package/src/tools/acp/list-agents.test.ts +9 -19
- package/src/tools/acp/list-agents.ts +3 -15
- package/src/tools/acp/spawn.test.ts +173 -202
- package/src/tools/acp/spawn.ts +37 -172
- package/src/tools/acp/steer.test.ts +105 -8
- package/src/tools/acp/steer.ts +48 -17
- package/src/tools/apps/executors.ts +166 -50
- package/src/tools/browser/browser-execution.ts +12 -2
- package/src/tools/filesystem/write.ts +34 -0
- package/src/tools/network/web-fetch.ts +65 -24
- package/src/tools/skills/load.ts +1 -1
- package/src/tools/subagent/spawn.ts +2 -4
- package/src/tools/ui-surface/definitions.ts +32 -5
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
- package/docs/plugins.md +0 -832
- package/examples/plugins/echo/register.ts +0 -143
- 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__/overflow-reduce-pipeline.test.ts +0 -667
- package/src/__tests__/pipeline-runner.test.ts +0 -554
- package/src/daemon/wake-target-adapter.ts +0 -253
- package/src/memory/v3/__tests__/assign.test.ts +0 -242
- package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
- package/src/memory/v3/__tests__/core.test.ts +0 -39
- package/src/memory/v3/__tests__/health.test.ts +0 -219
- package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
- package/src/memory/v3/__tests__/needle.test.ts +0 -107
- package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
- package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
- package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
- package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
- package/src/memory/v3/__tests__/router.test.ts +0 -332
- package/src/memory/v3/__tests__/selector.test.ts +0 -470
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
- package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
- package/src/memory/v3/__tests__/tree.test.ts +0 -192
- package/src/memory/v3/assign.ts +0 -268
- package/src/memory/v3/capabilities.ts +0 -124
- package/src/memory/v3/core.ts +0 -26
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/maintain-job.ts +0 -314
- package/src/memory/v3/needle.ts +0 -115
- package/src/memory/v3/orchestrate.ts +0 -126
- package/src/memory/v3/page-content.ts +0 -34
- package/src/memory/v3/provider-blocks.ts +0 -26
- package/src/memory/v3/reconcile.ts +0 -523
- package/src/memory/v3/router.ts +0 -190
- package/src/memory/v3/selection-log-store.ts +0 -84
- package/src/memory/v3/selector.ts +0 -226
- package/src/memory/v3/shadow-plugin.ts +0 -411
- package/src/memory/v3/snapshot.ts +0 -209
- package/src/memory/v3/tree.ts +0 -174
- package/src/memory/v3/types.ts +0 -59
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
- 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/register.ts +0 -35
- package/src/plugins/defaults/compaction/terminal.ts +0 -73
- package/src/plugins/defaults/empty-response/register.ts +0 -23
- package/src/plugins/defaults/history-repair/register.ts +0 -24
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
- 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/title-generate/register.ts +0 -35
- package/src/plugins/defaults/tool-error/register.ts +0 -23
- package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
- package/src/proactive-artifact/aux-message-injector.ts +0 -97
- package/src/proactive-artifact/decision.test.ts +0 -226
- package/src/proactive-artifact/decision.ts +0 -165
- package/src/proactive-artifact/index.ts +0 -7
- package/src/proactive-artifact/job.test.ts +0 -962
- package/src/proactive-artifact/job.ts +0 -372
- package/src/proactive-artifact/message-copy.ts +0 -58
- package/src/proactive-artifact/trigger-state.test.ts +0 -286
- package/src/proactive-artifact/trigger-state.ts +0 -123
- package/src/util/map-limit.ts +0 -27
- /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__/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}/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}/llm-retry.ts +0 -0
|
@@ -28,48 +28,82 @@ import {
|
|
|
28
28
|
getCredentialMetadata,
|
|
29
29
|
upsertCredentialMetadata,
|
|
30
30
|
} from "../tools/credentials/metadata-store.js";
|
|
31
|
+
import { getLogger } from "../util/logger.js";
|
|
31
32
|
import type { AcpAgentConfig } from "./types.js";
|
|
32
33
|
|
|
34
|
+
const log = getLogger("acp:prepare-agent-env");
|
|
35
|
+
|
|
33
36
|
const ACP_SPAWN_TOOL = "acp_spawn";
|
|
37
|
+
const ACP_SERVICE = "acp";
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
|
-
* Ensure
|
|
37
|
-
*
|
|
40
|
+
* Ensure an `acp/<field>` credential has metadata that allows the
|
|
41
|
+
* `acp_spawn` tool to read it, but only for legacy/unmanaged cases:
|
|
38
42
|
*
|
|
39
|
-
* - No metadata at all
|
|
40
|
-
* - Metadata exists with an empty `allowedTools
|
|
43
|
+
* - No metadata at all: create with `allowedTools: ["acp_spawn"]`.
|
|
44
|
+
* - Metadata exists with an empty `allowedTools`: default provisioning
|
|
41
45
|
* path (user ran `credentials set` without `--allowed-tools`), add it.
|
|
42
|
-
* - Metadata exists with a non-empty `allowedTools
|
|
43
|
-
* by the user/admin. Respect it even if `acp_spawn` is absent
|
|
44
|
-
* broker will deny the read and the
|
|
46
|
+
* - Metadata exists with a non-empty `allowedTools`: explicit policy set
|
|
47
|
+
* by the user/admin. Respect it even if `acp_spawn` is absent; the
|
|
48
|
+
* broker will deny the read and the caller decides whether that's fatal.
|
|
45
49
|
*/
|
|
46
|
-
function
|
|
47
|
-
|
|
50
|
+
function ensureAcpCredentialPolicy(
|
|
51
|
+
field: string,
|
|
52
|
+
usageDescription: string,
|
|
53
|
+
): void {
|
|
54
|
+
const meta = getCredentialMetadata(ACP_SERVICE, field);
|
|
48
55
|
if (!meta) {
|
|
49
|
-
upsertCredentialMetadata(
|
|
56
|
+
upsertCredentialMetadata(ACP_SERVICE, field, {
|
|
50
57
|
allowedTools: [ACP_SPAWN_TOOL],
|
|
51
|
-
usageDescription
|
|
52
|
-
"Claude OAuth token for ACP agent authentication",
|
|
58
|
+
usageDescription,
|
|
53
59
|
});
|
|
54
60
|
return;
|
|
55
61
|
}
|
|
56
62
|
const tools = meta.allowedTools ?? [];
|
|
57
63
|
if (tools.length === 0) {
|
|
58
|
-
upsertCredentialMetadata(
|
|
64
|
+
upsertCredentialMetadata(ACP_SERVICE, field, {
|
|
59
65
|
allowedTools: [ACP_SPAWN_TOOL],
|
|
60
66
|
});
|
|
61
67
|
}
|
|
62
68
|
}
|
|
63
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Read an `acp/<field>` credential through the broker and inject it into
|
|
72
|
+
* `env` under `envVar`. Returns the broker's failure reason when the value
|
|
73
|
+
* was not injected (missing credential, denied policy, no stored value),
|
|
74
|
+
* or undefined on success. Never throws: `serverUse` signals every failure
|
|
75
|
+
* mode, including a simply-absent credential, as `{ success: false,
|
|
76
|
+
* reason }`, so callers choose whether a miss is fatal.
|
|
77
|
+
*/
|
|
78
|
+
async function injectCredential(
|
|
79
|
+
env: Record<string, string>,
|
|
80
|
+
field: string,
|
|
81
|
+
envVar: string,
|
|
82
|
+
usageDescription: string,
|
|
83
|
+
): Promise<string | undefined> {
|
|
84
|
+
ensureAcpCredentialPolicy(field, usageDescription);
|
|
85
|
+
const result = await credentialBroker.serverUse<void>({
|
|
86
|
+
service: ACP_SERVICE,
|
|
87
|
+
field,
|
|
88
|
+
toolName: ACP_SPAWN_TOOL,
|
|
89
|
+
execute: async (value) => {
|
|
90
|
+
env[envVar] = value;
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
return result.success ? undefined : result.reason;
|
|
94
|
+
}
|
|
95
|
+
|
|
64
96
|
/**
|
|
65
97
|
* Returns a NEW config with any required credentials merged into `env`.
|
|
66
98
|
* Does NOT mutate the input. Throws `FailedDependencyError` if a required
|
|
67
99
|
* credential is missing from both the user-supplied env override and the
|
|
68
100
|
* secure store.
|
|
69
101
|
*
|
|
70
|
-
* Gating is keyed off the resolved
|
|
71
|
-
*
|
|
72
|
-
*
|
|
102
|
+
* Gating is keyed off the resolved command basename, not the user-facing
|
|
103
|
+
* agent id. A custom `acp.agents.my-claude = { command: "claude-agent-acp",
|
|
104
|
+
* ... }` alias (or a full path like `/opt/bin/claude-agent-acp`) still gets
|
|
105
|
+
* the env it needs. Because resolution always yields the real adapter binary
|
|
106
|
+
* (never a `bun x` wrapper), the basename is the canonical adapter identity.
|
|
73
107
|
*
|
|
74
108
|
* For `claude-agent-acp` the only required env var is
|
|
75
109
|
* `CLAUDE_CODE_OAUTH_TOKEN`. Two provisioning routes converge on it, with
|
|
@@ -84,6 +118,11 @@ function ensureAcpTokenPolicy(): void {
|
|
|
84
118
|
* before spawning. The "fail-fast" throw is symmetric with the existing
|
|
85
119
|
* `binary_not_found` preflight in `resolveAcpAgent` and strictly better
|
|
86
120
|
* than a `warn` + zombie subprocess 10 seconds later.
|
|
121
|
+
*
|
|
122
|
+
* For `gemini` the env var is `GEMINI_API_KEY`, provisioned the same two
|
|
123
|
+
* ways (config.json override wins, vault field `gemini_api_key` second),
|
|
124
|
+
* but it is OPTIONAL: the Gemini CLI supports its own OAuth login, so a
|
|
125
|
+
* vault miss proceeds without the key instead of failing the spawn.
|
|
87
126
|
*/
|
|
88
127
|
export async function prepareAgentEnv(
|
|
89
128
|
agentConfig: AcpAgentConfig,
|
|
@@ -92,19 +131,16 @@ export async function prepareAgentEnv(
|
|
|
92
131
|
// agent reference. The local `env` binding sidesteps TS narrowing
|
|
93
132
|
// limitations on the optional `AcpAgentConfig.env` field.
|
|
94
133
|
const env: Record<string, string> = { ...(agentConfig.env ?? {}) };
|
|
95
|
-
const
|
|
134
|
+
const adapterCommand = basename(agentConfig.command);
|
|
96
135
|
|
|
97
|
-
if (
|
|
136
|
+
if (adapterCommand === "claude-agent-acp") {
|
|
98
137
|
if (!env.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
106
|
-
},
|
|
107
|
-
});
|
|
138
|
+
await injectCredential(
|
|
139
|
+
env,
|
|
140
|
+
"claude_oauth_token",
|
|
141
|
+
"CLAUDE_CODE_OAUTH_TOKEN",
|
|
142
|
+
"Claude OAuth token for ACP agent authentication",
|
|
143
|
+
);
|
|
108
144
|
}
|
|
109
145
|
if (!env.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
110
146
|
throw new FailedDependencyError(
|
|
@@ -113,6 +149,23 @@ export async function prepareAgentEnv(
|
|
|
113
149
|
"(or set it under acp.agents.<id>.env in config.json).",
|
|
114
150
|
);
|
|
115
151
|
}
|
|
152
|
+
} else if (adapterCommand === "gemini") {
|
|
153
|
+
if (!env.GEMINI_API_KEY) {
|
|
154
|
+
const missReason = await injectCredential(
|
|
155
|
+
env,
|
|
156
|
+
"gemini_api_key",
|
|
157
|
+
"GEMINI_API_KEY",
|
|
158
|
+
"Gemini API key for ACP agent authentication",
|
|
159
|
+
);
|
|
160
|
+
if (missReason !== undefined) {
|
|
161
|
+
// Optional credential: Gemini CLI can authenticate via its own
|
|
162
|
+
// OAuth login, so a vault miss must not fail the spawn.
|
|
163
|
+
log.debug(
|
|
164
|
+
{ reason: missReason },
|
|
165
|
+
"Gemini API key unavailable from the vault; spawning without GEMINI_API_KEY",
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
116
169
|
}
|
|
117
170
|
|
|
118
171
|
return { ...agentConfig, env };
|
|
@@ -24,19 +24,6 @@ beforeEach(() => {
|
|
|
24
24
|
// ---------------------------------------------------------------------------
|
|
25
25
|
|
|
26
26
|
describe("resolveAcpAgent", () => {
|
|
27
|
-
test("returns acp_disabled when config.acp.enabled is false", () => {
|
|
28
|
-
config.setConfig({ enabled: false });
|
|
29
|
-
|
|
30
|
-
const result = resolveAcpAgent("claude");
|
|
31
|
-
|
|
32
|
-
expect(result.ok).toBe(false);
|
|
33
|
-
if (result.ok) return;
|
|
34
|
-
expect(result.reason).toBe("acp_disabled");
|
|
35
|
-
if (result.reason !== "acp_disabled") return;
|
|
36
|
-
expect(result.hint).toContain("acp.enabled");
|
|
37
|
-
expect(result.hint).toContain("config.json");
|
|
38
|
-
});
|
|
39
|
-
|
|
40
27
|
test("user config wins over default profile", () => {
|
|
41
28
|
config.setConfig({
|
|
42
29
|
agents: {
|
|
@@ -78,6 +65,79 @@ describe("resolveAcpAgent", () => {
|
|
|
78
65
|
expect(result.agent.command).toBe("claude-agent-acp");
|
|
79
66
|
});
|
|
80
67
|
|
|
68
|
+
test("falls back to the gemini default profile when no user entry", () => {
|
|
69
|
+
config.setConfig({ agents: {} });
|
|
70
|
+
|
|
71
|
+
const result = resolveAcpAgent("gemini");
|
|
72
|
+
|
|
73
|
+
expect(result.ok).toBe(true);
|
|
74
|
+
if (!result.ok) return;
|
|
75
|
+
expect(result.agent.command).toBe("gemini");
|
|
76
|
+
expect(result.agent.args).toEqual(["--acp"]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test.each([
|
|
80
|
+
["claude code", "claude-agent-acp"],
|
|
81
|
+
["Claude Code", "claude-agent-acp"],
|
|
82
|
+
["claude-code", "claude-agent-acp"],
|
|
83
|
+
["claude_code", "claude-agent-acp"],
|
|
84
|
+
["codex cli", "codex-acp"],
|
|
85
|
+
["OpenAI Codex", "codex-acp"],
|
|
86
|
+
["gemini cli", "gemini"],
|
|
87
|
+
["Gemini CLI", "gemini"],
|
|
88
|
+
["google gemini", "gemini"],
|
|
89
|
+
])("alias %p resolves to the %p profile", (alias, command) => {
|
|
90
|
+
config.setConfig({ agents: {} });
|
|
91
|
+
|
|
92
|
+
const result = resolveAcpAgent(alias);
|
|
93
|
+
|
|
94
|
+
expect(result.ok).toBe(true);
|
|
95
|
+
if (!result.ok) return;
|
|
96
|
+
expect(result.agent.command).toBe(command);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("user config entry literally keyed 'claude code' beats the alias", () => {
|
|
100
|
+
config.setConfig({
|
|
101
|
+
agents: {
|
|
102
|
+
"claude code": {
|
|
103
|
+
command: "my-claude-fork",
|
|
104
|
+
args: [],
|
|
105
|
+
description: "user-defined agent that happens to share an alias",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const result = resolveAcpAgent("claude code");
|
|
111
|
+
|
|
112
|
+
expect(result.ok).toBe(true);
|
|
113
|
+
if (!result.ok) return;
|
|
114
|
+
expect(result.agent.command).toBe("my-claude-fork");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("alias re-runs the normal lookup, so a user override of the canonical id wins", () => {
|
|
118
|
+
config.setConfig({
|
|
119
|
+
agents: {
|
|
120
|
+
claude: { command: "my-custom-claude", args: [] },
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const result = resolveAcpAgent("claude code");
|
|
125
|
+
|
|
126
|
+
expect(result.ok).toBe(true);
|
|
127
|
+
if (!result.ok) return;
|
|
128
|
+
expect(result.agent.command).toBe("my-custom-claude");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("non-alias unknown id still returns unknown_agent", () => {
|
|
132
|
+
config.setConfig({ agents: {} });
|
|
133
|
+
|
|
134
|
+
const result = resolveAcpAgent("cursor cli");
|
|
135
|
+
|
|
136
|
+
expect(result.ok).toBe(false);
|
|
137
|
+
if (result.ok) return;
|
|
138
|
+
expect(result.reason).toBe("unknown_agent");
|
|
139
|
+
});
|
|
140
|
+
|
|
81
141
|
test("returns unknown_agent with merged available list when id not found", () => {
|
|
82
142
|
config.setConfig({
|
|
83
143
|
agents: {
|
|
@@ -92,7 +152,12 @@ describe("resolveAcpAgent", () => {
|
|
|
92
152
|
expect(result.reason).toBe("unknown_agent");
|
|
93
153
|
if (result.reason !== "unknown_agent") return;
|
|
94
154
|
// Defaults plus user-only ids, deduped, in stable order (defaults first).
|
|
95
|
-
expect(result.available).toEqual([
|
|
155
|
+
expect(result.available).toEqual([
|
|
156
|
+
"claude",
|
|
157
|
+
"codex",
|
|
158
|
+
"gemini",
|
|
159
|
+
"user-only",
|
|
160
|
+
]);
|
|
96
161
|
});
|
|
97
162
|
|
|
98
163
|
test("unknown_agent available list contains both defaults when user config is empty", () => {
|
|
@@ -106,6 +171,7 @@ describe("resolveAcpAgent", () => {
|
|
|
106
171
|
if (result.reason !== "unknown_agent") return;
|
|
107
172
|
expect(result.available).toContain("claude");
|
|
108
173
|
expect(result.available).toContain("codex");
|
|
174
|
+
expect(result.available).toContain("gemini");
|
|
109
175
|
});
|
|
110
176
|
|
|
111
177
|
test("returns binary_not_found with the registered install hint", () => {
|
|
@@ -118,7 +184,7 @@ describe("resolveAcpAgent", () => {
|
|
|
118
184
|
if (result.ok) return;
|
|
119
185
|
expect(result.reason).toBe("binary_not_found");
|
|
120
186
|
if (result.reason !== "binary_not_found") return;
|
|
121
|
-
expect(result.hint).toBe("
|
|
187
|
+
expect(result.hint).toBe("bun add -g @agentclientprotocol/claude-agent-acp");
|
|
122
188
|
expect(result.command).toBe("claude-agent-acp");
|
|
123
189
|
});
|
|
124
190
|
|
|
@@ -158,7 +224,7 @@ describe("resolveAcpAgent", () => {
|
|
|
158
224
|
if (result.ok) return;
|
|
159
225
|
expect(result.reason).toBe("binary_not_found");
|
|
160
226
|
if (result.reason !== "binary_not_found") return;
|
|
161
|
-
expect(result.hint).toBe("
|
|
227
|
+
expect(result.hint).toBe("bun add -g @zed-industries/codex-acp");
|
|
162
228
|
});
|
|
163
229
|
|
|
164
230
|
test("binary preflight honors agent.env.PATH override (matches spawn env)", () => {
|
|
@@ -200,30 +266,74 @@ describe("resolveAcpAgent", () => {
|
|
|
200
266
|
if (!result.ok) return;
|
|
201
267
|
expect(result.agent.args).toEqual(["--verbose"]);
|
|
202
268
|
});
|
|
269
|
+
|
|
270
|
+
test("resolves a full-path command directly without rewriting it", () => {
|
|
271
|
+
config.setConfig({
|
|
272
|
+
agents: {
|
|
273
|
+
custom: { command: "/opt/bin/claude-agent-acp", args: [] },
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const direct = resolveAcpAgent("claude");
|
|
278
|
+
expect(direct.ok).toBe(true);
|
|
279
|
+
if (!direct.ok) return;
|
|
280
|
+
expect(direct.agent.command).toBe("claude-agent-acp");
|
|
281
|
+
|
|
282
|
+
const fullPath = resolveAcpAgent("custom");
|
|
283
|
+
expect(fullPath.ok).toBe(true);
|
|
284
|
+
if (!fullPath.ok) return;
|
|
285
|
+
expect(fullPath.agent.command).toBe("/opt/bin/claude-agent-acp");
|
|
286
|
+
});
|
|
203
287
|
});
|
|
204
288
|
|
|
205
289
|
// ---------------------------------------------------------------------------
|
|
206
|
-
//
|
|
290
|
+
// resolveAcpAgent - missing binaries are never run from the task cwd
|
|
207
291
|
// ---------------------------------------------------------------------------
|
|
208
292
|
|
|
209
|
-
describe("
|
|
210
|
-
test("
|
|
211
|
-
|
|
293
|
+
describe("resolveAcpAgent - missing binary", () => {
|
|
294
|
+
test("binary missing + bun present: still binary_not_found (no bunx rewrite)", () => {
|
|
295
|
+
// bun on PATH no longer makes a missing adapter "runnable" at resolve
|
|
296
|
+
// time: the sandboxed install happens separately, never as a `bun x`
|
|
297
|
+
// rewrite in the untrusted cwd.
|
|
298
|
+
config.setConfig({ agents: {} });
|
|
299
|
+
which.setWhich({ bun: "/usr/local/bin/bun" });
|
|
212
300
|
|
|
213
|
-
const result =
|
|
301
|
+
const result = resolveAcpAgent("claude");
|
|
302
|
+
|
|
303
|
+
expect(result.ok).toBe(false);
|
|
304
|
+
if (result.ok) return;
|
|
305
|
+
expect(result.reason).toBe("binary_not_found");
|
|
306
|
+
if (result.reason !== "binary_not_found") return;
|
|
307
|
+
expect(result.command).toBe("claude-agent-acp");
|
|
308
|
+
expect(result.hint).toBe("bun add -g @agentclientprotocol/claude-agent-acp");
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("binary missing + bun missing: binary_not_found with the bun hint", () => {
|
|
312
|
+
config.setConfig({ agents: {} });
|
|
313
|
+
which.setWhich({});
|
|
214
314
|
|
|
215
|
-
|
|
216
|
-
|
|
315
|
+
const result = resolveAcpAgent("claude");
|
|
316
|
+
|
|
317
|
+
expect(result.ok).toBe(false);
|
|
318
|
+
if (result.ok) return;
|
|
319
|
+
expect(result.reason).toBe("binary_not_found");
|
|
320
|
+
if (result.reason !== "binary_not_found") return;
|
|
321
|
+
expect(result.hint).toBe("bun add -g @agentclientprotocol/claude-agent-acp");
|
|
217
322
|
});
|
|
323
|
+
});
|
|
218
324
|
|
|
219
|
-
|
|
325
|
+
// ---------------------------------------------------------------------------
|
|
326
|
+
// listAcpAgents
|
|
327
|
+
// ---------------------------------------------------------------------------
|
|
328
|
+
|
|
329
|
+
describe("listAcpAgents", () => {
|
|
330
|
+
test("includes all bundled defaults when user config is empty", () => {
|
|
220
331
|
config.setConfig({ agents: {} });
|
|
221
332
|
|
|
222
333
|
const result = listAcpAgents();
|
|
223
334
|
|
|
224
|
-
expect(result.enabled).toBe(true);
|
|
225
335
|
const ids = result.agents.map((a) => a.id);
|
|
226
|
-
expect(ids).toEqual(["claude", "codex"]);
|
|
336
|
+
expect(ids).toEqual(["claude", "codex", "gemini"]);
|
|
227
337
|
for (const entry of result.agents) {
|
|
228
338
|
expect(entry.source).toBe("default");
|
|
229
339
|
expect(entry.available).toBe(true);
|
|
@@ -245,6 +355,7 @@ describe("listAcpAgents", () => {
|
|
|
245
355
|
which.setWhich({
|
|
246
356
|
"my-claude": "/usr/bin/my-claude",
|
|
247
357
|
"codex-acp": "/usr/bin/codex-acp",
|
|
358
|
+
gemini: "/usr/bin/gemini",
|
|
248
359
|
});
|
|
249
360
|
|
|
250
361
|
const result = listAcpAgents();
|
|
@@ -257,6 +368,27 @@ describe("listAcpAgents", () => {
|
|
|
257
368
|
expect(codex?.source).toBe("default");
|
|
258
369
|
});
|
|
259
370
|
|
|
371
|
+
test("missing binaries are listed unavailable even when bun is present", () => {
|
|
372
|
+
// bun presence no longer makes a missing adapter available: it is
|
|
373
|
+
// installed on demand at spawn time, not run via `bun x` from the cwd.
|
|
374
|
+
config.setConfig({ agents: {} });
|
|
375
|
+
which.setWhich({ bun: "/usr/local/bin/bun" });
|
|
376
|
+
|
|
377
|
+
const result = listAcpAgents();
|
|
378
|
+
|
|
379
|
+
for (const entry of result.agents) {
|
|
380
|
+
expect(entry.available).toBe(false);
|
|
381
|
+
expect(entry.unavailableReason).toBeDefined();
|
|
382
|
+
expect(entry.setupHint).toContain("bun add -g");
|
|
383
|
+
}
|
|
384
|
+
// The catalog keeps the canonical adapter commands.
|
|
385
|
+
expect(result.agents.map((a) => a.command)).toEqual([
|
|
386
|
+
"claude-agent-acp",
|
|
387
|
+
"codex-acp",
|
|
388
|
+
"gemini",
|
|
389
|
+
]);
|
|
390
|
+
});
|
|
391
|
+
|
|
260
392
|
test("unavailable agent surfaces install hint derived from DEFAULT_AGENT_NPM_PACKAGES", () => {
|
|
261
393
|
config.setConfig({ agents: {} });
|
|
262
394
|
which.setWhich({ "claude-agent-acp": "/usr/bin/claude-agent-acp" });
|
|
@@ -266,7 +398,33 @@ describe("listAcpAgents", () => {
|
|
|
266
398
|
const codex = result.agents.find((a) => a.id === "codex");
|
|
267
399
|
expect(codex?.available).toBe(false);
|
|
268
400
|
expect(codex?.unavailableReason).toBe("'codex-acp' is not on PATH");
|
|
269
|
-
expect(codex?.setupHint).toBe("
|
|
401
|
+
expect(codex?.setupHint).toBe("bun add -g @zed-industries/codex-acp");
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
test("unavailable gemini surfaces the @google/gemini-cli install hint", () => {
|
|
405
|
+
config.setConfig({ agents: {} });
|
|
406
|
+
which.setWhich({
|
|
407
|
+
"claude-agent-acp": "/usr/bin/claude-agent-acp",
|
|
408
|
+
"codex-acp": "/usr/bin/codex-acp",
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
const result = listAcpAgents();
|
|
412
|
+
|
|
413
|
+
const gemini = result.agents.find((a) => a.id === "gemini");
|
|
414
|
+
expect(gemini?.available).toBe(false);
|
|
415
|
+
expect(gemini?.unavailableReason).toBe("'gemini' is not on PATH");
|
|
416
|
+
expect(gemini?.setupHint).toBe("bun add -g @google/gemini-cli");
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
test("aliases are resolution sugar, not catalog entries", () => {
|
|
420
|
+
config.setConfig({ agents: {} });
|
|
421
|
+
|
|
422
|
+
// "gemini cli" resolves via the alias...
|
|
423
|
+
expect(resolveAcpAgent("gemini cli").ok).toBe(true);
|
|
424
|
+
|
|
425
|
+
// ...but the catalog lists only canonical ids.
|
|
426
|
+
const ids = listAcpAgents().agents.map((a) => a.id);
|
|
427
|
+
expect(ids).toEqual(["claude", "codex", "gemini"]);
|
|
270
428
|
});
|
|
271
429
|
|
|
272
430
|
test("user-only agent appended after defaults in stable order", () => {
|
|
@@ -282,6 +440,7 @@ describe("listAcpAgents", () => {
|
|
|
282
440
|
which.setWhich({
|
|
283
441
|
"claude-agent-acp": "/x",
|
|
284
442
|
"codex-acp": "/x",
|
|
443
|
+
gemini: "/x",
|
|
285
444
|
"my-binary": "/x",
|
|
286
445
|
});
|
|
287
446
|
|
|
@@ -290,9 +449,10 @@ describe("listAcpAgents", () => {
|
|
|
290
449
|
expect(result.agents.map((a) => a.id)).toEqual([
|
|
291
450
|
"claude",
|
|
292
451
|
"codex",
|
|
452
|
+
"gemini",
|
|
293
453
|
"my-agent",
|
|
294
454
|
]);
|
|
295
|
-
const userOnly = result.agents[
|
|
455
|
+
const userOnly = result.agents[3];
|
|
296
456
|
expect(userOnly.source).toBe("config");
|
|
297
457
|
expect(userOnly.description).toBe("user-only");
|
|
298
458
|
});
|