@agentmeshhq/agent 0.1.17 → 0.2.1

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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/__tests__/orphan-process.test.d.ts +11 -0
  4. package/dist/__tests__/orphan-process.test.js +286 -0
  5. package/dist/__tests__/orphan-process.test.js.map +1 -0
  6. package/dist/__tests__/runner.test.js +16 -0
  7. package/dist/__tests__/runner.test.js.map +1 -1
  8. package/dist/__tests__/watchdog.test.js +138 -12
  9. package/dist/__tests__/watchdog.test.js.map +1 -1
  10. package/dist/cli/index.js +2 -1
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/cli/start.d.ts +2 -1
  13. package/dist/cli/start.js +6 -3
  14. package/dist/cli/start.js.map +1 -1
  15. package/dist/cli/status.js +11 -0
  16. package/dist/cli/status.js.map +1 -1
  17. package/dist/cli/stop.js +7 -2
  18. package/dist/cli/stop.js.map +1 -1
  19. package/dist/config/schema.d.ts +4 -2
  20. package/dist/core/daemon/assignment-message.d.ts +12 -0
  21. package/dist/core/daemon/assignment-message.js +36 -0
  22. package/dist/core/daemon/assignment-message.js.map +1 -0
  23. package/dist/core/daemon/bootstrap.d.ts +35 -0
  24. package/dist/core/daemon/bootstrap.js +52 -0
  25. package/dist/core/daemon/bootstrap.js.map +1 -0
  26. package/dist/core/daemon/crash-log.d.ts +16 -0
  27. package/dist/core/daemon/crash-log.js +24 -0
  28. package/dist/core/daemon/crash-log.js.map +1 -0
  29. package/dist/core/daemon/health-policy.d.ts +21 -0
  30. package/dist/core/daemon/health-policy.js +32 -0
  31. package/dist/core/daemon/health-policy.js.map +1 -0
  32. package/dist/core/daemon/sandbox-config.d.ts +9 -0
  33. package/dist/core/daemon/sandbox-config.js +17 -0
  34. package/dist/core/daemon/sandbox-config.js.map +1 -0
  35. package/dist/core/daemon/state.d.ts +33 -0
  36. package/dist/core/daemon/state.js +77 -0
  37. package/dist/core/daemon/state.js.map +1 -0
  38. package/dist/core/daemon/tmux-session.d.ts +17 -0
  39. package/dist/core/daemon/tmux-session.js +34 -0
  40. package/dist/core/daemon/tmux-session.js.map +1 -0
  41. package/dist/core/daemon/workspace.d.ts +10 -0
  42. package/dist/core/daemon/workspace.js +51 -0
  43. package/dist/core/daemon/workspace.js.map +1 -0
  44. package/dist/core/daemon.d.ts +4 -7
  45. package/dist/core/daemon.js +143 -259
  46. package/dist/core/daemon.js.map +1 -1
  47. package/dist/core/injector.js +6 -0
  48. package/dist/core/injector.js.map +1 -1
  49. package/dist/core/registry.js +1 -1
  50. package/dist/core/registry.js.map +1 -1
  51. package/dist/core/runner/build.d.ts +9 -0
  52. package/dist/core/runner/build.js +53 -0
  53. package/dist/core/runner/build.js.map +1 -0
  54. package/dist/core/runner/detect.d.ts +5 -0
  55. package/dist/core/runner/detect.js +14 -0
  56. package/dist/core/runner/detect.js.map +1 -0
  57. package/dist/core/runner/index.d.ts +5 -0
  58. package/dist/core/runner/index.js +5 -0
  59. package/dist/core/runner/index.js.map +1 -0
  60. package/dist/core/runner/model.d.ts +5 -0
  61. package/dist/core/runner/model.js +7 -0
  62. package/dist/core/runner/model.js.map +1 -0
  63. package/dist/core/runner/opencode-models.d.ts +15 -0
  64. package/dist/core/runner/opencode-models.js +70 -0
  65. package/dist/core/runner/opencode-models.js.map +1 -0
  66. package/dist/core/runner/types.d.ts +19 -0
  67. package/dist/core/runner/types.js +8 -0
  68. package/dist/core/runner/types.js.map +1 -0
  69. package/dist/core/runner.d.ts +5 -47
  70. package/dist/core/runner.js +5 -167
  71. package/dist/core/runner.js.map +1 -1
  72. package/dist/core/tmux-runtime.d.ts +13 -0
  73. package/dist/core/tmux-runtime.js +72 -0
  74. package/dist/core/tmux-runtime.js.map +1 -0
  75. package/dist/core/tmux.d.ts +7 -1
  76. package/dist/core/tmux.js +75 -45
  77. package/dist/core/tmux.js.map +1 -1
  78. package/dist/core/watchdog.d.ts +18 -1
  79. package/dist/core/watchdog.js +78 -29
  80. package/dist/core/watchdog.js.map +1 -1
  81. package/package.json +30 -11
  82. package/dist/cli/inbox.d.ts +0 -5
  83. package/dist/cli/inbox.js +0 -123
  84. package/dist/cli/inbox.js.map +0 -1
  85. package/dist/cli/issue.d.ts +0 -42
  86. package/dist/cli/issue.js +0 -297
  87. package/dist/cli/issue.js.map +0 -1
  88. package/dist/cli/ready.d.ts +0 -5
  89. package/dist/cli/ready.js +0 -131
  90. package/dist/cli/ready.js.map +0 -1
  91. package/dist/cli/sync.d.ts +0 -8
  92. package/dist/cli/sync.js +0 -154
  93. package/dist/cli/sync.js.map +0 -1
  94. package/dist/core/issue-cache.d.ts +0 -44
  95. package/dist/core/issue-cache.js +0 -75
  96. package/dist/core/issue-cache.js.map +0 -1
  97. package/src/__tests__/context.test.ts +0 -464
  98. package/src/__tests__/injector.test.ts +0 -29
  99. package/src/__tests__/jwt.test.ts +0 -112
  100. package/src/__tests__/loader.test.ts +0 -239
  101. package/src/__tests__/runner.test.ts +0 -104
  102. package/src/__tests__/sandbox.test.ts +0 -435
  103. package/src/__tests__/watchdog.test.ts +0 -368
  104. package/src/cli/attach.ts +0 -22
  105. package/src/cli/build.ts +0 -145
  106. package/src/cli/config.ts +0 -148
  107. package/src/cli/context.ts +0 -231
  108. package/src/cli/deploy.ts +0 -155
  109. package/src/cli/index.ts +0 -375
  110. package/src/cli/init.ts +0 -75
  111. package/src/cli/list.ts +0 -70
  112. package/src/cli/local.ts +0 -183
  113. package/src/cli/logs.ts +0 -64
  114. package/src/cli/migrate.ts +0 -212
  115. package/src/cli/nudge.ts +0 -81
  116. package/src/cli/restart.ts +0 -59
  117. package/src/cli/slack.ts +0 -70
  118. package/src/cli/start.ts +0 -115
  119. package/src/cli/status.ts +0 -91
  120. package/src/cli/stop.ts +0 -48
  121. package/src/cli/test.ts +0 -143
  122. package/src/cli/token.ts +0 -188
  123. package/src/cli/whoami.ts +0 -142
  124. package/src/config/loader.ts +0 -121
  125. package/src/config/schema.ts +0 -68
  126. package/src/context/handoff.ts +0 -122
  127. package/src/context/index.ts +0 -8
  128. package/src/context/schema.ts +0 -111
  129. package/src/context/storage.ts +0 -197
  130. package/src/core/daemon.ts +0 -1308
  131. package/src/core/heartbeat.ts +0 -129
  132. package/src/core/injector.ts +0 -292
  133. package/src/core/registry.ts +0 -159
  134. package/src/core/runner.ts +0 -225
  135. package/src/core/sandbox.ts +0 -547
  136. package/src/core/session-id.ts +0 -111
  137. package/src/core/tmux.ts +0 -405
  138. package/src/core/watchdog.ts +0 -238
  139. package/src/core/websocket.ts +0 -94
  140. package/src/index.ts +0 -10
  141. package/src/utils/jwt.ts +0 -87
  142. package/tsconfig.json +0 -8
  143. package/vitest.config.ts +0 -12
