@vellumai/assistant 0.8.7-dev.202606052232.2ddc989 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/bun.lock +2 -2
  2. package/docs/plugins.md +832 -0
  3. package/examples/plugins/echo/README.md +60 -61
  4. package/examples/plugins/echo/package.json +2 -1
  5. package/examples/plugins/echo/register.ts +143 -0
  6. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +6 -7
  7. package/openapi.yaml +5 -15
  8. package/package.json +2 -2
  9. package/src/__tests__/agent-loop-exit-reason.test.ts +56 -3
  10. package/src/__tests__/anthropic-provider.test.ts +1 -1
  11. package/src/__tests__/app-control-flow.test.ts +1 -1
  12. package/src/__tests__/app-dir-path-guard.test.ts +0 -1
  13. package/src/__tests__/approval-routes-http.test.ts +1 -4
  14. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  15. package/src/__tests__/channel-approvals.test.ts +1 -1
  16. package/src/__tests__/circuit-breaker-pipeline.test.ts +405 -0
  17. package/src/__tests__/compaction-pipeline.test.ts +210 -0
  18. package/src/__tests__/compaction-timeout-recovery.test.ts +251 -0
  19. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
  20. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
  21. package/src/__tests__/conversation-agent-loop-overflow.test.ts +7 -3
  22. package/src/__tests__/conversation-agent-loop.test.ts +39 -42
  23. package/src/__tests__/conversation-clean-command.test.ts +2 -5
  24. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -4
  25. package/src/__tests__/conversation-runtime-assembly.test.ts +71 -140
  26. package/src/__tests__/conversation-runtime-workspace.test.ts +27 -108
  27. package/src/__tests__/conversation-starter-routes.test.ts +6 -14
  28. package/src/__tests__/conversation-workspace-cache-state.test.ts +16 -17
  29. package/src/__tests__/conversation-workspace-injection.test.ts +1 -61
  30. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -7
  31. package/src/__tests__/db-acp-history.test.ts +0 -101
  32. package/src/__tests__/dynamic-page-surface.test.ts +0 -31
  33. package/src/__tests__/file-write-tool.test.ts +0 -63
  34. package/src/__tests__/gateway-only-guard.test.ts +2 -12
  35. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  36. package/src/__tests__/guardian-routing-invariants.test.ts +4 -2
  37. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  38. package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -1
  39. package/src/__tests__/heartbeat-service.test.ts +0 -1
  40. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  41. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  42. package/src/__tests__/injector-background-turn.test.ts +1 -1
  43. package/src/__tests__/injector-chain.test.ts +6 -34
  44. package/src/__tests__/injector-disk-pressure.test.ts +34 -77
  45. package/src/__tests__/injector-document-comments.test.ts +1 -1
  46. package/src/__tests__/list-messages-hidden-metadata.test.ts +0 -38
  47. package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
  48. package/src/__tests__/{overflow-reduction-loop.test.ts → overflow-reduce-pipeline.test.ts} +284 -64
  49. package/src/__tests__/pipeline-runner.test.ts +554 -0
  50. package/src/__tests__/plugin-api-shim.test.ts +6 -3
  51. package/src/__tests__/plugin-bootstrap.test.ts +23 -12
  52. package/src/__tests__/plugin-registry.test.ts +49 -3
  53. package/src/__tests__/plugin-types.test.ts +70 -0
  54. package/src/__tests__/reaction-persistence.test.ts +1 -1
  55. package/src/__tests__/send-endpoint-busy.test.ts +1 -4
  56. package/src/__tests__/skill-feature-flags-integration.test.ts +0 -33
  57. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  58. package/src/__tests__/subagent-fork-notifications.test.ts +3 -1
  59. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  60. package/src/__tests__/subagent-manager-notify.test.ts +3 -1
  61. package/src/__tests__/subagent-notify-parent.test.ts +3 -1
  62. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  63. package/src/__tests__/user-plugin-loader.test.ts +286 -54
  64. package/src/acp/__tests__/client-handler.test.ts +0 -40
  65. package/src/acp/__tests__/prepare-agent-env.test.ts +0 -137
  66. package/src/acp/__tests__/session-manager-persistence.test.ts +28 -95
  67. package/src/acp/agent-process.ts +1 -61
  68. package/src/acp/client-handler.ts +0 -31
  69. package/src/acp/prepare-agent-env.ts +29 -83
  70. package/src/acp/resolve-agent.test.ts +7 -320
  71. package/src/acp/resolve-agent.ts +18 -182
  72. package/src/acp/session-manager.ts +73 -495
  73. package/src/acp/types.ts +0 -8
  74. package/src/agent/compaction-circuit.ts +102 -60
  75. package/src/agent/loop.ts +59 -32
  76. package/src/api/responses/conversation-message.ts +1 -7
  77. package/src/approvals/guardian-request-resolvers.ts +1 -1
  78. package/src/background-wake/next-wake.ts +0 -1
  79. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  80. package/src/config/acp-defaults.test.ts +0 -10
  81. package/src/config/acp-defaults.ts +0 -6
  82. package/src/config/bundled-skills/acp/SKILL.md +31 -83
  83. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  84. package/src/config/bundled-skills/app-builder/SKILL.md +381 -224
  85. package/src/config/bundled-skills/app-builder/TOOLS.json +0 -29
  86. package/src/config/bundled-skills/document-editor/SKILL.md +23 -28
  87. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  88. package/src/config/bundled-tool-registry.ts +0 -2
  89. package/src/config/feature-flag-registry.json +5 -14
  90. package/src/config/schemas/heartbeat.ts +0 -9
  91. package/src/context/strip-injections.ts +2 -8
  92. package/src/context/window-manager.ts +1 -2
  93. package/src/daemon/conversation-agent-loop-handlers.ts +11 -0
  94. package/src/daemon/conversation-agent-loop.ts +279 -62
  95. package/src/daemon/conversation-runtime-assembly.ts +69 -106
  96. package/src/daemon/conversation-store.ts +90 -9
  97. package/src/daemon/conversation-workspace.ts +0 -17
  98. package/src/daemon/conversation.ts +6 -0
  99. package/src/daemon/external-plugins-bootstrap.ts +11 -11
  100. package/src/daemon/handlers/conversations.ts +1 -3
  101. package/src/daemon/handlers/skills.ts +1 -4
  102. package/src/daemon/lifecycle.ts +0 -21
  103. package/src/daemon/server.ts +0 -2
  104. package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -3
  105. package/src/heartbeat/heartbeat-run-store.ts +1 -23
  106. package/src/heartbeat/heartbeat-service.ts +0 -26
  107. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  108. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  109. package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -15
  110. package/src/ipc/skill-routes/memory.ts +2 -4
  111. package/src/memory/conversation-starter-checkpoints.ts +0 -1
  112. package/src/memory/db-init.ts +0 -2
  113. package/src/memory/job-handlers/conversation-starters.ts +2 -13
  114. package/src/memory/jobs-worker.ts +1 -1
  115. package/src/memory/migrations/index.ts +0 -1
  116. package/src/memory/schema/acp.ts +0 -4
  117. package/src/memory/v2/__tests__/consolidation-job.test.ts +3 -3
  118. package/src/memory/v2/consolidation-job.ts +4 -13
  119. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/assign.test.ts +4 -4
  120. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/live-integration.test.ts +4 -4
  121. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/maintain-job.test.ts +5 -5
  122. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/orchestrate.test.ts +3 -3
  123. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/reconcile.test.ts +2 -2
  124. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/render-injection.test.ts +1 -1
  125. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/router.test.ts +3 -3
  126. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/selection-log-store.test.ts +8 -8
  127. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/selector.test.ts +3 -3
  128. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/shadow-plugin.test.ts +12 -12
  129. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/assign.ts +5 -5
  130. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/capabilities.ts +2 -2
  131. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/maintain-job.ts +8 -8
  132. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/page-content.ts +2 -2
  133. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/provider-blocks.ts +1 -1
  134. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/reconcile.ts +3 -3
  135. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/render-injection.ts +1 -1
  136. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/router.ts +3 -3
  137. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/selection-log-store.ts +4 -4
  138. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/selector.ts +4 -4
  139. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/shadow-plugin.ts +90 -28
  140. package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/tree.ts +1 -1
  141. package/src/plugin-api/index.ts +5 -0
  142. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +93 -0
  143. package/src/plugins/defaults/{memory-v3-shadow → circuit-breaker}/package.json +2 -2
  144. package/src/plugins/defaults/circuit-breaker/register.ts +39 -0
  145. package/src/plugins/defaults/compaction/middlewares/compaction.ts +25 -0
  146. package/src/plugins/defaults/compaction/package.json +1 -1
  147. package/src/plugins/defaults/compaction/register.ts +19 -8
  148. package/src/plugins/defaults/compaction/terminal.ts +73 -0
  149. package/src/plugins/defaults/index.ts +5 -3
  150. package/src/plugins/defaults/{memory-retrieval/injectors.ts → injectors/register.ts} +7 -45
  151. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +7 -11
  152. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  153. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +126 -0
  154. package/src/plugins/defaults/overflow-reduce/package.json +15 -0
  155. package/src/plugins/defaults/overflow-reduce/register.ts +42 -0
  156. package/src/plugins/external-api.ts +2 -2
  157. package/src/plugins/pipeline.ts +293 -6
  158. package/src/plugins/registry.ts +37 -9
  159. package/src/plugins/types.ts +336 -32
  160. package/src/plugins/user-loader.ts +127 -30
  161. package/src/proactive-artifact/aux-message-injector.ts +1 -1
  162. package/src/proactive-artifact/job.test.ts +1 -1
  163. package/src/prompts/__tests__/system-prompt.test.ts +0 -6
  164. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +2 -4
  165. package/src/runtime/__tests__/agent-wake.test.ts +5 -5
  166. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  167. package/src/runtime/agent-wake.ts +3 -0
  168. package/src/runtime/assistant-event-hub.ts +1 -1
  169. package/src/runtime/channel-approvals.ts +1 -1
  170. package/src/runtime/interactive-ui.ts +1 -1
  171. package/src/runtime/routes/__tests__/acp-routes.test.ts +55 -283
  172. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  173. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +4 -5
  174. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -4
  175. package/src/runtime/routes/acp-routes.test.ts +25 -89
  176. package/src/runtime/routes/acp-routes.ts +29 -81
  177. package/src/runtime/routes/approval-routes.ts +1 -1
  178. package/src/runtime/routes/browser-routes.ts +1 -1
  179. package/src/runtime/routes/browser-tabs-routes.ts +10 -6
  180. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  181. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  182. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  183. package/src/runtime/routes/conversation-routes.ts +2 -15
  184. package/src/runtime/routes/conversation-starter-routes.ts +7 -13
  185. package/src/runtime/routes/conversations-import-routes.ts +7 -24
  186. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  187. package/src/runtime/routes/host-cu-routes.ts +1 -1
  188. package/src/runtime/routes/identity-routes.ts +3 -18
  189. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  190. package/src/runtime/routes/memory-v3-routes.ts +6 -16
  191. package/src/runtime/routes/playground/helpers.ts +1 -1
  192. package/src/runtime/routes/surface-conversation-resolver.ts +3 -4
  193. package/src/runtime/routes/work-items-routes.ts +4 -2
  194. package/src/runtime/services/conversation-serializer.ts +1 -1
  195. package/src/signals/cancel.ts +4 -2
  196. package/src/subagent/manager.ts +5 -17
  197. package/src/tools/acp/list-agents.test.ts +1 -7
  198. package/src/tools/acp/spawn.test.ts +55 -158
  199. package/src/tools/acp/spawn.ts +72 -47
  200. package/src/tools/acp/steer.test.ts +8 -105
  201. package/src/tools/acp/steer.ts +17 -48
  202. package/src/tools/apps/executors.ts +8 -13
  203. package/src/tools/filesystem/write.ts +0 -34
  204. package/src/tools/subagent/spawn.ts +4 -2
  205. package/src/tools/ui-surface/definitions.ts +4 -25
  206. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +5 -4
  207. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +45 -69
  208. package/examples/plugins/echo/hooks/post-tool-use.ts +0 -18
  209. package/examples/plugins/echo/hooks/stop.ts +0 -16
  210. package/examples/plugins/echo/hooks/user-prompt-submit.ts +0 -18
  211. package/examples/plugins/echo/src/emit.ts +0 -19
  212. package/src/__tests__/compaction-circuit.test.ts +0 -258
  213. package/src/__tests__/compaction-direct.test.ts +0 -132
  214. package/src/__tests__/conversations-import-system-filter.test.ts +0 -101
  215. package/src/acp/__tests__/agent-process.test.ts +0 -161
  216. package/src/acp/__tests__/helpers/acp-history-db.ts +0 -82
  217. package/src/acp/__tests__/helpers/exec-file-stub.ts +0 -101
  218. package/src/acp/__tests__/session-manager-resume.test.ts +0 -736
  219. package/src/acp/auto-install.test.ts +0 -196
  220. package/src/acp/auto-install.ts +0 -177
  221. package/src/acp/feature-gate.test.ts +0 -48
  222. package/src/acp/feature-gate.ts +0 -34
  223. package/src/acp/resume-hint.ts +0 -25
  224. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +0 -48
  225. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +0 -57
  226. package/src/config/bundled-skills/app-builder/references/SLIDES.md +0 -38
  227. package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -62
  228. package/src/daemon/conversation-registry.ts +0 -159
  229. package/src/daemon/overflow-reduction-loop.ts +0 -230
  230. package/src/memory/migrations/272-acp-session-history-cwd.ts +0 -36
  231. package/src/plugins/defaults/compaction/compact.ts +0 -59
  232. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +0 -14
  233. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +0 -19
  234. package/src/plugins/defaults/memory-v3-shadow/injector.ts +0 -75
  235. package/src/plugins/defaults/memory-v3-shadow/register.ts +0 -26
  236. package/src/tools/acp/context.ts +0 -20
  237. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/capabilities.test.ts +0 -0
  238. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/core.test.ts +0 -0
  239. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/fixtures/eval-turns.json +0 -0
  240. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/fixtures/live-turns.json +0 -0
  241. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/health.test.ts +0 -0
  242. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/needle.test.ts +0 -0
  243. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/provider-blocks.test.ts +0 -0
  244. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/snapshot.test.ts +0 -0
  245. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/tree.test.ts +0 -0
  246. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/types.test.ts +0 -0
  247. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/working-set-eviction.test.ts +0 -0
  248. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/working-set-skeleton.test.ts +0 -0
  249. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/core.ts +0 -0
  250. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/README.md +0 -0
  251. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/assignments.json +0 -0
  252. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/core.json +0 -0
  253. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/leaves/domain-a/topic-x.md +0 -0
  254. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/leaves/domain-a/topic-y.md +0 -0
  255. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/leaves/domain-b/topic-z.md +0 -0
  256. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/health.ts +0 -0
  257. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/llm-retry.ts +0 -0
  258. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/needle.ts +0 -0
  259. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/orchestrate.ts +0 -0
  260. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/snapshot.ts +0 -0
  261. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/types.ts +0 -0
  262. /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/working-set.ts +0 -0
