terminal-pilot 0.0.48 → 0.0.50

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 (84) hide show
  1. package/dist/cli.js +584 -163
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.js.map +1 -1
  4. package/dist/commands/create-session.js.map +1 -1
  5. package/dist/commands/daemon-runtime.js.map +1 -1
  6. package/dist/commands/fill.js.map +1 -1
  7. package/dist/commands/get-session.js.map +1 -1
  8. package/dist/commands/index.js +61 -11
  9. package/dist/commands/index.js.map +4 -4
  10. package/dist/commands/install.js +65 -15
  11. package/dist/commands/install.js.map +4 -4
  12. package/dist/commands/installer.js +21 -7
  13. package/dist/commands/installer.js.map +2 -2
  14. package/dist/commands/list-sessions.js.map +1 -1
  15. package/dist/commands/press-key.js.map +1 -1
  16. package/dist/commands/read-history.js.map +1 -1
  17. package/dist/commands/read-screen.js.map +1 -1
  18. package/dist/commands/resize.js.map +1 -1
  19. package/dist/commands/runtime.js.map +1 -1
  20. package/dist/commands/screenshot.js.map +1 -1
  21. package/dist/commands/send-signal.js.map +1 -1
  22. package/dist/commands/type.js.map +1 -1
  23. package/dist/commands/uninstall.js +21 -7
  24. package/dist/commands/uninstall.js.map +2 -2
  25. package/dist/commands/wait-for-exit.js.map +1 -1
  26. package/dist/commands/wait-for.js.map +1 -1
  27. package/dist/composition.json +6 -1
  28. package/dist/testing/cli-repl.js +584 -163
  29. package/dist/testing/cli-repl.js.map +4 -4
  30. package/dist/testing/qa-cli.js +584 -163
  31. package/dist/testing/qa-cli.js.map +4 -4
  32. package/node_modules/@poe-code/agent-defs/README.md +14 -1
  33. package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.js +2 -1
  34. package/node_modules/@poe-code/agent-defs/dist/agents/claude-desktop.js +1 -0
  35. package/node_modules/@poe-code/agent-defs/dist/agents/codex.js +2 -1
  36. package/node_modules/@poe-code/agent-defs/dist/agents/cursor.js +1 -0
  37. package/node_modules/@poe-code/agent-defs/dist/agents/gemini-cli.js +2 -1
  38. package/node_modules/@poe-code/agent-defs/dist/agents/goose.js +1 -0
  39. package/node_modules/@poe-code/agent-defs/dist/agents/kimi.js +2 -1
  40. package/node_modules/@poe-code/agent-defs/dist/agents/opencode.js +2 -1
  41. package/node_modules/@poe-code/agent-defs/dist/agents/pi.js +2 -1
  42. package/node_modules/@poe-code/agent-defs/dist/agents/poe-agent.js +1 -0
  43. package/node_modules/@poe-code/agent-defs/dist/capabilities.d.ts +14 -0
  44. package/node_modules/@poe-code/agent-defs/dist/capabilities.js +63 -0
  45. package/node_modules/@poe-code/agent-defs/dist/index.d.ts +2 -1
  46. package/node_modules/@poe-code/agent-defs/dist/index.js +1 -0
  47. package/node_modules/@poe-code/agent-defs/dist/registry.js +3 -0
  48. package/node_modules/@poe-code/agent-defs/dist/types.d.ts +7 -0
  49. package/node_modules/@poe-code/agent-skill-config/dist/apply.d.ts +2 -0
  50. package/node_modules/@poe-code/agent-skill-config/dist/apply.js +18 -14
  51. package/node_modules/@poe-code/agent-skill-config/dist/bridge-active-skills.js +3 -1
  52. package/node_modules/@poe-code/agent-skill-config/dist/configs.d.ts +2 -0
  53. package/node_modules/@poe-code/agent-skill-config/dist/configs.js +2 -1
  54. package/node_modules/@poe-code/frontmatter/README.md +3 -0
  55. package/node_modules/@poe-code/frontmatter/dist/index.d.ts +1 -1
  56. package/node_modules/@poe-code/frontmatter/dist/index.js +1 -1
  57. package/node_modules/@poe-code/frontmatter/dist/parse.d.ts +9 -0
  58. package/node_modules/@poe-code/frontmatter/dist/parse.js +16 -0
  59. package/node_modules/@poe-code/user-error/README.md +56 -0
  60. package/node_modules/@poe-code/user-error/dist/index.d.ts +17 -0
  61. package/node_modules/@poe-code/user-error/dist/index.js +21 -0
  62. package/node_modules/@poe-code/user-error/package.json +24 -0
  63. package/node_modules/toolcraft-design/dist/acp/components.d.ts +8 -1
  64. package/node_modules/toolcraft-design/dist/acp/components.js +11 -6
  65. package/node_modules/toolcraft-design/dist/acp/index.d.ts +1 -0
  66. package/node_modules/toolcraft-design/dist/components/command-errors.d.ts +2 -0
  67. package/node_modules/toolcraft-design/dist/components/command-errors.js +8 -2
  68. package/node_modules/toolcraft-design/dist/components/help-formatter-plain.js +61 -25
  69. package/node_modules/toolcraft-design/dist/components/help-formatter.d.ts +15 -0
  70. package/node_modules/toolcraft-design/dist/components/help-formatter.js +128 -29
  71. package/node_modules/toolcraft-design/dist/components/index.d.ts +3 -3
  72. package/node_modules/toolcraft-design/dist/components/index.js +2 -2
  73. package/node_modules/toolcraft-design/dist/components/table.d.ts +1 -0
  74. package/node_modules/toolcraft-design/dist/components/table.js +52 -5
  75. package/node_modules/toolcraft-design/dist/components/template.d.ts +9 -0
  76. package/node_modules/toolcraft-design/dist/components/template.js +27 -2
  77. package/node_modules/toolcraft-design/dist/help-formatter.d.ts +2 -2
  78. package/node_modules/toolcraft-design/dist/help-formatter.js +1 -1
  79. package/node_modules/toolcraft-design/dist/index.d.ts +4 -4
  80. package/node_modules/toolcraft-design/dist/index.js +3 -3
  81. package/node_modules/toolcraft-design/dist/prompts/interactive/core.d.ts +5 -0
  82. package/node_modules/toolcraft-design/dist/prompts/interactive/core.js +15 -1
  83. package/node_modules/toolcraft-design/dist/prompts/primitives/spinner.js +1 -1
  84. package/package.json +5 -3
@@ -1650,26 +1650,68 @@ function splitWords(value) {
1650
1650
  }
1651
1651
  return words;
1652
1652
  }
