@laitszkin/apollo-toolkit 4.1.3 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/bin/apollo-toolkit.ts +4 -0
  3. package/dist/bin/apollo-toolkit.js +4 -0
  4. package/package.json +7 -2
  5. package/packages/cli/dist/help-text-builder.d.ts +23 -0
  6. package/packages/cli/dist/help-text-builder.js +166 -0
  7. package/packages/cli/dist/index.d.ts +6 -17
  8. package/packages/cli/dist/index.js +52 -246
  9. package/packages/cli/dist/installer.d.ts +1 -0
  10. package/packages/cli/dist/installer.js +20 -7
  11. package/packages/cli/dist/parsers/install-parser.d.ts +15 -0
  12. package/packages/cli/dist/parsers/install-parser.js +87 -0
  13. package/packages/cli/dist/parsers/parser-utils.d.ts +9 -0
  14. package/packages/cli/dist/parsers/parser-utils.js +16 -0
  15. package/packages/cli/dist/parsers/tool-parser.d.ts +16 -0
  16. package/packages/cli/dist/parsers/tool-parser.js +58 -0
  17. package/packages/cli/dist/parsers/types.d.ts +50 -0
  18. package/packages/cli/dist/parsers/types.js +1 -0
  19. package/packages/cli/dist/parsers/uninstall-parser.d.ts +15 -0
  20. package/packages/cli/dist/parsers/uninstall-parser.js +67 -0
  21. package/packages/cli/dist/tool-registration.d.ts +2 -0
  22. package/packages/cli/dist/tool-registration.js +2 -0
  23. package/packages/cli/dist/tsconfig.tsbuildinfo +1 -1
  24. package/packages/cli/dist/types.d.ts +3 -1
  25. package/packages/cli/dist/updater.js +11 -5
  26. package/packages/cli/help-text-builder.ts +180 -0
  27. package/packages/cli/index.ts +59 -251
  28. package/packages/cli/installer.ts +19 -7
  29. package/packages/cli/package.json +6 -3
  30. package/packages/cli/parsers/install-parser.ts +94 -0
  31. package/packages/cli/parsers/parser-utils.ts +17 -0
  32. package/packages/cli/parsers/tool-parser.ts +65 -0
  33. package/packages/cli/parsers/types.ts +56 -0
  34. package/packages/cli/parsers/uninstall-parser.ts +75 -0
  35. package/packages/cli/tool-registration.ts +3 -0
  36. package/packages/cli/types.ts +6 -1
  37. package/packages/cli/updater.ts +11 -5
  38. package/packages/tool-registry/dist/registry.js +3 -4
  39. package/packages/tool-registry/dist/tsconfig.tsbuildinfo +1 -1
  40. package/packages/tool-registry/dist/types.d.ts +2 -9
  41. package/packages/tool-registry/package.json +3 -3
  42. package/packages/tool-registry/registry.ts +3 -4
  43. package/packages/tool-registry/tsconfig.json +6 -2
  44. package/packages/tool-registry/types.ts +3 -9
  45. package/packages/tool-utils/app-error.ts +97 -0
  46. package/packages/tool-utils/dist/app-error.d.ts +49 -0
  47. package/packages/tool-utils/dist/app-error.js +80 -0
  48. package/packages/tool-utils/dist/index.d.ts +5 -0
  49. package/packages/tool-utils/dist/index.js +3 -0
  50. package/packages/tool-utils/dist/platform-adapter.d.ts +48 -0
  51. package/packages/tool-utils/dist/platform-adapter.js +73 -0
  52. package/packages/tool-utils/dist/schema.d.ts +68 -0
  53. package/packages/tool-utils/dist/schema.js +67 -0
  54. package/packages/tool-utils/dist/tsconfig.tsbuildinfo +1 -1
  55. package/packages/tool-utils/index.ts +12 -0
  56. package/packages/tool-utils/package.json +3 -3
  57. package/packages/tool-utils/platform-adapter.ts +112 -0
  58. package/packages/tool-utils/schema.ts +122 -0
  59. package/packages/tools/architecture/dist/index.d.ts +13 -0
  60. package/packages/tools/architecture/dist/index.js +55 -57
  61. package/packages/tools/architecture/dist/index.test.js +17 -4
  62. package/packages/tools/architecture/dist/tsconfig.tsbuildinfo +1 -1
  63. package/packages/tools/architecture/index.test.ts +27 -14
  64. package/packages/tools/architecture/index.ts +85 -88
  65. package/packages/tools/architecture/package.json +3 -3
  66. package/packages/tools/codegraph/dist/index.js +21 -17
  67. package/packages/tools/codegraph/dist/tsconfig.tsbuildinfo +1 -1
  68. package/packages/tools/codegraph/index.ts +21 -17
  69. package/packages/tools/codegraph/package.json +3 -3
  70. package/packages/tools/create-review-report/dist/index.d.ts +1 -2
  71. package/packages/tools/create-review-report/dist/index.js +46 -77
  72. package/packages/tools/create-review-report/dist/tsconfig.tsbuildinfo +1 -1
  73. package/packages/tools/create-review-report/index.ts +52 -81
  74. package/packages/tools/create-review-report/package.json +3 -3
  75. package/packages/tools/create-specs/dist/index.d.ts +1 -2
  76. package/packages/tools/create-specs/dist/index.js +70 -123
  77. package/packages/tools/create-specs/dist/tsconfig.tsbuildinfo +1 -1
  78. package/packages/tools/create-specs/index.ts +82 -128
  79. package/packages/tools/create-specs/package.json +3 -3
  80. package/packages/tools/docs-to-voice/dist/index.d.ts +1 -2
  81. package/packages/tools/docs-to-voice/dist/index.js +116 -219
  82. package/packages/tools/docs-to-voice/dist/tsconfig.tsbuildinfo +1 -1
  83. package/packages/tools/docs-to-voice/index.ts +265 -385
  84. package/packages/tools/docs-to-voice/package.json +3 -3
  85. package/packages/tools/enforce-video-aspect-ratio/dist/index.d.ts +1 -2
  86. package/packages/tools/enforce-video-aspect-ratio/dist/index.js +77 -154
  87. package/packages/tools/enforce-video-aspect-ratio/dist/tsconfig.tsbuildinfo +1 -1
  88. package/packages/tools/enforce-video-aspect-ratio/index.ts +87 -172
  89. package/packages/tools/enforce-video-aspect-ratio/package.json +3 -3
  90. package/packages/tools/eval/dist/index.js +7 -0
  91. package/packages/tools/eval/dist/tsconfig.tsbuildinfo +1 -1
  92. package/packages/tools/eval/index.ts +8 -0
  93. package/packages/tools/eval/package.json +3 -3
  94. package/packages/tools/extract-conversations/dist/index.d.ts +1 -2
  95. package/packages/tools/extract-conversations/dist/index.js +31 -29
  96. package/packages/tools/extract-conversations/dist/tsconfig.tsbuildinfo +1 -1
  97. package/packages/tools/extract-conversations/index.ts +37 -30
  98. package/packages/tools/extract-conversations/package.json +3 -3
  99. package/packages/tools/extract-pdf-text/dist/index.d.ts +1 -2
  100. package/packages/tools/extract-pdf-text/dist/index.js +44 -65
  101. package/packages/tools/extract-pdf-text/dist/tsconfig.tsbuildinfo +1 -1
  102. package/packages/tools/extract-pdf-text/index.ts +55 -74
  103. package/packages/tools/extract-pdf-text/package.json +3 -3
  104. package/packages/tools/filter-logs/dist/index.js +60 -84
  105. package/packages/tools/filter-logs/dist/tsconfig.tsbuildinfo +1 -1
  106. package/packages/tools/filter-logs/index.ts +67 -97
  107. package/packages/tools/filter-logs/package.json +3 -3
  108. package/packages/tools/find-github-issues/dist/index.d.ts +10 -0
  109. package/packages/tools/find-github-issues/dist/index.js +34 -5
  110. package/packages/tools/find-github-issues/dist/tsconfig.tsbuildinfo +1 -1
  111. package/packages/tools/find-github-issues/index.ts +37 -5
  112. package/packages/tools/find-github-issues/package.json +3 -3
  113. package/packages/tools/generate-storyboard-images/dist/index.d.ts +1 -2
  114. package/packages/tools/generate-storyboard-images/dist/index.js +98 -173
  115. package/packages/tools/generate-storyboard-images/dist/tsconfig.tsbuildinfo +1 -1
  116. package/packages/tools/generate-storyboard-images/index.ts +100 -188
  117. package/packages/tools/generate-storyboard-images/package.json +3 -3
  118. package/packages/tools/open-github-issue/dist/index.d.ts +13 -0
  119. package/packages/tools/open-github-issue/dist/index.js +67 -68
  120. package/packages/tools/open-github-issue/dist/tsconfig.tsbuildinfo +1 -1
  121. package/packages/tools/open-github-issue/index.ts +71 -72
  122. package/packages/tools/open-github-issue/package.json +3 -3
  123. package/packages/tools/read-github-issue/dist/index.d.ts +16 -1
  124. package/packages/tools/read-github-issue/dist/index.js +32 -40
  125. package/packages/tools/read-github-issue/dist/tsconfig.tsbuildinfo +1 -1
  126. package/packages/tools/read-github-issue/index.ts +32 -45
  127. package/packages/tools/read-github-issue/package.json +3 -3
  128. package/packages/tools/render-error-book/dist/index.d.ts +1 -2
  129. package/packages/tools/render-error-book/dist/index.js +74 -95
  130. package/packages/tools/render-error-book/dist/tsconfig.tsbuildinfo +1 -1
  131. package/packages/tools/render-error-book/index.ts +88 -103
  132. package/packages/tools/render-error-book/package.json +3 -3
  133. package/packages/tools/render-katex/dist/index.d.ts +1 -2
  134. package/packages/tools/render-katex/dist/index.js +70 -157
  135. package/packages/tools/render-katex/dist/tsconfig.tsbuildinfo +1 -1
  136. package/packages/tools/render-katex/index.ts +138 -222
  137. package/packages/tools/render-katex/package.json +3 -3
  138. package/packages/tools/review-threads/dist/index.d.ts +12 -0
  139. package/packages/tools/review-threads/dist/index.js +83 -86
  140. package/packages/tools/review-threads/dist/tsconfig.tsbuildinfo +1 -1
  141. package/packages/tools/review-threads/index.ts +90 -84
  142. package/packages/tools/review-threads/package.json +3 -3
  143. package/packages/tools/search-logs/dist/index.js +100 -136
  144. package/packages/tools/search-logs/dist/tsconfig.tsbuildinfo +1 -1
  145. package/packages/tools/search-logs/index.ts +113 -145
  146. package/packages/tools/search-logs/package.json +3 -3
  147. package/packages/tools/sync-memory-index/dist/index.js +34 -28
  148. package/packages/tools/sync-memory-index/dist/tsconfig.tsbuildinfo +1 -1
  149. package/packages/tools/sync-memory-index/index.ts +37 -28
  150. package/packages/tools/sync-memory-index/package.json +3 -3
  151. package/packages/tools/validate-openai-agent-config/dist/index.js +13 -7
  152. package/packages/tools/validate-openai-agent-config/dist/tsconfig.tsbuildinfo +1 -1
  153. package/packages/tools/validate-openai-agent-config/index.ts +13 -7
  154. package/packages/tools/validate-openai-agent-config/package.json +3 -3
  155. package/packages/tools/validate-skill-frontmatter/dist/index.js +12 -6
  156. package/packages/tools/validate-skill-frontmatter/dist/tsconfig.tsbuildinfo +1 -1
  157. package/packages/tools/validate-skill-frontmatter/index.ts +12 -6
  158. package/packages/tools/validate-skill-frontmatter/package.json +3 -3
  159. package/packages/tui/dist/index.d.ts +2 -1
  160. package/packages/tui/dist/index.js +1 -0
  161. package/packages/tui/dist/stdio-adapter.d.ts +36 -0
  162. package/packages/tui/dist/stdio-adapter.js +69 -0
  163. package/packages/tui/dist/terminal.js +3 -1
  164. package/packages/tui/dist/tsconfig.tsbuildinfo +1 -1
  165. package/packages/tui/dist/types.d.ts +17 -0
  166. package/packages/tui/index.ts +2 -1
  167. package/packages/tui/package.json +6 -5
  168. package/packages/tui/stdio-adapter.ts +85 -0
  169. package/packages/tui/terminal.ts +3 -1
  170. package/packages/tui/tsconfig.json +5 -2
  171. package/packages/tui/types.ts +19 -0
  172. package/resources/project-architecture/assets/architecture.css +2 -1
  173. package/resources/project-architecture/atlas/atlas.history.log +1 -0
  174. package/resources/project-architecture/atlas/atlas.history.undo.json +13 -2
  175. package/resources/project-architecture/atlas/atlas.history.undo.stack.json +610 -0
  176. package/resources/project-architecture/atlas/atlas.index.yaml +81 -5
  177. package/resources/project-architecture/atlas/features/cli-dispatch.yaml +43 -0
  178. package/resources/project-architecture/atlas/features/terminal-ui.yaml +29 -0
  179. package/resources/project-architecture/atlas/features/tool-registry.yaml +22 -0
  180. package/resources/project-architecture/atlas/features/tool-utils.yaml +22 -0
  181. package/resources/project-architecture/features/cli-dispatch/arg-parser.html +40 -0
  182. package/resources/project-architecture/features/cli-dispatch/help-builder.html +40 -0
  183. package/resources/project-architecture/features/cli-dispatch/index.html +64 -0
  184. package/resources/project-architecture/features/cli-dispatch/installer-core.html +40 -0
  185. package/resources/project-architecture/features/cli-dispatch/tool-discovery.html +40 -0
  186. package/resources/project-architecture/features/cli-dispatch/update-checker.html +40 -0
  187. package/resources/project-architecture/features/terminal-ui/banner-display.html +40 -0
  188. package/resources/project-architecture/features/terminal-ui/index.html +50 -0
  189. package/resources/project-architecture/features/terminal-ui/interactive-prompts.html +40 -0
  190. package/resources/project-architecture/features/terminal-ui/terminal-detection.html +40 -0
  191. package/resources/project-architecture/features/tool-registry/formatter.html +40 -0
  192. package/resources/project-architecture/features/tool-registry/index.html +43 -0
  193. package/resources/project-architecture/features/tool-registry/registry-core.html +40 -0
  194. package/resources/project-architecture/features/tool-utils/index.html +43 -0
  195. package/resources/project-architecture/features/tool-utils/log-utils.html +40 -0
  196. package/resources/project-architecture/features/tool-utils/skill-discovery.html +40 -0
  197. package/resources/project-architecture/index.html +365 -121
  198. package/scripts/rewrite-imports.mjs +2 -2
  199. package/scripts/test.sh +144 -8
  200. package/skills/design/SKILL.md +57 -64
  201. package/skills/design/assets/templates/DESIGN.md +12 -0
  202. package/skills/design/references/code-smells.md +94 -0
  203. package/skills/design/references/module-boundary-adjustment.md +126 -0
  204. package/skills/design/references/module-internal-restructuring.md +132 -0
  205. package/skills/design/references/module-internal-simplification.md +164 -0
