@piewf/cli 5.5.0-rc.1 → 5.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/cli.js CHANGED
@@ -8,7 +8,7 @@ import { ProjectTrustStore, SessionManager, SettingsManager, createAgentSessionF
8
8
  import { Value } from "typebox/value";
9
9
  import { doctor, doctorExitCode, formatDoctorReport } from "./doctor.js";
10
10
  import { doctorCleanup, doctorCleanupExitCode, formatDoctorCleanupReport } from "./doctor-cleanup.js";
11
- import workflowExtension, { formatWorkflowProgress, isNodeError, jsonValue, loadAgentDefinitions, registeredWorkflowFunctions, truncateWorkflowProgress, workflowCatalog, workflowSettingsPath } from "pi-extensible-workflows";
11
+ import workflowExtension, { errorText, formatWorkflowProgress, isNodeError, jsonValue, loadAgentDefinitions, registeredWorkflowFunctions, truncateWorkflowProgress, workflowCatalog, workflowSettingsPath } from "pi-extensible-workflows";
12
12
  import { portableEngineVersion, portablePiVersion, writePortableWorkflowBundle } from "./bundles.js";
13
13
  import { runSessionInspector, transcriptFileLines } from "./session-inspector.js";
14
14
  import { isPersistedRun } from "pi-extensible-workflows/persistence";
@@ -752,7 +752,7 @@ export async function runCli(args, options = {}, write = (text) => { process.std
752
752
  return doctorExitCode(report);
753
753
  }
754
754
  catch (error) {
755
- stderr(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
755
+ stderr(`Error: ${errorText(error)}\n`);
756
756
  return 1;
757
757
  }
758
758
  }
@@ -769,7 +769,7 @@ export async function runCli(args, options = {}, write = (text) => { process.std
769
769
  return doctorCleanupExitCode(report);
770
770
  }
771
771
  catch (error) {
772
- stderr(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
772
+ stderr(`Error: ${errorText(error)}\n`);
773
773
  return 1;
774
774
  }
775
775
  }
@@ -783,7 +783,7 @@ export async function runCli(args, options = {}, write = (text) => { process.std
783
783
  return 0;
784
784
  }
785
785
  catch (error) {
786
- write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
786
+ write(`Error: ${errorText(error)}\n`);
787
787
  return 1;
788
788
  }
789
789
  }
@@ -797,7 +797,7 @@ export async function runCli(args, options = {}, write = (text) => { process.std
797
797
  return 0;
798
798
  }
799
799
  catch (error) {
800
- write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
800
+ write(`Error: ${errorText(error)}\n`);
801
801
  return 1;
802
802
  }
803
803
  }
@@ -809,7 +809,7 @@ export async function runCli(args, options = {}, write = (text) => { process.std
809
809
  return args[0] === "run" ? await runWorkflowCli(args.slice(1), workflowOptions) : await exportWorkflowCli(args.slice(1), workflowOptions);
810
810
  }
811
811
  catch (error) {
812
- stderr(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
812
+ stderr(`Error: ${errorText(error)}\n`);
813
813
  return 1;
814
814
  }
815
815
  }
@@ -4,7 +4,7 @@ import { homedir } from "node:os";
4
4
  import { join, resolve } from "node:path";
5
5
  import { validateBudget } from "pi-extensible-workflows";
6
6
  import { RUN_STATES } from "pi-extensible-workflows";
7
- import { isNodeError, jsonValue, validateModelAliases } from "pi-extensible-workflows";
7
+ import { errorText, isNodeError, jsonValue, validateModelAliases } from "pi-extensible-workflows";
8
8
  import { validateSchema } from "pi-extensible-workflows";
9
9
  import { acquireSessionLease, hasLiveSessionLease, projectSessionsDirectory, RunStore } from "pi-extensible-workflows/persistence";
10
10
  const TERMINAL_STATES = new Set(["completed", "failed", "stopped"]);
@@ -25,7 +25,6 @@ function isAgentState(value) { return typeof value === "string" && AGENT_STATES.
25
25
  function isSchedulerState(value) { return typeof value === "string" && SCHEDULER_STATES.has(value); }
26
26
  function isToolCallState(value) { return ["running", "completed", "failed"].some((candidate) => candidate === value); }
27
27
  function isActivityKind(value) { return ["reasoning", "tool", "text"].some((candidate) => candidate === value); }
28
- function textError(error) { return error instanceof Error ? error.message : String(error); }
29
28
  function positiveDays(value) { if (!Number.isSafeInteger(value) || value < 1 || !Number.isFinite(value * DAY_MS))
30
29
  throw new Error("older-than-days must be a positive integer"); return value; }
31
30
  function runItem(entry, action, reason) { return { sessionId: entry.sessionId, runId: entry.runId, action, state: entry.run.state, stateMtimeMs: entry.stateMtimeMs, path: entry.store.directory, ...(reason ? { reason } : {}) }; }
@@ -63,33 +62,14 @@ function agentDefinition(value, label) { if (!object(value))
63
62
  function optionalRole(value, label) {
64
63
  if (value === undefined)
65
64
  return;
66
- if (typeof value === "string") {
67
- if (!value.trim())
68
- throw new Error(`${label} is invalid`);
69
- return;
70
- }
71
- if (!object(value) || typeof value.name !== "string" || !value.name.trim())
65
+ if (typeof value !== "string" || !value.trim())
72
66
  throw new Error(`${label} is invalid`);
73
- for (const key of ["model", "description"])
74
- if (value[key] !== undefined && value[key] !== null && typeof value[key] !== "string")
75
- throw new Error(`${label}.${key} is invalid`);
76
- if (value.thinking !== undefined && value.thinking !== null && !isThinking(value.thinking))
77
- throw new Error(`${label}.thinking is invalid`);
78
- if (value.tools !== undefined && value.tools !== null)
79
- stringList(value.tools, `${label}.tools`);
80
- if (value.overrideSystemPrompt !== undefined && value.overrideSystemPrompt !== null && typeof value.overrideSystemPrompt !== "boolean")
81
- throw new Error(`${label}.overrideSystemPrompt is invalid`);
82
- if (value.contextFiles !== undefined && value.contextFiles !== null)
83
- stringList(value.contextFiles, `${label}.contextFiles`);
84
- if (value.skills !== undefined && value.skills !== null)
85
- stringList(value.skills, `${label}.skills`);
86
- if (value.extensions !== undefined && value.extensions !== null)
87
- stringList(value.extensions, `${label}.extensions`);
88
67
  }
89
68
  function validateScheduledOptions(value, label) { if (!object(value) || typeof value.label !== "string" || !value.label || typeof value.cwd !== "string" || !value.cwd)
90
69
  throw new Error(`${label} is invalid`); optionalString(value.requestedLabel, `${label}.requestedLabel`); optionalString(value.parentBreadcrumb, `${label}.parentBreadcrumb`); stringList(value.tools, `${label}.tools`); if (value.skills !== undefined)
91
70
  stringList(value.skills, `${label}.skills`); if (value.extensions !== undefined)
92
- stringList(value.extensions, `${label}.extensions`); optionalString(value.worktreeOwner, `${label}.worktreeOwner`); optionalString(value.model, `${label}.model`); if (value.thinking !== undefined && !isThinking(value.thinking))
71
+ stringList(value.extensions, `${label}.extensions`); if (value.contextFiles !== undefined)
72
+ stringList(value.contextFiles, `${label}.contextFiles`); optionalString(value.worktreeOwner, `${label}.worktreeOwner`); optionalString(value.model, `${label}.model`); if (value.thinking !== undefined && !isThinking(value.thinking))
93
73
  throw new Error(`${label}.thinking is invalid`); optionalRole(value.role, `${label}.role`); if (value.schema !== undefined)
94
74
  validateSchema(value.schema, `${label}.schema`); if (value.retries !== undefined)
95
75
  nonNegativeInteger(value.retries, `${label}.retries`); if (value.timeoutMs !== undefined && value.timeoutMs !== null)
@@ -426,7 +406,7 @@ async function scanSession(cwd, sessionId, home, expectedLease) {
426
406
  runs.push({ sessionId, runId, store, run: loaded.run, stateMtimeMs: afterState.mtimeMs, dependencies: [...dependencies] });
427
407
  }
428
408
  catch (error) {
429
- throw new Error(`Run ${runId} is corrupt or incomplete: ${textError(error)}`, { cause: error });
409
+ throw new Error(`Run ${runId} is corrupt or incomplete: ${errorText(error)}`, { cause: error });
430
410
  }
431
411
  }
432
412
  const after = await sessionEntries(runsPath);
@@ -461,7 +441,7 @@ async function recheckCandidate(entry, cutoffMs) {
461
441
  const before = await stat(join(entry.store.directory, "state.json")).catch(() => undefined);
462
442
  if (!before)
463
443
  return "State record disappeared before deletion";
464
- const loaded = await entry.store.load().catch((error) => { throw new Error(`Candidate could not be reloaded: ${textError(error)}`); });
444
+ const loaded = await entry.store.load().catch((error) => { throw new Error(`Candidate could not be reloaded: ${errorText(error)}`); });
465
445
  validateRunRecord(loaded.run);
466
446
  if (loaded.run.id !== entry.runId || loaded.run.state !== entry.run.state || !TERMINAL_STATES.has(loaded.run.state))
467
447
  return "Candidate state changed before deletion";
@@ -550,7 +530,7 @@ export async function doctorCleanup(options = {}) {
550
530
  sessionIds = await storedSessionIds(cwd, home);
551
531
  }
552
532
  catch (error) {
553
- addFailure(failures, "(project)", textError(error));
533
+ addFailure(failures, "(project)", errorText(error));
554
534
  return { cwd, cutoffMs, olderThanDays, yes, sessions, candidates, skipped, deleted, failures };
555
535
  }
556
536
  for (const sessionId of sessionIds) {
@@ -559,8 +539,8 @@ export async function doctorCleanup(options = {}) {
559
539
  initial = await scanSession(cwd, sessionId, home);
560
540
  }
561
541
  catch (error) {
562
- sessions.push({ sessionId, path: join(projectSessionsDirectory(cwd, home), sessionId), status: "failed", reason: textError(error) });
563
- addFailure(failures, sessionId, textError(error));
542
+ sessions.push({ sessionId, path: join(projectSessionsDirectory(cwd, home), sessionId), status: "failed", reason: errorText(error) });
543
+ addFailure(failures, sessionId, errorText(error));
564
544
  continue;
565
545
  }
566
546
  const initialPlan = planSession(initial, cutoffMs);
@@ -577,7 +557,7 @@ export async function doctorCleanup(options = {}) {
577
557
  lease = await acquireSessionLease(cwd, sessionId, home);
578
558
  }
579
559
  catch (error) {
580
- const message = textError(error);
560
+ const message = errorText(error);
581
561
  if (/already owned|active ownership|RUN_OWNED/i.test(message)) {
582
562
  sessions.push({ sessionId, path: initial.path, status: "skipped", reason: "Session has a live ownership lease" });
583
563
  continue;
@@ -592,7 +572,7 @@ export async function doctorCleanup(options = {}) {
592
572
  current = await scanSession(cwd, sessionId, home, lease);
593
573
  }
594
574
  catch (error) {
595
- const message = textError(error);
575
+ const message = errorText(error);
596
576
  sessions.push({ sessionId, path: initial.path, status: "failed", reason: message });
597
577
  addFailure(failures, sessionId, message);
598
578
  continue;
@@ -613,7 +593,7 @@ export async function doctorCleanup(options = {}) {
613
593
  addUnique(skipped, item);
614
594
  }
615
595
  catch (error) {
616
- const message = textError(error);
596
+ const message = errorText(error);
617
597
  addFailure(failures, sessionId, message);
618
598
  clean = false;
619
599
  break;
@@ -625,7 +605,7 @@ export async function doctorCleanup(options = {}) {
625
605
  ordered = deletionOrder(current, freshPlan.candidates);
626
606
  }
627
607
  catch (error) {
628
- const message = textError(error);
608
+ const message = errorText(error);
629
609
  addFailure(failures, sessionId, message);
630
610
  clean = false;
631
611
  break;
@@ -638,7 +618,7 @@ export async function doctorCleanup(options = {}) {
638
618
  changed = await recheckCandidate(target, cutoffMs);
639
619
  }
640
620
  catch (error) {
641
- const message = textError(error);
621
+ const message = errorText(error);
642
622
  addFailure(failures, sessionId, message, target.runId);
643
623
  clean = false;
644
624
  break;
@@ -653,7 +633,7 @@ export async function doctorCleanup(options = {}) {
653
633
  deleted.push(runItem(target, "deleted"));
654
634
  }
655
635
  catch (error) {
656
- const message = textError(error);
636
+ const message = errorText(error);
657
637
  addUnique(skipped, runItem(target, "failed", message));
658
638
  addFailure(failures, sessionId, message, target.runId);
659
639
  clean = false;
@@ -670,7 +650,7 @@ export async function doctorCleanup(options = {}) {
670
650
  await lease.release();
671
651
  }
672
652
  catch (error) {
673
- addFailure(failures, sessionId, textError(error));
653
+ addFailure(failures, sessionId, errorText(error));
674
654
  }
675
655
  }
676
656
  }
@@ -212,7 +212,7 @@ function validateModel(value, known, available, source, diagnostics, aliases, dy
212
212
  }
213
213
  catch (error) {
214
214
  const message = errorText(error);
215
- diagnostics.push(diagnostic("error", "MODEL_INVALID", message, source, message.includes("thinking") ? THINKING_HINT : "Use provider/model or provider/model:thinking."));
215
+ diagnostics.push(diagnostic("error", "MODEL_INVALID", message, source, message.includes("thinking") ? THINKING_HINT : "Use provider/model:thinking."));
216
216
  }
217
217
  }
218
218
  function inspectRole(path, activeTools, knownModels, availableModels, diagnostics, aliases, dynamicAliases, settingsPath, source) {
@@ -225,7 +225,7 @@ function inspectRole(path, activeTools, knownModels, availableModels, diagnostic
225
225
  diagnostics.push(legacyAgentResourceSelectorDiagnostic(path));
226
226
  return undefined;
227
227
  }
228
- const message = error instanceof Error ? error.message : String(error);
228
+ const message = errorText(error);
229
229
  diagnostics.push(diagnostic("error", "ROLE_FRONTMATTER", source ? `${roleProvenance(source)} contains invalid role at "${path}": ${message}` : message, path, "Fix the role YAML frontmatter."));
230
230
  return undefined;
231
231
  }
@@ -270,14 +270,14 @@ async function inspectRoleSession(cwd, agentDir, roleName, definition, rolePath,
270
270
  prepared = await prepareAgentSetupForInspection(root, prompt, options, transport);
271
271
  }
272
272
  catch (error) {
273
- setupDiagnostics.push(diagnostic("error", "ROLE_INSPECTION", error instanceof Error ? error.message : String(error), rolePath));
273
+ setupDiagnostics.push(diagnostic("error", "ROLE_INSPECTION", errorText(error), rolePath));
274
274
  diagnostics.push(...setupDiagnostics);
275
275
  return undefined;
276
276
  }
277
277
  if (prepared.failure) {
278
278
  const error = prepared.failure.error;
279
279
  const code = prepared.failure.hook ? "ROLE_SETUP_HOOK" : "ROLE_INSPECTION";
280
- setupDiagnostics.push(diagnostic("error", code, `${prepared.failure.hook ? `Role setup hook ${prepared.failure.hook} failed: ` : ""}${error instanceof Error ? error.message : String(error)}`, prepared.failure.hook ?? rolePath));
280
+ setupDiagnostics.push(diagnostic("error", code, `${prepared.failure.hook ? `Role setup hook ${prepared.failure.hook} failed: ` : ""}${errorText(error)}`, prepared.failure.hook ?? rolePath));
281
281
  diagnostics.push(...setupDiagnostics);
282
282
  return undefined;
283
283
  }
@@ -285,7 +285,7 @@ async function inspectRoleSession(cwd, agentDir, roleName, definition, rolePath,
285
285
  return await createLocalPiSession({ ...prepared.setup.sessionInput, sessionManager: SessionManager.inMemory() });
286
286
  }
287
287
  catch (error) {
288
- setupDiagnostics.push(diagnostic("error", "ROLE_INSPECTION", error instanceof Error ? error.message : String(error), rolePath));
288
+ setupDiagnostics.push(diagnostic("error", "ROLE_INSPECTION", errorText(error), rolePath));
289
289
  return undefined;
290
290
  } })();
291
291
  if (!session) {
@@ -304,7 +304,7 @@ async function inspectRoleSession(cwd, agentDir, roleName, definition, rolePath,
304
304
  return { role: roleName, path: rolePath, model: actualModel, tools: state?.tools.map(({ name }) => name) ?? [...prepared.setup.sessionInput.tools], resources: { selectors: { skills: [...policy.effective.skills], extensions: [...policy.effective.extensions], tools: [...(policy.effective.tools ?? [])] }, skills: policy.selectedSkills ?? resources.skills, extensions: policy.selectedExtensions ?? resources.extensions, tools: policy.selectedTools ?? prepared.setup.sessionInput.tools, unmatchedSkills: policy.unmatchedSkills, unmatchedExtensions: policy.unmatchedExtensions, unmatchedTools: policy.unmatchedTools ?? [], selectorSources: policy.selectorSources }, systemPrompt: { probe: prompt, expandedProbe: promptResult.expandedPrompt, text: promptResult.systemPrompt, ...(resources.systemPromptSource ? { source: resources.systemPromptSource } : {}) }, setup: { hooks: prepared.summary.hookNames, diagnostics: setupDiagnostics } };
305
305
  }
306
306
  catch (error) {
307
- setupDiagnostics.push(diagnostic("error", "ROLE_INSPECTION", error instanceof Error ? error.message : String(error), rolePath));
307
+ setupDiagnostics.push(diagnostic("error", "ROLE_INSPECTION", errorText(error), rolePath));
308
308
  diagnostics.push(...setupDiagnostics);
309
309
  return undefined;
310
310
  }
@@ -353,7 +353,7 @@ export async function doctor(options = {}) {
353
353
  settingsSources = resolved.sources;
354
354
  }
355
355
  catch (error) {
356
- const message = error instanceof Error ? error.message : String(error);
356
+ const message = errorText(error);
357
357
  const source = message.includes(projectSettingsPath) ? projectSettingsPath : settingsPath;
358
358
  if (!diagnostics.some(({ code, source: itemSource }) => code === "SETTINGS_INVALID" && itemSource === source))
359
359
  diagnostics.push(diagnostic("error", "SETTINGS_INVALID", message, source, "Fix or remove the invalid workflow settings file."));
@@ -363,7 +363,7 @@ export async function doctor(options = {}) {
363
363
  resourcePolicy = matchResourcePolicy(resolveAgentResourcePolicy(cwd, pi.trust.trusted, settingsPath), pi);
364
364
  }
365
365
  catch (error) {
366
- const message = error instanceof Error ? error.message : String(error);
366
+ const message = errorText(error);
367
367
  const source = message.includes(projectSettingsPath) ? projectSettingsPath : settingsPath;
368
368
  if (!diagnostics.some(({ code, source: itemSource }) => code === "SETTINGS_INVALID" && itemSource === source))
369
369
  diagnostics.push(diagnostic("error", "SETTINGS_INVALID", message, source, "Fix or remove the invalid workflow settings file."));
@@ -395,7 +395,7 @@ export async function doctor(options = {}) {
395
395
  const definitions = new Map();
396
396
  const extensionScan = scanExtensionRoleFiles(registeredWorkflowRoleDirectoryRegistrations());
397
397
  for (const { registration, error } of extensionScan.errors) {
398
- const message = error instanceof Error ? error.message : String(error);
398
+ const message = errorText(error);
399
399
  diagnostics.push(diagnostic("error", "ROLE_DIRECTORY", `${extensionLabel(registration.extension)} role directory "${registration.path}" could not be scanned: ${message}`, registration.path, "Fix or remove the registered role directory."));
400
400
  }
401
401
  for (const registration of extensionScan.empty)
@@ -500,7 +500,7 @@ export async function doctor(options = {}) {
500
500
  diagnostics.push(...roleInspection.setup.diagnostics);
501
501
  }
502
502
  catch (error) {
503
- diagnostics.push(diagnostic("error", "ROLE_INSPECTION_MODEL", error instanceof Error ? error.message : String(error), activeRole.path));
503
+ diagnostics.push(diagnostic("error", "ROLE_INSPECTION_MODEL", errorText(error), activeRole.path));
504
504
  }
505
505
  }
506
506
  }
@@ -4,7 +4,7 @@ import { emitKeypressEvents } from "node:readline";
4
4
  import { createInterface } from "node:readline/promises";
5
5
  import { stdin, stdout } from "node:process";
6
6
  import { highlightCode, initTheme, SessionManager, truncateToVisualLines } from "@earendil-works/pi-coding-agent";
7
- import { formatBudgetStatus, inspectWorkflowScript } from "pi-extensible-workflows";
7
+ import { errorText, formatBudgetStatus, inspectWorkflowScript } from "pi-extensible-workflows";
8
8
  import { listPersistedSessionIds, listRunIds, RunStore } from "pi-extensible-workflows/persistence";
9
9
  function text(content) {
10
10
  if (typeof content === "string")
@@ -242,7 +242,7 @@ export async function loadSessionReport(path, home = homedir()) {
242
242
  staticCalls = inspectWorkflowScript(script);
243
243
  }
244
244
  catch (error) {
245
- parseError = error instanceof Error ? error.message : String(error);
245
+ parseError = errorText(error);
246
246
  }
247
247
  }
248
248
  workflows.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piewf/cli",
3
- "version": "5.5.0-rc.1",
3
+ "version": "5.6.1",
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.5.0-rc.1"
49
+ "pi-extensible-workflows": "5.6.1"
50
50
  },
51
51
  "publishConfig": {
52
52
  "access": "public"