1653
- function wrapWords(value, width) {
1654
- const words = splitWords(value);
1653
+ function leadingWhitespaceWidth(value) {
1654
+ let index = 0;
1655
+ while (index < value.length && isWhitespace(value[index])) {
1656
+ index += 1;
1657
+ }
1658
+ return { prefix: value.slice(0, index), rest: value.slice(index) };
1659
+ }
1660
+ function takeVisiblePrefix(value, width) {
1661
+ let visible = 0;
1662
+ let index = 0;
1663
+ while (index < value.length) {
1664
+ const controlEnd = readControlSequence(value, index);
1665
+ if (controlEnd !== void 0) {
1666
+ index = controlEnd;
1667
+ continue;
1668
+ }
1669
+ const segment = graphemeSegmenter.segment(value.slice(index))[Symbol.iterator]().next().value;
1670
+ const cluster = segment?.segment ?? value[index] ?? "";
1671
+ const nextWidth = clusterWidth(cluster);
1672
+ if (visible > 0 && visible + nextWidth > width) {
1673
+ break;
1674
+ }
1675
+ visible += nextWidth;
1676
+ index += cluster.length || 1;
1677
+ }
1678
+ return { prefix: value.slice(0, index), rest: value.slice(index) };
1679
+ }
1680
+ function wrapWords(value, width, continuationWidth = width) {
1681
+ const { prefix, rest } = leadingWhitespaceWidth(value);
1682
+ const prefixWidth = visibleWidth(prefix);
1683
+ const firstContentWidth = Math.max(1, width - prefixWidth);
1684
+ const words = splitWords(rest);
1655
1685
  if (words.length === 0) {
1656
- return [""];
1686
+ return [prefix];
1657
1687
  }
1658
1688
  const lines = [];
1659
1689
  let line = "";
1690
+ let isFirstLine = true;
1660
1691
  for (const word of words) {
1661
- if (!line) {
1662
- line = word;
1663
- continue;
1664
- }
1665
- if (visibleWidth(line) + 1 + visibleWidth(word) <= width) {
1692
+ const limit = isFirstLine ? firstContentWidth : continuationWidth;
1693
+ if (line && visibleWidth(line) + 1 + visibleWidth(word) <= limit) {
1666
1694
  line += ` ${word}`;
1667
1695
  continue;
1668
1696
  }
1669
- lines.push(line);
1670
- line = word;
1697
+ if (line) {
1698
+ lines.push(isFirstLine ? `${prefix}${line}` : line);
1699
+ isFirstLine = false;
1700
+ line = "";
1701
+ }
1702
+ let remaining = word;
1703
+ while (visibleWidth(remaining) > (isFirstLine ? firstContentWidth : continuationWidth)) {
1704
+ const chunk = takeVisiblePrefix(
1705
+ remaining,
1706
+ isFirstLine ? firstContentWidth : continuationWidth
1707
+ );
1708
+ lines.push(isFirstLine ? `${prefix}${chunk.prefix}` : chunk.prefix);
1709
+ isFirstLine = false;
1710
+ remaining = chunk.rest;
1711
+ }
1712
+ line = remaining;
1671
1713
  }
1672
- lines.push(line);
1714
+ lines.push(isFirstLine ? `${prefix}${line}` : line);
1673
1715
  return lines;
1674
1716
  }
1675
1717
  function validateLayoutValue(value, name) {
@@ -1697,37 +1739,90 @@ function formatColumns(opts) {
1697
1739
  validateLayoutValue(indent, "indent");
1698
1740
  const maxLeftContentWidth = Math.max(...rows.map((row) => visibleWidth(row.left)));
1699
1741
  const leftWidth = clamp(maxLeftContentWidth + gap, minLeftWidth, maxLeftWidth);
1700
- const rightWidth = Math.max(20, totalWidth - leftWidth - indent);
1742
+ const rightWidth = Math.max(1, totalWidth - leftWidth - indent);
1743
+ const leftWrapWidth = Math.max(1, totalWidth - indent);
1701
1744
  const firstIndent = " ".repeat(indent);
1702
1745
  const continuationIndent = " ".repeat(indent + leftWidth);
1703
1746
  return rows.flatMap((row) => {
1747
+ const leftLeading = leadingWhitespaceWidth(row.left).prefix;
1748
+ const leftHangIndent = " ".repeat(indent + visibleWidth(leftLeading) + 2);
1749
+ const leftLines = wrapWords(
1750
+ row.left,
1751
+ leftWrapWidth,
1752
+ Math.max(1, totalWidth - visibleWidth(leftHangIndent))
1753
+ );
1704
1754
  if (row.right.length === 0) {
1705
- return [`${firstIndent}${row.left}`];
1755
+ return leftLines.map(
1756
+ (line, index) => index === 0 ? `${firstIndent}${line}` : `${leftHangIndent}${line}`
1757
+ );
1706
1758
  }
1707
1759
  const rightLines = wrapWords(row.right, rightWidth);
1708
- if (visibleWidth(row.left) >= leftWidth) {
1709
- return [
1710
- `${firstIndent}${row.left}`,
1711
- ...rightLines.map((line) => `${continuationIndent}${line}`)
1712
- ];
1713
- }
1714
- const firstLine = `${firstIndent}${padEndVisible(row.left, leftWidth)}${rightLines[0]}`;
1715
- const continuationLines = rightLines.slice(1).map((line) => `${continuationIndent}${line}`);
1716
- return [firstLine, ...continuationLines];
1760
+ const leftFitsInColumn = visibleWidth(row.left) < leftWidth;
1761
+ if (leftFitsInColumn && leftLines.length === 1) {
1762
+ const firstLine = `${firstIndent}${padEndVisible(leftLines[0] ?? "", leftWidth)}${rightLines[0]}`;
1763
+ const continuationLines = rightLines.slice(1).map((line) => `${continuationIndent}${line}`);
1764
+ return [firstLine, ...continuationLines];
1765
+ }
1766
+ const renderedLeft = leftLines.map(
1767
+ (line, index) => index === 0 ? `${firstIndent}${line}` : `${leftHangIndent}${line}`
1768
+ );
1769
+ const renderedRight = rightLines.map((line) => `${continuationIndent}${line}`);
1770
+ return [...renderedLeft, ...renderedRight];
1717
1771
  }).join("\n");
1718
1772
  }
1773
+ function styleHelpToken(token) {
1774
+ switch (token.role) {
1775
+ case "command":
1776
+ return text.command(token.text);
1777
+ case "argument":
1778
+ return styleArgumentToken(token.text);
1779
+ case "option":
1780
+ return text.option(token.text);
1781
+ case "dim":
1782
+ return styleDim(token.text);
1783
+ case "literal":
1784
+ return token.text;
1785
+ }
1786
+ }
1787
+ function styleArgumentToken(content) {
1788
+ const format = resolveOutputFormat();
1789
+ if (format === "markdown" && content.startsWith("<") && content.endsWith(">")) {
1790
+ return text.argument(content.slice(1, -1));
1791
+ }
1792
+ if (format === "json") {
1793
+ return content;
1794
+ }
1795
+ return text.argument(content);
1796
+ }
1797
+ function styleDim(content) {
1798
+ const format = resolveOutputFormat();
1799
+ if (format === "json" || format === "markdown") {
1800
+ return content;
1801
+ }
1802
+ return typography.dim(content);
1803
+ }
1804
+ function joinHelpTokens(tokens) {
1805
+ return tokens.map((token) => token.text).join("");
1806
+ }
1807
+ function renderHelpTokens(tokens) {
1808
+ return tokens.map((token) => styleHelpToken(token)).join("");
1809
+ }
1719
1810
  function formatCommandList(commands) {
1720
1811
  return formatColumns({
1721
- rows: commands.map((cmd) => ({
1722
- left: `${" ".repeat((cmd.depth ?? 0) * 2)}${text.command(cmd.name)}`,
1723
- right: cmd.description
1724
- }))
1812
+ rows: commands.map((cmd) => {
1813
+ const depthPrefix = " ".repeat((cmd.depth ?? 0) * 2);
1814
+ const styledName = cmd.nameTokens !== void 0 && cmd.nameTokens.length > 0 ? renderHelpTokens(cmd.nameTokens) : text.command(cmd.name);
1815
+ return {
1816
+ left: `${depthPrefix}${styledName}`,
1817
+ right: cmd.description
1818
+ };
1819
+ })
1725
1820
  });
1726
1821
  }
1727
1822
  function formatOptionList(options) {
1728
1823
  return formatColumns({
1729
1824
  rows: options.map((opt) => ({
1730
- left: text.option(opt.flags),
1825
+ left: opt.flagTokens !== void 0 && opt.flagTokens.length > 0 ? renderHelpTokens(opt.flagTokens) : text.option(opt.flags),
1731
1826
  right: opt.description
1732
1827
  }))
1733
1828
  });
@@ -1797,26 +1892,47 @@ function splitWords2(value) {
1797
1892
  }
1798
1893
  return words;
1799
1894
  }
1800
- function wrapWords2(value, width) {
1801
- const words = splitWords2(value);
1895
+ function leadingWhitespace(value) {
1896
+ let index = 0;
1897
+ while (index < value.length && isWhitespace2(value[index])) {
1898
+ index += 1;
1899
+ }
1900
+ return { prefix: value.slice(0, index), rest: value.slice(index) };
1901
+ }
1902
+ function takePrefix(value, width) {
1903
+ return { prefix: value.slice(0, width), rest: value.slice(width) };
1904
+ }
1905
+ function wrapWords2(value, width, continuationWidth = width) {
1906
+ const { prefix, rest } = leadingWhitespace(value);
1907
+ const firstContentWidth = Math.max(1, width - prefix.length);
1908
+ const words = splitWords2(rest);
1802
1909
  if (words.length === 0) {
1803
- return [""];
1910
+ return [prefix];
1804
1911
  }
1805
1912
  const lines = [];
1806
1913
  let line = "";
1914
+ let isFirstLine = true;
1807
1915
  for (const word of words) {
1808
- if (!line) {
1809
- line = word;
1810
- continue;
1811
- }
1812
- if (line.length + 1 + word.length <= width) {
1916
+ const limit = isFirstLine ? firstContentWidth : continuationWidth;
1917
+ if (line && line.length + 1 + word.length <= limit) {
1813
1918
  line += ` ${word}`;
1814
1919
  continue;
1815
1920
  }
1816
- lines.push(line);
1817
- line = word;
1921
+ if (line) {
1922
+ lines.push(isFirstLine ? `${prefix}${line}` : line);
1923
+ isFirstLine = false;
1924
+ line = "";
1925
+ }
1926
+ let remaining = word;
1927
+ while (remaining.length > (isFirstLine ? firstContentWidth : continuationWidth)) {
1928
+ const chunk = takePrefix(remaining, isFirstLine ? firstContentWidth : continuationWidth);
1929
+ lines.push(isFirstLine ? `${prefix}${chunk.prefix}` : chunk.prefix);
1930
+ isFirstLine = false;
1931
+ remaining = chunk.rest;
1932
+ }
1933
+ line = remaining;
1818
1934
  }
1819
- lines.push(line);
1935
+ lines.push(isFirstLine ? `${prefix}${line}` : line);
1820
1936
  return lines;
1821
1937
  }
1822
1938
  function formatColumns2(opts) {
@@ -1834,29 +1950,44 @@ function formatColumns2(opts) {
1834
1950
  const indent = opts.indent ?? 2;
1835
1951
  const maxLeftContentWidth = Math.max(...rows.map((row) => row.left.length));
1836
1952
  const leftWidth = clamp2(maxLeftContentWidth + gap, minLeftWidth, maxLeftWidth);
1837
- const rightWidth = Math.max(20, totalWidth - leftWidth - indent);
1953
+ const rightWidth = Math.max(1, totalWidth - leftWidth - indent);
1954
+ const leftWrapWidth = Math.max(1, totalWidth - indent);
1838
1955
  const firstIndent = " ".repeat(indent);
1839
1956
  const continuationIndent = " ".repeat(indent + leftWidth);
1840
1957
  return rows.flatMap((row) => {
1958
+ let leftLeadingWidth = 0;
1959
+ while (leftLeadingWidth < row.left.length && isWhitespace2(row.left[leftLeadingWidth])) {
1960
+ leftLeadingWidth += 1;
1961
+ }
1962
+ const leftHangIndent = " ".repeat(indent + leftLeadingWidth + 2);
1963
+ const leftLines = wrapWords2(
1964
+ row.left,
1965
+ leftWrapWidth,
1966
+ Math.max(1, totalWidth - leftHangIndent.length)
1967
+ );
1841
1968
  if (row.right.length === 0) {
1842
- return [`${firstIndent}${row.left}`];
1969
+ return leftLines.map(
1970
+ (line, index) => index === 0 ? `${firstIndent}${line}` : `${leftHangIndent}${line}`
1971
+ );
1843
1972
  }
1844
1973
  const rightLines = wrapWords2(row.right, rightWidth);
1845
- if (row.left.length >= leftWidth) {
1846
- return [
1847
- `${firstIndent}${row.left}`,
1848
- ...rightLines.map((line) => `${continuationIndent}${line}`)
1849
- ];
1850
- }
1851
- const firstLine = `${firstIndent}${padEndVisible2(row.left, leftWidth)}${rightLines[0]}`;
1852
- const continuationLines = rightLines.slice(1).map((line) => `${continuationIndent}${line}`);
1853
- return [firstLine, ...continuationLines];
1974
+ const leftFitsInColumn = row.left.length < leftWidth;
1975
+ if (leftFitsInColumn && leftLines.length === 1) {
1976
+ const firstLine = `${firstIndent}${padEndVisible2(leftLines[0] ?? "", leftWidth)}${rightLines[0]}`;
1977
+ const continuationLines = rightLines.slice(1).map((line) => `${continuationIndent}${line}`);
1978
+ return [firstLine, ...continuationLines];
1979
+ }
1980
+ const renderedLeft = leftLines.map(
1981
+ (line, index) => index === 0 ? `${firstIndent}${line}` : `${leftHangIndent}${line}`
1982
+ );
1983
+ const renderedRight = rightLines.map((line) => `${continuationIndent}${line}`);
1984
+ return [...renderedLeft, ...renderedRight];
1854
1985
  }).join("\n");
1855
1986
  }
1856
1987
  function formatCommandList2(commands) {
1857
1988
  return formatColumns2({
1858
1989
  rows: commands.map((cmd) => ({
1859
- left: `${" ".repeat((cmd.depth ?? 0) * 2)}${cmd.name}`,
1990
+ left: `${" ".repeat((cmd.depth ?? 0) * 2)}${cmd.nameTokens !== void 0 && cmd.nameTokens.length > 0 ? joinHelpTokens(cmd.nameTokens) : cmd.name}`,
1860
1991
  right: cmd.description
1861
1992
  }))
1862
1993
  });
@@ -1864,7 +1995,7 @@ function formatCommandList2(commands) {
1864
1995
  function formatOptionList2(options) {
1865
1996
  return formatColumns2({
1866
1997
  rows: options.map((opt) => ({
1867
- left: opt.flags,
1998
+ left: opt.flagTokens !== void 0 && opt.flagTokens.length > 0 ? joinHelpTokens(opt.flagTokens) : opt.flags,
1868
1999
  right: opt.description
1869
2000
  }))
1870
2001
  });
@@ -1873,6 +2004,7 @@ function formatOptionList2(options) {
1873
2004
  // ../toolcraft-design/src/components/table.ts
1874
2005
  var reset2 = "\x1B[0m";
1875
2006
  var ellipsis = "\u2026";
2007
+ var minCellWidth = 4;
1876
2008
  var graphemeSegmenter2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1877
2009
  function getCell(row, name) {
1878
2010
  return Object.prototype.hasOwnProperty.call(row, name) ? row[name] ?? "" : "";
@@ -2006,6 +2138,39 @@ function computeColumns(columns) {
2006
2138
  width: getColumnWidth(column)
2007
2139
  }));
2008
2140
  }
2141
+ function frameWidth(columnCount) {
2142
+ return columnCount * 3 + 1;
2143
+ }
2144
+ function budgetColumns(columns, maxWidth) {
2145
+ if (maxWidth === void 0) {
2146
+ return columns;
2147
+ }
2148
+ const available = maxWidth - frameWidth(columns.length);
2149
+ const contentWidth = (cap2) => columns.reduce((total, column) => total + Math.min(column.width, cap2), 0);
2150
+ if (columns.reduce((total, column) => total + column.width, 0) <= available) {
2151
+ return columns;
2152
+ }
2153
+ let cap = minCellWidth;
2154
+ while (contentWidth(cap + 1) <= available) {
2155
+ cap += 1;
2156
+ }
2157
+ const budgeted = columns.map((column) => ({ ...column, width: Math.min(column.width, cap) }));
2158
+ let slack = available - contentWidth(cap);
2159
+ while (slack > 0) {
2160
+ const growable = budgeted.filter((column, index) => column.width < columns[index].width);
2161
+ if (growable.length === 0) {
2162
+ break;
2163
+ }
2164
+ for (const column of growable) {
2165
+ if (slack === 0) {
2166
+ break;
2167
+ }
2168
+ column.width += 1;
2169
+ slack -= 1;
2170
+ }
2171
+ }
2172
+ return budgeted;
2173
+ }
2009
2174
  function renderBorder(columns, theme, parts) {
2010
2175
  const horizontal = theme.muted("\u2500");
2011
2176
  const segments = columns.map((column) => horizontal.repeat(column.width + 2));
@@ -2090,14 +2255,15 @@ function renderTableTerminal(options) {
2090
2255
  }
2091
2256
  const separatorOptions = options;
2092
2257
  const includeRowSeparators = separatorOptions.rowSeparator === true || separatorOptions.rowSeparators === true;
2093
- const top = renderBorder(computedColumns, theme, { left: "\u250C", mid: "\u252C", right: "\u2510" });
2258
+ const budgetedColumns = budgetColumns(computedColumns, options.maxWidth ?? process.stdout.columns);
2259
+ const top = renderBorder(budgetedColumns, theme, { left: "\u250C", mid: "\u252C", right: "\u2510" });
2094
2260
  const header = renderTerminalRow(
2095
- computedColumns.map((column) => theme.header(column.title)),
2096
- computedColumns,
2261
+ budgetedColumns.map((column) => theme.header(column.title)),
2262
+ budgetedColumns,
2097
2263
  theme
2098
2264
  );
2099
- const headerBottom = renderBorder(computedColumns, theme, { left: "\u251C", mid: "\u253C", right: "\u2524" });
2100
- const bottom = renderBorder(computedColumns, theme, { left: "\u2514", mid: "\u2534", right: "\u2518" });
2265
+ const headerBottom = renderBorder(budgetedColumns, theme, { left: "\u251C", mid: "\u253C", right: "\u2524" });
2266
+ const bottom = renderBorder(budgetedColumns, theme, { left: "\u2514", mid: "\u2534", right: "\u2518" });
2101
2267
  const renderedRows = [];
2102
2268
  for (const [index, row] of rows.entries()) {
2103
2269
  if (includeRowSeparators && index > 0) {
@@ -2105,8 +2271,8 @@ function renderTableTerminal(options) {
2105
2271
  }
2106
2272
  renderedRows.push(
2107
2273
  renderTerminalRow(
2108
- computedColumns.map((column) => getCell(row, column.name)),
2109
- computedColumns,
2274
+ budgetedColumns.map((column) => getCell(row, column.name)),
2275
+ budgetedColumns,
2110
2276
  theme
2111
2277
  )
2112
2278
  );
@@ -2199,6 +2365,19 @@ ${options.theme.muted(options.badges.map((badge) => badge[0] + badge.slice(1).to
2199
2365
 
2200
2366
  // ../toolcraft-design/src/components/template.ts
2201
2367
  var MAX_PARTIAL_DEPTH = 100;
2368
+ var MAX_TAG_EXCERPT_LENGTH = 40;
2369
+ var TemplateParseError = class extends Error {
2370
+ description;
2371
+ line;
2372
+ column;
2373
+ constructor(description, position) {
2374
+ super(`${description} at line ${position.line}, column ${position.column}`);
2375
+ this.name = "TemplateParseError";
2376
+ this.description = description;
2377
+ this.line = position.line;
2378
+ this.column = position.column;
2379
+ }
2380
+ };
2202
2381
  var HTML_ESCAPE = {
2203
2382
  "&": "&amp;",
2204
2383
  "<": "&lt;",
@@ -2305,13 +2484,13 @@ function parseTag(template, open) {
2305
2484
  if (template.startsWith("{{{", open)) {
2306
2485
  const close2 = template.indexOf("}}}", open + 3);
2307
2486
  if (close2 === -1) {
2308
- throw new Error("Unclosed unescaped tag");
2487
+ throw unclosedTagError(template, open, "}}}");
2309
2488
  }
2310
2489
  return { kind: "unescaped", name: template.slice(open + 3, close2).trim(), end: close2 + 3 };
2311
2490
  }
2312
2491
  const close = template.indexOf("}}", open + 2);
2313
2492
  if (close === -1) {
2314
- throw new Error("Unclosed tag");
2493
+ throw unclosedTagError(template, open, "}}");
2315
2494
  }
2316
2495
  const raw = template.slice(open + 2, close).trim();
2317
2496
  const sigil = raw[0];
@@ -2326,6 +2505,16 @@ function parseTag(template, open) {
2326
2505
  if (sigil === "=" && raw.endsWith("=")) return { kind: "delimiter", name, end };
2327
2506
  return { kind: "name", name: raw, end };
2328
2507
  }
2508
+ function unclosedTagError(template, open, expected) {
2509
+ const before = template.slice(0, open);
2510
+ const lineEnd = template.indexOf("\n", open);
2511
+ const opened = template.slice(open, lineEnd === -1 ? template.length : lineEnd).trimEnd();
2512
+ const tag = opened.length > MAX_TAG_EXCERPT_LENGTH ? `${opened.slice(0, MAX_TAG_EXCERPT_LENGTH)}...` : opened;
2513
+ return new TemplateParseError(`Unclosed tag "${tag}": expected "${expected}"`, {
2514
+ line: before.split("\n").length,
2515
+ column: open - (before.lastIndexOf("\n") + 1) + 1
2516
+ });
2517
+ }
2329
2518
  function getStandalone(template, tagStart, tagEnd, kind) {
2330
2519
  if (!["section", "inverted", "close", "comment", "partial", "delimiter"].includes(kind)) {
2331
2520
  return void 0;
@@ -2897,6 +3086,15 @@ var cursor = {
2897
3086
  var erase = {
2898
3087
  down: "\x1B[J"
2899
3088
  };
3089
+ function nonTtyPromptMessage(argv = process.argv) {
3090
+ const tokens = [];
3091
+ for (const arg of argv.slice(2)) {
3092
+ if (arg.startsWith("-")) break;
3093
+ tokens.push(arg);
3094
+ }
3095
+ const retry = [...tokens, "--yes"].join(" ");
3096
+ return `Interactive prompt requires a TTY. Re-run with \`${retry}\` to accept defaults non-interactively, or set POE_NO_PROMPT=1 in CI.`;
3097
+ }
2900
3098
  var Prompt = class extends EventEmitter {
2901
3099
  state = "initial";
2902
3100
  value;
@@ -2967,7 +3165,7 @@ var Prompt = class extends EventEmitter {
2967
3165
  });
2968
3166
  }
2969
3167
  promptNonTty() {
2970
- return Promise.reject(new Error("Interactive prompt requires a TTY. Set POE_NO_PROMPT=1 to accept defaults non-interactively."));
3168
+ return Promise.reject(new Error(nonTtyPromptMessage()));
2971
3169
  }
2972
3170
  readNonTtyLine() {
2973
3171
  return new Promise((resolve) => {
@@ -3491,6 +3689,9 @@ var UserError = class extends Error {
3491
3689
  this.name = "UserError";
3492
3690
  }
3493
3691
  };
3692
+ function isUserError(error3) {
3693
+ return error3 instanceof UserError || error3 instanceof Error && error3.name === "UserError";
3694
+ }
3494
3695
  var ToolcraftBugError = class extends Error {
3495
3696
  constructor(message2) {
3496
3697
  super(message2);
@@ -5132,6 +5333,9 @@ function compactUrl(value) {
5132
5333
  return value;
5133
5334
  }
5134
5335
  }
5336
+ function stackedList(value) {
5337
+ return value.map((entry) => displayScalar(entry)).join("\n") || "\u2014";
5338
+ }
5135
5339
  function displayRowValue(value) {
5136
5340
  return isUrl(value) ? compactUrl(value) : displayScalar(value);
5137
5341
  }
@@ -5157,7 +5361,7 @@ function renderObjectCard(result, primitives, title) {
5157
5361
  const scalarRows = directScalarRows(result);
5158
5362
  const nestedSections = directObjectSections(result);
5159
5363
  const arrayObjectSections = directArrayObjectSections(result);
5160
- const listRows = Object.entries(result).filter(([, value]) => Array.isArray(value) && !isNonEmptyArrayOfObjects(value)).map(([key, value]) => ({ label: humanizeKey(key), value: displayScalar(value) }));
5364
+ const listRows = Object.entries(result).filter(([, value]) => Array.isArray(value) && !isNonEmptyArrayOfObjects(value)).map(([key, value]) => ({ label: humanizeKey(key), value: stackedList(value) }));
5161
5365
  return renderDetailCard({
5162
5366
  theme: primitives.getTheme(),
5163
5367
  title,
@@ -5859,6 +6063,13 @@ function formatOptionFlags(field, globalLongOptionFlags) {
5859
6063
  }
5860
6064
  return [`-${field.shortFlag}`, field.optionFlag, ...field.longAliases].join(", ");
5861
6065
  }
6066
+ function formatMissingParameterMessage(field) {
6067
+ const message2 = `Missing required parameter "${field.displayPath}".`;
6068
+ if (field.schema.kind !== "enum") {
6069
+ return message2;
6070
+ }
6071
+ return `${message2} Expected one of: ${field.schema.values.map((value) => String(value)).join(", ")}.`;
6072
+ }
5862
6073
  function formatPositionalToken(field) {
5863
6074
  const optionalPositional = field.optional || field.hasDefault;
5864
6075
  if (field.variadicPosition === true) {
@@ -6340,12 +6551,31 @@ function appendHelpMetadata(description, metadata) {
6340
6551
  return description;
6341
6552
  }
6342
6553
  if (description.length === 0) {
6343
- return `(${metadata.join(", ")})`;
6554
+ return metadata.map((entry) => `(${entry})`).join(" ");
6555
+ }
6556
+ return `${description} ${metadata.map((entry) => `(${entry})`).join(" ")}`;
6557
+ }
6558
+ function normalizeHelpEchoKey(value) {
6559
+ let normalized = "";
6560
+ for (const character of value.trim().toLowerCase()) {
6561
+ if (character !== " " && character !== " " && character !== "\n" && character !== "\r" && character !== "_" && character !== "." && character !== "-") {
6562
+ normalized += character;
6563
+ }
6344
6564
  }
6345
- return `${description} (${metadata.join(", ")})`;
6565
+ return normalized;
6566
+ }
6567
+ function isEchoHelpDescription(description, name) {
6568
+ if (description.length === 0) {
6569
+ return false;
6570
+ }
6571
+ return normalizeHelpEchoKey(description) === normalizeHelpEchoKey(name);
6572
+ }
6573
+ function suppressEchoHelpDescription(description, name) {
6574
+ return isEchoHelpDescription(description, name) ? "" : description;
6346
6575
  }
6347
6576
  function formatHelpFieldDescription(field) {
6348
- const description = field.description ?? field.displayPath;
6577
+ const rawDescription = field.description ?? field.displayPath;
6578
+ const description = suppressEchoHelpDescription(rawDescription, field.displayPath);
6349
6579
  const metadata = [];
6350
6580
  if (field.schema.kind === "enum" && field.schema.values.length <= 8) {
6351
6581
  const values = field.schema.values.map((value) => String(value)).join(", ");
@@ -6494,13 +6724,21 @@ function formatDynamicHelpMetadata(field) {
6494
6724
  }
6495
6725
  return metadata;
6496
6726
  }
6727
+ function createHelpOptionRow(flags, description) {
6728
+ return {
6729
+ flags,
6730
+ flagTokens: tokenizeHelpFlags(flags),
6731
+ description
6732
+ };
6733
+ }
6497
6734
  function collectDynamicObjectHelpRows(schema, casing, optionPrefix, displayPrefix, metadata) {
6498
6735
  const rows = [];
6499
6736
  for (const [key, rawChildSchema] of Object.entries(schema.shape)) {
6500
6737
  const childSchema = unwrapOptional2(rawChildSchema);
6501
6738
  const optionFlag = `${optionPrefix}.${formatSegment(key, casing)}`;
6502
6739
  const displayPath = `${displayPrefix}.${key}`;
6503
- const description = childSchema.description ?? displayPath;
6740
+ const rawDescription = childSchema.description ?? displayPath;
6741
+ const description = suppressEchoHelpDescription(rawDescription, displayPath);
6504
6742
  if (childSchema.kind === "object") {
6505
6743
  rows.push(
6506
6744
  ...collectDynamicObjectHelpRows(childSchema, casing, optionFlag, displayPath, metadata)
@@ -6508,24 +6746,26 @@ function collectDynamicObjectHelpRows(schema, casing, optionPrefix, displayPrefi
6508
6746
  continue;
6509
6747
  }
6510
6748
  if (childSchema.kind === "record") {
6511
- rows.push({
6512
- flags: `${optionFlag}.<key> <${describeDynamicFieldType({
6513
- ...{
6514
- id: displayPath,
6515
- path: [],
6516
- displayPath,
6517
- optionPath: [],
6518
- optionPathDisplay: `${displayPath}.<key>`,
6519
- optionFlag: `${optionFlag}.<key>`,
6520
- optional: false,
6521
- hasDefault: false,
6522
- defaultValue: void 0,
6523
- requiredWhenActive: false,
6524
- schema: childSchema
6525
- }
6526
- })}>`,
6527
- description: appendHelpMetadata(description, metadata)
6528
- });
6749
+ rows.push(
6750
+ createHelpOptionRow(
6751
+ `${optionFlag}.<key> <${describeDynamicFieldType({
6752
+ ...{
6753
+ id: displayPath,
6754
+ path: [],
6755
+ displayPath,
6756
+ optionPath: [],
6757
+ optionPathDisplay: `${displayPath}.<key>`,
6758
+ optionFlag: `${optionFlag}.<key>`,
6759
+ optional: false,
6760
+ hasDefault: false,
6761
+ defaultValue: void 0,
6762
+ requiredWhenActive: false,
6763
+ schema: childSchema
6764
+ }
6765
+ })}>`,
6766
+ appendHelpMetadata(description, metadata)
6767
+ )
6768
+ );
6529
6769
  continue;
6530
6770
  }
6531
6771
  if (childSchema.kind === "array" && unwrapOptional2(childSchema.item).kind === "object") {
@@ -6540,13 +6780,15 @@ function collectDynamicObjectHelpRows(schema, casing, optionPrefix, displayPrefi
6540
6780
  );
6541
6781
  continue;
6542
6782
  }
6543
- rows.push({
6544
- flags: childSchema.kind === "boolean" ? childSchema.default === true ? `--no-${optionFlag.slice(2)}` : optionFlag : `${optionFlag} <${describeHelpValueToken(childSchema, {
6545
- displayPath,
6546
- optionFlag
6547
- })}>`,
6548
- description: appendHelpMetadata(description, metadata)
6549
- });
6783
+ rows.push(
6784
+ createHelpOptionRow(
6785
+ childSchema.kind === "boolean" ? childSchema.default === true ? `--no-${optionFlag.slice(2)}` : optionFlag : `${optionFlag} <${describeHelpValueToken(childSchema, {
6786
+ displayPath,
6787
+ optionFlag
6788
+ })}>`,
6789
+ appendHelpMetadata(description, metadata)
6790
+ )
6791
+ );
6550
6792
  }
6551
6793
  return rows;
6552
6794
  }
@@ -6577,17 +6819,22 @@ function formatDynamicHelpFields(field, casing) {
6577
6819
  }
6578
6820
  }
6579
6821
  return [
6580
- {
6581
- flags: `${field.optionFlag} <${describeDynamicFieldType(field)}>`,
6582
- description: appendHelpMetadata(field.description ?? field.optionPathDisplay, metadata)
6583
- }
6822
+ createHelpOptionRow(
6823
+ `${field.optionFlag} <${describeDynamicFieldType(field)}>`,
6824
+ appendHelpMetadata(
6825
+ suppressEchoHelpDescription(
6826
+ field.description ?? field.optionPathDisplay,
6827
+ field.optionPathDisplay
6828
+ ),
6829
+ metadata
6830
+ )
6831
+ )
6584
6832
  ];
6585
6833
  }
6586
6834
  function formatSecretRows(secrets) {
6587
- return Object.values(secrets).map((secret) => ({
6588
- flags: secret.env,
6589
- description: formatSecretDescription(secret)
6590
- }));
6835
+ return Object.values(secrets).map(
6836
+ (secret) => createHelpOptionRow(secret.env, formatSecretDescription(secret))
6837
+ );
6591
6838
  }
6592
6839
  function formatSecretDescription(secret) {
6593
6840
  if (secret.description !== void 0 && secret.description.length > 0) {
@@ -6615,20 +6862,82 @@ function formatExampleRows(examples, breadcrumb, rootUsageName) {
6615
6862
  ${formatExampleCommand(breadcrumb, rootUsageName, example.params)}`
6616
6863
  );
6617
6864
  }
6618
- function wrapOptionalCommandParameterToken(token, optional) {
6619
- return optional ? `[${token}]` : token;
6865
+ var MAX_INLINE_OPTIONAL_PARAMETER_TOKENS = 8;
6866
+ var DEFAULT_HELP_TOTAL_WIDTH = 100;
6867
+ function tokenizeHelpFlags(flags) {
6868
+ const tokens = [];
6869
+ let index = 0;
6870
+ while (index < flags.length) {
6871
+ if (flags[index] === " ") {
6872
+ let end2 = index + 1;
6873
+ while (end2 < flags.length && flags[end2] === " ") {
6874
+ end2 += 1;
6875
+ }
6876
+ tokens.push({ text: flags.slice(index, end2), role: "literal" });
6877
+ index = end2;
6878
+ continue;
6879
+ }
6880
+ if (flags[index] === "[" || flags[index] === "]") {
6881
+ tokens.push({ text: flags[index], role: "dim" });
6882
+ index += 1;
6883
+ continue;
6884
+ }
6885
+ if (flags[index] === "<") {
6886
+ const close = flags.indexOf(">", index);
6887
+ if (close === -1) {
6888
+ tokens.push({ text: flags.slice(index), role: "literal" });
6889
+ break;
6890
+ }
6891
+ tokens.push({ text: flags.slice(index, close + 1), role: "argument" });
6892
+ index = close + 1;
6893
+ continue;
6894
+ }
6895
+ if (flags.startsWith("--", index) || flags[index] === "-" && flags[index + 1] !== void 0 && flags[index + 1] !== "-") {
6896
+ let end2 = index + 1;
6897
+ while (end2 < flags.length && flags[end2] !== " " && flags[end2] !== "[" && flags[end2] !== "]" && flags[end2] !== "<") {
6898
+ end2 += 1;
6899
+ }
6900
+ tokens.push({ text: flags.slice(index, end2), role: "option" });
6901
+ index = end2;
6902
+ continue;
6903
+ }
6904
+ let end = index + 1;
6905
+ while (end < flags.length && flags[end] !== " " && flags[end] !== "[" && flags[end] !== "]" && flags[end] !== "<") {
6906
+ end += 1;
6907
+ }
6908
+ const piece = flags.slice(index, end);
6909
+ tokens.push({
6910
+ text: piece,
6911
+ role: piece.includes("|") ? "literal" : piece.startsWith("+") ? "dim" : "literal"
6912
+ });
6913
+ index = end;
6914
+ }
6915
+ return tokens;
6916
+ }
6917
+ function wrapOptionalParameterTokens(tokens, optional) {
6918
+ if (!optional) {
6919
+ return tokens;
6920
+ }
6921
+ return [{ text: "[", role: "dim" }, ...tokens, { text: "]", role: "dim" }];
6922
+ }
6923
+ function createCommandParameterToken(text3, optional) {
6924
+ return {
6925
+ text: optional ? `[${text3}]` : text3,
6926
+ optional,
6927
+ tokens: wrapOptionalParameterTokens(tokenizeHelpFlags(text3), optional)
6928
+ };
6620
6929
  }
6621
6930
  function formatCommandDynamicParameterTokens(field, casing) {
6622
6931
  const optional = field.optional || field.hasDefault;
6623
6932
  return formatDynamicHelpFields(field, casing).map(
6624
- (row) => wrapOptionalCommandParameterToken(row.flags, optional)
6933
+ (row) => createCommandParameterToken(row.flags, optional)
6625
6934
  );
6626
6935
  }
6627
6936
  function formatCommandParameterTokens(command, casing, globalLongOptionFlags) {
6628
6937
  const collected = collectFields(command.params, casing, globalLongOptionFlags);
6629
6938
  const fields = assignPositionals(collected.fields, command.positional);
6630
6939
  return fields.filter((field) => field.global !== true).map(
6631
- (field) => wrapOptionalCommandParameterToken(
6940
+ (field) => createCommandParameterToken(
6632
6941
  formatCommandParameterFieldFlags(field, globalLongOptionFlags),
6633
6942
  field.positionalIndex === void 0 && (field.optional || field.hasDefault)
6634
6943
  )
@@ -6636,30 +6945,65 @@ function formatCommandParameterTokens(command, casing, globalLongOptionFlags) {
6636
6945
  collected.dynamicFields.flatMap((field) => formatCommandDynamicParameterTokens(field, casing))
6637
6946
  );
6638
6947
  }
6639
- function formatCommandRowName(node, casing, globalLongOptionFlags) {
6948
+ function collapseOptionalParameterTokens(parameterTokens, inlineWidthBudget = Number.POSITIVE_INFINITY) {
6949
+ const optionalCount = parameterTokens.filter((token) => token.optional).length;
6950
+ if (optionalCount === 0) {
6951
+ return parameterTokens;
6952
+ }
6953
+ const inlineWidth = parameterTokens.reduce((total, token) => total + token.text.length + 1, 0);
6954
+ if (optionalCount <= MAX_INLINE_OPTIONAL_PARAMETER_TOKENS && inlineWidth <= inlineWidthBudget) {
6955
+ return parameterTokens;
6956
+ }
6957
+ const required = parameterTokens.filter((token) => !token.optional);
6958
+ const collapsedText = `+${optionalCount} options`;
6959
+ return [
6960
+ ...required,
6961
+ {
6962
+ text: `[${collapsedText}]`,
6963
+ optional: true,
6964
+ tokens: [
6965
+ { text: "[", role: "dim" },
6966
+ { text: collapsedText, role: "dim" },
6967
+ { text: "]", role: "dim" }
6968
+ ]
6969
+ }
6970
+ ];
6971
+ }
6972
+ function formatCommandRowNameTokens(node, casing, globalLongOptionFlags) {
6640
6973
  const baseName = node.aliases.length === 0 ? node.name : `${node.name} (${node.aliases.join(", ")})`;
6641
- const parameterTokens = node.kind === "command" ? formatCommandParameterTokens(node, casing, globalLongOptionFlags) : [];
6642
- const name = parameterTokens.length === 0 ? baseName : `${baseName} ${parameterTokens.join(" ")}`;
6643
- return name;
6974
+ const nameTokens = [{ text: baseName, role: "command" }];
6975
+ const inlineWidthBudget = Math.max(
6976
+ 0,
6977
+ (process.stdout.columns ?? DEFAULT_HELP_TOTAL_WIDTH) - 2 - baseName.length
6978
+ );
6979
+ const parameterTokens = node.kind === "command" ? collapseOptionalParameterTokens(
6980
+ formatCommandParameterTokens(node, casing, globalLongOptionFlags),
6981
+ inlineWidthBudget
6982
+ ) : [];
6983
+ for (const token of parameterTokens) {
6984
+ nameTokens.push({ text: " ", role: "literal" }, ...token.tokens);
6985
+ }
6986
+ const name = parameterTokens.length === 0 ? baseName : `${baseName} ${parameterTokens.map((token) => token.text).join(" ")}`;
6987
+ return { name, nameTokens };
6644
6988
  }
6645
6989
  function formatCommandRows(group, scope, casing, globalLongOptionFlags, help) {
6646
- if (help === "concise") {
6647
- return getHelpChildren(group, scope).map((child) => ({
6648
- name: formatCommandRowName(child, casing, globalLongOptionFlags),
6649
- description: child.description ?? "",
6990
+ const toRow = (child, depth) => {
6991
+ const { name, nameTokens } = formatCommandRowNameTokens(child, casing, globalLongOptionFlags);
6992
+ return {
6993
+ name,
6994
+ nameTokens,
6995
+ description: suppressEchoHelpDescription(child.description ?? "", child.name),
6650
6996
  kind: child.kind,
6651
- depth: 0
6652
- }));
6997
+ depth
6998
+ };
6999
+ };
7000
+ if (help === "concise") {
7001
+ return getHelpChildren(group, scope).map((child) => toRow(child, 0));
6653
7002
  }
6654
7003
  const rows = [];
6655
7004
  const visit = (node, depth) => {
6656
7005
  for (const child of getHelpChildren(node, scope)) {
6657
- rows.push({
6658
- name: formatCommandRowName(child, casing, globalLongOptionFlags),
6659
- description: child.description ?? "",
6660
- kind: child.kind,
6661
- depth
6662
- });
7006
+ rows.push(toRow(child, depth));
6663
7007
  if (child.kind === "group") {
6664
7008
  visit(child, depth + 1);
6665
7009
  }
@@ -6685,10 +7029,10 @@ function formatGlobalOptionsLine(ctx) {
6685
7029
  if (ctx.showVersion) {
6686
7030
  flags.push("--version");
6687
7031
  }
6688
- return flags.length > 0 ? `${text.section("Options:")} ${flags.join(" ")}` : "";
7032
+ return flags.length > 0 ? `${text.section("Global Options:")} ${flags.join(" ")}` : "";
6689
7033
  }
6690
7034
  function formatLeafGlobalOptionsLine(ctx) {
6691
- return ctx.controls.verbose ? `${text.section("Options:")} -v, --verbose` : "";
7035
+ return ctx.controls.verbose ? `${text.section("Global Options:")} -v, --verbose` : "";
6692
7036
  }
6693
7037
  function collectSchemaGlobalFieldRows(group, scope, casing, globalLongOptionFlags) {
6694
7038
  const seen = /* @__PURE__ */ new Map();
@@ -6706,10 +7050,13 @@ function collectSchemaGlobalFieldRows(group, scope, casing, globalLongOptionFlag
6706
7050
  if (seen.has(dedupeKey)) {
6707
7051
  continue;
6708
7052
  }
6709
- seen.set(dedupeKey, {
6710
- flags: formatHelpFieldFlags(field, globalLongOptionFlags),
6711
- description: formatHelpFieldDescription(field)
6712
- });
7053
+ seen.set(
7054
+ dedupeKey,
7055
+ createHelpOptionRow(
7056
+ formatHelpFieldFlags(field, globalLongOptionFlags),
7057
+ formatHelpFieldDescription(field)
7058
+ )
7059
+ );
6713
7060
  }
6714
7061
  return;
6715
7062
  }
@@ -6729,6 +7076,18 @@ function formatHelpCommandList(rows) {
6729
7076
  function formatHelpOptionList(rows) {
6730
7077
  return process.stdout.isTTY !== true ? help_formatter_plain_exports.formatOptionList(rows) : formatOptionList(rows);
6731
7078
  }
7079
+ function sortLeafHelpOptionFields(fields) {
7080
+ const required = [];
7081
+ const optional = [];
7082
+ for (const field of fields) {
7083
+ if (!field.optional && !field.hasDefault) {
7084
+ required.push(field);
7085
+ continue;
7086
+ }
7087
+ optional.push(field);
7088
+ }
7089
+ return [...required, ...optional];
7090
+ }
6732
7091
  function buildUsageLine(breadcrumb, rootUsageName, suffix) {
6733
7092
  const visibleBreadcrumb = breadcrumb.filter((segment) => segment.length > 0);
6734
7093
  const usageBreadcrumb = breadcrumb[0] === "" ? [rootUsageName, ...visibleBreadcrumb] : visibleBreadcrumb;
@@ -6738,15 +7097,37 @@ function buildUsageLine(breadcrumb, rootUsageName, suffix) {
6738
7097
  }
6739
7098
  function formatGroupUsageSuffix(group, scope, casing, globalLongOptionFlags) {
6740
7099
  if (group.default !== void 0 && group.default.hidden === true && group.default.scope.includes(scope)) {
6741
- const parameterTokens = formatCommandParameterTokens(
6742
- group.default,
6743
- casing,
6744
- globalLongOptionFlags
7100
+ const parameterTokens = collapseOptionalParameterTokens(
7101
+ formatCommandParameterTokens(group.default, casing, globalLongOptionFlags)
6745
7102
  );
6746
- return ["[command]", "[OPTIONS]", ...parameterTokens].join(" ");
7103
+ return ["[command]", "[OPTIONS]", ...parameterTokens.map((token) => token.text)].join(" ");
6747
7104
  }
6748
7105
  return "[command] [OPTIONS]";
6749
7106
  }
7107
+ function formatHelpDrillDownFooter(rootUsageName) {
7108
+ return text.muted(`Run ${rootUsageName} <command> --help for full options.`);
7109
+ }
7110
+ function formatStyledUsageLine(usageLine) {
7111
+ const parts = usageLine.split(" ").filter((part) => part.length > 0);
7112
+ if (parts.length === 0) {
7113
+ return text.usageCommand(usageLine);
7114
+ }
7115
+ const commandEnd = parts.findIndex(
7116
+ (part) => part.startsWith("-") || part.startsWith("[") || part.startsWith("<")
7117
+ );
7118
+ const commandParts = commandEnd === -1 ? parts : parts.slice(0, commandEnd);
7119
+ const argParts = commandEnd === -1 ? [] : parts.slice(commandEnd);
7120
+ const command = commandParts.join(" ");
7121
+ if (argParts.length === 0) {
7122
+ return text.usageCommand(command);
7123
+ }
7124
+ return `${text.usageCommand(command)} ${renderHelpTokens(
7125
+ argParts.flatMap((part, index) => [
7126
+ ...index === 0 ? [] : [{ text: " ", role: "literal" }],
7127
+ ...tokenizeHelpFlags(part)
7128
+ ])
7129
+ )}`;
7130
+ }
6750
7131
  function renderGroupHelp(group, breadcrumb, scope, casing, globalOptions, rootUsageName, isRoot) {
6751
7132
  const sections = [];
6752
7133
  const globalLongOptionFlags = getGlobalLongOptionFlags(
@@ -6762,7 +7143,7 @@ function renderGroupHelp(group, breadcrumb, scope, casing, globalOptions, rootUs
6762
7143
  globalOptions.controls.help
6763
7144
  );
6764
7145
  if (commandRows.length > 0) {
6765
- sections.push(`${text.sectionHeader("Commands")}
7146
+ sections.push(`${text.section("Commands:")}
6766
7147
  ${formatHelpCommandList(commandRows)}`);
6767
7148
  }
6768
7149
  if (isRoot) {
@@ -6775,7 +7156,7 @@ ${formatHelpCommandList(commandRows)}`);
6775
7156
  const builtInLine = formatGlobalOptionsLine(globalOptions);
6776
7157
  if (schemaGlobalRows.length > 0) {
6777
7158
  sections.push(
6778
- `${text.sectionHeader("Options")}
7159
+ `${text.section("Options:")}
6779
7160
  ${formatHelpOptionList(schemaGlobalRows)}
6780
7161
  ${builtInLine}`
6781
7162
  );
@@ -6783,6 +7164,9 @@ ${builtInLine}`
6783
7164
  sections.push(builtInLine);
6784
7165
  }
6785
7166
  }
7167
+ if (commandRows.length > 0) {
7168
+ sections.push(formatHelpDrillDownFooter(rootUsageName));
7169
+ }
6786
7170
  return renderHelpDocument({
6787
7171
  breadcrumb,
6788
7172
  rootUsageName,
@@ -6805,12 +7189,21 @@ function renderLeafHelp(command, breadcrumb, casing, globalOptions, rootUsageNam
6805
7189
  );
6806
7190
  const collected = collectFields(command.params, casing, globalLongOptionFlags);
6807
7191
  const fields = assignPositionals(collected.fields, command.positional);
6808
- const optionRows = fields.filter((field) => field.global !== true).map((field) => ({
6809
- flags: formatHelpFieldFlags(field, globalLongOptionFlags),
6810
- description: formatHelpFieldDescription(field)
6811
- })).concat(collected.dynamicFields.flatMap((field) => formatDynamicHelpFields(field, casing)));
7192
+ const localFields = fields.filter((field) => field.global !== true);
7193
+ const toHelpRow = (field) => createHelpOptionRow(
7194
+ formatHelpFieldFlags(field, globalLongOptionFlags),
7195
+ formatHelpFieldDescription(field)
7196
+ );
7197
+ const argumentRows = localFields.filter((field) => field.positionalIndex !== void 0).map(toHelpRow);
7198
+ const optionRows = sortLeafHelpOptionFields(
7199
+ localFields.filter((field) => field.positionalIndex === void 0)
7200
+ ).map(toHelpRow).concat(collected.dynamicFields.flatMap((field) => formatDynamicHelpFields(field, casing)));
7201
+ if (argumentRows.length > 0) {
7202
+ sections.push(`${text.section("Arguments:")}
7203
+ ${formatHelpOptionList(argumentRows)}`);
7204
+ }
6812
7205
  if (optionRows.length > 0) {
6813
- sections.push(`${text.sectionHeader("Options")}
7206
+ sections.push(`${text.section("Options:")}
6814
7207
  ${formatHelpOptionList(optionRows)}`);
6815
7208
  }
6816
7209
  const builtInLine = formatLeafGlobalOptionsLine(globalOptions);
@@ -6820,13 +7213,13 @@ ${formatHelpOptionList(optionRows)}`);
6820
7213
  const secretRows = formatSecretRows(command.secrets);
6821
7214
  if (secretRows.length > 0) {
6822
7215
  sections.push(
6823
- `${text.sectionHeader("Secrets (environment)")}
7216
+ `${text.section("Secrets (environment):")}
6824
7217
  ${formatHelpOptionList(secretRows)}`
6825
7218
  );
6826
7219
  }
6827
7220
  if (command.examples.length > 0) {
6828
7221
  sections.push(
6829
- `${text.sectionHeader("Examples")}
7222
+ `${text.section("Examples:")}
6830
7223
  ${formatExampleRows(command.examples, breadcrumb, rootUsageName).join("\n")}`
6831
7224
  );
6832
7225
  }
@@ -6948,7 +7341,7 @@ function renderHelpDocument(input) {
6948
7341
  if (remainingDescription.length > 0) {
6949
7342
  lines.push(remainingDescription, "");
6950
7343
  }
6951
- lines.push(`Usage: ${text.usageCommand(input.usageLine)}`, "");
7344
+ lines.push(`Usage: ${formatStyledUsageLine(input.usageLine)}`, "");
6952
7345
  if (input.requiresAuth) {
6953
7346
  lines.push("Requires: authentication");
6954
7347
  }
@@ -7032,7 +7425,9 @@ function createNodeCommand(node, casing, globalLongOptionFlags, execute, presets
7032
7425
  }
7033
7426
  for (const field of fields) {
7034
7427
  if (field.positionalIndex !== void 0) {
7035
- command.argument(formatPositionalToken(field));
7428
+ command.argument(
7429
+ field.variadicPosition === true ? `[${field.displayPath}...]` : `[${field.displayPath}]`
7430
+ );
7036
7431
  continue;
7037
7432
  }
7038
7433
  for (const option of createOption(field, globalLongOptionFlags)) {
@@ -7867,11 +8262,11 @@ function writeRichHeader(title) {
7867
8262
  function isHumanInLoopPending(result) {
7868
8263
  return typeof result === "object" && result !== null && result.status === "pending-approval" && typeof result.approvalId === "string" && typeof result.message === "string" && typeof result.enqueuedAt === "string";
7869
8264
  }
7870
- function renderHumanInLoopPending(pending) {
8265
+ function renderHumanInLoopPending(pending, rootUsageName) {
7871
8266
  process.stdout.write(
7872
8267
  `\u2713 Queued for human approval (id: ${pending.approvalId})
7873
8268
  Message: ${pending.message}
7874
- Track: toolcraft approvals show ${pending.approvalId}
8269
+ Track: ${rootUsageName} approvals show --approval-id ${pending.approvalId}
7875
8270
  `
7876
8271
  );
7877
8272
  }
@@ -7975,7 +8370,7 @@ function parseOptionFieldValue(field, value, errors) {
7975
8370
  }
7976
8371
  return { ok: true, value: parsedValue };
7977
8372
  } catch (error3) {
7978
- if (error3 instanceof UserError || error3 instanceof InvalidArgumentError) {
8373
+ if (isUserError(error3) || error3 instanceof InvalidArgumentError) {
7979
8374
  errors.push({
7980
8375
  path: field.displayPath,
7981
8376
  message: error3.message
@@ -8557,7 +8952,7 @@ async function resolveParams(fields, dynamicFields, variants, positionalValues,
8557
8952
  }
8558
8953
  errors.push({
8559
8954
  path: field.displayPath,
8560
- message: `Missing required parameter "${field.displayPath}".`
8955
+ message: formatMissingParameterMessage(field)
8561
8956
  });
8562
8957
  continue;
8563
8958
  }
@@ -8608,7 +9003,7 @@ function getResolvedFlags(command) {
8608
9003
  const flags = command.optsWithGlobals();
8609
9004
  return flags;
8610
9005
  }
8611
- async function executeCommand(state, services, requirementOptions, runtimeFetch, humanInLoop, runtimeEnv, runtimeFs, outputEmitter, outputFormats, promptStreams, diagnosticsOptions, onErrorReportContext) {
9006
+ async function executeCommand(state, rootUsageName, services, requirementOptions, runtimeFetch, humanInLoop, runtimeEnv, runtimeFs, outputEmitter, outputFormats, promptStreams, diagnosticsOptions, onErrorReportContext) {
8612
9007
  const logger2 = createLogger(outputEmitter);
8613
9008
  const optionValues = state.actionCommand.optsWithGlobals();
8614
9009
  const resolvedFlags = optionValues;
@@ -8764,7 +9159,7 @@ async function executeCommand(state, services, requirementOptions, runtimeFetch,
8764
9159
  writeRichHeader(`${state.command.name} (fixture)`);
8765
9160
  }
8766
9161
  if (isHumanInLoopPending(result)) {
8767
- renderHumanInLoopPending(result);
9162
+ renderHumanInLoopPending(result, rootUsageName);
8768
9163
  return;
8769
9164
  }
8770
9165
  const renderStatus = renderCLIResult(
@@ -9007,7 +9402,7 @@ function renderHttpError(error3, options) {
9007
9402
  async function handleRunError(error3, options) {
9008
9403
  const logger2 = createLogger(options.outputEmitter);
9009
9404
  await withOutputFormat2(options.output, async () => {
9010
- if (error3 instanceof UserError) {
9405
+ if (isUserError(error3)) {
9011
9406
  renderCliErrorPattern(
9012
9407
  options.userErrorPattern === "definition" ? {
9013
9408
  kind: "definition",
@@ -9323,11 +9718,9 @@ function getDefaultCommanderCommandName(command) {
9323
9718
  function configureCommanderSuggestionOutput(command) {
9324
9719
  command.exitOverride();
9325
9720
  command.configureOutput({
9326
- outputError: (message2, write2) => {
9327
- if (message2.includes("unknown command") || message2.includes("unknown option")) {
9328
- return;
9329
- }
9330
- write2(message2);
9721
+ // Every Commander error throws through exitOverride and is rendered once by handleRunError
9722
+ // in the design-system error pattern; writing it here as well double-reports one mistake.
9723
+ outputError: () => {
9331
9724
  }
9332
9725
  });
9333
9726
  command.commands.forEach((child) => configureCommanderSuggestionOutput(child));
@@ -9400,6 +9793,7 @@ async function runCLI(roots, options = {}) {
9400
9793
  resolvedCommandPath = formatCliCommandPath(state.commandPath);
9401
9794
  await executeCommand(
9402
9795
  state,
9796
+ rootUsageName,
9403
9797
  servicesWithBuiltIns,
9404
9798
  requirementOptions,
9405
9799
  runtimeFetch,
@@ -11070,7 +11464,7 @@ var claudeCodeAgent = {
11070
11464
  id: "claude-code",
11071
11465
  name: "claude-code",
11072
11466
  label: "Claude Code",
11073
- summary: "Configure Claude Code to route through Poe.",
11467
+ summary: "Anthropic's agentic coding tool for the terminal.",
11074
11468
  aliases: ["claude"],
11075
11469
  binaryName: "claude",
11076
11470
  apiShapes: ["anthropic-messages"],
@@ -11080,6 +11474,7 @@ var claudeCodeAgent = {
11080
11474
  }
11081
11475
  },
11082
11476
  configPath: "~/.claude.json",
11477
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
11083
11478
  branding: {
11084
11479
  colors: {
11085
11480
  dark: "#C15F3C",
@@ -11100,6 +11495,7 @@ var claudeDesktopAgent = {
11100
11495
  linux: "~/.config/Claude/claude_desktop_config.json",
11101
11496
  win32: "~/AppData/Roaming/Claude/claude_desktop_config.json"
11102
11497
  },
11498
+ capabilities: ["mcp"],
11103
11499
  branding: {
11104
11500
  colors: {
11105
11501
  dark: "#D97757",
@@ -11113,7 +11509,7 @@ var codexAgent = {
11113
11509
  id: "codex",
11114
11510
  name: "codex",
11115
11511
  label: "Codex",
11116
- summary: "Configure Codex to use Poe as the model provider.",
11512
+ summary: "OpenAI's coding agent for the terminal.",
11117
11513
  binaryName: "codex",
11118
11514
  apiShapes: ["openai-responses"],
11119
11515
  otelCapture: {
@@ -11127,6 +11523,7 @@ var codexAgent = {
11127
11523
  ]
11128
11524
  },
11129
11525
  configPath: "~/.codex/config.toml",
11526
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
11130
11527
  branding: {
11131
11528
  colors: {
11132
11529
  dark: "#D5D9DF",
@@ -11144,6 +11541,7 @@ var cursorAgent = {
11144
11541
  summary: "Cursor's CLI coding agent.",
11145
11542
  binaryName: "cursor-agent",
11146
11543
  configPath: "~/.cursor/mcp.json",
11544
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
11147
11545
  branding: {
11148
11546
  colors: {
11149
11547
  dark: "#FFFFFF",
@@ -11158,10 +11556,11 @@ var geminiCliAgent = {
11158
11556
  name: "gemini-cli",
11159
11557
  aliases: ["gemini"],
11160
11558
  label: "Gemini CLI",
11161
- summary: "Configure Google's Gemini CLI to use a compatible Google generations API.",
11559
+ summary: "Google's open-source AI agent for the terminal.",
11162
11560
  binaryName: "gemini",
11163
11561
  configPath: "~/.gemini/settings.json",
11164
11562
  apiShapes: ["google-generations"],
11563
+ capabilities: ["spawn", "configure", "install", "test", "skill"],
11165
11564
  branding: {
11166
11565
  colors: {
11167
11566
  dark: "#8AB4F8",
@@ -11175,7 +11574,7 @@ var openCodeAgent = {
11175
11574
  id: "opencode",
11176
11575
  name: "opencode",
11177
11576
  label: "OpenCode CLI",
11178
- summary: "Configure OpenCode CLI to use the Poe API.",
11577
+ summary: "Open-source AI coding agent for the terminal.",
11179
11578
  binaryName: "opencode",
11180
11579
  apiShapes: ["openai-chat-completions"],
11181
11580
  otelCapture: {
@@ -11184,6 +11583,7 @@ var openCodeAgent = {
11184
11583
  }
11185
11584
  },
11186
11585
  configPath: "~/.config/opencode/opencode.json",
11586
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
11187
11587
  branding: {
11188
11588
  colors: {
11189
11589
  dark: "#4A4F55",
@@ -11197,11 +11597,12 @@ var kimiAgent = {
11197
11597
  id: "kimi",
11198
11598
  name: "kimi",
11199
11599
  label: "Kimi",
11200
- summary: "Configure Kimi CLI to use Poe API",
11600
+ summary: "Moonshot AI's coding agent for the terminal.",
11201
11601
  aliases: ["kimi-cli"],
11202
11602
  binaryName: "kimi",
11203
11603
  apiShapes: ["openai-chat-completions"],
11204
11604
  configPath: "~/.kimi/mcp.json",
11605
+ capabilities: ["spawn", "configure", "install", "test", "mcp"],
11205
11606
  branding: {
11206
11607
  colors: {
11207
11608
  dark: "#7B68EE",
@@ -11220,6 +11621,7 @@ var gooseAgent = {
11220
11621
  apiShapes: ["openai-chat-completions"],
11221
11622
  otelCapture: {},
11222
11623
  configPath: "~/.config/goose/config.yaml",
11624
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
11223
11625
  branding: {
11224
11626
  colors: {
11225
11627
  dark: "#FF6B35",
@@ -11234,8 +11636,9 @@ var piAgent = {
11234
11636
  name: "pi",
11235
11637
  aliases: ["pi-agent"],
11236
11638
  label: "Pi",
11237
- summary: "Pi coding agent (spawn-only; uses local Pi auth/settings).",
11639
+ summary: "Minimal AI coding agent for the terminal.",
11238
11640
  binaryName: "pi",
11641
+ capabilities: ["spawn"],
11239
11642
  branding: {
11240
11643
  colors: {
11241
11644
  dark: "#F2F2F2",
@@ -11252,6 +11655,7 @@ var poeAgentAgent = {
11252
11655
  summary: "Run one-shot prompts with the built-in Poe agent runtime.",
11253
11656
  apiShapes: ["openai-responses", "openai-chat-completions"],
11254
11657
  configPath: "~/.poe-code/config.json",
11658
+ capabilities: ["configure"],
11255
11659
  branding: {
11256
11660
  colors: {
11257
11661
  dark: "#A465F7",
@@ -11268,6 +11672,9 @@ function freezeAgent(agent) {
11268
11672
  if (agent.apiShapes !== void 0) {
11269
11673
  Object.freeze(agent.apiShapes);
11270
11674
  }
11675
+ if (agent.capabilities !== void 0) {
11676
+ Object.freeze(agent.capabilities);
11677
+ }
11271
11678
  if (agent.otelCapture?.env !== void 0) {
11272
11679
  Object.freeze(agent.otelCapture.env);
11273
11680
  }
@@ -11331,7 +11738,8 @@ var agentSkillConfigs = {
11331
11738
  },
11332
11739
  goose: {
11333
11740
  globalSkillDir: "~/.agents/skills",
11334
- localSkillDir: ".agents/skills"
11741
+ localSkillDir: ".agents/skills",
11742
+ dirNote: "Goose discovers skills from the shared .agents/skills convention, not a goose-specific directory."
11335
11743
  }
11336
11744
  };
11337
11745
  var supportedAgents = Object.freeze(Object.keys(agentSkillConfigs));
@@ -12705,6 +13113,16 @@ async function executeMutation(mutation, context, options) {
12705
13113
  }
12706
13114
  }
12707
13115
 
13116
+ // ../user-error/src/index.ts
13117
+ var UserError2 = class extends Error {
13118
+ hint;
13119
+ constructor(message2, options) {
13120
+ super(message2, options);
13121
+ this.name = "UserError";
13122
+ this.hint = options?.hint;
13123
+ }
13124
+ };
13125
+
12708
13126
  // ../agent-skill-config/src/error-codes.ts
12709
13127
  function hasOwnErrorCode4(error3, code) {
12710
13128
  return error3 instanceof Error && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === code;
@@ -12756,8 +13174,11 @@ async function installSkill(agentId, skill, options) {
12756
13174
  const skillFilePath = `${skillFolderPath}/SKILL.md`;
12757
13175
  const displayPath = `${scope === "global" ? config2.globalSkillDir : config2.localSkillDir}/${skill.name}/SKILL.md`;
12758
13176
  const absoluteSkillPath = `${scope === "global" ? options.homeDir : options.cwd}/${skillFilePath.slice(2)}`;
12759
- if (await pathExists2(options.fs, absoluteSkillPath)) {
12760
- throw new Error(`Skill already exists: ${displayPath}`);
13177
+ if (!options.force && await pathExists2(options.fs, absoluteSkillPath)) {
13178
+ throw new UserError2(
13179
+ `Skill already exists: ${displayPath}
13180
+ Re-run with --force to overwrite it, or remove it first.`
13181
+ );
12761
13182
  }
12762
13183
  await runMutations(
12763
13184
  [
@@ -14835,7 +15256,7 @@ function sleep2(ms) {
14835
15256
  // src/cli.ts
14836
15257
  configureTheme({ brand: "green", label: "Terminal Pilot" });
14837
15258
  function getBundledPackageVersion() {
14838
- return true ? "0.0.48" : void 0;
15259
+ return true ? "0.0.50" : void 0;
14839
15260
  }
14840
15261
  var pilotOptionsWithValues = /* @__PURE__ */ new Set([
14841
15262
  "--session",