herdctl 1.3.10 → 1.4.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/dist/commands/__tests__/agent.test.d.ts +2 -0
- package/dist/commands/__tests__/agent.test.d.ts.map +1 -0
- package/dist/commands/__tests__/agent.test.js +1461 -0
- package/dist/commands/__tests__/agent.test.js.map +1 -0
- package/dist/commands/__tests__/init-agent.test.d.ts +2 -0
- package/dist/commands/__tests__/init-agent.test.d.ts.map +1 -0
- package/dist/commands/__tests__/init-agent.test.js +363 -0
- package/dist/commands/__tests__/init-agent.test.js.map +1 -0
- package/dist/commands/__tests__/init-fleet.test.d.ts +2 -0
- package/dist/commands/__tests__/init-fleet.test.d.ts.map +1 -0
- package/dist/commands/__tests__/init-fleet.test.js +154 -0
- package/dist/commands/__tests__/init-fleet.test.js.map +1 -0
- package/dist/commands/__tests__/init.test.js +43 -213
- package/dist/commands/__tests__/init.test.js.map +1 -1
- package/dist/commands/agent.d.ts +143 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +845 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/init-agent.d.ts +22 -0
- package/dist/commands/init-agent.d.ts.map +1 -0
- package/dist/commands/init-agent.js +273 -0
- package/dist/commands/init-agent.js.map +1 -0
- package/dist/commands/init-fleet.d.ts +13 -0
- package/dist/commands/init-fleet.d.ts.map +1 -0
- package/dist/commands/init-fleet.js +91 -0
- package/dist/commands/init-fleet.js.map +1 -0
- package/dist/commands/init-utils.d.ts +8 -0
- package/dist/commands/init-utils.d.ts.map +1 -0
- package/dist/commands/init-utils.js +24 -0
- package/dist/commands/init-utils.js.map +1 -0
- package/dist/commands/init.d.ts +9 -9
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +30 -289
- package/dist/commands/init.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +131 -8
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { initFleetCommand } from "../init-fleet.js";
|
|
6
|
+
function createTempDir() {
|
|
7
|
+
const baseDir = path.join(tmpdir(), `herdctl-fleet-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
8
|
+
fs.mkdirSync(baseDir, { recursive: true });
|
|
9
|
+
return fs.realpathSync(baseDir);
|
|
10
|
+
}
|
|
11
|
+
function cleanupTempDir(dir) {
|
|
12
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
13
|
+
}
|
|
14
|
+
describe("initFleetCommand", () => {
|
|
15
|
+
let tempDir;
|
|
16
|
+
let originalCwd;
|
|
17
|
+
let consoleLogs;
|
|
18
|
+
let consoleErrors;
|
|
19
|
+
let originalConsoleLog;
|
|
20
|
+
let originalConsoleError;
|
|
21
|
+
let originalProcessExit;
|
|
22
|
+
let exitCode;
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
tempDir = createTempDir();
|
|
25
|
+
originalCwd = process.cwd();
|
|
26
|
+
process.chdir(tempDir);
|
|
27
|
+
consoleLogs = [];
|
|
28
|
+
consoleErrors = [];
|
|
29
|
+
originalConsoleLog = console.log;
|
|
30
|
+
originalConsoleError = console.error;
|
|
31
|
+
console.log = (...args) => consoleLogs.push(args.join(" "));
|
|
32
|
+
console.error = (...args) => consoleErrors.push(args.join(" "));
|
|
33
|
+
exitCode = undefined;
|
|
34
|
+
originalProcessExit = process.exit;
|
|
35
|
+
process.exit = ((code) => {
|
|
36
|
+
exitCode = code ?? 0;
|
|
37
|
+
throw new Error(`process.exit(${code})`);
|
|
38
|
+
});
|
|
39
|
+
vi.clearAllMocks();
|
|
40
|
+
});
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
process.chdir(originalCwd);
|
|
43
|
+
cleanupTempDir(tempDir);
|
|
44
|
+
console.log = originalConsoleLog;
|
|
45
|
+
console.error = originalConsoleError;
|
|
46
|
+
process.exit = originalProcessExit;
|
|
47
|
+
});
|
|
48
|
+
describe("file creation", () => {
|
|
49
|
+
it("creates herdctl.yaml with fleet name from --name", async () => {
|
|
50
|
+
await initFleetCommand({ name: "my-fleet" });
|
|
51
|
+
const configPath = path.join(tempDir, "herdctl.yaml");
|
|
52
|
+
expect(fs.existsSync(configPath)).toBe(true);
|
|
53
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
54
|
+
expect(content).toContain("version: 1");
|
|
55
|
+
expect(content).toContain("name: my-fleet");
|
|
56
|
+
});
|
|
57
|
+
it("creates herdctl.yaml with directory basename when no --name", async () => {
|
|
58
|
+
await initFleetCommand({});
|
|
59
|
+
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
60
|
+
expect(content).toContain(`name: ${path.basename(tempDir)}`);
|
|
61
|
+
});
|
|
62
|
+
it("does NOT create agents/ directory", async () => {
|
|
63
|
+
await initFleetCommand({});
|
|
64
|
+
const agentsDir = path.join(tempDir, "agents");
|
|
65
|
+
expect(fs.existsSync(agentsDir)).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
it("creates .herdctl/ directory", async () => {
|
|
68
|
+
await initFleetCommand({});
|
|
69
|
+
const stateDir = path.join(tempDir, ".herdctl");
|
|
70
|
+
expect(fs.existsSync(stateDir)).toBe(true);
|
|
71
|
+
expect(fs.statSync(stateDir).isDirectory()).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe("template content", () => {
|
|
75
|
+
it("includes version: 1", async () => {
|
|
76
|
+
await initFleetCommand({});
|
|
77
|
+
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
78
|
+
expect(content).toContain("version: 1");
|
|
79
|
+
});
|
|
80
|
+
it("includes commented-out defaults section", async () => {
|
|
81
|
+
await initFleetCommand({});
|
|
82
|
+
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
83
|
+
expect(content).toContain("# defaults:");
|
|
84
|
+
expect(content).toContain("# permission_mode: default");
|
|
85
|
+
});
|
|
86
|
+
it("enables web dashboard by default", async () => {
|
|
87
|
+
await initFleetCommand({});
|
|
88
|
+
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
89
|
+
expect(content).toContain("web:");
|
|
90
|
+
expect(content).toContain("enabled: true");
|
|
91
|
+
expect(content).toContain("port: 3232");
|
|
92
|
+
});
|
|
93
|
+
it("includes commented-out fleets section", async () => {
|
|
94
|
+
await initFleetCommand({});
|
|
95
|
+
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
96
|
+
expect(content).toContain("# fleets:");
|
|
97
|
+
});
|
|
98
|
+
it("includes empty agents array with init agent hint", async () => {
|
|
99
|
+
await initFleetCommand({});
|
|
100
|
+
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
101
|
+
expect(content).toContain("agents: []");
|
|
102
|
+
expect(content).toContain("herdctl init agent");
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe("error handling", () => {
|
|
106
|
+
it("errors if herdctl.yaml already exists", async () => {
|
|
107
|
+
fs.writeFileSync(path.join(tempDir, "herdctl.yaml"), "version: 1");
|
|
108
|
+
await initFleetCommand({});
|
|
109
|
+
expect(process.exitCode).toBe(1);
|
|
110
|
+
});
|
|
111
|
+
it("overwrites with --force", async () => {
|
|
112
|
+
fs.writeFileSync(path.join(tempDir, "herdctl.yaml"), "version: 1\nfleet:\n name: old-fleet");
|
|
113
|
+
await initFleetCommand({ force: true, name: "new-fleet" });
|
|
114
|
+
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
115
|
+
expect(content).toContain("name: new-fleet");
|
|
116
|
+
expect(content).not.toContain("old-fleet");
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe(".gitignore handling", () => {
|
|
120
|
+
it("updates existing .gitignore to include .herdctl/", async () => {
|
|
121
|
+
fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules/\n");
|
|
122
|
+
await initFleetCommand({});
|
|
123
|
+
const gitignore = fs.readFileSync(path.join(tempDir, ".gitignore"), "utf-8");
|
|
124
|
+
expect(gitignore).toContain(".herdctl/");
|
|
125
|
+
expect(gitignore).toContain("node_modules/");
|
|
126
|
+
});
|
|
127
|
+
it("does not duplicate .herdctl/ in .gitignore", async () => {
|
|
128
|
+
fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules/\n.herdctl/\n");
|
|
129
|
+
await initFleetCommand({});
|
|
130
|
+
const gitignore = fs.readFileSync(path.join(tempDir, ".gitignore"), "utf-8");
|
|
131
|
+
const count = (gitignore.match(/\.herdctl\//g) || []).length;
|
|
132
|
+
expect(count).toBe(1);
|
|
133
|
+
});
|
|
134
|
+
it("does not create .gitignore if it does not exist", async () => {
|
|
135
|
+
await initFleetCommand({});
|
|
136
|
+
expect(fs.existsSync(path.join(tempDir, ".gitignore"))).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe("output", () => {
|
|
140
|
+
it("prints success message", async () => {
|
|
141
|
+
await initFleetCommand({});
|
|
142
|
+
expect(consoleLogs.some((log) => log.includes("Initialized herdctl fleet"))).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
it("prints next steps including herdctl init agent", async () => {
|
|
145
|
+
await initFleetCommand({});
|
|
146
|
+
expect(consoleLogs.some((log) => log.includes("herdctl init agent"))).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
it("prints herdctl start as next step", async () => {
|
|
149
|
+
await initFleetCommand({});
|
|
150
|
+
expect(consoleLogs.some((log) => log.includes("herdctl start"))).toBe(true);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
//# sourceMappingURL=init-fleet.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-fleet.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/init-fleet.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,248 +1,78 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import * as path from "node:path";
|
|
4
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
-
import { initCommand } from "../init.js";
|
|
6
2
|
// Mock @inquirer/prompts
|
|
7
3
|
vi.mock("@inquirer/prompts", () => ({
|
|
8
4
|
input: vi.fn(),
|
|
9
5
|
confirm: vi.fn(),
|
|
10
6
|
select: vi.fn(),
|
|
11
7
|
}));
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
// Mock subcommands
|
|
9
|
+
vi.mock("../init-fleet.js", () => ({
|
|
10
|
+
initFleetCommand: vi.fn(),
|
|
11
|
+
}));
|
|
12
|
+
vi.mock("../init-agent.js", () => ({
|
|
13
|
+
initAgentCommand: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
import { select } from "@inquirer/prompts";
|
|
16
|
+
import { initRouterAction } from "../init.js";
|
|
17
|
+
import { initAgentCommand } from "../init-agent.js";
|
|
18
|
+
import { initFleetCommand } from "../init-fleet.js";
|
|
15
19
|
const mockedSelect = vi.mocked(select);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
fs.mkdirSync(baseDir, { recursive: true });
|
|
20
|
-
return fs.realpathSync(baseDir);
|
|
21
|
-
}
|
|
22
|
-
// Helper to clean up temp directory
|
|
23
|
-
function cleanupTempDir(dir) {
|
|
24
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
25
|
-
}
|
|
26
|
-
describe("initCommand", () => {
|
|
27
|
-
let tempDir;
|
|
28
|
-
let originalCwd;
|
|
29
|
-
let consoleLogs;
|
|
20
|
+
const mockedInitFleet = vi.mocked(initFleetCommand);
|
|
21
|
+
const mockedInitAgent = vi.mocked(initAgentCommand);
|
|
22
|
+
describe("initRouterAction", () => {
|
|
30
23
|
let consoleErrors;
|
|
31
|
-
let originalConsoleLog;
|
|
32
24
|
let originalConsoleError;
|
|
33
25
|
let originalProcessExit;
|
|
34
26
|
let exitCode;
|
|
35
27
|
beforeEach(() => {
|
|
36
|
-
tempDir = createTempDir();
|
|
37
|
-
originalCwd = process.cwd();
|
|
38
|
-
process.chdir(tempDir);
|
|
39
|
-
// Capture console output
|
|
40
|
-
consoleLogs = [];
|
|
41
28
|
consoleErrors = [];
|
|
42
|
-
originalConsoleLog = console.log;
|
|
43
29
|
originalConsoleError = console.error;
|
|
44
|
-
console.log = (...args) => consoleLogs.push(args.join(" "));
|
|
45
30
|
console.error = (...args) => consoleErrors.push(args.join(" "));
|
|
46
|
-
// Mock process.exit
|
|
47
31
|
exitCode = undefined;
|
|
48
32
|
originalProcessExit = process.exit;
|
|
49
33
|
process.exit = ((code) => {
|
|
50
34
|
exitCode = code ?? 0;
|
|
51
35
|
throw new Error(`process.exit(${code})`);
|
|
52
36
|
});
|
|
53
|
-
// Reset mocks
|
|
54
37
|
vi.clearAllMocks();
|
|
55
38
|
});
|
|
56
39
|
afterEach(() => {
|
|
57
|
-
process.chdir(originalCwd);
|
|
58
|
-
cleanupTempDir(tempDir);
|
|
59
|
-
console.log = originalConsoleLog;
|
|
60
40
|
console.error = originalConsoleError;
|
|
61
41
|
process.exit = originalProcessExit;
|
|
62
42
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
expect(content).toContain(`name: ${path.basename(tempDir)}`);
|
|
71
|
-
});
|
|
72
|
-
it("creates agents/ directory", async () => {
|
|
73
|
-
await initCommand({ yes: true });
|
|
74
|
-
const agentsDir = path.join(tempDir, "agents");
|
|
75
|
-
expect(fs.existsSync(agentsDir)).toBe(true);
|
|
76
|
-
expect(fs.statSync(agentsDir).isDirectory()).toBe(true);
|
|
77
|
-
});
|
|
78
|
-
it("creates .herdctl/ directory", async () => {
|
|
79
|
-
await initCommand({ yes: true });
|
|
80
|
-
const stateDir = path.join(tempDir, ".herdctl");
|
|
81
|
-
expect(fs.existsSync(stateDir)).toBe(true);
|
|
82
|
-
expect(fs.statSync(stateDir).isDirectory()).toBe(true);
|
|
83
|
-
});
|
|
84
|
-
it("creates example agent file with simple template", async () => {
|
|
85
|
-
await initCommand({ yes: true });
|
|
86
|
-
const agentPath = path.join(tempDir, "agents", "example-agent.yaml");
|
|
87
|
-
expect(fs.existsSync(agentPath)).toBe(true);
|
|
88
|
-
const content = fs.readFileSync(agentPath, "utf-8");
|
|
89
|
-
expect(content).toContain("name: example-agent");
|
|
90
|
-
expect(content).toContain("schedules:");
|
|
91
|
-
});
|
|
92
|
-
it("uses provided --name option", async () => {
|
|
93
|
-
await initCommand({ yes: true, name: "my-fleet" });
|
|
94
|
-
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
95
|
-
expect(content).toContain("name: my-fleet");
|
|
96
|
-
});
|
|
97
|
-
it("shows success message and next steps", async () => {
|
|
98
|
-
await initCommand({ yes: true });
|
|
99
|
-
expect(consoleLogs.some((log) => log.includes("Initialized herdctl project"))).toBe(true);
|
|
100
|
-
expect(consoleLogs.some((log) => log.includes("Next steps"))).toBe(true);
|
|
101
|
-
expect(consoleLogs.some((log) => log.includes("herdctl start"))).toBe(true);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
describe("template selection", () => {
|
|
105
|
-
it("uses simple template by default", async () => {
|
|
106
|
-
await initCommand({ yes: true });
|
|
107
|
-
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
108
|
-
expect(content).toContain("defaults:");
|
|
109
|
-
expect(content).toContain("max_turns: 50");
|
|
110
|
-
expect(content).not.toContain("model:"); // model should not be set - SDK uses its own default
|
|
111
|
-
const agentPath = path.join(tempDir, "agents", "example-agent.yaml");
|
|
112
|
-
expect(fs.existsSync(agentPath)).toBe(true);
|
|
113
|
-
});
|
|
114
|
-
it("uses quickstart template with --example quickstart", async () => {
|
|
115
|
-
await initCommand({ yes: true, example: "quickstart" });
|
|
116
|
-
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
117
|
-
expect(content).not.toContain("defaults:");
|
|
118
|
-
const agentPath = path.join(tempDir, "agents", "hello-agent.yaml");
|
|
119
|
-
expect(fs.existsSync(agentPath)).toBe(true);
|
|
120
|
-
const agentContent = fs.readFileSync(agentPath, "utf-8");
|
|
121
|
-
expect(agentContent).toContain("name: hello-agent");
|
|
122
|
-
expect(agentContent).toContain("interval: 30s");
|
|
123
|
-
});
|
|
124
|
-
it("uses github template with --example github", async () => {
|
|
125
|
-
await initCommand({ yes: true, example: "github" });
|
|
126
|
-
const agentPath = path.join(tempDir, "agents", "github-agent.yaml");
|
|
127
|
-
expect(fs.existsSync(agentPath)).toBe(true);
|
|
128
|
-
const agentContent = fs.readFileSync(agentPath, "utf-8");
|
|
129
|
-
expect(agentContent).toContain("name: github-agent");
|
|
130
|
-
expect(agentContent).toContain("github_issues");
|
|
131
|
-
});
|
|
132
|
-
it("exits with error for unknown template", async () => {
|
|
133
|
-
await expect(initCommand({ yes: true, example: "nonexistent" })).rejects.toThrow("process.exit");
|
|
134
|
-
expect(exitCode).toBe(1);
|
|
135
|
-
expect(consoleErrors.some((e) => e.includes("Unknown example template"))).toBe(true);
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
describe("error handling", () => {
|
|
139
|
-
it("exits with error if herdctl.yaml already exists", async () => {
|
|
140
|
-
fs.writeFileSync(path.join(tempDir, "herdctl.yaml"), "version: 1");
|
|
141
|
-
await expect(initCommand({ yes: true })).rejects.toThrow("process.exit");
|
|
142
|
-
expect(exitCode).toBe(1);
|
|
143
|
-
expect(consoleErrors.some((e) => e.includes("herdctl.yaml already exists"))).toBe(true);
|
|
144
|
-
});
|
|
145
|
-
it("overwrites existing config with --force", async () => {
|
|
146
|
-
fs.writeFileSync(path.join(tempDir, "herdctl.yaml"), "version: 1\nfleet:\n name: old-fleet");
|
|
147
|
-
await initCommand({ yes: true, force: true, name: "new-fleet" });
|
|
148
|
-
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
149
|
-
expect(content).toContain("name: new-fleet");
|
|
150
|
-
expect(content).not.toContain("old-fleet");
|
|
151
|
-
});
|
|
43
|
+
it("shows select prompt when invoked without --yes", async () => {
|
|
44
|
+
mockedSelect.mockResolvedValueOnce("fleet");
|
|
45
|
+
mockedInitFleet.mockResolvedValueOnce(undefined);
|
|
46
|
+
await initRouterAction({});
|
|
47
|
+
expect(mockedSelect).toHaveBeenCalledWith(expect.objectContaining({
|
|
48
|
+
message: "What would you like to initialize?",
|
|
49
|
+
}));
|
|
152
50
|
});
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
expect(gitignore).toContain("node_modules/");
|
|
160
|
-
});
|
|
161
|
-
it("does not duplicate .herdctl/ in .gitignore", async () => {
|
|
162
|
-
fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules/\n.herdctl/\n");
|
|
163
|
-
await initCommand({ yes: true });
|
|
164
|
-
const gitignore = fs.readFileSync(path.join(tempDir, ".gitignore"), "utf-8");
|
|
165
|
-
const count = (gitignore.match(/\.herdctl\//g) || []).length;
|
|
166
|
-
expect(count).toBe(1);
|
|
167
|
-
});
|
|
168
|
-
it("does not create .gitignore if it does not exist", async () => {
|
|
169
|
-
await initCommand({ yes: true });
|
|
170
|
-
// .gitignore should not be created
|
|
171
|
-
expect(fs.existsSync(path.join(tempDir, ".gitignore"))).toBe(false);
|
|
172
|
-
});
|
|
51
|
+
it("routes to fleet init when Fleet is selected", async () => {
|
|
52
|
+
mockedSelect.mockResolvedValueOnce("fleet");
|
|
53
|
+
mockedInitFleet.mockResolvedValueOnce(undefined);
|
|
54
|
+
await initRouterAction({});
|
|
55
|
+
expect(mockedInitFleet).toHaveBeenCalledWith({ force: undefined });
|
|
56
|
+
expect(mockedInitAgent).not.toHaveBeenCalled();
|
|
173
57
|
});
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
await initCommand({});
|
|
181
|
-
expect(mockedInput).toHaveBeenCalledWith(expect.objectContaining({
|
|
182
|
-
message: "Fleet name:",
|
|
183
|
-
}));
|
|
184
|
-
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
185
|
-
expect(content).toContain("name: prompted-fleet");
|
|
186
|
-
});
|
|
187
|
-
it("uses provided name in interactive mode", async () => {
|
|
188
|
-
mockedInput.mockResolvedValueOnce("A test fleet"); // description
|
|
189
|
-
mockedSelect.mockResolvedValueOnce("simple"); // template
|
|
190
|
-
mockedConfirm.mockResolvedValueOnce(true); // proceed
|
|
191
|
-
await initCommand({ name: "my-preset-fleet" });
|
|
192
|
-
// Should not prompt for fleet name
|
|
193
|
-
expect(mockedInput).not.toHaveBeenCalledWith(expect.objectContaining({
|
|
194
|
-
message: "Fleet name:",
|
|
195
|
-
}));
|
|
196
|
-
const content = fs.readFileSync(path.join(tempDir, "herdctl.yaml"), "utf-8");
|
|
197
|
-
expect(content).toContain("name: my-preset-fleet");
|
|
198
|
-
});
|
|
199
|
-
it("aborts when user declines confirmation", async () => {
|
|
200
|
-
mockedInput.mockResolvedValueOnce("test-fleet"); // fleet name
|
|
201
|
-
mockedInput.mockResolvedValueOnce(""); // description
|
|
202
|
-
mockedSelect.mockResolvedValueOnce("simple"); // template
|
|
203
|
-
mockedConfirm.mockResolvedValueOnce(false); // decline
|
|
204
|
-
await expect(initCommand({})).rejects.toThrow("process.exit");
|
|
205
|
-
expect(exitCode).toBe(0);
|
|
206
|
-
expect(consoleLogs.some((log) => log.includes("Aborted"))).toBe(true);
|
|
207
|
-
// Should not create any files
|
|
208
|
-
expect(fs.existsSync(path.join(tempDir, "herdctl.yaml"))).toBe(false);
|
|
209
|
-
});
|
|
210
|
-
it("skips template prompt when --example is provided", async () => {
|
|
211
|
-
mockedInput.mockResolvedValueOnce("test-fleet"); // fleet name
|
|
212
|
-
mockedInput.mockResolvedValueOnce(""); // description
|
|
213
|
-
mockedConfirm.mockResolvedValueOnce(true); // proceed
|
|
214
|
-
await initCommand({ example: "quickstart" });
|
|
215
|
-
// Should not prompt for template
|
|
216
|
-
expect(mockedSelect).not.toHaveBeenCalled();
|
|
217
|
-
});
|
|
58
|
+
it("routes to agent init when Agent is selected", async () => {
|
|
59
|
+
mockedSelect.mockResolvedValueOnce("agent");
|
|
60
|
+
mockedInitAgent.mockResolvedValueOnce(undefined);
|
|
61
|
+
await initRouterAction({});
|
|
62
|
+
expect(mockedInitAgent).toHaveBeenCalledWith(undefined, { force: undefined });
|
|
63
|
+
expect(mockedInitFleet).not.toHaveBeenCalled();
|
|
218
64
|
});
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const content = fs.readFileSync(path.join(tempDir, "agents", "example-agent.yaml"), "utf-8");
|
|
225
|
-
// With force, it should be overwritten
|
|
226
|
-
expect(content).toContain("name: example-agent");
|
|
227
|
-
});
|
|
228
|
-
it("preserves existing agent file without --force", async () => {
|
|
229
|
-
fs.mkdirSync(path.join(tempDir, "agents"), { recursive: true });
|
|
230
|
-
fs.writeFileSync(path.join(tempDir, "agents", "example-agent.yaml"), "name: existing-agent");
|
|
231
|
-
// Need force to overwrite herdctl.yaml, but agent file should be preserved
|
|
232
|
-
// Actually this is a new init, so let's test differently
|
|
233
|
-
// First create config, then try init with force
|
|
234
|
-
fs.writeFileSync(path.join(tempDir, "herdctl.yaml"), "version: 1");
|
|
235
|
-
await initCommand({ yes: true, force: true });
|
|
236
|
-
// Agent file should be overwritten with --force
|
|
237
|
-
const content = fs.readFileSync(path.join(tempDir, "agents", "example-agent.yaml"), "utf-8");
|
|
238
|
-
expect(content).toContain("name: example-agent");
|
|
239
|
-
});
|
|
65
|
+
it("passes force option through to subcommands", async () => {
|
|
66
|
+
mockedSelect.mockResolvedValueOnce("fleet");
|
|
67
|
+
mockedInitFleet.mockResolvedValueOnce(undefined);
|
|
68
|
+
await initRouterAction({ force: true });
|
|
69
|
+
expect(mockedInitFleet).toHaveBeenCalledWith({ force: true });
|
|
240
70
|
});
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
71
|
+
it("errors with --yes and no subcommand", async () => {
|
|
72
|
+
await expect(initRouterAction({ yes: true })).rejects.toThrow("process.exit");
|
|
73
|
+
expect(exitCode).toBe(1);
|
|
74
|
+
expect(consoleErrors.some((e) => e.includes("specify a subcommand"))).toBe(true);
|
|
75
|
+
expect(mockedSelect).not.toHaveBeenCalled();
|
|
246
76
|
});
|
|
247
77
|
});
|
|
248
78
|
//# sourceMappingURL=init.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/init.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"init.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/init.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* herdctl agent commands
|
|
3
|
+
*
|
|
4
|
+
* Commands for managing installed agents:
|
|
5
|
+
* - herdctl agent add <source> Install an agent from GitHub or local path
|
|
6
|
+
* - herdctl agent list List all discovered agents in the fleet
|
|
7
|
+
* - herdctl agent info <name> Show detailed information about an agent
|
|
8
|
+
* - herdctl agent remove <name> Remove an installed agent
|
|
9
|
+
*
|
|
10
|
+
* The add command orchestrates the full agent installation flow:
|
|
11
|
+
* 1. Parse source specifier (github:user/repo[@ref] or ./local/path)
|
|
12
|
+
* 2. Fetch repository to temp directory
|
|
13
|
+
* 3. Validate agent repository structure
|
|
14
|
+
* 4. Install files to ./agents/<name>/
|
|
15
|
+
* 5. Update herdctl.yaml with agent reference
|
|
16
|
+
* 6. Scan and display required environment variables
|
|
17
|
+
*/
|
|
18
|
+
import { type ResolvedAgent } from "@herdctl/core";
|
|
19
|
+
export interface AgentAddOptions {
|
|
20
|
+
/** Override the target installation directory */
|
|
21
|
+
path?: string;
|
|
22
|
+
/** Show what would happen without making changes */
|
|
23
|
+
dryRun?: boolean;
|
|
24
|
+
/** Overwrite existing agent directory */
|
|
25
|
+
force?: boolean;
|
|
26
|
+
/** Path to config file or directory */
|
|
27
|
+
config?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface AgentRemoveOptions {
|
|
30
|
+
/** Skip confirmation (no-op for now, reserved for future interactive confirmation) */
|
|
31
|
+
force?: boolean;
|
|
32
|
+
/** Preserve workspace directory contents */
|
|
33
|
+
keepWorkspace?: boolean;
|
|
34
|
+
/** Path to config file or directory */
|
|
35
|
+
config?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Install an agent from a source specifier
|
|
39
|
+
*
|
|
40
|
+
* Orchestrates the full installation flow:
|
|
41
|
+
* 1. Parse source specifier
|
|
42
|
+
* 2. Fetch repository
|
|
43
|
+
* 3. Validate repository
|
|
44
|
+
* 4. Install files (unless dry-run)
|
|
45
|
+
* 5. Update fleet config (unless dry-run)
|
|
46
|
+
* 6. Scan and display env variables
|
|
47
|
+
* 7. Cleanup temp directory
|
|
48
|
+
*
|
|
49
|
+
* @param source - Source specifier (e.g., "github:user/repo", "./local/path")
|
|
50
|
+
* @param options - Command options
|
|
51
|
+
*/
|
|
52
|
+
export declare function agentAddCommand(source: string, options: AgentAddOptions): Promise<void>;
|
|
53
|
+
export interface AgentListOptions {
|
|
54
|
+
/** Output as JSON for scripting */
|
|
55
|
+
json?: boolean;
|
|
56
|
+
/** Path to config file or directory */
|
|
57
|
+
config?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Maximum number of agents before switching to summary mode.
|
|
61
|
+
* When total agents exceed this threshold, fleet-level counts are shown
|
|
62
|
+
* instead of individual agent names to avoid overwhelming output.
|
|
63
|
+
*/
|
|
64
|
+
export declare const TREE_AGENT_THRESHOLD = 200;
|
|
65
|
+
/**
|
|
66
|
+
* Tree node representing a fleet or agent in the hierarchy
|
|
67
|
+
*/
|
|
68
|
+
export interface FleetTreeNode {
|
|
69
|
+
name: string;
|
|
70
|
+
description?: string;
|
|
71
|
+
agents: string[];
|
|
72
|
+
children: FleetTreeNode[];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Build a tree structure from a flat array of resolved agents.
|
|
76
|
+
*
|
|
77
|
+
* Groups agents by their fleetPath hierarchy. Root-level agents (empty fleetPath)
|
|
78
|
+
* go directly under the root node. Sub-fleet agents are nested under their
|
|
79
|
+
* respective fleet nodes.
|
|
80
|
+
*/
|
|
81
|
+
export declare function buildFleetTree(agents: ResolvedAgent[], rootName: string, rootDescription?: string): FleetTreeNode;
|
|
82
|
+
/**
|
|
83
|
+
* Render a fleet tree with box-drawing characters.
|
|
84
|
+
*
|
|
85
|
+
* Uses standard Unicode box-drawing characters for the tree structure:
|
|
86
|
+
* - Connector for intermediate items
|
|
87
|
+
* - End connector for last items
|
|
88
|
+
* - Vertical bar for continuing branches
|
|
89
|
+
*
|
|
90
|
+
* @param node - The tree node to render
|
|
91
|
+
* @param prefix - Current indentation prefix
|
|
92
|
+
* @param isLast - Whether this node is the last child of its parent
|
|
93
|
+
* @param isRoot - Whether this is the root node
|
|
94
|
+
* @param summaryMode - When true, show agent counts instead of names
|
|
95
|
+
*/
|
|
96
|
+
export declare function renderFleetTree(node: FleetTreeNode, prefix?: string, isLast?: boolean, isRoot?: boolean, summaryMode?: boolean): string[];
|
|
97
|
+
/**
|
|
98
|
+
* List all agents in the fleet
|
|
99
|
+
*
|
|
100
|
+
* Discovers agents from the fleet configuration and displays them.
|
|
101
|
+
* When sub-fleets exist, displays a tree view showing agents grouped by fleet hierarchy.
|
|
102
|
+
* When no sub-fleets exist, displays a flat table (original behavior).
|
|
103
|
+
*
|
|
104
|
+
* If total agents across the hierarchy exceed 200, shows fleet-level summary counts
|
|
105
|
+
* instead of individual agent names.
|
|
106
|
+
*
|
|
107
|
+
* @param options - Command options
|
|
108
|
+
*/
|
|
109
|
+
export declare function agentListCommand(options: AgentListOptions): Promise<void>;
|
|
110
|
+
export interface AgentInfoOptions {
|
|
111
|
+
/** Output as JSON for scripting */
|
|
112
|
+
json?: boolean;
|
|
113
|
+
/** Path to config file or directory */
|
|
114
|
+
config?: string;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get detailed information about a specific agent
|
|
118
|
+
*
|
|
119
|
+
* Shows comprehensive agent information including:
|
|
120
|
+
* - Basic info (name, description, status)
|
|
121
|
+
* - Source and installation details
|
|
122
|
+
* - Environment variables
|
|
123
|
+
* - Schedules
|
|
124
|
+
* - Files in the agent directory
|
|
125
|
+
*
|
|
126
|
+
* @param name - Agent name to look up
|
|
127
|
+
* @param options - Command options
|
|
128
|
+
*/
|
|
129
|
+
export declare function agentInfoCommand(name: string, options: AgentInfoOptions): Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Remove an agent from the fleet
|
|
132
|
+
*
|
|
133
|
+
* This command:
|
|
134
|
+
* 1. Finds the agent by name in the fleet configuration
|
|
135
|
+
* 2. Deletes the agent directory (optionally preserving workspace)
|
|
136
|
+
* 3. Removes the agent reference from herdctl.yaml
|
|
137
|
+
* 4. Reports environment variables that were used (for cleanup reference)
|
|
138
|
+
*
|
|
139
|
+
* @param name - Agent name to remove
|
|
140
|
+
* @param options - Command options
|
|
141
|
+
*/
|
|
142
|
+
export declare function agentRemoveCommand(name: string, options: AgentRemoveOptions): Promise<void>;
|
|
143
|
+
//# sourceMappingURL=agent.d.ts.map
|