terminal-pilot 0.0.15 → 0.0.17

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 (45) hide show
  1. package/dist/cli.js +2570 -774
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.js +7 -2
  4. package/dist/commands/close-session.js.map +4 -4
  5. package/dist/commands/create-session.js +7 -2
  6. package/dist/commands/create-session.js.map +4 -4
  7. package/dist/commands/fill.js +7 -2
  8. package/dist/commands/fill.js.map +4 -4
  9. package/dist/commands/get-session.js +7 -2
  10. package/dist/commands/get-session.js.map +4 -4
  11. package/dist/commands/index.js +29 -24
  12. package/dist/commands/index.js.map +4 -4
  13. package/dist/commands/install.js +13 -8
  14. package/dist/commands/install.js.map +4 -4
  15. package/dist/commands/installer.js +15 -10
  16. package/dist/commands/installer.js.map +4 -4
  17. package/dist/commands/list-sessions.js +7 -2
  18. package/dist/commands/list-sessions.js.map +4 -4
  19. package/dist/commands/press-key.js +7 -2
  20. package/dist/commands/press-key.js.map +4 -4
  21. package/dist/commands/read-history.js +7 -2
  22. package/dist/commands/read-history.js.map +4 -4
  23. package/dist/commands/read-screen.js +7 -2
  24. package/dist/commands/read-screen.js.map +4 -4
  25. package/dist/commands/resize.js +7 -2
  26. package/dist/commands/resize.js.map +4 -4
  27. package/dist/commands/runtime.js +6 -1
  28. package/dist/commands/runtime.js.map +4 -4
  29. package/dist/commands/screenshot.js +11 -6
  30. package/dist/commands/screenshot.js.map +4 -4
  31. package/dist/commands/send-signal.js +7 -2
  32. package/dist/commands/send-signal.js.map +4 -4
  33. package/dist/commands/type.js +7 -2
  34. package/dist/commands/type.js.map +4 -4
  35. package/dist/commands/uninstall.js +16 -11
  36. package/dist/commands/uninstall.js.map +4 -4
  37. package/dist/commands/wait-for-exit.js +7 -2
  38. package/dist/commands/wait-for-exit.js.map +4 -4
  39. package/dist/commands/wait-for.js +7 -2
  40. package/dist/commands/wait-for.js.map +4 -4
  41. package/dist/testing/cli-repl.js +2571 -774
  42. package/dist/testing/cli-repl.js.map +4 -4
  43. package/dist/testing/qa-cli.js +2579 -782
  44. package/dist/testing/qa-cli.js.map +4 -4
  45. package/package.json +4 -2
package/dist/cli.js CHANGED
@@ -1,65 +1,68 @@
1
1
  #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
2
7
 
3
8
  // src/cli.ts
4
9
  import { realpath } from "node:fs/promises";
5
- import path11 from "node:path";
6
- import { fileURLToPath as fileURLToPath4 } from "node:url";
10
+ import path14 from "node:path";
11
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
7
12
 
8
13
  // ../toolcraft/src/cli.ts
