@moxxy/agent-cli 0.0.3 → 0.0.5

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.
@@ -0,0 +1,2108 @@
1
+ // src/cli.ts
2
+ import { Command } from "commander";
3
+
4
+ // src/core/plugin-registry.ts
5
+ var PluginRegistry = class {
6
+ plugins = /* @__PURE__ */ new Map();
7
+ register(plugin) {
8
+ this.plugins.set(plugin.name, plugin);
9
+ }
10
+ get(name) {
11
+ return this.plugins.get(name);
12
+ }
13
+ getAll() {
14
+ return Array.from(this.plugins.values());
15
+ }
16
+ has(name) {
17
+ return this.plugins.has(name);
18
+ }
19
+ };
20
+
21
+ // src/core/exec.ts
22
+ import { execFile } from "child_process";
23
+ function exec(command, args, options) {
24
+ return new Promise((resolve14, reject) => {
25
+ execFile(
26
+ command,
27
+ args,
28
+ { ...options, maxBuffer: 10 * 1024 * 1024 },
29
+ (error, stdout, stderr) => {
30
+ if (error) {
31
+ reject(Object.assign(error, { stdout, stderr }));
32
+ } else {
33
+ resolve14({ stdout, stderr });
34
+ }
35
+ }
36
+ );
37
+ });
38
+ }
39
+
40
+ // src/core/context.ts
41
+ import * as fs from "fs";
42
+ import * as path from "path";
43
+ var currentContext = null;
44
+ async function detectWorkspace(cwd) {
45
+ const context = {
46
+ cwd,
47
+ isGitRepo: false
48
+ };
49
+ try {
50
+ const { stdout } = await exec("git", ["rev-parse", "--show-toplevel"], { cwd });
51
+ context.isGitRepo = true;
52
+ context.repoRoot = stdout.trim();
53
+ } catch {
54
+ context.isGitRepo = false;
55
+ }
56
+ if (context.isGitRepo) {
57
+ try {
58
+ const { stdout } = await exec("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
59
+ context.branch = stdout.trim();
60
+ } catch {
61
+ }
62
+ }
63
+ const lockfiles = [
64
+ { file: "pnpm-lock.yaml", manager: "pnpm" },
65
+ { file: "yarn.lock", manager: "yarn" },
66
+ { file: "bun.lockb", manager: "bun" },
67
+ { file: "package-lock.json", manager: "npm" }
68
+ ];
69
+ const searchDir = context.repoRoot || cwd;
70
+ for (const { file, manager } of lockfiles) {
71
+ if (fs.existsSync(path.join(searchDir, file))) {
72
+ context.packageManager = manager;
73
+ break;
74
+ }
75
+ }
76
+ currentContext = context;
77
+ return context;
78
+ }
79
+ function getContext() {
80
+ return currentContext;
81
+ }
82
+
83
+ // src/core/result.ts
84
+ function success(command, data, startTime) {
85
+ return {
86
+ success: true,
87
+ command,
88
+ data,
89
+ duration_ms: Date.now() - startTime
90
+ };
91
+ }
92
+ function failure(command, code, message, startTime, details) {
93
+ return {
94
+ success: false,
95
+ command,
96
+ error: { code, message, details },
97
+ duration_ms: Date.now() - startTime
98
+ };
99
+ }
100
+ function output(result) {
101
+ process.stdout.write(JSON.stringify(result) + "\n");
102
+ }
103
+ function log(message) {
104
+ process.stderr.write(message + "\n");
105
+ }
106
+
107
+ // src/plugins/workspace/init.ts
108
+ function registerInit(parent) {
109
+ parent.command("init").description("Initialize a workspace by cloning a repo and setting up the environment").option("--repo <url>", "Git repository URL to clone").option("--branch <name>", "Branch to create or checkout").option("--clone-dir <path>", "Directory to clone into").action(async (opts) => {
110
+ const startTime = Date.now();
111
+ const cmd = "workspace init";
112
+ try {
113
+ if (!opts.repo) {
114
+ output(failure(cmd, "MISSING_ARGUMENT", "--repo is required", startTime));
115
+ return;
116
+ }
117
+ const cloneDir = opts.cloneDir || process.cwd();
118
+ log(`Cloning ${opts.repo} into ${cloneDir}...`);
119
+ const cloneArgs = ["clone", opts.repo, cloneDir];
120
+ await exec("git", cloneArgs);
121
+ if (opts.branch) {
122
+ log(`Creating and checking out branch ${opts.branch}...`);
123
+ await exec("git", ["checkout", "-b", opts.branch], { cwd: cloneDir });
124
+ }
125
+ const context = await detectWorkspace(cloneDir);
126
+ if (context.packageManager) {
127
+ log(`Detected ${context.packageManager}, installing dependencies...`);
128
+ try {
129
+ await exec(context.packageManager, ["install"], { cwd: cloneDir });
130
+ } catch (err) {
131
+ log(`Warning: dependency install failed: ${err.message}`);
132
+ }
133
+ }
134
+ output(success(cmd, {
135
+ path: cloneDir,
136
+ repo: opts.repo,
137
+ branch: opts.branch || context.branch,
138
+ packageManager: context.packageManager,
139
+ isGitRepo: context.isGitRepo
140
+ }, startTime));
141
+ } catch (err) {
142
+ output(failure(cmd, "WORKSPACE_INIT_ERROR", err.message, startTime, err.stderr));
143
+ }
144
+ });
145
+ }
146
+
147
+ // src/plugins/workspace/info.ts
148
+ function registerInfo(parent) {
149
+ parent.command("info").description("Display current workspace context").action(async () => {
150
+ const startTime = Date.now();
151
+ const cmd = "workspace info";
152
+ try {
153
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
154
+ const context = await detectWorkspace(cwd);
155
+ output(success(cmd, context, startTime));
156
+ } catch (err) {
157
+ output(failure(cmd, "WORKSPACE_INFO_ERROR", err.message, startTime));
158
+ }
159
+ });
160
+ }
161
+
162
+ // src/plugins/workspace/clean.ts
163
+ import * as fs2 from "fs";
164
+ function registerClean(parent) {
165
+ parent.command("clean").description("Remove workspace directory").argument("<path>", "Workspace directory to remove").action(async (targetPath) => {
166
+ const startTime = Date.now();
167
+ const cmd = "workspace clean";
168
+ try {
169
+ if (!fs2.existsSync(targetPath)) {
170
+ output(failure(cmd, "NOT_FOUND", `Directory not found: ${targetPath}`, startTime));
171
+ return;
172
+ }
173
+ log(`Removing ${targetPath}...`);
174
+ fs2.rmSync(targetPath, { recursive: true, force: true });
175
+ output(success(cmd, { path: targetPath, removed: true }, startTime));
176
+ } catch (err) {
177
+ output(failure(cmd, "WORKSPACE_CLEAN_ERROR", err.message, startTime));
178
+ }
179
+ });
180
+ }
181
+
182
+ // src/plugins/workspace/index.ts
183
+ var WorkspacePlugin = class {
184
+ name = "workspace";
185
+ version = "1.0.0";
186
+ description = "Workspace initialization and management";
187
+ register(program) {
188
+ const workspace = program.command("workspace").description(this.description);
189
+ registerInit(workspace);
190
+ registerInfo(workspace);
191
+ registerClean(workspace);
192
+ }
193
+ getCommands() {
194
+ return [
195
+ {
196
+ name: "workspace init",
197
+ description: "Clone a repo and set up workspace",
198
+ args: [],
199
+ options: [
200
+ { name: "--repo", description: "Git repository URL", required: true, type: "string" },
201
+ { name: "--branch", description: "Branch to create", required: false, type: "string" },
202
+ { name: "--clone-dir", description: "Clone target directory", required: false, type: "string" }
203
+ ],
204
+ examples: ["moxxy-agent workspace init --repo https://github.com/org/repo --branch feat/new"]
205
+ },
206
+ {
207
+ name: "workspace info",
208
+ description: "Display current workspace context",
209
+ args: [],
210
+ options: [],
211
+ examples: ["moxxy-agent workspace info"]
212
+ },
213
+ {
214
+ name: "workspace clean",
215
+ description: "Remove workspace directory",
216
+ args: [{ name: "path", description: "Directory to remove", required: true, type: "string" }],
217
+ options: [],
218
+ examples: ["moxxy-agent workspace clean /tmp/workspace"]
219
+ }
220
+ ];
221
+ }
222
+ };
223
+
224
+ // src/plugins/file/create.ts
225
+ import * as fs3 from "fs";
226
+ import * as path2 from "path";
227
+ function registerCreate(parent) {
228
+ parent.command("create").description("Create a new file").argument("<path>", "File path to create").option("--content <text>", "File content").option("--from-stdin", "Read content from stdin").action(async (filePath, opts) => {
229
+ const startTime = Date.now();
230
+ const cmd = "file create";
231
+ try {
232
+ const resolvedPath = path2.resolve(filePath);
233
+ const dir = path2.dirname(resolvedPath);
234
+ if (!fs3.existsSync(dir)) {
235
+ fs3.mkdirSync(dir, { recursive: true });
236
+ }
237
+ let content = opts.content || "";
238
+ if (opts.fromStdin) {
239
+ content = await readStdin();
240
+ }
241
+ fs3.writeFileSync(resolvedPath, content, "utf-8");
242
+ const stats = fs3.statSync(resolvedPath);
243
+ output(success(cmd, { path: resolvedPath, size: stats.size }, startTime));
244
+ } catch (err) {
245
+ output(failure(cmd, "FILE_CREATE_ERROR", err.message, startTime));
246
+ }
247
+ });
248
+ }
249
+ function readStdin() {
250
+ return new Promise((resolve14, reject) => {
251
+ const chunks = [];
252
+ process.stdin.on("data", (chunk) => chunks.push(chunk));
253
+ process.stdin.on("end", () => resolve14(Buffer.concat(chunks).toString("utf-8")));
254
+ process.stdin.on("error", reject);
255
+ });
256
+ }
257
+
258
+ // src/plugins/file/read.ts
259
+ import * as fs4 from "fs";
260
+ import * as path3 from "path";
261
+ function registerRead(parent) {
262
+ parent.command("read").description("Read a file").argument("<path>", "File path to read").option("--lines <range>", "Line range, e.g. 1:10").action(async (filePath, opts) => {
263
+ const startTime = Date.now();
264
+ const cmd = "file read";
265
+ try {
266
+ const resolvedPath = path3.resolve(filePath);
267
+ if (!fs4.existsSync(resolvedPath)) {
268
+ output(failure(cmd, "NOT_FOUND", `File not found: ${resolvedPath}`, startTime));
269
+ return;
270
+ }
271
+ const raw = fs4.readFileSync(resolvedPath, "utf-8");
272
+ let lines = raw.split("\n");
273
+ let startLine = 1;
274
+ let endLine = lines.length;
275
+ if (opts.lines) {
276
+ const parts = opts.lines.split(":");
277
+ startLine = Math.max(1, parseInt(parts[0], 10) || 1);
278
+ endLine = parts[1] ? parseInt(parts[1], 10) || lines.length : lines.length;
279
+ lines = lines.slice(startLine - 1, endLine);
280
+ }
281
+ output(success(cmd, {
282
+ path: resolvedPath,
283
+ content: lines.join("\n"),
284
+ lines: lines.length,
285
+ startLine,
286
+ endLine: Math.min(endLine, startLine + lines.length - 1)
287
+ }, startTime));
288
+ } catch (err) {
289
+ output(failure(cmd, "FILE_READ_ERROR", err.message, startTime));
290
+ }
291
+ });
292
+ }
293
+
294
+ // src/plugins/file/update.ts
295
+ import * as fs5 from "fs";
296
+ import * as path4 from "path";
297
+ function registerUpdate(parent) {
298
+ parent.command("update").description("Overwrite a file with new content").argument("<path>", "File path to update").option("--content <text>", "New file content").option("--from-stdin", "Read content from stdin").action(async (filePath, opts) => {
299
+ const startTime = Date.now();
300
+ const cmd = "file update";
301
+ try {
302
+ const resolvedPath = path4.resolve(filePath);
303
+ if (!fs5.existsSync(resolvedPath)) {
304
+ output(failure(cmd, "NOT_FOUND", `File not found: ${resolvedPath}`, startTime));
305
+ return;
306
+ }
307
+ let content = opts.content || "";
308
+ if (opts.fromStdin) {
309
+ content = await readStdin2();
310
+ }
311
+ fs5.writeFileSync(resolvedPath, content, "utf-8");
312
+ const stats = fs5.statSync(resolvedPath);
313
+ output(success(cmd, { path: resolvedPath, size: stats.size }, startTime));
314
+ } catch (err) {
315
+ output(failure(cmd, "FILE_UPDATE_ERROR", err.message, startTime));
316
+ }
317
+ });
318
+ }
319
+ function readStdin2() {
320
+ return new Promise((resolve14, reject) => {
321
+ const chunks = [];
322
+ process.stdin.on("data", (chunk) => chunks.push(chunk));
323
+ process.stdin.on("end", () => resolve14(Buffer.concat(chunks).toString("utf-8")));
324
+ process.stdin.on("error", reject);
325
+ });
326
+ }
327
+
328
+ // src/plugins/file/delete.ts
329
+ import * as fs6 from "fs";
330
+ import * as path5 from "path";
331
+ function registerDelete(parent) {
332
+ parent.command("delete").description("Delete a file").argument("<path>", "File path to delete").action(async (filePath) => {
333
+ const startTime = Date.now();
334
+ const cmd = "file delete";
335
+ try {
336
+ const resolvedPath = path5.resolve(filePath);
337
+ if (!fs6.existsSync(resolvedPath)) {
338
+ output(failure(cmd, "NOT_FOUND", `File not found: ${resolvedPath}`, startTime));
339
+ return;
340
+ }
341
+ fs6.unlinkSync(resolvedPath);
342
+ output(success(cmd, { path: resolvedPath, deleted: true }, startTime));
343
+ } catch (err) {
344
+ output(failure(cmd, "FILE_DELETE_ERROR", err.message, startTime));
345
+ }
346
+ });
347
+ }
348
+
349
+ // src/plugins/file/move.ts
350
+ import * as fs7 from "fs";
351
+ import * as path6 from "path";
352
+ function registerMove(parent) {
353
+ parent.command("move").description("Move or rename a file").argument("<source>", "Source file path").argument("<dest>", "Destination file path").action(async (source, dest) => {
354
+ const startTime = Date.now();
355
+ const cmd = "file move";
356
+ try {
357
+ const resolvedSource = path6.resolve(source);
358
+ const resolvedDest = path6.resolve(dest);
359
+ if (!fs7.existsSync(resolvedSource)) {
360
+ output(failure(cmd, "NOT_FOUND", `Source file not found: ${resolvedSource}`, startTime));
361
+ return;
362
+ }
363
+ const destDir = path6.dirname(resolvedDest);
364
+ if (!fs7.existsSync(destDir)) {
365
+ fs7.mkdirSync(destDir, { recursive: true });
366
+ }
367
+ fs7.renameSync(resolvedSource, resolvedDest);
368
+ output(success(cmd, { source: resolvedSource, dest: resolvedDest }, startTime));
369
+ } catch (err) {
370
+ output(failure(cmd, "FILE_MOVE_ERROR", err.message, startTime));
371
+ }
372
+ });
373
+ }
374
+
375
+ // src/plugins/file/patch.ts
376
+ import * as fs8 from "fs";
377
+ import * as path7 from "path";
378
+ function registerPatch(parent) {
379
+ parent.command("patch").description("Replace a string in a file").argument("<path>", "File path to patch").requiredOption("--search <text>", "String to search for").requiredOption("--replace <text>", "Replacement string").action(async (filePath, opts) => {
380
+ const startTime = Date.now();
381
+ const cmd = "file patch";
382
+ try {
383
+ const resolvedPath = path7.resolve(filePath);
384
+ if (!fs8.existsSync(resolvedPath)) {
385
+ output(failure(cmd, "NOT_FOUND", `File not found: ${resolvedPath}`, startTime));
386
+ return;
387
+ }
388
+ const content = fs8.readFileSync(resolvedPath, "utf-8");
389
+ if (!content.includes(opts.search)) {
390
+ output(failure(
391
+ cmd,
392
+ "SEARCH_NOT_FOUND",
393
+ `Search string not found in ${resolvedPath}`,
394
+ startTime
395
+ ));
396
+ return;
397
+ }
398
+ let replacements = 0;
399
+ let idx = 0;
400
+ while ((idx = content.indexOf(opts.search, idx)) !== -1) {
401
+ replacements++;
402
+ idx += opts.search.length;
403
+ }
404
+ const newContent = content.replaceAll(opts.search, opts.replace);
405
+ fs8.writeFileSync(resolvedPath, newContent, "utf-8");
406
+ output(success(cmd, { path: resolvedPath, replacements }, startTime));
407
+ } catch (err) {
408
+ output(failure(cmd, "FILE_PATCH_ERROR", err.message, startTime));
409
+ }
410
+ });
411
+ }
412
+
413
+ // src/plugins/file/index.ts
414
+ var FilePlugin = class {
415
+ name = "file";
416
+ version = "1.0.0";
417
+ description = "File operations (create, read, update, delete, move, patch)";
418
+ register(program) {
419
+ const file = program.command("file").description(this.description);
420
+ registerCreate(file);
421
+ registerRead(file);
422
+ registerUpdate(file);
423
+ registerDelete(file);
424
+ registerMove(file);
425
+ registerPatch(file);
426
+ }
427
+ getCommands() {
428
+ return [
429
+ {
430
+ name: "file create",
431
+ description: "Create a new file",
432
+ args: [{ name: "path", description: "File path", required: true, type: "string" }],
433
+ options: [
434
+ { name: "--content", description: "File content", required: false, type: "string" },
435
+ { name: "--from-stdin", description: "Read from stdin", required: false, type: "boolean" }
436
+ ],
437
+ examples: ['moxxy-agent file create src/main.ts --content "console.log(1)"']
438
+ },
439
+ {
440
+ name: "file read",
441
+ description: "Read a file",
442
+ args: [{ name: "path", description: "File path", required: true, type: "string" }],
443
+ options: [
444
+ { name: "--lines", description: "Line range (start:end)", required: false, type: "string" }
445
+ ],
446
+ examples: ["moxxy-agent file read src/main.ts --lines 1:10"]
447
+ },
448
+ {
449
+ name: "file update",
450
+ description: "Overwrite a file",
451
+ args: [{ name: "path", description: "File path", required: true, type: "string" }],
452
+ options: [
453
+ { name: "--content", description: "New content", required: false, type: "string" },
454
+ { name: "--from-stdin", description: "Read from stdin", required: false, type: "boolean" }
455
+ ],
456
+ examples: ['moxxy-agent file update src/main.ts --content "updated"']
457
+ },
458
+ {
459
+ name: "file delete",
460
+ description: "Delete a file",
461
+ args: [{ name: "path", description: "File path", required: true, type: "string" }],
462
+ options: [],
463
+ examples: ["moxxy-agent file delete src/old.ts"]
464
+ },
465
+ {
466
+ name: "file move",
467
+ description: "Move or rename a file",
468
+ args: [
469
+ { name: "source", description: "Source path", required: true, type: "string" },
470
+ { name: "dest", description: "Destination path", required: true, type: "string" }
471
+ ],
472
+ options: [],
473
+ examples: ["moxxy-agent file move src/old.ts src/new.ts"]
474
+ },
475
+ {
476
+ name: "file patch",
477
+ description: "Replace a string in a file",
478
+ args: [{ name: "path", description: "File path", required: true, type: "string" }],
479
+ options: [
480
+ { name: "--search", description: "String to find", required: true, type: "string" },
481
+ { name: "--replace", description: "Replacement string", required: true, type: "string" }
482
+ ],
483
+ examples: ['moxxy-agent file patch src/main.ts --search "old" --replace "new"']
484
+ }
485
+ ];
486
+ }
487
+ };
488
+
489
+ // src/plugins/dir/list.ts
490
+ import * as fs9 from "fs";
491
+ import * as path8 from "path";
492
+ import { glob } from "glob";
493
+ function registerList(parent) {
494
+ parent.command("list").description("List directory entries").argument("[path]", "Directory path", ".").option("--recursive", "List recursively").option("--pattern <glob>", "Filter by glob pattern").action(async (dirPath, opts) => {
495
+ const startTime = Date.now();
496
+ const cmd = "dir list";
497
+ try {
498
+ const resolvedPath = path8.resolve(dirPath);
499
+ if (!fs9.existsSync(resolvedPath)) {
500
+ output(failure(cmd, "NOT_FOUND", `Directory not found: ${resolvedPath}`, startTime));
501
+ return;
502
+ }
503
+ if (!fs9.statSync(resolvedPath).isDirectory()) {
504
+ output(failure(cmd, "NOT_A_DIRECTORY", `Not a directory: ${resolvedPath}`, startTime));
505
+ return;
506
+ }
507
+ let entries;
508
+ if (opts.pattern || opts.recursive) {
509
+ const pattern = opts.pattern || (opts.recursive ? "**/*" : "*");
510
+ const matches = await glob(pattern, {
511
+ cwd: resolvedPath,
512
+ dot: false,
513
+ nodir: false,
514
+ stat: true,
515
+ withFileTypes: true
516
+ });
517
+ entries = matches.map((entry) => ({
518
+ name: entry.relative(),
519
+ type: entry.isDirectory() ? "directory" : "file",
520
+ size: entry.isDirectory() ? 0 : fs9.statSync(path8.join(resolvedPath, entry.relative())).size
521
+ }));
522
+ } else {
523
+ const dirEntries = fs9.readdirSync(resolvedPath, { withFileTypes: true });
524
+ entries = dirEntries.map((entry) => ({
525
+ name: entry.name,
526
+ type: entry.isDirectory() ? "directory" : "file",
527
+ size: entry.isDirectory() ? 0 : fs9.statSync(path8.join(resolvedPath, entry.name)).size
528
+ }));
529
+ }
530
+ output(success(cmd, { path: resolvedPath, entries, count: entries.length }, startTime));
531
+ } catch (err) {
532
+ output(failure(cmd, "DIR_LIST_ERROR", err.message, startTime));
533
+ }
534
+ });
535
+ }
536
+
537
+ // src/plugins/dir/create.ts
538
+ import * as fs10 from "fs";
539
+ import * as path9 from "path";
540
+ function registerCreate2(parent) {
541
+ parent.command("create").description("Create a directory recursively").argument("<path>", "Directory path to create").action(async (dirPath) => {
542
+ const startTime = Date.now();
543
+ const cmd = "dir create";
544
+ try {
545
+ const resolvedPath = path9.resolve(dirPath);
546
+ fs10.mkdirSync(resolvedPath, { recursive: true });
547
+ output(success(cmd, { path: resolvedPath, created: true }, startTime));
548
+ } catch (err) {
549
+ output(failure(cmd, "DIR_CREATE_ERROR", err.message, startTime));
550
+ }
551
+ });
552
+ }
553
+
554
+ // src/plugins/dir/delete.ts
555
+ import * as fs11 from "fs";
556
+ import * as path10 from "path";
557
+ function registerDelete2(parent) {
558
+ parent.command("delete").description("Remove a directory").argument("<path>", "Directory path to remove").action(async (dirPath) => {
559
+ const startTime = Date.now();
560
+ const cmd = "dir delete";
561
+ try {
562
+ const resolvedPath = path10.resolve(dirPath);
563
+ if (!fs11.existsSync(resolvedPath)) {
564
+ output(failure(cmd, "NOT_FOUND", `Directory not found: ${resolvedPath}`, startTime));
565
+ return;
566
+ }
567
+ fs11.rmSync(resolvedPath, { recursive: true, force: true });
568
+ output(success(cmd, { path: resolvedPath, deleted: true }, startTime));
569
+ } catch (err) {
570
+ output(failure(cmd, "DIR_DELETE_ERROR", err.message, startTime));
571
+ }
572
+ });
573
+ }
574
+
575
+ // src/plugins/dir/tree.ts
576
+ import * as fs12 from "fs";
577
+ import * as path11 from "path";
578
+ function buildTree(dirPath, currentDepth, maxDepth) {
579
+ if (currentDepth >= maxDepth) {
580
+ return [];
581
+ }
582
+ const entries = fs12.readdirSync(dirPath, { withFileTypes: true });
583
+ const nodes = [];
584
+ for (const entry of entries) {
585
+ if (entry.name.startsWith(".") || entry.name === "node_modules") {
586
+ continue;
587
+ }
588
+ const node = {
589
+ name: entry.name,
590
+ type: entry.isDirectory() ? "directory" : "file"
591
+ };
592
+ if (entry.isDirectory()) {
593
+ node.children = buildTree(
594
+ path11.join(dirPath, entry.name),
595
+ currentDepth + 1,
596
+ maxDepth
597
+ );
598
+ }
599
+ nodes.push(node);
600
+ }
601
+ return nodes.sort((a, b) => {
602
+ if (a.type !== b.type) return a.type === "directory" ? -1 : 1;
603
+ return a.name.localeCompare(b.name);
604
+ });
605
+ }
606
+ function registerTree(parent) {
607
+ parent.command("tree").description("Display directory tree structure").argument("[path]", "Directory path", ".").option("--depth <n>", "Maximum depth", "3").action(async (dirPath, opts) => {
608
+ const startTime = Date.now();
609
+ const cmd = "dir tree";
610
+ try {
611
+ const resolvedPath = path11.resolve(dirPath);
612
+ const maxDepth = parseInt(opts.depth, 10) || 3;
613
+ if (!fs12.existsSync(resolvedPath)) {
614
+ output(failure(cmd, "NOT_FOUND", `Directory not found: ${resolvedPath}`, startTime));
615
+ return;
616
+ }
617
+ if (!fs12.statSync(resolvedPath).isDirectory()) {
618
+ output(failure(cmd, "NOT_A_DIRECTORY", `Not a directory: ${resolvedPath}`, startTime));
619
+ return;
620
+ }
621
+ const tree = buildTree(resolvedPath, 0, maxDepth);
622
+ output(success(cmd, { path: resolvedPath, tree, depth: maxDepth }, startTime));
623
+ } catch (err) {
624
+ output(failure(cmd, "DIR_TREE_ERROR", err.message, startTime));
625
+ }
626
+ });
627
+ }
628
+
629
+ // src/plugins/dir/index.ts
630
+ var DirPlugin = class {
631
+ name = "dir";
632
+ version = "1.0.0";
633
+ description = "Directory operations (list, create, delete, tree)";
634
+ register(program) {
635
+ const dir = program.command("dir").description(this.description);
636
+ registerList(dir);
637
+ registerCreate2(dir);
638
+ registerDelete2(dir);
639
+ registerTree(dir);
640
+ }
641
+ getCommands() {
642
+ return [
643
+ {
644
+ name: "dir list",
645
+ description: "List directory entries",
646
+ args: [{ name: "path", description: "Directory path", required: false, type: "string" }],
647
+ options: [
648
+ { name: "--recursive", description: "List recursively", required: false, type: "boolean" },
649
+ { name: "--pattern", description: "Glob filter pattern", required: false, type: "string" }
650
+ ],
651
+ examples: ['moxxy-agent dir list src --recursive --pattern "*.ts"']
652
+ },
653
+ {
654
+ name: "dir create",
655
+ description: "Create a directory",
656
+ args: [{ name: "path", description: "Directory path", required: true, type: "string" }],
657
+ options: [],
658
+ examples: ["moxxy-agent dir create src/utils"]
659
+ },
660
+ {
661
+ name: "dir delete",
662
+ description: "Remove a directory",
663
+ args: [{ name: "path", description: "Directory path", required: true, type: "string" }],
664
+ options: [],
665
+ examples: ["moxxy-agent dir delete tmp"]
666
+ },
667
+ {
668
+ name: "dir tree",
669
+ description: "Display directory tree",
670
+ args: [{ name: "path", description: "Directory path", required: false, type: "string" }],
671
+ options: [
672
+ { name: "--depth", description: "Maximum depth", required: false, type: "number" }
673
+ ],
674
+ examples: ["moxxy-agent dir tree src --depth 2"]
675
+ }
676
+ ];
677
+ }
678
+ };
679
+
680
+ // src/plugins/git/init.ts
681
+ function registerInit2(parent) {
682
+ parent.command("init").description("Initialize a new git repository").argument("[path]", "Directory to initialize", ".").action(async (dirPath) => {
683
+ const startTime = Date.now();
684
+ const cmd = "git init";
685
+ try {
686
+ const { stdout } = await exec("git", ["init", dirPath]);
687
+ output(success(cmd, { path: dirPath, message: stdout.trim() }, startTime));
688
+ } catch (err) {
689
+ output(failure(cmd, "GIT_INIT_ERROR", err.message, startTime, err.stderr));
690
+ }
691
+ });
692
+ }
693
+
694
+ // src/plugins/git/clone.ts
695
+ function registerClone(parent) {
696
+ parent.command("clone").description("Clone a git repository").argument("<url>", "Repository URL").argument("[directory]", "Target directory").option("--branch <name>", "Branch to clone").action(async (url, directory, opts) => {
697
+ const startTime = Date.now();
698
+ const cmd = "git clone";
699
+ try {
700
+ const args = ["clone"];
701
+ if (opts.branch) {
702
+ args.push("--branch", opts.branch);
703
+ }
704
+ args.push(url);
705
+ if (directory) {
706
+ args.push(directory);
707
+ }
708
+ log(`Cloning ${url}...`);
709
+ const { stdout, stderr } = await exec("git", args);
710
+ output(success(cmd, {
711
+ url,
712
+ directory: directory || url.split("/").pop()?.replace(".git", ""),
713
+ branch: opts.branch,
714
+ message: (stdout || stderr).trim()
715
+ }, startTime));
716
+ } catch (err) {
717
+ output(failure(cmd, "GIT_CLONE_ERROR", err.message, startTime, err.stderr));
718
+ }
719
+ });
720
+ }
721
+
722
+ // src/plugins/git/branch.ts
723
+ function registerBranch(parent) {
724
+ parent.command("branch").description("Create or list branches").argument("[name]", "Branch name to create").option("--list", "List all branches").action(async (name, opts) => {
725
+ const startTime = Date.now();
726
+ const cmd = "git branch";
727
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
728
+ try {
729
+ if (opts.list || !name) {
730
+ const { stdout } = await exec("git", ["branch", "-a"], { cwd });
731
+ const branches = stdout.split("\n").filter((line) => line.trim()).map((line) => {
732
+ const isCurrent = line.startsWith("* ");
733
+ const branchName = line.replace(/^\*?\s+/, "").trim();
734
+ return { name: branchName, current: isCurrent };
735
+ });
736
+ output(success(cmd, { branches }, startTime));
737
+ } else {
738
+ const { stdout } = await exec("git", ["branch", name], { cwd });
739
+ output(success(cmd, { name, created: true, message: stdout.trim() }, startTime));
740
+ }
741
+ } catch (err) {
742
+ output(failure(cmd, "GIT_BRANCH_ERROR", err.message, startTime, err.stderr));
743
+ }
744
+ });
745
+ }
746
+
747
+ // src/plugins/git/checkout.ts
748
+ function registerCheckout(parent) {
749
+ parent.command("checkout").description("Checkout a branch").argument("<branch>", "Branch name to checkout").option("-b", "Create new branch").action(async (branch, opts) => {
750
+ const startTime = Date.now();
751
+ const cmd = "git checkout";
752
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
753
+ try {
754
+ const args = ["checkout"];
755
+ if (opts.b) {
756
+ args.push("-b");
757
+ }
758
+ args.push(branch);
759
+ const { stdout, stderr } = await exec("git", args, { cwd });
760
+ output(success(cmd, {
761
+ branch,
762
+ created: !!opts.b,
763
+ message: (stderr || stdout).trim()
764
+ }, startTime));
765
+ } catch (err) {
766
+ output(failure(cmd, "GIT_CHECKOUT_ERROR", err.message, startTime, err.stderr));
767
+ }
768
+ });
769
+ }
770
+
771
+ // src/plugins/git/add.ts
772
+ function registerAdd(parent) {
773
+ parent.command("add").description("Stage files for commit").argument("[files...]", "Files to stage").option("--all", "Stage all changes").action(async (files, opts) => {
774
+ const startTime = Date.now();
775
+ const cmd = "git add";
776
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
777
+ try {
778
+ const args = ["add"];
779
+ if (opts.all) {
780
+ args.push("-A");
781
+ } else if (files.length > 0) {
782
+ args.push(...files);
783
+ } else {
784
+ output(failure(
785
+ cmd,
786
+ "MISSING_ARGUMENT",
787
+ "Provide files to stage or use --all",
788
+ startTime
789
+ ));
790
+ return;
791
+ }
792
+ await exec("git", args, { cwd });
793
+ output(success(cmd, {
794
+ files: opts.all ? ["(all)"] : files,
795
+ staged: true
796
+ }, startTime));
797
+ } catch (err) {
798
+ output(failure(cmd, "GIT_ADD_ERROR", err.message, startTime, err.stderr));
799
+ }
800
+ });
801
+ }
802
+
803
+ // src/plugins/git/commit.ts
804
+ function registerCommit(parent) {
805
+ parent.command("commit").description("Create a git commit").requiredOption("-m <message>", "Commit message").action(async (opts) => {
806
+ const startTime = Date.now();
807
+ const cmd = "git commit";
808
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
809
+ try {
810
+ const { stdout } = await exec("git", ["commit", "-m", opts.m], { cwd });
811
+ const match = stdout.match(/\[.+?\s+([a-f0-9]+)\]/);
812
+ const hash = match?.[1] || "";
813
+ output(success(cmd, {
814
+ hash,
815
+ message: opts.m,
816
+ output: stdout.trim()
817
+ }, startTime));
818
+ } catch (err) {
819
+ const isNothingToCommit = err.stdout?.includes("nothing to commit") || err.stderr?.includes("nothing to commit");
820
+ if (isNothingToCommit) {
821
+ output(failure(
822
+ cmd,
823
+ "NOTHING_TO_COMMIT",
824
+ "Nothing to commit, working tree clean",
825
+ startTime
826
+ ));
827
+ } else {
828
+ output(failure(cmd, "GIT_COMMIT_ERROR", err.message, startTime, err.stderr));
829
+ }
830
+ }
831
+ });
832
+ }
833
+
834
+ // src/plugins/git/push.ts
835
+ function registerPush(parent) {
836
+ parent.command("push").description("Push commits to remote").option("--set-upstream", "Set upstream tracking branch").option("--remote <name>", "Remote name", "origin").option("--branch <name>", "Branch name").action(async (opts) => {
837
+ const startTime = Date.now();
838
+ const cmd = "git push";
839
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
840
+ try {
841
+ const args = ["push"];
842
+ if (opts.setUpstream) {
843
+ args.push("--set-upstream");
844
+ args.push(opts.remote);
845
+ if (opts.branch) {
846
+ args.push(opts.branch);
847
+ } else {
848
+ const { stdout: stdout2 } = await exec("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
849
+ args.push(stdout2.trim());
850
+ }
851
+ }
852
+ const { stdout, stderr } = await exec("git", args, { cwd });
853
+ output(success(cmd, { message: (stderr || stdout).trim() }, startTime));
854
+ } catch (err) {
855
+ output(failure(cmd, "GIT_PUSH_ERROR", err.message, startTime, err.stderr));
856
+ }
857
+ });
858
+ }
859
+
860
+ // src/plugins/git/pull.ts
861
+ function registerPull(parent) {
862
+ parent.command("pull").description("Pull changes from remote").action(async () => {
863
+ const startTime = Date.now();
864
+ const cmd = "git pull";
865
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
866
+ try {
867
+ const { stdout, stderr } = await exec("git", ["pull"], { cwd });
868
+ output(success(cmd, { message: (stdout || stderr).trim() }, startTime));
869
+ } catch (err) {
870
+ output(failure(cmd, "GIT_PULL_ERROR", err.message, startTime, err.stderr));
871
+ }
872
+ });
873
+ }
874
+
875
+ // src/plugins/git/diff.ts
876
+ function registerDiff(parent) {
877
+ parent.command("diff").description("Show changes").option("--staged", "Show staged changes").action(async (opts) => {
878
+ const startTime = Date.now();
879
+ const cmd = "git diff";
880
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
881
+ try {
882
+ const args = ["diff"];
883
+ if (opts.staged) {
884
+ args.push("--staged");
885
+ }
886
+ const { stdout } = await exec("git", args, { cwd });
887
+ output(success(cmd, { diff: stdout, staged: !!opts.staged }, startTime));
888
+ } catch (err) {
889
+ output(failure(cmd, "GIT_DIFF_ERROR", err.message, startTime, err.stderr));
890
+ }
891
+ });
892
+ }
893
+
894
+ // src/plugins/git/status.ts
895
+ function parsePorcelain(raw) {
896
+ return raw.split("\n").filter((line) => line.trim()).map((line) => {
897
+ const status = line.substring(0, 2).trim();
898
+ const filePath = line.substring(3);
899
+ return { status, path: filePath };
900
+ });
901
+ }
902
+ function registerStatus(parent) {
903
+ parent.command("status").description("Show working tree status").action(async () => {
904
+ const startTime = Date.now();
905
+ const cmd = "git status";
906
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
907
+ try {
908
+ const { stdout } = await exec("git", ["status", "--porcelain"], { cwd });
909
+ const entries = parsePorcelain(stdout);
910
+ const isClean = entries.length === 0;
911
+ output(success(cmd, {
912
+ clean: isClean,
913
+ entries,
914
+ staged: entries.filter((e) => ["A", "M", "D", "R"].includes(e.status[0])),
915
+ unstaged: entries.filter((e) => e.status.length > 1 && e.status[1] !== " "),
916
+ untracked: entries.filter((e) => e.status === "??")
917
+ }, startTime));
918
+ } catch (err) {
919
+ output(failure(cmd, "GIT_STATUS_ERROR", err.message, startTime, err.stderr));
920
+ }
921
+ });
922
+ }
923
+
924
+ // src/plugins/git/log.ts
925
+ function parseLog(raw) {
926
+ return raw.split("\n").filter((line) => line.trim()).map((line) => {
927
+ const spaceIdx = line.indexOf(" ");
928
+ if (spaceIdx === -1) return { hash: line, message: "" };
929
+ return {
930
+ hash: line.substring(0, spaceIdx),
931
+ message: line.substring(spaceIdx + 1)
932
+ };
933
+ });
934
+ }
935
+ function registerLog(parent) {
936
+ parent.command("log").description("Show commit log").option("--limit <n>", "Number of commits to show", "10").action(async (opts) => {
937
+ const startTime = Date.now();
938
+ const cmd = "git log";
939
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
940
+ try {
941
+ const limit = parseInt(opts.limit, 10) || 10;
942
+ const { stdout } = await exec(
943
+ "git",
944
+ ["log", `--oneline`, `-n`, String(limit)],
945
+ { cwd }
946
+ );
947
+ const commits = parseLog(stdout);
948
+ output(success(cmd, { commits, count: commits.length }, startTime));
949
+ } catch (err) {
950
+ output(failure(cmd, "GIT_LOG_ERROR", err.message, startTime, err.stderr));
951
+ }
952
+ });
953
+ }
954
+
955
+ // src/plugins/git/index.ts
956
+ var GitPlugin = class {
957
+ name = "git";
958
+ version = "1.0.0";
959
+ description = "Git operations";
960
+ register(program) {
961
+ const git = program.command("git").description(this.description);
962
+ registerInit2(git);
963
+ registerClone(git);
964
+ registerBranch(git);
965
+ registerCheckout(git);
966
+ registerAdd(git);
967
+ registerCommit(git);
968
+ registerPush(git);
969
+ registerPull(git);
970
+ registerDiff(git);
971
+ registerStatus(git);
972
+ registerLog(git);
973
+ }
974
+ getCommands() {
975
+ return [
976
+ {
977
+ name: "git init",
978
+ description: "Initialize a new git repository",
979
+ args: [{ name: "path", description: "Directory path", required: false, type: "string" }],
980
+ options: [],
981
+ examples: ["moxxy-agent git init ."]
982
+ },
983
+ {
984
+ name: "git clone",
985
+ description: "Clone a git repository",
986
+ args: [
987
+ { name: "url", description: "Repository URL", required: true, type: "string" },
988
+ { name: "directory", description: "Target directory", required: false, type: "string" }
989
+ ],
990
+ options: [
991
+ { name: "--branch", description: "Branch to clone", required: false, type: "string" }
992
+ ],
993
+ examples: ["moxxy-agent git clone https://github.com/org/repo --branch main"]
994
+ },
995
+ {
996
+ name: "git branch",
997
+ description: "Create or list branches",
998
+ args: [{ name: "name", description: "Branch name", required: false, type: "string" }],
999
+ options: [
1000
+ { name: "--list", description: "List all branches", required: false, type: "boolean" }
1001
+ ],
1002
+ examples: ["moxxy-agent git branch --list", "moxxy-agent git branch feat/new"]
1003
+ },
1004
+ {
1005
+ name: "git checkout",
1006
+ description: "Checkout a branch",
1007
+ args: [{ name: "branch", description: "Branch name", required: true, type: "string" }],
1008
+ options: [
1009
+ { name: "-b", description: "Create new branch", required: false, type: "boolean" }
1010
+ ],
1011
+ examples: ["moxxy-agent git checkout main", "moxxy-agent git checkout -b feat/new"]
1012
+ },
1013
+ {
1014
+ name: "git add",
1015
+ description: "Stage files for commit",
1016
+ args: [{ name: "files", description: "Files to stage", required: false, type: "string" }],
1017
+ options: [
1018
+ { name: "--all", description: "Stage all changes", required: false, type: "boolean" }
1019
+ ],
1020
+ examples: ["moxxy-agent git add src/main.ts", "moxxy-agent git add --all"]
1021
+ },
1022
+ {
1023
+ name: "git commit",
1024
+ description: "Create a commit",
1025
+ args: [],
1026
+ options: [
1027
+ { name: "-m", description: "Commit message", required: true, type: "string" }
1028
+ ],
1029
+ examples: ['moxxy-agent git commit -m "feat: add feature"']
1030
+ },
1031
+ {
1032
+ name: "git push",
1033
+ description: "Push commits to remote",
1034
+ args: [],
1035
+ options: [
1036
+ { name: "--set-upstream", description: "Set upstream tracking", required: false, type: "boolean" },
1037
+ { name: "--remote", description: "Remote name", required: false, type: "string" },
1038
+ { name: "--branch", description: "Branch name", required: false, type: "string" }
1039
+ ],
1040
+ examples: ["moxxy-agent git push", "moxxy-agent git push --set-upstream"]
1041
+ },
1042
+ {
1043
+ name: "git pull",
1044
+ description: "Pull changes from remote",
1045
+ args: [],
1046
+ options: [],
1047
+ examples: ["moxxy-agent git pull"]
1048
+ },
1049
+ {
1050
+ name: "git diff",
1051
+ description: "Show changes",
1052
+ args: [],
1053
+ options: [
1054
+ { name: "--staged", description: "Show staged changes", required: false, type: "boolean" }
1055
+ ],
1056
+ examples: ["moxxy-agent git diff", "moxxy-agent git diff --staged"]
1057
+ },
1058
+ {
1059
+ name: "git status",
1060
+ description: "Show working tree status",
1061
+ args: [],
1062
+ options: [],
1063
+ examples: ["moxxy-agent git status"]
1064
+ },
1065
+ {
1066
+ name: "git log",
1067
+ description: "Show commit log",
1068
+ args: [],
1069
+ options: [
1070
+ { name: "--limit", description: "Number of commits", required: false, type: "number" }
1071
+ ],
1072
+ examples: ["moxxy-agent git log --limit 20"]
1073
+ }
1074
+ ];
1075
+ }
1076
+ };
1077
+
1078
+ // src/plugins/search/code.ts
1079
+ function parseGrepOutput(raw) {
1080
+ return raw.split("\n").filter((line) => line.trim()).map((line) => {
1081
+ const firstColon = line.indexOf(":");
1082
+ const secondColon = line.indexOf(":", firstColon + 1);
1083
+ if (firstColon === -1 || secondColon === -1) {
1084
+ return { file: "", line: 0, content: line };
1085
+ }
1086
+ return {
1087
+ file: line.substring(0, firstColon),
1088
+ line: parseInt(line.substring(firstColon + 1, secondColon), 10) || 0,
1089
+ content: line.substring(secondColon + 1)
1090
+ };
1091
+ }).filter((m) => m.file);
1092
+ }
1093
+ function registerCode(parent) {
1094
+ parent.command("code").description("Search for code patterns").argument("<query>", "Search query (regex pattern)").option("--path <dir>", "Directory to search in", ".").option("--type <ext>", "File extension filter (e.g., ts, js)").action(async (query, opts) => {
1095
+ const startTime = Date.now();
1096
+ const cmd = "search code";
1097
+ try {
1098
+ let matches;
1099
+ try {
1100
+ const args = ["--line-number", "--no-heading", "--color", "never"];
1101
+ if (opts.type) {
1102
+ args.push("--type", opts.type);
1103
+ }
1104
+ args.push(query, opts.path);
1105
+ const { stdout } = await exec("rg", args);
1106
+ matches = parseGrepOutput(stdout);
1107
+ } catch {
1108
+ const args = ["-rn"];
1109
+ if (opts.type) {
1110
+ args.push("--include", `*.${opts.type}`);
1111
+ }
1112
+ args.push(query, opts.path);
1113
+ try {
1114
+ const { stdout } = await exec("grep", args);
1115
+ matches = parseGrepOutput(stdout);
1116
+ } catch (grepErr) {
1117
+ if (grepErr.code === 1) {
1118
+ matches = [];
1119
+ } else {
1120
+ throw grepErr;
1121
+ }
1122
+ }
1123
+ }
1124
+ output(success(cmd, { query, matches, count: matches.length }, startTime));
1125
+ } catch (err) {
1126
+ output(failure(cmd, "SEARCH_CODE_ERROR", err.message, startTime, err.stderr));
1127
+ }
1128
+ });
1129
+ }
1130
+
1131
+ // src/plugins/search/files.ts
1132
+ import * as path12 from "path";
1133
+ import { glob as glob2 } from "glob";
1134
+ function registerFiles(parent) {
1135
+ parent.command("files").description("Find files matching a glob pattern").argument("<pattern>", "Glob pattern").option("--path <dir>", "Directory to search in", ".").action(async (pattern, opts) => {
1136
+ const startTime = Date.now();
1137
+ const cmd = "search files";
1138
+ try {
1139
+ const searchDir = path12.resolve(opts.path);
1140
+ const matches = await glob2(pattern, {
1141
+ cwd: searchDir,
1142
+ nodir: false,
1143
+ dot: false,
1144
+ ignore: ["node_modules/**", ".git/**"]
1145
+ });
1146
+ const files = matches.map((match) => path12.join(searchDir, match));
1147
+ output(success(cmd, { pattern, files, count: files.length }, startTime));
1148
+ } catch (err) {
1149
+ output(failure(cmd, "SEARCH_FILES_ERROR", err.message, startTime));
1150
+ }
1151
+ });
1152
+ }
1153
+
1154
+ // src/plugins/search/docs.ts
1155
+ import * as fs13 from "fs";
1156
+ import * as path13 from "path";
1157
+ import { glob as glob3 } from "glob";
1158
+ function registerDocs(parent) {
1159
+ parent.command("docs").description("Search documentation files (README, markdown, comments)").argument("<query>", "Search query").option("--path <dir>", "Directory to search in", ".").action(async (query, opts) => {
1160
+ const startTime = Date.now();
1161
+ const cmd = "search docs";
1162
+ try {
1163
+ const searchDir = path13.resolve(opts.path);
1164
+ const docPatterns = ["**/*.md", "**/README*", "**/*.txt", "**/CHANGELOG*", "**/LICENSE*"];
1165
+ const matches = [];
1166
+ for (const pattern of docPatterns) {
1167
+ const files = await glob3(pattern, {
1168
+ cwd: searchDir,
1169
+ nodir: true,
1170
+ dot: false,
1171
+ ignore: ["node_modules/**", ".git/**"]
1172
+ });
1173
+ for (const file of files) {
1174
+ const fullPath = path13.join(searchDir, file);
1175
+ try {
1176
+ const content = fs13.readFileSync(fullPath, "utf-8");
1177
+ const lines = content.split("\n");
1178
+ const queryLower = query.toLowerCase();
1179
+ for (let i = 0; i < lines.length; i++) {
1180
+ if (lines[i].toLowerCase().includes(queryLower)) {
1181
+ matches.push({
1182
+ file,
1183
+ line: i + 1,
1184
+ content: lines[i].trim()
1185
+ });
1186
+ }
1187
+ }
1188
+ } catch {
1189
+ }
1190
+ }
1191
+ }
1192
+ output(success(cmd, { query, matches, count: matches.length }, startTime));
1193
+ } catch (err) {
1194
+ output(failure(cmd, "SEARCH_DOCS_ERROR", err.message, startTime));
1195
+ }
1196
+ });
1197
+ }
1198
+
1199
+ // src/plugins/search/index.ts
1200
+ var SearchPlugin = class {
1201
+ name = "search";
1202
+ version = "1.0.0";
1203
+ description = "Search operations (code, files, docs)";
1204
+ register(program) {
1205
+ const search = program.command("search").description(this.description);
1206
+ registerCode(search);
1207
+ registerFiles(search);
1208
+ registerDocs(search);
1209
+ }
1210
+ getCommands() {
1211
+ return [
1212
+ {
1213
+ name: "search code",
1214
+ description: "Search for code patterns using ripgrep/grep",
1215
+ args: [{ name: "query", description: "Regex pattern", required: true, type: "string" }],
1216
+ options: [
1217
+ { name: "--path", description: "Directory to search", required: false, type: "string" },
1218
+ { name: "--type", description: "File extension filter", required: false, type: "string" }
1219
+ ],
1220
+ examples: ['moxxy-agent search code "TODO" --type ts']
1221
+ },
1222
+ {
1223
+ name: "search files",
1224
+ description: "Find files matching a glob pattern",
1225
+ args: [{ name: "pattern", description: "Glob pattern", required: true, type: "string" }],
1226
+ options: [
1227
+ { name: "--path", description: "Directory to search", required: false, type: "string" }
1228
+ ],
1229
+ examples: ['moxxy-agent search files "**/*.ts" --path src']
1230
+ },
1231
+ {
1232
+ name: "search docs",
1233
+ description: "Search documentation files",
1234
+ args: [{ name: "query", description: "Search query", required: true, type: "string" }],
1235
+ options: [
1236
+ { name: "--path", description: "Directory to search", required: false, type: "string" }
1237
+ ],
1238
+ examples: ['moxxy-agent search docs "installation"']
1239
+ }
1240
+ ];
1241
+ }
1242
+ };
1243
+
1244
+ // src/plugins/pr/create.ts
1245
+ function registerCreate3(parent) {
1246
+ parent.command("create").description("Create a pull request").requiredOption("--title <text>", "PR title").option("--body <text>", "PR body/description").option("--base <branch>", "Base branch").action(async (opts) => {
1247
+ const startTime = Date.now();
1248
+ const cmd = "pr create";
1249
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
1250
+ try {
1251
+ const args = ["pr", "create", "--title", opts.title];
1252
+ if (opts.body) {
1253
+ args.push("--body", opts.body);
1254
+ }
1255
+ if (opts.base) {
1256
+ args.push("--base", opts.base);
1257
+ }
1258
+ log(`Creating PR: ${opts.title}`);
1259
+ const { stdout } = await exec("gh", args, { cwd });
1260
+ const url = stdout.trim();
1261
+ output(success(cmd, {
1262
+ url,
1263
+ title: opts.title,
1264
+ base: opts.base
1265
+ }, startTime));
1266
+ } catch (err) {
1267
+ output(failure(cmd, "PR_CREATE_ERROR", err.message, startTime, err.stderr));
1268
+ }
1269
+ });
1270
+ }
1271
+
1272
+ // src/plugins/pr/comment.ts
1273
+ function registerComment(parent) {
1274
+ parent.command("comment").description("Add a comment to a pull request").argument("<number>", "PR number").requiredOption("--body <text>", "Comment body").action(async (number, opts) => {
1275
+ const startTime = Date.now();
1276
+ const cmd = "pr comment";
1277
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
1278
+ try {
1279
+ const { stdout } = await exec(
1280
+ "gh",
1281
+ ["pr", "comment", number, "--body", opts.body],
1282
+ { cwd }
1283
+ );
1284
+ output(success(cmd, {
1285
+ prNumber: parseInt(number, 10),
1286
+ commented: true,
1287
+ url: stdout.trim()
1288
+ }, startTime));
1289
+ } catch (err) {
1290
+ output(failure(cmd, "PR_COMMENT_ERROR", err.message, startTime, err.stderr));
1291
+ }
1292
+ });
1293
+ }
1294
+
1295
+ // src/plugins/pr/index.ts
1296
+ var PRPlugin = class {
1297
+ name = "pr";
1298
+ version = "1.0.0";
1299
+ description = "Pull request operations (create, comment)";
1300
+ register(program) {
1301
+ const pr = program.command("pr").description(this.description);
1302
+ registerCreate3(pr);
1303
+ registerComment(pr);
1304
+ }
1305
+ getCommands() {
1306
+ return [
1307
+ {
1308
+ name: "pr create",
1309
+ description: "Create a pull request using gh CLI",
1310
+ args: [],
1311
+ options: [
1312
+ { name: "--title", description: "PR title", required: true, type: "string" },
1313
+ { name: "--body", description: "PR description", required: false, type: "string" },
1314
+ { name: "--base", description: "Base branch", required: false, type: "string" }
1315
+ ],
1316
+ examples: ['moxxy-agent pr create --title "feat: add feature" --base main']
1317
+ },
1318
+ {
1319
+ name: "pr comment",
1320
+ description: "Comment on a pull request",
1321
+ args: [{ name: "number", description: "PR number", required: true, type: "number" }],
1322
+ options: [
1323
+ { name: "--body", description: "Comment text", required: true, type: "string" }
1324
+ ],
1325
+ examples: ['moxxy-agent pr comment 42 --body "LGTM"']
1326
+ }
1327
+ ];
1328
+ }
1329
+ };
1330
+
1331
+ // src/plugins/workflow/run.ts
1332
+ import * as fs14 from "fs";
1333
+ import * as path14 from "path";
1334
+
1335
+ // ../types/dist/index.mjs
1336
+ import { z as z2 } from "zod";
1337
+ import { z } from "zod";
1338
+ import { z as z3 } from "zod";
1339
+ import { z as z4 } from "zod";
1340
+ import { z as z5 } from "zod";
1341
+ import { z as z6 } from "zod";
1342
+ import { z as z7 } from "zod";
1343
+ import { z as z8 } from "zod";
1344
+ import { z as z10 } from "zod";
1345
+ import { z as z9 } from "zod";
1346
+ import { z as z11 } from "zod";
1347
+ var uuidSchema = z.string().uuid();
1348
+ var timestampSchema = z.number().int().positive();
1349
+ var paginationSchema = z.object({
1350
+ page: z.number().int().positive().optional().default(1),
1351
+ limit: z.number().int().positive().max(100).optional().default(20),
1352
+ orderBy: z.string().optional(),
1353
+ order: z.enum(["asc", "desc"]).optional().default("desc")
1354
+ });
1355
+ var activityTypeSchema = z2.enum([
1356
+ "created",
1357
+ "assigned",
1358
+ "status_change",
1359
+ "comment",
1360
+ "commit",
1361
+ "pr_created",
1362
+ "pr_merged",
1363
+ "pr_closed"
1364
+ ]);
1365
+ var taskActivitySchema = z2.object({
1366
+ id: uuidSchema,
1367
+ taskId: uuidSchema,
1368
+ agentId: uuidSchema.nullable(),
1369
+ activityType: activityTypeSchema,
1370
+ description: z2.string().max(500),
1371
+ metadata: z2.record(z2.any()),
1372
+ createdAt: timestampSchema
1373
+ });
1374
+ var createActivitySchema = z2.object({
1375
+ taskId: uuidSchema,
1376
+ agentId: uuidSchema.nullable().optional(),
1377
+ activityType: activityTypeSchema,
1378
+ description: z2.string().max(500),
1379
+ metadata: z2.record(z2.any()).optional().default({})
1380
+ });
1381
+ var agentStatusSchema = z3.enum(["available", "busy", "offline"]);
1382
+ var agentTypeSchema = z3.enum([
1383
+ "developer",
1384
+ "prd",
1385
+ "code-review",
1386
+ "orchestrator",
1387
+ "custom"
1388
+ ]);
1389
+ var agentCapabilitySchema = z3.enum([
1390
+ "frontend",
1391
+ "backend",
1392
+ "fullstack",
1393
+ "devops",
1394
+ "testing",
1395
+ "documentation"
1396
+ ]);
1397
+ var agentIdentitySchema = z3.object({
1398
+ /** Display name for the agent (persona name) */
1399
+ displayName: z3.string().max(100).optional(),
1400
+ /** Theme/persona description */
1401
+ theme: z3.string().max(500).optional(),
1402
+ /** Emoji representation */
1403
+ emoji: z3.string().max(10).optional(),
1404
+ /** Avatar path or URL */
1405
+ avatar: z3.string().url().optional().or(z3.string().max(0)),
1406
+ /** Custom system prompt */
1407
+ systemPrompt: z3.string().max(1e4).optional()
1408
+ });
1409
+ var agentModelConfigSchema = z3.object({
1410
+ /** Primary model (provider/model format) */
1411
+ primary: z3.string().optional(),
1412
+ /** Fallback models in order of preference */
1413
+ fallbacks: z3.array(z3.string()).optional()
1414
+ });
1415
+ var agentSchema = z3.object({
1416
+ id: uuidSchema,
1417
+ name: z3.string().min(1).max(100),
1418
+ moltAgentId: z3.string().min(1),
1419
+ githubToken: z3.string().min(1),
1420
+ githubUsername: z3.string().min(1),
1421
+ workspace: z3.string().min(1),
1422
+ capabilities: z3.array(agentCapabilitySchema),
1423
+ status: agentStatusSchema,
1424
+ currentTaskId: uuidSchema.nullable(),
1425
+ agentType: agentTypeSchema.optional(),
1426
+ identity: agentIdentitySchema.optional(),
1427
+ modelConfig: agentModelConfigSchema.optional(),
1428
+ projectId: uuidSchema.optional(),
1429
+ lastSyncAt: timestampSchema,
1430
+ createdAt: timestampSchema,
1431
+ updatedAt: timestampSchema
1432
+ });
1433
+ var createAgentSchema = z3.object({
1434
+ name: z3.string().min(1).max(100),
1435
+ githubToken: z3.string().min(1),
1436
+ githubUsername: z3.string().min(1),
1437
+ capabilities: z3.array(agentCapabilitySchema).min(1),
1438
+ workspace: z3.string().min(1),
1439
+ /** Agent type for specialized behaviors */
1440
+ agentType: agentTypeSchema.optional(),
1441
+ /** Agent identity/persona configuration */
1442
+ identity: agentIdentitySchema.optional()
1443
+ });
1444
+ var updateAgentSchema = z3.object({
1445
+ name: z3.string().min(1).max(100).optional(),
1446
+ status: agentStatusSchema.optional(),
1447
+ workspace: z3.string().min(1).optional(),
1448
+ capabilities: z3.array(agentCapabilitySchema).optional(),
1449
+ /** Agent type for specialized behaviors */
1450
+ agentType: agentTypeSchema.optional(),
1451
+ /** Agent identity/persona configuration */
1452
+ identity: agentIdentitySchema.optional(),
1453
+ /** Model configuration update */
1454
+ modelConfig: agentModelConfigSchema.optional(),
1455
+ /** Update GitHub PAT token */
1456
+ githubToken: z3.string().min(1).optional(),
1457
+ /** Update GitHub username */
1458
+ githubUsername: z3.string().min(1).optional()
1459
+ });
1460
+ var taskFiltersSchema = z4.object({
1461
+ projectId: z4.string().uuid().optional(),
1462
+ status: z4.string().optional(),
1463
+ type: z4.string().optional(),
1464
+ priority: z4.string().optional(),
1465
+ assignedAgentId: z4.string().uuid().optional()
1466
+ });
1467
+ var INTEGRATION_TYPES = ["slack", "discord", "email", "github"];
1468
+ var NOTIFICATION_EVENTS = [
1469
+ "task:created",
1470
+ "task:completed",
1471
+ "task:failed",
1472
+ "task:assigned",
1473
+ "task:status_changed",
1474
+ "agent:status_changed",
1475
+ "pr:created",
1476
+ "pr:merged"
1477
+ ];
1478
+ var createIntegrationSchema = z5.object({
1479
+ type: z5.enum(INTEGRATION_TYPES),
1480
+ name: z5.string().min(1).max(100),
1481
+ enabled: z5.boolean().optional().default(false),
1482
+ config: z5.record(z5.unknown()),
1483
+ enabledEvents: z5.array(z5.enum(NOTIFICATION_EVENTS)).optional().default([])
1484
+ });
1485
+ var updateIntegrationSchema = z5.object({
1486
+ name: z5.string().min(1).max(100).optional(),
1487
+ enabled: z5.boolean().optional(),
1488
+ config: z5.record(z5.unknown()).optional(),
1489
+ enabledEvents: z5.array(z5.enum(NOTIFICATION_EVENTS)).optional()
1490
+ });
1491
+ var projectStatusSchema = z6.enum(["active", "archived", "paused"]);
1492
+ var workflowModeSchema = z6.enum(["manual", "automatic"]);
1493
+ var validationSettingsSchema = z6.object({
1494
+ runInstall: z6.boolean().optional(),
1495
+ runTests: z6.boolean().optional(),
1496
+ runBuild: z6.boolean().optional(),
1497
+ runLint: z6.boolean().optional(),
1498
+ blockOnFailure: z6.boolean().optional(),
1499
+ installCommand: z6.string().max(500).optional(),
1500
+ testCommand: z6.string().max(500).optional(),
1501
+ buildCommand: z6.string().max(500).optional(),
1502
+ lintCommand: z6.string().max(500).optional(),
1503
+ maxRetries: z6.number().int().min(0).max(100).optional(),
1504
+ preferSameAgent: z6.boolean().optional(),
1505
+ timeout: z6.number().int().min(1e3).max(36e5).optional()
1506
+ // 1s to 1h
1507
+ });
1508
+ var workflowSettingsSchema = z6.object({
1509
+ mode: workflowModeSchema,
1510
+ previewBranch: z6.string().min(1).max(100),
1511
+ autoMerge: z6.boolean().optional(),
1512
+ validation: validationSettingsSchema.optional()
1513
+ });
1514
+ var prdStatusSchema = z6.enum([
1515
+ "idle",
1516
+ "generating",
1517
+ "completed",
1518
+ "failed",
1519
+ "tasks_generating",
1520
+ "tasks_completed",
1521
+ "tasks_failed"
1522
+ ]);
1523
+ var prdTemplateSchema = z6.enum(["mobile", "web", "api", "feature", "data-pipeline"]);
1524
+ var prdTaskSchema = z6.object({
1525
+ id: z6.string(),
1526
+ prdId: z6.string(),
1527
+ step: z6.number(),
1528
+ title: z6.string(),
1529
+ description: z6.string(),
1530
+ status: z6.enum(["todo", "in_progress", "done", "blocked"]),
1531
+ priority: z6.enum(["P0", "P1", "P2"]),
1532
+ estimatedHours: z6.number().optional(),
1533
+ phase: z6.enum(["discovery", "design", "development", "testing", "deployment"]).optional(),
1534
+ createdAt: z6.string(),
1535
+ updatedAt: z6.string(),
1536
+ completedAt: z6.string().optional()
1537
+ });
1538
+ var projectSchema = z6.object({
1539
+ id: uuidSchema,
1540
+ name: z6.string().min(1).max(100),
1541
+ description: z6.string().max(500),
1542
+ githubRepoUrl: z6.string().url(),
1543
+ githubOwner: z6.string().min(1),
1544
+ githubRepo: z6.string().min(1),
1545
+ status: projectStatusSchema,
1546
+ defaultBranch: z6.string().min(1).max(100).optional(),
1547
+ workflowSettings: workflowSettingsSchema.optional(),
1548
+ assignedAgentIds: z6.array(uuidSchema).optional(),
1549
+ prd: z6.string().optional(),
1550
+ prdGeneratedAt: timestampSchema.optional(),
1551
+ prdStatus: prdStatusSchema.optional(),
1552
+ prdError: z6.string().optional(),
1553
+ prdTemplate: prdTemplateSchema.optional(),
1554
+ prdTasks: z6.array(prdTaskSchema).optional(),
1555
+ createdAt: timestampSchema,
1556
+ updatedAt: timestampSchema
1557
+ });
1558
+ var generatePRDInputSchema = z6.object({
1559
+ template: prdTemplateSchema.optional().default("feature")
1560
+ });
1561
+ var importPRDTasksInputSchema = z6.object({
1562
+ tasks: z6.array(
1563
+ z6.object({
1564
+ title: z6.string(),
1565
+ description: z6.string(),
1566
+ priority: z6.enum(["P0", "P1", "P2"]).optional(),
1567
+ estimatedHours: z6.number().optional(),
1568
+ phase: z6.string().optional()
1569
+ })
1570
+ ),
1571
+ taskType: z6.enum(["feature", "bug", "research", "refactor", "documentation"])
1572
+ });
1573
+ var updatePRDInputSchema = z6.object({
1574
+ prd: z6.string()
1575
+ });
1576
+ var createProjectSchema = z6.object({
1577
+ name: z6.string().min(1).max(100),
1578
+ description: z6.string().max(500),
1579
+ githubRepoUrl: z6.string().url()
1580
+ });
1581
+ var updateProjectSchema = z6.object({
1582
+ name: z6.string().min(1).max(100).optional(),
1583
+ description: z6.string().max(500).optional(),
1584
+ status: projectStatusSchema.optional(),
1585
+ defaultBranch: z6.string().min(1).max(100).optional(),
1586
+ workflowSettings: workflowSettingsSchema.optional()
1587
+ });
1588
+ var taskStatusSchema = z7.enum(["todo", "in_progress", "review", "done", "blocked"]);
1589
+ var taskTypeSchema = z7.enum(["feature", "bug", "research", "refactor", "documentation"]);
1590
+ var taskPrioritySchema = z7.enum(["low", "medium", "high", "urgent"]);
1591
+ var agentNoteTypeSchema = z7.enum([
1592
+ "progress",
1593
+ "summary",
1594
+ "error",
1595
+ "completion",
1596
+ "feedback"
1597
+ ]);
1598
+ var agentNoteSchema = z7.object({
1599
+ id: uuidSchema,
1600
+ agentId: uuidSchema,
1601
+ agentName: z7.string(),
1602
+ content: z7.string(),
1603
+ type: agentNoteTypeSchema,
1604
+ createdAt: timestampSchema,
1605
+ isUserFeedback: z7.boolean().optional()
1606
+ });
1607
+ var taskSchema = z7.object({
1608
+ id: uuidSchema,
1609
+ projectId: uuidSchema,
1610
+ title: z7.string().min(1).max(200),
1611
+ description: z7.string().max(2e3),
1612
+ type: taskTypeSchema,
1613
+ status: taskStatusSchema,
1614
+ priority: taskPrioritySchema,
1615
+ position: z7.number().int().default(0),
1616
+ // Manual ordering within status
1617
+ assignedAgentId: uuidSchema.nullable(),
1618
+ autoAssign: z7.boolean().default(true),
1619
+ // Whether agents should auto-pick this task
1620
+ agentNotes: z7.array(agentNoteSchema).default([]),
1621
+ githubIssueNumber: z7.number().int().positive().nullable(),
1622
+ githubPrNumber: z7.number().int().positive().nullable(),
1623
+ metadata: z7.record(z7.any()),
1624
+ blockedBy: z7.array(uuidSchema).default([]),
1625
+ // Task IDs that must be completed before this task
1626
+ blocking: z7.array(uuidSchema).default([]),
1627
+ // Task IDs that depend on this task
1628
+ createdAt: timestampSchema,
1629
+ updatedAt: timestampSchema,
1630
+ completedAt: timestampSchema.nullable()
1631
+ });
1632
+ var createTaskSchema = z7.object({
1633
+ projectId: uuidSchema,
1634
+ title: z7.string().min(1).max(200),
1635
+ description: z7.string().max(2e3),
1636
+ type: taskTypeSchema,
1637
+ priority: taskPrioritySchema.optional().default("medium"),
1638
+ assignedAgentId: uuidSchema.optional(),
1639
+ // Optional agent to assign on creation
1640
+ autoAssign: z7.boolean().optional().default(true),
1641
+ // Auto-assign to agents (default: true)
1642
+ blockedBy: z7.array(uuidSchema).optional()
1643
+ // Task IDs that must be completed before this task
1644
+ });
1645
+ var updateTaskSchema = z7.object({
1646
+ title: z7.string().min(1).max(200).optional(),
1647
+ description: z7.string().max(2e3).optional(),
1648
+ type: taskTypeSchema.optional(),
1649
+ status: taskStatusSchema.optional(),
1650
+ priority: taskPrioritySchema.optional(),
1651
+ position: z7.number().int().optional(),
1652
+ // Manual ordering within status
1653
+ assignedAgentId: uuidSchema.nullable().optional(),
1654
+ autoAssign: z7.boolean().optional(),
1655
+ // Whether agents should auto-pick this task
1656
+ githubIssueNumber: z7.number().int().positive().nullable().optional(),
1657
+ githubPrNumber: z7.number().int().positive().nullable().optional(),
1658
+ metadata: z7.record(z7.any()).optional(),
1659
+ blockedBy: z7.array(uuidSchema).optional()
1660
+ // Task IDs that must be completed before this task
1661
+ });
1662
+ var clientEventTypeSchema = z8.enum([
1663
+ "subscribe:project",
1664
+ "unsubscribe:project",
1665
+ "subscribe:task",
1666
+ "unsubscribe:task"
1667
+ ]);
1668
+ var serverEventTypeSchema = z8.enum([
1669
+ "task:created",
1670
+ "task:updated",
1671
+ "task:status_changed",
1672
+ "task:assigned",
1673
+ "task:progress",
1674
+ "task:stream",
1675
+ "task:note_added",
1676
+ "task:execution_cancelled",
1677
+ "task:dependencies_updated",
1678
+ "tasks:reordered",
1679
+ "agent:created",
1680
+ "agent:updated",
1681
+ "agent:status_changed",
1682
+ "agent:log",
1683
+ "activity:created",
1684
+ "project:updated",
1685
+ "project:prd_status_changed",
1686
+ "error"
1687
+ ]);
1688
+ var githubIssuePayloadSchema = z9.object({
1689
+ action: z9.string(),
1690
+ issueNumber: z9.number().int().positive(),
1691
+ title: z9.string(),
1692
+ body: z9.string().nullable(),
1693
+ labels: z9.array(z9.string()),
1694
+ author: z9.string(),
1695
+ repo: z9.object({
1696
+ owner: z9.string(),
1697
+ name: z9.string(),
1698
+ fullName: z9.string(),
1699
+ defaultBranch: z9.string(),
1700
+ cloneUrl: z9.string()
1701
+ }),
1702
+ url: z9.string().url(),
1703
+ createdAt: z9.string()
1704
+ });
1705
+ var ISSUE_TYPES = ["feature", "bug", "refactor", "docs", "test", "chore"];
1706
+ var ISSUE_PRIORITIES = ["low", "medium", "high", "urgent"];
1707
+ var ISSUE_COMPLEXITIES = ["trivial", "small", "medium", "large", "epic"];
1708
+ var issueClassificationSchema = z9.object({
1709
+ type: z9.enum(ISSUE_TYPES),
1710
+ priority: z9.enum(ISSUE_PRIORITIES),
1711
+ complexity: z9.enum(ISSUE_COMPLEXITIES),
1712
+ confidence: z9.number().min(0).max(1),
1713
+ reasoning: z9.string()
1714
+ });
1715
+ var PIPELINE_STAGES = [
1716
+ "triage",
1717
+ "research",
1718
+ "inspect",
1719
+ "plan",
1720
+ "implement"
1721
+ ];
1722
+ var PIPELINE_STATUSES = [
1723
+ "pending",
1724
+ "running",
1725
+ "completed",
1726
+ "failed",
1727
+ "cancelled"
1728
+ ];
1729
+ var pipelineStageResultSchema = z9.object({
1730
+ stage: z9.enum(PIPELINE_STAGES),
1731
+ status: z9.enum(PIPELINE_STATUSES),
1732
+ output: z9.unknown().optional(),
1733
+ error: z9.string().optional(),
1734
+ duration_ms: z9.number().optional()
1735
+ });
1736
+ var pipelineRunSchema = z9.object({
1737
+ id: z9.string(),
1738
+ issueNumber: z9.number().int().positive(),
1739
+ repo: z9.object({
1740
+ owner: z9.string(),
1741
+ name: z9.string()
1742
+ }),
1743
+ stages: z9.array(pipelineStageResultSchema),
1744
+ status: z9.enum(PIPELINE_STATUSES),
1745
+ branchName: z9.string().optional(),
1746
+ prNumber: z9.number().int().positive().optional(),
1747
+ classification: issueClassificationSchema.optional(),
1748
+ createdAt: z9.number(),
1749
+ updatedAt: z9.number()
1750
+ });
1751
+ var gatewayConfigSchema = z10.object({
1752
+ url: z10.string().url(),
1753
+ authToken: z10.string().optional(),
1754
+ deviceId: z10.string().optional(),
1755
+ devicePrivateKey: z10.string().optional()
1756
+ });
1757
+ var githubAuthConfigSchema = z10.object({
1758
+ token: z10.string(),
1759
+ webhookSecret: z10.string().optional(),
1760
+ appId: z10.string().optional(),
1761
+ privateKey: z10.string().optional()
1762
+ });
1763
+ var webhookServerConfigSchema = z10.object({
1764
+ port: z10.number().int().positive().default(3456),
1765
+ host: z10.string().default("0.0.0.0"),
1766
+ path: z10.string().default("/webhook/github")
1767
+ });
1768
+ var watchedRepoSchema = z10.object({
1769
+ owner: z10.string(),
1770
+ repo: z10.string(),
1771
+ defaultBranch: z10.string().default("main"),
1772
+ enabledEvents: z10.array(z10.string()).default(["issues.opened", "issues.labeled"]),
1773
+ labels: z10.array(z10.string()).optional()
1774
+ });
1775
+ var agentRunConfigSchema = z10.object({
1776
+ moltAgentId: z10.string().optional(),
1777
+ maxConcurrentTasks: z10.number().int().positive().default(1)
1778
+ });
1779
+ var sdkProviderSchema = z10.enum(["molt", "claude"]).default("molt");
1780
+ var claudeConfigSchema = z10.object({
1781
+ apiKey: z10.string().optional(),
1782
+ cliPath: z10.string().default("claude"),
1783
+ model: z10.string().default("claude-sonnet-4-5"),
1784
+ timeout: z10.number().int().positive().default(3e5),
1785
+ permissionMode: z10.string().default("default")
1786
+ });
1787
+ var pipelineConfigSchema = z10.object({
1788
+ enabledStages: z10.array(z10.enum(PIPELINE_STAGES)).default(["triage", "research", "inspect", "plan", "implement"])
1789
+ });
1790
+ var moxxyConfigSchema = z10.object({
1791
+ version: z10.number().int().positive().default(1),
1792
+ sdk: sdkProviderSchema,
1793
+ gateway: gatewayConfigSchema.optional(),
1794
+ github: githubAuthConfigSchema,
1795
+ webhook: webhookServerConfigSchema.optional(),
1796
+ repos: z10.array(watchedRepoSchema).default([]),
1797
+ agent: agentRunConfigSchema.optional(),
1798
+ pipeline: pipelineConfigSchema.optional(),
1799
+ claude: claudeConfigSchema.optional()
1800
+ });
1801
+ var agentCommandResultSchema = z11.object({
1802
+ success: z11.boolean(),
1803
+ command: z11.string(),
1804
+ data: z11.unknown().optional(),
1805
+ error: z11.object({
1806
+ code: z11.string(),
1807
+ message: z11.string(),
1808
+ details: z11.string().optional()
1809
+ }).optional(),
1810
+ duration_ms: z11.number()
1811
+ });
1812
+ var argDefSchema = z11.object({
1813
+ name: z11.string(),
1814
+ description: z11.string(),
1815
+ required: z11.boolean().default(false),
1816
+ type: z11.enum(["string", "number", "boolean"]).default("string")
1817
+ });
1818
+ var optionDefSchema = z11.object({
1819
+ name: z11.string(),
1820
+ short: z11.string().optional(),
1821
+ description: z11.string(),
1822
+ required: z11.boolean().default(false),
1823
+ type: z11.enum(["string", "number", "boolean"]).default("string"),
1824
+ defaultValue: z11.unknown().optional()
1825
+ });
1826
+ var agentCLICommandDefSchema = z11.object({
1827
+ name: z11.string(),
1828
+ description: z11.string(),
1829
+ args: z11.array(argDefSchema),
1830
+ options: z11.array(optionDefSchema),
1831
+ examples: z11.array(z11.string())
1832
+ });
1833
+ var workflowStepSchema = z11.object({
1834
+ id: z11.string(),
1835
+ plugin: z11.string(),
1836
+ command: z11.string(),
1837
+ args: z11.record(z11.unknown()),
1838
+ description: z11.string(),
1839
+ dependsOn: z11.array(z11.string()).optional(),
1840
+ optional: z11.boolean().optional()
1841
+ });
1842
+ var workflowSchema = z11.object({
1843
+ id: z11.string(),
1844
+ name: z11.string(),
1845
+ description: z11.string(),
1846
+ steps: z11.array(workflowStepSchema),
1847
+ context: z11.record(z11.unknown())
1848
+ });
1849
+ var workflowStepResultSchema = z11.object({
1850
+ stepId: z11.string(),
1851
+ result: agentCommandResultSchema,
1852
+ skipped: z11.boolean().default(false)
1853
+ });
1854
+ var workflowResultSchema = z11.object({
1855
+ workflowId: z11.string(),
1856
+ success: z11.boolean(),
1857
+ stepResults: z11.array(workflowStepResultSchema),
1858
+ duration_ms: z11.number()
1859
+ });
1860
+
1861
+ // src/plugins/workflow/run.ts
1862
+ async function executeStep(step, cwd) {
1863
+ const args = [step.plugin, step.command];
1864
+ for (const [key, value] of Object.entries(step.args)) {
1865
+ if (typeof value === "boolean") {
1866
+ if (value) args.push(`--${key}`);
1867
+ } else {
1868
+ args.push(`--${key}`, String(value));
1869
+ }
1870
+ }
1871
+ const startTime = Date.now();
1872
+ try {
1873
+ const { stdout } = await exec("moxxy-agent", args, { cwd });
1874
+ const result = JSON.parse(stdout.trim());
1875
+ return { stepId: step.id, result, skipped: false };
1876
+ } catch (err) {
1877
+ return {
1878
+ stepId: step.id,
1879
+ result: {
1880
+ success: false,
1881
+ command: `${step.plugin} ${step.command}`,
1882
+ error: { code: "STEP_FAILED", message: err.message },
1883
+ duration_ms: Date.now() - startTime
1884
+ },
1885
+ skipped: false
1886
+ };
1887
+ }
1888
+ }
1889
+ function topologicalSort(steps) {
1890
+ const visited = /* @__PURE__ */ new Set();
1891
+ const sorted = [];
1892
+ const stepsById = new Map(steps.map((s) => [s.id, s]));
1893
+ function visit(step) {
1894
+ if (visited.has(step.id)) return;
1895
+ visited.add(step.id);
1896
+ for (const depId of step.dependsOn || []) {
1897
+ const dep = stepsById.get(depId);
1898
+ if (dep) visit(dep);
1899
+ }
1900
+ sorted.push(step);
1901
+ }
1902
+ for (const step of steps) {
1903
+ visit(step);
1904
+ }
1905
+ return sorted;
1906
+ }
1907
+ function registerRun(parent) {
1908
+ parent.command("run").description("Run a workflow from a JSON file").argument("<workflow-file>", "Path to workflow JSON file").action(async (workflowFile) => {
1909
+ const startTime = Date.now();
1910
+ const cmd = "workflow run";
1911
+ const cwd = parent.optsWithGlobals().cwd || process.cwd();
1912
+ try {
1913
+ const filePath = path14.resolve(workflowFile);
1914
+ if (!fs14.existsSync(filePath)) {
1915
+ output(failure(cmd, "NOT_FOUND", `Workflow file not found: ${filePath}`, startTime));
1916
+ return;
1917
+ }
1918
+ const raw = JSON.parse(fs14.readFileSync(filePath, "utf-8"));
1919
+ const workflow = workflowSchema.parse(raw);
1920
+ log(`Running workflow: ${workflow.name}`);
1921
+ const sortedSteps = topologicalSort(workflow.steps);
1922
+ const stepResults = [];
1923
+ const completedSteps = /* @__PURE__ */ new Set();
1924
+ let allSuccess = true;
1925
+ for (const step of sortedSteps) {
1926
+ const depsFailed = (step.dependsOn || []).some((depId) => {
1927
+ const depResult = stepResults.find((r) => r.stepId === depId);
1928
+ return depResult && !depResult.result.success;
1929
+ });
1930
+ if (depsFailed) {
1931
+ if (step.optional) {
1932
+ stepResults.push({
1933
+ stepId: step.id,
1934
+ result: {
1935
+ success: false,
1936
+ command: `${step.plugin} ${step.command}`,
1937
+ error: {
1938
+ code: "SKIPPED",
1939
+ message: "Skipped due to failed dependency"
1940
+ },
1941
+ duration_ms: 0
1942
+ },
1943
+ skipped: true
1944
+ });
1945
+ continue;
1946
+ }
1947
+ allSuccess = false;
1948
+ stepResults.push({
1949
+ stepId: step.id,
1950
+ result: {
1951
+ success: false,
1952
+ command: `${step.plugin} ${step.command}`,
1953
+ error: {
1954
+ code: "DEP_FAILED",
1955
+ message: "Dependency failed, step not executed"
1956
+ },
1957
+ duration_ms: 0
1958
+ },
1959
+ skipped: true
1960
+ });
1961
+ continue;
1962
+ }
1963
+ log(` Step: ${step.id} - ${step.description}`);
1964
+ const result = await executeStep(step, cwd);
1965
+ stepResults.push(result);
1966
+ if (result.result.success) {
1967
+ completedSteps.add(step.id);
1968
+ } else {
1969
+ allSuccess = false;
1970
+ if (!step.optional) {
1971
+ log(` Step ${step.id} failed, stopping workflow`);
1972
+ for (const remaining of sortedSteps) {
1973
+ if (!stepResults.find((r) => r.stepId === remaining.id)) {
1974
+ stepResults.push({
1975
+ stepId: remaining.id,
1976
+ result: {
1977
+ success: false,
1978
+ command: `${remaining.plugin} ${remaining.command}`,
1979
+ error: {
1980
+ code: "SKIPPED",
1981
+ message: "Skipped due to earlier failure"
1982
+ },
1983
+ duration_ms: 0
1984
+ },
1985
+ skipped: true
1986
+ });
1987
+ }
1988
+ }
1989
+ break;
1990
+ }
1991
+ }
1992
+ }
1993
+ const workflowResult = {
1994
+ workflowId: workflow.id,
1995
+ success: allSuccess,
1996
+ stepResults,
1997
+ duration_ms: Date.now() - startTime
1998
+ };
1999
+ output(success(cmd, workflowResult, startTime));
2000
+ } catch (err) {
2001
+ output(failure(cmd, "WORKFLOW_RUN_ERROR", err.message, startTime));
2002
+ }
2003
+ });
2004
+ }
2005
+
2006
+ // src/plugins/workflow/status.ts
2007
+ function registerStatus2(parent) {
2008
+ parent.command("status").description("Show status of running workflows").action(async () => {
2009
+ const startTime = Date.now();
2010
+ const cmd = "workflow status";
2011
+ output(success(cmd, {
2012
+ running: [],
2013
+ message: "No workflows currently running"
2014
+ }, startTime));
2015
+ });
2016
+ }
2017
+
2018
+ // src/plugins/workflow/index.ts
2019
+ var WorkflowPlugin = class {
2020
+ name = "workflow";
2021
+ version = "1.0.0";
2022
+ description = "Workflow orchestration (run, status)";
2023
+ register(program) {
2024
+ const workflow = program.command("workflow").description(this.description);
2025
+ registerRun(workflow);
2026
+ registerStatus2(workflow);
2027
+ }
2028
+ getCommands() {
2029
+ return [
2030
+ {
2031
+ name: "workflow run",
2032
+ description: "Run a workflow from a JSON definition file",
2033
+ args: [
2034
+ { name: "workflow-file", description: "Path to workflow JSON", required: true, type: "string" }
2035
+ ],
2036
+ options: [],
2037
+ examples: ["moxxy-agent workflow run deploy.json"]
2038
+ },
2039
+ {
2040
+ name: "workflow status",
2041
+ description: "Show status of running workflows",
2042
+ args: [],
2043
+ options: [],
2044
+ examples: ["moxxy-agent workflow status"]
2045
+ }
2046
+ ];
2047
+ }
2048
+ };
2049
+
2050
+ // src/core/plugin-loader.ts
2051
+ function loadBuiltinPlugins(registry) {
2052
+ registry.register(new WorkspacePlugin());
2053
+ registry.register(new FilePlugin());
2054
+ registry.register(new DirPlugin());
2055
+ registry.register(new GitPlugin());
2056
+ registry.register(new SearchPlugin());
2057
+ registry.register(new PRPlugin());
2058
+ registry.register(new WorkflowPlugin());
2059
+ }
2060
+
2061
+ // src/help/index.ts
2062
+ function showHelp(registry) {
2063
+ log("");
2064
+ log("moxxy-agent - Agent-facing CLI tool for structured operations");
2065
+ log("");
2066
+ log("Usage: moxxy-agent [options] <plugin> <command> [args...]");
2067
+ log("");
2068
+ log("Global Options:");
2069
+ log(" --cwd <path> Set working directory");
2070
+ log(" --verbose Enable verbose logging");
2071
+ log(" -h, --help Show help");
2072
+ log(" -V, --version Show version");
2073
+ log("");
2074
+ log("Plugins:");
2075
+ for (const plugin of registry.getAll()) {
2076
+ log(` ${plugin.name.padEnd(15)} ${plugin.description}`);
2077
+ for (const cmd of plugin.getCommands()) {
2078
+ log(` ${cmd.name.padEnd(25)} ${cmd.description}`);
2079
+ }
2080
+ log("");
2081
+ }
2082
+ }
2083
+
2084
+ // src/cli.ts
2085
+ function createProgram() {
2086
+ const program = new Command();
2087
+ const registry = new PluginRegistry();
2088
+ program.name("moxxy-agent").description("Agent-facing CLI tool for structured operations").version("1.0.0").option("--cwd <path>", "Set working directory").option("--verbose", "Enable verbose logging");
2089
+ loadBuiltinPlugins(registry);
2090
+ for (const plugin of registry.getAll()) {
2091
+ plugin.register(program);
2092
+ }
2093
+ program.on("--help", () => {
2094
+ showHelp(registry);
2095
+ });
2096
+ return program;
2097
+ }
2098
+
2099
+ export {
2100
+ PluginRegistry,
2101
+ detectWorkspace,
2102
+ getContext,
2103
+ success,
2104
+ failure,
2105
+ output,
2106
+ log,
2107
+ createProgram
2108
+ };