mthds 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/binaries.d.ts +14 -1
  3. package/dist/agent/binaries.js +21 -6
  4. package/dist/agent/binaries.js.map +1 -1
  5. package/dist/agent/commands/api-commands.d.ts +13 -0
  6. package/dist/agent/commands/api-commands.js +494 -0
  7. package/dist/agent/commands/api-commands.js.map +1 -0
  8. package/dist/agent/commands/doctor.js +25 -17
  9. package/dist/agent/commands/doctor.js.map +1 -1
  10. package/dist/agent/commands/install.js +2 -2
  11. package/dist/agent/commands/install.js.map +1 -1
  12. package/dist/agent/commands/pipelex-commands.d.ts +13 -0
  13. package/dist/agent/commands/pipelex-commands.js +63 -0
  14. package/dist/agent/commands/pipelex-commands.js.map +1 -0
  15. package/dist/agent/commands/pipelex-passthrough.d.ts +15 -0
  16. package/dist/agent/commands/pipelex-passthrough.js +43 -0
  17. package/dist/agent/commands/pipelex-passthrough.js.map +1 -0
  18. package/dist/agent/commands/update-check.d.ts +16 -0
  19. package/dist/agent/commands/update-check.js +169 -0
  20. package/dist/agent/commands/update-check.js.map +1 -0
  21. package/dist/agent/commands/upgrade.d.ts +17 -0
  22. package/dist/agent/commands/upgrade.js +155 -0
  23. package/dist/agent/commands/upgrade.js.map +1 -0
  24. package/dist/agent/passthrough.d.ts +1 -0
  25. package/dist/agent/passthrough.js +93 -32
  26. package/dist/agent/passthrough.js.map +1 -1
  27. package/dist/agent/snooze.d.ts +32 -0
  28. package/dist/agent/snooze.js +108 -0
  29. package/dist/agent/snooze.js.map +1 -0
  30. package/dist/agent/update-cache.d.ts +43 -0
  31. package/dist/agent/update-cache.js +125 -0
  32. package/dist/agent/update-cache.js.map +1 -0
  33. package/dist/agent-cli.d.ts +8 -2
  34. package/dist/agent-cli.js +132 -124
  35. package/dist/agent-cli.js.map +1 -1
  36. package/dist/cli/commands/install.js +3 -3
  37. package/dist/cli/commands/install.js.map +1 -1
  38. package/dist/config/credentials.d.ts +2 -0
  39. package/dist/config/credentials.js +64 -33
  40. package/dist/config/credentials.js.map +1 -1
  41. package/dist/installer/runtime/installer.d.ts +12 -6
  42. package/dist/installer/runtime/installer.js +49 -25
  43. package/dist/installer/runtime/installer.js.map +1 -1
  44. package/dist/installer/runtime/version-check.d.ts +31 -0
  45. package/dist/installer/runtime/version-check.js +78 -0
  46. package/dist/installer/runtime/version-check.js.map +1 -0
  47. package/dist/runners/api-runner.d.ts +2 -2
  48. package/dist/runners/api-runner.js +2 -2
  49. package/dist/runners/api-runner.js.map +1 -1
  50. package/dist/runners/pipelex-runner.d.ts +2 -2
  51. package/dist/runners/pipelex-runner.js +11 -37
  52. package/dist/runners/pipelex-runner.js.map +1 -1
  53. package/dist/runners/types.d.ts +10 -12
  54. package/package.json +1 -1
  55. package/dist/agent/commands/build.d.ts +0 -32
  56. package/dist/agent/commands/build.js +0 -291
  57. package/dist/agent/commands/build.js.map +0 -1
  58. package/dist/agent/commands/runner-commands.d.ts +0 -20
  59. package/dist/agent/commands/runner-commands.js +0 -800
  60. package/dist/agent/commands/runner-commands.js.map +0 -1