@@ -1,368 +0,0 @@
1
- import { execSync, spawnSync } from "node:child_process";
2
- import { beforeEach, describe, expect, it, vi } from "vitest";
3
- import * as tmux from "../core/tmux.js";
4
- import {
5
- checkAgentProgress,
6
- cleanupOrphanContainers,
7
- detectPermissionPrompt,
8
- findOrphanContainers,
9
- getLastActivityTime,
10
- isProcessRunning,
11
- sendNudge,
12
- type WatchdogResult,
13
- } from "../core/watchdog.js";
14
-
15
- // Mock child_process
16
- vi.mock("node:child_process", () => ({
17
- execSync: vi.fn(),
18
- spawnSync: vi.fn(),
19
- }));
20
-
21
- // Mock tmux module
22
- vi.mock("../core/tmux.js", () => ({
23
- captureSessionOutput: vi.fn(),
24
- }));
25
-
26
- describe("Watchdog Module", () => {
27
- beforeEach(() => {
28
- vi.resetAllMocks();
29
- });
30
-
31
- describe("detectPermissionPrompt", () => {
32
- it("should return null when no permission prompt detected", () => {
33
- vi.mocked(tmux.captureSessionOutput).mockReturnValue(
34
- "Normal output without any prompts\nJust some code being written",
35
- );
36
-
37
- const result = detectPermissionPrompt("test-agent");
38
- expect(result).toBeNull();
39
- });
40
-
41
- it("should detect 'Permission required' prompt", () => {
42
- vi.mocked(tmux.captureSessionOutput).mockReturnValue(
43
- "Some output\nPermission required\nAllow once | Allow always | Reject",
44
- );
45
-
46
- const result = detectPermissionPrompt("test-agent");
47
- expect(result).toBe("Permission prompt detected");
48
- });
49
-
50
- it("should detect external directory access prompt", () => {
51
- vi.mocked(tmux.captureSessionOutput).mockReturnValue(
52
- "Access external directory /tmp/some-path\nAllow once | Allow always | Reject",
53
- );
54
-
55
- const result = detectPermissionPrompt("test-agent");
56
- expect(result).toBe("External directory: /tmp/some-path");
57
- });
58
-
59
- it("should detect triangle permission prompt", () => {
60
- vi.mocked(tmux.captureSessionOutput).mockReturnValue(
61
- "Some output\n△ Permission required\nWaiting for approval",
62
- );
63
-
64
- const result = detectPermissionPrompt("test-agent");
65
- expect(result).toBe("Permission prompt detected");
66
- });
67
-
68
- it("should return null when capture fails", () => {
69
- vi.mocked(tmux.captureSessionOutput).mockReturnValue(null);
70
-
71
- const result = detectPermissionPrompt("test-agent");
72
- expect(result).toBeNull();
73
- });
74
-
75
- it("should return null when capture throws", () => {
76
- vi.mocked(tmux.captureSessionOutput).mockImplementation(() => {
77
- throw new Error("Session not found");
78
- });
79
-
80
- const result = detectPermissionPrompt("test-agent");
81
- expect(result).toBeNull();
82
- });
83
- });
84
-
85
- describe("getLastActivityTime", () => {
86
- it("should parse timestamp from local log file", () => {
87
- vi.mocked(spawnSync).mockReturnValue({
88
- status: 0,
89
- stdout: "INFO 2026-02-26T00:14:42 +0ms service=opencode message=test",
90
- stderr: "",
91
- pid: 123,
92
- signal: null,
93
- output: [],
94
- });
95
-
96
- const result = getLastActivityTime("test-agent");
97
- expect(result).toBeInstanceOf(Date);
98
- expect(result?.toISOString()).toContain("2026-02-26");
99
- });
100
-
101
- it("should parse timestamp from container log file", () => {
102
- vi.mocked(spawnSync).mockReturnValue({
103
- status: 0,
104
- stdout: "INFO 2026-02-26T01:30:00 +0ms service=opencode",
105
- stderr: "",
106
- pid: 123,
107
- signal: null,
108
- output: [],
109
- });
110
-
111
- const result = getLastActivityTime("test-agent", "container-123");
112
- expect(result).toBeInstanceOf(Date);
113
- });
114
-
115
- it("should return null when command fails", () => {
116
- vi.mocked(spawnSync).mockReturnValue({
117
- status: 1,
118
- stdout: "",
119
- stderr: "No such file",
120
- pid: 123,
121
- signal: null,
122
- output: [],
123
- });
124
-
125
- const result = getLastActivityTime("test-agent");
126
- expect(result).toBeNull();
127
- });
128
-
129
- it("should return null when no timestamp found", () => {
130
- vi.mocked(spawnSync).mockReturnValue({
131
- status: 0,
132
- stdout: "Some output without timestamp",
133
- stderr: "",
134
- pid: 123,
135
- signal: null,
136
- output: [],
137
- });
138
-
139
- const result = getLastActivityTime("test-agent");
140
- expect(result).toBeNull();
141
- });
142
-
143
- it("should return null on empty output", () => {
144
- vi.mocked(spawnSync).mockReturnValue({
145
- status: 0,
146
- stdout: "",
147
- stderr: "",
148
- pid: 123,
149
- signal: null,
150
- output: [],
151
- });
152
-
153
- const result = getLastActivityTime("test-agent");
154
- expect(result).toBeNull();
155
- });
156
- });
157
-
158
- describe("checkAgentProgress", () => {
159
- it("should return permission_blocked when permission prompt detected", () => {
160
- vi.mocked(tmux.captureSessionOutput).mockReturnValue("Permission required\nAllow once");
161
-
162
- const result = checkAgentProgress("test-agent");
163
- expect(result.status).toBe("permission_blocked");
164
- expect(result.blockedOn).toBe("Permission prompt detected");
165
- });
166
-
167
- it("should return active when recent activity", () => {
168
- vi.mocked(tmux.captureSessionOutput).mockReturnValue("Normal output");
169
-
170
- // Mock recent timestamp (1 minute ago)
171
- const recentTime = new Date(Date.now() - 60 * 1000);
172
- vi.mocked(spawnSync).mockReturnValue({
173
- status: 0,
174
- stdout: `INFO ${recentTime.toISOString().slice(0, 19)} +0ms service=opencode`,
175
- stderr: "",
176
- pid: 123,
177
- signal: null,
178
- output: [],
179
- });
180
-
181
- const result = checkAgentProgress("test-agent");
182
- expect(result.status).toBe("active");
183
- });
184
-
185
- it("should return idle when no activity for 3 minutes", () => {
186
- vi.mocked(tmux.captureSessionOutput).mockReturnValue("Normal output");
187
-
188
- // Mock timestamp 3 minutes ago
189
- const idleTime = new Date(Date.now() - 3 * 60 * 1000);
190
- vi.mocked(spawnSync).mockReturnValue({
191
- status: 0,
192
- stdout: `INFO ${idleTime.toISOString().slice(0, 19)} +0ms service=opencode`,
193
- stderr: "",
194
- pid: 123,
195
- signal: null,
196
- output: [],
197
- });
198
-
199
- const result = checkAgentProgress("test-agent");
200
- expect(result.status).toBe("idle");
201
- });
202
-
203
- it("should return stuck when no activity for 6 minutes", () => {
204
- vi.mocked(tmux.captureSessionOutput).mockReturnValue("Normal output");
205
-
206
- // Mock timestamp 6 minutes ago
207
- const stuckTime = new Date(Date.now() - 6 * 60 * 1000);
208
- vi.mocked(spawnSync).mockReturnValue({
209
- status: 0,
210
- stdout: `INFO ${stuckTime.toISOString().slice(0, 19)} +0ms service=opencode`,
211
- stderr: "",
212
- pid: 123,
213
- signal: null,
214
- output: [],
215
- });
216
-
217
- const result = checkAgentProgress("test-agent");
218
- expect(result.status).toBe("stuck");
219
- });
220
-
221
- it("should return active when activity time cannot be determined", () => {
222
- vi.mocked(tmux.captureSessionOutput).mockReturnValue("Normal output");
223
- vi.mocked(spawnSync).mockReturnValue({
224
- status: 1,
225
- stdout: "",
226
- stderr: "",
227
- pid: 123,
228
- signal: null,
229
- output: [],
230
- });
231
-
232
- const result = checkAgentProgress("test-agent");
233
- expect(result.status).toBe("active");
234
- expect(result.details).toContain("Unable to determine");
235
- });
236
- });
237
-
238
- describe("isProcessRunning", () => {
239
- it("should return true for running process", () => {
240
- // Current process is always running
241
- const result = isProcessRunning(process.pid);
242
- expect(result).toBe(true);
243
- });
244
-
245
- it("should return false for non-existent process", () => {
246
- // Use a very high PID that's unlikely to exist
247
- const result = isProcessRunning(999999999);
248
- expect(result).toBe(false);
249
- });
250
- });
251
-
252
- describe("findOrphanContainers", () => {
253
- it("should return list of container IDs", () => {
254
- vi.mocked(spawnSync).mockReturnValue({
255
- status: 0,
256
- stdout: "abc123\ndef456\nghi789",
257
- stderr: "",
258
- pid: 123,
259
- signal: null,
260
- output: [],
261
- });
262
-
263
- const result = findOrphanContainers("test-agent");
264
- expect(result).toEqual(["abc123", "def456", "ghi789"]);
265
- });
266
-
267
- it("should return empty array when no containers found", () => {
268
- vi.mocked(spawnSync).mockReturnValue({
269
- status: 0,
270
- stdout: "",
271
- stderr: "",
272
- pid: 123,
273
- signal: null,
274
- output: [],
275
- });
276
-
277
- const result = findOrphanContainers("test-agent");
278
- expect(result).toEqual([]);
279
- });
280
-
281
- it("should return empty array on command failure", () => {
282
- vi.mocked(spawnSync).mockReturnValue({
283
- status: 1,
284
- stdout: "",
285
- stderr: "docker not found",
286
- pid: 123,
287
- signal: null,
288
- output: [],
289
- });
290
-
291
- const result = findOrphanContainers("test-agent");
292
- expect(result).toEqual([]);
293
- });
294
- });
295
-
296
- describe("cleanupOrphanContainers", () => {
297
- it("should remove found containers and return count", () => {
298
- vi.mocked(spawnSync)
299
- .mockReturnValueOnce({
300
- // findOrphanContainers call
301
- status: 0,
302
- stdout: "abc123\ndef456",
303
- stderr: "",
304
- pid: 123,
305
- signal: null,
306
- output: [],
307
- })
308
- .mockReturnValue({
309
- // docker rm calls
310
- status: 0,
311
- stdout: "",
312
- stderr: "",
313
- pid: 123,
314
- signal: null,
315
- output: [],
316
- });
317
-
318
- const result = cleanupOrphanContainers("test-agent");
319
- expect(result).toBe(2);
320
- });
321
-
322
- it("should return 0 when no orphan containers", () => {
323
- vi.mocked(spawnSync).mockReturnValue({
324
- status: 0,
325
- stdout: "",
326
- stderr: "",
327
- pid: 123,
328
- signal: null,
329
- output: [],
330
- });
331
-
332
- const result = cleanupOrphanContainers("test-agent");
333
- expect(result).toBe(0);
334
- });
335
- });
336
-
337
- describe("sendNudge", () => {
338
- it("should send nudge message to tmux session", () => {
339
- vi.mocked(execSync).mockReturnValue(Buffer.from(""));
340
-
341
- const result = sendNudge("test-agent", "Please continue working");
342
- expect(result).toBe(true);
343
- expect(execSync).toHaveBeenCalledWith(
344
- expect.stringContaining("tmux send-keys"),
345
- expect.any(Object),
346
- );
347
- });
348
-
349
- it("should return false when tmux command fails", () => {
350
- vi.mocked(execSync).mockImplementation(() => {
351
- throw new Error("tmux session not found");
352
- });
353
-
354
- const result = sendNudge("test-agent", "Continue");
355
- expect(result).toBe(false);
356
- });
357
-
358
- it("should escape quotes in message", () => {
359
- vi.mocked(execSync).mockReturnValue(Buffer.from(""));
360
-
361
- sendNudge("test-agent", 'Message with "quotes"');
362
- expect(execSync).toHaveBeenCalledWith(
363
- expect.stringContaining('\\"quotes\\"'),
364
- expect.any(Object),
365
- );
366
- });
367
- });
368
- });
package/src/cli/attach.ts DELETED
@@ -1,22 +0,0 @@
1
- import pc from "picocolors";
2
- import { attachSession, getSessionName, sessionExists } from "../core/tmux.js";
3
-
4
- export function attach(name: string): void {
5
- if (!name) {
6
- console.log(pc.red("Agent name is required."));
7
- process.exit(1);
8
- }
9
-
10
- const sessionName = getSessionName(name);
11
-
12
- if (!sessionExists(sessionName)) {
13
- console.log(pc.red(`Agent "${name}" is not running.`));
14
- console.log(`Start it with: ${pc.cyan(`agentmesh start --name ${name}`)}`);
15
- process.exit(1);
16
- }
17
-
18
- console.log(`Attaching to ${sessionName}...`);
19
- console.log(pc.dim("Detach with: Ctrl+B, D\n"));
20
-
21
- attachSession(name);
22
- }
package/src/cli/build.ts DELETED
@@ -1,145 +0,0 @@
1
- import { execSync, spawnSync } from "node:child_process";
2
- import path from "node:path";
3
- import pc from "picocolors";
4
-
5
- function findProjectRoot(): string {
6
- let dir = process.cwd();
7
- for (let i = 0; i < 10; i++) {
8
- const packageJson = path.join(dir, "package.json");
9
- const pnpmWorkspace = path.join(dir, "pnpm-workspace.yaml");
10
- try {
11
- execSync(`test -f "${packageJson}" && test -f "${pnpmWorkspace}"`, { stdio: "ignore" });
12
- return dir;
13
- } catch {
14
- dir = path.dirname(dir);
15
- }
16
- }
17
- throw new Error(
18
- "Could not find AgentMesh project root. Make sure you're in the agentmesh repository.",
19
- );
20
- }
21
-
22
- export interface BuildOptions {
23
- docker?: boolean;
24
- package?: string;
25
- clean?: boolean;
26
- }
27
-
28
- export async function build(options: BuildOptions = {}): Promise<void> {
29
- const projectRoot = findProjectRoot();
30
-
31
- if (options.docker) {
32
- await buildDocker(projectRoot, options);
33
- } else {
34
- await buildPackages(projectRoot, options);
35
- }
36
- }
37
-
38
- async function buildPackages(projectRoot: string, options: BuildOptions): Promise<void> {
39
- console.log(pc.cyan("Building AgentMesh packages..."));
40
- console.log();
41
-
42
- const args = ["pnpm"];
43
-
44
- if (options.package) {
45
- args.push("--filter", options.package);
46
- }
47
-
48
- if (options.clean) {
49
- console.log(pc.dim("Cleaning build artifacts..."));
50
- const cleanResult = spawnSync("pnpm", ["-r", "exec", "rm", "-rf", "dist"], {
51
- cwd: projectRoot,
52
- stdio: "inherit",
53
- });
54
- if (cleanResult.status !== 0) {
55
- console.warn(pc.yellow("Warning: Clean may have partially failed"));
56
- }
57
- console.log();
58
- }
59
-
60
- args.push("build");
61
-
62
- const result = spawnSync(args[0], args.slice(1), {
63
- cwd: projectRoot,
64
- stdio: "inherit",
65
- });
66
-
67
- if (result.status !== 0) {
68
- console.error(pc.red("Build failed"));
69
- process.exit(1);
70
- }
71
-
72
- console.log();
73
- console.log(pc.green("Build completed successfully!"));
74
- }
75
-
76
- async function buildDocker(projectRoot: string, options: BuildOptions): Promise<void> {
77
- console.log(pc.cyan("Building Docker images..."));
78
- console.log();
79
-
80
- // Check if docker is available
81
- try {
82
- execSync("docker --version", { stdio: "ignore" });
83
- } catch {
84
- console.error(pc.red("Docker is not installed or not running"));
85
- process.exit(1);
86
- }
87
-
88
- // Use docker buildx bake for multi-image builds
89
- const dockerDir = path.join(projectRoot, "docker");
90
- const dockerfilePath = path.join(dockerDir, "Dockerfile");
91
-
92
- try {
93
- execSync(`test -f "${dockerfilePath}"`, { stdio: "ignore" });
94
- } catch {
95
- console.error(pc.red("Dockerfile not found at docker/Dockerfile"));
96
- process.exit(1);
97
- }
98
-
99
- // Build using docker compose to leverage the existing setup
100
- const composePath = path.join(dockerDir, "docker-compose.local.yml");
101
-
102
- const args = ["compose", "-f", composePath, "build"];
103
- if (options.package) {
104
- // Map package names to service names
105
- const serviceMap: Record<string, string> = {
106
- "@agentmesh/hub": "hub-api",
107
- "@agentmesh/admin": "admin",
108
- hub: "hub-api",
109
- admin: "admin",
110
- };
111
- const service = serviceMap[options.package] || options.package;
112
- args.push(service);
113
- }
114
-
115
- const result = spawnSync("docker", args, {
116
- cwd: projectRoot,
117
- stdio: "inherit",
118
- });
119
-
120
- if (result.status !== 0) {
121
- console.error(pc.red("Docker build failed"));
122
- process.exit(1);
123
- }
124
-
125
- console.log();
126
- console.log(pc.green("Docker images built successfully!"));
127
-
128
- // List built images
129
- console.log();
130
- console.log(pc.bold("Built images:"));
131
- const listResult = spawnSync(
132
- "docker",
133
- [
134
- "images",
135
- "--filter",
136
- "reference=*agentmesh*",
137
- "--format",
138
- "{{.Repository}}:{{.Tag}}\t{{.Size}}",
139
- ],
140
- { encoding: "utf-8" },
141
- );
142
- if (listResult.stdout) {
143
- console.log(pc.dim(listResult.stdout));
144
- }
145
- }
package/src/cli/config.ts DELETED
@@ -1,148 +0,0 @@
1
- import pc from "picocolors";
2
- import { loadConfig, saveConfig } from "../config/loader.js";
3
- import { CONFIG_PATH, type Config } from "../config/schema.js";
4
-
5
- export async function configCmd(action: string, key?: string, value?: string): Promise<void> {
6
- const config = loadConfig();
7
-
8
- if (!config) {
9
- console.log(pc.red("No config found. Run 'agentmesh init' first."));
10
- process.exit(1);
11
- }
12
-
13
- switch (action) {
14
- case "show":
15
- case "view":
16
- showConfig(config);
17
- break;
18
-
19
- case "get":
20
- if (!key) {
21
- console.log(pc.red("Key required. Usage: agentmesh config get <key>"));
22
- process.exit(1);
23
- }
24
- getConfigValue(config, key);
25
- break;
26
-
27
- case "set":
28
- if (!key || value === undefined) {
29
- console.log(pc.red("Key and value required. Usage: agentmesh config set <key> <value>"));
30
- process.exit(1);
31
- }
32
- setConfigValue(config, key, value);
33
- break;
34
-
35
- case "path":
36
- console.log(CONFIG_PATH);
37
- break;
38
-
39
- case "edit":
40
- await editConfig();
41
- break;
42
-
43
- default:
44
- // Default to show
45
- showConfig(config);
46
- }
47
- }
48
-
49
- function showConfig(config: Config): void {
50
- console.log(pc.bold("AgentMesh Configuration\n"));
51
- console.log(pc.dim(`Path: ${CONFIG_PATH}\n`));
52
-
53
- // Show main settings
54
- console.log(`hubUrl: ${pc.cyan(config.hubUrl)}`);
55
- console.log(`workspace: ${pc.cyan(config.workspace)}`);
56
- console.log(`apiKey: ${pc.dim(maskApiKey(config.apiKey))}`);
57
-
58
- // Show defaults
59
- console.log();
60
- console.log(pc.dim("Defaults:"));
61
- console.log(` command: ${config.defaults.command}`);
62
- console.log(` model: ${config.defaults.model}`);
63
-
64
- // Show agents
65
- if (config.agents.length > 0) {
66
- console.log();
67
- console.log(pc.dim("Agent Configs:"));
68
- for (const agent of config.agents) {
69
- console.log(` ${agent.name}:`);
70
- if (agent.command) console.log(` command: ${agent.command}`);
71
- if (agent.model) console.log(` model: ${agent.model}`);
72
- }
73
- }
74
- }
75
-
76
- function getConfigValue(config: Config, key: string): void {
77
- const parts = key.split(".");
78
- let value: unknown = config;
79
-
80
- for (const part of parts) {
81
- if (value && typeof value === "object" && part in value) {
82
- value = (value as Record<string, unknown>)[part];
83
- } else {
84
- console.log(pc.red(`Key "${key}" not found.`));
85
- process.exit(1);
86
- }
87
- }
88
-
89
- if (typeof value === "object") {
90
- console.log(JSON.stringify(value, null, 2));
91
- } else {
92
- console.log(String(value));
93
- }
94
- }
95
-
96
- function setConfigValue(config: Config, key: string, value: string): void {
97
- const parts = key.split(".");
98
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
- let target: any = config;
100
-
101
- // Navigate to parent
102
- for (let i = 0; i < parts.length - 1; i++) {
103
- const part = parts[i];
104
- if (!(part in target)) {
105
- target[part] = {};
106
- }
107
- target = target[part];
108
- }
109
-
110
- const finalKey = parts[parts.length - 1];
111
- const oldValue = target[finalKey];
112
-
113
- // Try to parse as JSON, otherwise use string
114
- try {
115
- target[finalKey] = JSON.parse(value);
116
- } catch {
117
- target[finalKey] = value;
118
- }
119
-
120
- saveConfig(config);
121
-
122
- console.log(pc.green(`Set ${key}:`));
123
- console.log(` Old: ${pc.dim(String(oldValue))}`);
124
- console.log(` New: ${pc.cyan(String(target[finalKey]))}`);
125
- }
126
-
127
- async function editConfig(): Promise<void> {
128
- const { spawn } = await import("node:child_process");
129
- const editor = process.env.EDITOR || process.env.VISUAL || "vi";
130
-
131
- console.log(pc.dim(`Opening ${CONFIG_PATH} with ${editor}...`));
132
-
133
- const child = spawn(editor, [CONFIG_PATH], {
134
- stdio: "inherit",
135
- });
136
-
137
- child.on("exit", (code) => {
138
- if (code === 0) {
139
- console.log(pc.green("Config saved."));
140
- }
141
- process.exit(code ?? 0);
142
- });
143
- }
144
-
145
- function maskApiKey(key: string): string {
146
- if (!key || key.length < 12) return "***";
147
- return `${key.slice(0, 8)}...${key.slice(-4)}`;
148
- }