@@ -1,26 +1,19 @@
1
1
  import { afterAll, beforeEach, describe, expect, test } from "bun:test";
2
2
 
3
- import { setOverridesForTesting } from "../__tests__/feature-flag-test-helpers.js";
4
3
  import { installAcpConfigStub } from "./__tests__/helpers/acp-config-stub.js";
5
4
  import { installWhichStub } from "./__tests__/helpers/which-stub.js";
6
- import { ACP_FLAG_KEY } from "./feature-gate.js";
7
5
 
8
6
  const config = await installAcpConfigStub();
9
7
  const which = installWhichStub();
10
8
 
11
9
  afterAll(() => {
12
10
  which.restore();
13
- setOverridesForTesting({});
14
11
  });
15
12
 
16
- const { resolveAcpAgent, listAcpAgents, adapterCommandOf, runsViaBunx } =
17
- await import("./resolve-agent.js");
13
+ const { resolveAcpAgent, listAcpAgents } = await import("./resolve-agent.js");
18
14
 
19
15
  beforeEach(() => {
20
16
  config.setConfig({});
21
- // Default: no flag overrides, so the `acp` flag falls back to its registry
22
- // default (false) and enablement comes from the config stub alone.
23
- setOverridesForTesting({});
24
17
  // Default: every command on PATH so binary preflight passes unless a test
25
18
  // explicitly says otherwise.
26
19
  which.setWhich((cmd) => `/usr/local/bin/${cmd}`);
@@ -31,7 +24,7 @@ beforeEach(() => {
31
24
  // ---------------------------------------------------------------------------
32
25
 
33
26
  describe("resolveAcpAgent", () => {
34
- test("returns acp_disabled when both the feature flag and config.acp.enabled are off", () => {
27
+ test("returns acp_disabled when config.acp.enabled is false", () => {
35
28
  config.setConfig({ enabled: false });
36
29
 
37
30
  const result = resolveAcpAgent("claude");
@@ -40,23 +33,10 @@ describe("resolveAcpAgent", () => {
40
33
  if (result.ok) return;
41
34
  expect(result.reason).toBe("acp_disabled");
42
35
  if (result.reason !== "acp_disabled") return;
43
- expect(result.hint).toContain("ACP Coding Agents");
44
- expect(result.hint).toContain("feature flag");
45
36
  expect(result.hint).toContain("acp.enabled");
46
37
  expect(result.hint).toContain("config.json");
47
38
  });
48
39
 
49
- test("resolution proceeds when the acp feature flag is on and config.acp.enabled is false", () => {
50
- config.setConfig({ enabled: false });
51
- setOverridesForTesting({ [ACP_FLAG_KEY]: true });
52
-
53
- const result = resolveAcpAgent("claude");
54
-
55
- expect(result.ok).toBe(true);
56
- if (!result.ok) return;
57
- expect(result.agent.command).toBe("claude-agent-acp");
58
- });
59
-
60
40
  test("user config wins over default profile", () => {
61
41
  config.setConfig({
62
42
  agents: {
@@ -98,79 +78,6 @@ describe("resolveAcpAgent", () => {
98
78
  expect(result.agent.command).toBe("claude-agent-acp");
99
79
  });
100
80
 
101
- test("falls back to the gemini default profile when no user entry", () => {
102
- config.setConfig({ agents: {} });
103
-
104
- const result = resolveAcpAgent("gemini");
105
-
106
- expect(result.ok).toBe(true);
107
- if (!result.ok) return;
108
- expect(result.agent.command).toBe("gemini");
109
- expect(result.agent.args).toEqual(["--acp"]);
110
- });
111
-
112
- test.each([
113
- ["claude code", "claude-agent-acp"],
114
- ["Claude Code", "claude-agent-acp"],
115
- ["claude-code", "claude-agent-acp"],
116
- ["claude_code", "claude-agent-acp"],
117
- ["codex cli", "codex-acp"],
118
- ["OpenAI Codex", "codex-acp"],
119
- ["gemini cli", "gemini"],
120
- ["Gemini CLI", "gemini"],
121
- ["google gemini", "gemini"],
122
- ])("alias %p resolves to the %p profile", (alias, command) => {
123
- config.setConfig({ agents: {} });
124
-
125
- const result = resolveAcpAgent(alias);
126
-
127
- expect(result.ok).toBe(true);
128
- if (!result.ok) return;
129
- expect(result.agent.command).toBe(command);
130
- });
131
-
132
- test("user config entry literally keyed 'claude code' beats the alias", () => {
133
- config.setConfig({
134
- agents: {
135
- "claude code": {
136
- command: "my-claude-fork",
137
- args: [],
138
- description: "user-defined agent that happens to share an alias",
139
- },
140
- },
141
- });
142
-
143
- const result = resolveAcpAgent("claude code");
144
-
145
- expect(result.ok).toBe(true);
146
- if (!result.ok) return;
147
- expect(result.agent.command).toBe("my-claude-fork");
148
- });
149
-
150
- test("alias re-runs the normal lookup, so a user override of the canonical id wins", () => {
151
- config.setConfig({
152
- agents: {
153
- claude: { command: "my-custom-claude", args: [] },
154
- },
155
- });
156
-
157
- const result = resolveAcpAgent("claude code");
158
-
159
- expect(result.ok).toBe(true);
160
- if (!result.ok) return;
161
- expect(result.agent.command).toBe("my-custom-claude");
162
- });
163
-
164
- test("non-alias unknown id still returns unknown_agent", () => {
165
- config.setConfig({ agents: {} });
166
-
167
- const result = resolveAcpAgent("cursor cli");
168
-
169
- expect(result.ok).toBe(false);
170
- if (result.ok) return;
171
- expect(result.reason).toBe("unknown_agent");
172
- });
173
-
174
81
  test("returns unknown_agent with merged available list when id not found", () => {
175
82
  config.setConfig({
176
83
  agents: {
@@ -185,12 +92,7 @@ describe("resolveAcpAgent", () => {
185
92
  expect(result.reason).toBe("unknown_agent");
186
93
  if (result.reason !== "unknown_agent") return;
187
94
  // Defaults plus user-only ids, deduped, in stable order (defaults first).
188
- expect(result.available).toEqual([
189
- "claude",
190
- "codex",
191
- "gemini",
192
- "user-only",
193
- ]);
95
+ expect(result.available).toEqual(["claude", "codex", "user-only"]);
194
96
  });
195
97
 
196
98
  test("unknown_agent available list contains both defaults when user config is empty", () => {
@@ -204,7 +106,6 @@ describe("resolveAcpAgent", () => {
204
106
  if (result.reason !== "unknown_agent") return;
205
107
  expect(result.available).toContain("claude");
206
108
  expect(result.available).toContain("codex");
207
- expect(result.available).toContain("gemini");
208
109
  });
209
110
 
210
111
  test("returns binary_not_found with the registered install hint", () => {
@@ -299,158 +200,6 @@ describe("resolveAcpAgent", () => {
299
200
  if (!result.ok) return;
300
201
  expect(result.agent.args).toEqual(["--verbose"]);
301
202
  });
302
-
303
- test("direct resolution sets adapterCommand to the command basename", () => {
304
- config.setConfig({
305
- agents: {
306
- custom: { command: "/opt/bin/claude-agent-acp", args: [] },
307
- },
308
- });
309
-
310
- const direct = resolveAcpAgent("claude");
311
- expect(direct.ok).toBe(true);
312
- if (!direct.ok) return;
313
- expect(direct.agent.adapterCommand).toBe("claude-agent-acp");
314
- expect(runsViaBunx(direct.agent)).toBe(false);
315
-
316
- const fullPath = resolveAcpAgent("custom");
317
- expect(fullPath.ok).toBe(true);
318
- if (!fullPath.ok) return;
319
- expect(fullPath.agent.adapterCommand).toBe("claude-agent-acp");
320
- });
321
- });
322
-
323
- // ---------------------------------------------------------------------------
324
- // resolveAcpAgent - bunx fallback for missing binaries
325
- // ---------------------------------------------------------------------------
326
-
327
- describe("resolveAcpAgent - bunx fallback", () => {
328
- test("binary missing + bun present: rewrites to `bun x --bun <pkg>` with adapterCommand preserved", () => {
329
- config.setConfig({ agents: {} });
330
- which.setWhich({ bun: "/usr/local/bin/bun" });
331
-
332
- const result = resolveAcpAgent("claude");
333
-
334
- expect(result.ok).toBe(true);
335
- if (!result.ok) return;
336
- expect(result.agent.command).toBe("bun");
337
- expect(result.agent.args).toEqual([
338
- "x",
339
- "--bun",
340
- "@agentclientprotocol/claude-agent-acp",
341
- ]);
342
- expect(result.agent.adapterCommand).toBe("claude-agent-acp");
343
- expect(runsViaBunx(result.agent)).toBe(true);
344
- expect(adapterCommandOf(result.agent)).toBe("claude-agent-acp");
345
- });
346
-
347
- test("bunx rewrite appends the original args after the package (gemini --acp)", () => {
348
- config.setConfig({ agents: {} });
349
- which.setWhich({ bun: "/usr/local/bin/bun" });
350
-
351
- const result = resolveAcpAgent("gemini");
352
-
353
- expect(result.ok).toBe(true);
354
- if (!result.ok) return;
355
- expect(result.agent.command).toBe("bun");
356
- expect(result.agent.args).toEqual([
357
- "x",
358
- "--bun",
359
- "@google/gemini-cli",
360
- "--acp",
361
- ]);
362
- expect(result.agent.adapterCommand).toBe("gemini");
363
- });
364
-
365
- test("bunx rewrite leaves env unchanged", () => {
366
- config.setConfig({
367
- agents: {
368
- claude: {
369
- command: "claude-agent-acp",
370
- args: [],
371
- env: { KEEP_ME: "yes" },
372
- },
373
- },
374
- });
375
- which.setWhich({ bun: "/usr/local/bin/bun" });
376
-
377
- const result = resolveAcpAgent("claude");
378
-
379
- expect(result.ok).toBe(true);
380
- if (!result.ok) return;
381
- expect(result.agent.command).toBe("bun");
382
- expect(result.agent.env).toEqual({ KEEP_ME: "yes" });
383
- });
384
-
385
- test("bun lookup honors agent.env.PATH override (matches spawn env)", () => {
386
- config.setConfig({
387
- agents: {
388
- claude: {
389
- command: "claude-agent-acp",
390
- args: [],
391
- env: { PATH: "/opt/custom/bin" },
392
- },
393
- },
394
- });
395
- which.setWhich((cmd, options) =>
396
- cmd === "bun" && options?.PATH === "/opt/custom/bin"
397
- ? "/opt/custom/bin/bun"
398
- : null,
399
- );
400
-
401
- const result = resolveAcpAgent("claude");
402
-
403
- expect(result.ok).toBe(true);
404
- if (!result.ok) return;
405
- expect(result.agent.command).toBe("bun");
406
- });
407
-
408
- test("user-config command without a package mapping is NOT rewritten even when bun is present", () => {
409
- config.setConfig({
410
- agents: {
411
- custom: { command: "unknown-binary", args: [] },
412
- },
413
- });
414
- which.setWhich({ bun: "/usr/local/bin/bun" });
415
-
416
- const result = resolveAcpAgent("custom");
417
-
418
- expect(result.ok).toBe(false);
419
- if (result.ok) return;
420
- expect(result.reason).toBe("binary_not_found");
421
- });
422
-
423
- test("binary missing + bun missing: binary_not_found with the npm hint", () => {
424
- config.setConfig({ agents: {} });
425
- which.setWhich({});
426
-
427
- const result = resolveAcpAgent("claude");
428
-
429
- expect(result.ok).toBe(false);
430
- if (result.ok) return;
431
- expect(result.reason).toBe("binary_not_found");
432
- if (result.reason !== "binary_not_found") return;
433
- expect(result.hint).toBe("npm i -g @agentclientprotocol/claude-agent-acp");
434
- });
435
- });
436
-
437
- // ---------------------------------------------------------------------------
438
- // adapterCommandOf - fallback for plain configs
439
- // ---------------------------------------------------------------------------
440
-
441
- describe("adapterCommandOf", () => {
442
- test("falls back to the command basename for configs without adapterCommand", () => {
443
- expect(adapterCommandOf({ command: "/opt/bin/claude-agent-acp" })).toBe(
444
- "claude-agent-acp",
445
- );
446
- expect(adapterCommandOf({ command: "codex-acp" })).toBe("codex-acp");
447
- });
448
-
449
- test("prefers an explicit adapterCommand over the command", () => {
450
- expect(
451
- adapterCommandOf({ command: "bun", adapterCommand: "claude-agent-acp" }),
452
- ).toBe("claude-agent-acp");
453
- });
454
203
  });
455
204
 
456
205
  // ---------------------------------------------------------------------------
@@ -458,7 +207,7 @@ describe("adapterCommandOf", () => {
458
207
  // ---------------------------------------------------------------------------
459
208
 
460
209
  describe("listAcpAgents", () => {
461
- test("returns enabled: false with empty agents when both the flag and config are off", () => {
210
+ test("returns enabled: false with empty agents when ACP is disabled", () => {
462
211
  config.setConfig({ enabled: false });
463
212
 
464
213
  const result = listAcpAgents();
@@ -467,28 +216,14 @@ describe("listAcpAgents", () => {
467
216
  expect(result.agents).toEqual([]);
468
217
  });
469
218
 
470
- test("returns the catalog when the acp feature flag is on and config.acp.enabled is false", () => {
471
- config.setConfig({ enabled: false });
472
- setOverridesForTesting({ [ACP_FLAG_KEY]: true });
473
-
474
- const result = listAcpAgents();
475
-
476
- expect(result.enabled).toBe(true);
477
- expect(result.agents.map((a) => a.id)).toEqual([
478
- "claude",
479
- "codex",
480
- "gemini",
481
- ]);
482
- });
483
-
484
- test("includes all bundled defaults when user config is empty", () => {
219
+ test("includes both bundled defaults when user config is empty", () => {
485
220
  config.setConfig({ agents: {} });
486
221
 
487
222
  const result = listAcpAgents();
488
223
 
489
224
  expect(result.enabled).toBe(true);
490
225
  const ids = result.agents.map((a) => a.id);
491
- expect(ids).toEqual(["claude", "codex", "gemini"]);
226
+ expect(ids).toEqual(["claude", "codex"]);
492
227
  for (const entry of result.agents) {
493
228
  expect(entry.source).toBe("default");
494
229
  expect(entry.available).toBe(true);
@@ -510,7 +245,6 @@ describe("listAcpAgents", () => {
510
245
  which.setWhich({
511
246
  "my-claude": "/usr/bin/my-claude",
512
247
  "codex-acp": "/usr/bin/codex-acp",
513
- gemini: "/usr/bin/gemini",
514
248
  });
515
249
 
516
250
  const result = listAcpAgents();
@@ -523,25 +257,6 @@ describe("listAcpAgents", () => {
523
257
  expect(codex?.source).toBe("default");
524
258
  });
525
259
 
526
- test("missing binaries with bun present are listed available (bunx fallback)", () => {
527
- config.setConfig({ agents: {} });
528
- which.setWhich({ bun: "/usr/local/bin/bun" });
529
-
530
- const result = listAcpAgents();
531
-
532
- for (const entry of result.agents) {
533
- expect(entry.available).toBe(true);
534
- expect(entry.unavailableReason).toBeUndefined();
535
- expect(entry.setupHint).toBeUndefined();
536
- }
537
- // The catalog keeps the canonical adapter commands, not the rewrite.
538
- expect(result.agents.map((a) => a.command)).toEqual([
539
- "claude-agent-acp",
540
- "codex-acp",
541
- "gemini",
542
- ]);
543
- });
544
-
545
260
  test("unavailable agent surfaces install hint derived from DEFAULT_AGENT_NPM_PACKAGES", () => {
546
261
  config.setConfig({ agents: {} });
547
262
  which.setWhich({ "claude-agent-acp": "/usr/bin/claude-agent-acp" });
@@ -554,32 +269,6 @@ describe("listAcpAgents", () => {
554
269
  expect(codex?.setupHint).toBe("npm i -g @zed-industries/codex-acp");
555
270
  });
556
271
 
557
- test("unavailable gemini surfaces the @google/gemini-cli install hint", () => {
558
- config.setConfig({ agents: {} });
559
- which.setWhich({
560
- "claude-agent-acp": "/usr/bin/claude-agent-acp",
561
- "codex-acp": "/usr/bin/codex-acp",
562
- });
563
-
564
- const result = listAcpAgents();
565
-
566
- const gemini = result.agents.find((a) => a.id === "gemini");
567
- expect(gemini?.available).toBe(false);
568
- expect(gemini?.unavailableReason).toBe("'gemini' is not on PATH");
569
- expect(gemini?.setupHint).toBe("npm i -g @google/gemini-cli");
570
- });
571
-
572
- test("aliases are resolution sugar, not catalog entries", () => {
573
- config.setConfig({ agents: {} });
574
-
575
- // "gemini cli" resolves via the alias...
576
- expect(resolveAcpAgent("gemini cli").ok).toBe(true);
577
-
578
- // ...but the catalog lists only canonical ids.
579
- const ids = listAcpAgents().agents.map((a) => a.id);
580
- expect(ids).toEqual(["claude", "codex", "gemini"]);
581
- });
582
-
583
272
  test("user-only agent appended after defaults in stable order", () => {
584
273
  config.setConfig({
585
274
  agents: {
@@ -593,7 +282,6 @@ describe("listAcpAgents", () => {
593
282
  which.setWhich({
594
283
  "claude-agent-acp": "/x",
595
284
  "codex-acp": "/x",
596
- gemini: "/x",
597
285
  "my-binary": "/x",
598
286
  });
599
287
 
@@ -602,10 +290,9 @@ describe("listAcpAgents", () => {
602
290
  expect(result.agents.map((a) => a.id)).toEqual([
603
291
  "claude",
604
292
  "codex",
605
- "gemini",
606
293
  "my-agent",
607
294
  ]);
608
- const userOnly = result.agents[3];
295
+ const userOnly = result.agents[2];
609
296
  expect(userOnly.source).toBe("config");
610
297
  expect(userOnly.description).toBe("user-only");
611
298
  });