@@ -1,800 +0,0 @@
1
- /**
2
- * Runner-aware commands — registered at the top level.
3
- *
4
- * mthds-agent [--runner <type>] <cmd> [args...]
5
- *
6
- * Runner resolution: --runner flag → default runner from config.
7
- * For pipelex runner: run and validate use passthrough for full CLI compatibility.
8
- * For all runners: concept, pipe, assemble, inputs, models use the Runner interface.
9
- */
10
- import { existsSync, readFileSync, statSync } from "node:fs";
11
- import { join } from "node:path";
12
- import { agentError, agentSuccess, AGENT_ERROR_DOMAINS } from "../output.js";
13
- import { createRunner } from "../../runners/registry.js";
14
- import { isPipelexRunner } from "../../cli/commands/utils.js";
15
- function collect(val, prev) {
16
- return [...prev, val];
17
- }
18
- /**
19
- * Try to read `value` as a file path; if the file does not exist (ENOENT),
20
- * treat `value` as inline content and return it as-is.
21
- */
22
- export function resolveFileOrInline(value) {
23
- try {
24
- return readFileSync(value, "utf-8");
25
- }
26
- catch (err) {
27
- if (err.code === "ENOENT") {
28
- return value;
29
- }
30
- throw err;
31
- }
32
- }
33
- /** Extract raw args after a command keyword, filtering out global options */
34
- function extractPassthroughArgs(keyword) {
35
- const argv = process.argv;
36
- const idx = argv.indexOf(keyword);
37
- if (idx === -1)
38
- return [];
39
- const raw = argv.slice(idx + 1);
40
- const result = [];
41
- let i = 0;
42
- while (i < raw.length) {
43
- if (raw[i] === "--runner" ||
44
- raw[i] === "-L" ||
45
- raw[i] === "--library-dir" ||
46
- raw[i] === "--log-level") {
47
- i += 2;
48
- }
49
- else if (raw[i].startsWith("--runner=") ||
50
- raw[i].startsWith("--library-dir=") ||
51
- raw[i].startsWith("--log-level=")) {
52
- i += 1;
53
- }
54
- else if (raw[i] === "--auto-install") {
55
- i += 1;
56
- }
57
- else {
58
- result.push(raw[i]);
59
- i++;
60
- }
61
- }
62
- return result;
63
- }
64
- /**
65
- * Register all runner-aware commands directly on the program.
66
- * Uses --runner flag or default runner from config.
67
- */
68
- export function registerRunnerCommands(program, logLevelArgs, _autoInstall) {
69
- const getLibraryDirs = () => (program.optsWithGlobals().libraryDir ?? []);
70
- function makeRunner() {
71
- const runnerType = program.optsWithGlobals().runner;
72
- const libraryDirs = getLibraryDirs();
73
- return createRunner(runnerType, libraryDirs.length ? libraryDirs : undefined);
74
- }
75
- // ── concept ──
76
- program
77
- .command("concept")
78
- .description("Structure a concept from JSON spec and output TOML")
79
- .option("--spec <json>", "JSON string with concept specification")
80
- .option("--spec-file <path>", "Path to JSON file with concept specification")
81
- .allowUnknownOption()
82
- .allowExcessArguments(true)
83
- .exitOverride()
84
- .action(async (options) => {
85
- let runner;
86
- try {
87
- runner = makeRunner();
88
- }
89
- catch (err) {
90
- agentError(err.message, "RunnerError", {
91
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
92
- });
93
- }
94
- let specStr = options.spec;
95
- if (!specStr && options.specFile) {
96
- try {
97
- specStr = readFileSync(options.specFile, "utf-8");
98
- }
99
- catch (err) {
100
- agentError(`Cannot read spec file: ${err.message}`, "IOError", {
101
- error_domain: AGENT_ERROR_DOMAINS.IO,
102
- });
103
- }
104
- }
105
- if (!specStr) {
106
- agentError("--spec or --spec-file is required.", "ArgumentError", {
107
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
108
- });
109
- }
110
- let spec;
111
- try {
112
- spec = JSON.parse(specStr);
113
- }
114
- catch {
115
- agentError("--spec must be valid JSON.", "ArgumentError", {
116
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
117
- });
118
- }
119
- try {
120
- const result = await runner.concept({ spec });
121
- agentSuccess({ ...result });
122
- }
123
- catch (err) {
124
- agentError(err.message, "RunnerError", {
125
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
126
- });
127
- }
128
- });
129
- // ── pipe ──
130
- program
131
- .command("pipe")
132
- .description("Structure a pipe from JSON spec and output TOML")
133
- .option("--type <type>", "Pipe type (PipeLLM, PipeSequence, etc.)")
134
- .option("--spec <json>", "JSON string with pipe specification")
135
- .option("--spec-file <path>", "Path to JSON file with pipe specification")
136
- .allowUnknownOption()
137
- .allowExcessArguments(true)
138
- .exitOverride()
139
- .action(async (options) => {
140
- let runner;
141
- try {
142
- runner = makeRunner();
143
- }
144
- catch (err) {
145
- agentError(err.message, "RunnerError", {
146
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
147
- });
148
- }
149
- if (!options.type) {
150
- agentError("--type is required.", "ArgumentError", {
151
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
152
- });
153
- }
154
- let specStr = options.spec;
155
- if (!specStr && options.specFile) {
156
- try {
157
- specStr = readFileSync(options.specFile, "utf-8");
158
- }
159
- catch (err) {
160
- agentError(`Cannot read spec file: ${err.message}`, "IOError", {
161
- error_domain: AGENT_ERROR_DOMAINS.IO,
162
- });
163
- }
164
- }
165
- if (!specStr) {
166
- agentError("--spec or --spec-file is required.", "ArgumentError", {
167
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
168
- });
169
- }
170
- let spec;
171
- try {
172
- spec = JSON.parse(specStr);
173
- }
174
- catch {
175
- agentError("--spec must be valid JSON.", "ArgumentError", {
176
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
177
- });
178
- }
179
- try {
180
- const result = await runner.pipeSpec({ pipe_type: options.type, spec });
181
- agentSuccess({ ...result });
182
- }
183
- catch (err) {
184
- agentError(err.message, "RunnerError", {
185
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
186
- });
187
- }
188
- });
189
- // ── assemble ──
190
- program
191
- .command("assemble")
192
- .description("Assemble a complete .mthds bundle from TOML parts")
193
- .requiredOption("--domain <domain>", "Domain code for the bundle")
194
- .requiredOption("--main-pipe <pipe>", "Main pipe code for the bundle")
195
- .option("--description <desc>", "Description of the bundle")
196
- .option("--system-prompt <prompt>", "Default system prompt for LLM pipes")
197
- .option("--concepts <toml>", "TOML for concepts (repeatable)", collect, [])
198
- .option("--pipes <toml>", "TOML for pipes (repeatable)", collect, [])
199
- .allowUnknownOption()
200
- .allowExcessArguments(true)
201
- .exitOverride()
202
- .action(async (options) => {
203
- let runner;
204
- try {
205
- runner = makeRunner();
206
- }
207
- catch (err) {
208
- agentError(err.message, "RunnerError", {
209
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
210
- });
211
- }
212
- // Read file contents for concepts/pipes so both runners get TOML content
213
- let concepts;
214
- if (options.concepts?.length) {
215
- try {
216
- concepts = options.concepts.map(resolveFileOrInline);
217
- }
218
- catch (err) {
219
- agentError(`Failed to read concept file: ${err.message}`, "FileError", {
220
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
221
- });
222
- return;
223
- }
224
- }
225
- let pipes;
226
- if (options.pipes?.length) {
227
- try {
228
- pipes = options.pipes.map(resolveFileOrInline);
229
- }
230
- catch (err) {
231
- agentError(`Failed to read pipe file: ${err.message}`, "FileError", {
232
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
233
- });
234
- return;
235
- }
236
- }
237
- const request = {
238
- domain: options.domain,
239
- main_pipe: options.mainPipe,
240
- description: options.description,
241
- system_prompt: options.systemPrompt,
242
- concepts,
243
- pipes,
244
- };
245
- try {
246
- const result = await runner.assemble(request);
247
- agentSuccess({ ...result });
248
- }
249
- catch (err) {
250
- agentError(err.message, "RunnerError", {
251
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
252
- });
253
- }
254
- });
255
- // ── validate ──
256
- const validateGroup = program
257
- .command("validate")
258
- .description("Validate a method, pipe, or bundle")
259
- .passThroughOptions()
260
- .allowUnknownOption();
261
- validateGroup
262
- .command("bundle")
263
- .argument("[target]", "Bundle file (.mthds) or directory")
264
- .option("--pipe <code>", "Pipe code to validate within the bundle")
265
- .option("--content <mthds>", "Bundle content as a string (alternative to file path)")
266
- .description("Validate a bundle file or content")
267
- .allowUnknownOption()
268
- .allowExcessArguments(true)
269
- .exitOverride()
270
- .action(async (target, options) => {
271
- let runner;
272
- try {
273
- runner = makeRunner();
274
- }
275
- catch (err) {
276
- agentError(err.message, "RunnerError", {
277
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
278
- });
279
- }
280
- // Passthrough for pipelex runner (forwards all CLI flags like --graph)
281
- if (isPipelexRunner(runner)) {
282
- try {
283
- await runner.validatePassthrough([...logLevelArgs(), ...extractPassthroughArgs("validate")]);
284
- }
285
- catch (err) {
286
- agentError(err.message, "ValidationError", {
287
- error_domain: AGENT_ERROR_DOMAINS.VALIDATION,
288
- });
289
- }
290
- return;
291
- }
292
- let mthdsContent;
293
- if (options.content) {
294
- mthdsContent = options.content;
295
- }
296
- else if (target) {
297
- try {
298
- mthdsContent = readFileSync(target, "utf-8");
299
- }
300
- catch (err) {
301
- agentError(`Cannot read bundle: ${err.message}`, "IOError", {
302
- error_domain: AGENT_ERROR_DOMAINS.IO,
303
- });
304
- }
305
- }
306
- else {
307
- agentError("Either <target> or --content is required.", "ArgumentError", {
308
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
309
- });
310
- }
311
- try {
312
- const result = await runner.validate({
313
- mthds_contents: [mthdsContent],
314
- pipe_code: options.pipe,
315
- });
316
- if (result.success) {
317
- agentSuccess({ ...result });
318
- }
319
- else {
320
- agentError(result.message, "ValidationError", {
321
- error_domain: AGENT_ERROR_DOMAINS.VALIDATION,
322
- });
323
- }
324
- }
325
- catch (err) {
326
- agentError(err.message, "RunnerError", {
327
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
328
- });
329
- }
330
- });
331
- validateGroup
332
- .command("pipe")
333
- .argument("<target>", "Pipe code or .mthds bundle file")
334
- .option("--pipe <code>", "Pipe code to validate")
335
- .option("--bundle <file>", "Bundle file path (alternative to positional)")
336
- .description("Validate a pipe by code or bundle file")
337
- .allowUnknownOption()
338
- .allowExcessArguments(true)
339
- .exitOverride()
340
- .action(async (target, options) => {
341
- let runner;
342
- try {
343
- runner = makeRunner();
344
- }
345
- catch (err) {
346
- agentError(err.message, "RunnerError", {
347
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
348
- });
349
- }
350
- // Passthrough for pipelex runner
351
- if (isPipelexRunner(runner)) {
352
- try {
353
- await runner.validatePassthrough([...logLevelArgs(), ...extractPassthroughArgs("validate")]);
354
- }
355
- catch (err) {
356
- agentError(err.message, "ValidationError", {
357
- error_domain: AGENT_ERROR_DOMAINS.VALIDATION,
358
- });
359
- }
360
- return;
361
- }
362
- if (target.endsWith(".mthds")) {
363
- let mthdsContent;
364
- try {
365
- mthdsContent = readFileSync(target, "utf-8");
366
- }
367
- catch (err) {
368
- agentError(`Cannot read bundle: ${err.message}`, "IOError", {
369
- error_domain: AGENT_ERROR_DOMAINS.IO,
370
- });
371
- }
372
- try {
373
- const result = await runner.validate({
374
- mthds_contents: [mthdsContent],
375
- pipe_code: options.pipe,
376
- });
377
- if (result.success) {
378
- agentSuccess({ ...result });
379
- }
380
- else {
381
- agentError(result.message, "ValidationError", {
382
- error_domain: AGENT_ERROR_DOMAINS.VALIDATION,
383
- });
384
- }
385
- }
386
- catch (err) {
387
- agentError(err.message, "RunnerError", {
388
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
389
- });
390
- }
391
- }
392
- else {
393
- try {
394
- const result = await runner.validate({ pipe_code: target });
395
- if (result.success) {
396
- agentSuccess({ ...result });
397
- }
398
- else {
399
- agentError(result.message, "ValidationError", {
400
- error_domain: AGENT_ERROR_DOMAINS.VALIDATION,
401
- });
402
- }
403
- }
404
- catch (err) {
405
- agentError(err.message, "RunnerError", {
406
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
407
- });
408
- }
409
- }
410
- });
411
- validateGroup
412
- .command("method")
413
- .argument("<target>", "Method name, GitHub URL, or local path")
414
- .option("--pipe <code>", "Pipe code to validate")
415
- .description("Validate a method")
416
- .allowUnknownOption()
417
- .allowExcessArguments(true)
418
- .exitOverride()
419
- .action(async (target, options) => {
420
- let runner;
421
- try {
422
- runner = makeRunner();
423
- }
424
- catch (err) {
425
- agentError(err.message, "RunnerError", {
426
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
427
- });
428
- }
429
- // Passthrough for pipelex runner
430
- if (isPipelexRunner(runner)) {
431
- try {
432
- await runner.validatePassthrough([...logLevelArgs(), ...extractPassthroughArgs("validate")]);
433
- }
434
- catch (err) {
435
- agentError(err.message, "ValidationError", {
436
- error_domain: AGENT_ERROR_DOMAINS.VALIDATION,
437
- });
438
- }
439
- return;
440
- }
441
- try {
442
- const result = await runner.validate({
443
- method_url: target,
444
- pipe_code: options.pipe,
445
- });
446
- if (result.success) {
447
- agentSuccess({ ...result });
448
- }
449
- else {
450
- agentError(result.message, "ValidationError", {
451
- error_domain: AGENT_ERROR_DOMAINS.VALIDATION,
452
- });
453
- }
454
- }
455
- catch (err) {
456
- agentError(err.message, "RunnerError", {
457
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
458
- });
459
- }
460
- });
461
- // ── inputs ──
462
- const inputsGroup = program
463
- .command("inputs")
464
- .description("Generate example input JSON for a pipe")
465
- .passThroughOptions()
466
- .allowUnknownOption();
467
- inputsGroup
468
- .command("bundle")
469
- .argument("[target]", "Bundle file (.mthds) or directory")
470
- .option("--pipe <code>", "Pipe code to generate inputs for")
471
- .option("--content <mthds>", "Bundle content as a string (alternative to file path)")
472
- .description("Generate inputs from a bundle file or content")
473
- .allowUnknownOption()
474
- .allowExcessArguments(true)
475
- .exitOverride()
476
- .action(async (target, options) => {
477
- let runner;
478
- try {
479
- runner = makeRunner();
480
- }
481
- catch (err) {
482
- agentError(err.message, "RunnerError", {
483
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
484
- });
485
- }
486
- let mthdsContent;
487
- if (options.content) {
488
- mthdsContent = options.content;
489
- }
490
- else if (target) {
491
- try {
492
- mthdsContent = readFileSync(target, "utf-8");
493
- }
494
- catch (err) {
495
- agentError(`Cannot read bundle: ${err.message}`, "IOError", {
496
- error_domain: AGENT_ERROR_DOMAINS.IO,
497
- });
498
- }
499
- }
500
- else {
501
- agentError("Either <target> or --content is required.", "ArgumentError", {
502
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
503
- });
504
- }
505
- let pipeCode = options.pipe;
506
- if (!pipeCode) {
507
- const match = mthdsContent.match(/^main_pipe\s*=\s*"([^"]+)"/m);
508
- if (match)
509
- pipeCode = match[1];
510
- }
511
- if (!pipeCode) {
512
- agentError("Could not determine pipe code. Use --pipe to specify it.", "ArgumentError", {
513
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
514
- });
515
- }
516
- try {
517
- const result = await runner.buildInputs({
518
- mthds_contents: [mthdsContent],
519
- pipe_code: pipeCode,
520
- });
521
- agentSuccess({ success: true, pipe_code: pipeCode, inputs: result });
522
- }
523
- catch (err) {
524
- agentError(err.message, "RunnerError", {
525
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
526
- });
527
- }
528
- });
529
- inputsGroup
530
- .command("pipe")
531
- .argument("<target>", "Bundle file (.mthds) or pipe code")
532
- .option("--pipe <code>", "Pipe code to generate inputs for")
533
- .description("Generate inputs for a pipe")
534
- .allowUnknownOption()
535
- .allowExcessArguments(true)
536
- .exitOverride()
537
- .action(async (target, options) => {
538
- let runner;
539
- try {
540
- runner = makeRunner();
541
- }
542
- catch (err) {
543
- agentError(err.message, "RunnerError", {
544
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
545
- });
546
- }
547
- if (target.endsWith(".mthds")) {
548
- let mthdsContent;
549
- try {
550
- mthdsContent = readFileSync(target, "utf-8");
551
- }
552
- catch (err) {
553
- agentError(`Cannot read bundle: ${err.message}`, "IOError", {
554
- error_domain: AGENT_ERROR_DOMAINS.IO,
555
- });
556
- }
557
- let pipeCode = options.pipe;
558
- if (!pipeCode) {
559
- const match = mthdsContent.match(/^main_pipe\s*=\s*"([^"]+)"/m);
560
- if (match)
561
- pipeCode = match[1];
562
- }
563
- if (!pipeCode) {
564
- agentError("Could not determine pipe code. Use --pipe to specify it.", "ArgumentError", {
565
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
566
- });
567
- }
568
- try {
569
- const result = await runner.buildInputs({
570
- mthds_contents: [mthdsContent],
571
- pipe_code: pipeCode,
572
- });
573
- agentSuccess({ success: true, pipe_code: pipeCode, inputs: result });
574
- }
575
- catch (err) {
576
- agentError(err.message, "RunnerError", {
577
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
578
- });
579
- }
580
- }
581
- else {
582
- agentError("Pipe code without a bundle file is not supported yet. Provide a .mthds file.", "ArgumentError", { error_domain: AGENT_ERROR_DOMAINS.ARGUMENT });
583
- }
584
- });
585
- inputsGroup
586
- .command("method")
587
- .argument("<name>", "Method name")
588
- .option("--pipe <code>", "Pipe code to generate inputs for")
589
- .description("Generate inputs for an installed method")
590
- .allowUnknownOption()
591
- .allowExcessArguments(true)
592
- .exitOverride()
593
- .action(async () => {
594
- agentError("'inputs method' is not yet supported via the runner interface.", "UnsupportedError", { error_domain: AGENT_ERROR_DOMAINS.RUNNER });
595
- });
596
- // ── run ──
597
- const runGroup = program
598
- .command("run")
599
- .description("Execute a pipeline")
600
- .passThroughOptions()
601
- .allowUnknownOption();
602
- runGroup
603
- .command("method")
604
- .argument("<name>", "Name of the installed method")
605
- .option("--pipe <code>", "Pipe code (overrides method's main_pipe)")
606
- .option("-i, --inputs <file>", "Path to JSON inputs file")
607
- .description("Run an installed method by name")
608
- .allowUnknownOption()
609
- .allowExcessArguments(true)
610
- .exitOverride()
611
- .action(async () => {
612
- let runner;
613
- try {
614
- runner = makeRunner();
615
- }
616
- catch (err) {
617
- agentError(err.message, "RunnerError", {
618
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
619
- });
620
- }
621
- // Passthrough for pipelex runner
622
- if (isPipelexRunner(runner)) {
623
- try {
624
- await runner.runPassthrough([...logLevelArgs(), ...extractPassthroughArgs("run")]);
625
- }
626
- catch (err) {
627
- agentError(err.message, "RunError", {
628
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
629
- });
630
- }
631
- return;
632
- }
633
- agentError("Method target is not yet supported for the API runner. Use 'mthds-agent run pipe <target>' instead, or specify a different runner with --runner <name>.", "ArgumentError", { error_domain: AGENT_ERROR_DOMAINS.ARGUMENT });
634
- });
635
- /** Shared execution logic for run pipe / run bundle */
636
- async function executeViaRunner(runner, target, options) {
637
- let mthdsContent;
638
- if (options.content) {
639
- mthdsContent = options.content;
640
- }
641
- else if (target) {
642
- // Resolve target: if directory, look for bundle.mthds inside
643
- let bundlePath = target;
644
- if (existsSync(target) && statSync(target).isDirectory()) {
645
- const candidate = join(target, "bundle.mthds");
646
- if (existsSync(candidate)) {
647
- bundlePath = candidate;
648
- }
649
- else {
650
- agentError(`No bundle.mthds found in directory: ${target}`, "IOError", {
651
- error_domain: AGENT_ERROR_DOMAINS.IO,
652
- });
653
- }
654
- // Also check for inputs.json in directory if not specified
655
- if (!options.inputs && !options.inputsJson) {
656
- const inputsCandidate = join(target, "inputs.json");
657
- if (existsSync(inputsCandidate)) {
658
- options.inputs = inputsCandidate;
659
- }
660
- }
661
- }
662
- try {
663
- mthdsContent = readFileSync(bundlePath, "utf-8");
664
- }
665
- catch (err) {
666
- agentError(`Cannot read bundle: ${err.message}`, "IOError", {
667
- error_domain: AGENT_ERROR_DOMAINS.IO,
668
- });
669
- }
670
- }
671
- else {
672
- agentError("Either <target> or --content is required.", "ArgumentError", {
673
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
674
- });
675
- }
676
- let pipeCode = options.pipe;
677
- if (!pipeCode) {
678
- const match = mthdsContent.match(/^main_pipe\s*=\s*"([^"]+)"/m);
679
- if (match)
680
- pipeCode = match[1];
681
- }
682
- let inputs;
683
- if (options.inputsJson) {
684
- try {
685
- inputs = JSON.parse(options.inputsJson);
686
- }
687
- catch {
688
- agentError("--inputs-json must be valid JSON.", "ArgumentError", {
689
- error_domain: AGENT_ERROR_DOMAINS.ARGUMENT,
690
- });
691
- }
692
- }
693
- else if (options.inputs) {
694
- try {
695
- inputs = JSON.parse(readFileSync(options.inputs, "utf-8"));
696
- }
697
- catch (err) {
698
- agentError(`Cannot read inputs: ${err.message}`, "IOError", {
699
- error_domain: AGENT_ERROR_DOMAINS.IO,
700
- });
701
- }
702
- }
703
- try {
704
- const result = await runner.execute({
705
- mthds_contents: [mthdsContent],
706
- pipe_code: pipeCode,
707
- inputs,
708
- });
709
- agentSuccess({ ...result });
710
- }
711
- catch (err) {
712
- agentError(err.message, "RunnerError", {
713
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
714
- });
715
- }
716
- }
717
- /** Shared runner dispatch for run pipe / run bundle */
718
- async function runAction(target, options) {
719
- let runner;
720
- try {
721
- runner = makeRunner();
722
- }
723
- catch (err) {
724
- agentError(err.message, "RunnerError", {
725
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
726
- });
727
- }
728
- // Passthrough for pipelex runner (forwards all CLI flags like --dry-run, --output-dir, etc.)
729
- if (isPipelexRunner(runner)) {
730
- try {
731
- await runner.runPassthrough([...logLevelArgs(), ...extractPassthroughArgs("run")]);
732
- }
733
- catch (err) {
734
- agentError(err.message, "RunError", {
735
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
736
- });
737
- }
738
- return;
739
- }
740
- await executeViaRunner(runner, target, options);
741
- }
742
- // run pipe [target] [--pipe <code>] [-i <inputs>] [--content <mthds>] [--inputs-json <json>]
743
- runGroup
744
- .command("pipe")
745
- .argument("[target]", "Bundle file (.mthds) or directory")
746
- .option("--pipe <code>", "Pipe code to run")
747
- .option("-i, --inputs <file>", "Path to JSON inputs file")
748
- .option("--content <mthds>", "Bundle content as a string (alternative to file path)")
749
- .option("--inputs-json <json>", "Inputs as a JSON string (alternative to inputs file)")
750
- .option("--dry-run", "Validate without executing")
751
- .option("--mock-inputs", "Use mock inputs for dry run")
752
- .description("Run a pipe from a bundle file, directory, or content")
753
- .allowUnknownOption()
754
- .allowExcessArguments(true)
755
- .exitOverride()
756
- .action(runAction);
757
- // run bundle [target] (alias for run pipe)
758
- runGroup
759
- .command("bundle")
760
- .argument("[target]", "Bundle file (.mthds) or directory")
761
- .option("--pipe <code>", "Pipe code to run")
762
- .option("-i, --inputs <file>", "Path to JSON inputs file")
763
- .option("--content <mthds>", "Bundle content as a string (alternative to file path)")
764
- .option("--inputs-json <json>", "Inputs as a JSON string (alternative to inputs file)")
765
- .description("Run a bundle file or content")
766
- .allowUnknownOption()
767
- .allowExcessArguments(true)
768
- .exitOverride()
769
- .action(runAction);
770
- // ── models ──
771
- program
772
- .command("models")
773
- .description("List available model presets, aliases, and talent mappings")
774
- .option("--type <type>", "Filter by model category (repeatable): llm, extract, img_gen, search", collect, [])
775
- .allowUnknownOption()
776
- .allowExcessArguments(true)
777
- .exitOverride()
778
- .action(async (options) => {
779
- let runner;
780
- try {
781
- runner = makeRunner();
782
- }
783
- catch (err) {
784
- agentError(err.message, "RunnerError", {
785
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
786
- });
787
- }
788
- try {
789
- const request = options.type?.length ? { type: options.type } : undefined;
790
- const result = await runner.models(request);
791
- agentSuccess({ ...result });
792
- }
793
- catch (err) {
794
- agentError(err.message, "RunnerError", {
795
- error_domain: AGENT_ERROR_DOMAINS.RUNNER,
796
- });
797
- }
798
- });
799
- }
800
- //# sourceMappingURL=runner-commands.js.map