terminal-pilot 0.0.27 → 0.0.29

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 (57) hide show
  1. package/dist/cli.js +1224 -206
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.js +87 -6
  4. package/dist/commands/close-session.js.map +2 -2
  5. package/dist/commands/create-session.js +94 -9
  6. package/dist/commands/create-session.js.map +2 -2
  7. package/dist/commands/fill.js +87 -6
  8. package/dist/commands/fill.js.map +2 -2
  9. package/dist/commands/get-session.js +87 -6
  10. package/dist/commands/get-session.js.map +2 -2
  11. package/dist/commands/index.js +482 -118
  12. package/dist/commands/index.js.map +4 -4
  13. package/dist/commands/install.js +108 -48
  14. package/dist/commands/install.js.map +4 -4
  15. package/dist/commands/installer.js +88 -42
  16. package/dist/commands/installer.js.map +4 -4
  17. package/dist/commands/list-sessions.js +80 -4
  18. package/dist/commands/list-sessions.js.map +2 -2
  19. package/dist/commands/press-key.js +160 -71
  20. package/dist/commands/press-key.js.map +3 -3
  21. package/dist/commands/read-history.js +95 -7
  22. package/dist/commands/read-history.js.map +2 -2
  23. package/dist/commands/read-screen.js +87 -6
  24. package/dist/commands/read-screen.js.map +2 -2
  25. package/dist/commands/resize.js +89 -8
  26. package/dist/commands/resize.js.map +2 -2
  27. package/dist/commands/runtime.js +66 -4
  28. package/dist/commands/runtime.js.map +2 -2
  29. package/dist/commands/screenshot.js +242 -23
  30. package/dist/commands/screenshot.js.map +3 -3
  31. package/dist/commands/send-signal.js +87 -6
  32. package/dist/commands/send-signal.js.map +2 -2
  33. package/dist/commands/type.js +87 -6
  34. package/dist/commands/type.js.map +2 -2
  35. package/dist/commands/uninstall.js +102 -42
  36. package/dist/commands/uninstall.js.map +4 -4
  37. package/dist/commands/wait-for-exit.js +93 -7
  38. package/dist/commands/wait-for-exit.js.map +2 -2
  39. package/dist/commands/wait-for.js +104 -8
  40. package/dist/commands/wait-for.js.map +3 -3
  41. package/dist/index.js +52 -1
  42. package/dist/index.js.map +2 -2
  43. package/dist/keys.d.ts +1 -0
  44. package/dist/keys.js +15 -0
  45. package/dist/keys.js.map +2 -2
  46. package/dist/terminal-buffer.d.ts +2 -0
  47. package/dist/terminal-buffer.js +38 -1
  48. package/dist/terminal-buffer.js.map +2 -2
  49. package/dist/terminal-pilot.js +52 -1
  50. package/dist/terminal-pilot.js.map +2 -2
  51. package/dist/terminal-session.js +52 -1
  52. package/dist/terminal-session.js.map +2 -2
  53. package/dist/testing/cli-repl.js +1229 -211
  54. package/dist/testing/cli-repl.js.map +4 -4
  55. package/dist/testing/qa-cli.js +1229 -211
  56. package/dist/testing/qa-cli.js.map +4 -4
  57. package/package.json +3 -2
package/dist/cli.js CHANGED
@@ -65,12 +65,12 @@ var styleNames = Object.keys(ansiStyles);
65
65
  function replaceAll(value, search, replacement) {
66
66
  return value.split(search).join(replacement);
67
67
  }