9
- import { access as access2, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
10
- import path6 from "node:path";
11
- import { Command as CommanderCommand, CommanderError, InvalidArgumentError, Option } from "commander";
14
+ import { access as access2, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
15
+ import path9 from "node:path";
16
+ import {
17
+ Command as CommanderCommand,
18
+ CommanderError,
19
+ InvalidArgumentError,
20
+ Option
21
+ } from "commander";
12
22
 
13
23
  // ../design-system/src/tokens/colors.ts
14
24
  import chalk from "chalk";
15
25
  var dark = {
16
- header: (text4) => chalk.magentaBright.bold(text4),
17
- divider: (text4) => chalk.dim(text4),
18
- prompt: (text4) => chalk.cyan(text4),
19
- number: (text4) => chalk.cyanBright(text4),
20
- intro: (text4) => chalk.bgMagenta.white(` Poe - ${text4} `),
26
+ header: (text5) => chalk.magentaBright.bold(text5),
27
+ divider: (text5) => chalk.dim(text5),
28
+ prompt: (text5) => chalk.cyan(text5),
29
+ number: (text5) => chalk.cyanBright(text5),
30
+ intro: (text5) => chalk.bgMagenta.white(` Poe - ${text5} `),
21
31
  resolvedSymbol: chalk.magenta("\u25C7"),
22
32
  errorSymbol: chalk.red("\u25A0"),
23
- accent: (text4) => chalk.cyan(text4),
24
- muted: (text4) => chalk.dim(text4),
25
- success: (text4) => chalk.green(text4),
26
- warning: (text4) => chalk.yellow(text4),
27
- error: (text4) => chalk.red(text4),
28
- info: (text4) => chalk.magenta(text4),
29
- badge: (text4) => chalk.bgYellow.black(` ${text4} `)
33
+ accent: (text5) => chalk.cyan(text5),
34
+ muted: (text5) => chalk.dim(text5),
35
+ success: (text5) => chalk.green(text5),
36
+ warning: (text5) => chalk.yellow(text5),
37
+ error: (text5) => chalk.red(text5),
38
+ info: (text5) => chalk.magenta(text5),
39
+ badge: (text5) => chalk.bgYellow.black(` ${text5} `)
30
40
  };
31
41
  var light = {
32
- header: (text4) => chalk.hex("#a200ff").bold(text4),
33
- divider: (text4) => chalk.hex("#666666")(text4),
34
- prompt: (text4) => chalk.hex("#006699").bold(text4),
35
- number: (text4) => chalk.hex("#0077cc").bold(text4),
36
- intro: (text4) => chalk.bgHex("#a200ff").white(` Poe - ${text4} `),
42
+ header: (text5) => chalk.hex("#a200ff").bold(text5),
43
+ divider: (text5) => chalk.hex("#666666")(text5),
44
+ prompt: (text5) => chalk.hex("#006699").bold(text5),
45
+ number: (text5) => chalk.hex("#0077cc").bold(text5),
46
+ intro: (text5) => chalk.bgHex("#a200ff").white(` Poe - ${text5} `),
37
47
  resolvedSymbol: chalk.hex("#a200ff")("\u25C7"),
38
48
  errorSymbol: chalk.hex("#cc0000")("\u25A0"),
39
- accent: (text4) => chalk.hex("#006699").bold(text4),
40
- muted: (text4) => chalk.hex("#666666")(text4),
41
- success: (text4) => chalk.hex("#008800")(text4),
42
- warning: (text4) => chalk.hex("#cc6600")(text4),
43
- error: (text4) => chalk.hex("#cc0000")(text4),
44
- info: (text4) => chalk.hex("#a200ff")(text4),
45
- badge: (text4) => chalk.bgHex("#cc6600").white(` ${text4} `)
49
+ accent: (text5) => chalk.hex("#006699").bold(text5),
50
+ muted: (text5) => chalk.hex("#666666")(text5),
51
+ success: (text5) => chalk.hex("#008800")(text5),
52
+ warning: (text5) => chalk.hex("#cc6600")(text5),
53
+ error: (text5) => chalk.hex("#cc0000")(text5),
54
+ info: (text5) => chalk.hex("#a200ff")(text5),
55
+ badge: (text5) => chalk.bgHex("#cc6600").white(` ${text5} `)
46
56
  };
47
57
 
48
58
  // ../design-system/src/tokens/typography.ts
49
59
  import chalk2 from "chalk";
50
60
  var typography = {
51
- bold: (text4) => chalk2.bold(text4),
52
- dim: (text4) => chalk2.dim(text4),
53
- italic: (text4) => chalk2.italic(text4),
54
- underline: (text4) => chalk2.underline(text4),
55
- strikethrough: (text4) => chalk2.strikethrough(text4)
56
- };
57
-
58
- // ../design-system/src/tokens/widths.ts
59
- var widths = {
60
- header: 60,
61
- helpColumn: 24,
62
- maxLine: 80
61
+ bold: (text5) => chalk2.bold(text5),
62
+ dim: (text5) => chalk2.dim(text5),
63
+ italic: (text5) => chalk2.italic(text5),
64
+ underline: (text5) => chalk2.underline(text5),
65
+ strikethrough: (text5) => chalk2.strikethrough(text5)
63
66
  };
64
67
 
65
68
  // ../design-system/src/components/text.ts
@@ -153,6 +156,12 @@ var text = {
153
156
  if (format === "markdown") return `**${content}**`;
154
157
  return typography.bold(content);
155
158
  },
159
+ sectionHeader(content) {
160
+ const format = resolveOutputFormat();
161
+ if (format === "json") return content;
162
+ if (format === "markdown") return `## ${content}`;
163
+ return typography.bold(content.toUpperCase());
164
+ },
156
165
  command(content) {
157
166
  const format = resolveOutputFormat();
158
167
  if (format === "json") return content;
@@ -465,19 +474,248 @@ function createLogger(emitter) {
465
474
  var logger = createLogger();
466
475
 
467
476
  // ../design-system/src/components/help-formatter.ts
468
- function formatCommand(name, description) {
469
- const paddedName = name.padEnd(widths.helpColumn);
470
- return ` ${text.command(paddedName)} ${description}`;
477
+ function stripAnsi2(value) {
478
+ let output = "";
479
+ for (let index = 0; index < value.length; index += 1)
480
+ if (value[index] === "\x1B" && value[index + 1] === "[")
481
+ while (index < value.length && value[index] !== "m") index += 1;
482
+ else output += value[index];
483
+ return output;
484
+ }
485
+ function visibleWidth(value) {
486
+ return stripAnsi2(value).length;
487
+ }
488
+ function clamp(value, min, max) {
489
+ return Math.min(Math.max(value, min), max);
490
+ }
491
+ function padEndVisible(value, width) {
492
+ return value + " ".repeat(Math.max(0, width - visibleWidth(value)));
493
+ }
494
+ function isWhitespace(char) {
495
+ return char === " " || char === "\n" || char === " " || char === "\r";
496
+ }
497
+ function splitWords(value) {
498
+ const words = [];
499
+ let word = "";
500
+ for (const char of value) {
501
+ if (isWhitespace(char)) {
502
+ if (word) {
503
+ words.push(word);
504
+ word = "";
505
+ }
506
+ continue;
507
+ }
508
+ word += char;
509
+ }
510
+ if (word) {
511
+ words.push(word);
512
+ }
513
+ return words;
514
+ }
515
+ function wrapWords(value, width) {
516
+ const words = splitWords(value);
517
+ if (words.length === 0) {
518
+ return [""];
519
+ }
520
+ const lines = [];
521
+ let line = "";
522
+ for (const word of words) {
523
+ if (!line) {
524
+ line = word;
525
+ continue;
526
+ }
527
+ if (visibleWidth(line) + 1 + visibleWidth(word) <= width) {
528
+ line += ` ${word}`;
529
+ continue;
530
+ }
531
+ lines.push(line);
532
+ line = word;
533
+ }
534
+ lines.push(line);
535
+ return lines;
471
536
  }
472
- function formatOption(flags, description) {
473
- const paddedFlags = flags.padEnd(widths.helpColumn);
474
- return ` ${text.option(paddedFlags)} ${description}`;
537
+ function formatColumns(opts) {
538
+ const { rows } = opts;
539
+ if (rows.length === 0) {
540
+ return "";
541
+ }
542
+ const totalWidth = opts.totalWidth ?? process.stdout.columns ?? 100;
543
+ const minLeftWidth = opts.minLeftWidth ?? 12;
544
+ const maxLeftWidth = opts.maxLeftWidth ?? 32;
545
+ const gap = opts.gap ?? 3;
546
+ const indent = opts.indent ?? 2;
547
+ const maxLeftContentWidth = Math.max(...rows.map((row) => visibleWidth(row.left)));
548
+ const leftWidth = clamp(maxLeftContentWidth + gap, minLeftWidth, maxLeftWidth);
549
+ const rightWidth = Math.max(20, totalWidth - leftWidth - indent);
550
+ const firstIndent = " ".repeat(indent);
551
+ const continuationIndent = " ".repeat(indent + leftWidth);
552
+ return rows.flatMap((row) => {
553
+ if (row.right.length === 0) {
554
+ return [`${firstIndent}${row.left}`];
555
+ }
556
+ const rightLines = wrapWords(row.right, rightWidth);
557
+ if (visibleWidth(row.left) > leftWidth) {
558
+ return [
559
+ `${firstIndent}${row.left}`,
560
+ ...rightLines.map((line) => `${continuationIndent}${line}`)
561
+ ];
562
+ }
563
+ const firstLine = `${firstIndent}${padEndVisible(row.left, leftWidth)}${rightLines[0]}`;
564
+ const continuationLines = rightLines.slice(1).map((line) => `${continuationIndent}${line}`);
565
+ return [firstLine, ...continuationLines];
566
+ }).join("\n");
475
567
  }
476
568
  function formatCommandList(commands) {
477
- return commands.map((cmd) => formatCommand(cmd.name, cmd.description)).join("\n");
569
+ return formatColumns({
570
+ rows: commands.map((cmd) => ({
571
+ left: text.command(cmd.name),
572
+ right: cmd.description
573
+ }))
574
+ });
478
575
  }
479
576
  function formatOptionList(options) {
480
- return options.map((opt) => formatOption(opt.flags, opt.description)).join("\n");
577
+ return formatColumns({
578
+ rows: options.map((opt) => ({
579
+ left: text.option(opt.flags),
580
+ right: opt.description
581
+ }))
582
+ });
583
+ }
584
+
585
+ // ../design-system/src/components/help-formatter-plain.ts
586
+ var help_formatter_plain_exports = {};
587
+ __export(help_formatter_plain_exports, {
588
+ formatColumns: () => formatColumns2,
589
+ formatCommandList: () => formatCommandList2,
590
+ formatOptionList: () => formatOptionList2
591
+ });
592
+ function stripAnsi3(value) {
593
+ let output = "";
594
+ for (let index = 0; index < value.length; index += 1) {
595
+ if (value[index] === "\x1B") {
596
+ if (value[index + 1] === "[") {
597
+ index += 2;
598
+ while (index < value.length) {
599
+ const code = value.charCodeAt(index);
600
+ if (code >= 64 && code <= 126) {
601
+ break;
602
+ }
603
+ index += 1;
604
+ }
605
+ }
606
+ continue;
607
+ }
608
+ output += value[index];
609
+ }
610
+ return output;
611
+ }
612
+ function toAscii(value) {
613
+ let output = "";
614
+ const stripped = stripAnsi3(value);
615
+ for (let index = 0; index < stripped.length; index += 1) {
616
+ const code = stripped.charCodeAt(index);
617
+ output += code <= 127 ? stripped[index] : "?";
618
+ }
619
+ return output;
620
+ }
621
+ function clamp2(value, min, max) {
622
+ return Math.min(Math.max(value, min), max);
623
+ }
624
+ function padEndVisible2(value, width) {
625
+ return value + " ".repeat(Math.max(0, width - value.length));
626
+ }
627
+ function isWhitespace2(char) {
628
+ return char === " " || char === "\n" || char === " " || char === "\r";
629
+ }
630
+ function splitWords2(value) {
631
+ const words = [];
632
+ let word = "";
633
+ for (const char of value) {
634
+ if (isWhitespace2(char)) {
635
+ if (word) {
636
+ words.push(word);
637
+ word = "";
638
+ }
639
+ continue;
640
+ }
641
+ word += char;
642
+ }
643
+ if (word) {
644
+ words.push(word);
645
+ }
646
+ return words;
647
+ }
648
+ function wrapWords2(value, width) {
649
+ const words = splitWords2(value);
650
+ if (words.length === 0) {
651
+ return [""];
652
+ }
653
+ const lines = [];
654
+ let line = "";
655
+ for (const word of words) {
656
+ if (!line) {
657
+ line = word;
658
+ continue;
659
+ }
660
+ if (line.length + 1 + word.length <= width) {
661
+ line += ` ${word}`;
662
+ continue;
663
+ }
664
+ lines.push(line);
665
+ line = word;
666
+ }
667
+ lines.push(line);
668
+ return lines;
669
+ }
670
+ function formatColumns2(opts) {
671
+ const rows = opts.rows.map((row) => ({
672
+ left: toAscii(row.left),
673
+ right: toAscii(row.right)
674
+ }));
675
+ if (rows.length === 0) {
676
+ return "";
677
+ }
678
+ const totalWidth = opts.totalWidth ?? process.stdout.columns ?? 100;
679
+ const minLeftWidth = opts.minLeftWidth ?? 12;
680
+ const maxLeftWidth = opts.maxLeftWidth ?? 32;
681
+ const gap = opts.gap ?? 3;
682
+ const indent = opts.indent ?? 2;
683
+ const maxLeftContentWidth = Math.max(...rows.map((row) => row.left.length));
684
+ const leftWidth = clamp2(maxLeftContentWidth + gap, minLeftWidth, maxLeftWidth);
685
+ const rightWidth = Math.max(20, totalWidth - leftWidth - indent);
686
+ const firstIndent = " ".repeat(indent);
687
+ const continuationIndent = " ".repeat(indent + leftWidth);
688
+ return rows.flatMap((row) => {
689
+ if (row.right.length === 0) {
690
+ return [`${firstIndent}${row.left}`];
691
+ }
692
+ const rightLines = wrapWords2(row.right, rightWidth);
693
+ if (row.left.length > leftWidth) {
694
+ return [
695
+ `${firstIndent}${row.left}`,
696
+ ...rightLines.map((line) => `${continuationIndent}${line}`)
697
+ ];
698
+ }
699
+ const firstLine = `${firstIndent}${padEndVisible2(row.left, leftWidth)}${rightLines[0]}`;
700
+ const continuationLines = rightLines.slice(1).map((line) => `${continuationIndent}${line}`);
701
+ return [firstLine, ...continuationLines];
702
+ }).join("\n");
703
+ }
704
+ function formatCommandList2(commands) {
705
+ return formatColumns2({
706
+ rows: commands.map((cmd) => ({
707
+ left: cmd.name,
708
+ right: cmd.description
709
+ }))
710
+ });
711
+ }
712
+ function formatOptionList2(options) {
713
+ return formatColumns2({
714
+ rows: options.map((opt) => ({
715
+ left: opt.flags,
716
+ right: opt.description
717
+ }))
718
+ });
481
719
  }
482
720
 
483
721
  // ../design-system/src/components/table.ts
@@ -666,7 +904,7 @@ async function confirm2(opts) {
666
904
  import chalk16 from "chalk";
667
905
 
668
906
  // ../toolcraft/src/index.ts
669
- import { fileURLToPath } from "node:url";
907
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
670
908
 
671
909
  // ../toolcraft/src/user-error.ts
672
910
  var UserError = class extends Error {
@@ -835,6 +1073,62 @@ var S = {
835
1073
  Json
836
1074
  };
837
1075
 
1076
+ // ../toolcraft/src/package-metadata.ts
1077
+ import { existsSync, readFileSync, statSync } from "node:fs";
1078
+ import path from "node:path";
1079
+ import { fileURLToPath } from "node:url";
1080
+ function pathFromInput(from) {
1081
+ if (from instanceof URL) {
1082
+ return fileURLToPath(from);
1083
+ }
1084
+ if (from.startsWith("file:")) {
1085
+ return fileURLToPath(from);
1086
+ }
1087
+ return path.resolve(from);
1088
+ }
1089
+ function getSearchDirectory(from) {
1090
+ const resolved = pathFromInput(from);
1091
+ try {
1092
+ return statSync(resolved).isDirectory() ? resolved : path.dirname(resolved);
1093
+ } catch {
1094
+ return path.dirname(resolved);
1095
+ }
1096
+ }
1097
+ function readPackageMetadata(packageJsonPath) {
1098
+ const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
1099
+ const metadata = { path: packageJsonPath };
1100
+ if (typeof parsed.name === "string") {
1101
+ metadata.name = parsed.name;
1102
+ }
1103
+ if (typeof parsed.version === "string") {
1104
+ metadata.version = parsed.version;
1105
+ }
1106
+ return metadata;
1107
+ }
1108
+ function findPackageMetadata(from) {
1109
+ let current = getSearchDirectory(from);
1110
+ while (true) {
1111
+ const packageJsonPath = path.join(current, "package.json");
1112
+ if (existsSync(packageJsonPath)) {
1113
+ return readPackageMetadata(packageJsonPath);
1114
+ }
1115
+ const parent = path.dirname(current);
1116
+ if (parent === current) {
1117
+ return void 0;
1118
+ }
1119
+ current = parent;
1120
+ }
1121
+ }
1122
+ function findEntrypointPackageMetadata(entrypoint) {
1123
+ if (entrypoint === void 0 || entrypoint.length === 0) {
1124
+ return void 0;
1125
+ }
1126
+ if (!path.isAbsolute(entrypoint) && !entrypoint.startsWith("file:")) {
1127
+ return void 0;
1128
+ }
1129
+ return findPackageMetadata(entrypoint);
1130
+ }
1131
+
838
1132
  // ../toolcraft/src/index.ts
839
1133
  var commandConfigSymbol = /* @__PURE__ */ Symbol("toolcraft.command.config");
840
1134
  var groupConfigSymbol = /* @__PURE__ */ Symbol("toolcraft.group.config");
@@ -920,7 +1214,7 @@ function validateRenameMap(rename2) {
920
1214
  function parseStackPath(candidate) {
921
1215
  if (candidate.startsWith("file://")) {
922
1216
  try {
923
- return fileURLToPath(candidate);
1217
+ return fileURLToPath2(candidate);
924
1218
  } catch {
925
1219
  return void 0;
926
1220
  }
@@ -1274,134 +1568,1196 @@ function getCommandSourcePath(command) {
1274
1568
  // ../task-list/src/open.ts
1275
1569
  import * as fsPromises2 from "node:fs/promises";
1276
1570
 
1277
- // ../task-list/src/backends/markdown-dir.ts
1278
- import path2 from "node:path";
1279
-
1280
- // ../file-lock/src/lock.ts
1281
- import * as fsPromises from "node:fs/promises";
1282
- import * as os from "node:os";
1283
- var LockTimeoutError = class extends Error {
1284
- constructor(message2) {
1285
- super(message2);
1286
- this.name = "LockTimeoutError";
1287
- }
1288
- };
1289
- function createAbortError() {
1290
- const error2 = new Error("The operation was aborted.");
1291
- error2.name = "AbortError";
1292
- return error2;
1571
+ // ../task-list/src/state-machine.ts
1572
+ function isRecord(value) {
1573
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1293
1574
  }
1294
- function throwIfAborted(signal) {
1295
- if (signal?.aborted) {
1296
- throw createAbortError();
1575
+ function isStateList(value) {
1576
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
1577
+ }
1578
+ function canFireFromState(event, fromState) {
1579
+ if (event.from === "*") {
1580
+ return event.to !== fromState;
1297
1581
  }
1582
+ return event.from.includes(fromState);
1298
1583
  }
1299
- function sleep(ms, signal) {
1300
- if (!signal) {
1301
- return new Promise((resolve) => setTimeout(resolve, ms));
1584
+ function validateMachine(machine) {
1585
+ if (!isRecord(machine)) {
1586
+ throw new TypeError("State machine must be an object.");
1302
1587
  }
1303
- if (signal.aborted) {
1304
- return Promise.reject(createAbortError());
1588
+ if (!isStateList(machine.states)) {
1589
+ throw new TypeError("State machine states must be a string array.");
1305
1590
  }
1306
- return new Promise((resolve, reject) => {
1307
- const timeoutId = setTimeout(() => {
1308
- signal.removeEventListener("abort", onAbort);
1309
- resolve();
1310
- }, ms);
1311
- const onAbort = () => {
1312
- clearTimeout(timeoutId);
1313
- signal.removeEventListener("abort", onAbort);
1314
- reject(createAbortError());
1315
- };
1316
- signal.addEventListener("abort", onAbort, { once: true });
1317
- });
1318
- }
1319
- function backoff(attempt, minTimeout, maxTimeout) {
1320
- const delay = Math.min(maxTimeout, minTimeout * 2 ** attempt);
1321
- return delay + Math.random() * delay * 0.1;
1322
- }
1323
- function hasErrorCode(error2, code) {
1324
- return !!error2 && typeof error2 === "object" && "code" in error2 && error2.code === code;
1325
- }
1326
- function createDefaultFs() {
1327
- return {
1328
- open: (path12, flags) => fsPromises.open(path12, flags),
1329
- stat: fsPromises.stat,
1330
- unlink: fsPromises.unlink
1331
- };
1332
- }
1333
- async function removeLockFile(fs2, lockPath) {
1334
- try {
1335
- await fs2.unlink(lockPath);
1336
- } catch (error2) {
1337
- if (!hasErrorCode(error2, "ENOENT")) {
1338
- throw error2;
1339
- }
1591
+ const states = new Set(machine.states);
1592
+ if (typeof machine.initial !== "string") {
1593
+ throw new TypeError("State machine initial must be a string.");
1340
1594
  }
1341
- }
1342
- async function writeLockMetadata(handle) {
1343
- try {
1344
- await handle.writeFile(
1345
- JSON.stringify({ pid: process.pid, host: os.hostname(), acquiredAt: (/* @__PURE__ */ new Date()).toISOString() }),
1346
- { encoding: "utf8" }
1347
- );
1348
- } catch (ignoredError) {
1349
- void ignoredError;
1595
+ if (!states.has(machine.initial)) {
1596
+ throw new Error(`Initial state "${machine.initial}" is not declared.`);
1350
1597
  }
1351
- try {
1352
- await handle.close();
1353
- } catch (ignoredError) {
1354
- void ignoredError;
1598
+ if (!isRecord(machine.events)) {
1599
+ throw new TypeError("State machine events must be an object.");
1355
1600
  }
1356
- }
1357
- async function acquireFileLock(filePath, options = {}) {
1358
- const fs2 = options.fs ?? createDefaultFs();
1359
- const retries = options.retries ?? 20;
1360
- const minTimeout = options.minTimeout ?? 25;
1361
- const maxTimeout = options.maxTimeout ?? 250;
1362
- const staleMs = options.staleMs ?? 3e4;
1363
- const lockPath = `${filePath}.lock`;
1364
- let attempt = 0;
1365
- while (attempt <= retries) {
1366
- throwIfAborted(options.signal);
1367
- try {
1368
- const handle = await fs2.open(lockPath, "wx");
1369
- await writeLockMetadata(handle);
1370
- let released = false;
1371
- return async () => {
1372
- if (released) {
1373
- return;
1374
- }
1375
- released = true;
1376
- await removeLockFile(fs2, lockPath);
1377
- };
1378
- } catch (error2) {
1379
- if (!hasErrorCode(error2, "EEXIST")) {
1380
- throw error2;
1381
- }
1601
+ for (const [eventName, event] of Object.entries(machine.events)) {
1602
+ if (!isRecord(event)) {
1603
+ throw new TypeError(`Event "${eventName}" must be an object.`);
1382
1604
  }
1383
- let stat3;
1384
- try {
1385
- stat3 = await fs2.stat(lockPath);
1386
- } catch (statError) {
1387
- if (hasErrorCode(statError, "ENOENT")) {
1388
- continue;
1389
- }
1390
- throw statError;
1605
+ if (event.from !== "*" && !isStateList(event.from)) {
1606
+ throw new TypeError(`Event "${eventName}" has an invalid "from" definition.`);
1391
1607
  }
1392
- if (Date.now() - stat3.mtimeMs > staleMs) {
1393
- await removeLockFile(fs2, lockPath);
1394
- continue;
1608
+ if (typeof event.to !== "string") {
1609
+ throw new TypeError(`Event "${eventName}" target state must be a string.`);
1395
1610
  }
1396
- if (attempt >= retries) {
1397
- break;
1611
+ if (!states.has(event.to)) {
1612
+ throw new Error(`Event "${eventName}" references unknown target state "${event.to}".`);
1398
1613
  }
1399
- await sleep(backoff(attempt, minTimeout, maxTimeout), options.signal);
1400
- attempt += 1;
1401
- }
1402
- throw new LockTimeoutError(`Failed to acquire lock on "${filePath}".`);
1403
- }
1404
-
1614
+ if (event.from !== "*") {
1615
+ for (const fromState of event.from) {
1616
+ if (!states.has(fromState)) {
1617
+ throw new Error(`Event "${eventName}" references unknown source state "${fromState}".`);
1618
+ }
1619
+ }
1620
+ }
1621
+ }
1622
+ }
1623
+ function eventsFromState(machine, fromState) {
1624
+ const events = [];
1625
+ for (const [eventName, event] of Object.entries(machine.events)) {
1626
+ if (canFireFromState(event, fromState)) {
1627
+ events.push(eventName);
1628
+ }
1629
+ }
1630
+ return events;
1631
+ }
1632
+ function findEvent(machine, fromState, eventName) {
1633
+ const event = machine.events[eventName];
1634
+ if (event === void 0) {
1635
+ return void 0;
1636
+ }
1637
+ return canFireFromState(event, fromState) ? event : void 0;
1638
+ }
1639
+
1640
+ // ../task-list/src/types.ts
1641
+ var TaskNotFoundError = class extends Error {
1642
+ constructor(message2 = "Task not found.") {
1643
+ super(message2);
1644
+ this.name = "TaskNotFoundError";
1645
+ }
1646
+ };
1647
+ var TaskAlreadyExistsError = class extends Error {
1648
+ constructor(message2 = "Task already exists.") {
1649
+ super(message2);
1650
+ this.name = "TaskAlreadyExistsError";
1651
+ }
1652
+ };
1653
+ var InvalidTransitionError = class extends Error {
1654
+ task;
1655
+ event;
1656
+ to;
1657
+ reason;
1658
+ constructor(messageOrOptions = "Invalid task transition.") {
1659
+ const options = typeof messageOrOptions === "string" ? {
1660
+ reason: messageOrOptions
1661
+ } : messageOrOptions;
1662
+ super(options.reason);
1663
+ this.name = "InvalidTransitionError";
1664
+ this.task = options.task;
1665
+ this.event = options.event;
1666
+ this.to = options.to;
1667
+ this.reason = options.reason;
1668
+ }
1669
+ };
1670
+ var MalformedTaskError = class extends Error {
1671
+ constructor(message2 = "Malformed task.") {
1672
+ super(message2);
1673
+ this.name = "MalformedTaskError";
1674
+ }
1675
+ };
1676
+ var OrderMismatchError = class extends Error {
1677
+ missing;
1678
+ extra;
1679
+ constructor(options) {
1680
+ const parts = [];
1681
+ if (options.missing.length > 0) {
1682
+ parts.push(`missing ${options.missing.map((id) => `"${id}"`).join(", ")}`);
1683
+ }
1684
+ if (options.extra.length > 0) {
1685
+ parts.push(`extra ${options.extra.map((id) => `"${id}"`).join(", ")}`);
1686
+ }
1687
+ super(`reorder requires the exact set of active task ids: ${parts.join("; ")}.`);
1688
+ this.name = "OrderMismatchError";
1689
+ this.missing = options.missing;
1690
+ this.extra = options.extra;
1691
+ }
1692
+ };
1693
+ var AnchorNotFoundError = class extends Error {
1694
+ anchor;
1695
+ constructor(anchor) {
1696
+ super(`Anchor task "${anchor}" not found.`);
1697
+ this.name = "AnchorNotFoundError";
1698
+ this.anchor = anchor;
1699
+ }
1700
+ };
1701
+
1702
+ // ../task-list/src/backends/gh-issues-client.ts
1703
+ import { text as text4 } from "node:stream/consumers";
1704
+
1705
+ // ../process-runner/src/docker/context.ts
1706
+ import { execSync } from "node:child_process";
1707
+
1708
+ // ../process-runner/src/docker/engine.ts
1709
+ import { execSync as execSync2 } from "node:child_process";
1710
+
1711
+ // ../process-runner/src/docker/docker-runner.ts
1712
+ import * as childProcess from "node:child_process";
1713
+ import { randomBytes } from "node:crypto";
1714
+
1715
+ // ../process-runner/src/docker/args.ts
1716
+ import path2 from "node:path";
1717
+
1718
+ // ../process-runner/src/docker/docker-execution-env.ts
1719
+ import { createHash, randomBytes as randomBytes2 } from "node:crypto";
1720
+ import { mkdtempSync, rmSync } from "node:fs";
1721
+ import { readFile } from "node:fs/promises";
1722
+ import { tmpdir } from "node:os";
1723
+ import path3 from "node:path";
1724
+
1725
+ // ../process-runner/src/host/host-runner.ts
1726
+ import { spawn as spawnChildProcess } from "node:child_process";
1727
+ function createHostRunner(options = {}) {
1728
+ const detached = options.detached === true;
1729
+ return {
1730
+ name: "host",
1731
+ exec(spec) {
1732
+ const stdinMode = spec.stdin ?? "ignore";
1733
+ const stdoutMode = spec.stdout ?? "pipe";
1734
+ const stderrMode = spec.stderr ?? "pipe";
1735
+ const stdio = stdinMode === "inherit" && stdoutMode === "inherit" && stderrMode === "inherit" ? "inherit" : [stdinMode, stdoutMode, stderrMode];
1736
+ const child = spawnChildProcess(spec.command, spec.args ?? [], {
1737
+ cwd: spec.cwd,
1738
+ env: spec.env,
1739
+ stdio,
1740
+ ...detached ? { detached: true } : {}
1741
+ });
1742
+ if (detached) {
1743
+ child.unref();
1744
+ }
1745
+ const kill = (signal) => {
1746
+ if (detached && process.platform !== "win32" && child.pid !== void 0) {
1747
+ process.kill(-child.pid, signal);
1748
+ return;
1749
+ }
1750
+ child.kill(signal);
1751
+ };
1752
+ let settled = false;
1753
+ let resolveResult = null;
1754
+ const result = new Promise((resolve) => {
1755
+ resolveResult = resolve;
1756
+ });
1757
+ const cleanupAbort = bindAbortSignal(spec.signal, () => {
1758
+ kill("SIGTERM");
1759
+ });
1760
+ child.once("close", (code) => {
1761
+ if (settled) return;
1762
+ settled = true;
1763
+ cleanupAbort();
1764
+ resolveResult?.({ exitCode: code ?? 1 });
1765
+ });
1766
+ child.once("error", () => {
1767
+ if (settled) return;
1768
+ settled = true;
1769
+ cleanupAbort();
1770
+ resolveResult?.({ exitCode: 1 });
1771
+ });
1772
+ return {
1773
+ pid: child.pid ?? null,
1774
+ stdin: child.stdin,
1775
+ stdout: child.stdout,
1776
+ stderr: child.stderr,
1777
+ result,
1778
+ kill
1779
+ };
1780
+ }
1781
+ };
1782
+ }
1783
+ function bindAbortSignal(signal, onAbort) {
1784
+ if (signal === void 0) {
1785
+ return () => {
1786
+ };
1787
+ }
1788
+ if (signal.aborted) {
1789
+ onAbort();
1790
+ return () => {
1791
+ };
1792
+ }
1793
+ signal.addEventListener("abort", onAbort, { once: true });
1794
+ return () => {
1795
+ signal.removeEventListener("abort", onAbort);
1796
+ };
1797
+ }
1798
+
1799
+ // ../process-runner/src/testing/mock-runner.ts
1800
+ import { Readable, Writable } from "node:stream";
1801
+
1802
+ // ../task-list/src/backends/gh-issues-client.ts
1803
+ var DEFAULT_ENDPOINT = "https://api.github.com/graphql";
1804
+ var USER_AGENT = "poe-code-task-list/0.0.1";
1805
+ var AUTH_ERROR = "gh auth token failed; install gh, run 'gh auth login', or pass auth: { token }";
1806
+ function createGhClient(options) {
1807
+ const fetchImpl = options.fetch ?? fetch;
1808
+ const endpoint = options.endpoint || DEFAULT_ENDPOINT;
1809
+ return {
1810
+ async graphql(query, variables) {
1811
+ const response = await fetchImpl(endpoint, {
1812
+ method: "POST",
1813
+ headers: {
1814
+ Authorization: `Bearer ${options.token}`,
1815
+ "Content-Type": "application/json",
1816
+ "User-Agent": USER_AGENT
1817
+ },
1818
+ body: JSON.stringify({ query, variables })
1819
+ });
1820
+ const body = await response.text();
1821
+ if (response.status !== 200) {
1822
+ throw new Error(`GitHub GraphQL request failed with status ${response.status}: ${body}`);
1823
+ }
1824
+ const parsed = JSON.parse(body);
1825
+ const firstError = parsed.errors?.[0];
1826
+ if (firstError !== void 0) {
1827
+ throw new Error(firstError.message ?? "GitHub GraphQL request failed");
1828
+ }
1829
+ return parsed.data;
1830
+ }
1831
+ };
1832
+ }
1833
+ async function resolveAuth(options) {
1834
+ if (options.explicitToken !== void 0) {
1835
+ return options.explicitToken;
1836
+ }
1837
+ const runner = options.runner ?? createHostRunner();
1838
+ const handle = runner.exec({
1839
+ command: "gh",
1840
+ args: ["auth", "token"],
1841
+ stdout: "pipe",
1842
+ stderr: "pipe"
1843
+ });
1844
+ const [stdout, , result] = await Promise.all([
1845
+ handle.stdout === null ? Promise.resolve("") : text4(handle.stdout),
1846
+ handle.stderr === null ? Promise.resolve("") : text4(handle.stderr),
1847
+ handle.result
1848
+ ]);
1849
+ const token = stdout.trim();
1850
+ if (result.exitCode !== 0 || token.length === 0) {
1851
+ throw new Error(AUTH_ERROR);
1852
+ }
1853
+ return token;
1854
+ }
1855
+ function resolveEndpoint(options = {}) {
1856
+ const env = options.env ?? process.env;
1857
+ const host = env.GH_HOST;
1858
+ if (host !== void 0 && host !== "" && host !== "github.com") {
1859
+ return `https://${host}/api/graphql`;
1860
+ }
1861
+ return DEFAULT_ENDPOINT;
1862
+ }
1863
+
1864
+ // ../task-list/src/backends/utils.ts
1865
+ import path4 from "node:path";
1866
+ function compareCreated(left, right) {
1867
+ const leftCreated = typeof left.raw.created === "string" ? left.raw.created : "";
1868
+ const rightCreated = typeof right.raw.created === "string" ? right.raw.created : "";
1869
+ if (leftCreated === "" && rightCreated === "") {
1870
+ return left.task.qualifiedId.localeCompare(right.task.qualifiedId);
1871
+ }
1872
+ if (leftCreated === "") return 1;
1873
+ if (rightCreated === "") return -1;
1874
+ return leftCreated.localeCompare(rightCreated);
1875
+ }
1876
+ function applyOrder(entries, order) {
1877
+ if (order === "alphabetical") {
1878
+ return sortTasks(entries.map((entry) => entry.task));
1879
+ }
1880
+ if (order === "created") {
1881
+ return [...entries].sort(compareCreated).map((entry) => entry.task);
1882
+ }
1883
+ return entries.map((entry) => entry.task);
1884
+ }
1885
+ var tmpFileCounter = 0;
1886
+ function hasErrorCode(error2, code) {
1887
+ return !!error2 && typeof error2 === "object" && "code" in error2 && error2.code === code;
1888
+ }
1889
+ function isRecord2(value) {
1890
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1891
+ }
1892
+ function sortStrings(values) {
1893
+ return [...values].sort((left, right) => left.localeCompare(right));
1894
+ }
1895
+ function sortTasks(tasks) {
1896
+ return [...tasks].sort((left, right) => left.qualifiedId.localeCompare(right.qualifiedId));
1897
+ }
1898
+ function validateTaskId(id) {
1899
+ if (id.length === 0 || id.startsWith(".") || id.includes("/") || id.includes("\\") || id.includes("..")) {
1900
+ throw new Error(`Invalid task id "${id}".`);
1901
+ }
1902
+ return id;
1903
+ }
1904
+ async function statIfExists(fs2, filePath) {
1905
+ try {
1906
+ return await fs2.stat(filePath);
1907
+ } catch (error2) {
1908
+ if (hasErrorCode(error2, "ENOENT")) {
1909
+ return void 0;
1910
+ }
1911
+ throw error2;
1912
+ }
1913
+ }
1914
+ async function writeAtomically(fs2, filePath, content) {
1915
+ const tempPath = `${filePath}.tmp-${process.pid}-${tmpFileCounter}`;
1916
+ tmpFileCounter += 1;
1917
+ await fs2.mkdir(path4.dirname(filePath), { recursive: true });
1918
+ try {
1919
+ await fs2.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
1920
+ await fs2.rename(tempPath, filePath);
1921
+ } catch (error2) {
1922
+ try {
1923
+ await fs2.unlink(tempPath);
1924
+ } catch (unlinkError) {
1925
+ if (!hasErrorCode(unlinkError, "ENOENT")) {
1926
+ throw unlinkError;
1927
+ }
1928
+ }
1929
+ throw error2;
1930
+ }
1931
+ }
1932
+
1933
+ // ../task-list/src/backends/gh-issues.ts
1934
+ var PROJECT_ORGANIZATION_QUERY = `query Project($owner: String!, $number: Int!) {
1935
+ organization(login: $owner) {
1936
+ projectV2(number: $number) {
1937
+ id
1938
+ title
1939
+ field(name: "Status") {
1940
+ ... on ProjectV2SingleSelectField {
1941
+ id
1942
+ options { id name }
1943
+ }
1944
+ }
1945
+ }
1946
+ }
1947
+ }`;
1948
+ var PROJECT_USER_QUERY = `query Project($owner: String!, $number: Int!) {
1949
+ user(login: $owner) {
1950
+ projectV2(number: $number) {
1951
+ id
1952
+ title
1953
+ field(name: "Status") {
1954
+ ... on ProjectV2SingleSelectField {
1955
+ id
1956
+ options { id name }
1957
+ }
1958
+ }
1959
+ }
1960
+ }
1961
+ }`;
1962
+ var PROJECT_ITEMS_QUERY = `query Items($projectId: ID!, $after: String) {
1963
+ node(id: $projectId) {
1964
+ ... on ProjectV2 {
1965
+ items(first: 100, after: $after) {
1966
+ nodes {
1967
+ id
1968
+ content {
1969
+ __typename
1970
+ ... on Issue {
1971
+ number
1972
+ title
1973
+ body
1974
+ url
1975
+ createdAt
1976
+ labels(first: 50) { nodes { name } }
1977
+ assignees(first: 20) { nodes { login } }
1978
+ milestone { title }
1979
+ }
1980
+ }
1981
+ fieldValueByName(name: "Status") {
1982
+ ... on ProjectV2ItemFieldSingleSelectValue {
1983
+ name
1984
+ }
1985
+ }
1986
+ }
1987
+ pageInfo { hasNextPage endCursor }
1988
+ }
1989
+ }
1990
+ }
1991
+ }`;
1992
+ var ISSUE_QUERY = `query Issue($owner: String!, $repo: String!, $number: Int!) {
1993
+ repository(owner: $owner, name: $repo) {
1994
+ issue(number: $number) {
1995
+ number
1996
+ title
1997
+ body
1998
+ url
1999
+ createdAt
2000
+ labels(first: 50) { nodes { name } }
2001
+ assignees(first: 20) { nodes { login } }
2002
+ milestone { title }
2003
+ projectItems(first: 10) {
2004
+ nodes {
2005
+ id
2006
+ project { id }
2007
+ fieldValueByName(name: "Status") {
2008
+ ... on ProjectV2ItemFieldSingleSelectValue {
2009
+ name
2010
+ }
2011
+ }
2012
+ }
2013
+ }
2014
+ }
2015
+ }
2016
+ }`;
2017
+ var REPOSITORY_QUERY = `query Repository($owner: String!, $repo: String!) {
2018
+ repository(owner: $owner, name: $repo) {
2019
+ id
2020
+ }
2021
+ }`;
2022
+ var ISSUE_ID_QUERY = `query IssueId($owner: String!, $repo: String!, $number: Int!) {
2023
+ repository(owner: $owner, name: $repo) {
2024
+ issue(number: $number) {
2025
+ id
2026
+ }
2027
+ }
2028
+ }`;
2029
+ var ISSUE_PROJECT_ITEM_QUERY = `query IssueProjectItem($owner: String!, $repo: String!, $number: Int!) {
2030
+ repository(owner: $owner, name: $repo) {
2031
+ issue(number: $number) {
2032
+ id
2033
+ projectItems(first: 10) {
2034
+ nodes {
2035
+ id
2036
+ project { id }
2037
+ }
2038
+ }
2039
+ }
2040
+ }
2041
+ }`;
2042
+ var CREATE_ISSUE_MUTATION = `mutation CreateIssue($input: CreateIssueInput!) {
2043
+ createIssue(input: $input) {
2044
+ issue {
2045
+ id
2046
+ number
2047
+ }
2048
+ }
2049
+ }`;
2050
+ var ADD_PROJECT_ITEM_MUTATION = `mutation AddProjectItem($input: AddProjectV2ItemByIdInput!) {
2051
+ addProjectV2ItemById(input: $input) {
2052
+ item {
2053
+ id
2054
+ }
2055
+ }
2056
+ }`;
2057
+ var UPDATE_STATUS_MUTATION = `mutation UpdateProjectItemStatus($input: UpdateProjectV2ItemFieldValueInput!) {
2058
+ updateProjectV2ItemFieldValue(input: $input) {
2059
+ projectV2Item {
2060
+ id
2061
+ }
2062
+ }
2063
+ }`;
2064
+ var UPDATE_ISSUE_MUTATION = `mutation UpdateIssue($input: UpdateIssueInput!) {
2065
+ updateIssue(input: $input) {
2066
+ issue {
2067
+ id
2068
+ }
2069
+ }
2070
+ }`;
2071
+ var UPDATE_PROJECT_ITEM_POSITION_MUTATION = `mutation UpdateProjectItemPosition($input: UpdateProjectV2ItemPositionInput!) {
2072
+ updateProjectV2ItemPosition(input: $input) {
2073
+ clientMutationId
2074
+ }
2075
+ }`;
2076
+ var DELETE_PROJECT_ITEM_MUTATION = `mutation DeleteProjectItem($input: DeleteProjectV2ItemInput!) {
2077
+ deleteProjectV2Item(input: $input) {
2078
+ deletedItemId
2079
+ }
2080
+ }`;
2081
+ async function ghIssuesBackend(deps) {
2082
+ const client = createGhClient({
2083
+ token: deps.token,
2084
+ endpoint: deps.endpoint,
2085
+ fetch: deps.fetch
2086
+ });
2087
+ const listName = `${deps.project.owner}/${deps.project.number}`;
2088
+ const variables = {
2089
+ owner: deps.project.owner,
2090
+ number: deps.project.number
2091
+ };
2092
+ const organizationResult = await client.graphql(
2093
+ PROJECT_ORGANIZATION_QUERY,
2094
+ variables
2095
+ );
2096
+ let project = organizationResult.organization?.projectV2 ?? null;
2097
+ if (project === null) {
2098
+ const userResult = await client.graphql(PROJECT_USER_QUERY, variables);
2099
+ project = userResult.user?.projectV2 ?? null;
2100
+ }
2101
+ if (project === null) {
2102
+ throw new Error(`Project ${listName} not found or inaccessible.`);
2103
+ }
2104
+ const field = project.field;
2105
+ if (!isStatusField(field)) {
2106
+ throw new Error(`Project ${listName} has no Status field; gh-issues requires one.`);
2107
+ }
2108
+ if (field.options.length === 0) {
2109
+ throw new Error(`Project ${listName} Status field has no options.`);
2110
+ }
2111
+ const session = createSession(project, field);
2112
+ const repoParts = parseRepo(deps.repo);
2113
+ const context = {
2114
+ client,
2115
+ repoOwner: repoParts.owner,
2116
+ repoName: repoParts.name,
2117
+ issueIds: /* @__PURE__ */ new Map()
2118
+ };
2119
+ function list(name) {
2120
+ assertSingleList(name, listName);
2121
+ return createTasksView(listName, session, context);
2122
+ }
2123
+ return {
2124
+ list,
2125
+ async lists() {
2126
+ return [listName];
2127
+ },
2128
+ async allTasks(filter) {
2129
+ return list(listName).all(filter);
2130
+ },
2131
+ async get(qualifiedId) {
2132
+ const id = parseQualifiedId(qualifiedId, listName);
2133
+ return list(listName).get(id);
2134
+ },
2135
+ async moveBetweenLists(_qualifiedId, _targetList) {
2136
+ throw singleListError(listName);
2137
+ }
2138
+ };
2139
+ }
2140
+ function createSession(project, field) {
2141
+ const statusOptions = new Map(field.options.map((option) => [option.name, option.id]));
2142
+ const states = field.options.map((option) => option.name);
2143
+ const events = Object.fromEntries(
2144
+ states.map((state) => [state, Object.freeze({ from: "*", to: state })])
2145
+ );
2146
+ const stateMachine = Object.freeze({
2147
+ states: Object.freeze([...states]),
2148
+ initial: states[0],
2149
+ events: Object.freeze(events)
2150
+ });
2151
+ return Object.freeze({
2152
+ projectId: project.id,
2153
+ statusFieldId: field.id,
2154
+ statusOptions,
2155
+ stateMachine
2156
+ });
2157
+ }
2158
+ function createTasksView(name, session, context) {
2159
+ return {
2160
+ name,
2161
+ stateMachine: session.stateMachine,
2162
+ async all(filter) {
2163
+ if (filter?.includeArchived === true) {
2164
+ return [];
2165
+ }
2166
+ const tasks = await fetchProjectTasks(name, session, context);
2167
+ const filteredTasks = filter?.state === void 0 ? tasks : tasks.filter((task) => task.state === filter.state);
2168
+ if (filter?.order === "alphabetical") {
2169
+ return sortTasks(filteredTasks);
2170
+ }
2171
+ if (filter?.order === "created") {
2172
+ return applyOrder(
2173
+ filteredTasks.map((task) => ({
2174
+ task,
2175
+ raw: {
2176
+ created: task.metadata.created
2177
+ }
2178
+ })),
2179
+ "created"
2180
+ );
2181
+ }
2182
+ return filteredTasks;
2183
+ },
2184
+ async get(id) {
2185
+ return fetchIssueTask(id, name, session, context);
2186
+ },
2187
+ /**
2188
+ * GitHub Issues assigns the issue number, so TaskCreate.id is intentionally ignored.
2189
+ */
2190
+ async create(input) {
2191
+ const repositoryId = await resolveRepositoryId(context);
2192
+ const created = await context.client.graphql(CREATE_ISSUE_MUTATION, {
2193
+ input: {
2194
+ repositoryId,
2195
+ title: input.name,
2196
+ body: input.description ?? ""
2197
+ }
2198
+ });
2199
+ const issue = created.createIssue?.issue;
2200
+ const issueId = issue?.id ?? null;
2201
+ const issueNumber = issue?.number ?? null;
2202
+ if (issueId === null || issueNumber === null) {
2203
+ throw new Error("GitHub createIssue response did not include issue id and number.");
2204
+ }
2205
+ context.issueIds.set(issueNumber, issueId);
2206
+ const added = await context.client.graphql(
2207
+ ADD_PROJECT_ITEM_MUTATION,
2208
+ {
2209
+ input: {
2210
+ projectId: session.projectId,
2211
+ contentId: issueId
2212
+ }
2213
+ }
2214
+ );
2215
+ const projectItemId = added.addProjectV2ItemById?.item?.id ?? null;
2216
+ if (projectItemId === null) {
2217
+ throw new Error("GitHub addProjectV2ItemById response did not include project item id.");
2218
+ }
2219
+ await updateProjectItemStatus(projectItemId, session.stateMachine.initial, session, context);
2220
+ return fetchIssueTask(String(issueNumber), name, session, context);
2221
+ },
2222
+ async update(id, patch) {
2223
+ const input = {};
2224
+ if (patch.name !== void 0) {
2225
+ input.title = patch.name;
2226
+ }
2227
+ if (patch.description !== void 0) {
2228
+ input.body = patch.description;
2229
+ }
2230
+ if (Object.keys(input).length > 0) {
2231
+ input.id = await resolveIssueId(id, name, context);
2232
+ await context.client.graphql(UPDATE_ISSUE_MUTATION, {
2233
+ input
2234
+ });
2235
+ }
2236
+ return fetchIssueTask(id, name, session, context);
2237
+ },
2238
+ async fire(id, event, _opts) {
2239
+ if (!session.statusOptions.has(event)) {
2240
+ throw new InvalidTransitionError({
2241
+ event,
2242
+ to: event,
2243
+ reason: `Unknown gh-issues Status state "${event}".`
2244
+ });
2245
+ }
2246
+ const projectItemId = await resolveProjectItemId(id, name, session, context);
2247
+ await updateProjectItemStatus(projectItemId, event, session, context);
2248
+ return fetchIssueTask(id, name, session, context);
2249
+ },
2250
+ async canFire(id, event) {
2251
+ return findEvent(session.stateMachine, id, event) !== void 0;
2252
+ },
2253
+ async events(id) {
2254
+ return eventsFromState(session.stateMachine, id);
2255
+ },
2256
+ async delete(id) {
2257
+ const projectItemId = await resolveProjectItemId(id, name, session, context);
2258
+ await context.client.graphql(DELETE_PROJECT_ITEM_MUTATION, {
2259
+ input: {
2260
+ projectId: session.projectId,
2261
+ itemId: projectItemId
2262
+ }
2263
+ });
2264
+ },
2265
+ async move(id, anchor) {
2266
+ const projectItemId = await resolveProjectItemId(id, name, session, context);
2267
+ const afterId = await resolveMoveAfterId(id, anchor, name, session, context);
2268
+ await updateProjectItemPosition(projectItemId, afterId, session, context);
2269
+ return fetchIssueTask(id, name, session, context);
2270
+ },
2271
+ async reorder(ids) {
2272
+ const currentTasks = await fetchProjectTasks(name, session, context);
2273
+ const currentIds = currentTasks.map((task) => task.id);
2274
+ const currentSet = new Set(currentIds);
2275
+ const inputSet = new Set(ids);
2276
+ const seenInputIds = /* @__PURE__ */ new Set();
2277
+ const missing = currentIds.filter((id) => !inputSet.has(id));
2278
+ const extra = ids.filter((id) => {
2279
+ if (!currentSet.has(id)) {
2280
+ return true;
2281
+ }
2282
+ if (seenInputIds.has(id)) {
2283
+ return true;
2284
+ }
2285
+ seenInputIds.add(id);
2286
+ return false;
2287
+ });
2288
+ if (missing.length > 0 || extra.length > 0) {
2289
+ throw new OrderMismatchError({ missing, extra });
2290
+ }
2291
+ const itemIdsByTaskId = new Map(
2292
+ currentTasks.map((task) => [task.id, projectItemIdFromTask(task)])
2293
+ );
2294
+ let afterId = null;
2295
+ for (const id of ids) {
2296
+ const projectItemId = itemIdsByTaskId.get(id);
2297
+ if (projectItemId === void 0) {
2298
+ throw new OrderMismatchError({ missing: [id], extra: [] });
2299
+ }
2300
+ await updateProjectItemPosition(projectItemId, afterId, session, context);
2301
+ afterId = projectItemId;
2302
+ }
2303
+ return fetchProjectTasks(name, session, context);
2304
+ }
2305
+ };
2306
+ }
2307
+ async function resolveRepositoryId(context) {
2308
+ if (context.repositoryId !== void 0) {
2309
+ return context.repositoryId;
2310
+ }
2311
+ const result = await context.client.graphql(REPOSITORY_QUERY, {
2312
+ owner: context.repoOwner,
2313
+ repo: context.repoName
2314
+ });
2315
+ const repositoryId = result.repository?.id ?? null;
2316
+ if (repositoryId === null) {
2317
+ throw new Error(
2318
+ `Repository ${context.repoOwner}/${context.repoName} not found or inaccessible.`
2319
+ );
2320
+ }
2321
+ context.repositoryId = repositoryId;
2322
+ return repositoryId;
2323
+ }
2324
+ async function resolveIssueId(id, listName, context) {
2325
+ const issueNumber = parseIssueNumber(id, listName);
2326
+ const cachedIssueId = context.issueIds.get(issueNumber);
2327
+ if (cachedIssueId !== void 0) {
2328
+ return cachedIssueId;
2329
+ }
2330
+ const result = await context.client.graphql(ISSUE_ID_QUERY, {
2331
+ owner: context.repoOwner,
2332
+ repo: context.repoName,
2333
+ number: issueNumber
2334
+ });
2335
+ const issueId = result.repository?.issue?.id ?? null;
2336
+ if (issueId === null) {
2337
+ throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
2338
+ }
2339
+ context.issueIds.set(issueNumber, issueId);
2340
+ return issueId;
2341
+ }
2342
+ async function resolveProjectItemId(id, listName, session, context) {
2343
+ const issueNumber = parseIssueNumber(id, listName);
2344
+ const result = await context.client.graphql(ISSUE_PROJECT_ITEM_QUERY, {
2345
+ owner: context.repoOwner,
2346
+ repo: context.repoName,
2347
+ number: issueNumber
2348
+ });
2349
+ const issue = result.repository?.issue ?? null;
2350
+ if (issue === null) {
2351
+ throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
2352
+ }
2353
+ if (issue.id !== void 0 && issue.id !== null) {
2354
+ context.issueIds.set(issueNumber, issue.id);
2355
+ }
2356
+ const projectItem = issue.projectItems?.nodes?.find((item) => item.project?.id === session.projectId) ?? null;
2357
+ if (projectItem === null) {
2358
+ throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
2359
+ }
2360
+ return projectItem.id;
2361
+ }
2362
+ async function updateProjectItemStatus(projectItemId, state, session, context) {
2363
+ const optionId = session.statusOptions.get(state);
2364
+ if (optionId === void 0) {
2365
+ throw new InvalidTransitionError({
2366
+ to: state,
2367
+ reason: `Unknown gh-issues Status state "${state}".`
2368
+ });
2369
+ }
2370
+ await context.client.graphql(UPDATE_STATUS_MUTATION, {
2371
+ input: {
2372
+ projectId: session.projectId,
2373
+ itemId: projectItemId,
2374
+ fieldId: session.statusFieldId,
2375
+ value: {
2376
+ singleSelectOptionId: optionId
2377
+ }
2378
+ }
2379
+ });
2380
+ }
2381
+ async function updateProjectItemPosition(projectItemId, afterId, session, context) {
2382
+ await context.client.graphql(UPDATE_PROJECT_ITEM_POSITION_MUTATION, {
2383
+ input: {
2384
+ projectId: session.projectId,
2385
+ itemId: projectItemId,
2386
+ afterId
2387
+ }
2388
+ });
2389
+ }
2390
+ async function resolveMoveAfterId(movingId, anchor, listName, session, context) {
2391
+ if ("position" in anchor) {
2392
+ if (anchor.position === "top") {
2393
+ return null;
2394
+ }
2395
+ const tasks2 = await fetchProjectTasks(listName, session, context);
2396
+ for (let index = tasks2.length - 1; index >= 0; index -= 1) {
2397
+ const task = tasks2[index];
2398
+ if (task.id !== movingId) {
2399
+ return projectItemIdFromTask(task);
2400
+ }
2401
+ }
2402
+ return null;
2403
+ }
2404
+ const anchorId = "before" in anchor ? anchor.before : anchor.after;
2405
+ let anchorProjectItemId;
2406
+ try {
2407
+ anchorProjectItemId = await resolveProjectItemId(anchorId, listName, session, context);
2408
+ } catch (error2) {
2409
+ if (error2 instanceof TaskNotFoundError) {
2410
+ throw new AnchorNotFoundError(anchorId);
2411
+ }
2412
+ throw error2;
2413
+ }
2414
+ if ("after" in anchor) {
2415
+ return anchorProjectItemId;
2416
+ }
2417
+ const tasks = await fetchProjectTasks(listName, session, context);
2418
+ const anchorIndex = tasks.findIndex((task) => task.id === anchorId);
2419
+ if (anchorIndex < 0) {
2420
+ throw new AnchorNotFoundError(anchorId);
2421
+ }
2422
+ for (let index = anchorIndex - 1; index >= 0; index -= 1) {
2423
+ const predecessor = tasks[index];
2424
+ if (predecessor.id !== movingId) {
2425
+ return projectItemIdFromTask(predecessor);
2426
+ }
2427
+ }
2428
+ return null;
2429
+ }
2430
+ async function fetchProjectTasks(listName, session, context) {
2431
+ const tasks = [];
2432
+ let after = null;
2433
+ do {
2434
+ const result = await context.client.graphql(
2435
+ PROJECT_ITEMS_QUERY,
2436
+ {
2437
+ projectId: session.projectId,
2438
+ after
2439
+ }
2440
+ );
2441
+ const items = result.node?.items;
2442
+ for (const item of items?.nodes ?? []) {
2443
+ const task = mapProjectItemToTask(item, listName, session);
2444
+ if (task !== null) {
2445
+ tasks.push(task);
2446
+ }
2447
+ }
2448
+ after = items?.pageInfo?.hasNextPage === true ? items.pageInfo.endCursor ?? null : null;
2449
+ } while (after !== null);
2450
+ return tasks;
2451
+ }
2452
+ async function fetchIssueTask(id, listName, session, context) {
2453
+ const issueNumber = parseIssueNumber(id, listName);
2454
+ const result = await context.client.graphql(ISSUE_QUERY, {
2455
+ owner: context.repoOwner,
2456
+ repo: context.repoName,
2457
+ number: issueNumber
2458
+ });
2459
+ const issue = result.repository?.issue ?? null;
2460
+ if (issue === null) {
2461
+ throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
2462
+ }
2463
+ const projectItem = issue.projectItems?.nodes?.find((item) => item.project?.id === session.projectId) ?? null;
2464
+ if (projectItem === null) {
2465
+ throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
2466
+ }
2467
+ return mapIssueToTask({
2468
+ issue,
2469
+ projectItemId: projectItem.id,
2470
+ statusName: projectItem.fieldValueByName?.name ?? null,
2471
+ listName,
2472
+ initialState: session.stateMachine.initial
2473
+ });
2474
+ }
2475
+ function parseIssueNumber(id, listName) {
2476
+ const issueNumber = Number(id);
2477
+ if (!Number.isInteger(issueNumber) || issueNumber < 1) {
2478
+ throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
2479
+ }
2480
+ return issueNumber;
2481
+ }
2482
+ function mapProjectItemToTask(item, listName, session) {
2483
+ const content = item.content;
2484
+ if (!isIssueNode(content)) {
2485
+ return null;
2486
+ }
2487
+ return mapIssueToTask({
2488
+ issue: content,
2489
+ projectItemId: item.id,
2490
+ statusName: item.fieldValueByName?.name ?? null,
2491
+ listName,
2492
+ initialState: session.stateMachine.initial
2493
+ });
2494
+ }
2495
+ function isIssueNode(value) {
2496
+ return isRecord3(value) && value.__typename === "Issue" && typeof value.number === "number" && typeof value.title === "string" && typeof value.url === "string" && typeof value.createdAt === "string";
2497
+ }
2498
+ function mapIssueToTask(options) {
2499
+ const id = String(options.issue.number);
2500
+ const labels = (options.issue.labels?.nodes ?? []).filter((node) => node !== null).map((node) => node.name);
2501
+ const assignees = (options.issue.assignees?.nodes ?? []).filter((node) => node !== null).map((node) => node.login);
2502
+ return {
2503
+ list: options.listName,
2504
+ id,
2505
+ qualifiedId: `${options.listName}/${id}`,
2506
+ name: options.issue.title,
2507
+ description: options.issue.body ?? "",
2508
+ state: options.statusName ?? options.initialState,
2509
+ metadata: {
2510
+ url: options.issue.url,
2511
+ labels,
2512
+ assignees,
2513
+ milestone: options.issue.milestone?.title ?? null,
2514
+ projectItemId: options.projectItemId,
2515
+ created: options.issue.createdAt
2516
+ }
2517
+ };
2518
+ }
2519
+ function projectItemIdFromTask(task) {
2520
+ const projectItemId = task.metadata.projectItemId;
2521
+ if (typeof projectItemId !== "string") {
2522
+ throw new Error(`Task "${task.qualifiedId}" is missing GitHub project item metadata.`);
2523
+ }
2524
+ return projectItemId;
2525
+ }
2526
+ function parseRepo(repo) {
2527
+ const parts = repo.split("/");
2528
+ if (parts.length !== 2 || parts[0] === "" || parts[1] === "") {
2529
+ throw new Error(`Invalid GitHub repository "${repo}". Expected "owner/name".`);
2530
+ }
2531
+ return {
2532
+ owner: parts[0],
2533
+ name: parts[1]
2534
+ };
2535
+ }
2536
+ function isRecord3(value) {
2537
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2538
+ }
2539
+ function isStatusOption(value) {
2540
+ return isRecord3(value) && typeof value.id === "string" && typeof value.name === "string";
2541
+ }
2542
+ function isStatusField(value) {
2543
+ return isRecord3(value) && typeof value.id === "string" && Array.isArray(value.options) && value.options.every(isStatusOption);
2544
+ }
2545
+ function assertSingleList(name, listName) {
2546
+ if (name !== listName) {
2547
+ throw singleListError(listName);
2548
+ }
2549
+ }
2550
+ function singleListError(listName) {
2551
+ return new Error(`gh-issues backend has a single list ${listName}`);
2552
+ }
2553
+ function parseQualifiedId(qualifiedId, listName) {
2554
+ const prefix = `${listName}/`;
2555
+ if (!qualifiedId.startsWith(prefix) || qualifiedId.length === prefix.length) {
2556
+ throw new Error(`Invalid qualified task id "${qualifiedId}".`);
2557
+ }
2558
+ return qualifiedId.slice(prefix.length);
2559
+ }
2560
+
2561
+ // ../task-list/src/backends/markdown-dir.ts
2562
+ import path5 from "node:path";
2563
+
2564
+ // ../file-lock/src/lock.ts
2565
+ import * as fsPromises from "node:fs/promises";
2566
+ import * as os from "node:os";
2567
+ var LockTimeoutError = class extends Error {
2568
+ constructor(message2) {
2569
+ super(message2);
2570
+ this.name = "LockTimeoutError";
2571
+ }
2572
+ };
2573
+ function createAbortError() {
2574
+ const error2 = new Error("The operation was aborted.");
2575
+ error2.name = "AbortError";
2576
+ return error2;
2577
+ }
2578
+ function throwIfAborted(signal) {
2579
+ if (signal?.aborted) {
2580
+ throw createAbortError();
2581
+ }
2582
+ }
2583
+ function sleep(ms, signal) {
2584
+ if (!signal) {
2585
+ return new Promise((resolve) => setTimeout(resolve, ms));
2586
+ }
2587
+ if (signal.aborted) {
2588
+ return Promise.reject(createAbortError());
2589
+ }
2590
+ return new Promise((resolve, reject) => {
2591
+ const timeoutId = setTimeout(() => {
2592
+ signal.removeEventListener("abort", onAbort);
2593
+ resolve();
2594
+ }, ms);
2595
+ const onAbort = () => {
2596
+ clearTimeout(timeoutId);
2597
+ signal.removeEventListener("abort", onAbort);
2598
+ reject(createAbortError());
2599
+ };
2600
+ signal.addEventListener("abort", onAbort, { once: true });
2601
+ });
2602
+ }
2603
+ function backoff(attempt, minTimeout, maxTimeout) {
2604
+ const delay = Math.min(maxTimeout, minTimeout * 2 ** attempt);
2605
+ return delay + Math.random() * delay * 0.1;
2606
+ }
2607
+ function hasErrorCode2(error2, code) {
2608
+ return !!error2 && typeof error2 === "object" && "code" in error2 && error2.code === code;
2609
+ }
2610
+ function hasAnyErrorCode(error2, codes) {
2611
+ return codes.some((code) => hasErrorCode2(error2, code));
2612
+ }
2613
+ function isPidRunning(pid) {
2614
+ try {
2615
+ process.kill(pid, 0);
2616
+ return true;
2617
+ } catch (error2) {
2618
+ return !hasErrorCode2(error2, "ESRCH");
2619
+ }
2620
+ }
2621
+ function createDefaultFs() {
2622
+ return {
2623
+ open: (path15, flags) => fsPromises.open(path15, flags),
2624
+ readFile: (path15, encoding) => fsPromises.readFile(path15, encoding),
2625
+ stat: fsPromises.stat,
2626
+ unlink: fsPromises.unlink
2627
+ };
2628
+ }
2629
+ async function removeLockFile(fs2, lockPath, signal) {
2630
+ for (let attempt = 0; attempt <= 4; attempt += 1) {
2631
+ throwIfAborted(signal);
2632
+ try {
2633
+ await fs2.unlink(lockPath);
2634
+ return;
2635
+ } catch (error2) {
2636
+ if (hasErrorCode2(error2, "ENOENT")) {
2637
+ return;
2638
+ }
2639
+ if (!hasAnyErrorCode(error2, ["EPERM", "EBUSY"]) || attempt === 4) {
2640
+ throw error2;
2641
+ }
2642
+ }
2643
+ await sleep(25 * 2 ** attempt, signal);
2644
+ }
2645
+ }
2646
+ function parseLockMetadata(content) {
2647
+ try {
2648
+ const parsed = JSON.parse(content);
2649
+ if (!parsed || typeof parsed !== "object" || !("host" in parsed) || !("pid" in parsed)) {
2650
+ return void 0;
2651
+ }
2652
+ const { host, pid } = parsed;
2653
+ if (typeof host === "string" && typeof pid === "number" && Number.isSafeInteger(pid) && pid > 0) {
2654
+ return {
2655
+ host,
2656
+ pid
2657
+ };
2658
+ }
2659
+ } catch (ignoredError) {
2660
+ void ignoredError;
2661
+ }
2662
+ return void 0;
2663
+ }
2664
+ async function readLockMetadata(fs2, lockPath) {
2665
+ if (!fs2.readFile) {
2666
+ return void 0;
2667
+ }
2668
+ try {
2669
+ return parseLockMetadata(await fs2.readFile(lockPath, "utf8"));
2670
+ } catch (error2) {
2671
+ if (hasErrorCode2(error2, "ENOENT")) {
2672
+ return null;
2673
+ }
2674
+ return void 0;
2675
+ }
2676
+ }
2677
+ async function shouldReclaimLock(options) {
2678
+ const metadata = await readLockMetadata(options.fs, options.lockPath);
2679
+ if (metadata === null) {
2680
+ return "missing";
2681
+ }
2682
+ if (metadata?.host === os.hostname()) {
2683
+ return !options.isPidRunning(metadata.pid);
2684
+ }
2685
+ return Date.now() - options.stat.mtimeMs > options.staleMs;
2686
+ }
2687
+ async function writeLockMetadata(handle) {
2688
+ try {
2689
+ await handle.writeFile(
2690
+ JSON.stringify({ pid: process.pid, host: os.hostname(), acquiredAt: (/* @__PURE__ */ new Date()).toISOString() }),
2691
+ { encoding: "utf8" }
2692
+ );
2693
+ } catch (ignoredError) {
2694
+ void ignoredError;
2695
+ }
2696
+ try {
2697
+ await handle.close();
2698
+ } catch (ignoredError) {
2699
+ void ignoredError;
2700
+ }
2701
+ }
2702
+ async function acquireFileLock(filePath, options = {}) {
2703
+ const fs2 = options.fs ?? createDefaultFs();
2704
+ const retries = options.retries ?? 20;
2705
+ const minTimeout = options.minTimeout ?? 25;
2706
+ const maxTimeout = options.maxTimeout ?? 250;
2707
+ const staleMs = options.staleMs ?? 1e3;
2708
+ const pidIsRunning = options.isPidRunning ?? isPidRunning;
2709
+ const lockPath = `${filePath}.lock`;
2710
+ let attempt = 0;
2711
+ while (attempt <= retries) {
2712
+ throwIfAborted(options.signal);
2713
+ try {
2714
+ const handle = await fs2.open(lockPath, "wx");
2715
+ await writeLockMetadata(handle);
2716
+ let released = false;
2717
+ return async () => {
2718
+ if (released) {
2719
+ return;
2720
+ }
2721
+ released = true;
2722
+ await removeLockFile(fs2, lockPath, options.signal);
2723
+ };
2724
+ } catch (error2) {
2725
+ if (!hasErrorCode2(error2, "EEXIST")) {
2726
+ throw error2;
2727
+ }
2728
+ }
2729
+ let stat3;
2730
+ try {
2731
+ stat3 = await fs2.stat(lockPath);
2732
+ } catch (statError) {
2733
+ if (hasErrorCode2(statError, "ENOENT")) {
2734
+ continue;
2735
+ }
2736
+ throw statError;
2737
+ }
2738
+ const reclaimLock = await shouldReclaimLock({
2739
+ fs: fs2,
2740
+ isPidRunning: pidIsRunning,
2741
+ lockPath,
2742
+ staleMs,
2743
+ stat: stat3
2744
+ });
2745
+ if (reclaimLock === "missing") {
2746
+ continue;
2747
+ }
2748
+ if (reclaimLock) {
2749
+ await removeLockFile(fs2, lockPath, options.signal);
2750
+ continue;
2751
+ }
2752
+ if (attempt >= retries) {
2753
+ break;
2754
+ }
2755
+ await sleep(backoff(attempt, minTimeout, maxTimeout), options.signal);
2756
+ attempt += 1;
2757
+ }
2758
+ throw new LockTimeoutError(`Failed to acquire lock on "${filePath}".`);
2759
+ }
2760
+
1405
2761
  // ../task-list/src/backends/markdown-dir.ts
1406
2762
  import { parseDocument, stringify } from "yaml";
1407
2763
 
@@ -1440,112 +2796,6 @@ var task_schema_default = {
1440
2796
  additionalProperties: true
1441
2797
  };
1442
2798
 
1443
- // ../task-list/src/state-machine.ts
1444
- function isRecord(value) {
1445
- return typeof value === "object" && value !== null && !Array.isArray(value);
1446
- }
1447
- function isStateList(value) {
1448
- return Array.isArray(value) && value.every((entry) => typeof entry === "string");
1449
- }
1450
- function canFireFromState(event, fromState) {
1451
- if (event.from === "*") {
1452
- return event.to !== fromState;
1453
- }
1454
- return event.from.includes(fromState);
1455
- }
1456
- function validateMachine(machine) {
1457
- if (!isRecord(machine)) {
1458
- throw new TypeError("State machine must be an object.");
1459
- }
1460
- if (!isStateList(machine.states)) {
1461
- throw new TypeError("State machine states must be a string array.");
1462
- }
1463
- const states = new Set(machine.states);
1464
- if (typeof machine.initial !== "string") {
1465
- throw new TypeError("State machine initial must be a string.");
1466
- }
1467
- if (!states.has(machine.initial)) {
1468
- throw new Error(`Initial state "${machine.initial}" is not declared.`);
1469
- }
1470
- if (!isRecord(machine.events)) {
1471
- throw new TypeError("State machine events must be an object.");
1472
- }
1473
- for (const [eventName, event] of Object.entries(machine.events)) {
1474
- if (!isRecord(event)) {
1475
- throw new TypeError(`Event "${eventName}" must be an object.`);
1476
- }
1477
- if (event.from !== "*" && !isStateList(event.from)) {
1478
- throw new TypeError(`Event "${eventName}" has an invalid "from" definition.`);
1479
- }
1480
- if (typeof event.to !== "string") {
1481
- throw new TypeError(`Event "${eventName}" target state must be a string.`);
1482
- }
1483
- if (!states.has(event.to)) {
1484
- throw new Error(`Event "${eventName}" references unknown target state "${event.to}".`);
1485
- }
1486
- if (event.from !== "*") {
1487
- for (const fromState of event.from) {
1488
- if (!states.has(fromState)) {
1489
- throw new Error(`Event "${eventName}" references unknown source state "${fromState}".`);
1490
- }
1491
- }
1492
- }
1493
- }
1494
- }
1495
- function eventsFromState(machine, fromState) {
1496
- const events = [];
1497
- for (const [eventName, event] of Object.entries(machine.events)) {
1498
- if (canFireFromState(event, fromState)) {
1499
- events.push(eventName);
1500
- }
1501
- }
1502
- return events;
1503
- }
1504
- function findEvent(machine, fromState, eventName) {
1505
- const event = machine.events[eventName];
1506
- if (event === void 0) {
1507
- return void 0;
1508
- }
1509
- return canFireFromState(event, fromState) ? event : void 0;
1510
- }
1511
-
1512
- // ../task-list/src/types.ts
1513
- var TaskNotFoundError = class extends Error {
1514
- constructor(message2 = "Task not found.") {
1515
- super(message2);
1516
- this.name = "TaskNotFoundError";
1517
- }
1518
- };
1519
- var TaskAlreadyExistsError = class extends Error {
1520
- constructor(message2 = "Task already exists.") {
1521
- super(message2);
1522
- this.name = "TaskAlreadyExistsError";
1523
- }
1524
- };
1525
- var InvalidTransitionError = class extends Error {
1526
- task;
1527
- event;
1528
- to;
1529
- reason;
1530
- constructor(messageOrOptions = "Invalid task transition.") {
1531
- const options = typeof messageOrOptions === "string" ? {
1532
- reason: messageOrOptions
1533
- } : messageOrOptions;
1534
- super(options.reason);
1535
- this.name = "InvalidTransitionError";
1536
- this.task = options.task;
1537
- this.event = options.event;
1538
- this.to = options.to;
1539
- this.reason = options.reason;
1540
- }
1541
- };
1542
- var MalformedTaskError = class extends Error {
1543
- constructor(message2 = "Malformed task.") {
1544
- super(message2);
1545
- this.name = "MalformedTaskError";
1546
- }
1547
- };
1548
-
1549
2799
  // ../task-list/src/state.ts
1550
2800
  var defaultStateMachine = {
1551
2801
  initial: "draft",
@@ -1581,64 +2831,17 @@ function resolveStateMachine(stateMachine) {
1581
2831
  return stateMachine ?? defaultStateMachine;
1582
2832
  }
1583
2833
 
1584
- // ../task-list/src/backends/utils.ts
1585
- import path from "node:path";
1586
- var tmpFileCounter = 0;
1587
- function hasErrorCode2(error2, code) {
1588
- return !!error2 && typeof error2 === "object" && "code" in error2 && error2.code === code;
1589
- }
1590
- function isRecord2(value) {
1591
- return typeof value === "object" && value !== null && !Array.isArray(value);
1592
- }
1593
- function sortStrings(values) {
1594
- return [...values].sort((left, right) => left.localeCompare(right));
1595
- }
1596
- function sortTasks(tasks) {
1597
- return [...tasks].sort((left, right) => left.qualifiedId.localeCompare(right.qualifiedId));
1598
- }
1599
- function validateTaskId(id) {
1600
- if (id.length === 0 || id.startsWith(".") || id.includes("/") || id.includes("\\") || id.includes("..")) {
1601
- throw new Error(`Invalid task id "${id}".`);
1602
- }
1603
- return id;
1604
- }
1605
- async function statIfExists(fs2, filePath) {
1606
- try {
1607
- return await fs2.stat(filePath);
1608
- } catch (error2) {
1609
- if (hasErrorCode2(error2, "ENOENT")) {
1610
- return void 0;
1611
- }
1612
- throw error2;
1613
- }
1614
- }
1615
- async function writeAtomically(fs2, filePath, content) {
1616
- const tempPath = `${filePath}.tmp-${process.pid}-${tmpFileCounter}`;
1617
- tmpFileCounter += 1;
1618
- await fs2.mkdir(path.dirname(filePath), { recursive: true });
1619
- try {
1620
- await fs2.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
1621
- await fs2.rename(tempPath, filePath);
1622
- } catch (error2) {
1623
- try {
1624
- await fs2.unlink(tempPath);
1625
- } catch (unlinkError) {
1626
- if (!hasErrorCode2(unlinkError, "ENOENT")) {
1627
- throw unlinkError;
1628
- }
1629
- }
1630
- throw error2;
1631
- }
1632
- }
1633
-
1634
2834
  // ../task-list/src/backends/markdown-dir.ts
1635
2835
  var ARCHIVE_DIRECTORY_NAME = "archive";
1636
2836
  var MARKDOWN_EXTENSION = ".md";
1637
2837
  var TASK_KIND = "task";
1638
2838
  var TASK_VERSION = 1;
1639
2839
  var TASK_SCHEMA_ID = task_schema_default.$id;
2840
+ var ORDER_LOCK_FILENAME = ".order.lock";
2841
+ var MIN_PREFIX_WIDTH = 2;
1640
2842
  var RESERVED_FRONTMATTER_KEYS = /* @__PURE__ */ new Set([
1641
2843
  "$schema",
2844
+ "created",
1642
2845
  "description",
1643
2846
  "kind",
1644
2847
  "name",
@@ -1651,7 +2854,7 @@ function validateListName(name) {
1651
2854
  }
1652
2855
  return name;
1653
2856
  }
1654
- function parseQualifiedId(qualifiedId) {
2857
+ function parseQualifiedId2(qualifiedId) {
1655
2858
  const separatorIndex = qualifiedId.indexOf("/");
1656
2859
  if (separatorIndex <= 0 || separatorIndex !== qualifiedId.lastIndexOf("/") || separatorIndex === qualifiedId.length - 1) {
1657
2860
  throw new Error(`Invalid qualified task id "${qualifiedId}".`);
@@ -1662,16 +2865,16 @@ function parseQualifiedId(qualifiedId) {
1662
2865
  };
1663
2866
  }
1664
2867
  function listPath(rootPath, list) {
1665
- return path2.join(rootPath, list);
2868
+ return path5.join(rootPath, list);
1666
2869
  }
1667
2870
  function archiveDirectoryPath(rootPath, list) {
1668
- return path2.join(listPath(rootPath, list), ARCHIVE_DIRECTORY_NAME);
2871
+ return path5.join(listPath(rootPath, list), ARCHIVE_DIRECTORY_NAME);
1669
2872
  }
1670
- function activeTaskPath(rootPath, list, id) {
1671
- return path2.join(listPath(rootPath, list), `${id}${MARKDOWN_EXTENSION}`);
2873
+ function activeTaskFilename(id, order, width) {
2874
+ return `${String(order).padStart(width, "0")}-${id}${MARKDOWN_EXTENSION}`;
1672
2875
  }
1673
2876
  function archivedTaskPath(rootPath, list, id) {
1674
- return path2.join(archiveDirectoryPath(rootPath, list), `${id}${MARKDOWN_EXTENSION}`);
2877
+ return path5.join(archiveDirectoryPath(rootPath, list), `${id}${MARKDOWN_EXTENSION}`);
1675
2878
  }
1676
2879
  function isMarkdownFile(entryName) {
1677
2880
  return entryName.endsWith(MARKDOWN_EXTENSION);
@@ -1682,6 +2885,27 @@ function isHiddenEntry(entryName) {
1682
2885
  function isLockFile(entryName) {
1683
2886
  return entryName.endsWith(".lock");
1684
2887
  }
2888
+ function isValidTaskIdShape(id) {
2889
+ return id.length > 0 && !id.startsWith(".") && !id.includes("/") && !id.includes("\\") && !id.includes("..");
2890
+ }
2891
+ function parseActiveFilename(entryName) {
2892
+ if (!isMarkdownFile(entryName)) return void 0;
2893
+ const stem = entryName.slice(0, -MARKDOWN_EXTENSION.length);
2894
+ const match = /^(\d+)-(.+)$/.exec(stem);
2895
+ if (match) {
2896
+ const id = match[2];
2897
+ if (isValidTaskIdShape(id)) {
2898
+ return { id, order: Number.parseInt(match[1], 10) };
2899
+ }
2900
+ }
2901
+ if (isValidTaskIdShape(stem)) {
2902
+ return { id: stem, order: null };
2903
+ }
2904
+ return void 0;
2905
+ }
2906
+ function padWidthForCount(count) {
2907
+ return Math.max(MIN_PREFIX_WIDTH, String(Math.max(count, 1)).length);
2908
+ }
1685
2909
  function malformedTask(filePath, field) {
1686
2910
  return new MalformedTaskError(`Malformed task "${filePath}": invalid "${field}".`);
1687
2911
  }
@@ -1775,7 +2999,7 @@ async function readDirectoryNames(fs2, directoryPath) {
1775
2999
  try {
1776
3000
  return sortStrings(await fs2.readdir(directoryPath));
1777
3001
  } catch (error2) {
1778
- if (hasErrorCode2(error2, "ENOENT")) {
3002
+ if (hasErrorCode(error2, "ENOENT")) {
1779
3003
  return [];
1780
3004
  }
1781
3005
  throw error2;
@@ -1799,22 +3023,31 @@ async function readTaskFile(fs2, list, id, filePath, validStates) {
1799
3023
  task: createTask(list, id, frontmatter, document.body)
1800
3024
  };
1801
3025
  }
3026
+ async function findActiveTaskFilename(fs2, listDirectoryPath, id) {
3027
+ const entries = await readDirectoryNames(fs2, listDirectoryPath);
3028
+ for (const entryName of entries) {
3029
+ if (isHiddenEntry(entryName) || isLockFile(entryName)) continue;
3030
+ const parsed = parseActiveFilename(entryName);
3031
+ if (parsed?.id === id) {
3032
+ return entryName;
3033
+ }
3034
+ }
3035
+ return void 0;
3036
+ }
1802
3037
  async function findTaskLocation(fs2, rootPath, list, id) {
1803
- const activePath = activeTaskPath(rootPath, list, id);
1804
- const activeStat = await statIfExists(fs2, activePath);
1805
- if (activeStat?.isFile()) {
1806
- return {
1807
- archived: false,
1808
- path: activePath
1809
- };
3038
+ const listDirectoryPath = listPath(rootPath, list);
3039
+ const activeName = await findActiveTaskFilename(fs2, listDirectoryPath, id);
3040
+ if (activeName) {
3041
+ const activePath = path5.join(listDirectoryPath, activeName);
3042
+ const activeStat = await statIfExists(fs2, activePath);
3043
+ if (activeStat?.isFile()) {
3044
+ return { archived: false, path: activePath };
3045
+ }
1810
3046
  }
1811
3047
  const archivedPath = archivedTaskPath(rootPath, list, id);
1812
3048
  const archivedStat = await statIfExists(fs2, archivedPath);
1813
3049
  if (archivedStat?.isFile()) {
1814
- return {
1815
- archived: true,
1816
- path: archivedPath
1817
- };
3050
+ return { archived: true, path: archivedPath };
1818
3051
  }
1819
3052
  return void 0;
1820
3053
  }
@@ -1843,6 +3076,7 @@ function createdFrontmatter(defaults, input, initialState) {
1843
3076
  frontmatter[key2] = value;
1844
3077
  }
1845
3078
  }
3079
+ frontmatter.created = (/* @__PURE__ */ new Date()).toISOString();
1846
3080
  return frontmatter;
1847
3081
  }
1848
3082
  function updatedFrontmatter(existingFrontmatter, task, patch) {
@@ -1887,35 +3121,95 @@ function assertCreateDoesNotSetState(input) {
1887
3121
  );
1888
3122
  }
1889
3123
  }
3124
+ function assertCreateHasId(input) {
3125
+ if (input.id === void 0) {
3126
+ throw new Error("id is required for markdown-dir backend");
3127
+ }
3128
+ }
1890
3129
  function assertUpdateDoesNotSetState(patch) {
1891
3130
  if (Object.prototype.hasOwnProperty.call(patch, "state")) {
1892
3131
  throw new Error('Tasks.update() does not accept "state"; use fire() to change task state.');
1893
3132
  }
1894
3133
  }
1895
- function createTasksView(deps, list) {
3134
+ function createTasksView2(deps, list) {
1896
3135
  const listDirectoryPath = listPath(deps.path, list);
1897
3136
  const stateMachine = resolveStateMachine(deps.stateMachine);
1898
3137
  const validStates = new Set(stateMachine.states);
1899
- async function listFiles(directoryPath) {
1900
- const entries = await readDirectoryNames(deps.fs, directoryPath);
1901
- const tasks = [];
3138
+ async function readActiveEntries() {
3139
+ const entries = await readDirectoryNames(deps.fs, listDirectoryPath);
3140
+ const result = [];
1902
3141
  for (const entryName of entries) {
1903
- if (isHiddenEntry(entryName) || isLockFile(entryName) || !isMarkdownFile(entryName)) {
1904
- continue;
1905
- }
1906
- const entryPath = path2.join(directoryPath, entryName);
3142
+ if (isHiddenEntry(entryName) || isLockFile(entryName)) continue;
3143
+ const parsed = parseActiveFilename(entryName);
3144
+ if (!parsed) continue;
3145
+ const entryPath = path5.join(listDirectoryPath, entryName);
1907
3146
  const entryStat = await statIfExists(deps.fs, entryPath);
1908
- if (!entryStat?.isFile()) {
1909
- continue;
1910
- }
3147
+ if (!entryStat?.isFile()) continue;
3148
+ result.push({ id: parsed.id, order: parsed.order, filename: entryName });
3149
+ }
3150
+ result.sort((left, right) => {
3151
+ const leftOrder = left.order ?? Number.POSITIVE_INFINITY;
3152
+ const rightOrder = right.order ?? Number.POSITIVE_INFINITY;
3153
+ if (leftOrder !== rightOrder) return leftOrder - rightOrder;
3154
+ return left.filename.localeCompare(right.filename);
3155
+ });
3156
+ return result;
3157
+ }
3158
+ async function readActiveTasks() {
3159
+ const entries = await readActiveEntries();
3160
+ const tasks = /* @__PURE__ */ new Map();
3161
+ for (const entry of entries) {
3162
+ const filePath = path5.join(listDirectoryPath, entry.filename);
3163
+ const file = await readTaskFile(deps.fs, list, entry.id, filePath, validStates);
3164
+ tasks.set(entry.id, { task: file.task, raw: file.frontmatter });
3165
+ }
3166
+ return { entries, tasks };
3167
+ }
3168
+ async function readArchivedTasks() {
3169
+ const archivePath = archiveDirectoryPath(deps.path, list);
3170
+ const entries = await readDirectoryNames(deps.fs, archivePath);
3171
+ const result = [];
3172
+ for (const entryName of entries) {
3173
+ if (isHiddenEntry(entryName) || isLockFile(entryName) || !isMarkdownFile(entryName)) continue;
3174
+ const entryPath = path5.join(archivePath, entryName);
3175
+ const entryStat = await statIfExists(deps.fs, entryPath);
3176
+ if (!entryStat?.isFile()) continue;
1911
3177
  const id = entryName.slice(0, -MARKDOWN_EXTENSION.length);
1912
- tasks.push((await readTaskFile(deps.fs, list, id, entryPath, validStates)).task);
3178
+ const file = await readTaskFile(deps.fs, list, id, entryPath, validStates);
3179
+ result.push({ task: file.task, raw: file.frontmatter });
3180
+ }
3181
+ return result.sort((left, right) => left.task.qualifiedId.localeCompare(right.task.qualifiedId));
3182
+ }
3183
+ async function rewriteListPrefixes(orderedIds) {
3184
+ const entries = await readActiveEntries();
3185
+ const byId = new Map(entries.map((entry) => [entry.id, entry]));
3186
+ const width = padWidthForCount(orderedIds.length);
3187
+ for (let index = 0; index < orderedIds.length; index += 1) {
3188
+ const id = orderedIds[index];
3189
+ const entry = byId.get(id);
3190
+ if (!entry) continue;
3191
+ const desiredFilename = activeTaskFilename(id, index + 1, width);
3192
+ if (entry.filename !== desiredFilename) {
3193
+ const fromPath = path5.join(listDirectoryPath, entry.filename);
3194
+ const stagingPath = path5.join(listDirectoryPath, `${desiredFilename}.staging-${process.pid}-${index}`);
3195
+ await deps.fs.rename(fromPath, stagingPath);
3196
+ entry.filename = path5.basename(stagingPath);
3197
+ }
3198
+ }
3199
+ const refreshed = await readDirectoryNames(deps.fs, listDirectoryPath);
3200
+ for (const entryName of refreshed) {
3201
+ const stagingMatch = /\.staging-\d+-\d+$/.exec(entryName);
3202
+ if (!stagingMatch) continue;
3203
+ const desiredName = entryName.slice(0, stagingMatch.index);
3204
+ await deps.fs.rename(
3205
+ path5.join(listDirectoryPath, entryName),
3206
+ path5.join(listDirectoryPath, desiredName)
3207
+ );
1913
3208
  }
1914
- return sortTasks(tasks);
1915
3209
  }
1916
- async function withTaskLock(id, action) {
1917
- validateTaskId(id);
1918
- const release = await acquireFileLock(activeTaskPath(deps.path, list, id), {
3210
+ async function withListLock(action) {
3211
+ await deps.fs.mkdir(listDirectoryPath, { recursive: true });
3212
+ const release = await acquireFileLock(path5.join(listDirectoryPath, ORDER_LOCK_FILENAME), {
1919
3213
  fs: deps.fs,
1920
3214
  staleMs: deps.lockStaleMs,
1921
3215
  retries: deps.lockRetries
@@ -1926,6 +3220,10 @@ function createTasksView(deps, list) {
1926
3220
  await release();
1927
3221
  }
1928
3222
  }
3223
+ async function withTaskLock(id, action) {
3224
+ validateTaskId(id);
3225
+ return withListLock(action);
3226
+ }
1929
3227
  async function getTaskFile(id) {
1930
3228
  validateTaskId(id);
1931
3229
  return readTaskAtLocation(deps.fs, deps.path, list, id, validStates);
@@ -1946,27 +3244,41 @@ function createTasksView(deps, list) {
1946
3244
  name: list,
1947
3245
  stateMachine,
1948
3246
  async all(filter) {
1949
- const activeTasks = await listFiles(listDirectoryPath);
1950
- const archivedTasks = filter?.includeArchived ? await listFiles(archiveDirectoryPath(deps.path, list)) : [];
1951
- const combinedTasks = [...activeTasks, ...archivedTasks];
1952
- if (filter?.state) {
1953
- return combinedTasks.filter((task) => task.state === filter.state);
1954
- }
1955
- return combinedTasks;
3247
+ const { entries: activeEntries, tasks: activeTasks } = await readActiveTasks();
3248
+ const archivedEntries = filter?.includeArchived ? await readArchivedTasks() : [];
3249
+ const orderedActive = activeEntries.map((entry) => activeTasks.get(entry.id)).filter((entry) => {
3250
+ if (filter?.state && entry.task.state !== filter.state) return false;
3251
+ return true;
3252
+ });
3253
+ const filteredArchived = archivedEntries.filter((entry) => {
3254
+ if (filter?.state && entry.task.state !== filter.state) return false;
3255
+ return true;
3256
+ });
3257
+ const orderedActiveTasks = applyOrder(orderedActive, filter?.order);
3258
+ return [...orderedActiveTasks, ...filteredArchived.map((entry) => entry.task)];
1956
3259
  },
1957
3260
  async get(id) {
1958
3261
  return (await getTaskFile(id)).task;
1959
3262
  },
1960
3263
  async create(input) {
1961
3264
  assertCreateDoesNotSetState(input);
3265
+ assertCreateHasId(input);
1962
3266
  validateTaskId(input.id);
1963
3267
  await deps.fs.mkdir(listDirectoryPath, { recursive: true });
1964
- return withTaskLock(input.id, async () => {
3268
+ return withListLock(async () => {
1965
3269
  const existing = await findTaskLocation(deps.fs, deps.path, list, input.id);
1966
3270
  if (existing) {
1967
3271
  throw new TaskAlreadyExistsError(`Task "${list}/${input.id}" already exists.`);
1968
3272
  }
1969
- const targetPath = activeTaskPath(deps.path, list, input.id);
3273
+ const activeEntries = await readActiveEntries();
3274
+ const maxOrder = activeEntries.reduce(
3275
+ (max, entry) => entry.order !== null && entry.order > max ? entry.order : max,
3276
+ 0
3277
+ );
3278
+ const nextOrder = maxOrder + 1;
3279
+ const width = padWidthForCount(activeEntries.length + 1);
3280
+ const filename = activeTaskFilename(input.id, nextOrder, width);
3281
+ const targetPath = path5.join(listDirectoryPath, filename);
1970
3282
  const frontmatter = createdFrontmatter(deps.defaults, input, stateMachine.initial);
1971
3283
  const description = input.description ?? "";
1972
3284
  await writeAtomically(deps.fs, targetPath, serializeTaskDocument(frontmatter, description));
@@ -2042,14 +3354,60 @@ function createTasksView(deps, list) {
2042
3354
  }
2043
3355
  await deps.fs.unlink(location.path);
2044
3356
  });
3357
+ },
3358
+ async move(id, anchor) {
3359
+ validateTaskId(id);
3360
+ return withListLock(async () => {
3361
+ const { entries, tasks } = await readActiveTasks();
3362
+ const fromIndex = entries.findIndex((entry) => entry.id === id);
3363
+ if (fromIndex < 0) {
3364
+ throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
3365
+ }
3366
+ const ordered = entries.map((entry) => entry.id);
3367
+ ordered.splice(fromIndex, 1);
3368
+ let insertIndex;
3369
+ if ("position" in anchor) {
3370
+ insertIndex = anchor.position === "top" ? 0 : ordered.length;
3371
+ } else {
3372
+ const anchorId = "before" in anchor ? anchor.before : anchor.after;
3373
+ const anchorIndex = ordered.indexOf(anchorId);
3374
+ if (anchorIndex < 0) {
3375
+ throw new AnchorNotFoundError(anchorId);
3376
+ }
3377
+ insertIndex = "before" in anchor ? anchorIndex : anchorIndex + 1;
3378
+ }
3379
+ ordered.splice(insertIndex, 0, id);
3380
+ await rewriteListPrefixes(ordered);
3381
+ return tasks.get(id).task;
3382
+ });
3383
+ },
3384
+ async reorder(ids) {
3385
+ for (const id of ids) {
3386
+ validateTaskId(id);
3387
+ }
3388
+ return withListLock(async () => {
3389
+ const { entries, tasks } = await readActiveTasks();
3390
+ const currentIds = entries.map((entry) => entry.id);
3391
+ const currentSet = new Set(currentIds);
3392
+ const inputSet = new Set(ids);
3393
+ const missing = currentIds.filter((id) => !inputSet.has(id));
3394
+ const extra = ids.filter((id) => !currentSet.has(id));
3395
+ if (missing.length > 0 || extra.length > 0) {
3396
+ throw new OrderMismatchError({ missing, extra });
3397
+ }
3398
+ await rewriteListPrefixes(ids);
3399
+ return ids.map((id) => tasks.get(id).task);
3400
+ });
2045
3401
  }
2046
3402
  };
2047
3403
  }
2048
3404
  async function markdownDirBackend(deps) {
2049
3405
  await ensureRootPath(deps);
3406
+ const stateMachine = resolveStateMachine(deps.stateMachine);
3407
+ const validStates = new Set(stateMachine.states);
2050
3408
  const list = (name) => {
2051
3409
  const listName = validateListName(name);
2052
- return createTasksView(deps, listName);
3410
+ return createTasksView2(deps, listName);
2053
3411
  };
2054
3412
  const lists = async () => {
2055
3413
  const entries = await readDirectoryNames(deps.fs, deps.path);
@@ -2058,7 +3416,7 @@ async function markdownDirBackend(deps) {
2058
3416
  if (entryName === ARCHIVE_DIRECTORY_NAME || isHiddenEntry(entryName) || isLockFile(entryName)) {
2059
3417
  continue;
2060
3418
  }
2061
- const entryPath = path2.join(deps.path, entryName);
3419
+ const entryPath = path5.join(deps.path, entryName);
2062
3420
  const entryStat = await statIfExists(deps.fs, entryPath);
2063
3421
  if (entryStat?.isDirectory()) {
2064
3422
  result.push(entryName);
@@ -2072,22 +3430,70 @@ async function markdownDirBackend(deps) {
2072
3430
  for (const taskListName of allLists) {
2073
3431
  tasks.push(...await list(taskListName).all(filter));
2074
3432
  }
2075
- return sortTasks(tasks);
3433
+ return tasks;
2076
3434
  };
2077
3435
  const get = async (qualifiedId) => {
2078
- const { list: listName, id } = parseQualifiedId(qualifiedId);
3436
+ const { list: listName, id } = parseQualifiedId2(qualifiedId);
2079
3437
  return list(listName).get(id);
2080
3438
  };
3439
+ const moveBetweenLists = async (qualifiedId, targetList) => {
3440
+ const { list: sourceListName, id } = parseQualifiedId2(qualifiedId);
3441
+ const targetListName = validateListName(targetList);
3442
+ if (sourceListName === targetListName) {
3443
+ const file2 = await readTaskAtLocation(deps.fs, deps.path, sourceListName, id, validStates);
3444
+ return file2.task;
3445
+ }
3446
+ const targetExisting = await findTaskLocation(deps.fs, deps.path, targetListName, id);
3447
+ if (targetExisting) {
3448
+ throw new TaskAlreadyExistsError(`Task "${targetListName}/${id}" already exists.`);
3449
+ }
3450
+ const sourceLocation = await findTaskLocation(deps.fs, deps.path, sourceListName, id);
3451
+ if (!sourceLocation) {
3452
+ throw new TaskNotFoundError(`Task "${sourceListName}/${id}" not found.`);
3453
+ }
3454
+ const targetListDir = listPath(deps.path, targetListName);
3455
+ await deps.fs.mkdir(targetListDir, { recursive: true });
3456
+ const targetEntries = await (async () => {
3457
+ const out = [];
3458
+ const names = await readDirectoryNames(deps.fs, targetListDir);
3459
+ for (const entryName of names) {
3460
+ if (isHiddenEntry(entryName) || isLockFile(entryName)) continue;
3461
+ const parsed = parseActiveFilename(entryName);
3462
+ if (!parsed) continue;
3463
+ out.push({ id: parsed.id, order: parsed.order, filename: entryName });
3464
+ }
3465
+ return out;
3466
+ })();
3467
+ if (sourceLocation.archived) {
3468
+ const archivedTargetDir = archiveDirectoryPath(deps.path, targetListName);
3469
+ await deps.fs.mkdir(archivedTargetDir, { recursive: true });
3470
+ const archivedTargetPath = archivedTaskPath(deps.path, targetListName, id);
3471
+ await deps.fs.rename(sourceLocation.path, archivedTargetPath);
3472
+ const file2 = await readTaskFile(deps.fs, targetListName, id, archivedTargetPath, validStates);
3473
+ return file2.task;
3474
+ }
3475
+ const maxOrder = targetEntries.reduce(
3476
+ (max, entry) => entry.order !== null && entry.order > max ? entry.order : max,
3477
+ 0
3478
+ );
3479
+ const width = padWidthForCount(targetEntries.length + 1);
3480
+ const targetFilename = activeTaskFilename(id, maxOrder + 1, width);
3481
+ const targetPath = path5.join(targetListDir, targetFilename);
3482
+ await deps.fs.rename(sourceLocation.path, targetPath);
3483
+ const file = await readTaskFile(deps.fs, targetListName, id, targetPath, validStates);
3484
+ return file.task;
3485
+ };
2081
3486
  return {
2082
3487
  list,
2083
3488
  lists,
2084
3489
  allTasks,
2085
- get
3490
+ get,
3491
+ moveBetweenLists
2086
3492
  };
2087
3493
  }
2088
3494
 
2089
3495
  // ../task-list/src/backends/yaml-file.ts
2090
- import { parseDocument as parseDocument2 } from "yaml";
3496
+ import { isMap, parseDocument as parseDocument2 } from "yaml";
2091
3497
 
2092
3498
  // ../task-list/src/schema/store.schema.json
2093
3499
  var store_schema_default = {
@@ -2130,7 +3536,15 @@ var STORE_VERSION = 1;
2130
3536
  var TASK_KIND2 = "task";
2131
3537
  var TASK_SCHEMA_ID2 = task_schema_default.$id;
2132
3538
  var TASK_VERSION2 = 1;
2133
- var RESERVED_TASK_KEYS = /* @__PURE__ */ new Set(["$schema", "description", "kind", "name", "state", "version"]);
3539
+ var RESERVED_TASK_KEYS = /* @__PURE__ */ new Set([
3540
+ "$schema",
3541
+ "created",
3542
+ "description",
3543
+ "kind",
3544
+ "name",
3545
+ "state",
3546
+ "version"
3547
+ ]);
2134
3548
  function malformedStore(filePath, field) {
2135
3549
  return new MalformedTaskError(`Malformed task store "${filePath}": invalid "${field}".`);
2136
3550
  }
@@ -2143,7 +3557,7 @@ function validateListName2(name) {
2143
3557
  }
2144
3558
  return name;
2145
3559
  }
2146
- function parseQualifiedId2(qualifiedId) {
3560
+ function parseQualifiedId3(qualifiedId) {
2147
3561
  const separatorIndex = qualifiedId.indexOf("/");
2148
3562
  if (separatorIndex <= 0 || separatorIndex !== qualifiedId.lastIndexOf("/") || separatorIndex === qualifiedId.length - 1) {
2149
3563
  throw new Error(`Invalid qualified task id "${qualifiedId}".`);
@@ -2201,6 +3615,7 @@ function createTaskRecord(defaults, input, initialState) {
2201
3615
  taskRecord[key2] = value;
2202
3616
  }
2203
3617
  }
3618
+ taskRecord.created = (/* @__PURE__ */ new Date()).toISOString();
2204
3619
  return taskRecord;
2205
3620
  }
2206
3621
  function assertCreateDoesNotSetState2(input) {
@@ -2210,6 +3625,11 @@ function assertCreateDoesNotSetState2(input) {
2210
3625
  );
2211
3626
  }
2212
3627
  }
3628
+ function assertCreateHasId2(input) {
3629
+ if (input.id === void 0) {
3630
+ throw new Error("id is required for yaml-file backend");
3631
+ }
3632
+ }
2213
3633
  function assertUpdateDoesNotSetState2(patch) {
2214
3634
  if (Object.prototype.hasOwnProperty.call(patch, "state")) {
2215
3635
  throw new Error('Tasks.update() does not accept "state"; use fire() to change task state.');
@@ -2356,7 +3776,49 @@ function getTaskOrThrow(store, list, id) {
2356
3776
  if (!taskRecord) {
2357
3777
  throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
2358
3778
  }
2359
- return taskRecord;
3779
+ return taskRecord;
3780
+ }
3781
+ function getListNode(document, list) {
3782
+ const lists = document.get("lists");
3783
+ if (!isMap(lists)) {
3784
+ return void 0;
3785
+ }
3786
+ const listNode = lists.get(list);
3787
+ if (!isMap(listNode)) {
3788
+ return void 0;
3789
+ }
3790
+ return listNode;
3791
+ }
3792
+ function pairKey(pair) {
3793
+ const key2 = pair.key;
3794
+ if (typeof key2 === "string") {
3795
+ return key2;
3796
+ }
3797
+ if (key2 && typeof key2 === "object" && "value" in key2 && typeof key2.value === "string") {
3798
+ return key2.value;
3799
+ }
3800
+ return void 0;
3801
+ }
3802
+ function findItemIndex(listNode, id) {
3803
+ return listNode.items.findIndex((pair) => pairKey(pair) === id);
3804
+ }
3805
+ function activeItemIds(listNode, validStates) {
3806
+ const ids = [];
3807
+ for (const pair of listNode.items) {
3808
+ const id = pairKey(pair);
3809
+ if (id === void 0) continue;
3810
+ const value = pair.value;
3811
+ let state;
3812
+ if (value && typeof value === "object" && "get" in value && typeof value.get === "function") {
3813
+ state = value.get("state");
3814
+ } else if (isRecord2(value)) {
3815
+ state = value.state;
3816
+ }
3817
+ if (typeof state === "string" && validStates.has(state) && state !== "archived") {
3818
+ ids.push(id);
3819
+ }
3820
+ }
3821
+ return ids;
2360
3822
  }
2361
3823
  async function ensureStorePath(deps) {
2362
3824
  if (!deps.create) {
@@ -2395,7 +3857,7 @@ async function withStoreLock(deps, action) {
2395
3857
  await release();
2396
3858
  }
2397
3859
  }
2398
- function createTasksView2(deps, list) {
3860
+ function createTasksView3(deps, list) {
2399
3861
  const stateMachine = resolveStateMachine(deps.stateMachine);
2400
3862
  const validStates = new Set(stateMachine.states);
2401
3863
  async function readTasks(filter) {
@@ -2404,8 +3866,11 @@ function createTasksView2(deps, list) {
2404
3866
  if (!listRecord) {
2405
3867
  return [];
2406
3868
  }
2407
- const tasks = Object.entries(listRecord).map(([id, taskRecord]) => createTask2(list, id, taskRecord));
2408
- return sortTasks(tasks.filter((task) => matchesFilter(task, filter)));
3869
+ const entries = Object.entries(listRecord).map(([id, taskRecord]) => ({
3870
+ task: createTask2(list, id, taskRecord),
3871
+ raw: taskRecord
3872
+ })).filter(({ task }) => matchesFilter(task, filter));
3873
+ return applyOrder(entries, filter?.order);
2409
3874
  }
2410
3875
  function assertFireableTaskEvent(task, eventName) {
2411
3876
  const event = findEvent(stateMachine, task.state, eventName);
@@ -2432,6 +3897,7 @@ function createTasksView2(deps, list) {
2432
3897
  },
2433
3898
  async create(input) {
2434
3899
  assertCreateDoesNotSetState2(input);
3900
+ assertCreateHasId2(input);
2435
3901
  validateTaskId(input.id);
2436
3902
  return withStoreLock(deps, async () => {
2437
3903
  const { document, store } = await readStore(deps.fs, deps.path, validStates);
@@ -2520,6 +3986,72 @@ function createTasksView2(deps, list) {
2520
3986
  document.deleteIn(["lists", list, id]);
2521
3987
  await writeAtomically(deps.fs, deps.path, serializeDocument(document));
2522
3988
  });
3989
+ },
3990
+ async move(id, anchor) {
3991
+ validateTaskId(id);
3992
+ return withStoreLock(deps, async () => {
3993
+ const { document, store } = await readStore(deps.fs, deps.path, validStates);
3994
+ const taskRecord = getTaskOrThrow(store, list, id);
3995
+ const listNode = getListNode(document, list);
3996
+ if (!listNode) {
3997
+ throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
3998
+ }
3999
+ const fromIndex = findItemIndex(listNode, id);
4000
+ if (fromIndex < 0) {
4001
+ throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
4002
+ }
4003
+ const [movedPair] = listNode.items.splice(fromIndex, 1);
4004
+ let insertIndex;
4005
+ if ("position" in anchor) {
4006
+ insertIndex = anchor.position === "top" ? 0 : listNode.items.length;
4007
+ } else {
4008
+ const anchorId = "before" in anchor ? anchor.before : anchor.after;
4009
+ const anchorIndex = findItemIndex(listNode, anchorId);
4010
+ if (anchorIndex < 0) {
4011
+ listNode.items.splice(fromIndex, 0, movedPair);
4012
+ throw new AnchorNotFoundError(anchorId);
4013
+ }
4014
+ insertIndex = "before" in anchor ? anchorIndex : anchorIndex + 1;
4015
+ }
4016
+ listNode.items.splice(insertIndex, 0, movedPair);
4017
+ await writeAtomically(deps.fs, deps.path, serializeDocument(document));
4018
+ return createTask2(list, id, taskRecord);
4019
+ });
4020
+ },
4021
+ async reorder(ids) {
4022
+ for (const id of ids) {
4023
+ validateTaskId(id);
4024
+ }
4025
+ return withStoreLock(deps, async () => {
4026
+ const { document, store } = await readStore(deps.fs, deps.path, validStates);
4027
+ const listNode = getListNode(document, list);
4028
+ if (!listNode) {
4029
+ throw new OrderMismatchError({ missing: [...ids], extra: [] });
4030
+ }
4031
+ const currentActive = activeItemIds(listNode, validStates);
4032
+ const currentSet = new Set(currentActive);
4033
+ const inputSet = new Set(ids);
4034
+ const missing = currentActive.filter((id) => !inputSet.has(id));
4035
+ const extra = ids.filter((id) => !currentSet.has(id));
4036
+ if (missing.length > 0 || extra.length > 0) {
4037
+ throw new OrderMismatchError({ missing, extra });
4038
+ }
4039
+ const archivedPairs = listNode.items.filter((pair) => {
4040
+ const id = pairKey(pair);
4041
+ return id !== void 0 && !currentSet.has(id);
4042
+ });
4043
+ const orderedActive = ids.map((id) => {
4044
+ const pair = listNode.items.find((p) => pairKey(p) === id);
4045
+ if (!pair) {
4046
+ throw new OrderMismatchError({ missing: [id], extra: [] });
4047
+ }
4048
+ return pair;
4049
+ });
4050
+ listNode.items.splice(0, listNode.items.length, ...orderedActive, ...archivedPairs);
4051
+ await writeAtomically(deps.fs, deps.path, serializeDocument(document));
4052
+ const tasks = ids.map((id) => createTask2(list, id, getTaskOrThrow(store, list, id)));
4053
+ return tasks;
4054
+ });
2523
4055
  }
2524
4056
  };
2525
4057
  }
@@ -2529,7 +4061,7 @@ async function yamlFileBackend(deps) {
2529
4061
  const validStates = new Set(stateMachine.states);
2530
4062
  const list = (name) => {
2531
4063
  const listName = validateListName2(name);
2532
- return createTasksView2({ ...deps, stateMachine }, listName);
4064
+ return createTasksView3({ ...deps, stateMachine }, listName);
2533
4065
  };
2534
4066
  const lists = async () => {
2535
4067
  const { store } = await readStore(deps.fs, deps.path, validStates);
@@ -2537,26 +4069,47 @@ async function yamlFileBackend(deps) {
2537
4069
  };
2538
4070
  const allTasks = async (filter) => {
2539
4071
  const { store } = await readStore(deps.fs, deps.path, validStates);
2540
- const tasks = [];
2541
- for (const [listName, listRecord] of Object.entries(getListsRecord(store))) {
2542
- for (const [id, taskRecord] of Object.entries(listRecord)) {
2543
- const task = createTask2(listName, id, taskRecord);
2544
- if (matchesFilter(task, filter)) {
2545
- tasks.push(task);
2546
- }
2547
- }
4072
+ const result = [];
4073
+ const listNames = sortStrings(Object.keys(getListsRecord(store)));
4074
+ for (const listName of listNames) {
4075
+ const listRecord = getListsRecord(store)[listName];
4076
+ if (!isRecord2(listRecord)) continue;
4077
+ const entries = Object.entries(listRecord).map(([id, taskRecord]) => ({
4078
+ task: createTask2(listName, id, taskRecord),
4079
+ raw: taskRecord
4080
+ })).filter(({ task }) => matchesFilter(task, filter));
4081
+ result.push(...applyOrder(entries, filter?.order));
2548
4082
  }
2549
- return sortTasks(tasks);
4083
+ return result;
2550
4084
  };
2551
4085
  const get = async (qualifiedId) => {
2552
- const { list: listName, id } = parseQualifiedId2(qualifiedId);
4086
+ const { list: listName, id } = parseQualifiedId3(qualifiedId);
2553
4087
  return list(listName).get(id);
2554
4088
  };
4089
+ const moveBetweenLists = async (qualifiedId, targetList) => {
4090
+ const { list: sourceListName, id } = parseQualifiedId3(qualifiedId);
4091
+ const targetListName = validateListName2(targetList);
4092
+ return withStoreLock(deps, async () => {
4093
+ const { document, store } = await readStore(deps.fs, deps.path, validStates);
4094
+ const taskRecord = getTaskOrThrow(store, sourceListName, id);
4095
+ if (sourceListName === targetListName) {
4096
+ return createTask2(targetListName, id, taskRecord);
4097
+ }
4098
+ if (getTaskRecord(store, targetListName, id)) {
4099
+ throw new TaskAlreadyExistsError(`Task "${targetListName}/${id}" already exists.`);
4100
+ }
4101
+ document.deleteIn(["lists", sourceListName, id]);
4102
+ document.setIn(["lists", targetListName, id], taskRecord);
4103
+ await writeAtomically(deps.fs, deps.path, serializeDocument(document));
4104
+ return createTask2(targetListName, id, taskRecord);
4105
+ });
4106
+ };
2555
4107
  return {
2556
4108
  list,
2557
4109
  lists,
2558
4110
  allTasks,
2559
- get
4111
+ get,
4112
+ moveBetweenLists
2560
4113
  };
2561
4114
  }
2562
4115
 
@@ -2571,10 +4124,18 @@ function createDefaultFs2() {
2571
4124
  return fsPromises2;
2572
4125
  }
2573
4126
  async function openTaskList(options) {
2574
- const factory = backendFactories[options.type];
2575
- if (factory === void 0) {
2576
- throw new Error(`Unknown task list backend type "${options.type}".`);
4127
+ switch (options.type) {
4128
+ case "markdown-dir":
4129
+ case "yaml-file":
4130
+ return openFileBackend(options);
4131
+ case "gh-issues":
4132
+ return openGhIssuesBackend(options);
4133
+ default:
4134
+ throw new Error(`Unknown task list backend type "${options.type}".`);
2577
4135
  }
4136
+ }
4137
+ async function openFileBackend(options) {
4138
+ const factory = backendFactories[options.type];
2578
4139
  const stateMachine = resolveStateMachine(options.stateMachine);
2579
4140
  validateMachine(stateMachine);
2580
4141
  const deps = {
@@ -2590,9 +4151,23 @@ async function openTaskList(options) {
2590
4151
  };
2591
4152
  return factory(deps);
2592
4153
  }
4154
+ async function openGhIssuesBackend(options) {
4155
+ const token = await resolveAuth({ explicitToken: options.auth?.token });
4156
+ const endpoint = resolveEndpoint();
4157
+ return ghIssuesBackend({
4158
+ repo: options.repo,
4159
+ project: options.project,
4160
+ defaults: {
4161
+ metadata: { ...options.defaults?.metadata ?? {} }
4162
+ },
4163
+ token,
4164
+ endpoint,
4165
+ fetch: options.fetch
4166
+ });
4167
+ }
2593
4168
 
2594
4169
  // ../toolcraft/src/human-in-loop/approval-tasks.ts
2595
- import { randomBytes } from "node:crypto";
4170
+ import { randomBytes as randomBytes3 } from "node:crypto";
2596
4171
 
2597
4172
  // ../toolcraft/src/human-in-loop/state-machine.ts
2598
4173
  var approvalStateMachine = {
@@ -2675,7 +4250,7 @@ function isListValidated(runtimeOptions, listName) {
2675
4250
  return validatedListsByRuntime.get(runtimeOptions)?.has(listName) ?? false;
2676
4251
  }
2677
4252
  function createApprovalRecord(payload, enqueuedAt) {
2678
- const approvalId = `${enqueuedAt.slice(0, 19).replaceAll(":", "-")}-${randomBytes(3).toString("hex")}`;
4253
+ const approvalId = `${enqueuedAt.slice(0, 19).replaceAll(":", "-")}-${randomBytes3(3).toString("hex")}`;
2679
4254
  return {
2680
4255
  approvalId,
2681
4256
  name: `${payload.commandPath} (${enqueuedAt})`,
@@ -2758,7 +4333,7 @@ function areEqualStrings(left, right) {
2758
4333
  }
2759
4334
 
2760
4335
  // ../toolcraft/src/human-in-loop/runner.ts
2761
- import { access, readFile, writeFile } from "node:fs/promises";
4336
+ import { access, readFile as readFile3, writeFile } from "node:fs/promises";
2762
4337
 
2763
4338
  // ../toolcraft/src/human-in-loop/default-provider.ts
2764
4339
  import process2 from "node:process";
@@ -2866,13 +4441,13 @@ function defaultProviderForPlatform() {
2866
4441
  }
2867
4442
 
2868
4443
  // ../toolcraft/src/human-in-loop/spawn.ts
2869
- import { spawn } from "node:child_process";
4444
+ import { spawn as spawn2 } from "node:child_process";
2870
4445
  function spawnApprovalRunner(approvalId, runtimeOptions, spawnFn) {
2871
4446
  const { execPath, entryArgs } = runtimeOptions.binPath ?? {
2872
4447
  execPath: process.execPath,
2873
4448
  entryArgs: [process.argv[1]]
2874
4449
  };
2875
- const fn = spawnFn ?? spawn;
4450
+ const fn = spawnFn ?? spawn2;
2876
4451
  const child = fn(execPath, [...entryArgs, "approvals", "run", approvalId], {
2877
4452
  detached: true,
2878
4453
  stdio: "ignore",
@@ -3057,13 +4632,13 @@ function createHandlerContext(command, params17) {
3057
4632
  }
3058
4633
  function createFs() {
3059
4634
  return {
3060
- readFile: async (path12, encoding = "utf8") => readFile(path12, { encoding }),
3061
- writeFile: async (path12, contents) => {
3062
- await writeFile(path12, contents);
4635
+ readFile: async (path15, encoding = "utf8") => readFile3(path15, { encoding }),
4636
+ writeFile: async (path15, contents) => {
4637
+ await writeFile(path15, contents);
3063
4638
  },
3064
- exists: async (path12) => {
4639
+ exists: async (path15) => {
3065
4640
  try {
3066
- await access(path12);
4641
+ await access(path15);
3067
4642
  return true;
3068
4643
  } catch {
3069
4644
  return false;
@@ -3315,23 +4890,23 @@ function escapeMarkdownCell(value) {
3315
4890
  }
3316
4891
 
3317
4892
  // ../toolcraft/src/mcp-proxy.ts
3318
- import { existsSync } from "node:fs";
3319
- import { mkdir, readFile as readFile2, rename, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
3320
- import path5 from "node:path";
4893
+ import { existsSync as existsSync2 } from "node:fs";
4894
+ import { mkdir, readFile as readFile4, rename, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
4895
+ import path8 from "node:path";
3321
4896
 
3322
4897
  // ../tiny-mcp-client/src/internal.ts
3323
- import { spawn as spawn3 } from "node:child_process";
4898
+ import { spawn as spawn4 } from "node:child_process";
3324
4899
  import { PassThrough as PassThrough2 } from "node:stream";
3325
4900
 
3326
- // ../mcp-oauth/src/client/auth-store-session-store.ts
4901
+ // ../mcp-oauth/dist/client/auth-store-session-store.js
3327
4902
  import crypto from "node:crypto";
3328
- import path4 from "node:path";
4903
+ import path7 from "node:path";
3329
4904
 
3330
4905
  // ../auth-store/src/encrypted-file-store.ts
3331
- import { createCipheriv, createDecipheriv, randomBytes as randomBytes2, scrypt } from "node:crypto";
4906
+ import { createCipheriv, createDecipheriv, randomBytes as randomBytes4, scrypt } from "node:crypto";
3332
4907
  import { promises as fs } from "node:fs";
3333
4908
  import { homedir, hostname as hostname2, userInfo } from "node:os";
3334
- import path3 from "node:path";
4909
+ import path6 from "node:path";
3335
4910
  var derivedKeyCache = /* @__PURE__ */ new Map();
3336
4911
  var ENCRYPTION_ALGORITHM = "aes-256-gcm";
3337
4912
  var ENCRYPTION_VERSION = 1;
@@ -3349,13 +4924,13 @@ var EncryptedFileStore = class {
3349
4924
  constructor(input) {
3350
4925
  this.fs = input.fs ?? fs;
3351
4926
  this.salt = input.salt;
3352
- this.filePath = input.filePath ?? path3.join(
4927
+ this.filePath = input.filePath ?? path6.join(
3353
4928
  (input.getHomeDirectory ?? homedir)(),
3354
4929
  input.defaultDirectory ?? ".auth-store",
3355
4930
  input.defaultFileName ?? "credentials.enc"
3356
4931
  );
3357
4932
  this.getMachineIdentity = input.getMachineIdentity ?? defaultMachineIdentity;
3358
- this.getRandomBytes = input.getRandomBytes ?? randomBytes2;
4933
+ this.getRandomBytes = input.getRandomBytes ?? randomBytes4;
3359
4934
  }
3360
4935
  async get() {
3361
4936
  let rawDocument;
@@ -3402,7 +4977,7 @@ var EncryptedFileStore = class {
3402
4977
  authTag: authTag.toString("base64"),
3403
4978
  ciphertext: ciphertext.toString("base64")
3404
4979
  };
3405
- await this.fs.mkdir(path3.dirname(this.filePath), { recursive: true });
4980
+ await this.fs.mkdir(path6.dirname(this.filePath), { recursive: true });
3406
4981
  await this.fs.writeFile(this.filePath, JSON.stringify(document), {
3407
4982
  encoding: "utf8"
3408
4983
  });
@@ -3453,7 +5028,7 @@ async function deriveEncryptionKey(getMachineIdentity, salt) {
3453
5028
  function parseEncryptedDocument(raw) {
3454
5029
  try {
3455
5030
  const parsed = JSON.parse(raw);
3456
- if (!isRecord3(parsed)) {
5031
+ if (!isRecord4(parsed)) {
3457
5032
  return null;
3458
5033
  }
3459
5034
  if (parsed.version !== ENCRYPTION_VERSION) {
@@ -3472,7 +5047,7 @@ function parseEncryptedDocument(raw) {
3472
5047
  return null;
3473
5048
  }
3474
5049
  }
3475
- function isRecord3(value) {
5050
+ function isRecord4(value) {
3476
5051
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
3477
5052
  }
3478
5053
  function isNotFoundError(error2) {
@@ -3482,7 +5057,7 @@ function isNotFoundError(error2) {
3482
5057
  }
3483
5058
 
3484
5059
  // ../auth-store/src/keychain-store.ts
3485
- import { spawn as spawn2 } from "node:child_process";
5060
+ import { spawn as spawn3 } from "node:child_process";
3486
5061
  var SECURITY_CLI = "security";
3487
5062
  var KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE = 44;
3488
5063
  var KeychainStore = class {
@@ -3546,7 +5121,7 @@ var KeychainStore = class {
3546
5121
  };
3547
5122
  function runSecurityCommand(command, args) {
3548
5123
  return new Promise((resolve) => {
3549
- const child = spawn2(command, args, {
5124
+ const child = spawn3(command, args, {
3550
5125
  stdio: ["ignore", "pipe", "pipe"]
3551
5126
  });
3552
5127
  let stdout = "";
@@ -3640,7 +5215,7 @@ function resolveBackend(input) {
3640
5215
  return "file";
3641
5216
  }
3642
5217
 
3643
- // ../mcp-oauth/src/resource-indicator.ts
5218
+ // ../mcp-oauth/dist/resource-indicator.js
3644
5219
  function canonicalizeResourceIndicator(value) {
3645
5220
  let url;
3646
5221
  try {
@@ -3652,7 +5227,7 @@ function canonicalizeResourceIndicator(value) {
3652
5227
  return url.toString();
3653
5228
  }
3654
5229
 
3655
- // ../mcp-oauth/src/client/auth-store-session-store.ts
5230
+ // ../mcp-oauth/dist/client/auth-store-session-store.js
3656
5231
  var DEFAULT_FILE_SALT = "poe-code:mcp-oauth:v1";
3657
5232
  var DEFAULT_FILE_DIRECTORY = ".poe-code/mcp-oauth";
3658
5233
  var DEFAULT_KEYCHAIN_SERVICE = "poe-code-mcp-oauth";
@@ -3709,7 +5284,7 @@ function createAuthStoreClientStore(options) {
3709
5284
  }
3710
5285
  function createNamedSecretStore(key2, options, defaults) {
3711
5286
  const hash = crypto.createHash("sha256").update(key2).digest("hex");
3712
- const parsedFilePath = options.fileStore?.filePath === void 0 ? null : path4.parse(options.fileStore.filePath);
5287
+ const parsedFilePath = options.fileStore?.filePath === void 0 ? null : path7.parse(options.fileStore.filePath);
3713
5288
  const fileStore = {
3714
5289
  ...options.fileStore,
3715
5290
  salt: options.fileStore?.salt ?? defaults.salt,
@@ -3724,37 +5299,29 @@ function createNamedSecretStore(key2, options, defaults) {
3724
5299
  return createSecretStore({ ...options, fileStore, keychainStore }).store;
3725
5300
  }
3726
5301
  function createResourceSecretStore(resource, options) {
3727
- return createNamedSecretStore(
3728
- canonicalizeResourceIndicator(resource),
3729
- options,
3730
- {
3731
- salt: DEFAULT_FILE_SALT,
3732
- directory: DEFAULT_FILE_DIRECTORY,
3733
- service: DEFAULT_KEYCHAIN_SERVICE,
3734
- accountPrefix: "provider"
3735
- }
3736
- );
5302
+ return createNamedSecretStore(canonicalizeResourceIndicator(resource), options, {
5303
+ salt: DEFAULT_FILE_SALT,
5304
+ directory: DEFAULT_FILE_DIRECTORY,
5305
+ service: DEFAULT_KEYCHAIN_SERVICE,
5306
+ accountPrefix: "provider"
5307
+ });
3737
5308
  }
3738
5309
  function createIssuerSecretStore(issuer, options) {
3739
- return createNamedSecretStore(
3740
- issuer,
3741
- options,
3742
- {
3743
- salt: DEFAULT_CLIENT_FILE_SALT,
3744
- directory: DEFAULT_CLIENT_FILE_DIRECTORY,
3745
- service: DEFAULT_CLIENT_KEYCHAIN_SERVICE,
3746
- accountPrefix: "issuer"
3747
- }
3748
- );
5310
+ return createNamedSecretStore(issuer, options, {
5311
+ salt: DEFAULT_CLIENT_FILE_SALT,
5312
+ directory: DEFAULT_CLIENT_FILE_DIRECTORY,
5313
+ service: DEFAULT_CLIENT_KEYCHAIN_SERVICE,
5314
+ accountPrefix: "issuer"
5315
+ });
3749
5316
  }
3750
5317
 
3751
- // ../mcp-oauth/src/client/default-oauth-client-provider.ts
5318
+ // ../mcp-oauth/dist/client/default-oauth-client-provider.js
3752
5319
  import { URL as URL2 } from "node:url";
3753
5320
 
3754
- // ../mcp-oauth/src/client/loopback-authorization.ts
5321
+ // ../mcp-oauth/dist/client/loopback-authorization.js
3755
5322
  import http from "node:http";
3756
5323
 
3757
- // ../mcp-oauth/src/client/authorization-state.ts
5324
+ // ../mcp-oauth/dist/client/authorization-state.js
3758
5325
  import crypto2 from "node:crypto";
3759
5326
  function createAuthorizationState(input) {
3760
5327
  const payload = {
@@ -3784,7 +5351,7 @@ function parseAuthorizationState(value) {
3784
5351
  }
3785
5352
  }
3786
5353
 
3787
- // ../mcp-oauth/src/client/loopback-authorization.ts
5354
+ // ../mcp-oauth/dist/client/loopback-authorization.js
3788
5355
  async function createLoopbackAuthorizationSession(options = {}) {
3789
5356
  const callbackPath = options.callbackPath ?? "/callback";
3790
5357
  const server = options.createServer ? options.createServer() : http.createServer();
@@ -3857,10 +5424,7 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
3857
5424
  return;
3858
5425
  }
3859
5426
  try {
3860
- const code = validateAuthorizationCallbackParameters(
3861
- callbackParameters,
3862
- expectedAuthorization
3863
- );
5427
+ const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
3864
5428
  settle(() => resolve(code));
3865
5429
  } catch (error2) {
3866
5430
  settle(() => reject(error2 instanceof Error ? error2 : new Error(String(error2))));
@@ -3926,8 +5490,8 @@ function validateAuthorizationCallbackParameters(callback, expected) {
3926
5490
  }
3927
5491
  return callback.code;
3928
5492
  }
3929
- function escapeHtml(text4) {
3930
- return text4.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
5493
+ function escapeHtml(text5) {
5494
+ return text5.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
3931
5495
  }
3932
5496
  function buildSuccessPage(landingPage) {
3933
5497
  const title = landingPage?.title ?? "Connected";
@@ -3943,7 +5507,7 @@ function buildSuccessPage(landingPage) {
3943
5507
  ].join("");
3944
5508
  }
3945
5509
 
3946
- // ../mcp-oauth/src/client/pkce.ts
5510
+ // ../mcp-oauth/dist/client/pkce.js
3947
5511
  import crypto3 from "node:crypto";
3948
5512
  function generateCodeVerifier() {
3949
5513
  return crypto3.randomBytes(32).toString("base64url");
@@ -3952,7 +5516,7 @@ function generateCodeChallenge(verifier) {
3952
5516
  return crypto3.createHash("sha256").update(verifier).digest("base64url");
3953
5517
  }
3954
5518
 
3955
- // ../mcp-oauth/src/client/token-endpoint.ts
5519
+ // ../mcp-oauth/dist/client/token-endpoint.js
3956
5520
  var OAuthError = class extends Error {
3957
5521
  error;
3958
5522
  errorDescription;
@@ -4082,7 +5646,7 @@ function normalizeBearerTokenType(value) {
4082
5646
  return value.toLowerCase() === "bearer" ? "Bearer" : null;
4083
5647
  }
4084
5648
 
4085
- // ../mcp-oauth/src/client/default-oauth-client-provider.ts
5649
+ // ../mcp-oauth/dist/client/default-oauth-client-provider.js
4086
5650
  function createOAuthClientProvider(options) {
4087
5651
  if (isProviderOptions(options)) {
4088
5652
  return options.provider;
@@ -4116,16 +5680,10 @@ function createDefaultOAuthClientProvider(options) {
4116
5680
  const resource = canonicalizeResourceIndicator(input.discovery.resource);
4117
5681
  assertRequestMatchesResource(requestUrl, resource);
4118
5682
  const forceRefresh = hasCachedAccessToken(await loadSession(resource)) && input.challenge?.params.error === "invalid_token";
4119
- const session = await ensureAuthorizedSession(
4120
- resource,
4121
- {
4122
- ...input.discovery,
4123
- resource
4124
- },
4125
- input.fetch,
4126
- true,
4127
- forceRefresh
4128
- );
5683
+ const session = await ensureAuthorizedSession(resource, {
5684
+ ...input.discovery,
5685
+ resource
5686
+ }, input.fetch, true, forceRefresh);
4129
5687
  if (session?.tokens?.accessToken === void 0) {
4130
5688
  return { action: "fail" };
4131
5689
  }
@@ -4190,11 +5748,7 @@ function createDefaultOAuthClientProvider(options) {
4190
5748
  await saveSession(resource, clearedSession);
4191
5749
  return clearedSession;
4192
5750
  }
4193
- if (shouldReRegisterStoredDynamicClient(
4194
- error2,
4195
- await loadRegisteredClient(discovery.authorizationServer),
4196
- false
4197
- )) {
5751
+ if (shouldReRegisterStoredDynamicClient(error2, await loadRegisteredClient(discovery.authorizationServer), false)) {
4198
5752
  await clearRegisteredClient(discovery.authorizationServer);
4199
5753
  await clearSession(resource);
4200
5754
  return null;
@@ -4353,10 +5907,7 @@ function createDefaultOAuthClientProvider(options) {
4353
5907
  };
4354
5908
  }
4355
5909
  }
4356
- const registrationBody = buildClientRegistrationBody(
4357
- getClientMetadata(options.client),
4358
- redirectUri
4359
- );
5910
+ const registrationBody = buildClientRegistrationBody(getClientMetadata(options.client), redirectUri);
4360
5911
  const response = await fetch2(registrationEndpoint, {
4361
5912
  method: "POST",
4362
5913
  headers: {
@@ -4480,9 +6031,7 @@ function buildAuthorizationUrl(input) {
4480
6031
  }
4481
6032
  function assertS256PkceSupport(metadata) {
4482
6033
  if (!metadata.code_challenge_methods_supported.includes("S256")) {
4483
- throw new Error(
4484
- "Authorization server metadata must advertise code_challenge_methods_supported including S256"
4485
- );
6034
+ throw new Error("Authorization server metadata must advertise code_challenge_methods_supported including S256");
4486
6035
  }
4487
6036
  }
4488
6037
  function normalizeHostname(hostname3) {
@@ -4520,9 +6069,7 @@ function assertNoAccessTokenInUrl(value, label) {
4520
6069
  }
4521
6070
  function assertRequestMatchesResource(requestUrl, resource) {
4522
6071
  if (requestUrl !== resource) {
4523
- throw new Error(
4524
- `OAuth request URL ${requestUrl} does not match discovered resource ${resource}`
4525
- );
6072
+ throw new Error(`OAuth request URL ${requestUrl} does not match discovered resource ${resource}`);
4526
6073
  }
4527
6074
  }
4528
6075
  function buildClientRegistrationBody(metadata, redirectUri) {
@@ -4566,13 +6113,8 @@ function shouldReRegisterStoredDynamicClient(error2, client, alreadyAttempted) {
4566
6113
  return true;
4567
6114
  }
4568
6115
 
4569
- // ../mcp-oauth/src/server/jwks-token-verifier.ts
4570
- import {
4571
- decodeProtectedHeader,
4572
- errors,
4573
- importJWK,
4574
- jwtVerify
4575
- } from "jose";
6116
+ // ../mcp-oauth/dist/server/jwks-token-verifier.js
6117
+ import { decodeProtectedHeader, errors, importJWK, jwtVerify } from "jose";
4576
6118
 
4577
6119
  // ../tiny-mcp-client/src/oauth-discovery.ts
4578
6120
  function defaultOAuthMetadataFetch(input, init) {
@@ -5336,7 +6878,7 @@ var ERROR_INVALID_REQUEST = -32600;
5336
6878
  var ERROR_METHOD_NOT_FOUND = -32601;
5337
6879
  var ERROR_INTERNAL = -32603;
5338
6880
  function defaultStdioSpawn(command, args, options) {
5339
- return spawn3(command, args, options);
6881
+ return spawn4(command, args, options);
5340
6882
  }
5341
6883
  function defaultHttpTransportFetch(input, init) {
5342
6884
  return fetch(input, init);
@@ -6647,9 +8189,9 @@ function mergeJsonSchemas(base, overlay) {
6647
8189
  ...mergedRequired === void 0 ? {} : { required: mergedRequired }
6648
8190
  };
6649
8191
  }
6650
- function hasSelfReferencingRef(schema, root, path12 = "#", activePaths = /* @__PURE__ */ new Set()) {
8192
+ function hasSelfReferencingRef(schema, root, path15 = "#", activePaths = /* @__PURE__ */ new Set()) {
6651
8193
  const nextActivePaths = new Set(activePaths);
6652
- nextActivePaths.add(path12);
8194
+ nextActivePaths.add(path15);
6653
8195
  const localRefPath = getLocalRefPath(schema.$ref);
6654
8196
  if (localRefPath !== void 0) {
6655
8197
  if (nextActivePaths.has(localRefPath)) {
@@ -6660,13 +8202,13 @@ function hasSelfReferencingRef(schema, root, path12 = "#", activePaths = /* @__P
6660
8202
  return true;
6661
8203
  }
6662
8204
  }
6663
- if (schema.items !== void 0 && hasSelfReferencingRef(schema.items, root, `${path12}/items`, nextActivePaths)) {
8205
+ if (schema.items !== void 0 && hasSelfReferencingRef(schema.items, root, `${path15}/items`, nextActivePaths)) {
6664
8206
  return true;
6665
8207
  }
6666
8208
  if (typeof schema.additionalProperties === "object" && schema.additionalProperties !== null && hasSelfReferencingRef(
6667
8209
  schema.additionalProperties,
6668
8210
  root,
6669
- `${path12}/additionalProperties`,
8211
+ `${path15}/additionalProperties`,
6670
8212
  nextActivePaths
6671
8213
  )) {
6672
8214
  return true;
@@ -6675,7 +8217,7 @@ function hasSelfReferencingRef(schema, root, path12 = "#", activePaths = /* @__P
6675
8217
  if (hasSelfReferencingRef(
6676
8218
  childSchema,
6677
8219
  root,
6678
- `${path12}/properties/${escapeJsonPointerSegment(key2)}`,
8220
+ `${path15}/properties/${escapeJsonPointerSegment(key2)}`,
6679
8221
  nextActivePaths
6680
8222
  )) {
6681
8223
  return true;
@@ -6685,19 +8227,19 @@ function hasSelfReferencingRef(schema, root, path12 = "#", activePaths = /* @__P
6685
8227
  if (hasSelfReferencingRef(
6686
8228
  childSchema,
6687
8229
  root,
6688
- `${path12}/$defs/${escapeJsonPointerSegment(key2)}`,
8230
+ `${path15}/$defs/${escapeJsonPointerSegment(key2)}`,
6689
8231
  nextActivePaths
6690
8232
  )) {
6691
8233
  return true;
6692
8234
  }
6693
8235
  }
6694
8236
  for (const [index, childSchema] of (schema.oneOf ?? []).entries()) {
6695
- if (hasSelfReferencingRef(childSchema, root, `${path12}/oneOf/${index}`, nextActivePaths)) {
8237
+ if (hasSelfReferencingRef(childSchema, root, `${path15}/oneOf/${index}`, nextActivePaths)) {
6696
8238
  return true;
6697
8239
  }
6698
8240
  }
6699
8241
  for (const [index, childSchema] of (schema.anyOf ?? []).entries()) {
6700
- if (hasSelfReferencingRef(childSchema, root, `${path12}/anyOf/${index}`, nextActivePaths)) {
8242
+ if (hasSelfReferencingRef(childSchema, root, `${path15}/anyOf/${index}`, nextActivePaths)) {
6701
8243
  return true;
6702
8244
  }
6703
8245
  }
@@ -6713,14 +8255,14 @@ function getLocalRefPath(ref) {
6713
8255
  return ref.startsWith("#/") ? ref : void 0;
6714
8256
  }
6715
8257
  function resolveLocalRef(root, ref) {
6716
- const path12 = getLocalRefPath(ref);
6717
- if (path12 === void 0) {
8258
+ const path15 = getLocalRefPath(ref);
8259
+ if (path15 === void 0) {
6718
8260
  return void 0;
6719
8261
  }
6720
- if (path12 === "#") {
8262
+ if (path15 === "#") {
6721
8263
  return root;
6722
8264
  }
6723
- const segments = path12.slice(2).split("/").map(unescapeJsonPointerSegment);
8265
+ const segments = path15.slice(2).split("/").map(unescapeJsonPointerSegment);
6724
8266
  let current = root;
6725
8267
  for (const segment of segments) {
6726
8268
  if (Array.isArray(current)) {
@@ -6958,7 +8500,7 @@ async function ensureConnected(connection) {
6958
8500
  }
6959
8501
  async function readCache(cachePath) {
6960
8502
  try {
6961
- const raw = await readFile2(cachePath, "utf8");
8503
+ const raw = await readFile4(cachePath, "utf8");
6962
8504
  const parsed = JSON.parse(raw);
6963
8505
  if (parsed === null || typeof parsed !== "object" || !Array.isArray(parsed.tools) || parsed.upstream === void 0 || typeof parsed.upstream.name !== "string" || typeof parsed.upstream.version !== "string") {
6964
8506
  return void 0;
@@ -6979,7 +8521,7 @@ async function readCache(cachePath) {
6979
8521
  }
6980
8522
  }
6981
8523
  async function writeCache(cachePath, cache) {
6982
- const directory = path5.dirname(cachePath);
8524
+ const directory = path8.dirname(cachePath);
6983
8525
  const tempPath = `${cachePath}.tmp`;
6984
8526
  await mkdir(directory, { recursive: true });
6985
8527
  await writeFile2(tempPath, `${JSON.stringify(cache, null, 2)}
@@ -7065,7 +8607,7 @@ function isRefreshRequested(name, refresh) {
7065
8607
  }
7066
8608
  return refresh?.has(name) === true;
7067
8609
  }
7068
- async function resolveSingleProxy(group) {
8610
+ async function resolveSingleProxy(group, options) {
7069
8611
  const internal = getInternalGroupConfig2(group);
7070
8612
  const config = internal.mcp;
7071
8613
  if (config === void 0) {
@@ -7073,7 +8615,7 @@ async function resolveSingleProxy(group) {
7073
8615
  }
7074
8616
  const name = group.name;
7075
8617
  try {
7076
- const cachePath = resolveCachePath(name);
8618
+ const cachePath = resolveCachePath(name, options.projectRoot);
7077
8619
  const refresh = parseRefreshEnv(process.env.TOOLCRAFT_MCP_REFRESH);
7078
8620
  let cache;
7079
8621
  if (isRefreshRequested(name, refresh)) {
@@ -7122,14 +8664,14 @@ function collectProxyGroups(root) {
7122
8664
  }
7123
8665
  function resolveCachePath(name, projectRoot) {
7124
8666
  if (projectRoot !== void 0) {
7125
- return path5.join(projectRoot, ".toolcraft", "mcp", `${name}.json`);
8667
+ return path8.join(projectRoot, ".toolcraft", "mcp", `${name}.json`);
7126
8668
  }
7127
8669
  let current = process.cwd();
7128
8670
  while (true) {
7129
- if (existsSync(path5.join(current, "package.json"))) {
7130
- return path5.join(current, ".toolcraft", "mcp", `${name}.json`);
8671
+ if (existsSync2(path8.join(current, "package.json"))) {
8672
+ return path8.join(current, ".toolcraft", "mcp", `${name}.json`);
7131
8673
  }
7132
- const parent = path5.dirname(current);
8674
+ const parent = path8.dirname(current);
7133
8675
  if (parent === current) {
7134
8676
  throw new Error(
7135
8677
  `Could not find package.json above "${process.cwd()}" while resolving MCP cache path.`
@@ -7167,9 +8709,9 @@ async function dialUpstream(name, config) {
7167
8709
  await client.connect(transport);
7168
8710
  return client;
7169
8711
  }
7170
- async function resolveMcpProxies(root) {
8712
+ async function resolveMcpProxies(root, options = {}) {
7171
8713
  const groups = collectProxyGroups(root);
7172
- await Promise.all(groups.map((group) => resolveSingleProxy(group)));
8714
+ await Promise.all(groups.map((group) => resolveSingleProxy(group, options)));
7173
8715
  }
7174
8716
 
7175
8717
  // ../toolcraft/src/number-schema.ts
@@ -7181,9 +8723,49 @@ function getExpectedNumberDescription(schema) {
7181
8723
  }
7182
8724
 
7183
8725
  // ../toolcraft/src/renderer.ts
8726
+ import YAML from "yaml";
7184
8727
  function isObject(value) {
7185
8728
  return value !== null && typeof value === "object" && !Array.isArray(value);
7186
8729
  }
8730
+ function isMcpCallToolResult(value) {
8731
+ if (!isObject(value)) {
8732
+ return false;
8733
+ }
8734
+ const hasContent = Array.isArray(value.content);
8735
+ const hasStructured = value.structuredContent !== void 0;
8736
+ if (!hasContent && !hasStructured) {
8737
+ return false;
8738
+ }
8739
+ return Object.keys(value).every(
8740
+ (key2) => key2 === "content" || key2 === "structuredContent" || key2 === "isError" || key2 === "_meta"
8741
+ );
8742
+ }
8743
+ function isMcpTextContent(value) {
8744
+ return isObject(value) && value.type === "text" && typeof value.text === "string";
8745
+ }
8746
+ function extractMcpPayload(envelope) {
8747
+ const structuredContent = envelope.structuredContent;
8748
+ if (isObject(structuredContent) && "result" in structuredContent) {
8749
+ return structuredContent.result;
8750
+ }
8751
+ if (structuredContent !== void 0) {
8752
+ return structuredContent;
8753
+ }
8754
+ if (Array.isArray(envelope.content)) {
8755
+ const text5 = envelope.content.filter(isMcpTextContent).map((block) => block.text).join("\n");
8756
+ return text5.length > 0 ? text5 : void 0;
8757
+ }
8758
+ return void 0;
8759
+ }
8760
+ function unwrapMcpEnvelope(result) {
8761
+ if (!isMcpCallToolResult(result)) {
8762
+ return { result, mcpError: false };
8763
+ }
8764
+ return {
8765
+ result: extractMcpPayload(result),
8766
+ mcpError: result.isError === true
8767
+ };
8768
+ }
7187
8769
  function isArrayOfObjects(value) {
7188
8770
  return Array.isArray(value) && value.every((entry) => isObject(entry));
7189
8771
  }
@@ -7207,30 +8789,6 @@ function stringifyJson(value, spaces) {
7207
8789
  return String(value);
7208
8790
  }
7209
8791
  }
7210
- function renderObjectTable(result, primitives) {
7211
- const rows = Object.entries(result).map(([key2, value]) => ({
7212
- key: key2,
7213
- value: stringifyValue2(value)
7214
- }));
7215
- return primitives.renderTable({
7216
- theme: primitives.getTheme(),
7217
- columns: [
7218
- {
7219
- name: "key",
7220
- title: "Key",
7221
- alignment: "left",
7222
- maxLen: Math.max("Key".length, ...rows.map((row) => row.key.length))
7223
- },
7224
- {
7225
- name: "value",
7226
- title: "Value",
7227
- alignment: "left",
7228
- maxLen: Math.max("Value".length, ...rows.map((row) => row.value.length))
7229
- }
7230
- ],
7231
- rows
7232
- });
7233
- }
7234
8792
  function renderObjectMarkdown(result) {
7235
8793
  return Object.entries(result).map(([key2, value]) => `- ${key2}: ${stringifyValue2(value)}`).join("\n");
7236
8794
  }
@@ -7243,29 +8801,6 @@ function getColumnNames(rows) {
7243
8801
  }
7244
8802
  return [...names];
7245
8803
  }
7246
- function renderArrayTable(result, primitives) {
7247
- if (result.length === 0) {
7248
- return "[]";
7249
- }
7250
- const columnNames = getColumnNames(result);
7251
- return primitives.renderTable({
7252
- theme: primitives.getTheme(),
7253
- columns: columnNames.map((name) => ({
7254
- name,
7255
- title: name,
7256
- alignment: "left",
7257
- maxLen: Math.max(
7258
- name.length,
7259
- ...result.map((row) => name in row ? stringifyValue2(row[name]).length : 0)
7260
- )
7261
- })),
7262
- rows: result.map(
7263
- (row) => Object.fromEntries(
7264
- columnNames.map((name) => [name, name in row ? stringifyValue2(row[name]) : ""])
7265
- )
7266
- )
7267
- });
7268
- }
7269
8804
  function renderArrayMarkdown(result) {
7270
8805
  if (result.length === 0) {
7271
8806
  return "[]";
@@ -7278,7 +8813,7 @@ function renderArrayMarkdown(result) {
7278
8813
  );
7279
8814
  return [header, separator, ...rows].join("\n");
7280
8815
  }
7281
- function autoRender(result, output, primitives) {
8816
+ function autoRender(result, output, _primitives) {
7282
8817
  if (result === null || result === void 0) {
7283
8818
  if (output === "json") {
7284
8819
  return stringifyJson({ ok: true }, 2);
@@ -7291,14 +8826,16 @@ function autoRender(result, output, primitives) {
7291
8826
  }
7292
8827
  return result;
7293
8828
  }
8829
+ if (output === "rich" && Array.isArray(result) && result.every((value) => typeof value === "string")) {
8830
+ return result.join("\n");
8831
+ }
7294
8832
  if (isObject(result)) {
7295
- if (output === "rich") {
7296
- return renderObjectTable(result, primitives);
7297
- }
7298
8833
  if (output === "md") {
7299
8834
  return renderObjectMarkdown(result);
7300
8835
  }
7301
- return stringifyJson(result, 2);
8836
+ if (output === "json") {
8837
+ return stringifyJson(result, 2);
8838
+ }
7302
8839
  }
7303
8840
  if (isArrayOfObjects(result)) {
7304
8841
  if (output === "md") {
@@ -7307,20 +8844,36 @@ function autoRender(result, output, primitives) {
7307
8844
  if (output === "json") {
7308
8845
  return stringifyJson(result, 2);
7309
8846
  }
7310
- return renderArrayTable(result, primitives);
8847
+ }
8848
+ if (output === "rich") {
8849
+ return YAML.stringify(result);
7311
8850
  }
7312
8851
  return stringifyJson(result, 2);
7313
8852
  }
7314
- function renderResult(command, result, output, primitives, write2 = (chunk) => {
8853
+ function renderResult(command, result, output, primitives, write2 = (chunk, stream = "stdout") => {
8854
+ if (stream === "stderr") {
8855
+ process.stderr.write(chunk);
8856
+ return;
8857
+ }
7315
8858
  process.stdout.write(chunk);
7316
8859
  }) {
8860
+ const unwrapped = unwrapMcpEnvelope(result);
8861
+ result = unwrapped.result;
8862
+ if (unwrapped.mcpError) {
8863
+ const payload2 = autoRender(result, output, primitives);
8864
+ if (payload2.length > 0) {
8865
+ write2(`${payload2}
8866
+ `, "stderr");
8867
+ }
8868
+ return { mcpError: true };
8869
+ }
7317
8870
  if (output === "json" && command.render?.json) {
7318
8871
  const payload2 = command.render.json(result, primitives);
7319
8872
  if (payload2 !== void 0) {
7320
8873
  write2(`${stringifyJson(payload2, 2)}
7321
8874
  `);
7322
8875
  }
7323
- return;
8876
+ return { mcpError: false };
7324
8877
  }
7325
8878
  if (output === "md" && command.render?.markdown) {
7326
8879
  const payload2 = command.render.markdown(result, primitives);
@@ -7328,17 +8881,18 @@ function renderResult(command, result, output, primitives, write2 = (chunk) => {
7328
8881
  write2(`${payload2}
7329
8882
  `);
7330
8883
  }
7331
- return;
8884
+ return { mcpError: false };
7332
8885
  }
7333
8886
  if (output === "rich" && command.render?.rich) {
7334
8887
  command.render.rich(result, primitives);
7335
- return;
8888
+ return { mcpError: false };
7336
8889
  }
7337
8890
  const payload = autoRender(result, output, primitives);
7338
8891
  if (payload.length > 0) {
7339
8892
  write2(`${payload}
7340
8893
  `);
7341
8894
  }
8895
+ return { mcpError: false };
7342
8896
  }
7343
8897
 
7344
8898
  // ../toolcraft/src/cli.ts
@@ -7349,7 +8903,7 @@ function inferProgramName(argv) {
7349
8903
  if (typeof entrypoint !== "string" || entrypoint.length === 0) {
7350
8904
  return "toolcraft";
7351
8905
  }
7352
- const parsed = path6.parse(entrypoint);
8906
+ const parsed = path9.parse(entrypoint);
7353
8907
  return parsed.name.length > 0 ? parsed.name : "toolcraft";
7354
8908
  }
7355
8909
  function normalizeRoots(roots, argv) {
@@ -7371,7 +8925,7 @@ function unwrapOptional(schema) {
7371
8925
  }
7372
8926
  return schema;
7373
8927
  }
7374
- function splitWords(value) {
8928
+ function splitWords3(value) {
7375
8929
  const words = [];
7376
8930
  let current = "";
7377
8931
  for (let index = 0; index < value.length; index += 1) {
@@ -7405,13 +8959,13 @@ function splitWords(value) {
7405
8959
  }
7406
8960
  function formatSegment(segment, casing) {
7407
8961
  const separator = casing === "snake" ? "_" : "-";
7408
- return splitWords(segment).join(separator);
8962
+ return splitWords3(segment).join(separator);
7409
8963
  }
7410
- function toOptionFlag(path12, casing) {
7411
- return `--${path12.map((segment) => formatSegment(segment, casing)).join(".")}`;
8964
+ function toOptionFlag(path15, casing) {
8965
+ return `--${path15.map((segment) => formatSegment(segment, casing)).join(".")}`;
7412
8966
  }
7413
- function toOptionAttribute(path12, casing) {
7414
- return path12.map((segment) => {
8967
+ function toOptionAttribute(path15, casing) {
8968
+ return path15.map((segment) => {
7415
8969
  const formatted = formatSegment(segment, casing);
7416
8970
  if (casing === "snake") {
7417
8971
  return formatted;
@@ -7422,23 +8976,23 @@ function toOptionAttribute(path12, casing) {
7422
8976
  ).join("");
7423
8977
  }).join(".");
7424
8978
  }
7425
- function toDisplayPath(path12) {
7426
- return path12.join(".");
8979
+ function toDisplayPath(path15) {
8980
+ return path15.join(".");
7427
8981
  }
7428
- function toUnionKindControlPath(path12) {
7429
- if (path12.length === 0) {
8982
+ function toUnionKindControlPath(path15) {
8983
+ if (path15.length === 0) {
7430
8984
  return ["kind"];
7431
8985
  }
7432
- const head = path12.slice(0, -1);
7433
- const tail = path12[path12.length - 1] ?? "";
8986
+ const head = path15.slice(0, -1);
8987
+ const tail = path15[path15.length - 1] ?? "";
7434
8988
  return [...head, `${tail}Kind`];
7435
8989
  }
7436
- function toUnionKindDisplayPath(path12) {
7437
- if (path12.length === 0) {
8990
+ function toUnionKindDisplayPath(path15) {
8991
+ if (path15.length === 0) {
7438
8992
  return "kind";
7439
8993
  }
7440
- const head = path12.slice(0, -1);
7441
- const tail = path12[path12.length - 1] ?? "";
8994
+ const head = path15.slice(0, -1);
8995
+ const tail = path15[path15.length - 1] ?? "";
7442
8996
  return [...head, `${tail}-kind`].join(".");
7443
8997
  }
7444
8998
  function createSyntheticEnumSchema(values) {
@@ -7454,19 +9008,26 @@ function getRequiredBranchFingerprint(branch, casing) {
7454
9008
  const requiredKeys = Object.entries(branch.shape).filter(([, schema]) => schema.kind !== "optional").map(([key2]) => formatSegment(key2, casing)).sort();
7455
9009
  return requiredKeys.join("+");
7456
9010
  }
7457
- function collectFields(schema, casing, path12 = [], inheritedOptional = false, variantContext) {
9011
+ function collectFields(schema, casing, globalLongOptionFlags, path15 = [], inheritedOptional = false, variantContext) {
7458
9012
  const collected = {
7459
9013
  dynamicFields: [],
7460
9014
  fields: [],
7461
9015
  variants: []
7462
9016
  };
7463
9017
  for (const [key2, rawChildSchema] of Object.entries(schema.shape)) {
7464
- const nextPath = [...path12, key2];
9018
+ const nextPath = [...path15, key2];
7465
9019
  const runtimeOptional = inheritedOptional || rawChildSchema.kind === "optional";
7466
9020
  const childSchema = unwrapOptional(rawChildSchema);
7467
9021
  const requiredWhenActive = rawChildSchema.kind !== "optional" && childSchema.default === void 0;
7468
9022
  if (childSchema.kind === "object") {
7469
- const nested = collectFields(childSchema, casing, nextPath, runtimeOptional, variantContext);
9023
+ const nested = collectFields(
9024
+ childSchema,
9025
+ casing,
9026
+ globalLongOptionFlags,
9027
+ nextPath,
9028
+ runtimeOptional,
9029
+ variantContext
9030
+ );
7470
9031
  collected.dynamicFields.push(...nested.dynamicFields);
7471
9032
  collected.fields.push(...nested.fields);
7472
9033
  collected.variants.push(...nested.variants);
@@ -7480,7 +9041,11 @@ function collectFields(schema, casing, path12 = [], inheritedOptional = false, v
7480
9041
  path: [...nextPath, childSchema.discriminator],
7481
9042
  displayPath: toDisplayPath([...nextPath, childSchema.discriminator]),
7482
9043
  optionAttribute: toOptionAttribute([...nextPath, childSchema.discriminator], casing),
7483
- commanderOptionAttribute: toCommanderOptionAttribute([...nextPath, childSchema.discriminator], casing),
9044
+ commanderOptionAttribute: toCommanderOptionAttribute(
9045
+ [...nextPath, childSchema.discriminator],
9046
+ casing,
9047
+ globalLongOptionFlags
9048
+ ),
7484
9049
  optionFlag: toOptionFlag([...nextPath, childSchema.discriminator], casing),
7485
9050
  shortFlag: void 0,
7486
9051
  schema: createSyntheticEnumSchema(branchIds),
@@ -7493,7 +9058,7 @@ function collectFields(schema, casing, path12 = [], inheritedOptional = false, v
7493
9058
  collected.fields.push(controlField);
7494
9059
  const branches = [];
7495
9060
  for (const [branchId, branchSchema] of Object.entries(childSchema.branches)) {
7496
- const branch = collectFields(branchSchema, casing, nextPath, true, {
9061
+ const branch = collectFields(branchSchema, casing, globalLongOptionFlags, nextPath, true, {
7497
9062
  id: variantId,
7498
9063
  branchId
7499
9064
  });
@@ -7521,13 +9086,19 @@ function collectFields(schema, casing, path12 = [], inheritedOptional = false, v
7521
9086
  const variantId = `${toDisplayPath(nextPath)}:union`;
7522
9087
  const controlPath = toUnionKindControlPath(nextPath);
7523
9088
  const controlDisplayPath = toUnionKindDisplayPath(nextPath);
7524
- const branchIds = childSchema.branches.map((branch) => getRequiredBranchFingerprint(branch, casing));
9089
+ const branchIds = childSchema.branches.map(
9090
+ (branch) => getRequiredBranchFingerprint(branch, casing)
9091
+ );
7525
9092
  const controlField = {
7526
9093
  id: controlDisplayPath,
7527
9094
  path: controlPath,
7528
9095
  displayPath: controlDisplayPath,
7529
9096
  optionAttribute: toOptionAttribute(controlPath, casing),
7530
- commanderOptionAttribute: toCommanderOptionAttribute(controlPath, casing),
9097
+ commanderOptionAttribute: toCommanderOptionAttribute(
9098
+ controlPath,
9099
+ casing,
9100
+ globalLongOptionFlags
9101
+ ),
7531
9102
  optionFlag: toOptionFlag(controlPath, casing),
7532
9103
  shortFlag: void 0,
7533
9104
  schema: createSyntheticEnumSchema(branchIds),
@@ -7542,7 +9113,7 @@ function collectFields(schema, casing, path12 = [], inheritedOptional = false, v
7542
9113
  const branches = [];
7543
9114
  childSchema.branches.forEach((branchSchema, index) => {
7544
9115
  const branchId = branchIds[index] ?? "";
7545
- const branch = collectFields(branchSchema, casing, nextPath, true, {
9116
+ const branch = collectFields(branchSchema, casing, globalLongOptionFlags, nextPath, true, {
7546
9117
  id: variantId,
7547
9118
  branchId
7548
9119
  });
@@ -7609,7 +9180,7 @@ function collectFields(schema, casing, path12 = [], inheritedOptional = false, v
7609
9180
  path: nextPath,
7610
9181
  displayPath: toDisplayPath(nextPath),
7611
9182
  optionAttribute: toOptionAttribute(nextPath, casing),
7612
- commanderOptionAttribute: toCommanderOptionAttribute(nextPath, casing),
9183
+ commanderOptionAttribute: toCommanderOptionAttribute(nextPath, casing, globalLongOptionFlags),
7613
9184
  optionFlag: toOptionFlag(nextPath, casing),
7614
9185
  shortFlag: childSchema.short,
7615
9186
  schema: childSchema,
@@ -7624,10 +9195,10 @@ function collectFields(schema, casing, path12 = [], inheritedOptional = false, v
7624
9195
  }
7625
9196
  return collected;
7626
9197
  }
7627
- function toCommanderOptionAttribute(path12, casing) {
7628
- const optionAttribute = toOptionAttribute(path12, casing);
7629
- const optionFlag = toOptionFlag(path12, casing);
7630
- if (!GLOBAL_LONG_OPTION_FLAGS.has(optionFlag)) {
9198
+ function toCommanderOptionAttribute(path15, casing, globalLongOptionFlags) {
9199
+ const optionAttribute = toOptionAttribute(path15, casing);
9200
+ const optionFlag = toOptionFlag(path15, casing);
9201
+ if (!globalLongOptionFlags.has(optionFlag)) {
7631
9202
  return optionAttribute;
7632
9203
  }
7633
9204
  return `param_${optionAttribute}`;
@@ -7657,8 +9228,8 @@ function assignPositionals(fields, positional) {
7657
9228
  });
7658
9229
  return fields;
7659
9230
  }
7660
- function formatOptionFlags(field) {
7661
- const collidesWithGlobalFlag = GLOBAL_LONG_OPTION_FLAGS.has(field.optionFlag);
9231
+ function formatOptionFlags(field, globalLongOptionFlags) {
9232
+ const collidesWithGlobalFlag = globalLongOptionFlags.has(field.optionFlag);
7662
9233
  if (collidesWithGlobalFlag) {
7663
9234
  if (field.shortFlag === void 0) {
7664
9235
  throw new UserError(
@@ -7774,11 +9345,13 @@ function parseArrayValue(value, schema, label) {
7774
9345
  if (itemSchema.kind === "array" || itemSchema.kind === "object") {
7775
9346
  throw new UserError(`Array parameter "${label}" must use scalar items.`);
7776
9347
  }
7777
- return splitArrayInput(value).map((item) => parseScalarValue(item, itemSchema, label));
9348
+ return splitArrayInput(value).map(
9349
+ (item) => parseScalarValue(item, itemSchema, label)
9350
+ );
7778
9351
  }
7779
- function createOption(field) {
7780
- const flags = formatOptionFlags(field);
7781
- const collidesWithGlobalFlag = GLOBAL_LONG_OPTION_FLAGS.has(field.optionFlag);
9352
+ function createOption(field, globalLongOptionFlags) {
9353
+ const flags = formatOptionFlags(field, globalLongOptionFlags);
9354
+ const collidesWithGlobalFlag = globalLongOptionFlags.has(field.optionFlag);
7782
9355
  const commanderValue = (value) => value === null ? NULL_OPTION_VALUE : value;
7783
9356
  if (field.schema.kind === "boolean") {
7784
9357
  if (collidesWithGlobalFlag) {
@@ -7798,7 +9371,11 @@ function createOption(field) {
7798
9371
  return [
7799
9372
  createCommanderOption(`${flags} <value...>`, field.description, field).argParser(
7800
9373
  (value, previous = []) => {
7801
- const parsed = parseArrayValue(value, field.schema, field.displayPath);
9374
+ const parsed = parseArrayValue(
9375
+ value,
9376
+ field.schema,
9377
+ field.displayPath
9378
+ );
7802
9379
  if (parsed === null) {
7803
9380
  return NULL_OPTION_VALUE;
7804
9381
  }
@@ -7823,7 +9400,12 @@ function createOption(field) {
7823
9400
  );
7824
9401
  return [option];
7825
9402
  }
7826
- var GLOBAL_LONG_OPTION_FLAGS = /* @__PURE__ */ new Set(["--preset", "--yes", "--output", "--verbose"]);
9403
+ var ALWAYS_GLOBAL_LONG_OPTION_FLAGS = ["--yes", "--output", "--verbose"];
9404
+ function getGlobalLongOptionFlags(presetsEnabled) {
9405
+ return new Set(
9406
+ presetsEnabled ? ["--preset", ...ALWAYS_GLOBAL_LONG_OPTION_FLAGS] : ALWAYS_GLOBAL_LONG_OPTION_FLAGS
9407
+ );
9408
+ }
7827
9409
  function createCommanderOption(flags, description, field) {
7828
9410
  const option = new Option(flags, description);
7829
9411
  if (field.commanderOptionAttribute !== field.optionAttribute) {
@@ -7883,11 +9465,7 @@ function resolveHelpTarget(root, argv, scope, rootDisplayName) {
7883
9465
  if (current.kind !== "group") {
7884
9466
  break;
7885
9467
  }
7886
- const child = findVisibleChild(
7887
- current,
7888
- token,
7889
- scope
7890
- );
9468
+ const child = findVisibleChild(current, token, scope);
7891
9469
  if (child === void 0) {
7892
9470
  break;
7893
9471
  }
@@ -7899,32 +9477,23 @@ function resolveHelpTarget(root, argv, scope, rootDisplayName) {
7899
9477
  node: current
7900
9478
  };
7901
9479
  }
7902
- function describeSchemaType(schema) {
7903
- switch (schema.kind) {
7904
- case "string":
7905
- return "string";
7906
- case "number":
7907
- return "number";
7908
- case "boolean":
7909
- return "boolean";
7910
- case "enum":
7911
- return "value";
7912
- case "array":
7913
- return `${describeSchemaType(unwrapOptional(schema.item))}...`;
7914
- case "json":
7915
- return "json";
7916
- default:
7917
- throw new UserError("Unsupported CLI schema kind.");
7918
- }
7919
- }
7920
- function formatHelpFieldFlags(field) {
9480
+ function formatHelpFieldFlags(field, globalLongOptionFlags) {
7921
9481
  if (field.positionalIndex !== void 0) {
7922
9482
  return formatPositionalToken(field);
7923
9483
  }
7924
9484
  if (field.schema.kind === "boolean") {
7925
- return `${formatOptionFlags(field)} [value]`;
9485
+ if (field.defaultValue === true) {
9486
+ return `--no-${field.optionFlag.slice(2)}`;
9487
+ }
9488
+ return formatOptionFlags(field, globalLongOptionFlags);
7926
9489
  }
7927
- return `${formatOptionFlags(field)} <${describeSchemaType(field.schema)}>`;
9490
+ return `${formatOptionFlags(field, globalLongOptionFlags)} <${describeHelpValueToken(
9491
+ field.schema,
9492
+ {
9493
+ displayPath: field.displayPath,
9494
+ optionFlag: field.optionFlag
9495
+ }
9496
+ )}>`;
7928
9497
  }
7929
9498
  function appendHelpMetadata(description, metadata) {
7930
9499
  if (metadata.length === 0) {
@@ -7946,6 +9515,87 @@ function formatHelpFieldDescription(field) {
7946
9515
  }
7947
9516
  return appendHelpMetadata(description, metadata);
7948
9517
  }
9518
+ function describeKnownStringFormat(format) {
9519
+ switch (format) {
9520
+ case "date":
9521
+ return "date";
9522
+ case "date-time":
9523
+ return "datetime";
9524
+ case "uri":
9525
+ return "url";
9526
+ case "email":
9527
+ return "email";
9528
+ default:
9529
+ return void 0;
9530
+ }
9531
+ }
9532
+ function describeKnownStringPattern(pattern) {
9533
+ if (pattern === void 0) {
9534
+ return void 0;
9535
+ }
9536
+ if (pattern === "^\\d{4}-\\d{2}-\\d{2}$") {
9537
+ return "YYYY-MM-DD";
9538
+ }
9539
+ if (pattern.startsWith("^\\d{4}-\\d{2}-\\d{2}T")) {
9540
+ return "YYYY-MM-DDTHH:MM:SS";
9541
+ }
9542
+ return void 0;
9543
+ }
9544
+ function stripLongOptionPrefix(optionFlag) {
9545
+ return optionFlag.startsWith("--") ? optionFlag.slice(2) : optionFlag;
9546
+ }
9547
+ function getLastSegment(value, separator) {
9548
+ const segments = value.split(separator);
9549
+ return segments[segments.length - 1] ?? value;
9550
+ }
9551
+ function matchesFieldNameSuffix(name, suffix) {
9552
+ const lowerName = name.toLowerCase();
9553
+ const lowerSuffix = suffix.toLowerCase();
9554
+ return lowerName === lowerSuffix || name.endsWith(suffix) || lowerName.endsWith(`-${lowerSuffix}`) || lowerName.endsWith(`_${lowerSuffix}`);
9555
+ }
9556
+ function describeFieldNameValueToken(displayPath, optionFlag) {
9557
+ const displayName = getLastSegment(displayPath, ".");
9558
+ const optionName = getLastSegment(stripLongOptionPrefix(optionFlag), ".");
9559
+ const candidates = [displayName, optionName];
9560
+ const suffixTokens = [
9561
+ ["Path", "path"],
9562
+ ["Paths", "path"],
9563
+ ["File", "path"],
9564
+ ["Files", "path"],
9565
+ ["Url", "url"],
9566
+ ["Email", "email"],
9567
+ ["Name", "name"],
9568
+ ["Id", "id"]
9569
+ ];
9570
+ for (const [suffix, token] of suffixTokens) {
9571
+ if (candidates.some((candidate) => matchesFieldNameSuffix(candidate, suffix))) {
9572
+ return token;
9573
+ }
9574
+ }
9575
+ return void 0;
9576
+ }
9577
+ function describeHelpValueToken(schema, field) {
9578
+ if (schema.kind === "array") {
9579
+ const itemSchema = unwrapOptional(schema.item);
9580
+ if (itemSchema.kind === "array" || itemSchema.kind === "object") {
9581
+ return "value...";
9582
+ }
9583
+ return `${describeHelpValueToken(itemSchema, field)}...`;
9584
+ }
9585
+ if (schema.kind === "json") {
9586
+ return "json";
9587
+ }
9588
+ if (schema.kind === "string") {
9589
+ const metadataToken = describeKnownStringFormat(schema.format) ?? describeKnownStringPattern(schema.pattern);
9590
+ if (metadataToken !== void 0) {
9591
+ return metadataToken;
9592
+ }
9593
+ }
9594
+ if (schema.kind === "enum") {
9595
+ return "value";
9596
+ }
9597
+ return describeFieldNameValueToken(field.displayPath, field.optionFlag) ?? "value";
9598
+ }
7949
9599
  function describeDynamicFieldType(field) {
7950
9600
  if (field.schema.kind === "record") {
7951
9601
  const valueSchema = unwrapOptional(field.schema.value);
@@ -7953,12 +9603,18 @@ function describeDynamicFieldType(field) {
7953
9603
  return "json";
7954
9604
  }
7955
9605
  if (valueSchema.kind === "array") {
7956
- return `${describeSchemaType(valueSchema)}`;
9606
+ return describeHelpValueToken(valueSchema, {
9607
+ displayPath: field.optionPathDisplay,
9608
+ optionFlag: field.optionFlag
9609
+ });
7957
9610
  }
7958
9611
  if (valueSchema.kind === "object") {
7959
9612
  return "value";
7960
9613
  }
7961
- return describeSchemaType(valueSchema);
9614
+ return describeHelpValueToken(valueSchema, {
9615
+ displayPath: field.optionPathDisplay,
9616
+ optionFlag: field.optionFlag
9617
+ });
7962
9618
  }
7963
9619
  return "value";
7964
9620
  }
@@ -7980,7 +9636,9 @@ function collectDynamicObjectHelpRows(schema, casing, optionPrefix, displayPrefi
7980
9636
  const displayPath = `${displayPrefix}.${key2}`;
7981
9637
  const description = childSchema.description ?? displayPath;
7982
9638
  if (childSchema.kind === "object") {
7983
- rows.push(...collectDynamicObjectHelpRows(childSchema, casing, optionFlag, displayPath, metadata));
9639
+ rows.push(
9640
+ ...collectDynamicObjectHelpRows(childSchema, casing, optionFlag, displayPath, metadata)
9641
+ );
7984
9642
  continue;
7985
9643
  }
7986
9644
  if (childSchema.kind === "record") {
@@ -8017,7 +9675,10 @@ function collectDynamicObjectHelpRows(schema, casing, optionPrefix, displayPrefi
8017
9675
  continue;
8018
9676
  }
8019
9677
  rows.push({
8020
- flags: childSchema.kind === "boolean" ? `${optionFlag} [value]` : `${optionFlag} <${describeSchemaType(childSchema)}>`,
9678
+ flags: childSchema.kind === "boolean" ? childSchema.default === true ? `--no-${optionFlag.slice(2)}` : optionFlag : `${optionFlag} <${describeHelpValueToken(childSchema, {
9679
+ displayPath,
9680
+ optionFlag
9681
+ })}>`,
8021
9682
  description: appendHelpMetadata(description, metadata)
8022
9683
  });
8023
9684
  }
@@ -8049,10 +9710,12 @@ function formatDynamicHelpFields(field, casing) {
8049
9710
  );
8050
9711
  }
8051
9712
  }
8052
- return [{
8053
- flags: `${field.optionFlag} <${describeDynamicFieldType(field)}>`,
8054
- description: appendHelpMetadata(field.description ?? field.optionPathDisplay, metadata)
8055
- }];
9713
+ return [
9714
+ {
9715
+ flags: `${field.optionFlag} <${describeDynamicFieldType(field)}>`,
9716
+ description: appendHelpMetadata(field.description ?? field.optionPathDisplay, metadata)
9717
+ }
9718
+ ];
8056
9719
  }
8057
9720
  function formatSecretRows(secrets) {
8058
9721
  return Object.values(secrets).map((secret) => ({
@@ -8066,32 +9729,58 @@ function formatSecretDescription(secret) {
8066
9729
  }
8067
9730
  return secret.optional === true ? "Optional secret" : "Required secret";
8068
9731
  }
8069
- function formatCommandRows(group, scope) {
9732
+ function wrapOptionalCommandParameterToken(token, optional) {
9733
+ return optional ? `[${token}]` : token;
9734
+ }
9735
+ function formatCommandDynamicParameterTokens(field, casing) {
9736
+ const optional = field.optional || field.hasDefault;
9737
+ return formatDynamicHelpFields(field, casing).map(
9738
+ (row) => wrapOptionalCommandParameterToken(row.flags, optional)
9739
+ );
9740
+ }
9741
+ function formatCommandParameterTokens(command, casing, globalLongOptionFlags) {
9742
+ const collected = collectFields(command.params, casing, globalLongOptionFlags);
9743
+ const fields = assignPositionals(collected.fields, command.positional);
9744
+ return fields.map(
9745
+ (field) => wrapOptionalCommandParameterToken(
9746
+ formatHelpFieldFlags(field, globalLongOptionFlags),
9747
+ field.positionalIndex === void 0 && (field.optional || field.hasDefault)
9748
+ )
9749
+ ).concat(
9750
+ collected.dynamicFields.flatMap((field) => formatCommandDynamicParameterTokens(field, casing))
9751
+ );
9752
+ }
9753
+ function formatCommandRowName(node, casing, globalLongOptionFlags) {
9754
+ const baseName = node.aliases.length === 0 ? node.name : `${node.name} (${node.aliases.join(", ")})`;
9755
+ const parameterTokens = node.kind === "command" ? formatCommandParameterTokens(node, casing, globalLongOptionFlags) : [];
9756
+ const name = parameterTokens.length === 0 ? baseName : `${baseName} ${parameterTokens.join(" ")}`;
9757
+ return name;
9758
+ }
9759
+ function formatCommandRows(group, scope, casing, globalLongOptionFlags) {
8070
9760
  return getVisibleChildren(group, scope).map((child) => ({
8071
- name: child.aliases.length === 0 ? child.name : `${child.name} (${child.aliases.join(", ")})`,
9761
+ name: formatCommandRowName(child, casing, globalLongOptionFlags),
8072
9762
  description: child.description ?? ""
8073
9763
  }));
8074
9764
  }
8075
- function formatGlobalOptionRows(showVersion) {
8076
- const rows = [
8077
- {
9765
+ function formatGlobalOptionRows(ctx) {
9766
+ const rows = [];
9767
+ if (ctx.presetsEnabled) {
9768
+ rows.push({
8078
9769
  flags: "--preset <path>",
8079
9770
  description: "Load parameter defaults from a JSON file"
8080
- },
9771
+ });
9772
+ }
9773
+ rows.push(
8081
9774
  {
8082
9775
  flags: "--yes",
8083
9776
  description: "Accept defaults, skip prompts"
8084
9777
  },
8085
9778
  {
8086
9779
  flags: "--output <format>",
8087
- description: "Output format (rich, md, json)"
8088
- },
8089
- {
8090
- flags: "-h, --help",
8091
- description: "Show help"
9780
+ description: "Output format: rich, md, json."
8092
9781
  }
8093
- ];
8094
- if (showVersion) {
9782
+ );
9783
+ if (ctx.showVersion) {
8095
9784
  rows.push({
8096
9785
  flags: "--version",
8097
9786
  description: "Show version"
@@ -8102,53 +9791,69 @@ function formatGlobalOptionRows(showVersion) {
8102
9791
  function renderHelpSections(sections) {
8103
9792
  return sections.filter((section) => section.length > 0).join("\n\n");
8104
9793
  }
9794
+ function formatHelpCommandList(rows) {
9795
+ return process.stdout.isTTY === false ? help_formatter_plain_exports.formatCommandList(rows) : formatCommandList(rows);
9796
+ }
9797
+ function formatHelpOptionList(rows) {
9798
+ return process.stdout.isTTY === false ? help_formatter_plain_exports.formatOptionList(rows) : formatOptionList(rows);
9799
+ }
8105
9800
  function buildUsageLine(breadcrumb, rootUsageName, suffix) {
8106
- if (rootUsageName === void 0) {
8107
- return void 0;
8108
- }
8109
- const subPath = breadcrumb.slice(1).join(" ");
8110
- return subPath ? `${rootUsageName} ${subPath} ${suffix}` : `${rootUsageName} ${suffix}`;
9801
+ const visibleBreadcrumb = breadcrumb.filter((segment) => segment.length > 0);
9802
+ const usageBreadcrumb = breadcrumb[0] === "" ? [rootUsageName, ...visibleBreadcrumb] : visibleBreadcrumb;
9803
+ const subPath = usageBreadcrumb.slice(1).join(" ");
9804
+ const tokens = [rootUsageName, subPath, suffix].filter((segment) => segment.length > 0);
9805
+ return tokens.join(" ");
8111
9806
  }
8112
- function renderGroupHelp(group, breadcrumb, scope, showVersion, rootUsageName) {
9807
+ function renderGroupHelp(group, breadcrumb, scope, casing, globalOptions, rootUsageName) {
8113
9808
  const sections = [];
8114
- const commandRows = formatCommandRows(group, scope);
9809
+ const globalLongOptionFlags = getGlobalLongOptionFlags(globalOptions.presetsEnabled);
9810
+ const commandRows = formatCommandRows(group, scope, casing, globalLongOptionFlags);
8115
9811
  if (commandRows.length > 0) {
8116
- sections.push(`${text.section("Commands:")}
8117
- ${formatCommandList(commandRows)}`);
9812
+ sections.push(`${text.sectionHeader("Commands")}
9813
+ ${formatHelpCommandList(commandRows)}`);
8118
9814
  }
8119
- sections.push(`${text.section("Global options:")}
8120
- ${formatOptionList(formatGlobalOptionRows(showVersion))}`);
9815
+ sections.push(
9816
+ `${text.sectionHeader("Options")}
9817
+ ${formatHelpOptionList(formatGlobalOptionRows(globalOptions))}`
9818
+ );
8121
9819
  return renderHelpDocument({
8122
9820
  breadcrumb,
8123
- usageLine: buildUsageLine(breadcrumb, rootUsageName, "[options] [command]"),
9821
+ rootUsageName,
9822
+ usageLine: buildUsageLine(breadcrumb, rootUsageName, "[command] [options]"),
8124
9823
  description: group.description,
8125
9824
  requiresAuth: group.requires?.auth === true,
8126
9825
  sections
8127
9826
  });
8128
9827
  }
8129
- function renderLeafHelp(command, breadcrumb, casing, rootUsageName) {
9828
+ function renderLeafHelp(command, breadcrumb, casing, globalOptions, rootUsageName) {
8130
9829
  const sections = [];
8131
- const collected = collectFields(command.params, casing);
9830
+ const globalLongOptionFlags = getGlobalLongOptionFlags(globalOptions.presetsEnabled);
9831
+ const collected = collectFields(command.params, casing, globalLongOptionFlags);
8132
9832
  const fields = assignPositionals(collected.fields, command.positional);
8133
9833
  const optionRows = fields.map((field) => ({
8134
- flags: formatHelpFieldFlags(field),
9834
+ flags: formatHelpFieldFlags(field, globalLongOptionFlags),
8135
9835
  description: formatHelpFieldDescription(field)
8136
9836
  })).concat(collected.dynamicFields.flatMap((field) => formatDynamicHelpFields(field, casing)));
8137
9837
  if (optionRows.length > 0) {
8138
- sections.push(`${text.section("Options:")}
8139
- ${formatOptionList(optionRows)}`);
9838
+ sections.push(`${text.sectionHeader("Options")}
9839
+ ${formatHelpOptionList(optionRows)}`);
8140
9840
  }
8141
- sections.push(`${text.section("Global options:")}
8142
- ${formatOptionList(formatGlobalOptionRows(false))}`);
9841
+ sections.push(
9842
+ `${text.sectionHeader("Options")}
9843
+ ${formatHelpOptionList(formatGlobalOptionRows(globalOptions))}`
9844
+ );
8143
9845
  const secretRows = formatSecretRows(command.secrets);
8144
9846
  if (secretRows.length > 0) {
8145
- sections.push(`${text.section("Secrets (via environment):")}
8146
- ${formatOptionList(secretRows)}`);
9847
+ sections.push(
9848
+ `${text.sectionHeader("Secrets (environment)")}
9849
+ ${formatHelpOptionList(secretRows)}`
9850
+ );
8147
9851
  }
8148
9852
  const positionalFields = fields.filter((f) => f.positionalIndex !== void 0);
8149
9853
  const usageSuffix = positionalFields.length > 0 ? `[options] ${positionalFields.map(formatPositionalToken).join(" ")}` : "[options]";
8150
9854
  return renderHelpDocument({
8151
9855
  breadcrumb,
9856
+ rootUsageName,
8152
9857
  usageLine: buildUsageLine(breadcrumb, rootUsageName, usageSuffix),
8153
9858
  description: command.description,
8154
9859
  requiresAuth: command.requires?.auth === true,
@@ -8156,17 +9861,21 @@ ${formatOptionList(secretRows)}`);
8156
9861
  });
8157
9862
  }
8158
9863
  function renderHelpDocument(input) {
8159
- const lines = [text.heading(input.breadcrumb.join(" ")), ""];
8160
- if (input.usageLine !== void 0) {
8161
- lines.push(`${text.section("Usage:")} ${text.usageCommand(input.usageLine)}`, "");
8162
- }
8163
- if (input.description !== void 0) {
8164
- lines.push(input.description);
8165
- }
9864
+ const title = input.breadcrumb.filter((segment) => segment.length > 0).join(" ") || input.rootUsageName;
9865
+ const description = input.description ?? "";
9866
+ const sentenceEndIndex = description.indexOf(". ");
9867
+ const headingDescription = sentenceEndIndex === -1 ? description : description.slice(0, sentenceEndIndex + 1);
9868
+ const remainingDescription = sentenceEndIndex === -1 ? "" : description.slice(sentenceEndIndex + 2);
9869
+ const heading = headingDescription.length > 0 ? `${title} \u2014 ${headingDescription}` : title;
9870
+ const lines = [text.heading(heading), ""];
9871
+ if (remainingDescription.length > 0) {
9872
+ lines.push(remainingDescription, "");
9873
+ }
9874
+ lines.push(`Usage: ${text.usageCommand(input.usageLine)}`, "");
8166
9875
  if (input.requiresAuth) {
8167
9876
  lines.push("Requires: authentication");
8168
9877
  }
8169
- if (input.description !== void 0 || input.requiresAuth) {
9878
+ if (input.requiresAuth) {
8170
9879
  lines.push("");
8171
9880
  }
8172
9881
  lines.push(renderHelpSections(input.sections));
@@ -8177,26 +9886,46 @@ async function renderGeneratedHelp(root, argv, options) {
8177
9886
  const target = resolveHelpTarget(root, argv, "cli", options.rootDisplayName);
8178
9887
  const output = resolveHelpOutput(argv);
8179
9888
  const casing = options.casing ?? "kebab";
9889
+ const rootUsageName = options.rootUsageName ?? inferProgramName(argv);
8180
9890
  await withOutputFormat2(output, async () => {
8181
- const rendered = target.node.kind === "group" ? renderGroupHelp(target.node, target.breadcrumb, "cli", options.version !== void 0, options.rootUsageName) : renderLeafHelp(target.node, target.breadcrumb, casing, options.rootUsageName);
9891
+ const rendered = target.node.kind === "group" ? renderGroupHelp(
9892
+ target.node,
9893
+ target.breadcrumb,
9894
+ "cli",
9895
+ casing,
9896
+ {
9897
+ showVersion: options.version !== void 0,
9898
+ presetsEnabled: options.presets === true
9899
+ },
9900
+ rootUsageName
9901
+ ) : renderLeafHelp(
9902
+ target.node,
9903
+ target.breadcrumb,
9904
+ casing,
9905
+ {
9906
+ showVersion: options.version !== void 0,
9907
+ presetsEnabled: options.presets === true
9908
+ },
9909
+ rootUsageName
9910
+ );
8182
9911
  process.stdout.write(rendered);
8183
9912
  });
8184
9913
  }
8185
- function createNodeCommand(node, casing, execute, pathSegments = []) {
9914
+ function createNodeCommand(node, casing, globalLongOptionFlags, execute, presetsEnabled, pathSegments = []) {
8186
9915
  const nextPathSegments = [...pathSegments, node.name];
8187
9916
  if (node.kind === "command") {
8188
9917
  if (!node.scope.includes("cli")) {
8189
9918
  return null;
8190
9919
  }
8191
9920
  const command = new CommanderCommand(node.name);
8192
- const collected = collectFields(node.params, casing);
9921
+ const collected = collectFields(node.params, casing, globalLongOptionFlags);
8193
9922
  const fields = assignPositionals(collected.fields, node.positional);
8194
9923
  if (node.description !== void 0) {
8195
9924
  command.description(node.description);
8196
9925
  }
8197
9926
  node.aliases.forEach((alias) => command.alias(alias));
8198
9927
  command.addHelpCommand(false);
8199
- addGlobalOptions(command);
9928
+ addGlobalOptions(command, presetsEnabled);
8200
9929
  command.allowExcessArguments(true);
8201
9930
  if (collected.dynamicFields.length > 0) {
8202
9931
  command.allowUnknownOption(true);
@@ -8206,7 +9935,7 @@ function createNodeCommand(node, casing, execute, pathSegments = []) {
8206
9935
  command.argument(formatPositionalToken(field));
8207
9936
  continue;
8208
9937
  }
8209
- for (const option of createOption(field)) {
9938
+ for (const option of createOption(field, globalLongOptionFlags)) {
8210
9939
  command.addOption(option);
8211
9940
  }
8212
9941
  }
@@ -8220,6 +9949,7 @@ function createNodeCommand(node, casing, execute, pathSegments = []) {
8220
9949
  dynamicFields: collected.dynamicFields,
8221
9950
  fields,
8222
9951
  positionalValues,
9952
+ presetsEnabled,
8223
9953
  rawArgv: actionCommand.args,
8224
9954
  actionCommand,
8225
9955
  variants: collected.variants
@@ -8230,35 +9960,49 @@ function createNodeCommand(node, casing, execute, pathSegments = []) {
8230
9960
  if (!isNodeVisibleInScope(node, "cli")) {
8231
9961
  return null;
8232
9962
  }
8233
- const visibleChildren = node.children.map((child) => createNodeCommand(child, casing, execute, nextPathSegments)).filter((child) => child !== null);
9963
+ const visibleChildren = node.children.map(
9964
+ (child) => createNodeCommand(
9965
+ child,
9966
+ casing,
9967
+ globalLongOptionFlags,
9968
+ execute,
9969
+ presetsEnabled,
9970
+ nextPathSegments
9971
+ )
9972
+ ).filter((child) => child !== null);
8234
9973
  const group = new CommanderCommand(node.name);
8235
9974
  if (node.description !== void 0) {
8236
9975
  group.description(node.description);
8237
9976
  }
8238
9977
  node.aliases.forEach((alias) => group.alias(alias));
8239
9978
  group.addHelpCommand(false);
8240
- addGlobalOptions(group);
9979
+ addGlobalOptions(group, presetsEnabled);
8241
9980
  for (const child of visibleChildren) {
8242
9981
  const isDefaultChild = node.default !== void 0 && node.default.scope.includes("cli") && (child.name() === node.default.name || child.aliases().includes(node.default.name));
8243
9982
  group.addCommand(child, isDefaultChild ? { isDefault: true } : void 0);
8244
9983
  }
8245
9984
  return group;
8246
9985
  }
8247
- function addGlobalOptions(command) {
8248
- command.option("--preset <path>", "Load parameter defaults from a JSON file.").option("--yes", "Accept defaults and skip prompts.").option("--output <format>", "Output format.", (value) => {
9986
+ function addGlobalOptions(command, presetsEnabled) {
9987
+ if (presetsEnabled) {
9988
+ command.option("--preset <path>", "Load parameter defaults from a JSON file.");
9989
+ }
9990
+ command.option("--yes", "Accept defaults and skip prompts.").option("--output <format>", "Output format.", (value) => {
8249
9991
  if (value === "rich" || value === "md" || value === "json") {
8250
9992
  return value;
8251
9993
  }
8252
9994
  if (value === "markdown") {
8253
9995
  return "md";
8254
9996
  }
8255
- throw new InvalidArgumentError('Invalid value for "--output". Expected one of: rich, md, markdown, json.');
9997
+ throw new InvalidArgumentError(
9998
+ 'Invalid value for "--output". Expected one of: rich, md, markdown, json.'
9999
+ );
8256
10000
  }).option("--verbose", "Print stack traces for unexpected errors.");
8257
10001
  }
8258
- function setNestedValue(target, path12, value) {
10002
+ function setNestedValue(target, path15, value) {
8259
10003
  let cursor = target;
8260
- for (let index = 0; index < path12.length - 1; index += 1) {
8261
- const segment = path12[index] ?? "";
10004
+ for (let index = 0; index < path15.length - 1; index += 1) {
10005
+ const segment = path15[index] ?? "";
8262
10006
  const existing = cursor[segment];
8263
10007
  if (typeof existing === "object" && existing !== null) {
8264
10008
  cursor = existing;
@@ -8268,7 +10012,7 @@ function setNestedValue(target, path12, value) {
8268
10012
  cursor[segment] = next;
8269
10013
  cursor = next;
8270
10014
  }
8271
- const leaf = path12[path12.length - 1];
10015
+ const leaf = path15[path15.length - 1];
8272
10016
  if (leaf !== void 0) {
8273
10017
  cursor[leaf] = value;
8274
10018
  }
@@ -8370,13 +10114,13 @@ async function withOutputFormat2(output, fn) {
8370
10114
  }
8371
10115
  function createFs2() {
8372
10116
  return {
8373
- readFile: async (path12, encoding = "utf8") => readFile3(path12, { encoding }),
8374
- writeFile: async (path12, contents) => {
8375
- await writeFile3(path12, contents);
10117
+ readFile: async (path15, encoding = "utf8") => readFile5(path15, { encoding }),
10118
+ writeFile: async (path15, contents) => {
10119
+ await writeFile3(path15, contents);
8376
10120
  },
8377
- exists: async (path12) => {
10121
+ exists: async (path15) => {
8378
10122
  try {
8379
- await access2(path12);
10123
+ await access2(path15);
8380
10124
  return true;
8381
10125
  } catch {
8382
10126
  return false;
@@ -8397,9 +10141,9 @@ function isPlainObject2(value) {
8397
10141
  function hasFieldValue(value) {
8398
10142
  return value !== void 0;
8399
10143
  }
8400
- function hasNestedField(fields, path12) {
10144
+ function hasNestedField(fields, path15) {
8401
10145
  return fields.some(
8402
- (field) => path12.length < field.path.length && path12.every((segment, index) => field.path[index] === segment)
10146
+ (field) => path15.length < field.path.length && path15.every((segment, index) => field.path[index] === segment)
8403
10147
  );
8404
10148
  }
8405
10149
  function describeExpectedPresetValue(schema) {
@@ -8456,7 +10200,12 @@ function validatePresetFieldValue(value, field, presetPath) {
8456
10200
  return value;
8457
10201
  }
8458
10202
  if (field.schema.kind !== "array") {
8459
- return validatePresetScalarValue(value, field.schema, field.displayPath, presetPath);
10203
+ return validatePresetScalarValue(
10204
+ value,
10205
+ field.schema,
10206
+ field.displayPath,
10207
+ presetPath
10208
+ );
8460
10209
  }
8461
10210
  const itemSchema = unwrapOptional(field.schema.item);
8462
10211
  if (itemSchema.kind === "array" || itemSchema.kind === "object") {
@@ -8474,7 +10223,7 @@ function validatePresetFieldValue(value, field, presetPath) {
8474
10223
  async function loadPresetValues(fields, presetPath) {
8475
10224
  let rawPreset;
8476
10225
  try {
8477
- rawPreset = await readFile3(presetPath, {
10226
+ rawPreset = await readFile5(presetPath, {
8478
10227
  encoding: "utf8"
8479
10228
  });
8480
10229
  } catch (error2) {
@@ -8495,9 +10244,9 @@ async function loadPresetValues(fields, presetPath) {
8495
10244
  }
8496
10245
  const fieldByPath = new Map(fields.map((field) => [field.displayPath, field]));
8497
10246
  const presetValues = {};
8498
- function visitObject(current, path12) {
10247
+ function visitObject(current, path15) {
8499
10248
  for (const [key2, value] of Object.entries(current)) {
8500
- const nextPath = [...path12, key2];
10249
+ const nextPath = [...path15, key2];
8501
10250
  const displayPath = toDisplayPath(nextPath);
8502
10251
  const field = fieldByPath.get(displayPath);
8503
10252
  if (field !== void 0) {
@@ -8556,7 +10305,9 @@ function matchesFixtureValue(expected, actual) {
8556
10305
  if (!isPlainObject2(actual)) {
8557
10306
  return false;
8558
10307
  }
8559
- return Object.entries(expected).every(([key2, value]) => matchesFixtureValue(value, actual[key2]));
10308
+ return Object.entries(expected).every(
10309
+ ([key2, value]) => matchesFixtureValue(value, actual[key2])
10310
+ );
8560
10311
  }
8561
10312
  return Object.is(expected, actual);
8562
10313
  }
@@ -8594,7 +10345,9 @@ function createFixtureResponse(response) {
8594
10345
  }
8595
10346
  function createFixtureFetch(entries) {
8596
10347
  return async (input, init) => {
8597
- const method = normalizeHttpMethod(init?.method ?? (input instanceof Request ? input.method : void 0));
10348
+ const method = normalizeHttpMethod(
10349
+ init?.method ?? (input instanceof Request ? input.method : void 0)
10350
+ );
8598
10351
  const url = getFetchUrl(input);
8599
10352
  const match = entries?.find((entry) => {
8600
10353
  const requestMethod = normalizeHttpMethod(entry.request.method);
@@ -8639,7 +10392,9 @@ function resolveFixtureMethodResult(methodName, definition, args) {
8639
10392
  }
8640
10393
  const explicitMatcher = isPlainObject2(entry.request) ? entry.request : void 0;
8641
10394
  const matcher = explicitMatcher ?? Object.fromEntries(
8642
- Object.entries(entry).filter(([key2]) => key2 !== "result" && key2 !== "response" && key2 !== "error")
10395
+ Object.entries(entry).filter(
10396
+ ([key2]) => key2 !== "result" && key2 !== "response" && key2 !== "error"
10397
+ )
8643
10398
  );
8644
10399
  const firstArg = args[0];
8645
10400
  let matched = false;
@@ -8695,8 +10450,8 @@ function createFixtureService(definition) {
8695
10450
  );
8696
10451
  }
8697
10452
  function resolveFixturePath(commandPath) {
8698
- const parsed = path6.parse(commandPath);
8699
- return path6.join(parsed.dir, `${parsed.name}.fixture.json`);
10453
+ const parsed = path9.parse(commandPath);
10454
+ return path9.join(parsed.dir, `${parsed.name}.fixture.json`);
8700
10455
  }
8701
10456
  function selectFixtureScenario(scenarios, selector) {
8702
10457
  if (isNumericFixtureSelector(selector)) {
@@ -8718,12 +10473,14 @@ function selectFixtureScenario(scenarios, selector) {
8718
10473
  async function loadFixtureScenario(command, selector) {
8719
10474
  const commandPath = getCommandSourcePath(command);
8720
10475
  if (commandPath === void 0) {
8721
- throw new UserError(`Fixture mode could not determine the source file for command "${command.name}".`);
10476
+ throw new UserError(
10477
+ `Fixture mode could not determine the source file for command "${command.name}".`
10478
+ );
8722
10479
  }
8723
10480
  const fixturePath = resolveFixturePath(commandPath);
8724
10481
  let rawFixture;
8725
10482
  try {
8726
- rawFixture = await readFile3(fixturePath, {
10483
+ rawFixture = await readFile5(fixturePath, {
8727
10484
  encoding: "utf8"
8728
10485
  });
8729
10486
  } catch {
@@ -8819,8 +10576,8 @@ function validateServices(services) {
8819
10576
  }
8820
10577
  }
8821
10578
  }
8822
- function getNestedValue(target, path12) {
8823
- return path12.reduce(
10579
+ function getNestedValue(target, path15) {
10580
+ return path15.reduce(
8824
10581
  (current, segment) => current !== null && typeof current === "object" ? current[segment] : void 0,
8825
10582
  target
8826
10583
  );
@@ -8919,7 +10676,13 @@ function resolveDynamicLeaf(schema, rawSegments, casing, outputPath = [], displa
8919
10676
  if (formatSegment(key2, casing) !== head) {
8920
10677
  continue;
8921
10678
  }
8922
- return resolveDynamicLeaf(childSchema, rest, casing, [...outputPath, key2], [...displayPath, key2]);
10679
+ return resolveDynamicLeaf(
10680
+ childSchema,
10681
+ rest,
10682
+ casing,
10683
+ [...outputPath, key2],
10684
+ [...displayPath, key2]
10685
+ );
8923
10686
  }
8924
10687
  throw new UserError(`Unknown parameter "${[...displayPath, head].join(".")}".`);
8925
10688
  }
@@ -8936,13 +10699,23 @@ function resolveDynamicLeaf(schema, rawSegments, casing, outputPath = [], displa
8936
10699
  case "array": {
8937
10700
  const itemSchema = unwrapOptional(unwrappedSchema.item);
8938
10701
  if (itemSchema.kind !== "object") {
8939
- throw new UserError(`Array parameter "${toDisplayPath(displayPath)}" must use object items.`);
10702
+ throw new UserError(
10703
+ `Array parameter "${toDisplayPath(displayPath)}" must use object items.`
10704
+ );
8940
10705
  }
8941
10706
  const [head, ...rest] = rawSegments;
8942
10707
  if (head === void 0 || !isNumericFixtureSelector(head)) {
8943
- throw new UserError(`Array parameter "${toDisplayPath(displayPath)}" must use numeric indices.`);
10708
+ throw new UserError(
10709
+ `Array parameter "${toDisplayPath(displayPath)}" must use numeric indices.`
10710
+ );
8944
10711
  }
8945
- return resolveDynamicLeaf(itemSchema, rest, casing, [...outputPath, head], [...displayPath, head]);
10712
+ return resolveDynamicLeaf(
10713
+ itemSchema,
10714
+ rest,
10715
+ casing,
10716
+ [...outputPath, head],
10717
+ [...displayPath, head]
10718
+ );
8946
10719
  }
8947
10720
  default:
8948
10721
  throw new UserError(`Unknown parameter "${[...displayPath, ...rawSegments].join(".")}".`);
@@ -8978,7 +10751,9 @@ function finalizeDynamicValue(schema, value, displayPath) {
8978
10751
  }
8979
10752
  for (let index = 0; index < indices.length; index += 1) {
8980
10753
  if (indices[index] !== index) {
8981
- throw new UserError(`Array parameter "${displayPath}" must use contiguous indices starting at 0.`);
10754
+ throw new UserError(
10755
+ `Array parameter "${displayPath}" must use contiguous indices starting at 0.`
10756
+ );
8982
10757
  }
8983
10758
  }
8984
10759
  return indices.map(
@@ -9034,7 +10809,9 @@ function finalizeDynamicValue(schema, value, displayPath) {
9034
10809
  function parseDynamicValues(dynamicFields, rawArgv, casing) {
9035
10810
  const rawValues = /* @__PURE__ */ new Map();
9036
10811
  const providedFieldIds = /* @__PURE__ */ new Set();
9037
- const sortedFields = [...dynamicFields].sort((left, right) => right.optionPath.length - left.optionPath.length);
10812
+ const sortedFields = [...dynamicFields].sort(
10813
+ (left, right) => right.optionPath.length - left.optionPath.length
10814
+ );
9038
10815
  for (let index = 0; index < rawArgv.length; index += 1) {
9039
10816
  const token = rawArgv[index] ?? "";
9040
10817
  if (!token.startsWith("--")) {
@@ -9121,7 +10898,9 @@ async function enforceVariantConstraints(params17, fields, dynamicFields, varian
9121
10898
  );
9122
10899
  }
9123
10900
  }
9124
- const invalidDynamicFieldId = branch.dynamicFieldIds.find((fieldId) => providedDynamicFieldIds.has(fieldId));
10901
+ const invalidDynamicFieldId = branch.dynamicFieldIds.find(
10902
+ (fieldId) => providedDynamicFieldIds.has(fieldId)
10903
+ );
9125
10904
  if (invalidDynamicFieldId !== void 0) {
9126
10905
  const field = dynamicFieldById.get(invalidDynamicFieldId);
9127
10906
  if (field !== void 0) {
@@ -9286,7 +11065,7 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
9286
11065
  optionValues,
9287
11066
  state.rawArgv,
9288
11067
  state.casing,
9289
- resolvedFlags.preset,
11068
+ state.presetsEnabled ? resolvedFlags.preset : void 0,
9290
11069
  shouldPrompt
9291
11070
  );
9292
11071
  const context = {
@@ -9315,7 +11094,12 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
9315
11094
  throw new UserError("Operation cancelled.");
9316
11095
  }
9317
11096
  }
9318
- const result = await invokeWithHumanInLoop(state.command, context, runtimeOptions, state.commandPath);
11097
+ const result = await invokeWithHumanInLoop(
11098
+ state.command,
11099
+ context,
11100
+ runtimeOptions,
11101
+ state.commandPath
11102
+ );
9319
11103
  if (output === "rich" && runtime.isFixture) {
9320
11104
  writeRichHeader(`${state.command.name} (fixture)`);
9321
11105
  }
@@ -9323,7 +11107,10 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
9323
11107
  renderHumanInLoopPending(result);
9324
11108
  return;
9325
11109
  }
9326
- renderResult(state.command, result, output, primitives);
11110
+ const renderStatus = renderResult(state.command, result, output, primitives);
11111
+ if (renderStatus.mcpError) {
11112
+ process.exitCode = 1;
11113
+ }
9327
11114
  });
9328
11115
  }
9329
11116
  function handleRunError(error2, verbose) {
@@ -9350,10 +11137,11 @@ function handleRunError(error2, verbose) {
9350
11137
  }
9351
11138
  async function runCLI(roots, options = {}) {
9352
11139
  const root = mergeApprovalsGroup(normalizeRoots(roots, process.argv));
9353
- await resolveMcpProxies(root);
11140
+ await resolveMcpProxies(root, { projectRoot: options.projectRoot });
9354
11141
  const casing = options.casing ?? "kebab";
9355
11142
  const services = options.services ?? {};
9356
11143
  const runtimeOptions = options.humanInLoop ?? {};
11144
+ const version = options.version ?? findEntrypointPackageMetadata(process.argv[1])?.version;
9357
11145
  const servicesWithBuiltIns = {
9358
11146
  ...services,
9359
11147
  runtimeOptions,
@@ -9364,7 +11152,7 @@ async function runCLI(roots, options = {}) {
9364
11152
  };
9365
11153
  validateServices(services);
9366
11154
  if (hasHelpFlag(process.argv)) {
9367
- await renderGeneratedHelp(root, process.argv, options);
11155
+ await renderGeneratedHelp(root, process.argv, { ...options, version });
9368
11156
  return;
9369
11157
  }
9370
11158
  const program = new CommanderCommand();
@@ -9372,9 +11160,11 @@ async function runCLI(roots, options = {}) {
9372
11160
  program.exitOverride();
9373
11161
  program.showHelpAfterError();
9374
11162
  program.addHelpCommand(false);
9375
- addGlobalOptions(program);
9376
- if (options.version !== void 0) {
9377
- program.version(options.version, "--version");
11163
+ const presetsEnabled = options.presets === true;
11164
+ const globalLongOptionFlags = getGlobalLongOptionFlags(presetsEnabled);
11165
+ addGlobalOptions(program, presetsEnabled);
11166
+ if (version !== void 0) {
11167
+ program.version(version, "--version");
9378
11168
  }
9379
11169
  let lastActionCommand;
9380
11170
  const execute = async (state) => {
@@ -9382,7 +11172,13 @@ async function runCLI(roots, options = {}) {
9382
11172
  await executeCommand(state, servicesWithBuiltIns, requirementOptions, runtimeOptions);
9383
11173
  };
9384
11174
  for (const child of root.children) {
9385
- const command = createNodeCommand(child, casing, execute);
11175
+ const command = createNodeCommand(
11176
+ child,
11177
+ casing,
11178
+ globalLongOptionFlags,
11179
+ execute,
11180
+ presetsEnabled
11181
+ );
9386
11182
  if (command === null) {
9387
11183
  continue;
9388
11184
  }
@@ -9423,7 +11219,7 @@ var DCS = 144;
9423
11219
  var SOS = 152;
9424
11220
  var PM = 158;
9425
11221
  var APC = 159;
9426
- function stripAnsi2(input) {
11222
+ function stripAnsi4(input) {
9427
11223
  let output = "";
9428
11224
  for (let index = 0; index < input.length; index += 1) {
9429
11225
  const code = input.charCodeAt(index);
@@ -10112,7 +11908,7 @@ var TerminalScreen = class {
10112
11908
  cursor,
10113
11909
  size
10114
11910
  }) {
10115
- this.lines = Object.freeze(lines.map((line) => stripAnsi2(line)));
11911
+ this.lines = Object.freeze(lines.map((line) => stripAnsi4(line)));
10116
11912
  this.rawLines = Object.freeze([...rawLines]);
10117
11913
  this.cursor = Object.freeze({ ...cursor });
10118
11914
  this.size = Object.freeze({ ...size });
@@ -10197,14 +11993,14 @@ var TerminalSession = class {
10197
11993
  });
10198
11994
  });
10199
11995
  }
10200
- async type(text4) {
10201
- for (const character of text4) {
11996
+ async type(text5) {
11997
+ for (const character of text5) {
10202
11998
  await this.send(character);
10203
11999
  await sleep2(TYPE_DELAY_MS);
10204
12000
  }
10205
12001
  }
10206
- async fill(text4) {
10207
- await this.send(text4.replace(/\r?\n/g, "\r"));
12002
+ async fill(text5) {
12003
+ await this.send(text5.replace(/\r?\n/g, "\r"));
10208
12004
  }
10209
12005
  async press(key2) {
10210
12006
  await this.send(keyToSequence(key2));
@@ -10262,7 +12058,7 @@ var TerminalSession = class {
10262
12058
  });
10263
12059
  }
10264
12060
  async history(opts) {
10265
- const normalized = normalizeHistoryBuffer(stripAnsi2(this.rawBuffer));
12061
+ const normalized = normalizeHistoryBuffer(stripAnsi4(this.rawBuffer));
10266
12062
  const lines = splitHistoryLines(normalized);
10267
12063
  if (opts?.last === void 0) {
10268
12064
  return lines;
@@ -10368,7 +12164,7 @@ function isMissingFileError(error2) {
10368
12164
  return "code" in error2 && error2.code === "ENOENT";
10369
12165
  }
10370
12166
  function matchPattern(buffer, pattern) {
10371
- const clean = normalizeHistoryBuffer(stripAnsi2(buffer));
12167
+ const clean = normalizeHistoryBuffer(stripAnsi4(buffer));
10372
12168
  for (const line of clean.split("\n")) {
10373
12169
  if (typeof pattern === "string") {
10374
12170
  if (line.includes(pattern)) return line;
@@ -10628,7 +12424,7 @@ var params2 = S.Object({
10628
12424
  rows: S.Optional(S.Number({ description: "Terminal height in rows" })),
10629
12425
  observe: S.Optional(S.Boolean({ description: "Mirror PTY output to stderr" }))
10630
12426
  });
10631
- var createSession = defineCommand({
12427
+ var createSession2 = defineCommand({
10632
12428
  name: "create-session",
10633
12429
  description: "Spawn an interactive CLI in a PTY",
10634
12430
  scope: ["cli", "mcp", "sdk"],
@@ -10680,7 +12476,7 @@ var getSession = defineCommand({
10680
12476
 
10681
12477
  // ../agent-skill-config/src/configs.ts
10682
12478
  import os2 from "node:os";
10683
- import path7 from "node:path";
12479
+ import path10 from "node:path";
10684
12480
 
10685
12481
  // ../agent-defs/src/agents/claude-code.ts
10686
12482
  var claudeCodeAgent = {
@@ -11201,20 +12997,20 @@ function getConfigFormat(pathOrFormat) {
11201
12997
  }
11202
12998
  return formatRegistry[formatName];
11203
12999
  }
11204
- function detectFormat(path12) {
11205
- const ext = getExtension(path12);
13000
+ function detectFormat(path15) {
13001
+ const ext = getExtension(path15);
11206
13002
  return extensionMap[ext];
11207
13003
  }
11208
- function getExtension(path12) {
11209
- const lastDot = path12.lastIndexOf(".");
13004
+ function getExtension(path15) {
13005
+ const lastDot = path15.lastIndexOf(".");
11210
13006
  if (lastDot === -1) {
11211
13007
  return "";
11212
13008
  }
11213
- return path12.slice(lastDot).toLowerCase();
13009
+ return path15.slice(lastDot).toLowerCase();
11214
13010
  }
11215
13011
 
11216
13012
  // ../config-mutations/src/execution/path-utils.ts
11217
- import path8 from "node:path";
13013
+ import path11 from "node:path";
11218
13014
  function expandHome(targetPath, homeDir) {
11219
13015
  if (!targetPath?.startsWith("~")) {
11220
13016
  return targetPath;
@@ -11231,7 +13027,7 @@ function expandHome(targetPath, homeDir) {
11231
13027
  remainder = remainder.slice(1);
11232
13028
  }
11233
13029
  }
11234
- return remainder.length === 0 ? homeDir : path8.join(homeDir, remainder);
13030
+ return remainder.length === 0 ? homeDir : path11.join(homeDir, remainder);
11235
13031
  }
11236
13032
  function validateHomePath(targetPath) {
11237
13033
  if (typeof targetPath !== "string" || targetPath.length === 0) {
@@ -11249,12 +13045,12 @@ function resolvePath(rawPath, homeDir, pathMapper) {
11249
13045
  if (!pathMapper) {
11250
13046
  return expanded;
11251
13047
  }
11252
- const rawDirectory = path8.dirname(expanded);
13048
+ const rawDirectory = path11.dirname(expanded);
11253
13049
  const mappedDirectory = pathMapper.mapTargetDirectory({
11254
13050
  targetDirectory: rawDirectory
11255
13051
  });
11256
- const filename = path8.basename(expanded);
11257
- return filename.length === 0 ? mappedDirectory : path8.join(mappedDirectory, filename);
13052
+ const filename = path11.basename(expanded);
13053
+ return filename.length === 0 ? mappedDirectory : path11.join(mappedDirectory, filename);
11258
13054
  }
11259
13055
 
11260
13056
  // ../config-mutations/src/fs-utils.ts
@@ -11861,9 +13657,9 @@ import Mustache2 from "mustache";
11861
13657
  var originalEscape = Mustache2.escape;
11862
13658
 
11863
13659
  // ../agent-skill-config/src/templates.ts
11864
- import { readFile as readFile4, stat as stat2 } from "node:fs/promises";
11865
- import path9 from "node:path";
11866
- import { fileURLToPath as fileURLToPath2 } from "node:url";
13660
+ import { readFile as readFile6, stat as stat2 } from "node:fs/promises";
13661
+ import path12 from "node:path";
13662
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
11867
13663
 
11868
13664
  // ../agent-skill-config/src/apply.ts
11869
13665
  var UnsupportedAgentError = class extends Error {
@@ -11921,9 +13717,9 @@ async function installSkill(agentId, skill, options) {
11921
13717
 
11922
13718
  // src/commands/installer.ts
11923
13719
  import os3 from "node:os";
11924
- import path10 from "node:path";
13720
+ import path13 from "node:path";
11925
13721
  import * as nodeFs from "node:fs/promises";
11926
- import { readFile as readFile5 } from "node:fs/promises";
13722
+ import { readFile as readFile7 } from "node:fs/promises";
11927
13723
  var DEFAULT_INSTALL_AGENT = "claude-code";
11928
13724
  var DEFAULT_INSTALL_SCOPE = "local";
11929
13725
  var TERMINAL_PILOT_SKILL_NAME = "terminal-pilot";
@@ -11973,7 +13769,7 @@ async function loadTerminalPilotTemplate() {
11973
13769
  ];
11974
13770
  for (const candidate of candidates) {
11975
13771
  try {
11976
- terminalPilotTemplateCache = await readFile5(candidate, "utf8");
13772
+ terminalPilotTemplateCache = await readFile7(candidate, "utf8");
11977
13773
  return terminalPilotTemplateCache;
11978
13774
  } catch (error2) {
11979
13775
  if (!isNotFoundError2(error2)) {
@@ -11988,7 +13784,7 @@ function resolveHomeRelativePath(targetPath, homeDir) {
11988
13784
  return homeDir;
11989
13785
  }
11990
13786
  if (targetPath.startsWith("~/")) {
11991
- return path10.join(homeDir, targetPath.slice(2));
13787
+ return path13.join(homeDir, targetPath.slice(2));
11992
13788
  }
11993
13789
  return targetPath;
11994
13790
  }
@@ -11998,12 +13794,12 @@ function getSkillFolderWithHome(agent, scope, cwd, homeDir) {
11998
13794
  throwUnsupportedAgent(agent);
11999
13795
  }
12000
13796
  return {
12001
- displayPath: path10.join(
13797
+ displayPath: path13.join(
12002
13798
  scope === "global" ? config.globalSkillDir : config.localSkillDir,
12003
13799
  TERMINAL_PILOT_SKILL_NAME
12004
13800
  ),
12005
- fullPath: path10.join(
12006
- scope === "global" ? resolveHomeRelativePath(config.globalSkillDir, homeDir) : path10.resolve(cwd, config.localSkillDir),
13801
+ fullPath: path13.join(
13802
+ scope === "global" ? resolveHomeRelativePath(config.globalSkillDir, homeDir) : path13.resolve(cwd, config.localSkillDir),
12007
13803
  TERMINAL_PILOT_SKILL_NAME
12008
13804
  )
12009
13805
  };
@@ -12195,17 +13991,17 @@ function colorsEqual(left, right) {
12195
13991
  }
12196
13992
  return false;
12197
13993
  }
12198
- function pushRun(runs, style, text4) {
12199
- if (text4.length === 0) {
13994
+ function pushRun(runs, style, text5) {
13995
+ if (text5.length === 0) {
12200
13996
  return;
12201
13997
  }
12202
13998
  const previous = runs.at(-1);
12203
- if (previous && text4 !== "\n" && previous.text !== "\n" && stylesEqual(previous, style)) {
12204
- previous.text += text4;
13999
+ if (previous && text5 !== "\n" && previous.text !== "\n" && stylesEqual(previous, style)) {
14000
+ previous.text += text5;
12205
14001
  return;
12206
14002
  }
12207
14003
  runs.push({
12208
- text: text4,
14004
+ text: text5,
12209
14005
  fg: style.fg,
12210
14006
  bg: style.bg,
12211
14007
  bold: style.bold,
@@ -12407,18 +14203,18 @@ function parseAnsi2(input) {
12407
14203
  import { Resvg } from "@resvg/resvg-js";
12408
14204
 
12409
14205
  // ../terminal-png/src/font.ts
12410
- import { readFileSync } from "node:fs";
14206
+ import { readFileSync as readFileSync2 } from "node:fs";
12411
14207
  import { createRequire as createRequire2 } from "node:module";
12412
14208
  import { dirname as dirname2, join as join2 } from "node:path";
12413
- import { fileURLToPath as fileURLToPath3 } from "node:url";
14209
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
12414
14210
  var require2 = createRequire2(import.meta.url);
12415
14211
  var fontPackageRoot = dirname2(require2.resolve("jetbrains-mono/package.json"));
12416
14212
  var webfontRoot = join2(fontPackageRoot, "fonts/webfonts");
12417
14213
  function readWebfontBase64(filename) {
12418
- return readFileSync(join2(webfontRoot, filename)).toString("base64");
14214
+ return readFileSync2(join2(webfontRoot, filename)).toString("base64");
12419
14215
  }
12420
14216
  function resolveAssetPath(filename) {
12421
- return fileURLToPath3(new URL(`../assets/${filename}`, import.meta.url));
14217
+ return fileURLToPath4(new URL(`../assets/${filename}`, import.meta.url));
12422
14218
  }
12423
14219
  function createFontFace(base64, weight, style) {
12424
14220
  return `@font-face {
@@ -12804,10 +14600,10 @@ function measureLines(lines) {
12804
14600
  0
12805
14601
  );
12806
14602
  }
12807
- function displayWidth(text4) {
14603
+ function displayWidth(text5) {
12808
14604
  const segmenter = new Intl.Segmenter();
12809
14605
  let width = 0;
12810
- for (const { segment } of segmenter.segment(text4)) {
14606
+ for (const { segment } of segmenter.segment(text5)) {
12811
14607
  const cp = segment.codePointAt(0);
12812
14608
  width += cp !== void 0 && isWideCodePoint(cp) ? 2 : 1;
12813
14609
  }
@@ -13071,7 +14867,7 @@ var waitForExit2 = defineCommand({
13071
14867
  var children = [
13072
14868
  install,
13073
14869
  uninstall,
13074
- createSession,
14870
+ createSession2,
13075
14871
  fill,
13076
14872
  type,
13077
14873
  pressKey,
@@ -13114,9 +14910,9 @@ async function isDirectExecution(argv) {
13114
14910
  return false;
13115
14911
  }
13116
14912
  try {
13117
- const modulePath = fileURLToPath4(import.meta.url);
14913
+ const modulePath = fileURLToPath5(import.meta.url);
13118
14914
  const [resolvedEntryPoint, resolvedModulePath] = await Promise.all([
13119
- realpath(path11.resolve(entryPoint)),
14915
+ realpath(path14.resolve(entryPoint)),
13120
14916
  realpath(modulePath)
13121
14917
  ]);
13122
14918
  return resolvedEntryPoint === resolvedModulePath;