@piewf/cli 5.9.0 → 5.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/cli.d.ts CHANGED
@@ -15,6 +15,15 @@ export interface CliOptions extends DoctorOptions {
15
15
  }
16
16
  export declare function formatWorkflowCliHelp(fn: WorkflowCatalogFunction, command?: string): string;
17
17
  export declare function parseWorkflowCliArgs(schema: JsonSchema, rawArgs: readonly string[]): Record<string, JsonValue>;
18
+ type ScriptWorkflowCliArgs = {
19
+ help: true;
20
+ } | {
21
+ help: false;
22
+ scriptPath: string;
23
+ name: string;
24
+ args: JsonValue;
25
+ };
26
+ export declare function parseScriptWorkflowCliArgs(rawArgs: readonly string[]): ScriptWorkflowCliArgs;
18
27
  export declare function parseDoctorArgs(rawArgs: readonly string[]): {
19
28
  role?: string;
20
29
  prompt?: string;
@@ -22,3 +31,4 @@ export declare function parseDoctorArgs(rawArgs: readonly string[]): {
22
31
  };
23
32
  export declare function parseDoctorCleanupArgs(rawArgs: readonly string[]): Required<Pick<DoctorCleanupOptions, "olderThanDays" | "yes">>;
24
33
  export declare function runCli(args: readonly string[], options?: CliOptions, write?: (text: string) => void): Promise<number>;
34
+ export {};
package/dist/src/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { chmodSync, linkSync, mkdirSync, mkdtempSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { homedir } from "node:os";
5
- import { dirname, join } from "node:path";
5
+ import { basename, dirname, extname, join } from "node:path";
6
6
  import { pathToFileURL } from "node:url";
7
7
  import { ProjectTrustStore, SessionManager, SettingsManager, createAgentSessionFromServices, createAgentSessionServices, getAgentDir, hasTrustRequiringProjectResources } from "@earendil-works/pi-coding-agent";
8
8
  import { Value } from "typebox/value";
@@ -214,7 +214,53 @@ function launcherHelpLines() {
214
214
  " --".padEnd(28) + "End launcher option parsing; pass later tokens to workflow input",
215
215
  ];
216
216
  }
217
- function workflowUsage() { return [`Usage: piewf run <workflow-name> [workflow arguments] | export <workflow-name> [--name <command>] [--output <path>] [--force]`, "", "Launcher options:", ...launcherHelpLines()].join("\n") + "\n"; }
217
+ function workflowUsage() { return [`Usage: piewf run <workflow-name> [workflow arguments] | run --script <path> [--name <workflow-name>] [--input <json>] | export <workflow-name> [--name <command>] [--output <path>] [--force]`, "", "Launcher options:", ...launcherHelpLines()].join("\n") + "\n"; }
218
+ function scriptWorkflowUsage() { return [`Usage: piewf run --script <path> [--name <workflow-name>] [--input <json>]`, "", "Options:", ...launcherHelpLines().slice(0, 2), " -h, --help".padEnd(28) + "Show this help"].join("\n") + "\n"; }
219
+ function scriptWorkflowName(scriptPath) {
220
+ const filename = basename(scriptPath);
221
+ const extension = extname(filename);
222
+ return extension ? filename.slice(0, -extension.length) : filename;
223
+ }
224
+ export function parseScriptWorkflowCliArgs(rawArgs) {
225
+ let scriptPath;
226
+ let name;
227
+ let input;
228
+ for (let index = 0; index < rawArgs.length; index += 1) {
229
+ const token = requiredArg(rawArgs, index);
230
+ if (token === "--help" || token === "-h")
231
+ return { help: true };
232
+ const equals = token.indexOf("=");
233
+ const option = equals >= 0 ? token.slice(0, equals) : token;
234
+ if (option === "--script" || option === "--name" || option === "--input") {
235
+ const value = equals >= 0 ? token.slice(equals + 1) : rawArgs[++index];
236
+ if (!value?.trim())
237
+ throw new Error(`Missing value for ${option}`);
238
+ if (option === "--script") {
239
+ if (scriptPath !== undefined)
240
+ throw new Error("--script may only be provided once");
241
+ scriptPath = value;
242
+ }
243
+ else if (option === "--name") {
244
+ if (name !== undefined)
245
+ throw new Error("--name may only be provided once");
246
+ name = value;
247
+ }
248
+ else {
249
+ if (input !== undefined)
250
+ throw new Error("--input may only be provided once");
251
+ input = parseJsonInput(value);
252
+ }
253
+ continue;
254
+ }
255
+ throw new Error(`Unknown option: ${token}`);
256
+ }
257
+ if (scriptPath === undefined)
258
+ throw new Error("Missing required option: --script");
259
+ const workflowName = name === undefined ? scriptWorkflowName(scriptPath) : name.trim();
260
+ if (!workflowName)
261
+ throw new Error("Workflow name must be non-empty");
262
+ return { help: false, scriptPath, name: workflowName, args: input ?? null };
263
+ }
218
264
  function exportUsage() { return [`Usage: piewf export <workflow-name> [--name <command>] [--output <path>] [--force] [--bundle]`, "", "Launcher options:", ...launcherHelpLines()].join("\n") + "\n"; }
219
265
  function bundleUsage() { return [`Usage: piewf bundle <workflow-name> [--name <command>] [--output <directory>] [--force]`, "", "The bundle contains a launcher, manifest, workflow payload, and external-runtime setup instructions.", "Repeat --role, --alias, --tool, --command, or --environment to declare recipient requirements.", "Use --extension, --skill, --resource, and --dependency to copy selected payload resources."].join("\n") + "\n"; }
220
266
  function parseInspectArgs(rawArgs) {
@@ -524,15 +570,20 @@ class CliProgress {
524
570
  this.#run = undefined;
525
571
  }
526
572
  }
527
- async function invokeWorkflow(fn, args, runtime, options, context) {
528
- if (!Value.Check(fn.input, args))
529
- throw new Error(`Invalid input for ${fn.name}`);
573
+ async function invokeWorkflow(launch, runtime, options, context) {
574
+ if (launch.fn && (!object(launch.args) || !Value.Check(launch.fn.input, launch.args)))
575
+ throw new Error(`Invalid input for ${launch.fn.name}`);
576
+ if (!launch.fn && launch.scriptPath === undefined)
577
+ throw new Error("Workflow launch has no source");
530
578
  let announcedRunId;
531
579
  const announceRunId = (runId) => { if (announcedRunId === runId)
532
580
  return; announcedRunId = runId; options.stderr(`Run ID: ${runId}\n`); };
533
581
  const progress = new CliProgress(options.stderr, options.isTTY ?? process.stderr.isTTY, announceRunId);
534
582
  try {
535
- const result = await runtime.workflowTool.execute(randomUUID(), { name: fn.name, script: `return await ${fn.name}(args);`, args, foreground: true }, options.signal, (update) => { if (object(update) && object(update.details) && isPersistedRun(update.details.run))
583
+ const params = launch.scriptPath === undefined
584
+ ? { name: launch.name, script: `return await ${launch.fn?.name ?? launch.name}(args);`, args: launch.args, foreground: true }
585
+ : { name: launch.name, scriptPath: launch.scriptPath, args: launch.args, foreground: true };
586
+ const result = await runtime.workflowTool.execute(randomUUID(), params, options.signal, (update) => { if (object(update) && object(update.details) && isPersistedRun(update.details.run))
536
587
  progress.update(update.details.run); }, context);
537
588
  if (!isHeadlessWorkflowResult(result))
538
589
  throw new Error("Workflow returned an invalid result");
@@ -589,8 +640,22 @@ async function runWorkflowCli(rawArgs, options) {
589
640
  options.write(workflowUsage());
590
641
  return args.length ? 0 : 1;
591
642
  }
643
+ const runtimeOptions = { ...options, ...(parsed.trustOverride !== undefined ? { trustOverride: parsed.trustOverride } : {}) };
644
+ const scriptMode = args[0] === "--script" || args[0]?.startsWith("--script=") || args[0]?.startsWith("--") && args.some((arg) => arg === "--script" || arg.startsWith("--script="));
645
+ if (scriptMode) {
646
+ const script = parseScriptWorkflowCliArgs(args);
647
+ if (script.help) {
648
+ options.write(scriptWorkflowUsage());
649
+ return 0;
650
+ }
651
+ return withWorkflowRuntime(runtimeOptions, async (runtime, context) => {
652
+ const result = await invokeWorkflow({ name: script.name, scriptPath: script.scriptPath, args: script.args }, runtime, options, context);
653
+ options.write(`${JSON.stringify(result.value)}\n`);
654
+ return 0;
655
+ });
656
+ }
592
657
  const name = requiredArg(args, 0);
593
- return withWorkflowRuntime({ ...options, ...(parsed.trustOverride !== undefined ? { trustOverride: parsed.trustOverride } : {}) }, async (runtime, context) => {
658
+ return withWorkflowRuntime(runtimeOptions, async (runtime, context) => {
594
659
  const help = args.slice(1).some((arg) => arg === "--help" || arg === "-h");
595
660
  const fn = runtime.catalog.functions.find((candidate) => candidate.name === name);
596
661
  if (!fn)
@@ -600,7 +665,7 @@ async function runWorkflowCli(rawArgs, options) {
600
665
  return 0;
601
666
  }
602
667
  const input = parseWorkflowCliArgs(fn.input, args.slice(1));
603
- const result = await invokeWorkflow(fn, input, runtime, options, context);
668
+ const result = await invokeWorkflow({ name: fn.name, fn, args: input }, runtime, options, context);
604
669
  options.write(`${JSON.stringify(result.value)}\n`);
605
670
  return 0;
606
671
  });
@@ -842,7 +907,7 @@ export async function runCli(args, options = {}, write = (text) => { process.std
842
907
  return 1;
843
908
  }
844
909
  }
845
- write("Usage: piewf doctor [role] [--role <role>] [--prompt <text>] [--json] | inspect [session-id] [--json|--summary] [--failed] | transcript <session-file> | share <run-id> | bundle <workflow-name> [--name <command>] [--output <path>] [--force] | run <workflow-name> [workflow arguments] | export <workflow-name> [--name <command>] [--output <path>] [--force] [--bundle]\n");
910
+ write("Usage: piewf doctor [role] [--role <role>] [--prompt <text>] [--json] | inspect [session-id] [--json|--summary] [--failed] | transcript <session-file> | share <run-id> | bundle <workflow-name> [--name <command>] [--output <path>] [--force] | run <workflow-name> [workflow arguments] | run --script <path> [--name <workflow-name>] [--input <json>] | export <workflow-name> [--name <command>] [--output <path>] [--force] [--bundle]\n");
846
911
  return 1;
847
912
  }
848
913
  if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piewf/cli",
3
- "version": "5.9.0",
3
+ "version": "5.10.0",
4
4
  "description": "CLI for pi-extensible-workflows",
5
5
  "homepage": "https://vekexasia.github.io/pi-extensible-workflows/",
6
6
  "repository": {
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "license": "MIT",
48
48
  "dependencies": {
49
- "pi-extensible-workflows": "5.9.0"
49
+ "pi-extensible-workflows": "5.10.0"
50
50
  },
51
51
  "publishConfig": {
52
52
  "access": "public"