@@ -2,6 +2,7 @@ import { execSync } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import type { ToolDefinition, ToolContext } from '@laitszkin/tool-registry';
5
+ import { createToolRunner, UserInputError, SystemError } from '@laitszkin/tool-utils';
5
6
 
6
7
  interface KatexArgs {
7
8
  tex: string | null;
@@ -28,138 +29,46 @@ interface KatexArgs {
28
29
  minRuleThickness: number | null;
29
30
  }
30
31
 
31
- function parseArgs(args: string[]): KatexArgs {
32
- const parsed: KatexArgs = {
33
- tex: null,
34
- inputFile: null,
35
- outputFormat: 'html-fragment',
36
- katexFormat: 'htmlAndMathml',
37
- displayMode: false,
38
- leqno: false,
39
- fleqn: false,
40
- colorIsTextColor: false,
41
- noThrowOnError: false,
42
- outputFile: null,
43
- cssHref: 'https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.css',
44
- title: 'KaTeX Render',
45
- lang: 'en',
32
+ function convertValuesToKatexArgs(values: Record<string, unknown>): KatexArgs {
33
+ const rawOutputFormat = values['output-format'] as string | undefined;
34
+ const rawKatexFormat = values['katex-format'] as string | undefined;
35
+ const rawMaxSize = values['max-size'] as string | undefined;
36
+ const rawMaxExpand = values['max-expand'] as string | undefined;
37
+ const rawMinRuleThickness = values['min-rule-thickness'] as string | undefined;
38
+
39
+ return {
40
+ tex: (values['tex'] as string | undefined) ?? null,
41
+ inputFile: (values['input-file'] as string | undefined) ?? null,
42
+ outputFormat: rawOutputFormat && ['html-fragment', 'html-page', 'markdown-inline', 'markdown-block', 'json'].includes(rawOutputFormat)
43
+ ? rawOutputFormat : 'html-fragment',
44
+ katexFormat: rawKatexFormat && ['html', 'mathml', 'htmlAndMathml'].includes(rawKatexFormat)
45
+ ? rawKatexFormat : 'htmlAndMathml',
46
+ displayMode: !!values['display-mode'],
47
+ leqno: !!values['leqno'],
48
+ fleqn: !!values['fleqn'],
49
+ colorIsTextColor: !!values['color-is-text-color'],
50
+ noThrowOnError: !!values['no-throw-on-error'],
51
+ outputFile: (values['output-file'] as string | undefined) ?? null,
52
+ cssHref: (values['css-href'] as string) || 'https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.css',
53
+ title: (values['title'] as string) || 'KaTeX Render',
54
+ lang: (values['lang'] as string) || 'en',
46
55
  help: false,
47
- macro: [],
48
- macroFile: null,
49
- errorColor: null,
50
- strict: null,
51
- trust: null,
52
- maxSize: null,
53
- maxExpand: null,
54
- minRuleThickness: null,
56
+ macro: values['macro'] ? [values['macro'] as string] : [],
57
+ macroFile: (values['macro-file'] as string | undefined) ?? null,
58
+ errorColor: (values['error-color'] as string | undefined) ?? null,
59
+ strict: (values['strict'] as string | undefined) ?? null,
60
+ trust: (values['trust'] as string | undefined) ?? null,
61
+ maxSize: rawMaxSize ? Number(rawMaxSize) : null,
62
+ maxExpand: rawMaxExpand ? Number(rawMaxExpand) : null,
63
+ minRuleThickness: rawMinRuleThickness ? Number(rawMinRuleThickness) : null,
55
64
  };
56
-
57
- for (let i = 0; i < args.length; i++) {
58
- const arg = args[i];
59
- if (arg === '--help' || arg === '-h') {
60
- parsed.help = true;
61
- continue;
62
- }
63
-
64
- if (arg.startsWith('--')) {
65
- const eqIndex = arg.indexOf('=');
66
- let key: string;
67
- let value: string | boolean | null;
68
-
69
- if (eqIndex !== -1) {
70
- key = arg.slice(2, eqIndex);
71
- value = arg.slice(eqIndex + 1);
72
- } else {
73
- key = arg.slice(2);
74
- const next = args[i + 1];
75
- if (next !== undefined && !next.startsWith('--')) {
76
- value = next;
77
- i++;
78
- } else {
79
- value = true;
80
- }
81
- }
82
-
83
- switch (key) {
84
- case 'tex':
85
- parsed.tex = String(value);
86
- break;
87
- case 'input-file':
88
- parsed.inputFile = String(value);
89
- break;
90
- case 'output-format':
91
- if (['html-fragment', 'html-page', 'markdown-inline', 'markdown-block', 'json'].includes(String(value))) {
92
- parsed.outputFormat = String(value);
93
- }
94
- break;
95
- case 'katex-format':
96
- if (['html', 'mathml', 'htmlAndMathml'].includes(String(value))) {
97
- parsed.katexFormat = String(value);
98
- }
99
- break;
100
- case 'display-mode':
101
- parsed.displayMode = value === true || value === 'true';
102
- break;
103
- case 'leqno':
104
- parsed.leqno = value === true || value === 'true';
105
- break;
106
- case 'fleqn':
107
- parsed.fleqn = value === true || value === 'true';
108
- break;
109
- case 'color-is-text-color':
110
- parsed.colorIsTextColor = value === true || value === 'true';
111
- break;
112
- case 'no-throw-on-error':
113
- parsed.noThrowOnError = value === true || value === 'true';
114
- break;
115
- case 'output-file':
116
- parsed.outputFile = String(value);
117
- break;
118
- case 'css-href':
119
- parsed.cssHref = String(value);
120
- break;
121
- case 'title':
122
- parsed.title = String(value);
123
- break;
124
- case 'lang':
125
- parsed.lang = String(value);
126
- break;
127
- case 'macro':
128
- parsed.macro.push(String(value));
129
- break;
130
- case 'macro-file':
131
- parsed.macroFile = String(value);
132
- break;
133
- case 'error-color':
134
- parsed.errorColor = String(value);
135
- break;
136
- case 'strict':
137
- parsed.strict = String(value);
138
- break;
139
- case 'trust':
140
- parsed.trust = String(value);
141
- break;
142
- case 'max-size':
143
- parsed.maxSize = Number(value);
144
- break;
145
- case 'max-expand':
146
- parsed.maxExpand = Number(value);
147
- break;
148
- case 'min-rule-thickness':
149
- parsed.minRuleThickness = Number(value);
150
- break;
151
- }
152
- }
153
- }
154
-
155
- return parsed;
156
65
  }
157
66
 
158
67
  function loadTex(opts: KatexArgs): string {
159
68
  if (opts.inputFile) {
160
69
  const inputPath = path.resolve(opts.inputFile);
161
70
  if (!fs.existsSync(inputPath)) {
162
- throw new Error(`Input file not found: ${inputPath}`);
71
+ throw new UserInputError(`Input file not found: ${inputPath}`);
163
72
  }
164
73
  return fs.readFileSync(inputPath, 'utf-8').trim();
165
74
  }
@@ -208,7 +117,7 @@ function wrapOutput(renderedHtml: string, tex: string, opts: KatexArgs): string
208
117
  2,
209
118
  ) + '\n';
210
119
  default:
211
- throw new Error(`Unsupported output format: ${opts.outputFormat}`);
120
+ throw new UserInputError(`Unsupported output format: ${opts.outputFormat}`);
212
121
  }
213
122
  }
214
123
 
@@ -223,110 +132,117 @@ function writeOutput(content: string, outputFile: string | null, stdout: NodeJS.
223
132
  stdout.write(`${outputPath}\n`);
224
133
  }
225
134
 
226
- export async function renderKatexHandler(args: string[], context: ToolContext): Promise<number> {
227
- const stdout = context.stdout || process.stdout;
228
- const stderr = context.stderr || process.stderr;
229
-
230
- try {
231
- const opts = parseArgs(args);
232
-
233
- if (opts.help) {
234
- stdout.write(`Usage: apltk render-katex [options]
235
-
236
- Render TeX with KaTeX and emit insertion-ready output.
237
-
238
- Options:
239
- --tex <string> Raw TeX expression without delimiters
240
- --input-file <path> Path to a text file containing raw TeX
241
- --output-format <format> html-fragment (default) | html-page | markdown-inline | markdown-block | json
242
- --katex-format <format> html | mathml | htmlAndMathml (default)
243
- --display-mode Render in display mode
244
- --output-file <path> Write output to a file
245
- --css-href <url> Stylesheet href (default: KaTeX CDN)
246
- --title <text> Document title for html-page
247
- --lang <code> HTML lang attribute (default: en)
248
- `);
249
- return 0;
250
- }
251
-
252
- const tex = loadTex(opts);
253
- if (!tex) {
254
- stderr.write('Error: Input TeX is empty.\n');
255
- return 1;
256
- }
257
-
258
- // Build npx katex command
259
- const cmdArgs: string[] = [
260
- 'npx',
261
- '--yes',
262
- '--package',
263
- 'katex',
264
- 'katex',
265
- '--format',
266
- opts.katexFormat,
267
- ];
268
-
269
- if (opts.displayMode) cmdArgs.push('--display-mode');
270
- if (opts.leqno === true) cmdArgs.push('--leqno');
271
- if (opts.fleqn === true) cmdArgs.push('--fleqn');
272
- if (opts.colorIsTextColor === true) cmdArgs.push('--color-is-text-color');
273
- if (opts.noThrowOnError === true) cmdArgs.push('--no-throw-on-error');
274
-
275
- if (opts.errorColor) cmdArgs.push('--error-color', opts.errorColor);
276
- if (opts.strict) cmdArgs.push('--strict', opts.strict);
277
- if (opts.trust) cmdArgs.push('--trust', opts.trust);
278
- if (opts.maxSize !== null) cmdArgs.push('--max-size', String(opts.maxSize));
279
- if (opts.maxExpand !== null) cmdArgs.push('--max-expand', String(opts.maxExpand));
280
- if (opts.minRuleThickness !== null) cmdArgs.push('--min-rule-thickness', String(opts.minRuleThickness));
281
- // Handle macro args
282
- for (const macro of opts.macro) {
283
- cmdArgs.push('--macro', macro);
284
- }
285
- if (opts.macroFile) cmdArgs.push('--macro-file', opts.macroFile);
286
-
287
- // Write tex to temp file and pass it to katex
288
- const tmpFile = path.join(
289
- fs.mkdtempSync('katex-'),
290
- 'input.tex',
291
- );
292
- fs.mkdirSync(path.dirname(tmpFile), { recursive: true });
293
- fs.writeFileSync(tmpFile, tex + '\n', 'utf-8');
294
- cmdArgs.push('--input', tmpFile);
135
+ // ── Schema ────────────────────────────────────────────────────────────────────
136
+
137
+ const schema = {
138
+ options: {
139
+ 'tex': { type: 'string' as const },
140
+ 'input-file': { type: 'string' as const },
141
+ 'output-format': { type: 'string' as const, default: 'html-fragment' },
142
+ 'katex-format': { type: 'string' as const, default: 'htmlAndMathml' },
143
+ 'display-mode': { type: 'boolean' as const },
144
+ 'leqno': { type: 'boolean' as const },
145
+ 'fleqn': { type: 'boolean' as const },
146
+ 'color-is-text-color': { type: 'boolean' as const },
147
+ 'no-throw-on-error': { type: 'boolean' as const },
148
+ 'output-file': { type: 'string' as const },
149
+ 'css-href': { type: 'string' as const, default: 'https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.css' },
150
+ 'title': { type: 'string' as const, default: 'KaTeX Render' },
151
+ 'lang': { type: 'string' as const, default: 'en' },
152
+ 'macro': { type: 'string' as const },
153
+ 'macro-file': { type: 'string' as const },
154
+ 'error-color': { type: 'string' as const },
155
+ 'strict': { type: 'string' as const },
156
+ 'trust': { type: 'string' as const },
157
+ 'max-size': { type: 'string' as const },
158
+ 'max-expand': { type: 'string' as const },
159
+ 'min-rule-thickness': { type: 'string' as const },
160
+ },
161
+ allowPositionals: true,
162
+ usage: 'apltk render-katex [options]',
163
+ description: 'Render TeX with KaTeX and emit insertion-ready output.',
164
+ handler: async (
165
+ values: Record<string, unknown>,
166
+ positionals: string[],
167
+ context: ToolContext,
168
+ ): Promise<number> => {
169
+ const stdout = context.stdout || process.stdout;
170
+ const stderr = context.stderr || process.stderr;
171
+
172
+ const opts = convertValuesToKatexArgs(values);
173
+
174
+ const tex = loadTex(opts);
175
+ if (!tex) {
176
+ throw new UserInputError('Input TeX is empty.');
177
+ }
295
178
 
296
- let renderedHtml: string;
297
- try {
298
- const result = execSync(cmdArgs.join(' '), {
299
- encoding: 'utf-8',
300
- maxBuffer: 10 * 1024 * 1024,
301
- timeout: 60000,
302
- });
303
- renderedHtml = result.trim();
304
- } catch (err: unknown) {
305
- const message = err instanceof Error ? err.message : 'KaTeX CLI failed.';
306
- stderr.write(`Error: ${message}\n`);
307
- return 1;
308
- } finally {
179
+ // Build npx katex command
180
+ const cmdArgs: string[] = [
181
+ 'npx',
182
+ '--yes',
183
+ '--package',
184
+ 'katex',
185
+ 'katex',
186
+ '--format',
187
+ opts.katexFormat,
188
+ ];
189
+
190
+ if (opts.displayMode) cmdArgs.push('--display-mode');
191
+ if (opts.leqno === true) cmdArgs.push('--leqno');
192
+ if (opts.fleqn === true) cmdArgs.push('--fleqn');
193
+ if (opts.colorIsTextColor === true) cmdArgs.push('--color-is-text-color');
194
+ if (opts.noThrowOnError === true) cmdArgs.push('--no-throw-on-error');
195
+
196
+ if (opts.errorColor) cmdArgs.push('--error-color', opts.errorColor);
197
+ if (opts.strict) cmdArgs.push('--strict', opts.strict);
198
+ if (opts.trust) cmdArgs.push('--trust', opts.trust);
199
+ if (opts.maxSize !== null) cmdArgs.push('--max-size', String(opts.maxSize));
200
+ if (opts.maxExpand !== null) cmdArgs.push('--max-expand', String(opts.maxExpand));
201
+ if (opts.minRuleThickness !== null) cmdArgs.push('--min-rule-thickness', String(opts.minRuleThickness));
202
+ // Handle macro args
203
+ for (const macro of opts.macro) {
204
+ cmdArgs.push('--macro', macro);
205
+ }
206
+ if (opts.macroFile) cmdArgs.push('--macro-file', opts.macroFile);
207
+
208
+ // Write tex to temp file and pass it to katex
209
+ const tmpFile = path.join(
210
+ fs.mkdtempSync('katex-'),
211
+ 'input.tex',
212
+ );
213
+ fs.mkdirSync(path.dirname(tmpFile), { recursive: true });
214
+ fs.writeFileSync(tmpFile, tex + '\n', 'utf-8');
215
+ cmdArgs.push('--input', tmpFile);
216
+
217
+ let renderedHtml: string;
309
218
  try {
310
- fs.unlinkSync(tmpFile);
311
- fs.rmdirSync(path.dirname(tmpFile));
312
- } catch {
313
- // ignore cleanup errors
219
+ const result = execSync(cmdArgs.join(' '), {
220
+ encoding: 'utf-8',
221
+ maxBuffer: 10 * 1024 * 1024,
222
+ timeout: 60000,
223
+ });
224
+ renderedHtml = result.trim();
225
+ } catch (err: unknown) {
226
+ const message = err instanceof Error ? err.message : 'KaTeX CLI failed.';
227
+ throw new SystemError(message);
228
+ } finally {
229
+ try {
230
+ fs.unlinkSync(tmpFile);
231
+ fs.rmdirSync(path.dirname(tmpFile));
232
+ } catch {
233
+ // ignore cleanup errors
234
+ }
314
235
  }
315
- }
316
236
 
317
- const wrapped = wrapOutput(renderedHtml, tex, opts);
318
- writeOutput(wrapped, opts.outputFile, stdout);
319
- return 0;
320
- } catch (err: unknown) {
321
- const message = err instanceof Error ? err.message : 'Unknown error';
322
- stderr.write(`Error: ${message}\n`);
323
- return 1;
324
- }
325
- }
237
+ const wrapped = wrapOutput(renderedHtml, tex, opts);
238
+ writeOutput(wrapped, opts.outputFile, stdout);
239
+ return 0;
240
+ },
241
+ };
326
242
 
327
243
  export const tool: ToolDefinition = {
328
244
  name: 'render-katex',
329
245
  category: 'media',
330
246
  description: 'Render TeX with KaTeX and emit insertion-ready output.',
331
- handler: renderKatexHandler,
247
+ handler: createToolRunner(schema),
332
248
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@laitszkin/tool-render-katex",
3
- "version": "4.0.8",
4
- "description": "Apollo Toolkit CLI tool",
3
+ "version": "5.0.0",
4
+ "description": "Apollo Toolkit \u2014 CLI tool",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -19,4 +19,4 @@
19
19
  "dependencies": {
20
20
  "@laitszkin/tool-registry": "*"
21
21
  }
22
- }
22
+ }
@@ -1,3 +1,15 @@
1
1
  import type { ToolDefinition, ToolContext } from '@laitszkin/tool-registry';
2
+ /**
3
+ * reviewThreadsHandler — Known carryover from createToolRunner migration.
4
+ *
5
+ * Reason for not using createToolRunner:
6
+ * - Positional subcommand architecture (list/resolve) doesn't map cleanly
7
+ * to createToolRunner's options schema.
8
+ * - Error handling follows the AppError convention (UserInputError/SystemError
9
+ * throws) — errors propagate to the CLI boundary's formatAppError.
10
+ * - Argument parsing is handled manually via a 63-line parseArgs().
11
+ *
12
+ * See DESIGN.md §2.3 for the full architecture discussion.
13
+ */
2
14
  export declare function reviewThreadsHandler(argv: string[], context: ToolContext): Promise<number>;
3
15
  export declare const tool: ToolDefinition;