@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.
- package/bun.lock +2 -2
- package/docs/plugins.md +832 -0
- package/examples/plugins/echo/README.md +60 -61
- package/examples/plugins/echo/package.json +2 -1
- package/examples/plugins/echo/register.ts +143 -0
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +6 -7
- package/openapi.yaml +5 -15
- package/package.json +2 -2
- package/src/__tests__/agent-loop-exit-reason.test.ts +56 -3
- package/src/__tests__/anthropic-provider.test.ts +1 -1
- package/src/__tests__/app-control-flow.test.ts +1 -1
- package/src/__tests__/app-dir-path-guard.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +1 -4
- package/src/__tests__/channel-approval-routes.test.ts +1 -1
- package/src/__tests__/channel-approvals.test.ts +1 -1
- package/src/__tests__/circuit-breaker-pipeline.test.ts +405 -0
- package/src/__tests__/compaction-pipeline.test.ts +210 -0
- package/src/__tests__/compaction-timeout-recovery.test.ts +251 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +7 -3
- package/src/__tests__/conversation-agent-loop.test.ts +39 -42
- package/src/__tests__/conversation-clean-command.test.ts +2 -5
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -4
- package/src/__tests__/conversation-runtime-assembly.test.ts +71 -140
- package/src/__tests__/conversation-runtime-workspace.test.ts +27 -108
- package/src/__tests__/conversation-starter-routes.test.ts +6 -14
- package/src/__tests__/conversation-workspace-cache-state.test.ts +16 -17
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -61
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -7
- package/src/__tests__/db-acp-history.test.ts +0 -101
- package/src/__tests__/dynamic-page-surface.test.ts +0 -31
- package/src/__tests__/file-write-tool.test.ts +0 -63
- package/src/__tests__/gateway-only-guard.test.ts +2 -12
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +4 -2
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -1
- package/src/__tests__/heartbeat-service.test.ts +0 -1
- 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__/injector-background-turn.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +6 -34
- package/src/__tests__/injector-disk-pressure.test.ts +34 -77
- package/src/__tests__/injector-document-comments.test.ts +1 -1
- package/src/__tests__/list-messages-hidden-metadata.test.ts +0 -38
- package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
- package/src/__tests__/{overflow-reduction-loop.test.ts → overflow-reduce-pipeline.test.ts} +284 -64
- package/src/__tests__/pipeline-runner.test.ts +554 -0
- package/src/__tests__/plugin-api-shim.test.ts +6 -3
- package/src/__tests__/plugin-bootstrap.test.ts +23 -12
- package/src/__tests__/plugin-registry.test.ts +49 -3
- package/src/__tests__/plugin-types.test.ts +70 -0
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +1 -4
- package/src/__tests__/skill-feature-flags-integration.test.ts +0 -33
- package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
- package/src/__tests__/subagent-fork-notifications.test.ts +3 -1
- package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
- package/src/__tests__/subagent-manager-notify.test.ts +3 -1
- package/src/__tests__/subagent-notify-parent.test.ts +3 -1
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +286 -54
- package/src/acp/__tests__/client-handler.test.ts +0 -40
- package/src/acp/__tests__/prepare-agent-env.test.ts +0 -137
- package/src/acp/__tests__/session-manager-persistence.test.ts +28 -95
- package/src/acp/agent-process.ts +1 -61
- package/src/acp/client-handler.ts +0 -31
- package/src/acp/prepare-agent-env.ts +29 -83
- package/src/acp/resolve-agent.test.ts +7 -320
- package/src/acp/resolve-agent.ts +18 -182
- package/src/acp/session-manager.ts +73 -495
- package/src/acp/types.ts +0 -8
- package/src/agent/compaction-circuit.ts +102 -60
- package/src/agent/loop.ts +59 -32
- package/src/api/responses/conversation-message.ts +1 -7
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/background-wake/next-wake.ts +0 -1
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/acp-defaults.test.ts +0 -10
- package/src/config/acp-defaults.ts +0 -6
- package/src/config/bundled-skills/acp/SKILL.md +31 -83
- package/src/config/bundled-skills/acp/TOOLS.json +4 -4
- package/src/config/bundled-skills/app-builder/SKILL.md +381 -224
- package/src/config/bundled-skills/app-builder/TOOLS.json +0 -29
- package/src/config/bundled-skills/document-editor/SKILL.md +23 -28
- package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
- package/src/config/bundled-tool-registry.ts +0 -2
- package/src/config/feature-flag-registry.json +5 -14
- package/src/config/schemas/heartbeat.ts +0 -9
- package/src/context/strip-injections.ts +2 -8
- package/src/context/window-manager.ts +1 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +11 -0
- package/src/daemon/conversation-agent-loop.ts +279 -62
- package/src/daemon/conversation-runtime-assembly.ts +69 -106
- package/src/daemon/conversation-store.ts +90 -9
- package/src/daemon/conversation-workspace.ts +0 -17
- package/src/daemon/conversation.ts +6 -0
- package/src/daemon/external-plugins-bootstrap.ts +11 -11
- package/src/daemon/handlers/conversations.ts +1 -3
- package/src/daemon/handlers/skills.ts +1 -4
- package/src/daemon/lifecycle.ts +0 -21
- package/src/daemon/server.ts +0 -2
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -3
- package/src/heartbeat/heartbeat-run-store.ts +1 -23
- package/src/heartbeat/heartbeat-service.ts +0 -26
- 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 +0 -15
- package/src/ipc/skill-routes/memory.ts +2 -4
- package/src/memory/conversation-starter-checkpoints.ts +0 -1
- package/src/memory/db-init.ts +0 -2
- package/src/memory/job-handlers/conversation-starters.ts +2 -13
- package/src/memory/jobs-worker.ts +1 -1
- package/src/memory/migrations/index.ts +0 -1
- package/src/memory/schema/acp.ts +0 -4
- package/src/memory/v2/__tests__/consolidation-job.test.ts +3 -3
- package/src/memory/v2/consolidation-job.ts +4 -13
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/assign.test.ts +4 -4
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/live-integration.test.ts +4 -4
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/maintain-job.test.ts +5 -5
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/orchestrate.test.ts +3 -3
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/reconcile.test.ts +2 -2
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/render-injection.test.ts +1 -1
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/router.test.ts +3 -3
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/selection-log-store.test.ts +8 -8
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/selector.test.ts +3 -3
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/shadow-plugin.test.ts +12 -12
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/assign.ts +5 -5
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/capabilities.ts +2 -2
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/maintain-job.ts +8 -8
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/page-content.ts +2 -2
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/provider-blocks.ts +1 -1
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/reconcile.ts +3 -3
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/render-injection.ts +1 -1
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/router.ts +3 -3
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/selection-log-store.ts +4 -4
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/selector.ts +4 -4
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/shadow-plugin.ts +90 -28
- package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/tree.ts +1 -1
- package/src/plugin-api/index.ts +5 -0
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +93 -0
- package/src/plugins/defaults/{memory-v3-shadow → circuit-breaker}/package.json +2 -2
- package/src/plugins/defaults/circuit-breaker/register.ts +39 -0
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +25 -0
- package/src/plugins/defaults/compaction/package.json +1 -1
- package/src/plugins/defaults/compaction/register.ts +19 -8
- package/src/plugins/defaults/compaction/terminal.ts +73 -0
- package/src/plugins/defaults/index.ts +5 -3
- package/src/plugins/defaults/{memory-retrieval/injectors.ts → injectors/register.ts} +7 -45
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +7 -11
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
- package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +126 -0
- package/src/plugins/defaults/overflow-reduce/package.json +15 -0
- package/src/plugins/defaults/overflow-reduce/register.ts +42 -0
- package/src/plugins/external-api.ts +2 -2
- package/src/plugins/pipeline.ts +293 -6
- package/src/plugins/registry.ts +37 -9
- package/src/plugins/types.ts +336 -32
- package/src/plugins/user-loader.ts +127 -30
- package/src/proactive-artifact/aux-message-injector.ts +1 -1
- package/src/proactive-artifact/job.test.ts +1 -1
- package/src/prompts/__tests__/system-prompt.test.ts +0 -6
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +2 -4
- package/src/runtime/__tests__/agent-wake.test.ts +5 -5
- package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
- package/src/runtime/agent-wake.ts +3 -0
- 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 +55 -283
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +4 -5
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -4
- package/src/runtime/routes/acp-routes.test.ts +25 -89
- package/src/runtime/routes/acp-routes.ts +29 -81
- 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 +10 -6
- 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 +2 -15
- package/src/runtime/routes/conversation-starter-routes.ts +7 -13
- package/src/runtime/routes/conversations-import-routes.ts +7 -24
- 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 +3 -18
- package/src/runtime/routes/inbound-message-handler.ts +1 -1
- package/src/runtime/routes/memory-v3-routes.ts +6 -16
- package/src/runtime/routes/playground/helpers.ts +1 -1
- package/src/runtime/routes/surface-conversation-resolver.ts +3 -4
- package/src/runtime/routes/work-items-routes.ts +4 -2
- package/src/runtime/services/conversation-serializer.ts +1 -1
- package/src/signals/cancel.ts +4 -2
- package/src/subagent/manager.ts +5 -17
- package/src/tools/acp/list-agents.test.ts +1 -7
- package/src/tools/acp/spawn.test.ts +55 -158
- package/src/tools/acp/spawn.ts +72 -47
- package/src/tools/acp/steer.test.ts +8 -105
- package/src/tools/acp/steer.ts +17 -48
- package/src/tools/apps/executors.ts +8 -13
- package/src/tools/filesystem/write.ts +0 -34
- package/src/tools/subagent/spawn.ts +4 -2
- package/src/tools/ui-surface/definitions.ts +4 -25
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +5 -4
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +45 -69
- package/examples/plugins/echo/hooks/post-tool-use.ts +0 -18
- package/examples/plugins/echo/hooks/stop.ts +0 -16
- package/examples/plugins/echo/hooks/user-prompt-submit.ts +0 -18
- package/examples/plugins/echo/src/emit.ts +0 -19
- package/src/__tests__/compaction-circuit.test.ts +0 -258
- package/src/__tests__/compaction-direct.test.ts +0 -132
- package/src/__tests__/conversations-import-system-filter.test.ts +0 -101
- package/src/acp/__tests__/agent-process.test.ts +0 -161
- package/src/acp/__tests__/helpers/acp-history-db.ts +0 -82
- package/src/acp/__tests__/helpers/exec-file-stub.ts +0 -101
- package/src/acp/__tests__/session-manager-resume.test.ts +0 -736
- package/src/acp/auto-install.test.ts +0 -196
- package/src/acp/auto-install.ts +0 -177
- package/src/acp/feature-gate.test.ts +0 -48
- package/src/acp/feature-gate.ts +0 -34
- package/src/acp/resume-hint.ts +0 -25
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +0 -48
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +0 -57
- package/src/config/bundled-skills/app-builder/references/SLIDES.md +0 -38
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -62
- package/src/daemon/conversation-registry.ts +0 -159
- package/src/daemon/overflow-reduction-loop.ts +0 -230
- package/src/memory/migrations/272-acp-session-history-cwd.ts +0 -36
- package/src/plugins/defaults/compaction/compact.ts +0 -59
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +0 -14
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +0 -19
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +0 -75
- package/src/plugins/defaults/memory-v3-shadow/register.ts +0 -26
- package/src/tools/acp/context.ts +0 -20
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/capabilities.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/core.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/fixtures/eval-turns.json +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/fixtures/live-turns.json +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/health.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/needle.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/provider-blocks.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/snapshot.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/tree.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/types.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/working-set-eviction.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/__tests__/working-set-skeleton.test.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/core.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/README.md +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/assignments.json +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/core.json +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/leaves/domain-a/topic-x.md +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/leaves/domain-a/topic-y.md +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/data/leaves/domain-b/topic-z.md +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/health.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/llm-retry.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/needle.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/orchestrate.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/snapshot.ts +0 -0
- /package/src/{plugins/defaults/memory-v3-shadow → memory/v3}/types.ts +0 -0
- /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
|
|
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
|
|
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
|
|
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("
|
|
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"
|
|
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[
|
|
295
|
+
const userOnly = result.agents[2];
|
|
609
296
|
expect(userOnly.source).toBe("config");
|
|
610
297
|
expect(userOnly.description).toBe("user-only");
|
|
611
298
|
});
|