@ag-eco/agentplate-cli 0.13.4 → 0.14.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ag-eco/agentplate-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Multi-agent orchestration for AI coding agents — spawn workers in git worktrees via tmux, coordinate through SQLite mail, merge with tiered conflict resolution. Pluggable runtime adapters for Claude Code, Pi, and more.",
|
|
5
5
|
"author": "Jaymin West",
|
|
6
6
|
"license": "MIT",
|
|
@@ -682,6 +682,34 @@ describe("startCoordinator", () => {
|
|
|
682
682
|
expect(cmd).not.toContain("--model opus");
|
|
683
683
|
});
|
|
684
684
|
|
|
685
|
+
test("--runtime overrides the spawned runtime adapter (pi)", async () => {
|
|
686
|
+
const { deps, calls } = makeDeps();
|
|
687
|
+
const originalSleep = Bun.sleep;
|
|
688
|
+
Bun.sleep = (() => Promise.resolve()) as typeof Bun.sleep;
|
|
689
|
+
|
|
690
|
+
try {
|
|
691
|
+
await captureStdout(() =>
|
|
692
|
+
coordinatorCommand(["start", "--no-attach", "--json", "--runtime", "pi"], deps),
|
|
693
|
+
);
|
|
694
|
+
} finally {
|
|
695
|
+
Bun.sleep = originalSleep;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
expect(calls.createSession).toHaveLength(1);
|
|
699
|
+
const cmd = calls.createSession[0]?.command ?? "";
|
|
700
|
+
// Pi's buildSpawnCommand emits `pi --model <provider/model>`; the default
|
|
701
|
+
// claude runtime would not. Proves --runtime took precedence over config.
|
|
702
|
+
expect(cmd).toContain("pi --model");
|
|
703
|
+
expect(cmd).toContain("opus");
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
test("--runtime rejects an unknown adapter with ValidationError", async () => {
|
|
707
|
+
const { deps } = makeDeps();
|
|
708
|
+
await expect(
|
|
709
|
+
coordinatorCommand(["start", "--no-attach", "--runtime", "bogus"], deps),
|
|
710
|
+
).rejects.toThrow(ValidationError);
|
|
711
|
+
});
|
|
712
|
+
|
|
685
713
|
test("--json outputs JSON with expected fields", async () => {
|
|
686
714
|
const { deps } = makeDeps();
|
|
687
715
|
const originalSleep = Bun.sleep;
|
|
@@ -24,7 +24,7 @@ import { jsonOutput } from "../json.ts";
|
|
|
24
24
|
import { printHint, printSuccess, printWarning } from "../logging/color.ts";
|
|
25
25
|
import { createMailClient } from "../mail/client.ts";
|
|
26
26
|
import { createMailStore } from "../mail/store.ts";
|
|
27
|
-
import { getRuntime } from "../runtimes/registry.ts";
|
|
27
|
+
import { getRuntime, getRuntimeNames } from "../runtimes/registry.ts";
|
|
28
28
|
import { openSessionStore } from "../sessions/compat.ts";
|
|
29
29
|
import { createRunStore, createSessionStore } from "../sessions/store.ts";
|
|
30
30
|
import { resolveBackend, trackerCliName } from "../tracker/factory.ts";
|
|
@@ -332,6 +332,13 @@ export interface CoordinatorSessionOptions {
|
|
|
332
332
|
watchdog: boolean;
|
|
333
333
|
monitor: boolean;
|
|
334
334
|
profile?: string;
|
|
335
|
+
/**
|
|
336
|
+
* Runtime adapter override (e.g. "claude", "codex", "pi", "opencode",
|
|
337
|
+
* "gemini"). Takes precedence over config's per-capability and default
|
|
338
|
+
* runtime. When omitted, resolution falls back to
|
|
339
|
+
* runtime.capabilities[capability] → runtime.default → "claude".
|
|
340
|
+
*/
|
|
341
|
+
runtime?: string;
|
|
335
342
|
/** Override coordinator name (default: "coordinator"). */
|
|
336
343
|
coordinatorName?: string;
|
|
337
344
|
/** Generic persistent agent name override. Preferred over coordinatorName for new callers. */
|
|
@@ -386,6 +393,7 @@ export async function startCoordinatorSession(
|
|
|
386
393
|
watchdog: watchdogFlag,
|
|
387
394
|
monitor: monitorFlag,
|
|
388
395
|
profile: profileFlag,
|
|
396
|
+
runtime: runtimeOverride,
|
|
389
397
|
coordinatorName: coordinatorNameOpt,
|
|
390
398
|
agentName: agentNameOpt,
|
|
391
399
|
capability: capabilityOpt,
|
|
@@ -402,6 +410,16 @@ export async function startCoordinatorSession(
|
|
|
402
410
|
const displayName = displayNameOpt ?? COORDINATOR_SPEC.displayName;
|
|
403
411
|
const beaconBuilder = beaconBuilderOpt ?? buildCoordinatorBeacon;
|
|
404
412
|
|
|
413
|
+
// Fail fast on an unknown --runtime before doing any setup work, listing the
|
|
414
|
+
// valid adapters. getRuntime() would also reject it, but later and with a
|
|
415
|
+
// plain Error; this gives an immediate, typed, actionable message.
|
|
416
|
+
if (runtimeOverride && !getRuntimeNames().includes(runtimeOverride)) {
|
|
417
|
+
throw new ValidationError(
|
|
418
|
+
`Unknown runtime "${runtimeOverride}". Available: ${getRuntimeNames().join(", ")}`,
|
|
419
|
+
{ field: "runtime", value: runtimeOverride },
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
405
423
|
if (isRunningAsRoot()) {
|
|
406
424
|
throw new AgentError(
|
|
407
425
|
"Cannot spawn agents as root (UID 0). The claude CLI rejects --permission-mode bypassPermissions when run as root, causing the tmux session to die immediately. Run agentplate as a non-root user.",
|
|
@@ -478,7 +496,7 @@ export async function startCoordinatorSession(
|
|
|
478
496
|
);
|
|
479
497
|
const manifest = await manifestLoader.load();
|
|
480
498
|
const resolvedModel = resolveModel(config, manifest, capability, "opus");
|
|
481
|
-
const runtime = getRuntime(
|
|
499
|
+
const runtime = getRuntime(runtimeOverride, config, capability);
|
|
482
500
|
|
|
483
501
|
// Deploy hooks to the project root so the coordinator gets event logging,
|
|
484
502
|
// mail check --inject, and activity tracking via the standard hook pipeline.
|
|
@@ -875,6 +893,7 @@ async function startPersistentAgent(
|
|
|
875
893
|
watchdog: boolean;
|
|
876
894
|
monitor: boolean;
|
|
877
895
|
profile?: string;
|
|
896
|
+
runtime?: string;
|
|
878
897
|
acceptExistingWatchdog?: boolean;
|
|
879
898
|
},
|
|
880
899
|
deps: CoordinatorDeps = {},
|
|
@@ -1645,7 +1664,7 @@ export function createPersistentAgentCommand(
|
|
|
1645
1664
|
|
|
1646
1665
|
cmd
|
|
1647
1666
|
.command("start")
|
|
1648
|
-
.description(`Start the ${spec.commandName} (spawns
|
|
1667
|
+
.description(`Start the ${spec.commandName} (spawns the configured runtime at project root)`)
|
|
1649
1668
|
.option("--attach", "Always attach to tmux session after start")
|
|
1650
1669
|
.option("--no-attach", "Never attach to tmux session after start")
|
|
1651
1670
|
.option("--watchdog", `Auto-start watchdog daemon with ${spec.commandName}`)
|
|
@@ -1655,6 +1674,10 @@ export function createPersistentAgentCommand(
|
|
|
1655
1674
|
)
|
|
1656
1675
|
.option("--monitor", `Auto-start Tier 2 monitor agent with ${spec.commandName}`)
|
|
1657
1676
|
.option("--profile <name>", "Trellis profile to apply to spawned agents")
|
|
1677
|
+
.option(
|
|
1678
|
+
"--runtime <name>",
|
|
1679
|
+
"Runtime adapter: claude | codex | pi | opencode | gemini (default: config or claude)",
|
|
1680
|
+
)
|
|
1658
1681
|
.option("--json", "Output as JSON")
|
|
1659
1682
|
.action(
|
|
1660
1683
|
async (opts: {
|
|
@@ -1664,6 +1687,7 @@ export function createPersistentAgentCommand(
|
|
|
1664
1687
|
monitor?: boolean;
|
|
1665
1688
|
json?: boolean;
|
|
1666
1689
|
profile?: string;
|
|
1690
|
+
runtime?: string;
|
|
1667
1691
|
}) => {
|
|
1668
1692
|
// opts.attach = true if --attach, false if --no-attach, undefined if neither
|
|
1669
1693
|
const shouldAttach = opts.attach !== undefined ? opts.attach : !!process.stdout.isTTY;
|
|
@@ -1676,6 +1700,7 @@ export function createPersistentAgentCommand(
|
|
|
1676
1700
|
acceptExistingWatchdog: opts.acceptExistingWatchdog ?? false,
|
|
1677
1701
|
monitor: opts.monitor ?? false,
|
|
1678
1702
|
profile: opts.profile,
|
|
1703
|
+
runtime: opts.runtime,
|
|
1679
1704
|
},
|
|
1680
1705
|
deps,
|
|
1681
1706
|
);
|
|
@@ -7,7 +7,7 @@ import { CursorRuntime } from "./cursor.ts";
|
|
|
7
7
|
import { GeminiRuntime } from "./gemini.ts";
|
|
8
8
|
import { OpenCodeRuntime } from "./opencode.ts";
|
|
9
9
|
import { PiRuntime } from "./pi.ts";
|
|
10
|
-
import { getRuntime } from "./registry.ts";
|
|
10
|
+
import { getRuntime, getRuntimeNames } from "./registry.ts";
|
|
11
11
|
|
|
12
12
|
describe("getRuntime", () => {
|
|
13
13
|
it("returns a ClaudeRuntime by default (no args)", () => {
|
|
@@ -194,3 +194,18 @@ describe("getRuntime", () => {
|
|
|
194
194
|
});
|
|
195
195
|
});
|
|
196
196
|
});
|
|
197
|
+
|
|
198
|
+
describe("getRuntimeNames", () => {
|
|
199
|
+
it("lists every registered adapter, including the coordinator-supported set", () => {
|
|
200
|
+
const names = getRuntimeNames();
|
|
201
|
+
for (const expected of ["claude", "codex", "pi", "opencode", "gemini"]) {
|
|
202
|
+
expect(names).toContain(expected);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("returns names that all resolve via getRuntime", () => {
|
|
207
|
+
for (const name of getRuntimeNames()) {
|
|
208
|
+
expect(getRuntime(name).id).toBe(name);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
package/src/runtimes/registry.ts
CHANGED
|
@@ -55,6 +55,18 @@ export function getAllRuntimes(): AgentRuntime[] {
|
|
|
55
55
|
];
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Names of all registered runtime adapters, in registration order.
|
|
60
|
+
*
|
|
61
|
+
* Used to validate a user-supplied `--runtime <name>` before resolution so the
|
|
62
|
+
* error can list the valid choices (see `ap coordinator start --runtime`).
|
|
63
|
+
*
|
|
64
|
+
* @returns Array of runtime names (e.g. "claude", "codex", "pi").
|
|
65
|
+
*/
|
|
66
|
+
export function getRuntimeNames(): string[] {
|
|
67
|
+
return [...runtimes.keys()];
|
|
68
|
+
}
|
|
69
|
+
|
|
58
70
|
/**
|
|
59
71
|
* Resolve a runtime adapter by name.
|
|
60
72
|
*
|
package/src/version.ts
CHANGED