68
- function applyStyles(text5, styles) {
68
+ function applyStyles(text4, styles) {
69
69
  if (!supportsColor() || styles.length === 0) {
70
- return text5;
70
+ return text4;
71
71
  }
72
72
  const open = styles.map((style) => style.open).join("");
73
- const output = text5.includes(reset) ? replaceAll(text5, reset, `${reset}${open}`) : text5;
73
+ const output = text4.includes(reset) ? replaceAll(text4, reset, `${reset}${open}`) : text4;
74
74
  return `${open}${output}${reset}`;
75
75
  }
76
76
  function clampRgb(value) {
@@ -114,7 +114,7 @@ function bgRgbStyle(red, green, blue) {
114
114
  };
115
115
  }
116
116
  function createColor(styles = []) {
117
- const builder = ((text5) => applyStyles(String(text5), styles));
117
+ const builder = ((text4) => applyStyles(String(text4), styles));
118
118
  for (const name of styleNames) {
119
119
  Object.defineProperty(builder, name, {
120
120
  configurable: true,
@@ -196,24 +196,24 @@ function createPalette(activeBrand, mode) {
196
196
  const number2 = isPurple ? color.hex("#0077cc") : active2;
197
197
  return withStyles(
198
198
  {
199
- header: (text5) => active2.bold(text5),
200
- divider: (text5) => color.hex("#666666")(text5),
201
- prompt: (text5) => prompt2.bold(text5),
202
- number: (text5) => number2.bold(text5),
203
- intro: (text5) => color.bgHex(activeBrand.primary).white(` ${getThemeConfig().label} - ${text5} `),
199
+ header: (text4) => active2.bold(text4),
200
+ divider: (text4) => color.hex("#666666")(text4),
201
+ prompt: (text4) => prompt2.bold(text4),
202
+ number: (text4) => number2.bold(text4),
203
+ intro: (text4) => color.bgHex(activeBrand.primary).white(` ${getThemeConfig().label} - ${text4} `),
204
204
  get resolvedSymbol() {
205
205
  return active2("\u25C7");
206
206
  },
207
207
  get errorSymbol() {
208
208
  return color.hex("#cc0000")("\u25A0");
209
209
  },
210
- accent: (text5) => prompt2.bold(text5),
211
- muted: (text5) => color.hex("#666666")(text5),
212
- success: (text5) => color.hex("#008800")(text5),
213
- warning: (text5) => color.hex("#cc6600")(text5),
214
- error: (text5) => color.hex("#cc0000")(text5),
215
- info: (text5) => active2(text5),
216
- badge: (text5) => color.bgHex("#cc6600").white(` ${text5} `)
210
+ accent: (text4) => prompt2.bold(text4),
211
+ muted: (text4) => color.hex("#666666")(text4),
212
+ success: (text4) => color.hex("#008800")(text4),
213
+ warning: (text4) => color.hex("#cc6600")(text4),
214
+ error: (text4) => color.hex("#cc0000")(text4),
215
+ info: (text4) => active2(text4),
216
+ badge: (text4) => color.bgHex("#cc6600").white(` ${text4} `)
217
217
  },
218
218
  {
219
219
  accent: { fg: isPurple ? "#006699" : activeBrand.primary, bold: true },
@@ -232,24 +232,24 @@ function createPalette(activeBrand, mode) {
232
232
  const number = isPurple ? color.cyanBright : active;
233
233
  return withStyles(
234
234
  {
235
- header: (text5) => activeBright.bold(text5),
236
- divider: (text5) => color.dim(text5),
237
- prompt: (text5) => prompt(text5),
238
- number: (text5) => number(text5),
239
- intro: (text5) => activeBackground.white(` ${getThemeConfig().label} - ${text5} `),
235
+ header: (text4) => activeBright.bold(text4),
236
+ divider: (text4) => color.dim(text4),
237
+ prompt: (text4) => prompt(text4),
238
+ number: (text4) => number(text4),
239
+ intro: (text4) => activeBackground.white(` ${getThemeConfig().label} - ${text4} `),
240
240
  get resolvedSymbol() {
241
241
  return active("\u25C7");
242
242
  },
243
243
  get errorSymbol() {
244
244
  return color.red("\u25A0");
245
245
  },
246
- accent: (text5) => prompt(text5),
247
- muted: (text5) => color.dim(text5),
248
- success: (text5) => color.green(text5),
249
- warning: (text5) => color.yellow(text5),
250
- error: (text5) => color.red(text5),
251
- info: (text5) => active(text5),
252
- badge: (text5) => color.bgYellow.black(` ${text5} `)
246
+ accent: (text4) => prompt(text4),
247
+ muted: (text4) => color.dim(text4),
248
+ success: (text4) => color.green(text4),
249
+ warning: (text4) => color.yellow(text4),
250
+ error: (text4) => color.red(text4),
251
+ info: (text4) => active(text4),
252
+ badge: (text4) => color.bgYellow.black(` ${text4} `)
253
253
  },
254
254
  {
255
255
  accent: { fg: isPurple ? "cyan" : activeBrand.primary, bold: true },
@@ -266,11 +266,11 @@ var light = createPalette(brands.purple, "light");
266
266
 
267
267
  // ../toolcraft-design/src/tokens/typography.ts
268
268
  var typography = {
269
- bold: (text5) => color.bold(text5),
270
- dim: (text5) => color.dim(text5),
271
- italic: (text5) => color.italic(text5),
272
- underline: (text5) => color.underline(text5),
273
- strikethrough: (text5) => color.strikethrough(text5)
269
+ bold: (text4) => color.bold(text4),
270
+ dim: (text4) => color.dim(text4),
271
+ italic: (text4) => color.italic(text4),
272
+ underline: (text4) => color.underline(text4),
273
+ strikethrough: (text4) => color.strikethrough(text4)
274
274
  };
275
275
 
276
276
  // ../toolcraft-design/src/tokens/widths.ts
@@ -541,7 +541,7 @@ function renderMarkdownInline2(value) {
541
541
  return stripAnsi(value).replaceAll("\r\n", " ").replaceAll("\n", " ").replaceAll("\r", " ");
542
542
  }
543
543
  function writeTerminalMessage(msg, {
544
- symbol = color.gray("\u2502"),
544
+ symbol: symbol2 = color.gray("\u2502"),
545
545
  secondarySymbol = color.gray("\u2502"),
546
546
  spacing: spacing2 = 1,
547
547
  withGuide = true
@@ -549,7 +549,7 @@ function writeTerminalMessage(msg, {
549
549
  const lines = [];
550
550
  const showGuide = withGuide !== false;
551
551
  const contentLines = msg.split("\n");
552
- const prefix = showGuide ? `${symbol} ` : "";
552
+ const prefix = showGuide ? `${symbol2} ` : "";
553
553
  const continuationPrefix = showGuide ? `${secondarySymbol} ` : "";
554
554
  const emptyGuide = showGuide ? secondarySymbol : "";
555
555
  for (let index = 0; index < spacing2; index += 1) {
@@ -563,7 +563,7 @@ function writeTerminalMessage(msg, {
563
563
  if (firstLine.length > 0) {
564
564
  lines.push(`${prefix}${firstLine}`);
565
565
  } else {
566
- lines.push(showGuide ? symbol : "");
566
+ lines.push(showGuide ? symbol2 : "");
567
567
  }
568
568
  for (const line of continuationLines) {
569
569
  if (line.length > 0) {
@@ -713,12 +713,12 @@ function createLogger(emitter) {
713
713
  log.message(`${label}
714
714
  ${value}`, { symbol: symbols.errorResolved });
715
715
  },
716
- message(message2, symbol) {
716
+ message(message2, symbol2) {
717
717
  if (emitter) {
718
718
  emitter(message2);
719
719
  return;
720
720
  }
721
- log.message(message2, { symbol: symbol ?? color.gray("\u2502") });
721
+ log.message(message2, { symbol: symbol2 ?? color.gray("\u2502") });
722
722
  }
723
723
  };
724
724
  }
@@ -1521,18 +1521,18 @@ function getStandalone(template, tagStart, tagEnd, kind) {
1521
1521
  if (!isWhitespace3(template.slice(lineStart, tagStart))) {
1522
1522
  return void 0;
1523
1523
  }
1524
- let cursor = tagEnd;
1525
- while (cursor < template.length && (template[cursor] === " " || template[cursor] === " ")) {
1526
- cursor += 1;
1524
+ let cursor2 = tagEnd;
1525
+ while (cursor2 < template.length && (template[cursor2] === " " || template[cursor2] === " ")) {
1526
+ cursor2 += 1;
1527
1527
  }
1528
- if (template.startsWith("\r\n", cursor)) {
1529
- return { lineStart, nextIndex: cursor + 2 };
1528
+ if (template.startsWith("\r\n", cursor2)) {
1529
+ return { lineStart, nextIndex: cursor2 + 2 };
1530
1530
  }
1531
- if (template[cursor] === "\n") {
1532
- return { lineStart, nextIndex: cursor + 1 };
1531
+ if (template[cursor2] === "\n") {
1532
+ return { lineStart, nextIndex: cursor2 + 1 };
1533
1533
  }
1534
- if (cursor === template.length) {
1535
- return { lineStart, nextIndex: cursor };
1534
+ if (cursor2 === template.length) {
1535
+ return { lineStart, nextIndex: cursor2 };
1536
1536
  }
1537
1537
  return void 0;
1538
1538
  }
@@ -1630,13 +1630,13 @@ function lookup(context, name) {
1630
1630
  if (name === ".") {
1631
1631
  return { hit: true, value: callLambda(context.view, context.view) };
1632
1632
  }
1633
- let cursor = context;
1634
- while (cursor !== void 0) {
1635
- const result = name.includes(".") ? lookupDotted(cursor.view, name) : lookupName(cursor.view, name);
1633
+ let cursor2 = context;
1634
+ while (cursor2 !== void 0) {
1635
+ const result = name.includes(".") ? lookupDotted(cursor2.view, name) : lookupName(cursor2.view, name);
1636
1636
  if (result.hit) {
1637
- return { hit: true, value: callLambda(result.value, cursor.view) };
1637
+ return { hit: true, value: callLambda(result.value, cursor2.view) };
1638
1638
  }
1639
- cursor = cursor.parent;
1639
+ cursor2 = cursor2.parent;
1640
1640
  }
1641
1641
  return { hit: false, value: void 0 };
1642
1642
  }
@@ -1800,6 +1800,12 @@ function hasProperty(value, key2) {
1800
1800
  import { spawn } from "node:child_process";
1801
1801
  import process2 from "node:process";
1802
1802
 
1803
+ // ../frontmatter/src/parse.ts
1804
+ import { LineCounter, parse, parseDocument } from "yaml";
1805
+
1806
+ // ../frontmatter/src/stringify.ts
1807
+ import { stringify } from "yaml";
1808
+
1803
1809
  // ../toolcraft-design/src/acp/writer.ts
1804
1810
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1805
1811
  var storage = new AsyncLocalStorage2();
@@ -1820,11 +1826,629 @@ var REGION_MODAL = 1 << 4;
1820
1826
  var REGION_TOAST = 1 << 5;
1821
1827
  var REGION_ALL = REGION_HEADER | REGION_LIST | REGION_DETAIL | REGION_FOOTER | REGION_MODAL | REGION_TOAST;
1822
1828
 
1823
- // ../toolcraft-design/src/prompts/index.ts
1824
- import * as clack from "@clack/prompts";
1829
+ // ../toolcraft-design/src/prompts/interactive/glyphs.ts
1830
+ function supportsUnicode() {
1831
+ if (!process.platform.startsWith("win")) {
1832
+ return process.env.TERM !== "linux";
1833
+ }
1834
+ return Boolean(
1835
+ process.env.CI || process.env.WT_SESSION || process.env.TERMINUS_SUBLIME || process.env.ConEmuTask === "{cmd::Cmder}" || process.env.TERM_PROGRAM === "Terminus-Sublime" || process.env.TERM_PROGRAM === "vscode" || process.env.TERM === "xterm-256color" || process.env.TERM === "alacritty" || process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm"
1836
+ );
1837
+ }
1838
+ var UNICODE = supportsUnicode();
1839
+ function glyph(unicode, ascii) {
1840
+ return UNICODE ? unicode : ascii;
1841
+ }
1842
+ var GLYPHS = {
1843
+ stepActive: glyph("\u25C6", "*"),
1844
+ stepCancel: glyph("\u25A0", "x"),
1845
+ stepError: glyph("\u25B2", "x"),
1846
+ stepSubmit: glyph("\u25C7", "o"),
1847
+ barStart: glyph("\u250C", "T"),
1848
+ bar: glyph("\u2502", "|"),
1849
+ barEnd: glyph("\u2514", "-"),
1850
+ radioActive: glyph("\u25CF", ">"),
1851
+ radioInactive: glyph("\u25CB", " "),
1852
+ checkboxActive: glyph("\u25FB", "[ ]"),
1853
+ checkboxSelected: glyph("\u25FC", "[+]"),
1854
+ checkboxInactive: glyph("\u25FB", "[ ]"),
1855
+ passwordMask: glyph("\u2022", "*"),
1856
+ ellipsis: "..."
1857
+ };
1858
+ function symbol(state) {
1859
+ if (state === "cancel") return color.red(GLYPHS.stepCancel);
1860
+ if (state === "error") return color.yellow(GLYPHS.stepError);
1861
+ if (state === "submit") return color.green(GLYPHS.stepSubmit);
1862
+ return color.cyan(GLYPHS.stepActive);
1863
+ }
1864
+ function symbolBar(state) {
1865
+ if (state === "cancel") return color.red(GLYPHS.bar);
1866
+ if (state === "error") return color.yellow(GLYPHS.bar);
1867
+ if (state === "submit") return color.green(GLYPHS.bar);
1868
+ return color.cyan(GLYPHS.bar);
1869
+ }
1870
+
1871
+ // ../toolcraft-design/src/prompts/interactive/core.ts
1872
+ import { EventEmitter } from "node:events";
1873
+ import * as readline2 from "node:readline";
1874
+
1875
+ // ../toolcraft-design/src/prompts/interactive/cancel-symbol.ts
1876
+ var CANCEL = /* @__PURE__ */ Symbol.for("poe.cancel");
1877
+ function isCancel(value) {
1878
+ return value === CANCEL;
1879
+ }
1880
+
1881
+ // ../toolcraft-design/src/prompts/interactive/keys.ts
1882
+ var aliases = {
1883
+ k: "up",
1884
+ j: "down",
1885
+ h: "left",
1886
+ l: "right"
1887
+ };
1888
+ var keyActions = {
1889
+ up: "up",
1890
+ down: "down",
1891
+ left: "left",
1892
+ right: "right",
1893
+ space: "space",
1894
+ return: "enter",
1895
+ enter: "enter",
1896
+ escape: "cancel"
1897
+ };
1898
+ function mapKey(name, char) {
1899
+ if (char === "") {
1900
+ return "cancel";
1901
+ }
1902
+ if (char === " ") {
1903
+ return "space";
1904
+ }
1905
+ if (!name) {
1906
+ return void 0;
1907
+ }
1908
+ return keyActions[name] ?? aliases[name];
1909
+ }
1910
+
1911
+ // ../toolcraft-design/src/prompts/interactive/wrap.ts
1912
+ import { wrapAnsi } from "fast-wrap-ansi";
1913
+ import stringWidth from "fast-string-width";
1914
+ function getColumns(output) {
1915
+ return Math.max(1, output.columns ?? 80);
1916
+ }
1917
+ function getRows(output) {
1918
+ return Math.max(1, output.rows ?? 20);
1919
+ }
1920
+ function wrapFrame(output, frame) {
1921
+ return wrapAnsi(frame, getColumns(output), { hard: true, trim: false });
1922
+ }
1923
+
1924
+ // ../toolcraft-design/src/prompts/interactive/core.ts
1925
+ var cursor = {
1926
+ hide: "\x1B[?25l",
1927
+ show: "\x1B[?25h",
1928
+ move: (x, y) => {
1929
+ let output = "";
1930
+ if (x < 0) output += `\x1B[${-x}D`;
1931
+ if (x > 0) output += `\x1B[${x}C`;
1932
+ if (y < 0) output += `\x1B[${-y}A`;
1933
+ if (y > 0) output += `\x1B[${y}B`;
1934
+ return output;
1935
+ }
1936
+ };
1937
+ var erase = {
1938
+ down: "\x1B[J"
1939
+ };
1940
+ var Prompt = class extends EventEmitter {
1941
+ state = "initial";
1942
+ value;
1943
+ error = "";
1944
+ userInput = "";
1945
+ _cursor = 0;
1946
+ input;
1947
+ output;
1948
+ renderFrame;
1949
+ validate;
1950
+ signal;
1951
+ trackValue;
1952
+ previousFrame = "";
1953
+ readlineInterface;
1954
+ abortListener;
1955
+ closed = false;
1956
+ constructor(opts, trackValue = true) {
1957
+ super();
1958
+ this.input = opts.input ?? process.stdin;
1959
+ this.output = opts.output ?? process.stdout;
1960
+ this.renderFrame = opts.render;
1961
+ this.validate = opts.validate;
1962
+ this.signal = opts.signal;
1963
+ this.value = opts.initialValue;
1964
+ this.trackValue = trackValue;
1965
+ this.userInput = opts.initialUserInput ?? "";
1966
+ this._cursor = this.userInput.length;
1967
+ }
1968
+ get cursor() {
1969
+ return this._cursor;
1970
+ }
1971
+ prompt() {
1972
+ if (this.signal?.aborted) {
1973
+ this.state = "cancel";
1974
+ return Promise.resolve(CANCEL);
1975
+ }
1976
+ if (this.input.isTTY !== true) {
1977
+ return this.promptNonTty();
1978
+ }
1979
+ return new Promise((resolve) => {
1980
+ const onSubmit = (value) => resolve(value);
1981
+ const onCancel = () => resolve(CANCEL);
1982
+ this.once("submit", onSubmit);
1983
+ this.once("cancel", onCancel);
1984
+ this.abortListener = () => {
1985
+ this.state = "cancel";
1986
+ this.emit("finalize");
1987
+ this.render();
1988
+ this.close();
1989
+ };
1990
+ this.signal?.addEventListener("abort", this.abortListener, { once: true });
1991
+ this.readlineInterface = readline2.createInterface({
1992
+ input: this.input,
1993
+ output: void 0,
1994
+ tabSize: 2,
1995
+ prompt: "",
1996
+ escapeCodeTimeout: 50,
1997
+ terminal: true
1998
+ });
1999
+ readline2.emitKeypressEvents(this.input, this.readlineInterface);
2000
+ this.readlineInterface.prompt();
2001
+ this.input.on("keypress", this.onKeypress);
2002
+ if (this.input.setRawMode) {
2003
+ this.input.setRawMode(true);
2004
+ }
2005
+ this.output.on("resize", this.render);
2006
+ this.render();
2007
+ });
2008
+ }
2009
+ promptNonTty() {
2010
+ return Promise.reject(new Error("Interactive prompt requires a TTY. Set POE_NO_PROMPT=1 to accept defaults non-interactively."));
2011
+ }
2012
+ readNonTtyLine() {
2013
+ return new Promise((resolve) => {
2014
+ const rl = readline2.createInterface({ input: this.input, terminal: false });
2015
+ let settled = false;
2016
+ const settle = (value) => {
2017
+ if (settled) {
2018
+ return;
2019
+ }
2020
+ settled = true;
2021
+ rl.close();
2022
+ resolve(value);
2023
+ };
2024
+ rl.once("line", settle);
2025
+ rl.once("close", () => settle(rl.line));
2026
+ });
2027
+ }
2028
+ setValue(value) {
2029
+ this.value = value;
2030
+ this.emit("value", value);
2031
+ }
2032
+ setError(message2) {
2033
+ this.error = message2;
2034
+ }
2035
+ setUserInput(value) {
2036
+ this.userInput = value;
2037
+ this._cursor = Math.min(this._cursor, this.userInput.length);
2038
+ this.emit("userInput", this.userInput);
2039
+ }
2040
+ clearUserInput() {
2041
+ this.userInput = "";
2042
+ this._cursor = 0;
2043
+ this.emit("userInput", this.userInput);
2044
+ }
2045
+ onKeypress = (char, key2 = {}) => {
2046
+ let action = mapKey(key2.name, char);
2047
+ if (this.trackValue && char && char >= " " && key2.name !== "return" && key2.name !== "enter" && key2.name !== "escape") {
2048
+ action = void 0;
2049
+ }
2050
+ if (this.trackValue && action !== "enter") {
2051
+ this.updateTrackedInput(char, key2, action);
2052
+ }
2053
+ if (this.state === "error") {
2054
+ this.state = "active";
2055
+ this.error = "";
2056
+ }
2057
+ if (!this.trackValue && action) {
2058
+ this.emit("cursor", action);
2059
+ } else if (this.trackValue && action && action !== "enter") {
2060
+ this.emit("cursor", action);
2061
+ }
2062
+ if (char && /^[yn]$/i.test(char)) {
2063
+ this.emit("confirm", char.toLowerCase() === "y");
2064
+ }
2065
+ if (char) {
2066
+ this.emit("key", char.toLowerCase(), key2);
2067
+ }
2068
+ if (action === "enter") {
2069
+ const error3 = this.validate?.(this.value);
2070
+ if (error3) {
2071
+ this.error = error3 instanceof Error ? error3.message : error3;
2072
+ this.state = "error";
2073
+ } else {
2074
+ this.state = "submit";
2075
+ }
2076
+ }
2077
+ if (action === "cancel") {
2078
+ this.state = "cancel";
2079
+ }
2080
+ if (this.state === "submit" || this.state === "cancel") {
2081
+ this.emit("finalize");
2082
+ }
2083
+ this.render();
2084
+ if (this.state === "submit" || this.state === "cancel") {
2085
+ this.close();
2086
+ }
2087
+ };
2088
+ updateTrackedInput(char, key2, action) {
2089
+ if (key2.ctrl) {
2090
+ if (key2.name === "a") {
2091
+ this._cursor = 0;
2092
+ return;
2093
+ }
2094
+ if (key2.name === "e") {
2095
+ this._cursor = this.userInput.length;
2096
+ return;
2097
+ }
2098
+ if (key2.name === "u") {
2099
+ this.userInput = this.userInput.slice(this._cursor);
2100
+ this._cursor = 0;
2101
+ this.emit("userInput", this.userInput);
2102
+ return;
2103
+ }
2104
+ if (key2.name === "k") {
2105
+ this.userInput = this.userInput.slice(0, this._cursor);
2106
+ this.emit("userInput", this.userInput);
2107
+ return;
2108
+ }
2109
+ }
2110
+ if (action === "left") {
2111
+ this._cursor = Math.max(0, this._cursor - 1);
2112
+ return;
2113
+ }
2114
+ if (action === "right") {
2115
+ this._cursor = Math.min(this.userInput.length, this._cursor + 1);
2116
+ return;
2117
+ }
2118
+ if (action === "cancel" || action === "up" || action === "down" || action === "space") {
2119
+ return;
2120
+ }
2121
+ if (key2.name === "backspace" || char === "\b" || char === "\x7F") {
2122
+ if (this._cursor > 0) {
2123
+ this.userInput = `${this.userInput.slice(0, this._cursor - 1)}${this.userInput.slice(this._cursor)}`;
2124
+ this._cursor -= 1;
2125
+ this.emit("userInput", this.userInput);
2126
+ }
2127
+ return;
2128
+ }
2129
+ if (key2.name === "delete") {
2130
+ if (this._cursor < this.userInput.length) {
2131
+ this.userInput = `${this.userInput.slice(0, this._cursor)}${this.userInput.slice(this._cursor + 1)}`;
2132
+ this.emit("userInput", this.userInput);
2133
+ }
2134
+ return;
2135
+ }
2136
+ if (!char || char < " " || key2.ctrl) {
2137
+ return;
2138
+ }
2139
+ this.userInput = `${this.userInput.slice(0, this._cursor)}${char}${this.userInput.slice(this._cursor)}`;
2140
+ this._cursor += char.length;
2141
+ this.emit("userInput", this.userInput);
2142
+ }
2143
+ render = () => {
2144
+ if (this.closed) {
2145
+ return;
2146
+ }
2147
+ const frame = wrapFrame(this.output, this.renderFrame(this) ?? "");
2148
+ if (frame === this.previousFrame) {
2149
+ return;
2150
+ }
2151
+ if (!this.previousFrame) {
2152
+ this.output.write(`${cursor.hide}${frame}`);
2153
+ this.previousFrame = frame;
2154
+ if (this.state === "initial") {
2155
+ this.state = "active";
2156
+ }
2157
+ return;
2158
+ }
2159
+ const previousLineCount = this.previousFrame.split("\n").length - 1;
2160
+ this.output.write(`${cursor.move(-999, -previousLineCount)}${erase.down}${frame}`);
2161
+ this.previousFrame = frame;
2162
+ };
2163
+ close() {
2164
+ if (this.closed) {
2165
+ return;
2166
+ }
2167
+ this.closed = true;
2168
+ this.input.removeListener("keypress", this.onKeypress);
2169
+ this.output.removeListener("resize", this.render);
2170
+ if (this.abortListener) {
2171
+ this.signal?.removeEventListener("abort", this.abortListener);
2172
+ }
2173
+ this.output.write(`${cursor.show}
2174
+ `);
2175
+ if (!process.platform.startsWith("win") && this.input.setRawMode) {
2176
+ this.input.setRawMode(false);
2177
+ }
2178
+ this.readlineInterface?.close();
2179
+ this.input.unpipe?.();
2180
+ if (this.state === "cancel") {
2181
+ this.emit("cancel");
2182
+ } else {
2183
+ this.emit("submit", this.value);
2184
+ }
2185
+ this.removeAllListeners();
2186
+ }
2187
+ };
2188
+
2189
+ // ../toolcraft-design/src/prompts/interactive/confirm.ts
2190
+ var ConfirmPrompt = class extends Prompt {
2191
+ constructor(opts) {
2192
+ super({
2193
+ ...opts,
2194
+ initialValue: opts.initialValue ?? true,
2195
+ render: (prompt) => renderConfirmPrompt(prompt, opts)
2196
+ }, false);
2197
+ this.on("confirm", (value) => {
2198
+ this.setValue(value);
2199
+ this.state = "submit";
2200
+ this.emit("finalize");
2201
+ this.render();
2202
+ this.close();
2203
+ });
2204
+ this.on("cursor", (action) => {
2205
+ if (action === "up" || action === "down" || action === "left" || action === "right") {
2206
+ this.setValue(!this.value);
2207
+ }
2208
+ });
2209
+ }
2210
+ promptNonTty() {
2211
+ if (process.env.POE_NO_PROMPT === "1") {
2212
+ return Promise.resolve(this.value ?? true);
2213
+ }
2214
+ return super.promptNonTty();
2215
+ }
2216
+ };
2217
+ function choices(value) {
2218
+ const yes = value ? `${color.green(GLYPHS.radioActive)} ${color.bold("Yes")}` : `${color.dim(GLYPHS.radioInactive)} ${color.dim("Yes")}`;
2219
+ const no = value ? `${color.dim(GLYPHS.radioInactive)} ${color.dim("No")}` : `${color.green(GLYPHS.radioActive)} ${color.bold("No")}`;
2220
+ return `${yes} ${color.dim("/")} ${no}`;
2221
+ }
2222
+ function renderConfirmPrompt(prompt, opts) {
2223
+ if (prompt.state === "submit") {
2224
+ return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${opts.message}
2225
+ ${color.gray(GLYPHS.bar)} ${color.dim(prompt.value ? "Yes" : "No")}
2226
+ ${color.green(GLYPHS.barEnd)}`;
2227
+ }
2228
+ if (prompt.state === "cancel") {
2229
+ return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${opts.message}
2230
+ ${color.gray(GLYPHS.bar)} ${color.dim.strikethrough(prompt.value ? "Yes" : "No")}
2231
+ ${color.red(GLYPHS.barEnd)}`;
2232
+ }
2233
+ return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${opts.message}
2234
+ ${symbolBar(prompt.state)} ${choices(prompt.value)}
2235
+ ${color.cyan(GLYPHS.barEnd)}`;
2236
+ }
2237
+ function confirmPrompt(opts) {
2238
+ return new ConfirmPrompt(opts).prompt();
2239
+ }
2240
+
2241
+ // ../toolcraft-design/src/prompts/interactive/pagination.ts
2242
+ import { wrapAnsi as wrapAnsi2 } from "fast-wrap-ansi";
2243
+ function countLines(values) {
2244
+ return values.reduce((sum, value) => sum + value.split("\n").length, 0);
2245
+ }
2246
+ function trimToRows(values, cursorOffset, rows, hasTop, hasBottom) {
2247
+ const output = [...values];
2248
+ while (countLines(output) > rows && output.length > 1) {
2249
+ const removeFromTop = hasTop && cursorOffset > 0;
2250
+ const removeFromBottom = hasBottom && cursorOffset < output.length - 1;
2251
+ if (removeFromTop) {
2252
+ output.shift();
2253
+ cursorOffset -= 1;
2254
+ } else if (removeFromBottom) {
2255
+ output.pop();
2256
+ } else {
2257
+ output.pop();
2258
+ }
2259
+ }
2260
+ return output;
2261
+ }
2262
+ function limitOptions(opts) {
2263
+ const {
2264
+ cursor: cursor2,
2265
+ options,
2266
+ style,
2267
+ output,
2268
+ maxItems = Number.POSITIVE_INFINITY,
2269
+ columnPadding = 0,
2270
+ rowPadding = 4
2271
+ } = opts;
2272
+ if (options.length === 0) {
2273
+ return [];
2274
+ }
2275
+ const columns = Math.max(1, getColumns(output) - columnPadding);
2276
+ const rowBudget = Math.max(getRows(output) - rowPadding, 0);
2277
+ const visibleCount = Math.max(Math.min(maxItems, rowBudget), 5);
2278
+ const cappedVisibleCount = Math.min(visibleCount, options.length);
2279
+ let start = 0;
2280
+ if (cursor2 >= cappedVisibleCount - 3) {
2281
+ start = Math.max(Math.min(cursor2 - cappedVisibleCount + 3, options.length - cappedVisibleCount), 0);
2282
+ }
2283
+ const hasTopMarker = cappedVisibleCount < options.length && start > 0;
2284
+ const hasBottomMarker = cappedVisibleCount < options.length && start + cappedVisibleCount < options.length;
2285
+ const visible = options.slice(start, start + cappedVisibleCount).map((option, index) => wrapAnsi2(style(option, start + index === cursor2), columns, { hard: true, trim: false }));
2286
+ const trimmed = trimToRows(
2287
+ visible,
2288
+ Math.max(cursor2 - start, 0),
2289
+ Math.max(rowBudget - Number(hasTopMarker) - Number(hasBottomMarker), 1),
2290
+ hasTopMarker,
2291
+ hasBottomMarker
2292
+ );
2293
+ if (hasTopMarker) {
2294
+ trimmed.unshift(color.dim(GLYPHS.ellipsis));
2295
+ }
2296
+ if (hasBottomMarker) {
2297
+ trimmed.push(color.dim(GLYPHS.ellipsis));
2298
+ }
2299
+ return trimmed;
2300
+ }
2301
+
2302
+ // ../toolcraft-design/src/prompts/interactive/select.ts
2303
+ var SelectPrompt = class extends Prompt {
2304
+ options;
2305
+ constructor(opts) {
2306
+ if (opts.options.length === 0) {
2307
+ throw new Error("Select prompt requires at least one option.");
2308
+ }
2309
+ if (opts.options.every((option) => option.disabled)) {
2310
+ throw new Error("Select prompt requires at least one enabled option.");
2311
+ }
2312
+ const initialIndex = Math.max(opts.options.findIndex((option) => option.value === opts.initialValue), 0);
2313
+ const cursor2 = findNonDisabled(initialIndex, 1, opts.options);
2314
+ super({
2315
+ ...opts,
2316
+ initialValue: opts.options[cursor2]?.value,
2317
+ render: (prompt) => renderSelectPrompt(prompt, opts)
2318
+ }, false);
2319
+ this.options = opts.options;
2320
+ this._cursor = cursor2;
2321
+ this.setValue(this.options[this._cursor]?.value);
2322
+ this.on("cursor", (action) => {
2323
+ if (action === "up" || action === "left") {
2324
+ this._cursor = findNonDisabled(this._cursor - 1, -1, this.options);
2325
+ } else if (action === "down" || action === "right") {
2326
+ this._cursor = findNonDisabled(this._cursor + 1, 1, this.options);
2327
+ }
2328
+ this.setValue(this.options[this._cursor]?.value);
2329
+ });
2330
+ }
2331
+ get visibleOptions() {
2332
+ return this.options;
2333
+ }
2334
+ promptNonTty() {
2335
+ if (process.env.POE_NO_PROMPT === "1") {
2336
+ return Promise.resolve(this.value);
2337
+ }
2338
+ return super.promptNonTty();
2339
+ }
2340
+ };
2341
+ function findNonDisabled(start, direction, options) {
2342
+ if (options.every((option) => option.disabled)) {
2343
+ return start;
2344
+ }
2345
+ let index = start;
2346
+ for (let checked = 0; checked < options.length; checked += 1) {
2347
+ index = (index + options.length) % options.length;
2348
+ if (!options[index]?.disabled) {
2349
+ return index;
2350
+ }
2351
+ index += direction;
2352
+ }
2353
+ return start;
2354
+ }
2355
+ function renderOption(option, active, submitted, cancelled) {
2356
+ const hint = option.hint ? color.dim(` (${option.hint})`) : "";
2357
+ if (submitted) return color.dim(option.label);
2358
+ if (cancelled) return color.dim.strikethrough(option.label);
2359
+ if (option.disabled) return `${color.gray(GLYPHS.radioInactive)} ${color.gray.strikethrough(option.label)}${hint}`;
2360
+ if (active) return `${color.green(GLYPHS.radioActive)} ${option.label}${hint}`;
2361
+ return `${color.dim(GLYPHS.radioInactive)} ${color.dim(option.label)}${hint}`;
2362
+ }
2363
+ function renderSelectPrompt(prompt, opts) {
2364
+ if (prompt.state === "submit" || prompt.state === "cancel") {
2365
+ const option = prompt.visibleOptions[prompt.cursor];
2366
+ const rendered = option ? renderOption(option, false, prompt.state === "submit", prompt.state === "cancel") : "";
2367
+ const end = prompt.state === "submit" ? color.green(GLYPHS.barEnd) : color.red(GLYPHS.barEnd);
2368
+ return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${opts.message}
2369
+ ${color.gray(GLYPHS.bar)} ${rendered}
2370
+ ${end}`;
2371
+ }
2372
+ const lines = limitOptions({
2373
+ cursor: prompt.cursor,
2374
+ options: prompt.visibleOptions,
2375
+ output: opts.output ?? process.stdout,
2376
+ maxItems: opts.maxItems,
2377
+ columnPadding: 3,
2378
+ style: (option, active) => renderOption(option, active, false, false)
2379
+ }).map((line) => `${color.cyan(GLYPHS.bar)} ${line}`);
2380
+ return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${opts.message}
2381
+ ${lines.join("\n")}
2382
+ ${color.cyan(GLYPHS.barEnd)}`;
2383
+ }
2384
+ function selectPrompt(opts) {
2385
+ return new SelectPrompt(opts).prompt();
2386
+ }
2387
+
2388
+ // ../toolcraft-design/src/prompts/interactive/text.ts
2389
+ var TextPrompt = class extends Prompt {
2390
+ constructor(opts) {
2391
+ const initialUserInput = opts.initialValue ?? "";
2392
+ super({
2393
+ ...opts,
2394
+ initialValue: initialUserInput,
2395
+ initialUserInput,
2396
+ render: (prompt) => renderTextPrompt(prompt, opts),
2397
+ validate: opts.validate
2398
+ });
2399
+ this.on("userInput", (value) => this.setValue(value));
2400
+ this.on("finalize", () => {
2401
+ if (this.state === "submit") {
2402
+ this.setValue(this.value || opts.defaultValue || "");
2403
+ }
2404
+ });
2405
+ }
2406
+ get userInputWithCursor() {
2407
+ if (this.state === "submit") {
2408
+ return this.userInput;
2409
+ }
2410
+ const before = this.userInput.slice(0, this.cursor);
2411
+ const current = this.userInput[this.cursor];
2412
+ const after = this.userInput.slice(this.cursor + 1);
2413
+ if (current) {
2414
+ return `${before}${color.inverse(current)}${after}`;
2415
+ }
2416
+ return `${before}${color.inverse("\u2588")}`;
2417
+ }
2418
+ promptNonTty() {
2419
+ return this.readNonTtyLine();
2420
+ }
2421
+ };
2422
+ function renderHeader2(prompt, message2) {
2423
+ return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${message2}`;
2424
+ }
2425
+ function renderTextPrompt(prompt, opts) {
2426
+ const value = prompt.value ?? "";
2427
+ if (prompt.state === "submit") {
2428
+ return `${renderHeader2(prompt, opts.message)}
2429
+ ${color.gray(GLYPHS.bar)} ${color.dim(value)}
2430
+ ${color.green(GLYPHS.barEnd)}`;
2431
+ }
2432
+ if (prompt.state === "cancel") {
2433
+ return `${renderHeader2(prompt, opts.message)}
2434
+ ${color.gray(GLYPHS.bar)} ${color.dim.strikethrough(value)}
2435
+ ${color.red(GLYPHS.barEnd)}`;
2436
+ }
2437
+ const input = prompt.userInput.length > 0 ? prompt.userInputWithCursor : opts.placeholder ? `${color.inverse(opts.placeholder[0] ?? " ")}${color.dim(opts.placeholder.slice(1))}` : color.inverse("_");
2438
+ if (prompt.state === "error") {
2439
+ return `${renderHeader2(prompt, opts.message)}
2440
+ ${symbolBar(prompt.state)} ${input}
2441
+ ${color.yellow(GLYPHS.barEnd)} ${color.yellow(prompt.error)}`;
2442
+ }
2443
+ return `${renderHeader2(prompt, opts.message)}
2444
+ ${symbolBar(prompt.state)} ${input}
2445
+ ${color.cyan(GLYPHS.barEnd)}`;
2446
+ }
2447
+ function textPrompt(opts) {
2448
+ return new TextPrompt(opts).prompt();
2449
+ }
1825
2450
 
1826
2451
  // ../toolcraft-design/src/prompts/primitives/cancel.ts
1827
- import { isCancel } from "@clack/prompts";
1828
2452
  function cancel(msg = "") {
1829
2453
  if (resolveOutputFormat() !== "terminal") {
1830
2454
  return;
@@ -1887,14 +2511,14 @@ function note(message2, title) {
1887
2511
  var SPINNER_FRAMES = Object.freeze(["\u25D2", "\u25D0", "\u25D3", "\u25D1"]);
1888
2512
 
1889
2513
  // ../toolcraft-design/src/prompts/index.ts
1890
- async function select2(opts) {
1891
- return clack.select(opts);
2514
+ async function select(opts) {
2515
+ return selectPrompt(opts);
1892
2516
  }
1893
- async function text3(opts) {
1894
- return clack.text(opts);
2517
+ async function text2(opts) {
2518
+ return textPrompt(opts);
1895
2519
  }
1896
- async function confirm2(opts) {
1897
- return clack.confirm(opts);
2520
+ async function confirm(opts) {
2521
+ return confirmPrompt(opts);
1898
2522
  }
1899
2523
 
1900
2524
  // ../toolcraft/src/index.ts
@@ -2269,6 +2893,12 @@ function cloneRequires(requires) {
2269
2893
  function cloneStringArray(values) {
2270
2894
  return values === void 0 ? void 0 : [...values];
2271
2895
  }
2896
+ function cloneCommandExamples(examples) {
2897
+ return (examples ?? []).map((example) => ({
2898
+ title: example.title,
2899
+ params: { ...example.params }
2900
+ }));
2901
+ }
2272
2902
  function cloneStringRecord(values) {
2273
2903
  return values === void 0 ? void 0 : { ...values };
2274
2904
  }
@@ -2533,9 +3163,11 @@ function createBaseCommand(config2) {
2533
3163
  kind: "command",
2534
3164
  name: config2.name,
2535
3165
  description: config2.description,
3166
+ examples: cloneCommandExamples(config2.examples),
2536
3167
  aliases: [...config2.aliases ?? []],
2537
3168
  positional: [...config2.positional ?? []],
2538
3169
  params: config2.params,
3170
+ result: config2.result,
2539
3171
  secrets: cloneSecrets(config2.secrets),
2540
3172
  scope: resolveCommandScope(config2.scope, void 0),
2541
3173
  confirm: config2.confirm ?? false,
@@ -2547,6 +3179,8 @@ function createBaseCommand(config2) {
2547
3179
  Object.defineProperty(command, commandConfigSymbol, {
2548
3180
  value: {
2549
3181
  scope: cloneScope(config2.scope),
3182
+ examples: cloneCommandExamples(config2.examples),
3183
+ result: config2.result,
2550
3184
  humanInLoop: config2.humanInLoop,
2551
3185
  secrets: cloneSecrets(config2.secrets),
2552
3186
  requires: cloneRequires(config2.requires),
@@ -2595,9 +3229,11 @@ function materializeCommand(command, inherited) {
2595
3229
  kind: "command",
2596
3230
  name: command.name,
2597
3231
  description: command.description,
3232
+ examples: cloneCommandExamples(internal.examples),
2598
3233
  aliases: [...command.aliases],
2599
3234
  positional: [...command.positional],
2600
3235
  params: command.params,
3236
+ result: internal.result,
2601
3237
  secrets: mergeSecrets(inherited.secrets, internal.secrets),
2602
3238
  scope: resolveCommandScope(internal.scope, inherited.scope),
2603
3239
  confirm: command.confirm,
@@ -2609,6 +3245,8 @@ function materializeCommand(command, inherited) {
2609
3245
  Object.defineProperty(materialized, commandConfigSymbol, {
2610
3246
  value: {
2611
3247
  scope: cloneScope(internal.scope),
3248
+ examples: cloneCommandExamples(internal.examples),
3249
+ result: internal.result,
2612
3250
  humanInLoop: internal.humanInLoop,
2613
3251
  secrets: cloneSecrets(internal.secrets),
2614
3252
  requires: cloneRequires(internal.requires),
@@ -2850,7 +3488,7 @@ var AnchorNotFoundError = class extends Error {
2850
3488
  };
2851
3489
 
2852
3490
  // ../task-list/src/backends/gh-issues-client.ts
2853
- import { text as text4 } from "node:stream/consumers";
3491
+ import { text as text3 } from "node:stream/consumers";
2854
3492
 
2855
3493
  // ../process-runner/src/docker/context.ts
2856
3494
  import { execSync } from "node:child_process";
@@ -3059,8 +3697,8 @@ async function resolveAuth(options) {
3059
3697
  stderr: "pipe"
3060
3698
  });
3061
3699
  const [stdout, , result] = await Promise.all([
3062
- handle.stdout === null ? Promise.resolve("") : text4(handle.stdout),
3063
- handle.stderr === null ? Promise.resolve("") : text4(handle.stderr),
3700
+ handle.stdout === null ? Promise.resolve("") : text3(handle.stdout),
3701
+ handle.stderr === null ? Promise.resolve("") : text3(handle.stderr),
3064
3702
  handle.result
3065
3703
  ]);
3066
3704
  const token = stdout.trim();
@@ -4259,7 +4897,7 @@ function parseQualifiedId(qualifiedId, listName) {
4259
4897
 
4260
4898
  // ../task-list/src/backends/markdown-dir.ts
4261
4899
  import path7 from "node:path";
4262
- import { parseDocument, stringify } from "yaml";
4900
+ import { parseDocument as parseDocument2, stringify as stringify2 } from "yaml";
4263
4901
 
4264
4902
  // ../task-list/src/schema/task.schema.json
4265
4903
  var task_schema_default = {
@@ -4450,7 +5088,7 @@ function splitTaskDocument(content, filePath, mode) {
4450
5088
  };
4451
5089
  }
4452
5090
  function readFrontmatter(frontmatterContent, filePath) {
4453
- const document = parseDocument(frontmatterContent);
5091
+ const document = parseDocument2(frontmatterContent);
4454
5092
  if (document.errors.length > 0) {
4455
5093
  throw malformedTask(filePath, "frontmatter");
4456
5094
  }
@@ -4520,7 +5158,7 @@ function createTask(list, id, frontmatter, body, mode, sourcePath) {
4520
5158
  }
4521
5159
  function serializeTaskDocument(frontmatter, description) {
4522
5160
  return `---
4523
- ${stringify(frontmatter)}---
5161
+ ${stringify2(frontmatter)}---
4524
5162
 
4525
5163
  ${description}`;
4526
5164
  }
@@ -5258,7 +5896,7 @@ async function markdownDirBackend(deps) {
5258
5896
 
5259
5897
  // ../task-list/src/backends/yaml-file.ts
5260
5898
  import path8 from "node:path";
5261
- import { isMap, parseDocument as parseDocument2 } from "yaml";
5899
+ import { isMap, parseDocument as parseDocument3 } from "yaml";
5262
5900
 
5263
5901
  // ../task-list/src/schema/store.schema.json
5264
5902
  var store_schema_default = {
@@ -5435,7 +6073,7 @@ function buildFiredTaskRecord(existing, to, metadataPatch) {
5435
6073
  function parseStoreDocument(filePath, content) {
5436
6074
  let document;
5437
6075
  try {
5438
- document = parseDocument2(content, { keepSourceTokens: true, prettyErrors: false });
6076
+ document = parseDocument3(content, { keepSourceTokens: true, prettyErrors: false });
5439
6077
  } catch {
5440
6078
  throw malformedStore(filePath, "yaml");
5441
6079
  }
@@ -5612,7 +6250,7 @@ async function ensureStorePath(deps) {
5612
6250
  deps.fs,
5613
6251
  deps.path,
5614
6252
  serializeDocument(
5615
- parseDocument2(
6253
+ parseDocument3(
5616
6254
  [
5617
6255
  `$schema: ${STORE_SCHEMA_ID}`,
5618
6256
  `kind: ${STORE_KIND}`,
@@ -7616,8 +8254,8 @@ function validateAuthorizationCallbackBinding(callback, expected) {
7616
8254
  function createAuthorizationError(error3, description) {
7617
8255
  return new Error(`OAuth authorization failed: ${error3} \u2014 ${description}`);
7618
8256
  }
7619
- function escapeHtml2(text5) {
7620
- return text5.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
8257
+ function escapeHtml2(text4) {
8258
+ return text4.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
7621
8259
  }
7622
8260
  function buildSuccessPage(landingPage) {
7623
8261
  const title = landingPage?.title ?? "Connected";
@@ -10164,6 +10802,9 @@ function isCallToolResult(value) {
10164
10802
  if (!isObjectRecord5(value) || !Array.isArray(value.content)) {
10165
10803
  return false;
10166
10804
  }
10805
+ if (value.structuredContent !== void 0 && !isObjectRecord5(value.structuredContent)) {
10806
+ return false;
10807
+ }
10167
10808
  if (value.isError !== void 0 && typeof value.isError !== "boolean") {
10168
10809
  return false;
10169
10810
  }
@@ -10903,13 +11544,13 @@ var proxyNodeSymbol = /* @__PURE__ */ Symbol("toolcraft.mcpProxyNode");
10903
11544
  var proxyConnectionSymbol = /* @__PURE__ */ Symbol("toolcraft.mcpProxyConnection");
10904
11545
  var shutdownDisposers = /* @__PURE__ */ new Set();
10905
11546
  function getInternalGroupConfig2(group) {
10906
- const symbol = Object.getOwnPropertySymbols(group).find(
11547
+ const symbol2 = Object.getOwnPropertySymbols(group).find(
10907
11548
  (candidate) => candidate.description === GROUP_CONFIG_SYMBOL_DESCRIPTION
10908
11549
  );
10909
- if (symbol === void 0) {
11550
+ if (symbol2 === void 0) {
10910
11551
  return {};
10911
11552
  }
10912
- return group[symbol] ?? {};
11553
+ return group[symbol2] ?? {};
10913
11554
  }
10914
11555
  function isProxyNode(node) {
10915
11556
  return node[proxyNodeSymbol] === true;
@@ -10956,23 +11597,38 @@ function createProxyCommand(parent, tool, commandName, connection) {
10956
11597
  if (params17.kind !== "object") {
10957
11598
  throw new Error(`upstream tool "${tool.name}" must define an object input schema`);
10958
11599
  }
11600
+ const result = tool.outputSchema === void 0 ? void 0 : convertJsonSchema(tool.outputSchema);
11601
+ if (result !== void 0 && result.kind !== "object") {
11602
+ throw new Error(`upstream tool "${tool.name}" must define an object output schema`);
11603
+ }
10959
11604
  return markProxyNode({
10960
11605
  kind: "command",
10961
11606
  name: commandName,
10962
11607
  description: tool.description,
11608
+ examples: [],
10963
11609
  aliases: [],
10964
11610
  positional: [],
10965
11611
  params: params17,
11612
+ ...result === void 0 ? {} : { result },
10966
11613
  secrets: cloneSecrets2(parent.secrets),
10967
11614
  scope: cloneScope2(parent.scope) ?? ["cli", "sdk"],
10968
11615
  confirm: false,
10969
11616
  requires: parent.requires,
10970
11617
  handler: async (ctx) => {
10971
11618
  const client = await ensureConnected(connection);
10972
- return client.callTool({
11619
+ const toolResult = await client.callTool({
10973
11620
  name: tool.name,
10974
11621
  arguments: ctx.params
10975
11622
  });
11623
+ if (result === void 0) {
11624
+ return toolResult;
11625
+ }
11626
+ if (toolResult.structuredContent === void 0) {
11627
+ throw new Error(
11628
+ `upstream tool "${tool.name}" declared outputSchema but returned no structuredContent`
11629
+ );
11630
+ }
11631
+ return toolResult.structuredContent;
10976
11632
  },
10977
11633
  render: void 0
10978
11634
  });
@@ -11103,12 +11759,12 @@ async function fetchCache(name, config2) {
11103
11759
  try {
11104
11760
  logger2.info(`MCP ${name}: listing tools`);
11105
11761
  const tools = [];
11106
- let cursor;
11762
+ let cursor2;
11107
11763
  do {
11108
- const page = await client.listTools(cursor === void 0 ? {} : { cursor });
11764
+ const page = await client.listTools(cursor2 === void 0 ? {} : { cursor: cursor2 });
11109
11765
  tools.push(...page.tools);
11110
- cursor = page.nextCursor;
11111
- } while (cursor !== void 0);
11766
+ cursor2 = page.nextCursor;
11767
+ } while (cursor2 !== void 0);
11112
11768
  logger2.info(`MCP ${name}: found ${tools.length} tools`);
11113
11769
  const upstream = client.serverInfo ?? {
11114
11770
  name,
@@ -11846,10 +12502,15 @@ async function writeErrorReport(context) {
11846
12502
 
11847
12503
  // ../toolcraft/src/number-schema.ts
11848
12504
  function isValidNumberSchemaValue(value, schema) {
11849
- return typeof value === "number" && Number.isFinite(value) && (schema.jsonType !== "integer" || Number.isInteger(value));
12505
+ return typeof value === "number" && Number.isFinite(value) && (schema.jsonType !== "integer" || Number.isInteger(value)) && (schema.minimum === void 0 || value >= schema.minimum) && (schema.maximum === void 0 || value <= schema.maximum);
11850
12506
  }
11851
12507
  function getExpectedNumberDescription(schema) {
11852
- return schema.jsonType === "integer" ? "an integer" : "a number";
12508
+ const type2 = schema.jsonType === "integer" ? "an integer" : "a number";
12509
+ const bounds = [
12510
+ schema.minimum === void 0 ? void 0 : `greater than or equal to ${schema.minimum}`,
12511
+ schema.maximum === void 0 ? void 0 : `less than or equal to ${schema.maximum}`
12512
+ ].filter((bound) => bound !== void 0);
12513
+ return bounds.length === 0 ? type2 : `${type2} ${bounds.join(" and ")}`;
11853
12514
  }
11854
12515
 
11855
12516
  // ../toolcraft/src/renderer.ts
@@ -11882,8 +12543,8 @@ function extractMcpPayload(envelope) {
11882
12543
  return structuredContent;
11883
12544
  }
11884
12545
  if (Array.isArray(envelope.content)) {
11885
- const text5 = envelope.content.filter(isMcpTextContent).map((block) => block.text).join("\n");
11886
- return text5.length > 0 ? text5 : void 0;
12546
+ const text4 = envelope.content.filter(isMcpTextContent).map((block) => block.text).join("\n");
12547
+ return text4.length > 0 ? text4 : void 0;
11887
12548
  }
11888
12549
  return void 0;
11889
12550
  }
@@ -12441,6 +13102,7 @@ function collectFields(schema, casing, globalLongOptionFlags, path24 = [], inher
12441
13102
  globalLongOptionFlags
12442
13103
  ),
12443
13104
  optionFlag: toOptionFlag([...nextPath, childSchema.discriminator], casing),
13105
+ longAliases: [],
12444
13106
  shortFlag: void 0,
12445
13107
  schema: createSyntheticEnumSchema(branchIds),
12446
13108
  description: childSchema.description,
@@ -12494,6 +13156,7 @@ function collectFields(schema, casing, globalLongOptionFlags, path24 = [], inher
12494
13156
  globalLongOptionFlags
12495
13157
  ),
12496
13158
  optionFlag: toOptionFlag(controlPath, casing),
13159
+ longAliases: [],
12497
13160
  shortFlag: void 0,
12498
13161
  schema: createSyntheticEnumSchema(branchIds),
12499
13162
  description: childSchema.description,
@@ -12576,6 +13239,9 @@ function collectFields(schema, casing, globalLongOptionFlags, path24 = [], inher
12576
13239
  optionAttribute: toOptionAttribute(nextPath, casing),
12577
13240
  commanderOptionAttribute: toCommanderOptionAttribute(nextPath, casing, globalLongOptionFlags),
12578
13241
  optionFlag: toOptionFlag(nextPath, casing),
13242
+ longAliases: [...childSchema.cliAliases ?? []].map(
13243
+ (alias) => alias.startsWith("--") ? alias : `--${alias}`
13244
+ ),
12579
13245
  shortFlag: childSchema.short,
12580
13246
  schema: childSchema,
12581
13247
  description: childSchema.description,
@@ -12634,9 +13300,9 @@ function formatOptionFlags(field, globalLongOptionFlags) {
12634
13300
  return `-${field.shortFlag}`;
12635
13301
  }
12636
13302
  if (field.shortFlag === void 0) {
12637
- return field.optionFlag;
13303
+ return [field.optionFlag, ...field.longAliases].join(", ");
12638
13304
  }
12639
- return `-${field.shortFlag}, ${field.optionFlag}`;
13305
+ return [`-${field.shortFlag}`, field.optionFlag, ...field.longAliases].join(", ");
12640
13306
  }
12641
13307
  function formatPositionalToken(field) {
12642
13308
  const optionalPositional = field.optional || field.hasDefault;
@@ -12916,24 +13582,34 @@ function getGlobalLongOptionFlags(presetsEnabled, versionEnabled, controls) {
12916
13582
  }
12917
13583
  return new Set(flags);
12918
13584
  }
12919
- function validateUniqueOptionFlags(fields) {
13585
+ function validateUniqueOptionFlags(fields, globalLongOptionFlags) {
12920
13586
  const fieldsByFlag = /* @__PURE__ */ new Map();
12921
13587
  for (const field of fields) {
12922
13588
  if (field.positionalIndex !== void 0) {
12923
13589
  continue;
12924
13590
  }
12925
- const existing = fieldsByFlag.get(field.optionFlag);
12926
- if (existing !== void 0) {
12927
- throw new UserError(
12928
- `Parameters "${existing.displayPath}" and "${field.displayPath}" use conflicting CLI flag "${field.optionFlag}".`
12929
- );
13591
+ for (const flag of [field.optionFlag, ...field.longAliases]) {
13592
+ if (globalLongOptionFlags.has(flag)) {
13593
+ if (flag === field.optionFlag && field.shortFlag !== void 0) {
13594
+ continue;
13595
+ }
13596
+ throw new UserError(
13597
+ `Parameter "${field.displayPath}" uses reserved CLI flag "${flag}". Add a short flag or rename the parameter.`
13598
+ );
13599
+ }
13600
+ const existing = fieldsByFlag.get(flag);
13601
+ if (existing !== void 0) {
13602
+ throw new UserError(
13603
+ `Parameters "${existing.displayPath}" and "${field.displayPath}" use conflicting CLI flag "${flag}".`
13604
+ );
13605
+ }
13606
+ fieldsByFlag.set(flag, field);
12930
13607
  }
12931
- fieldsByFlag.set(field.optionFlag, field);
12932
13608
  }
12933
13609
  }
12934
13610
  function createCommanderOption(flags, description, field) {
12935
13611
  const option = new Option(flags, description);
12936
- if (field.commanderOptionAttribute !== field.optionAttribute) {
13612
+ if (field.commanderOptionAttribute !== field.optionAttribute || field.longAliases.length > 0) {
12937
13613
  option.attributeName = () => field.commanderOptionAttribute;
12938
13614
  }
12939
13615
  return option;
@@ -13254,6 +13930,26 @@ function formatSecretDescription(secret) {
13254
13930
  }
13255
13931
  return secret.optional === true ? "Optional secret" : "Required secret";
13256
13932
  }
13933
+ function formatExampleValue(value) {
13934
+ if (typeof value === "string" && value.length > 0 && !value.includes(" ")) {
13935
+ return value;
13936
+ }
13937
+ return JSON.stringify(value);
13938
+ }
13939
+ function formatExampleCommand(breadcrumb, rootUsageName, params17) {
13940
+ const commandPath = buildUsageLine(breadcrumb, rootUsageName, "");
13941
+ const flags = Object.entries(params17).map(([key2, value]) => {
13942
+ const flag = `--${key2}`;
13943
+ return typeof value === "boolean" ? value ? flag : `--no-${key2}` : `${flag} ${formatExampleValue(value)}`;
13944
+ });
13945
+ return [commandPath, ...flags].filter((token) => token.length > 0).join(" ");
13946
+ }
13947
+ function formatExampleRows(examples, breadcrumb, rootUsageName) {
13948
+ return examples.map(
13949
+ (example) => `${example.title}
13950
+ ${formatExampleCommand(breadcrumb, rootUsageName, example.params)}`
13951
+ );
13952
+ }
13257
13953
  function wrapOptionalCommandParameterToken(token, optional) {
13258
13954
  return optional ? `[${token}]` : token;
13259
13955
  }
@@ -13412,6 +14108,12 @@ ${formatHelpOptionList(optionRows)}`);
13412
14108
  ${formatHelpOptionList(secretRows)}`
13413
14109
  );
13414
14110
  }
14111
+ if (command.examples.length > 0) {
14112
+ sections.push(
14113
+ `${text.sectionHeader("Examples")}
14114
+ ${formatExampleRows(command.examples, breadcrumb, rootUsageName).join("\n")}`
14115
+ );
14116
+ }
13415
14117
  const positionalFields = fields.filter((f) => f.positionalIndex !== void 0);
13416
14118
  const usageSuffix = positionalFields.length > 0 ? `[OPTIONS] ${positionalFields.map(formatPositionalToken).join(" ")}` : "[OPTIONS]";
13417
14119
  return renderHelpDocument({
@@ -13487,7 +14189,7 @@ function createNodeCommand(node, casing, globalLongOptionFlags, execute, presets
13487
14189
  const command = new CommanderCommand(node.name);
13488
14190
  const collected = collectFields(node.params, casing, globalLongOptionFlags);
13489
14191
  const fields = assignPositionals(collected.fields, node.positional);
13490
- validateUniqueOptionFlags(fields);
14192
+ validateUniqueOptionFlags(fields, globalLongOptionFlags);
13491
14193
  if (node.description !== void 0) {
13492
14194
  command.description(node.description);
13493
14195
  }
@@ -13618,26 +14320,26 @@ function parseDebugStackMode(value) {
13618
14320
  );
13619
14321
  }
13620
14322
  function setNestedValue(target, path24, value) {
13621
- let cursor = target;
14323
+ let cursor2 = target;
13622
14324
  for (let index = 0; index < path24.length - 1; index += 1) {
13623
14325
  const segment = path24[index] ?? "";
13624
- const existing = Object.prototype.hasOwnProperty.call(cursor, segment) ? cursor[segment] : void 0;
14326
+ const existing = Object.prototype.hasOwnProperty.call(cursor2, segment) ? cursor2[segment] : void 0;
13625
14327
  if (typeof existing === "object" && existing !== null) {
13626
- cursor = existing;
14328
+ cursor2 = existing;
13627
14329
  continue;
13628
14330
  }
13629
14331
  const next = {};
13630
- Object.defineProperty(cursor, segment, {
14332
+ Object.defineProperty(cursor2, segment, {
13631
14333
  value: next,
13632
14334
  enumerable: true,
13633
14335
  configurable: true,
13634
14336
  writable: true
13635
14337
  });
13636
- cursor = next;
14338
+ cursor2 = next;
13637
14339
  }
13638
14340
  const leaf = path24[path24.length - 1];
13639
14341
  if (leaf !== void 0) {
13640
- Object.defineProperty(cursor, leaf, {
14342
+ Object.defineProperty(cursor2, leaf, {
13641
14343
  value,
13642
14344
  enumerable: true,
13643
14345
  configurable: true,
@@ -13671,7 +14373,7 @@ async function promptForField(field) {
13671
14373
  label: enumOptionLabel(schema, value),
13672
14374
  value
13673
14375
  }));
13674
- const selected = await select2({
14376
+ const selected = await select({
13675
14377
  message: field.description ?? fieldPromptLabel(field),
13676
14378
  options,
13677
14379
  initialValue: field.hasDefault ? field.defaultValue : void 0
@@ -13683,7 +14385,7 @@ async function promptForField(field) {
13683
14385
  return selected;
13684
14386
  }
13685
14387
  if (field.schema.kind === "boolean") {
13686
- const selected = await confirm2({
14388
+ const selected = await confirm({
13687
14389
  message: fieldPromptLabel(field),
13688
14390
  initialValue: field.hasDefault ? Boolean(field.defaultValue) : void 0
13689
14391
  });
@@ -13693,7 +14395,7 @@ async function promptForField(field) {
13693
14395
  }
13694
14396
  return selected;
13695
14397
  }
13696
- const entered = await text3({
14398
+ const entered = await text2({
13697
14399
  message: fieldPromptLabel(field),
13698
14400
  initialValue: field.hasDefault && field.defaultValue !== void 0 ? formatResolvedValue(field.defaultValue) : void 0
13699
14401
  });
@@ -14168,12 +14870,12 @@ function createFixtureEnvValues(command) {
14168
14870
  }
14169
14871
  return values;
14170
14872
  }
14171
- async function resolveFixtureRuntime(command, services, requirementOptions) {
14873
+ async function resolveFixtureRuntime(command, services, requirementOptions, runtimeFetch) {
14172
14874
  const selector = process.env.TOOLCRAFT_FIXTURE;
14173
14875
  if (selector === void 0 || selector.length === 0) {
14174
14876
  return {
14175
14877
  env: createEnv2(),
14176
- fetch: globalThis.fetch,
14878
+ fetch: runtimeFetch,
14177
14879
  fs: createFs2(),
14178
14880
  isFixture: false,
14179
14881
  requirementOptions,
@@ -14312,22 +15014,22 @@ function consumeFieldValue(args, index, schema, label, inlineValue) {
14312
15014
  if (schema.kind === "array") {
14313
15015
  const values = [];
14314
15016
  let nextIndex = index;
14315
- let cursor = index + 1;
14316
- while (cursor < args.length) {
14317
- const token = args[cursor] ?? "";
15017
+ let cursor2 = index + 1;
15018
+ while (cursor2 < args.length) {
15019
+ const token = args[cursor2] ?? "";
14318
15020
  if (token.startsWith("-")) {
14319
15021
  break;
14320
15022
  }
14321
15023
  const parsed = parseArrayValue(token, schema, label);
14322
15024
  if (parsed === null) {
14323
15025
  return {
14324
- nextIndex: cursor,
15026
+ nextIndex: cursor2,
14325
15027
  value: null
14326
15028
  };
14327
15029
  }
14328
15030
  values.push(...parsed);
14329
- nextIndex = cursor;
14330
- cursor += 1;
15031
+ nextIndex = cursor2;
15032
+ cursor2 += 1;
14331
15033
  }
14332
15034
  if (values.length === 0) {
14333
15035
  throw new InvalidArgumentError(`option '${label}' argument missing`);
@@ -14860,7 +15562,7 @@ function getResolvedFlags(command) {
14860
15562
  const flags = command.optsWithGlobals();
14861
15563
  return flags;
14862
15564
  }
14863
- async function executeCommand(state, services, requirementOptions, runtimeOptions, onErrorReportContext) {
15565
+ async function executeCommand(state, services, requirementOptions, runtimeFetch, runtimeOptions, onErrorReportContext) {
14864
15566
  const logger2 = createLogger();
14865
15567
  const primitives = {
14866
15568
  logger: logger2,
@@ -14872,7 +15574,12 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
14872
15574
  const resolvedFlags = optionValues;
14873
15575
  const output = resolveOutput(resolvedFlags);
14874
15576
  const shouldPrompt = !resolvedFlags.yes && Boolean(process.stdin.isTTY);
14875
- const runtime = await resolveFixtureRuntime(state.command, services, requirementOptions);
15577
+ const runtime = await resolveFixtureRuntime(
15578
+ state.command,
15579
+ services,
15580
+ requirementOptions,
15581
+ runtimeFetch
15582
+ );
14876
15583
  const preflightContext = {
14877
15584
  ...runtime.services,
14878
15585
  secrets: runtime.secrets,
@@ -14915,7 +15622,7 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
14915
15622
  logger2.resolved(field.displayPath, formatResolvedValue(value));
14916
15623
  }
14917
15624
  }
14918
- const proceed = await confirm2({
15625
+ const proceed = await confirm({
14919
15626
  message: "Proceed?",
14920
15627
  initialValue: true
14921
15628
  });
@@ -15403,6 +16110,7 @@ async function runCLI(roots, options = {}) {
15403
16110
  const casing = options.casing ?? "kebab";
15404
16111
  const services = options.services ?? {};
15405
16112
  const runtimeOptions = options.humanInLoop ?? {};
16113
+ const runtimeFetch = options.fetch ?? globalThis.fetch;
15406
16114
  const version = options.version ?? findEntrypointPackageMetadata(process.argv[1])?.version;
15407
16115
  const rootUsageName = options.rootUsageName ?? inferProgramName(process.argv);
15408
16116
  const controls = resolveCLIControls(options.controls);
@@ -15444,6 +16152,7 @@ async function runCLI(roots, options = {}) {
15444
16152
  state,
15445
16153
  servicesWithBuiltIns,
15446
16154
  requirementOptions,
16155
+ runtimeFetch,
15447
16156
  runtimeOptions,
15448
16157
  (context) => {
15449
16158
  errorReportContext = context;
@@ -15522,7 +16231,7 @@ async function runCLI(roots, options = {}) {
15522
16231
  import { randomUUID as randomUUID6 } from "node:crypto";
15523
16232
 
15524
16233
  // src/terminal-session.ts
15525
- import { EventEmitter } from "node:events";
16234
+ import { EventEmitter as EventEmitter2 } from "node:events";
15526
16235
  import { accessSync, chmodSync, constants } from "node:fs";
15527
16236
  import { createRequire } from "node:module";
15528
16237
  import { dirname, join } from "node:path";
@@ -15771,6 +16480,10 @@ var TerminalBuffer = class {
15771
16480
  }
15772
16481
  _writePrintable(ch) {
15773
16482
  const width = this._cellWidth(ch);
16483
+ if (width === 0) {
16484
+ this._appendCombiningMark(ch);
16485
+ return;
16486
+ }
15774
16487
  if (this._autoWrap && this._pendingWrap) {
15775
16488
  this._cursorX = 0;
15776
16489
  this._newline();
@@ -15805,11 +16518,40 @@ var TerminalBuffer = class {
15805
16518
  _cellWidth(ch) {
15806
16519
  const codePoint = ch.codePointAt(0);
15807
16520
  if (codePoint === void 0) return 0;
16521
+ if (isCombiningCodePoint2(codePoint)) {
16522
+ return 0;
16523
+ }
15808
16524
  if (codePoint >= 4352 && codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || codePoint >= 11904 && codePoint <= 12350 || codePoint >= 12353 && codePoint <= 13247 || codePoint >= 13312 && codePoint <= 19903 || codePoint >= 19968 && codePoint <= 42191 || codePoint >= 44032 && codePoint <= 55215 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 65040 && codePoint <= 65049 || codePoint >= 65072 && codePoint <= 65135 || codePoint >= 65280 && codePoint <= 65376 || codePoint >= 65504 && codePoint <= 65510 || codePoint >= 127488 && codePoint <= 131069 || codePoint >= 131072 && codePoint <= 262141) {
15809
16525
  return Math.min(2, this._cols);
15810
16526
  }
15811
16527
  return 1;
15812
16528
  }
16529
+ _appendCombiningMark(ch) {
16530
+ const target = this._findCombiningTarget();
16531
+ if (target === null) {
16532
+ return;
16533
+ }
16534
+ const cell = this._screen[target.y]?.[target.x];
16535
+ if (cell === null || cell === void 0) {
16536
+ return;
16537
+ }
16538
+ cell[1] += ch;
16539
+ }
16540
+ _findCombiningTarget() {
16541
+ const startX = this._pendingWrap ? this._cursorX : this._cursorX - 1;
16542
+ for (let y = this._cursorY; y >= 0; y -= 1) {
16543
+ const row = this._screen[y];
16544
+ if (row === void 0) {
16545
+ continue;
16546
+ }
16547
+ for (let x = y === this._cursorY ? startX : this._cols - 1; x >= 0; x -= 1) {
16548
+ if (row[x] !== null) {
16549
+ return { x, y };
16550
+ }
16551
+ }
16552
+ }
16553
+ return null;
16554
+ }
15813
16555
  _setChar(y, x, ch) {
15814
16556
  const row = this._screen[y];
15815
16557
  if (row && x >= 0 && x < this._cols) {
@@ -15950,7 +16692,8 @@ var TerminalBuffer = class {
15950
16692
  case "J":
15951
16693
  if (p0 === 0) {
15952
16694
  this._eraseLine(this._cursorY, this._cursorX, this._cols - 1);
15953
- for (let y = this._cursorY + 1; y < this._rows; y++) this._eraseLine(y, 0, this._cols - 1);
16695
+ for (let y = this._cursorY + 1; y < this._rows; y++)
16696
+ this._eraseLine(y, 0, this._cols - 1);
15954
16697
  } else if (p0 === 1) {
15955
16698
  for (let y = 0; y < this._cursorY; y++) this._eraseLine(y, 0, this._cols - 1);
15956
16699
  this._eraseLine(this._cursorY, 0, this._cursorX);
@@ -16315,6 +17058,9 @@ function createDefaultStyleState() {
16315
17058
  strikethrough: false
16316
17059
  };
16317
17060
  }
17061
+ function isCombiningCodePoint2(codePoint) {
17062
+ return codePoint >= 768 && codePoint <= 879 || codePoint >= 6832 && codePoint <= 6911 || codePoint >= 7616 && codePoint <= 7679 || codePoint >= 8400 && codePoint <= 8447 || codePoint >= 65056 && codePoint <= 65071;
17063
+ }
16318
17064
  function serializeStyleState(state) {
16319
17065
  const codes = [];
16320
17066
  if (state.bold) {
@@ -16368,6 +17114,8 @@ var NAMED_KEY_LOWER = new Map(
16368
17114
  Object.entries(NAMED_KEY_SEQUENCES).map(([k, v]) => [k.toLowerCase(), v])
16369
17115
  );
16370
17116
  var VALID_KEYS_HINT = `Valid keys: ${Object.keys(NAMED_KEY_SEQUENCES).join(", ")}, Control+<letter>, Alt+<key>`;
17117
+ var NAMED_KEY_PATTERN = Object.keys(NAMED_KEY_SEQUENCES).map(caseInsensitivePattern).join("|");
17118
+ var TERMINAL_KEY_PATTERN = `^(?:${NAMED_KEY_PATTERN}|.|[Cc][Oo][Nn][Tt][Rr][Oo][Ll]\\+[A-Za-z]|[Aa][Ll][Tt]\\+.+)$`;
16371
17119
  function unknownKeyError(key2) {
16372
17120
  return new Error(`Unknown terminal key: ${key2}. ${VALID_KEYS_HINT}`);
16373
17121
  }
@@ -16410,6 +17158,18 @@ function controlKeyToSequence(controlKey) {
16410
17158
  }
16411
17159
  return String.fromCharCode(charCode - 64);
16412
17160
  }
17161
+ function caseInsensitivePattern(value) {
17162
+ let pattern = "";
17163
+ for (const character of value) {
17164
+ const lower = character.toLowerCase();
17165
+ const upper = character.toUpperCase();
17166
+ pattern += lower === upper ? escapePatternCharacter(character) : `[${upper}${lower}]`;
17167
+ }
17168
+ return pattern;
17169
+ }
17170
+ function escapePatternCharacter(character) {
17171
+ return character.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
17172
+ }
16413
17173
 
16414
17174
  // src/terminal-screen.ts
16415
17175
  var TerminalScreen = class {
@@ -16420,12 +17180,12 @@ var TerminalScreen = class {
16420
17180
  constructor({
16421
17181
  lines,
16422
17182
  rawLines,
16423
- cursor,
17183
+ cursor: cursor2,
16424
17184
  size
16425
17185
  }) {
16426
17186
  this.lines = Object.freeze(lines.map((line) => stripAnsi4(line)));
16427
17187
  this.rawLines = Object.freeze([...rawLines]);
16428
- this.cursor = Object.freeze({ ...cursor });
17188
+ this.cursor = Object.freeze({ ...cursor2 });
16429
17189
  this.size = Object.freeze({ ...size });
16430
17190
  Object.freeze(this);
16431
17191
  }
@@ -16461,7 +17221,7 @@ var TerminalSession = class {
16461
17221
  exitCode = null;
16462
17222
  pty;
16463
17223
  terminal;
16464
- emitter = new EventEmitter();
17224
+ emitter = new EventEmitter2();
16465
17225
  exitPromise;
16466
17226
  rawBuffer = "";
16467
17227
  lastDataAt = Date.now();
@@ -16509,14 +17269,14 @@ var TerminalSession = class {
16509
17269
  });
16510
17270
  });
16511
17271
  }
16512
- async type(text5) {
16513
- for (const character of text5) {
17272
+ async type(text4) {
17273
+ for (const character of text4) {
16514
17274
  await this.send(character);
16515
17275
  await sleep(TYPE_DELAY_MS);
16516
17276
  }
16517
17277
  }
16518
- async fill(text5) {
16519
- await this.send(text5.replace(/\r?\n/g, "\r"));
17278
+ async fill(text4) {
17279
+ await this.send(text4.replace(/\r?\n/g, "\r"));
16520
17280
  }
16521
17281
  async press(key2) {
16522
17282
  await this.send(keyToSequence(key2));
@@ -16738,25 +17498,25 @@ function splitHistoryLines(input) {
16738
17498
  function normalizeHistoryBuffer(input) {
16739
17499
  let output = "";
16740
17500
  let line = "";
16741
- let cursor = 0;
17501
+ let cursor2 = 0;
16742
17502
  for (const character of input) {
16743
17503
  if (character === "\r") {
16744
- cursor = 0;
17504
+ cursor2 = 0;
16745
17505
  continue;
16746
17506
  }
16747
17507
  if (character === "\b") {
16748
- cursor = Math.max(0, cursor - 1);
17508
+ cursor2 = Math.max(0, cursor2 - 1);
16749
17509
  continue;
16750
17510
  }
16751
17511
  if (character === "\n") {
16752
17512
  output += `${line}
16753
17513
  `;
16754
17514
  line = "";
16755
- cursor = 0;
17515
+ cursor2 = 0;
16756
17516
  continue;
16757
17517
  }
16758
- line = `${line.slice(0, cursor)}${character}${line.slice(cursor + 1)}`;
16759
- cursor += 1;
17518
+ line = `${line.slice(0, cursor2)}${character}${line.slice(cursor2 + 1)}`;
17519
+ cursor2 += 1;
16760
17520
  }
16761
17521
  return output + line;
16762
17522
  }
@@ -16849,7 +17609,11 @@ function createTerminalPilotRuntime(options = {}) {
16849
17609
  const pendingNames = /* @__PURE__ */ new Set();
16850
17610
  let pilotPromise;
16851
17611
  function getRequestedName(name, env) {
16852
- return name ?? env?.get(SESSION_ENV_VAR);
17612
+ const requestedName = name ?? env?.get(SESSION_ENV_VAR);
17613
+ if (requestedName !== void 0 && requestedName.trim().length === 0) {
17614
+ throw new UserError("Session name must not be empty.");
17615
+ }
17616
+ return requestedName;
16853
17617
  }
16854
17618
  async function getPilot() {
16855
17619
  pilotPromise ??= launchPilot();
@@ -16885,7 +17649,9 @@ function createTerminalPilotRuntime(options = {}) {
16885
17649
  const sessionId = nameToId.get(name);
16886
17650
  if (sessionId === void 0) {
16887
17651
  const active = await listSessions2();
16888
- throw new UserError(`Session "${name}" was not found. ${formatAvailableSessions(active.map((entry) => entry.name))}`);
17652
+ throw new UserError(
17653
+ `Session "${name}" was not found. ${formatAvailableSessions(active.map((entry) => entry.name))}`
17654
+ );
16889
17655
  }
16890
17656
  const pilot = await getPilot();
16891
17657
  try {
@@ -16893,7 +17659,9 @@ function createTerminalPilotRuntime(options = {}) {
16893
17659
  } catch {
16894
17660
  forgetSession(name, sessionId);
16895
17661
  const active = await listSessions2();
16896
- throw new UserError(`Session "${name}" was not found. ${formatAvailableSessions(active.map((entry) => entry.name))}`);
17662
+ throw new UserError(
17663
+ `Session "${name}" was not found. ${formatAvailableSessions(active.map((entry) => entry.name))}`
17664
+ );
16897
17665
  }
16898
17666
  }
16899
17667
  async function listSessions2() {
@@ -16924,6 +17692,9 @@ function createTerminalPilotRuntime(options = {}) {
16924
17692
  }
16925
17693
  return {
16926
17694
  async createSession(params17, env) {
17695
+ if (params17.command.trim().length === 0) {
17696
+ throw new UserError("Command must not be empty.");
17697
+ }
16927
17698
  const requestedName = getRequestedName(params17.session, env) ?? nextSessionName();
16928
17699
  await discardExitedSessionName(requestedName);
16929
17700
  if (nameToId.has(requestedName) || pendingNames.has(requestedName)) {
@@ -16989,7 +17760,9 @@ function createTerminalPilotRuntime(options = {}) {
16989
17760
 
16990
17761
  // src/commands/close-session.ts
16991
17762
  var params = S.Object({
16992
- session: S.Optional(S.String({ short: "s", description: "Session name" }))
17763
+ session: S.Optional(
17764
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
17765
+ )
16993
17766
  });
16994
17767
  var closeSession = defineCommand({
16995
17768
  name: "close-session",
@@ -16997,19 +17770,28 @@ var closeSession = defineCommand({
16997
17770
  scope: ["cli", "mcp", "sdk"],
16998
17771
  params,
16999
17772
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
17000
- const { exitCode } = await getTerminalPilotRuntime(terminalPilotRuntime).closeSession(params17.session, env);
17773
+ const { exitCode } = await getTerminalPilotRuntime(terminalPilotRuntime).closeSession(
17774
+ params17.session,
17775
+ env
17776
+ );
17001
17777
  return { exitCode };
17002
17778
  }
17003
17779
  });
17004
17780
 
17005
17781
  // src/commands/create-session.ts
17006
17782
  var params2 = S.Object({
17007
- command: S.String({ description: "Command to execute" }),
17783
+ command: S.String({ description: "Command to execute", minLength: 1, pattern: "\\S" }),
17008
17784
  args: S.Optional(S.Array(S.String(), { description: "Command arguments" })),
17009
- session: S.Optional(S.String({ short: "s", description: "Session name" })),
17785
+ session: S.Optional(
17786
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
17787
+ ),
17010
17788
  cwd: S.Optional(S.String({ description: "Working directory" })),
17011
- cols: S.Optional(S.Number({ description: "Terminal width in columns" })),
17012
- rows: S.Optional(S.Number({ description: "Terminal height in rows" })),
17789
+ cols: S.Optional(
17790
+ S.Number({ description: "Terminal width in columns", jsonType: "integer", minimum: 1 })
17791
+ ),
17792
+ rows: S.Optional(
17793
+ S.Number({ description: "Terminal height in rows", jsonType: "integer", minimum: 1 })
17794
+ ),
17013
17795
  observe: S.Optional(S.Boolean({ description: "Mirror PTY output to stderr" }))
17014
17796
  });
17015
17797
  var createSession = defineCommand({
@@ -17019,7 +17801,10 @@ var createSession = defineCommand({
17019
17801
  positional: ["command", "args"],
17020
17802
  params: params2,
17021
17803
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
17022
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).createSession(params17, env);
17804
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).createSession(
17805
+ params17,
17806
+ env
17807
+ );
17023
17808
  return { session: namedSession.name, pid: namedSession.session.pid };
17024
17809
  }
17025
17810
  });
@@ -17027,7 +17812,9 @@ var createSession = defineCommand({
17027
17812
  // src/commands/fill.ts
17028
17813
  var params3 = S.Object({
17029
17814
  text: S.String({ description: "Text to write to the session" }),
17030
- session: S.Optional(S.String({ short: "s", description: "Session name" }))
17815
+ session: S.Optional(
17816
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
17817
+ )
17031
17818
  });
17032
17819
  var fill = defineCommand({
17033
17820
  name: "fill",
@@ -17036,7 +17823,10 @@ var fill = defineCommand({
17036
17823
  positional: ["text"],
17037
17824
  params: params3,
17038
17825
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
17039
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
17826
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
17827
+ params17.session,
17828
+ env
17829
+ );
17040
17830
  await namedSession.session.fill(params17.text);
17041
17831
  return void 0;
17042
17832
  }
@@ -17044,7 +17834,9 @@ var fill = defineCommand({
17044
17834
 
17045
17835
  // src/commands/get-session.ts
17046
17836
  var params4 = S.Object({
17047
- session: S.Optional(S.String({ short: "s", description: "Session name" }))
17837
+ session: S.Optional(
17838
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
17839
+ )
17048
17840
  });
17049
17841
  var getSession = defineCommand({
17050
17842
  name: "get-session",
@@ -17052,7 +17844,10 @@ var getSession = defineCommand({
17052
17844
  scope: ["cli", "mcp", "sdk"],
17053
17845
  params: params4,
17054
17846
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
17055
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
17847
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
17848
+ params17.session,
17849
+ env
17850
+ );
17056
17851
  return {
17057
17852
  session: namedSession.name,
17058
17853
  pid: namedSession.session.pid,
@@ -17080,7 +17875,7 @@ var claudeCodeAgent = {
17080
17875
  CLAUDE_CODE_ENABLE_TELEMETRY: "1"
17081
17876
  }
17082
17877
  },
17083
- configPath: "~/.claude/settings.json",
17878
+ configPath: "~/.claude.json",
17084
17879
  branding: {
17085
17880
  colors: {
17086
17881
  dark: "#C15F3C",
@@ -17095,7 +17890,12 @@ var claudeDesktopAgent = {
17095
17890
  name: "claude-desktop",
17096
17891
  label: "Claude Desktop",
17097
17892
  summary: "Anthropic's official desktop application for Claude",
17098
- configPath: "~/.claude/settings.json",
17893
+ configPath: "~/.config/Claude/claude_desktop_config.json",
17894
+ configPaths: {
17895
+ darwin: "~/Library/Application Support/Claude/claude_desktop_config.json",
17896
+ linux: "~/.config/Claude/claude_desktop_config.json",
17897
+ win32: "~/AppData/Roaming/Claude/claude_desktop_config.json"
17898
+ },
17099
17899
  branding: {
17100
17900
  colors: {
17101
17901
  dark: "#D97757",
@@ -17139,7 +17939,7 @@ var cursorAgent = {
17139
17939
  label: "Cursor",
17140
17940
  summary: "Cursor's CLI coding agent.",
17141
17941
  binaryName: "cursor-agent",
17142
- configPath: "~/.cursor/cli-config.json",
17942
+ configPath: "~/.cursor/mcp.json",
17143
17943
  branding: {
17144
17944
  colors: {
17145
17945
  dark: "#FFFFFF",
@@ -17179,7 +17979,7 @@ var openCodeAgent = {
17179
17979
  OPENCODE_CONFIG_CONTENT: '{"experimental":{"openTelemetry":true}}'
17180
17980
  }
17181
17981
  },
17182
- configPath: "~/.config/opencode/config.json",
17982
+ configPath: "~/.config/opencode/opencode.json",
17183
17983
  branding: {
17184
17984
  colors: {
17185
17985
  dark: "#4A4F55",
@@ -17197,7 +17997,7 @@ var kimiAgent = {
17197
17997
  aliases: ["kimi-cli"],
17198
17998
  binaryName: "kimi",
17199
17999
  apiShapes: ["openai-chat-completions"],
17200
- configPath: "~/.kimi/config.toml",
18000
+ configPath: "~/.kimi/mcp.json",
17201
18001
  branding: {
17202
18002
  colors: {
17203
18003
  dark: "#7B68EE",
@@ -17468,7 +18268,7 @@ function detectIndent(content) {
17468
18268
  }
17469
18269
  return " ";
17470
18270
  }
17471
- function parse3(content) {
18271
+ function parse4(content) {
17472
18272
  if (!content || content.trim() === "") {
17473
18273
  return {};
17474
18274
  }
@@ -17593,7 +18393,7 @@ function applyObjectUpdate(content, path24, current, next) {
17593
18393
  return result;
17594
18394
  }
17595
18395
  var jsonFormat = {
17596
- parse: parse3,
18396
+ parse: parse4,
17597
18397
  serialize,
17598
18398
  serializeUpdate,
17599
18399
  merge,
@@ -17605,7 +18405,7 @@ import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
17605
18405
  function isConfigObject2(value) {
17606
18406
  return typeof value === "object" && value !== null && !Array.isArray(value);
17607
18407
  }
17608
- function parse4(content) {
18408
+ function parse5(content) {
17609
18409
  if (!content || content.trim() === "") {
17610
18410
  return {};
17611
18411
  }
@@ -17671,7 +18471,7 @@ function prune2(obj, shape) {
17671
18471
  return { changed, result };
17672
18472
  }
17673
18473
  var tomlFormat = {
17674
- parse: parse4,
18474
+ parse: parse5,
17675
18475
  serialize: serialize2,
17676
18476
  merge: merge2,
17677
18477
  prune: prune2
@@ -17682,7 +18482,7 @@ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
17682
18482
  function isConfigObject3(value) {
17683
18483
  return typeof value === "object" && value !== null && !Array.isArray(value);
17684
18484
  }
17685
- function parse5(content) {
18485
+ function parse6(content) {
17686
18486
  if (!content || content.trim() === "") {
17687
18487
  return {};
17688
18488
  }
@@ -17748,7 +18548,7 @@ function prune3(obj, shape) {
17748
18548
  return { changed, result };
17749
18549
  }
17750
18550
  var yamlFormat = {
17751
- parse: parse5,
18551
+ parse: parse6,
17752
18552
  serialize: serialize3,
17753
18553
  merge: merge3,
17754
18554
  prune: prune3
@@ -18897,8 +19697,10 @@ var listSessions = defineCommand({
18897
19697
 
18898
19698
  // src/commands/press-key.ts
18899
19699
  var params7 = S.Object({
18900
- key: S.String({ description: "Named key to press" }),
18901
- session: S.Optional(S.String({ short: "s", description: "Session name" }))
19700
+ key: S.String({ description: "Named key to press", pattern: TERMINAL_KEY_PATTERN }),
19701
+ session: S.Optional(
19702
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
19703
+ )
18902
19704
  });
18903
19705
  var pressKey = defineCommand({
18904
19706
  name: "press-key",
@@ -18907,16 +19709,36 @@ var pressKey = defineCommand({
18907
19709
  positional: ["key"],
18908
19710
  params: params7,
18909
19711
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
18910
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
19712
+ assertTerminalKey(params17.key);
19713
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
19714
+ params17.session,
19715
+ env
19716
+ );
18911
19717
  await namedSession.session.press(params17.key);
18912
19718
  return void 0;
18913
19719
  }
18914
19720
  });
19721
+ function assertTerminalKey(key2) {
19722
+ try {
19723
+ keyToSequence(key2);
19724
+ } catch (error3) {
19725
+ throw new UserError(error3 instanceof Error ? error3.message : String(error3));
19726
+ }
19727
+ }
18915
19728
 
18916
19729
  // src/commands/read-history.ts
18917
19730
  var params8 = S.Object({
18918
- session: S.Optional(S.String({ short: "s", description: "Session name" })),
18919
- last: S.Optional(S.Number({ short: "n", description: "Return only the last N lines" }))
19731
+ session: S.Optional(
19732
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
19733
+ ),
19734
+ last: S.Optional(
19735
+ S.Number({
19736
+ short: "n",
19737
+ description: "Return only the last N lines",
19738
+ jsonType: "integer",
19739
+ minimum: 0
19740
+ })
19741
+ )
18920
19742
  });
18921
19743
  var readHistory = defineCommand({
18922
19744
  name: "read-history",
@@ -18924,7 +19746,10 @@ var readHistory = defineCommand({
18924
19746
  scope: ["cli", "mcp", "sdk"],
18925
19747
  params: params8,
18926
19748
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
18927
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
19749
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
19750
+ params17.session,
19751
+ env
19752
+ );
18928
19753
  const lines = await namedSession.session.history({ last: params17.last });
18929
19754
  return { lines, exitCode: namedSession.session.exitCode };
18930
19755
  }
@@ -18932,7 +19757,9 @@ var readHistory = defineCommand({
18932
19757
 
18933
19758
  // src/commands/read-screen.ts
18934
19759
  var params9 = S.Object({
18935
- session: S.Optional(S.String({ short: "s", description: "Session name" }))
19760
+ session: S.Optional(
19761
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
19762
+ )
18936
19763
  });
18937
19764
  var readScreen = defineCommand({
18938
19765
  name: "read-screen",
@@ -18940,7 +19767,10 @@ var readScreen = defineCommand({
18940
19767
  scope: ["cli", "mcp", "sdk"],
18941
19768
  params: params9,
18942
19769
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
18943
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
19770
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
19771
+ params17.session,
19772
+ env
19773
+ );
18944
19774
  const screen = await namedSession.session.screen();
18945
19775
  return {
18946
19776
  lines: [...screen.lines],
@@ -18953,9 +19783,11 @@ var readScreen = defineCommand({
18953
19783
 
18954
19784
  // src/commands/resize.ts
18955
19785
  var params10 = S.Object({
18956
- cols: S.Number({ description: "Terminal width in columns" }),
18957
- rows: S.Number({ description: "Terminal height in rows" }),
18958
- session: S.Optional(S.String({ short: "s", description: "Session name" }))
19786
+ cols: S.Number({ description: "Terminal width in columns", jsonType: "integer", minimum: 1 }),
19787
+ rows: S.Number({ description: "Terminal height in rows", jsonType: "integer", minimum: 1 }),
19788
+ session: S.Optional(
19789
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
19790
+ )
18959
19791
  });
18960
19792
  var resize = defineCommand({
18961
19793
  name: "resize",
@@ -18963,7 +19795,10 @@ var resize = defineCommand({
18963
19795
  scope: ["cli", "mcp", "sdk"],
18964
19796
  params: params10,
18965
19797
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
18966
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
19798
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
19799
+ params17.session,
19800
+ env
19801
+ );
18967
19802
  await namedSession.session.resize(params17.cols, params17.rows);
18968
19803
  return void 0;
18969
19804
  }
@@ -18975,6 +19810,9 @@ import { rename as rename4, rm, writeFile as writeFile6 } from "node:fs/promises
18975
19810
 
18976
19811
  // ../terminal-png/src/ansi-parser.ts
18977
19812
  var ESC2 = "\x1B";
19813
+ var TAB_WIDTH = 8;
19814
+ var MAX_TERMINAL_ROWS = 1e3;
19815
+ var MAX_TERMINAL_COLUMNS = 1e3;
18978
19816
  function createDefaultStyle() {
18979
19817
  return {
18980
19818
  fg: null,
@@ -19009,17 +19847,17 @@ function colorsEqual(left, right) {
19009
19847
  }
19010
19848
  return false;
19011
19849
  }
19012
- function pushRun(runs, style, text5) {
19013
- if (text5.length === 0) {
19850
+ function pushRun(runs, style, text4) {
19851
+ if (text4.length === 0) {
19014
19852
  return;
19015
19853
  }
19016
19854
  const previous = runs.at(-1);
19017
- if (previous && text5 !== "\n" && previous.text !== "\n" && stylesEqual(previous, style)) {
19018
- previous.text += text5;
19855
+ if (previous && text4 !== "\n" && previous.text !== "\n" && stylesEqual(previous, style)) {
19856
+ previous.text += text4;
19019
19857
  return;
19020
19858
  }
19021
19859
  runs.push({
19022
- text: text5,
19860
+ text: text4,
19023
19861
  fg: style.fg,
19024
19862
  bg: style.bg,
19025
19863
  bold: style.bold,
@@ -19259,10 +20097,34 @@ function positionParameter(params17, index, fallback) {
19259
20097
  const value = toInteger(params17.split(";")[index]);
19260
20098
  return value === null || value < 1 ? fallback : value;
19261
20099
  }
20100
+ function modeParameter(params17, fallback) {
20101
+ const value = toInteger(params17.split(";")[0]);
20102
+ return value === null ? fallback : value;
20103
+ }
20104
+ function displayWidth3(text4) {
20105
+ if (text4 === " ") {
20106
+ return TAB_WIDTH;
20107
+ }
20108
+ const codePoint = text4.codePointAt(0);
20109
+ if (codePoint === void 0) {
20110
+ return 0;
20111
+ }
20112
+ if (codePoint >= 4352 && codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || codePoint >= 11904 && codePoint <= 42191 && codePoint !== 12351 || codePoint >= 44032 && codePoint <= 55203 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 65040 && codePoint <= 65049 || codePoint >= 65072 && codePoint <= 65135 || codePoint >= 65280 && codePoint <= 65376 || codePoint >= 65504 && codePoint <= 65510 || codePoint >= 127744 && codePoint <= 128591 || codePoint >= 129280 && codePoint <= 129535 || codePoint >= 131072 && codePoint <= 262141) {
20113
+ return 2;
20114
+ }
20115
+ return 1;
20116
+ }
20117
+ function hasRenderableCell(line) {
20118
+ return (line ?? []).some((cell) => cell !== void 0 && cell.text.length > 0);
20119
+ }
19262
20120
  function buildRuns(lines, lineBreakStyles) {
19263
20121
  const runs = [];
19264
20122
  const defaultStyle = createDefaultStyle();
19265
- for (let row = 0; row < lines.length; row += 1) {
20123
+ let lastRow = lines.length - 1;
20124
+ while (lastRow > 0 && !hasRenderableCell(lines[lastRow]) && lineBreakStyles[lastRow - 1] === void 0) {
20125
+ lastRow -= 1;
20126
+ }
20127
+ for (let row = 0; row <= lastRow; row += 1) {
19266
20128
  const line = lines[row] ?? [];
19267
20129
  let lastCell = line.length - 1;
19268
20130
  while (lastCell >= 0 && line[lastCell] === void 0) {
@@ -19272,7 +20134,7 @@ function buildRuns(lines, lineBreakStyles) {
19272
20134
  const cell = line[column] ?? { text: " ", style: defaultStyle };
19273
20135
  pushRun(runs, cell.style, cell.text);
19274
20136
  }
19275
- if (row < lines.length - 1) {
20137
+ if (row < lastRow) {
19276
20138
  pushRun(runs, lineBreakStyles[row] ?? defaultStyle, "\n");
19277
20139
  }
19278
20140
  }
@@ -19284,7 +20146,21 @@ function parseAnsi2(input) {
19284
20146
  let style = createDefaultStyle();
19285
20147
  let row = 0;
19286
20148
  let column = 0;
20149
+ let savedRow = 0;
20150
+ let savedColumn = 0;
19287
20151
  let index = 0;
20152
+ const clampRow = (nextRow) => {
20153
+ if (nextRow < 0) {
20154
+ return 0;
20155
+ }
20156
+ return Math.min(nextRow, MAX_TERMINAL_ROWS - 1);
20157
+ };
20158
+ const clampColumn = (nextColumn) => {
20159
+ if (nextColumn < 0) {
20160
+ return 0;
20161
+ }
20162
+ return Math.min(nextColumn, MAX_TERMINAL_COLUMNS - 1);
20163
+ };
19288
20164
  const ensureLine = () => {
19289
20165
  while (lines.length <= row) {
19290
20166
  lines.push([]);
@@ -19292,12 +20168,64 @@ function parseAnsi2(input) {
19292
20168
  };
19293
20169
  const moveDown = (keepColumn) => {
19294
20170
  lineBreakStyles[row] = cloneStyle(style);
19295
- row += 1;
20171
+ row = clampRow(row + 1);
19296
20172
  if (!keepColumn) {
19297
20173
  column = 0;
19298
20174
  }
19299
20175
  ensureLine();
19300
20176
  };
20177
+ const eraseLine = (mode) => {
20178
+ const line = lines[row] ?? [];
20179
+ if (mode === 1) {
20180
+ for (let cell = 0; cell <= column; cell += 1) {
20181
+ delete line[cell];
20182
+ }
20183
+ return;
20184
+ }
20185
+ if (mode === 2) {
20186
+ lines[row] = [];
20187
+ return;
20188
+ }
20189
+ line.splice(column);
20190
+ };
20191
+ const eraseDisplay = (mode) => {
20192
+ if (mode === 1) {
20193
+ for (let lineRow = 0; lineRow < row; lineRow += 1) {
20194
+ lines[lineRow] = [];
20195
+ }
20196
+ eraseLine(1);
20197
+ return;
20198
+ }
20199
+ if (mode === 2 || mode === 3) {
20200
+ lines.length = 0;
20201
+ lineBreakStyles.length = 0;
20202
+ ensureLine();
20203
+ return;
20204
+ }
20205
+ eraseLine(0);
20206
+ lines.splice(row + 1);
20207
+ lineBreakStyles.splice(row);
20208
+ };
20209
+ const saveCursor = () => {
20210
+ savedRow = row;
20211
+ savedColumn = column;
20212
+ };
20213
+ const restoreCursor = () => {
20214
+ row = clampRow(savedRow);
20215
+ column = clampColumn(savedColumn);
20216
+ ensureLine();
20217
+ };
20218
+ const writeText = (text4) => {
20219
+ const width = displayWidth3(text4);
20220
+ if (width === 0) {
20221
+ return;
20222
+ }
20223
+ lines[row][column] = { text: text4, style: cloneStyle(style) };
20224
+ for (let offset = 1; offset < width && column + offset < MAX_TERMINAL_COLUMNS; offset += 1) {
20225
+ lines[row][column + offset] = { text: "", style: cloneStyle(style) };
20226
+ }
20227
+ column = clampColumn(column + width);
20228
+ };
19301
20229
  while (index < input.length) {
19302
20230
  const char = input[index];
19303
20231
  if (char === "\n") {
@@ -19320,39 +20248,74 @@ function parseAnsi2(input) {
19320
20248
  index += 1;
19321
20249
  continue;
19322
20250
  }
20251
+ if (char === " ") {
20252
+ const nextTabStop = Math.min(
20253
+ Math.floor(column / TAB_WIDTH) * TAB_WIDTH + TAB_WIDTH,
20254
+ MAX_TERMINAL_COLUMNS
20255
+ );
20256
+ while (column < nextTabStop) {
20257
+ writeText(" ");
20258
+ }
20259
+ index += 1;
20260
+ continue;
20261
+ }
19323
20262
  if (char === ESC2 && input[index + 1] === "]") {
19324
20263
  index = parseOscEnd(input, index);
19325
20264
  continue;
19326
20265
  }
20266
+ if (char === ESC2 && input[index + 1] === "7") {
20267
+ saveCursor();
20268
+ index += 2;
20269
+ continue;
20270
+ }
20271
+ if (char === ESC2 && input[index + 1] === "8") {
20272
+ restoreCursor();
20273
+ index += 2;
20274
+ continue;
20275
+ }
19327
20276
  const csiPrefixLength = char === "\x9B" ? 1 : char === ESC2 && input[index + 1] === "[" ? 2 : null;
19328
20277
  if (csiPrefixLength !== null) {
19329
20278
  const sequence = parseCsi(input, index, csiPrefixLength);
19330
20279
  if (sequence.final === "m") {
19331
20280
  style = applySgr(style, sequence.params);
19332
20281
  } else if (sequence.final === "G") {
19333
- column = positionParameter(sequence.params, 0, 1) - 1;
20282
+ column = clampColumn(positionParameter(sequence.params, 0, 1) - 1);
19334
20283
  } else if (sequence.final === "C") {
19335
- column += positionParameter(sequence.params, 0, 1);
20284
+ column = clampColumn(column + positionParameter(sequence.params, 0, 1));
19336
20285
  } else if (sequence.final === "D") {
19337
20286
  column = Math.max(0, column - positionParameter(sequence.params, 0, 1));
19338
20287
  } else if (sequence.final === "A") {
19339
- row = Math.max(0, row - positionParameter(sequence.params, 0, 1));
20288
+ row = clampRow(row - positionParameter(sequence.params, 0, 1));
19340
20289
  } else if (sequence.final === "B") {
19341
- row += positionParameter(sequence.params, 0, 1);
20290
+ row = clampRow(row + positionParameter(sequence.params, 0, 1));
19342
20291
  ensureLine();
20292
+ } else if (sequence.final === "E") {
20293
+ row = clampRow(row + positionParameter(sequence.params, 0, 1));
20294
+ column = 0;
20295
+ ensureLine();
20296
+ } else if (sequence.final === "F") {
20297
+ row = clampRow(row - positionParameter(sequence.params, 0, 1));
20298
+ column = 0;
19343
20299
  } else if (sequence.final === "H" || sequence.final === "f") {
19344
- row = positionParameter(sequence.params, 0, 1) - 1;
19345
- column = positionParameter(sequence.params, 1, 1) - 1;
20300
+ row = clampRow(positionParameter(sequence.params, 0, 1) - 1);
20301
+ column = clampColumn(positionParameter(sequence.params, 1, 1) - 1);
19346
20302
  ensureLine();
20303
+ } else if (sequence.final === "K") {
20304
+ eraseLine(modeParameter(sequence.params, 0));
20305
+ } else if (sequence.final === "J") {
20306
+ eraseDisplay(modeParameter(sequence.params, 0));
20307
+ } else if (sequence.final === "s") {
20308
+ saveCursor();
20309
+ } else if (sequence.final === "u") {
20310
+ restoreCursor();
19347
20311
  }
19348
20312
  index = sequence.end;
19349
20313
  continue;
19350
20314
  }
19351
20315
  const codePoint = input.codePointAt(index);
19352
- const text5 = codePoint === void 0 ? "" : String.fromCodePoint(codePoint);
19353
- lines[row][column] = { text: text5, style: cloneStyle(style) };
19354
- column += 1;
19355
- index += text5.length;
20316
+ const text4 = codePoint === void 0 ? "" : String.fromCodePoint(codePoint);
20317
+ writeText(text4);
20318
+ index += text4.length;
19356
20319
  }
19357
20320
  return buildRuns(lines, lineBreakStyles);
19358
20321
  }
@@ -19759,14 +20722,14 @@ function splitIntoLines(runs) {
19759
20722
  }
19760
20723
  function measureLines(lines) {
19761
20724
  return Math.max(
19762
- ...lines.map((line) => displayWidth3(line.map((run) => run.text).join("")) * CHARACTER_WIDTH),
20725
+ ...lines.map((line) => displayWidth4(line.map((run) => run.text).join("")) * CHARACTER_WIDTH),
19763
20726
  0
19764
20727
  );
19765
20728
  }
19766
- function displayWidth3(text5, startColumn = 0) {
20729
+ function displayWidth4(text4, startColumn = 0) {
19767
20730
  const segmenter = new Intl.Segmenter();
19768
20731
  let column = startColumn;
19769
- for (const { segment } of segmenter.segment(text5)) {
20732
+ for (const { segment } of segmenter.segment(text4)) {
19770
20733
  if (segment === " ") {
19771
20734
  column += 8 - column % 8;
19772
20735
  continue;
@@ -19825,7 +20788,7 @@ function renderBackgrounds(line, startX, y, height) {
19825
20788
  let column = 0;
19826
20789
  const rectangles = [];
19827
20790
  for (const run of line) {
19828
- const width = displayWidth3(run.text, column);
20791
+ const width = displayWidth4(run.text, column);
19829
20792
  const background = resolveBackgroundColor(run);
19830
20793
  if (background !== BACKGROUND && width > 0) {
19831
20794
  rectangles.push(`<rect x="${formatNumber(startX + column * CHARACTER_WIDTH)}" y="${formatNumber(y)}" width="${formatNumber(width * CHARACTER_WIDTH)}" height="${formatNumber(height)}" fill="${escapeXmlAttribute(background)}" />`);
@@ -19859,8 +20822,8 @@ function renderRun(run) {
19859
20822
  if (run.dim) {
19860
20823
  attributes.push('opacity="0.7"');
19861
20824
  }
19862
- const text5 = run.conceal ? " ".repeat(displayWidth3(run.text)) : run.text;
19863
- return `<tspan ${attributes.join(" ")}>${escapeXmlText(text5)}</tspan>`;
20825
+ const text4 = run.conceal ? " ".repeat(displayWidth4(run.text)) : run.text;
20826
+ return `<tspan ${attributes.join(" ")}>${escapeXmlText(text4)}</tspan>`;
19864
20827
  }
19865
20828
  function renderWindowControls() {
19866
20829
  return [
@@ -19908,13 +20871,16 @@ async function renderTerminalPng(ansiText, options = {}) {
19908
20871
  if (options.padding !== void 0 && (!Number.isInteger(options.padding) || options.padding < 0)) {
19909
20872
  throw new Error("Padding must be a non-negative integer.");
19910
20873
  }
20874
+ if (options.output !== void 0 && options.output.length === 0) {
20875
+ throw new Error("Output path must not be empty.");
20876
+ }
19911
20877
  const runs = parseAnsi2(ansiText);
19912
20878
  const svg = renderSvg(runs, {
19913
20879
  padding: options.padding,
19914
20880
  window: options.window
19915
20881
  });
19916
20882
  const png = renderPng(svg);
19917
- if (options.output) {
20883
+ if (options.output !== void 0) {
19918
20884
  const temporaryPath = `${options.output}.${randomUUID10()}.tmp`;
19919
20885
  let temporaryCreated = false;
19920
20886
  try {
@@ -19940,10 +20906,19 @@ function isAlreadyExistsError3(error3) {
19940
20906
 
19941
20907
  // src/commands/screenshot.ts
19942
20908
  var params11 = S.Object({
19943
- session: S.Optional(S.String({ short: "s", description: "Session name" })),
20909
+ session: S.Optional(
20910
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
20911
+ ),
19944
20912
  output: S.String({ short: "o", description: "Path to the output PNG file" }),
19945
20913
  window: S.Optional(S.Boolean({ description: "Include terminal window chrome", default: true })),
19946
- padding: S.Optional(S.Number({ short: "p", description: "Padding around terminal content" }))
20914
+ padding: S.Optional(
20915
+ S.Number({
20916
+ short: "p",
20917
+ description: "Padding around terminal content",
20918
+ jsonType: "integer",
20919
+ minimum: 0
20920
+ })
20921
+ )
19947
20922
  });
19948
20923
  var screenshot = defineCommand({
19949
20924
  name: "screenshot",
@@ -19951,7 +20926,10 @@ var screenshot = defineCommand({
19951
20926
  scope: ["cli"],
19952
20927
  params: params11,
19953
20928
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
19954
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
20929
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
20930
+ params17.session,
20931
+ env
20932
+ );
19955
20933
  const screen = await namedSession.session.screen();
19956
20934
  await renderTerminalPng(screen.rawLines.join("\n"), {
19957
20935
  output: params17.output,
@@ -19965,7 +20943,9 @@ var screenshot = defineCommand({
19965
20943
  // src/commands/send-signal.ts
19966
20944
  var params12 = S.Object({
19967
20945
  signal: S.String({ description: "Signal to send to the session process" }),
19968
- session: S.Optional(S.String({ short: "s", description: "Session name" }))
20946
+ session: S.Optional(
20947
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
20948
+ )
19969
20949
  });
19970
20950
  var sendSignal = defineCommand({
19971
20951
  name: "send-signal",
@@ -19974,7 +20954,10 @@ var sendSignal = defineCommand({
19974
20954
  positional: ["signal"],
19975
20955
  params: params12,
19976
20956
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
19977
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
20957
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
20958
+ params17.session,
20959
+ env
20960
+ );
19978
20961
  await namedSession.session.signal(params17.signal);
19979
20962
  return void 0;
19980
20963
  }
@@ -19983,7 +20966,9 @@ var sendSignal = defineCommand({
19983
20966
  // src/commands/type.ts
19984
20967
  var params13 = S.Object({
19985
20968
  text: S.String({ description: "Text to write to the session" }),
19986
- session: S.Optional(S.String({ short: "s", description: "Session name" }))
20969
+ session: S.Optional(
20970
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
20971
+ )
19987
20972
  });
19988
20973
  var type = defineCommand({
19989
20974
  name: "type",
@@ -19992,7 +20977,10 @@ var type = defineCommand({
19992
20977
  positional: ["text"],
19993
20978
  params: params13,
19994
20979
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
19995
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
20980
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
20981
+ params17.session,
20982
+ env
20983
+ );
19996
20984
  await namedSession.session.type(params17.text);
19997
20985
  return void 0;
19998
20986
  }
@@ -20070,9 +21058,17 @@ async function folderExists(fs4, folderPath) {
20070
21058
 
20071
21059
  // src/commands/wait-for.ts
20072
21060
  var params15 = S.Object({
20073
- pattern: S.String({ description: "Regular expression pattern to wait for" }),
20074
- session: S.Optional(S.String({ short: "s", description: "Session name" })),
20075
- timeout: S.Optional(S.Number({ short: "t", description: "Maximum wait time in milliseconds" })),
21061
+ pattern: S.String({
21062
+ description: "Regular expression pattern to wait for",
21063
+ minLength: 1,
21064
+ pattern: "\\S"
21065
+ }),
21066
+ session: S.Optional(
21067
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
21068
+ ),
21069
+ timeout: S.Optional(
21070
+ S.Number({ short: "t", description: "Maximum wait time in milliseconds", minimum: 0 })
21071
+ ),
20076
21072
  literal: S.Optional(
20077
21073
  S.Boolean({
20078
21074
  short: "l",
@@ -20087,17 +21083,33 @@ var waitFor = defineCommand({
20087
21083
  positional: ["pattern"],
20088
21084
  params: params15,
20089
21085
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
20090
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
21086
+ if (params17.pattern.trim().length === 0) {
21087
+ throw new UserError("Wait pattern must not be empty.");
21088
+ }
21089
+ assertTimeout2(params17.timeout);
21090
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
21091
+ params17.session,
21092
+ env
21093
+ );
20091
21094
  const pattern = params17.literal === true ? params17.pattern : new RegExp(params17.pattern);
20092
21095
  const line = params17.timeout === void 0 ? await namedSession.session.waitFor(pattern) : await namedSession.session.waitFor(pattern, { timeout: params17.timeout });
20093
21096
  return { matched: true, line };
20094
21097
  }
20095
21098
  });
21099
+ function assertTimeout2(timeout) {
21100
+ if (timeout !== void 0 && (!Number.isFinite(timeout) || timeout < 0)) {
21101
+ throw new UserError("Timeout must be a finite non-negative number.");
21102
+ }
21103
+ }
20096
21104
 
20097
21105
  // src/commands/wait-for-exit.ts
20098
21106
  var params16 = S.Object({
20099
- session: S.Optional(S.String({ short: "s", description: "Session name" })),
20100
- timeout: S.Optional(S.Number({ short: "t", description: "Maximum wait time in milliseconds" }))
21107
+ session: S.Optional(
21108
+ S.String({ short: "s", description: "Session name", minLength: 1, pattern: "\\S" })
21109
+ ),
21110
+ timeout: S.Optional(
21111
+ S.Number({ short: "t", description: "Maximum wait time in milliseconds", minimum: 0 })
21112
+ )
20101
21113
  });
20102
21114
  var waitForExit2 = defineCommand({
20103
21115
  name: "wait-for-exit",
@@ -20105,7 +21117,13 @@ var waitForExit2 = defineCommand({
20105
21117
  scope: ["cli", "mcp", "sdk"],
20106
21118
  params: params16,
20107
21119
  handler: async ({ params: params17, env, terminalPilotRuntime }) => {
20108
- const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(params17.session, env);
21120
+ if (params17.timeout !== void 0 && (!Number.isFinite(params17.timeout) || params17.timeout < 0)) {
21121
+ throw new UserError("Timeout must be a finite non-negative number.");
21122
+ }
21123
+ const namedSession = await getTerminalPilotRuntime(terminalPilotRuntime).resolveSession(
21124
+ params17.session,
21125
+ env
21126
+ );
20109
21127
  const exitCode = await namedSession.session.waitForExit(
20110
21128
  params17.timeout === void 0 ? void 0 : { timeout: params17.timeout }
20111
21129
  );