terminal-pilot 0.0.30 → 0.0.32

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 (329) hide show
  1. package/dist/cli.js +1599 -497
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.js +489 -6
  4. package/dist/commands/close-session.js.map +4 -4
  5. package/dist/commands/create-session.js +489 -6
  6. package/dist/commands/create-session.js.map +4 -4
  7. package/dist/commands/fill.js +489 -6
  8. package/dist/commands/fill.js.map +4 -4
  9. package/dist/commands/get-session.js +489 -6
  10. package/dist/commands/get-session.js.map +4 -4
  11. package/dist/commands/index.js +630 -44
  12. package/dist/commands/index.js.map +4 -4
  13. package/dist/commands/install.js +626 -40
  14. package/dist/commands/install.js.map +4 -4
  15. package/dist/commands/installer.js +68 -17
  16. package/dist/commands/installer.js.map +4 -4
  17. package/dist/commands/list-sessions.js +489 -6
  18. package/dist/commands/list-sessions.js.map +4 -4
  19. package/dist/commands/press-key.js +489 -6
  20. package/dist/commands/press-key.js.map +4 -4
  21. package/dist/commands/read-history.js +489 -6
  22. package/dist/commands/read-history.js.map +4 -4
  23. package/dist/commands/read-screen.js +489 -6
  24. package/dist/commands/read-screen.js.map +4 -4
  25. package/dist/commands/resize.js +489 -6
  26. package/dist/commands/resize.js.map +4 -4
  27. package/dist/commands/runtime.js.map +1 -1
  28. package/dist/commands/screenshot.js +489 -6
  29. package/dist/commands/screenshot.js.map +4 -4
  30. package/dist/commands/send-signal.js +489 -6
  31. package/dist/commands/send-signal.js.map +4 -4
  32. package/dist/commands/type.js +489 -6
  33. package/dist/commands/type.js.map +4 -4
  34. package/dist/commands/uninstall.js +554 -20
  35. package/dist/commands/uninstall.js.map +4 -4
  36. package/dist/commands/wait-for-exit.js +489 -6
  37. package/dist/commands/wait-for-exit.js.map +4 -4
  38. package/dist/commands/wait-for.js +489 -6
  39. package/dist/commands/wait-for.js.map +4 -4
  40. package/dist/testing/cli-repl.js +1599 -497
  41. package/dist/testing/cli-repl.js.map +4 -4
  42. package/dist/testing/qa-cli.js +1609 -507
  43. package/dist/testing/qa-cli.js.map +4 -4
  44. package/node_modules/@poe-code/agent-defs/README.md +35 -0
  45. package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.d.ts +2 -0
  46. package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.js +21 -0
  47. package/node_modules/@poe-code/agent-defs/dist/agents/claude-desktop.d.ts +2 -0
  48. package/node_modules/@poe-code/agent-defs/dist/agents/claude-desktop.js +18 -0
  49. package/node_modules/@poe-code/agent-defs/dist/agents/codex.d.ts +2 -0
  50. package/node_modules/@poe-code/agent-defs/dist/agents/codex.js +25 -0
  51. package/node_modules/@poe-code/agent-defs/dist/agents/cursor.d.ts +2 -0
  52. package/node_modules/@poe-code/agent-defs/dist/agents/cursor.js +15 -0
  53. package/node_modules/@poe-code/agent-defs/dist/agents/gemini-cli.d.ts +2 -0
  54. package/node_modules/@poe-code/agent-defs/dist/agents/gemini-cli.js +16 -0
  55. package/node_modules/@poe-code/agent-defs/dist/agents/goose.d.ts +2 -0
  56. package/node_modules/@poe-code/agent-defs/dist/agents/goose.js +16 -0
  57. package/node_modules/@poe-code/agent-defs/dist/agents/index.d.ts +9 -0
  58. package/node_modules/@poe-code/agent-defs/dist/agents/index.js +9 -0
  59. package/node_modules/@poe-code/agent-defs/dist/agents/kimi.d.ts +2 -0
  60. package/node_modules/@poe-code/agent-defs/dist/agents/kimi.js +16 -0
  61. package/node_modules/@poe-code/agent-defs/dist/agents/opencode.d.ts +2 -0
  62. package/node_modules/@poe-code/agent-defs/dist/agents/opencode.js +20 -0
  63. package/node_modules/@poe-code/agent-defs/dist/agents/poe-agent.d.ts +2 -0
  64. package/node_modules/@poe-code/agent-defs/dist/agents/poe-agent.js +14 -0
  65. package/node_modules/@poe-code/agent-defs/dist/index.d.ts +5 -0
  66. package/node_modules/@poe-code/agent-defs/dist/index.js +3 -0
  67. package/node_modules/@poe-code/agent-defs/dist/registry.d.ts +3 -0
  68. package/node_modules/@poe-code/agent-defs/dist/registry.js +45 -0
  69. package/node_modules/@poe-code/agent-defs/dist/specifier.d.ts +7 -0
  70. package/node_modules/@poe-code/agent-defs/dist/specifier.js +40 -0
  71. package/node_modules/@poe-code/agent-defs/dist/types.d.ts +28 -0
  72. package/node_modules/@poe-code/agent-defs/dist/types.js +1 -0
  73. package/node_modules/@poe-code/agent-defs/package.json +20 -0
  74. package/node_modules/@poe-code/agent-skill-config/dist/apply.js +2 -1
  75. package/node_modules/@poe-code/agent-skill-config/dist/bridge-active-skills.d.ts +1 -0
  76. package/node_modules/@poe-code/agent-skill-config/dist/bridge-active-skills.js +37 -18
  77. package/node_modules/@poe-code/agent-skill-config/dist/resolve-skill-reference.js +8 -4
  78. package/node_modules/@poe-code/agent-skill-config/package.json +1 -5
  79. package/node_modules/@poe-code/config-mutations/README.md +55 -0
  80. package/node_modules/@poe-code/config-mutations/dist/error-codes.d.ts +1 -0
  81. package/node_modules/@poe-code/config-mutations/dist/error-codes.js +6 -0
  82. package/node_modules/@poe-code/config-mutations/dist/execution/apply-mutation.d.ts +6 -0
  83. package/node_modules/@poe-code/config-mutations/dist/execution/apply-mutation.js +829 -0
  84. package/node_modules/@poe-code/config-mutations/dist/execution/path-utils.d.ts +17 -0
  85. package/node_modules/@poe-code/config-mutations/dist/execution/path-utils.js +64 -0
  86. package/node_modules/@poe-code/config-mutations/dist/execution/run-mutations.d.ts +7 -0
  87. package/node_modules/@poe-code/config-mutations/dist/execution/run-mutations.js +39 -0
  88. package/node_modules/@poe-code/config-mutations/dist/formats/index.d.ts +13 -0
  89. package/node_modules/@poe-code/config-mutations/dist/formats/index.js +49 -0
  90. package/node_modules/@poe-code/config-mutations/dist/formats/json.d.ts +32 -0
  91. package/node_modules/@poe-code/config-mutations/dist/formats/json.js +171 -0
  92. package/node_modules/@poe-code/config-mutations/dist/formats/object.d.ts +4 -0
  93. package/node_modules/@poe-code/config-mutations/dist/formats/object.js +27 -0
  94. package/node_modules/@poe-code/config-mutations/dist/formats/toml.d.ts +2 -0
  95. package/node_modules/@poe-code/config-mutations/dist/formats/toml.js +75 -0
  96. package/node_modules/@poe-code/config-mutations/dist/formats/yaml.d.ts +2 -0
  97. package/node_modules/@poe-code/config-mutations/dist/formats/yaml.js +76 -0
  98. package/node_modules/@poe-code/config-mutations/dist/fs-utils.d.ts +18 -0
  99. package/node_modules/@poe-code/config-mutations/dist/fs-utils.js +43 -0
  100. package/node_modules/@poe-code/config-mutations/dist/index.d.ts +8 -0
  101. package/node_modules/@poe-code/config-mutations/dist/index.js +8 -0
  102. package/node_modules/@poe-code/config-mutations/dist/mutations/config-mutation.d.ts +47 -0
  103. package/node_modules/@poe-code/config-mutations/dist/mutations/config-mutation.js +34 -0
  104. package/node_modules/@poe-code/config-mutations/dist/mutations/file-mutation.d.ts +62 -0
  105. package/node_modules/@poe-code/config-mutations/dist/mutations/file-mutation.js +55 -0
  106. package/node_modules/@poe-code/config-mutations/dist/mutations/template-mutation.d.ts +40 -0
  107. package/node_modules/@poe-code/config-mutations/dist/mutations/template-mutation.js +32 -0
  108. package/node_modules/@poe-code/config-mutations/dist/template/render.d.ts +6 -0
  109. package/node_modules/@poe-code/config-mutations/dist/template/render.js +8 -0
  110. package/node_modules/@poe-code/config-mutations/dist/testing/format-utils.d.ts +7 -0
  111. package/node_modules/@poe-code/config-mutations/dist/testing/format-utils.js +21 -0
  112. package/node_modules/@poe-code/config-mutations/dist/testing/index.d.ts +3 -0
  113. package/node_modules/@poe-code/config-mutations/dist/testing/index.js +2 -0
  114. package/node_modules/@poe-code/config-mutations/dist/testing/mock-fs.d.ts +25 -0
  115. package/node_modules/@poe-code/config-mutations/dist/testing/mock-fs.js +194 -0
  116. package/node_modules/@poe-code/config-mutations/dist/types.d.ts +168 -0
  117. package/node_modules/@poe-code/config-mutations/dist/types.js +6 -0
  118. package/node_modules/@poe-code/config-mutations/package.json +29 -0
  119. package/node_modules/@poe-code/frontmatter/README.md +35 -0
  120. package/node_modules/@poe-code/frontmatter/dist/fences.d.ts +25 -0
  121. package/node_modules/@poe-code/frontmatter/dist/fences.js +100 -0
  122. package/node_modules/@poe-code/frontmatter/dist/index.d.ts +3 -0
  123. package/node_modules/@poe-code/frontmatter/dist/index.js +3 -0
  124. package/node_modules/@poe-code/frontmatter/dist/parse.d.ts +20 -0
  125. package/node_modules/@poe-code/frontmatter/dist/parse.js +209 -0
  126. package/node_modules/@poe-code/frontmatter/dist/stringify.d.ts +1 -0
  127. package/node_modules/@poe-code/frontmatter/dist/stringify.js +48 -0
  128. package/node_modules/@poe-code/frontmatter/package.json +25 -0
  129. package/node_modules/toolcraft-design/README.md +160 -0
  130. package/node_modules/toolcraft-design/dist/acp/components.d.ts +12 -0
  131. package/node_modules/toolcraft-design/dist/acp/components.js +137 -0
  132. package/node_modules/toolcraft-design/dist/acp/index.d.ts +3 -0
  133. package/node_modules/toolcraft-design/dist/acp/index.js +2 -0
  134. package/node_modules/toolcraft-design/dist/acp/writer.d.ts +13 -0
  135. package/node_modules/toolcraft-design/dist/acp/writer.js +21 -0
  136. package/node_modules/toolcraft-design/dist/components/browser.d.ts +15 -0
  137. package/node_modules/toolcraft-design/dist/components/browser.js +31 -0
  138. package/node_modules/toolcraft-design/dist/components/catalog.d.ts +26 -0
  139. package/node_modules/toolcraft-design/dist/components/catalog.js +95 -0
  140. package/node_modules/toolcraft-design/dist/components/color.d.ts +31 -0
  141. package/node_modules/toolcraft-design/dist/components/color.js +102 -0
  142. package/node_modules/toolcraft-design/dist/components/command-errors.d.ts +16 -0
  143. package/node_modules/toolcraft-design/dist/components/command-errors.js +23 -0
  144. package/node_modules/toolcraft-design/dist/components/detail-card.d.ts +22 -0
  145. package/node_modules/toolcraft-design/dist/components/detail-card.js +45 -0
  146. package/node_modules/toolcraft-design/dist/components/help-formatter-plain.d.ts +5 -0
  147. package/node_modules/toolcraft-design/dist/components/help-formatter-plain.js +132 -0
  148. package/node_modules/toolcraft-design/dist/components/help-formatter.d.ts +33 -0
  149. package/node_modules/toolcraft-design/dist/components/help-formatter.js +213 -0
  150. package/node_modules/toolcraft-design/dist/components/index.d.ts +16 -0
  151. package/node_modules/toolcraft-design/dist/components/index.js +10 -0
  152. package/node_modules/toolcraft-design/dist/components/logger.d.ts +11 -0
  153. package/node_modules/toolcraft-design/dist/components/logger.js +60 -0
  154. package/node_modules/toolcraft-design/dist/components/symbols.d.ts +12 -0
  155. package/node_modules/toolcraft-design/dist/components/symbols.js +71 -0
  156. package/node_modules/toolcraft-design/dist/components/table.d.ts +15 -0
  157. package/node_modules/toolcraft-design/dist/components/table.js +302 -0
  158. package/node_modules/toolcraft-design/dist/components/template.d.ts +10 -0
  159. package/node_modules/toolcraft-design/dist/components/template.js +437 -0
  160. package/node_modules/toolcraft-design/dist/components/text.d.ts +16 -0
  161. package/node_modules/toolcraft-design/dist/components/text.js +145 -0
  162. package/node_modules/toolcraft-design/dist/dashboard/ansi.d.ts +18 -0
  163. package/node_modules/toolcraft-design/dist/dashboard/ansi.js +343 -0
  164. package/node_modules/toolcraft-design/dist/dashboard/buffer.d.ts +25 -0
  165. package/node_modules/toolcraft-design/dist/dashboard/buffer.js +219 -0
  166. package/node_modules/toolcraft-design/dist/dashboard/components/border.d.ts +9 -0
  167. package/node_modules/toolcraft-design/dist/dashboard/components/border.js +123 -0
  168. package/node_modules/toolcraft-design/dist/dashboard/components/footer.d.ts +8 -0
  169. package/node_modules/toolcraft-design/dist/dashboard/components/footer.js +56 -0
  170. package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.d.ts +12 -0
  171. package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.js +268 -0
  172. package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.d.ts +7 -0
  173. package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.js +107 -0
  174. package/node_modules/toolcraft-design/dist/dashboard/dashboard.d.ts +20 -0
  175. package/node_modules/toolcraft-design/dist/dashboard/dashboard.js +167 -0
  176. package/node_modules/toolcraft-design/dist/dashboard/demo.d.ts +13 -0
  177. package/node_modules/toolcraft-design/dist/dashboard/demo.js +145 -0
  178. package/node_modules/toolcraft-design/dist/dashboard/index.d.ts +8 -0
  179. package/node_modules/toolcraft-design/dist/dashboard/index.js +4 -0
  180. package/node_modules/toolcraft-design/dist/dashboard/keymap.d.ts +8 -0
  181. package/node_modules/toolcraft-design/dist/dashboard/keymap.js +233 -0
  182. package/node_modules/toolcraft-design/dist/dashboard/layout.d.ts +25 -0
  183. package/node_modules/toolcraft-design/dist/dashboard/layout.js +79 -0
  184. package/node_modules/toolcraft-design/dist/dashboard/should-use-dashboard.d.ts +10 -0
  185. package/node_modules/toolcraft-design/dist/dashboard/should-use-dashboard.js +7 -0
  186. package/node_modules/toolcraft-design/dist/dashboard/snapshot.d.ts +10 -0
  187. package/node_modules/toolcraft-design/dist/dashboard/snapshot.js +68 -0
  188. package/node_modules/toolcraft-design/dist/dashboard/store.d.ts +8 -0
  189. package/node_modules/toolcraft-design/dist/dashboard/store.js +51 -0
  190. package/node_modules/toolcraft-design/dist/dashboard/terminal-width.d.ts +4 -0
  191. package/node_modules/toolcraft-design/dist/dashboard/terminal-width.js +71 -0
  192. package/node_modules/toolcraft-design/dist/dashboard/terminal.d.ts +37 -0
  193. package/node_modules/toolcraft-design/dist/dashboard/terminal.js +264 -0
  194. package/node_modules/toolcraft-design/dist/dashboard/types.d.ts +38 -0
  195. package/node_modules/toolcraft-design/dist/dashboard/types.js +1 -0
  196. package/node_modules/toolcraft-design/dist/explorer/actions.d.ts +16 -0
  197. package/node_modules/toolcraft-design/dist/explorer/actions.js +39 -0
  198. package/node_modules/toolcraft-design/dist/explorer/demo.d.ts +13 -0
  199. package/node_modules/toolcraft-design/dist/explorer/demo.js +297 -0
  200. package/node_modules/toolcraft-design/dist/explorer/events.d.ts +67 -0
  201. package/node_modules/toolcraft-design/dist/explorer/events.js +1 -0
  202. package/node_modules/toolcraft-design/dist/explorer/filter.d.ts +10 -0
  203. package/node_modules/toolcraft-design/dist/explorer/filter.js +95 -0
  204. package/node_modules/toolcraft-design/dist/explorer/index.d.ts +8 -0
  205. package/node_modules/toolcraft-design/dist/explorer/index.js +8 -0
  206. package/node_modules/toolcraft-design/dist/explorer/jobs.d.ts +7 -0
  207. package/node_modules/toolcraft-design/dist/explorer/jobs.js +59 -0
  208. package/node_modules/toolcraft-design/dist/explorer/keymap.d.ts +21 -0
  209. package/node_modules/toolcraft-design/dist/explorer/keymap.js +376 -0
  210. package/node_modules/toolcraft-design/dist/explorer/layout.d.ts +20 -0
  211. package/node_modules/toolcraft-design/dist/explorer/layout.js +73 -0
  212. package/node_modules/toolcraft-design/dist/explorer/reducer.d.ts +9 -0
  213. package/node_modules/toolcraft-design/dist/explorer/reducer.js +782 -0
  214. package/node_modules/toolcraft-design/dist/explorer/render/detail.d.ts +4 -0
  215. package/node_modules/toolcraft-design/dist/explorer/render/detail.js +97 -0
  216. package/node_modules/toolcraft-design/dist/explorer/render/footer.d.ts +4 -0
  217. package/node_modules/toolcraft-design/dist/explorer/render/footer.js +73 -0
  218. package/node_modules/toolcraft-design/dist/explorer/render/header.d.ts +4 -0
  219. package/node_modules/toolcraft-design/dist/explorer/render/header.js +49 -0
  220. package/node_modules/toolcraft-design/dist/explorer/render/index.d.ts +8 -0
  221. package/node_modules/toolcraft-design/dist/explorer/render/index.js +53 -0
  222. package/node_modules/toolcraft-design/dist/explorer/render/list.d.ts +4 -0
  223. package/node_modules/toolcraft-design/dist/explorer/render/list.js +116 -0
  224. package/node_modules/toolcraft-design/dist/explorer/render/modal.d.ts +3 -0
  225. package/node_modules/toolcraft-design/dist/explorer/render/modal.js +87 -0
  226. package/node_modules/toolcraft-design/dist/explorer/render/test-fixtures.d.ts +8 -0
  227. package/node_modules/toolcraft-design/dist/explorer/render/test-fixtures.js +156 -0
  228. package/node_modules/toolcraft-design/dist/explorer/render/text.d.ts +12 -0
  229. package/node_modules/toolcraft-design/dist/explorer/render/text.js +81 -0
  230. package/node_modules/toolcraft-design/dist/explorer/runtime.d.ts +2 -0
  231. package/node_modules/toolcraft-design/dist/explorer/runtime.js +340 -0
  232. package/node_modules/toolcraft-design/dist/explorer/runtime.test-helpers.d.ts +50 -0
  233. package/node_modules/toolcraft-design/dist/explorer/runtime.test-helpers.js +101 -0
  234. package/node_modules/toolcraft-design/dist/explorer/state.d.ts +137 -0
  235. package/node_modules/toolcraft-design/dist/explorer/state.js +86 -0
  236. package/node_modules/toolcraft-design/dist/explorer/theme.d.ts +27 -0
  237. package/node_modules/toolcraft-design/dist/explorer/theme.js +29 -0
  238. package/node_modules/toolcraft-design/dist/index.d.ts +50 -0
  239. package/node_modules/toolcraft-design/dist/index.js +43 -0
  240. package/node_modules/toolcraft-design/dist/internal/color-support.d.ts +9 -0
  241. package/node_modules/toolcraft-design/dist/internal/color-support.js +12 -0
  242. package/node_modules/toolcraft-design/dist/internal/output-format.d.ts +6 -0
  243. package/node_modules/toolcraft-design/dist/internal/output-format.js +22 -0
  244. package/node_modules/toolcraft-design/dist/internal/strip-ansi.d.ts +1 -0
  245. package/node_modules/toolcraft-design/dist/internal/strip-ansi.js +50 -0
  246. package/node_modules/toolcraft-design/dist/internal/theme-detect.d.ts +12 -0
  247. package/node_modules/toolcraft-design/dist/internal/theme-detect.js +71 -0
  248. package/node_modules/toolcraft-design/dist/internal/theme-state.d.ts +12 -0
  249. package/node_modules/toolcraft-design/dist/internal/theme-state.js +35 -0
  250. package/node_modules/toolcraft-design/dist/prompts/index.d.ts +91 -0
  251. package/node_modules/toolcraft-design/dist/prompts/index.js +137 -0
  252. package/node_modules/toolcraft-design/dist/prompts/interactive/cancel-symbol.d.ts +2 -0
  253. package/node_modules/toolcraft-design/dist/prompts/interactive/cancel-symbol.js +4 -0
  254. package/node_modules/toolcraft-design/dist/prompts/interactive/confirm.d.ts +9 -0
  255. package/node_modules/toolcraft-design/dist/prompts/interactive/confirm.js +47 -0
  256. package/node_modules/toolcraft-design/dist/prompts/interactive/core.d.ts +55 -0
  257. package/node_modules/toolcraft-design/dist/prompts/interactive/core.js +274 -0
  258. package/node_modules/toolcraft-design/dist/prompts/interactive/glyphs.d.ts +20 -0
  259. package/node_modules/toolcraft-design/dist/prompts/interactive/glyphs.js +53 -0
  260. package/node_modules/toolcraft-design/dist/prompts/interactive/index.d.ts +6 -0
  261. package/node_modules/toolcraft-design/dist/prompts/interactive/index.js +6 -0
  262. package/node_modules/toolcraft-design/dist/prompts/interactive/keys.d.ts +2 -0
  263. package/node_modules/toolcraft-design/dist/prompts/interactive/keys.js +28 -0
  264. package/node_modules/toolcraft-design/dist/prompts/interactive/multiselect.d.ts +13 -0
  265. package/node_modules/toolcraft-design/dist/prompts/interactive/multiselect.js +131 -0
  266. package/node_modules/toolcraft-design/dist/prompts/interactive/pagination.d.ts +10 -0
  267. package/node_modules/toolcraft-design/dist/prompts/interactive/pagination.js +52 -0
  268. package/node_modules/toolcraft-design/dist/prompts/interactive/password.d.ts +10 -0
  269. package/node_modules/toolcraft-design/dist/prompts/interactive/password.js +55 -0
  270. package/node_modules/toolcraft-design/dist/prompts/interactive/select.d.ts +18 -0
  271. package/node_modules/toolcraft-design/dist/prompts/interactive/select.js +89 -0
  272. package/node_modules/toolcraft-design/dist/prompts/interactive/test-helpers.d.ts +21 -0
  273. package/node_modules/toolcraft-design/dist/prompts/interactive/test-helpers.js +32 -0
  274. package/node_modules/toolcraft-design/dist/prompts/interactive/text.d.ts +12 -0
  275. package/node_modules/toolcraft-design/dist/prompts/interactive/text.js +60 -0
  276. package/node_modules/toolcraft-design/dist/prompts/interactive/wrap.d.ts +4 -0
  277. package/node_modules/toolcraft-design/dist/prompts/interactive/wrap.js +18 -0
  278. package/node_modules/toolcraft-design/dist/prompts/primitives/cancel.d.ts +2 -0
  279. package/node_modules/toolcraft-design/dist/prompts/primitives/cancel.js +9 -0
  280. package/node_modules/toolcraft-design/dist/prompts/primitives/intro.d.ts +1 -0
  281. package/node_modules/toolcraft-design/dist/prompts/primitives/intro.js +16 -0
  282. package/node_modules/toolcraft-design/dist/prompts/primitives/log.d.ts +18 -0
  283. package/node_modules/toolcraft-design/dist/prompts/primitives/log.js +104 -0
  284. package/node_modules/toolcraft-design/dist/prompts/primitives/note.d.ts +1 -0
  285. package/node_modules/toolcraft-design/dist/prompts/primitives/note.js +39 -0
  286. package/node_modules/toolcraft-design/dist/prompts/primitives/outro.d.ts +1 -0
  287. package/node_modules/toolcraft-design/dist/prompts/primitives/outro.js +16 -0
  288. package/node_modules/toolcraft-design/dist/prompts/primitives/spinner.d.ts +6 -0
  289. package/node_modules/toolcraft-design/dist/prompts/primitives/spinner.js +74 -0
  290. package/node_modules/toolcraft-design/dist/prompts/theme.d.ts +11 -0
  291. package/node_modules/toolcraft-design/dist/prompts/theme.js +15 -0
  292. package/node_modules/toolcraft-design/dist/static/index.d.ts +4 -0
  293. package/node_modules/toolcraft-design/dist/static/index.js +2 -0
  294. package/node_modules/toolcraft-design/dist/static/menu.d.ts +11 -0
  295. package/node_modules/toolcraft-design/dist/static/menu.js +42 -0
  296. package/node_modules/toolcraft-design/dist/static/spinner.d.ts +14 -0
  297. package/node_modules/toolcraft-design/dist/static/spinner.js +52 -0
  298. package/node_modules/toolcraft-design/dist/terminal-markdown/ast.d.ts +92 -0
  299. package/node_modules/toolcraft-design/dist/terminal-markdown/ast.js +1 -0
  300. package/node_modules/toolcraft-design/dist/terminal-markdown/demo-content.d.ts +2 -0
  301. package/node_modules/toolcraft-design/dist/terminal-markdown/demo-content.js +139 -0
  302. package/node_modules/toolcraft-design/dist/terminal-markdown/index.d.ts +6 -0
  303. package/node_modules/toolcraft-design/dist/terminal-markdown/index.js +8 -0
  304. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/block.d.ts +7 -0
  305. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/block.js +1495 -0
  306. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/frontmatter.d.ts +8 -0
  307. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/frontmatter.js +36 -0
  308. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/inline.d.ts +10 -0
  309. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/inline.js +1190 -0
  310. package/node_modules/toolcraft-design/dist/terminal-markdown/parser.d.ts +5 -0
  311. package/node_modules/toolcraft-design/dist/terminal-markdown/parser.js +42 -0
  312. package/node_modules/toolcraft-design/dist/terminal-markdown/renderer.d.ts +6 -0
  313. package/node_modules/toolcraft-design/dist/terminal-markdown/renderer.js +615 -0
  314. package/node_modules/toolcraft-design/dist/terminal-markdown/testing/theme-render-fixture.d.ts +1 -0
  315. package/node_modules/toolcraft-design/dist/terminal-markdown/testing/theme-render-fixture.js +27 -0
  316. package/node_modules/toolcraft-design/dist/tokens/brand.d.ts +5 -0
  317. package/node_modules/toolcraft-design/dist/tokens/brand.js +5 -0
  318. package/node_modules/toolcraft-design/dist/tokens/colors.d.ts +37 -0
  319. package/node_modules/toolcraft-design/dist/tokens/colors.js +85 -0
  320. package/node_modules/toolcraft-design/dist/tokens/index.d.ts +6 -0
  321. package/node_modules/toolcraft-design/dist/tokens/index.js +5 -0
  322. package/node_modules/toolcraft-design/dist/tokens/spacing.d.ts +6 -0
  323. package/node_modules/toolcraft-design/dist/tokens/spacing.js +6 -0
  324. package/node_modules/toolcraft-design/dist/tokens/typography.d.ts +7 -0
  325. package/node_modules/toolcraft-design/dist/tokens/typography.js +8 -0
  326. package/node_modules/toolcraft-design/dist/tokens/widths.d.ts +5 -0
  327. package/node_modules/toolcraft-design/dist/tokens/widths.js +5 -0
  328. package/node_modules/toolcraft-design/package.json +44 -0
  329. package/package.json +15 -5
@@ -79,12 +79,12 @@ function consumeTerminatedString(input, index, allowBellTerminator) {
79
79
 
80
80
  // src/cli.ts
81
81
  import { realpath as realpath3 } from "node:fs/promises";
82
- import path23 from "node:path";
82
+ import path24 from "node:path";
83
83
  import { fileURLToPath as fileURLToPath5 } from "node:url";
84
84
 
85
85
  // ../toolcraft/src/cli.ts
86
- import { access as access2, lstat as lstat3, readFile as readFile4, rename as rename3, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
87
- import path14 from "node:path";
86
+ import { access as access2, lstat as lstat3, readFile as readFile5, rename as rename3, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
87
+ import path15 from "node:path";
88
88
  import {
89
89
  Command as CommanderCommand,
90
90
  CommanderError as CommanderError2,
@@ -450,7 +450,8 @@ function renderMarkdownCode(content) {
450
450
  currentRun = 0;
451
451
  }
452
452
  const delimiter = "`".repeat(longestRun + 1);
453
- return `${delimiter}${value}${delimiter}`;
453
+ const paddedValue = value.startsWith("`") || value.endsWith("`") ? ` ${value} ` : value;
454
+ return `${delimiter}${paddedValue}${delimiter}`;
454
455
  }
455
456
  function renderMarkdownLink(content) {
456
457
  const value = renderMarkdownInline(content);
@@ -605,7 +606,54 @@ var symbols = {
605
606
 
606
607
  // ../toolcraft-design/src/internal/strip-ansi.ts
607
608
  function stripAnsi2(value) {
608
- return value.replace(/\u001b\[[0-9;]*m/g, "");
609
+ let output = "";
610
+ let index = 0;
611
+ while (index < value.length) {
612
+ const char = value[index];
613
+ if (char === "\x1B") {
614
+ index = skipEscapeSequence(value, index);
615
+ continue;
616
+ }
617
+ if (char === "\x9B") {
618
+ index = skipCsiSequence(value, index + 1);
619
+ continue;
620
+ }
621
+ output += char;
622
+ index += char.length;
623
+ }
624
+ return output;
625
+ }
626
+ function skipEscapeSequence(value, index) {
627
+ const next = value[index + 1];
628
+ if (next === "[") {
629
+ return skipCsiSequence(value, index + 2);
630
+ }
631
+ if (next === "]") {
632
+ return skipOscSequence(value, index + 2);
633
+ }
634
+ return Math.min(value.length, index + 2);
635
+ }
636
+ function skipCsiSequence(value, index) {
637
+ while (index < value.length) {
638
+ const codePoint = value.charCodeAt(index);
639
+ index += 1;
640
+ if (codePoint >= 64 && codePoint <= 126) {
641
+ break;
642
+ }
643
+ }
644
+ return index;
645
+ }
646
+ function skipOscSequence(value, index) {
647
+ while (index < value.length) {
648
+ if (value[index] === "\x07") {
649
+ return index + 1;
650
+ }
651
+ if (value[index] === "\x1B" && value[index + 1] === "\\") {
652
+ return index + 2;
653
+ }
654
+ index += 1;
655
+ }
656
+ return index;
609
657
  }
610
658
 
611
659
  // ../toolcraft-design/src/prompts/primitives/log.ts
@@ -1394,38 +1442,14 @@ function renderTable(options) {
1394
1442
  }
1395
1443
 
1396
1444
  // ../toolcraft-design/src/components/detail-card.ts
1445
+ import stringWidth from "fast-string-width";
1446
+ import { wrapAnsi } from "fast-wrap-ansi";
1397
1447
  function wrap(value, width) {
1398
- const lines = [];
1399
- for (const paragraph of value.split("\n")) {
1400
- let line = "";
1401
- for (const rawWord of paragraph.split(" ")) {
1402
- const words = [];
1403
- let word = rawWord;
1404
- while (word.length > width) {
1405
- words.push(word.slice(0, width));
1406
- word = word.slice(width);
1407
- }
1408
- words.push(word);
1409
- for (const word2 of words) {
1410
- if (line.length === 0) {
1411
- line = word2;
1412
- continue;
1413
- }
1414
- if (`${line} ${word2}`.length <= width) {
1415
- line = `${line} ${word2}`;
1416
- continue;
1417
- }
1418
- lines.push(line);
1419
- line = word2;
1420
- }
1421
- }
1422
- lines.push(line);
1423
- }
1424
- return lines;
1448
+ return wrapAnsi(value, Math.max(1, width), { hard: true, trim: true }).split("\n");
1425
1449
  }
1426
1450
  function renderRows(rows, theme, width) {
1427
1451
  if (rows.length === 0) return [];
1428
- const labelWidth = Math.max(...rows.map((row) => row.label.length));
1452
+ const labelWidth = Math.max(...rows.map((row) => stringWidth(row.label)));
1429
1453
  const valueWidth = Math.max(20, width - labelWidth - 2);
1430
1454
  const continuation = " ".repeat(labelWidth + 2);
1431
1455
  return rows.flatMap((row) => {
@@ -1446,12 +1470,16 @@ function renderDetailCard(options) {
1446
1470
  ${options.theme.muted(options.badges.map((badge) => badge[0] + badge.slice(1).toLowerCase()).join(" \xB7 "))}` : identity;
1447
1471
  const blocks = [hero];
1448
1472
  for (const prose of options.prose ?? []) {
1449
- blocks.push(prose.title ? [options.theme.header(prose.title), wrap(prose.value, width).join("\n")].join("\n") : wrap(prose.value, width).join("\n"));
1473
+ blocks.push(
1474
+ prose.title ? [options.theme.header(prose.title), wrap(prose.value, width).join("\n")].join("\n") : wrap(prose.value, width).join("\n")
1475
+ );
1450
1476
  }
1451
1477
  for (const section of options.sections ?? []) {
1452
1478
  if (section.rows.length === 0) continue;
1453
1479
  const rows = renderRows(section.rows, options.theme, width);
1454
- blocks.push(section.title ? [options.theme.header(section.title), ...rows].join("\n") : rows.join("\n"));
1480
+ blocks.push(
1481
+ section.title ? [options.theme.header(section.title), ...rows].join("\n") : rows.join("\n")
1482
+ );
1455
1483
  }
1456
1484
  return blocks.join("\n\n");
1457
1485
  }
@@ -1878,13 +1906,13 @@ import { LineCounter, parse, parseDocument } from "yaml";
1878
1906
  // ../frontmatter/src/stringify.ts
1879
1907
  import { stringify } from "yaml";
1880
1908
 
1909
+ // ../toolcraft-design/src/dashboard/terminal-width.ts
1910
+ var graphemeSegmenter3 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1911
+
1881
1912
  // ../toolcraft-design/src/acp/writer.ts
1882
1913
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1883
1914
  var storage = new AsyncLocalStorage2();
1884
1915
 
1885
- // ../toolcraft-design/src/dashboard/terminal-width.ts
1886
- var graphemeSegmenter3 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1887
-
1888
1916
  // ../toolcraft-design/src/dashboard/terminal.ts
1889
1917
  import readline from "node:readline";
1890
1918
  import { PassThrough } from "node:stream";
@@ -1981,8 +2009,8 @@ function mapKey(name, char) {
1981
2009
  }
1982
2010
 
1983
2011
  // ../toolcraft-design/src/prompts/interactive/wrap.ts
1984
- import { wrapAnsi } from "fast-wrap-ansi";
1985
- import stringWidth from "fast-string-width";
2012
+ import { wrapAnsi as wrapAnsi2 } from "fast-wrap-ansi";
2013
+ import stringWidth2 from "fast-string-width";
1986
2014
  function getColumns(output) {
1987
2015
  return Math.max(1, output.columns ?? 80);
1988
2016
  }
@@ -1990,7 +2018,7 @@ function getRows(output) {
1990
2018
  return Math.max(1, output.rows ?? 20);
1991
2019
  }
1992
2020
  function wrapFrame(output, frame) {
1993
- return wrapAnsi(frame, getColumns(output), { hard: true, trim: false });
2021
+ return wrapAnsi2(frame, getColumns(output), { hard: true, trim: false });
1994
2022
  }
1995
2023
 
1996
2024
  // ../toolcraft-design/src/prompts/interactive/core.ts
@@ -2311,7 +2339,7 @@ function confirmPrompt(opts) {
2311
2339
  }
2312
2340
 
2313
2341
  // ../toolcraft-design/src/prompts/interactive/pagination.ts
2314
- import { wrapAnsi as wrapAnsi2 } from "fast-wrap-ansi";
2342
+ import { wrapAnsi as wrapAnsi3 } from "fast-wrap-ansi";
2315
2343
  function countLines(values) {
2316
2344
  return values.reduce((sum, value) => sum + value.split("\n").length, 0);
2317
2345
  }
@@ -2354,7 +2382,7 @@ function limitOptions(opts) {
2354
2382
  }
2355
2383
  const hasTopMarker = cappedVisibleCount < options.length && start > 0;
2356
2384
  const hasBottomMarker = cappedVisibleCount < options.length && start + cappedVisibleCount < options.length;
2357
- const visible = options.slice(start, start + cappedVisibleCount).map((option, index) => wrapAnsi2(style(option, start + index === cursor2), columns, { hard: true, trim: false }));
2385
+ const visible = options.slice(start, start + cappedVisibleCount).map((option, index) => wrapAnsi3(style(option, start + index === cursor2), columns, { hard: true, trim: false }));
2358
2386
  const trimmed = trimToRows(
2359
2387
  visible,
2360
2388
  Math.max(cursor2 - start, 0),
@@ -2737,6 +2765,9 @@ function isOptionalSchema(schema) {
2737
2765
  function getRequiredKeys(schema) {
2738
2766
  return Object.keys(schema.shape).filter((key2) => !isOptionalSchema(schema.shape[key2])).sort();
2739
2767
  }
2768
+ function getRequiredKeyFingerprint(schema) {
2769
+ return getRequiredKeys(schema).join("+");
2770
+ }
2740
2771
  function assertUniqueRequiredKeyFingerprints(branches) {
2741
2772
  const fingerprints = /* @__PURE__ */ new Map();
2742
2773
  branches.forEach((branch, index) => {
@@ -2774,6 +2805,451 @@ function Union(branches) {
2774
2805
  };
2775
2806
  }
2776
2807
 
2808
+ // ../toolcraft-schema/src/validate.ts
2809
+ var missingValue = /* @__PURE__ */ Symbol("missingValue");
2810
+ function validate(schema, value) {
2811
+ const state = { issues: [] };
2812
+ const result = walkSchema(schema, value, [], state);
2813
+ if (state.issues.length > 0) {
2814
+ return { ok: false, issues: state.issues };
2815
+ }
2816
+ return { ok: true, value: result.present ? result.value : void 0 };
2817
+ }
2818
+ function walkSchema(schema, value, path25, state) {
2819
+ if (schema.kind === "optional") {
2820
+ return walkOptional(schema, value, path25, state);
2821
+ }
2822
+ if (value === missingValue) {
2823
+ addIssue(
2824
+ state,
2825
+ path25,
2826
+ expectedFor(schema),
2827
+ "missing",
2828
+ `Expected ${expectedFor(schema)} at ${formatPath(path25)}`
2829
+ );
2830
+ return { present: false };
2831
+ }
2832
+ if (value === null && schema.nullable === true) {
2833
+ return { present: true, value };
2834
+ }
2835
+ switch (schema.kind) {
2836
+ case "string":
2837
+ return walkString(schema, value, path25, state);
2838
+ case "number":
2839
+ return walkNumber(schema, value, path25, state);
2840
+ case "boolean":
2841
+ return walkBoolean(value, path25, state);
2842
+ case "enum":
2843
+ return walkEnum(schema, value, path25, state);
2844
+ case "array":
2845
+ return walkArray(schema, value, path25, state);
2846
+ case "object":
2847
+ return walkObject(schema, value, path25, state);
2848
+ case "oneOf":
2849
+ return walkOneOf(schema, value, path25, state);
2850
+ case "union":
2851
+ return walkUnion(schema, value, path25, state);
2852
+ case "record":
2853
+ return walkRecord(schema, value, path25, state);
2854
+ case "json":
2855
+ return walkJson(value, path25, state);
2856
+ }
2857
+ }
2858
+ function walkOptional(schema, value, path25, state) {
2859
+ if (value === missingValue || value === void 0) {
2860
+ const defaultValue = getDefault(schema.inner);
2861
+ if (defaultValue.present) {
2862
+ return walkSchema(schema.inner, cloneDefault(defaultValue.value), path25, state);
2863
+ }
2864
+ return { present: false };
2865
+ }
2866
+ return walkSchema(schema.inner, value, path25, state);
2867
+ }
2868
+ function walkString(schema, value, path25, state) {
2869
+ if (typeof value !== "string") {
2870
+ addExpectedIssue(state, path25, "string", value);
2871
+ return { present: true, value };
2872
+ }
2873
+ if (schema.minLength !== void 0 && value.length < schema.minLength) {
2874
+ const expected = `string with length at least ${schema.minLength}`;
2875
+ addIssue(
2876
+ state,
2877
+ path25,
2878
+ expected,
2879
+ `string with length ${value.length}`,
2880
+ `Expected ${expected} at ${formatPath(path25)}`
2881
+ );
2882
+ }
2883
+ if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
2884
+ const expected = `string with length at most ${schema.maxLength}`;
2885
+ addIssue(
2886
+ state,
2887
+ path25,
2888
+ expected,
2889
+ `string with length ${value.length}`,
2890
+ `Expected ${expected} at ${formatPath(path25)}`
2891
+ );
2892
+ }
2893
+ if (schema.pattern !== void 0) {
2894
+ const pattern = compilePattern(schema.pattern);
2895
+ if (pattern === void 0 || !pattern.test(value)) {
2896
+ const expected = `string matching pattern ${schema.pattern}`;
2897
+ addIssue(state, path25, expected, value, `Expected ${expected} at ${formatPath(path25)}`);
2898
+ }
2899
+ }
2900
+ return { present: true, value };
2901
+ }
2902
+ function walkNumber(schema, value, path25, state) {
2903
+ if (typeof value !== "number" || !Number.isFinite(value)) {
2904
+ addExpectedIssue(state, path25, schema.jsonType === "integer" ? "integer" : "number", value);
2905
+ return { present: true, value };
2906
+ }
2907
+ if (schema.jsonType === "integer" && !Number.isInteger(value)) {
2908
+ addExpectedIssue(state, path25, "integer", value);
2909
+ }
2910
+ if (schema.minimum !== void 0 && value < schema.minimum) {
2911
+ const expected = `number greater than or equal to ${schema.minimum}`;
2912
+ addIssue(state, path25, expected, String(value), `Expected ${expected} at ${formatPath(path25)}`);
2913
+ }
2914
+ if (schema.maximum !== void 0 && value > schema.maximum) {
2915
+ const expected = `number less than or equal to ${schema.maximum}`;
2916
+ addIssue(state, path25, expected, String(value), `Expected ${expected} at ${formatPath(path25)}`);
2917
+ }
2918
+ return { present: true, value };
2919
+ }
2920
+ function walkBoolean(value, path25, state) {
2921
+ if (typeof value !== "boolean") {
2922
+ addExpectedIssue(state, path25, "boolean", value);
2923
+ }
2924
+ return { present: true, value };
2925
+ }
2926
+ function walkEnum(schema, value, path25, state) {
2927
+ if (!schema.values.includes(value)) {
2928
+ const expected = `one of ${schema.values.join(", ")}`;
2929
+ addIssue(
2930
+ state,
2931
+ path25,
2932
+ expected,
2933
+ receivedValue(value),
2934
+ `Expected ${expected} at ${formatPath(path25)}`
2935
+ );
2936
+ }
2937
+ return { present: true, value };
2938
+ }
2939
+ function walkArray(schema, value, path25, state) {
2940
+ if (!Array.isArray(value)) {
2941
+ addExpectedIssue(state, path25, "array", value);
2942
+ return { present: true, value };
2943
+ }
2944
+ if (schema.minItems !== void 0 && value.length < schema.minItems) {
2945
+ const expected = `array with at least ${schema.minItems} items`;
2946
+ addIssue(
2947
+ state,
2948
+ path25,
2949
+ expected,
2950
+ `array with ${value.length} items`,
2951
+ `Expected ${expected} at ${formatPath(path25)}`
2952
+ );
2953
+ }
2954
+ if (schema.maxItems !== void 0 && value.length > schema.maxItems) {
2955
+ const expected = `array with at most ${schema.maxItems} items`;
2956
+ addIssue(
2957
+ state,
2958
+ path25,
2959
+ expected,
2960
+ `array with ${value.length} items`,
2961
+ `Expected ${expected} at ${formatPath(path25)}`
2962
+ );
2963
+ }
2964
+ const nextValue = value.map((item, index) => {
2965
+ const result = walkSchema(schema.item, item, [...path25, String(index)], state);
2966
+ return result.present ? result.value : item;
2967
+ });
2968
+ return { present: true, value: nextValue };
2969
+ }
2970
+ function walkObject(schema, value, path25, state, injectedProperties = {}) {
2971
+ if (!isPlainRecord(value)) {
2972
+ addExpectedIssue(state, path25, "object", value);
2973
+ return { present: true, value };
2974
+ }
2975
+ const nextValue = {};
2976
+ const allowedKeys = /* @__PURE__ */ new Set([...Object.keys(schema.shape), ...Object.keys(injectedProperties)]);
2977
+ for (const [key2, propertySchema] of Object.entries(schema.shape)) {
2978
+ const propertyValue = Object.hasOwn(value, key2) ? value[key2] : missingValue;
2979
+ const result = walkSchema(propertySchema, propertyValue, [...path25, key2], state);
2980
+ if (result.present) {
2981
+ setOwnValue(nextValue, key2, result.value);
2982
+ }
2983
+ }
2984
+ for (const [key2, injectedValue] of Object.entries(injectedProperties)) {
2985
+ if (Object.hasOwn(value, key2)) {
2986
+ setOwnValue(nextValue, key2, value[key2]);
2987
+ } else {
2988
+ setOwnValue(nextValue, key2, injectedValue);
2989
+ }
2990
+ }
2991
+ for (const [key2, propertyValue] of Object.entries(value)) {
2992
+ if (allowedKeys.has(key2)) {
2993
+ continue;
2994
+ }
2995
+ if (schema.additionalProperties === true) {
2996
+ setOwnValue(nextValue, key2, propertyValue);
2997
+ } else {
2998
+ addUnexpectedPropertyIssue(state, [...path25, key2]);
2999
+ }
3000
+ }
3001
+ return { present: true, value: nextValue };
3002
+ }
3003
+ function walkOneOf(schema, value, path25, state) {
3004
+ if (!isPlainRecord(value)) {
3005
+ addExpectedIssue(state, path25, "object", value);
3006
+ return { present: true, value };
3007
+ }
3008
+ const discriminatorValue = value[schema.discriminator];
3009
+ const discriminatorPath = [...path25, schema.discriminator];
3010
+ const branchValues = Object.keys(schema.branches);
3011
+ const expected = `one of ${branchValues.join(", ")}`;
3012
+ if (!Object.hasOwn(value, schema.discriminator)) {
3013
+ addIssueWithMessage(
3014
+ state,
3015
+ discriminatorPath,
3016
+ expected,
3017
+ "missing",
3018
+ `Missing discriminator "${schema.discriminator}" at ${formatPath(path25)}. Expected one of: ${branchValues.join(", ")}.`
3019
+ );
3020
+ return { present: true, value };
3021
+ }
3022
+ if (typeof discriminatorValue !== "string" || !Object.hasOwn(schema.branches, discriminatorValue)) {
3023
+ addIssueWithMessage(
3024
+ state,
3025
+ discriminatorPath,
3026
+ expected,
3027
+ receivedValue(discriminatorValue),
3028
+ `Expected ${expected} at ${formatPath(discriminatorPath)}, got ${formatReceivedDiscriminator(discriminatorValue)}`
3029
+ );
3030
+ return { present: true, value };
3031
+ }
3032
+ return walkObject(schema.branches[discriminatorValue], value, path25, state, {
3033
+ [schema.discriminator]: discriminatorValue
3034
+ });
3035
+ }
3036
+ function walkUnion(schema, value, path25, state) {
3037
+ if (isPlainRecord(value)) {
3038
+ const candidateBranches = schema.branches.filter((branch) => hasRequiredKeys(branch, value));
3039
+ if (candidateBranches.length === 1) {
3040
+ return walkObject(candidateBranches[0], value, path25, state);
3041
+ }
3042
+ }
3043
+ const matches = [];
3044
+ for (const branch of schema.branches) {
3045
+ const branchState = { issues: [] };
3046
+ const result = walkObject(branch, value, path25, branchState);
3047
+ if (branchState.issues.length === 0 && result.present) {
3048
+ matches.push({ fingerprint: getRequiredKeyFingerprint(branch), value: result.value });
3049
+ }
3050
+ }
3051
+ if (matches.length === 1) {
3052
+ return { present: true, value: matches[0].value };
3053
+ }
3054
+ if (matches.length === 0) {
3055
+ const branchDescriptions = schema.branches.map((branch) => getRequiredKeyFingerprint(branch));
3056
+ addIssueWithMessage(
3057
+ state,
3058
+ path25,
3059
+ "exactly one union branch",
3060
+ "0 matching branches",
3061
+ `No union branch matched at ${formatPath(path25)}. Tried ${schema.branches.length} branches. Expected one of: ${branchDescriptions.join(" | ")}.`
3062
+ );
3063
+ return { present: true, value };
3064
+ }
3065
+ addIssueWithMessage(
3066
+ state,
3067
+ path25,
3068
+ "exactly one union branch",
3069
+ `${matches.length} matching branches`,
3070
+ `Expected exactly one union branch at ${formatPath(path25)}, but matched more than one branch: ${matches.map((match) => match.fingerprint).join(" | ")}`
3071
+ );
3072
+ return { present: true, value };
3073
+ }
3074
+ function hasRequiredKeys(schema, value) {
3075
+ for (const [key2, propertySchema] of Object.entries(schema.shape)) {
3076
+ if (propertySchema.kind !== "optional" && !Object.hasOwn(value, key2)) {
3077
+ return false;
3078
+ }
3079
+ }
3080
+ return true;
3081
+ }
3082
+ function walkRecord(schema, value, path25, state) {
3083
+ if (!isPlainRecord(value)) {
3084
+ addExpectedIssue(state, path25, "object", value);
3085
+ return { present: true, value };
3086
+ }
3087
+ const nextValue = {};
3088
+ for (const [key2, propertyValue] of Object.entries(value)) {
3089
+ const result = walkSchema(schema.value, propertyValue, [...path25, key2], state);
3090
+ if (result.present) {
3091
+ setOwnValue(nextValue, key2, result.value);
3092
+ }
3093
+ }
3094
+ return { present: true, value: nextValue };
3095
+ }
3096
+ function walkJson(value, path25, state) {
3097
+ if (isJsonValue(value)) {
3098
+ return { present: true, value };
3099
+ }
3100
+ addExpectedIssue(state, path25, "JSON value", value);
3101
+ return { present: true, value };
3102
+ }
3103
+ function getDefault(schema) {
3104
+ if (schema.default !== void 0) {
3105
+ return { present: true, value: schema.default };
3106
+ }
3107
+ if (schema.kind === "optional") {
3108
+ return getDefault(schema.inner);
3109
+ }
3110
+ return { present: false };
3111
+ }
3112
+ function isPlainRecord(value) {
3113
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
3114
+ return false;
3115
+ }
3116
+ const prototype = Object.getPrototypeOf(value);
3117
+ return prototype === Object.prototype || prototype === null;
3118
+ }
3119
+ function isJsonValue(value, ancestors = /* @__PURE__ */ new Set()) {
3120
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3121
+ return typeof value !== "number" || Number.isFinite(value);
3122
+ }
3123
+ if (Array.isArray(value)) {
3124
+ if (ancestors.has(value)) {
3125
+ return false;
3126
+ }
3127
+ ancestors.add(value);
3128
+ const result = value.every((item) => isJsonValue(item, ancestors));
3129
+ ancestors.delete(value);
3130
+ return result;
3131
+ }
3132
+ if (isPlainRecord(value)) {
3133
+ if (ancestors.has(value)) {
3134
+ return false;
3135
+ }
3136
+ ancestors.add(value);
3137
+ const result = Object.values(value).every((item) => isJsonValue(item, ancestors));
3138
+ ancestors.delete(value);
3139
+ return result;
3140
+ }
3141
+ return false;
3142
+ }
3143
+ function cloneDefault(value) {
3144
+ return structuredClone(value);
3145
+ }
3146
+ function setOwnValue(target, key2, value) {
3147
+ Object.defineProperty(target, key2, {
3148
+ configurable: true,
3149
+ enumerable: true,
3150
+ writable: true,
3151
+ value
3152
+ });
3153
+ }
3154
+ function expectedFor(schema) {
3155
+ switch (schema.kind) {
3156
+ case "string":
3157
+ return "string";
3158
+ case "number":
3159
+ return schema.jsonType === "integer" ? "integer" : "number";
3160
+ case "boolean":
3161
+ return "boolean";
3162
+ case "enum":
3163
+ return `one of ${schema.values.join(", ")}`;
3164
+ case "array":
3165
+ return "array";
3166
+ case "object":
3167
+ case "oneOf":
3168
+ case "record":
3169
+ return "object";
3170
+ case "union":
3171
+ return "exactly one union branch";
3172
+ case "json":
3173
+ return "JSON value";
3174
+ case "optional":
3175
+ return expectedFor(schema.inner);
3176
+ }
3177
+ }
3178
+ function addExpectedIssue(state, path25, expected, value) {
3179
+ addIssue(
3180
+ state,
3181
+ path25,
3182
+ expected,
3183
+ receivedType(value),
3184
+ `Expected ${expected} at ${formatPath(path25)}`
3185
+ );
3186
+ }
3187
+ function addUnexpectedPropertyIssue(state, path25) {
3188
+ addIssue(
3189
+ state,
3190
+ path25,
3191
+ "no additional properties",
3192
+ "unknown property",
3193
+ `Unexpected property ${formatPath(path25)}`
3194
+ );
3195
+ }
3196
+ function addIssue(state, path25, expected, received, _message) {
3197
+ state.issues.push({
3198
+ path: path25,
3199
+ expected,
3200
+ received,
3201
+ message: formatIssueMessage(expected, path25, received)
3202
+ });
3203
+ }
3204
+ function addIssueWithMessage(state, path25, expected, received, message2) {
3205
+ state.issues.push({
3206
+ path: path25,
3207
+ expected,
3208
+ received,
3209
+ message: message2
3210
+ });
3211
+ }
3212
+ function formatIssueMessage(expected, path25, received) {
3213
+ return `Expected ${expected} at ${formatPath(path25)}, got ${received}`;
3214
+ }
3215
+ function formatPath(path25) {
3216
+ return path25.length === 0 ? "value" : path25.join(".");
3217
+ }
3218
+ function compilePattern(pattern) {
3219
+ try {
3220
+ return new RegExp(pattern);
3221
+ } catch {
3222
+ return void 0;
3223
+ }
3224
+ }
3225
+ function receivedType(value) {
3226
+ if (value === null) {
3227
+ return "null";
3228
+ }
3229
+ if (Array.isArray(value)) {
3230
+ return "array";
3231
+ }
3232
+ if (typeof value === "number" && Number.isInteger(value)) {
3233
+ return "integer";
3234
+ }
3235
+ return typeof value;
3236
+ }
3237
+ function receivedValue(value) {
3238
+ if (typeof value === "string") {
3239
+ return value;
3240
+ }
3241
+ if (value === void 0) {
3242
+ return "undefined";
3243
+ }
3244
+ return String(value);
3245
+ }
3246
+ function formatReceivedDiscriminator(value) {
3247
+ if (typeof value === "string") {
3248
+ return JSON.stringify(value);
3249
+ }
3250
+ return receivedValue(value);
3251
+ }
3252
+
2777
3253
  // ../toolcraft-schema/src/index.ts
2778
3254
  function assertValidEnumValues(values) {
2779
3255
  if (values.length === 0) {
@@ -2797,6 +3273,22 @@ function assertFiniteNumber(value, name) {
2797
3273
  throw new Error(`${name} must be finite`);
2798
3274
  }
2799
3275
  }
3276
+ function assertMinMaxOrder(minimum, maximum, minimumName, maximumName) {
3277
+ if (minimum !== void 0 && maximum !== void 0 && minimum > maximum) {
3278
+ throw new Error(`${minimumName} must be less than or equal to ${maximumName}`);
3279
+ }
3280
+ }
3281
+ function assertValidDefault(schema) {
3282
+ if (schema.default === void 0) {
3283
+ return;
3284
+ }
3285
+ const result = validate(schema, schema.default);
3286
+ if (!result.ok) {
3287
+ throw new Error(
3288
+ `default must satisfy schema: ${result.issues[0]?.message ?? "invalid default"}`
3289
+ );
3290
+ }
3291
+ }
2800
3292
  function assertPattern(pattern) {
2801
3293
  if (pattern === void 0) {
2802
3294
  return;
@@ -2811,56 +3303,71 @@ var S = {
2811
3303
  String(options = {}) {
2812
3304
  assertNonNegativeInteger(options.minLength, "minLength");
2813
3305
  assertNonNegativeInteger(options.maxLength, "maxLength");
3306
+ assertMinMaxOrder(options.minLength, options.maxLength, "minLength", "maxLength");
2814
3307
  assertPattern(options.pattern);
2815
- return {
3308
+ const schema = {
2816
3309
  kind: "string",
2817
3310
  ...options
2818
3311
  };
3312
+ assertValidDefault(schema);
3313
+ return schema;
2819
3314
  },
2820
3315
  Number(options = {}) {
2821
3316
  assertFiniteNumber(options.minimum, "minimum");
2822
3317
  assertFiniteNumber(options.maximum, "maximum");
3318
+ assertMinMaxOrder(options.minimum, options.maximum, "minimum", "maximum");
2823
3319
  assertFiniteNumber(options.default, "default");
2824
3320
  if (options.jsonType === "integer" && options.default !== void 0 && !Number.isInteger(options.default)) {
2825
3321
  throw new Error("default must be an integer");
2826
3322
  }
2827
- return {
3323
+ const schema = {
2828
3324
  kind: "number",
2829
3325
  ...options
2830
3326
  };
3327
+ assertValidDefault(schema);
3328
+ return schema;
2831
3329
  },
2832
3330
  Boolean(options = {}) {
2833
- return {
3331
+ const schema = {
2834
3332
  kind: "boolean",
2835
3333
  ...options
2836
3334
  };
3335
+ assertValidDefault(schema);
3336
+ return schema;
2837
3337
  },
2838
3338
  Enum(values, options = {}) {
2839
3339
  assertValidEnumValues(values);
2840
3340
  if (options.jsonType === "integer" && values.some((value) => typeof value !== "number" || !Number.isInteger(value))) {
2841
3341
  throw new Error("Integer enum values must be integers");
2842
3342
  }
2843
- return {
3343
+ const schema = {
2844
3344
  kind: "enum",
2845
3345
  values,
2846
3346
  ...options
2847
3347
  };
3348
+ assertValidDefault(schema);
3349
+ return schema;
2848
3350
  },
2849
3351
  Array(item, options = {}) {
2850
3352
  assertNonNegativeInteger(options.minItems, "minItems");
2851
3353
  assertNonNegativeInteger(options.maxItems, "maxItems");
2852
- return {
3354
+ assertMinMaxOrder(options.minItems, options.maxItems, "minItems", "maxItems");
3355
+ const schema = {
2853
3356
  kind: "array",
2854
3357
  item,
2855
3358
  ...options
2856
3359
  };
3360
+ assertValidDefault(schema);
3361
+ return schema;
2857
3362
  },
2858
3363
  Object(shape, options = {}) {
2859
- return {
3364
+ const schema = {
2860
3365
  kind: "object",
2861
3366
  shape,
2862
3367
  ...options
2863
3368
  };
3369
+ assertValidDefault(schema);
3370
+ return schema;
2864
3371
  },
2865
3372
  Optional(inner) {
2866
3373
  return {
@@ -3235,6 +3742,7 @@ function createBaseCommand(config2) {
3235
3742
  kind: "command",
3236
3743
  name: config2.name,
3237
3744
  description: config2.description,
3745
+ hidden: config2.hidden ?? false,
3238
3746
  examples: cloneCommandExamples(config2.examples),
3239
3747
  aliases: [...config2.aliases ?? []],
3240
3748
  positional: [...config2.positional ?? []],
@@ -3251,6 +3759,7 @@ function createBaseCommand(config2) {
3251
3759
  Object.defineProperty(command, commandConfigSymbol, {
3252
3760
  value: {
3253
3761
  scope: cloneScope(config2.scope),
3762
+ hidden: config2.hidden ?? false,
3254
3763
  examples: cloneCommandExamples(config2.examples),
3255
3764
  result: config2.result,
3256
3765
  humanInLoop: config2.humanInLoop,
@@ -3301,6 +3810,7 @@ function materializeCommand(command, inherited) {
3301
3810
  kind: "command",
3302
3811
  name: command.name,
3303
3812
  description: command.description,
3813
+ hidden: internal.hidden,
3304
3814
  examples: cloneCommandExamples(internal.examples),
3305
3815
  aliases: [...command.aliases],
3306
3816
  positional: [...command.positional],
@@ -3317,6 +3827,7 @@ function materializeCommand(command, inherited) {
3317
3827
  Object.defineProperty(materialized, commandConfigSymbol, {
3318
3828
  value: {
3319
3829
  scope: cloneScope(internal.scope),
3830
+ hidden: internal.hidden,
3320
3831
  examples: cloneCommandExamples(internal.examples),
3321
3832
  result: internal.result,
3322
3833
  humanInLoop: internal.humanInLoop,
@@ -3432,6 +3943,9 @@ function isRecord(value) {
3432
3943
  function isStateList(value) {
3433
3944
  return Array.isArray(value) && value.every((entry) => typeof entry === "string");
3434
3945
  }
3946
+ function hasVisibleName(value) {
3947
+ return value.trim().length > 0;
3948
+ }
3435
3949
  function canFireFromState(event, fromState) {
3436
3950
  if (event.from === "*") {
3437
3951
  return event.to !== fromState;
@@ -3446,6 +3960,9 @@ function validateMachine(machine) {
3446
3960
  throw new TypeError("State machine states must be a string array.");
3447
3961
  }
3448
3962
  const states = new Set(machine.states);
3963
+ if (machine.states.some((state) => !hasVisibleName(state))) {
3964
+ throw new Error("State names must not be empty.");
3965
+ }
3449
3966
  if (!hasOwnRecordField(machine, "initial") || typeof machine.initial !== "string") {
3450
3967
  throw new TypeError("State machine initial must be a string.");
3451
3968
  }
@@ -3456,6 +3973,9 @@ function validateMachine(machine) {
3456
3973
  throw new TypeError("State machine events must be an object.");
3457
3974
  }
3458
3975
  for (const [eventName, event] of Object.entries(machine.events)) {
3976
+ if (!hasVisibleName(eventName)) {
3977
+ throw new Error("Event names must not be empty.");
3978
+ }
3459
3979
  if (!isRecord(event)) {
3460
3980
  throw new TypeError(`Event "${eventName}" must be an object.`);
3461
3981
  }
@@ -3565,6 +4085,13 @@ import { text as text3 } from "node:stream/consumers";
3565
4085
  // ../process-runner/src/docker/context.ts
3566
4086
  import { execSync } from "node:child_process";
3567
4087
 
4088
+ // ../process-runner/src/docker/build-context.ts
4089
+ import { readdir, readFile } from "node:fs/promises";
4090
+ import { createRequire } from "node:module";
4091
+ import path2 from "node:path";
4092
+ var require2 = createRequire(import.meta.url);
4093
+ var createIgnore = require2("ignore");
4094
+
3568
4095
  // ../process-runner/src/docker/engine.ts
3569
4096
  import { execSync as execSync2 } from "node:child_process";
3570
4097
 
@@ -3573,19 +4100,19 @@ import * as childProcess from "node:child_process";
3573
4100
  import { randomBytes } from "node:crypto";
3574
4101
 
3575
4102
  // ../process-runner/src/docker/args.ts
3576
- import path2 from "node:path";
4103
+ import path3 from "node:path";
3577
4104
 
3578
4105
  // ../process-runner/src/docker/env-file.ts
3579
4106
  import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3580
4107
  import { tmpdir } from "node:os";
3581
- import path3 from "node:path";
4108
+ import path4 from "node:path";
3582
4109
 
3583
4110
  // ../process-runner/src/docker/docker-execution-env.ts
3584
4111
  import { createHash as createHash2, randomBytes as randomBytes2 } from "node:crypto";
3585
4112
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
3586
- import { readdir, readFile, realpath, writeFile } from "node:fs/promises";
4113
+ import { readFile as readFile2, realpath, writeFile } from "node:fs/promises";
3587
4114
  import { tmpdir as tmpdir2 } from "node:os";
3588
- import path5 from "node:path";
4115
+ import path6 from "node:path";
3589
4116
 
3590
4117
  // ../process-runner/src/host/host-runner.ts
3591
4118
  import { spawn as spawnChildProcess } from "node:child_process";
@@ -3718,7 +4245,7 @@ function bindAbortSignal(signal, onAbort) {
3718
4245
  // ../process-runner/src/workspace-transfer.ts
3719
4246
  import { createHash, randomUUID } from "node:crypto";
3720
4247
  import { promises as nodeFs } from "node:fs";
3721
- import path4 from "node:path";
4248
+ import path5 from "node:path";
3722
4249
 
3723
4250
  // ../process-runner/src/testing/mock-runner.ts
3724
4251
  import { Readable, Writable } from "node:stream";
@@ -3790,7 +4317,7 @@ function resolveEndpoint(options = {}) {
3790
4317
 
3791
4318
  // ../task-list/src/backends/utils.ts
3792
4319
  import { randomUUID as randomUUID2 } from "node:crypto";
3793
- import path6 from "node:path";
4320
+ import path7 from "node:path";
3794
4321
  function compareCreated(left, right) {
3795
4322
  const leftCreated = typeof left.raw.created === "string" ? left.raw.created : "";
3796
4323
  const rightCreated = typeof right.raw.created === "string" ? right.raw.created : "";
@@ -3822,15 +4349,33 @@ function sortStrings(values) {
3822
4349
  function sortTasks(tasks) {
3823
4350
  return [...tasks].sort((left, right) => left.qualifiedId.localeCompare(right.qualifiedId));
3824
4351
  }
4352
+ function isTrimmedPrintableIdentifier(value) {
4353
+ if (value.length === 0 || value !== value.trim()) {
4354
+ return false;
4355
+ }
4356
+ for (let index = 0; index < value.length; index += 1) {
4357
+ const code = value.charCodeAt(index);
4358
+ if (code < 32 || code === 127) {
4359
+ return false;
4360
+ }
4361
+ }
4362
+ return true;
4363
+ }
3825
4364
  function validateTaskId(id) {
3826
- if (id.length === 0 || id.startsWith(".") || id.includes("/") || id.includes("\\") || id.includes("..")) {
4365
+ if (!isTrimmedPrintableIdentifier(id) || id.startsWith(".") || id.includes("/") || id.includes("\\") || id.includes("..")) {
3827
4366
  throw new Error(`Invalid task id "${id}".`);
3828
4367
  }
3829
4368
  return id;
3830
4369
  }
3831
- async function statIfExists(fs4, filePath) {
4370
+ function validateTaskName(name) {
4371
+ if (name.trim().length === 0) {
4372
+ throw new Error("Task name must not be empty.");
4373
+ }
4374
+ return name;
4375
+ }
4376
+ async function statIfExists(fs5, filePath) {
3832
4377
  try {
3833
- return await fs4.stat(filePath);
4378
+ return await fs5.stat(filePath);
3834
4379
  } catch (error3) {
3835
4380
  if (hasErrorCode(error3, "ENOENT")) {
3836
4381
  return void 0;
@@ -3838,15 +4383,18 @@ async function statIfExists(fs4, filePath) {
3838
4383
  throw error3;
3839
4384
  }
3840
4385
  }
3841
- async function rejectSymbolicLinkComponents(fs4, filePath) {
3842
- const resolvedPath = path6.resolve(filePath);
3843
- const rootPath = path6.parse(resolvedPath).root;
3844
- const components = resolvedPath.slice(rootPath.length).split(path6.sep).filter(Boolean);
4386
+ async function rejectSymbolicLinkComponents(fs5, filePath) {
4387
+ const resolvedPath = path7.resolve(filePath);
4388
+ const rootPath = path7.parse(resolvedPath).root;
4389
+ const components = resolvedPath.slice(rootPath.length).split(path7.sep).filter(Boolean);
3845
4390
  let currentPath = rootPath;
3846
4391
  for (const component of components) {
3847
- currentPath = path6.join(currentPath, component);
4392
+ currentPath = path7.join(currentPath, component);
3848
4393
  try {
3849
- if ((await fs4.lstat(currentPath)).isSymbolicLink()) {
4394
+ if ((await fs5.lstat(currentPath)).isSymbolicLink()) {
4395
+ if (currentPath === "/tmp") {
4396
+ continue;
4397
+ }
3850
4398
  throw new Error(`Path "${filePath}" contains a symbolic link.`);
3851
4399
  }
3852
4400
  } catch (error3) {
@@ -3857,19 +4405,19 @@ async function rejectSymbolicLinkComponents(fs4, filePath) {
3857
4405
  }
3858
4406
  }
3859
4407
  }
3860
- async function writeAtomically(fs4, filePath, content) {
4408
+ async function writeAtomically(fs5, filePath, content) {
3861
4409
  const tempPath = `${filePath}.${process.pid}.${randomUUID2()}.tmp`;
3862
4410
  let tempCreated = false;
3863
- await fs4.mkdir(path6.dirname(filePath), { recursive: true });
4411
+ await fs5.mkdir(path7.dirname(filePath), { recursive: true });
3864
4412
  try {
3865
- await fs4.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
4413
+ await fs5.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
3866
4414
  tempCreated = true;
3867
- await fs4.rename(tempPath, filePath);
4415
+ await fs5.rename(tempPath, filePath);
3868
4416
  tempCreated = false;
3869
4417
  } catch (error3) {
3870
4418
  if (tempCreated || !hasErrorCode(error3, "EEXIST")) {
3871
4419
  try {
3872
- await fs4.unlink(tempPath);
4420
+ await fs5.unlink(tempPath);
3873
4421
  } catch (unlinkError) {
3874
4422
  if (!hasErrorCode(unlinkError, "ENOENT")) {
3875
4423
  throw unlinkError;
@@ -3879,18 +4427,18 @@ async function writeAtomically(fs4, filePath, content) {
3879
4427
  throw error3;
3880
4428
  }
3881
4429
  }
3882
- async function withFileLock(fs4, lockPath, operation) {
3883
- await fs4.mkdir(path6.dirname(lockPath), { recursive: true });
4430
+ async function withFileLock(fs5, lockPath, operation) {
4431
+ await fs5.mkdir(path7.dirname(lockPath), { recursive: true });
3884
4432
  for (; ; ) {
3885
4433
  try {
3886
- await fs4.writeFile(lockPath, String(process.pid), { encoding: "utf8", flag: "wx" });
4434
+ await fs5.writeFile(lockPath, String(process.pid), { encoding: "utf8", flag: "wx" });
3887
4435
  break;
3888
4436
  } catch (error3) {
3889
4437
  if (!hasErrorCode(error3, "EEXIST")) {
3890
- await fs4.unlink(lockPath).catch(() => void 0);
4438
+ await fs5.unlink(lockPath).catch(() => void 0);
3891
4439
  throw error3;
3892
4440
  }
3893
- if (await removeAbandonedLock(fs4, lockPath)) {
4441
+ if (await removeAbandonedLock(fs5, lockPath)) {
3894
4442
  continue;
3895
4443
  }
3896
4444
  await Promise.resolve();
@@ -3899,13 +4447,13 @@ async function withFileLock(fs4, lockPath, operation) {
3899
4447
  try {
3900
4448
  return await operation();
3901
4449
  } finally {
3902
- await fs4.unlink(lockPath);
4450
+ await fs5.unlink(lockPath);
3903
4451
  }
3904
4452
  }
3905
- async function removeAbandonedLock(fs4, lockPath) {
4453
+ async function removeAbandonedLock(fs5, lockPath) {
3906
4454
  let content;
3907
4455
  try {
3908
- content = await fs4.readFile(lockPath, "utf8");
4456
+ content = await fs5.readFile(lockPath, "utf8");
3909
4457
  } catch (error3) {
3910
4458
  if (hasErrorCode(error3, "ENOENT")) {
3911
4459
  return true;
@@ -3913,11 +4461,11 @@ async function removeAbandonedLock(fs4, lockPath) {
3913
4461
  throw error3;
3914
4462
  }
3915
4463
  const owner = Number(content);
3916
- if (!Number.isInteger(owner) || owner <= 0 || isProcessRunning(owner)) {
4464
+ if (Number.isInteger(owner) && owner > 0 && isProcessRunning(owner)) {
3917
4465
  return false;
3918
4466
  }
3919
4467
  try {
3920
- await fs4.unlink(lockPath);
4468
+ await fs5.unlink(lockPath);
3921
4469
  return true;
3922
4470
  } catch (error3) {
3923
4471
  if (hasErrorCode(error3, "ENOENT")) {
@@ -4185,6 +4733,9 @@ async function ghIssuesBackend(deps) {
4185
4733
  if (deps.state?.labelPrefix === "") {
4186
4734
  throw new Error("gh-issues state.labelPrefix must be a non-empty string when configured.");
4187
4735
  }
4736
+ if (deps.stateMachine !== void 0) {
4737
+ validateMachine(deps.stateMachine);
4738
+ }
4188
4739
  const client = createGhClient({
4189
4740
  token: deps.token,
4190
4741
  endpoint: deps.endpoint,
@@ -4344,7 +4895,9 @@ function createTasksView(name, session, context) {
4344
4895
  );
4345
4896
  projectItemId = added.addProjectV2ItemById?.item?.id ?? void 0;
4346
4897
  if (projectItemId === void 0) {
4347
- throw new Error("GitHub addProjectV2ItemById response did not include project item id.");
4898
+ throw new Error(
4899
+ "GitHub addProjectV2ItemById response did not include project item id."
4900
+ );
4348
4901
  }
4349
4902
  }
4350
4903
  if (session.labelPrefix === void 0) {
@@ -4573,12 +5126,15 @@ async function resolveProjectItemId(id, listName, session, context) {
4573
5126
  const issueNumber = parseIssueNumber(id, listName);
4574
5127
  let after;
4575
5128
  while (true) {
4576
- const result = await context.client.graphql(ISSUE_STATE_LABELS_QUERY, {
4577
- owner: context.repoOwner,
4578
- repo: context.repoName,
4579
- number: issueNumber,
4580
- after
4581
- });
5129
+ const result = await context.client.graphql(
5130
+ ISSUE_STATE_LABELS_QUERY,
5131
+ {
5132
+ owner: context.repoOwner,
5133
+ repo: context.repoName,
5134
+ number: issueNumber,
5135
+ after
5136
+ }
5137
+ );
4582
5138
  const issue = result.repository?.issue ?? null;
4583
5139
  if (issue === null) {
4584
5140
  throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
@@ -4855,12 +5411,27 @@ async function fetchIssueTask(id, listName, session, context) {
4855
5411
  });
4856
5412
  }
4857
5413
  function parseIssueNumber(id, listName) {
5414
+ if (!isCanonicalDecimalIssueId(id)) {
5415
+ throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
5416
+ }
4858
5417
  const issueNumber = Number(id);
4859
- if (!Number.isInteger(issueNumber) || issueNumber < 1) {
5418
+ if (!Number.isSafeInteger(issueNumber) || issueNumber < 1) {
4860
5419
  throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
4861
5420
  }
4862
5421
  return issueNumber;
4863
5422
  }
5423
+ function isCanonicalDecimalIssueId(id) {
5424
+ if (id.length === 0 || id[0] === "0") {
5425
+ return false;
5426
+ }
5427
+ for (let index = 0; index < id.length; index += 1) {
5428
+ const charCode = id.charCodeAt(index);
5429
+ if (charCode < 48 || charCode > 57) {
5430
+ return false;
5431
+ }
5432
+ }
5433
+ return true;
5434
+ }
4864
5435
  function mapProjectItemToTask(item, listName, session) {
4865
5436
  const content = item.content;
4866
5437
  if (!isIssueNode(content)) {
@@ -4968,7 +5539,7 @@ function parseQualifiedId(qualifiedId, listName) {
4968
5539
  }
4969
5540
 
4970
5541
  // ../task-list/src/backends/markdown-dir.ts
4971
- import path7 from "node:path";
5542
+ import path8 from "node:path";
4972
5543
  import { parseDocument as parseDocument2, stringify as stringify2 } from "yaml";
4973
5544
 
4974
5545
  // ../task-list/src/schema/task.schema.json
@@ -5071,7 +5642,7 @@ function resolveListLayout(deps) {
5071
5642
  return deps.singleList ? { kind: "single", name: deps.singleList } : { kind: "multi" };
5072
5643
  }
5073
5644
  function validateListName(name) {
5074
- if (name.length === 0 || name === ARCHIVE_DIRECTORY_NAME || name.startsWith(".") || name.includes("/") || name.includes("\\") || name.includes("..")) {
5645
+ if (!isTrimmedPrintableIdentifier(name) || name === ARCHIVE_DIRECTORY_NAME || name.startsWith(".") || name.includes("/") || name.includes("\\") || name.includes("..")) {
5075
5646
  throw new Error(`Invalid task list name "${name}".`);
5076
5647
  }
5077
5648
  return name;
@@ -5087,16 +5658,16 @@ function parseQualifiedId2(qualifiedId) {
5087
5658
  };
5088
5659
  }
5089
5660
  function listPath(rootPath, layout, list) {
5090
- return layout.kind === "single" ? rootPath : path7.join(rootPath, list);
5661
+ return layout.kind === "single" ? rootPath : path8.join(rootPath, list);
5091
5662
  }
5092
5663
  function archiveDirectoryPath(rootPath, layout, list) {
5093
- return layout.kind === "single" ? path7.join(rootPath, ARCHIVE_DIRECTORY_NAME) : path7.join(rootPath, list, ARCHIVE_DIRECTORY_NAME);
5664
+ return layout.kind === "single" ? path8.join(rootPath, ARCHIVE_DIRECTORY_NAME) : path8.join(rootPath, list, ARCHIVE_DIRECTORY_NAME);
5094
5665
  }
5095
5666
  function activeTaskFilename(id, order, width) {
5096
5667
  return `${String(order).padStart(width, "0")}-${id}${MARKDOWN_EXTENSION}`;
5097
5668
  }
5098
5669
  function archivedTaskPath(rootPath, layout, list, id) {
5099
- return path7.join(archiveDirectoryPath(rootPath, layout, list), `${id}${MARKDOWN_EXTENSION}`);
5670
+ return path8.join(archiveDirectoryPath(rootPath, layout, list), `${id}${MARKDOWN_EXTENSION}`);
5100
5671
  }
5101
5672
  function isMarkdownFile(entryName) {
5102
5673
  return entryName.endsWith(MARKDOWN_EXTENSION);
@@ -5198,7 +5769,7 @@ function hasOwnTaskField(frontmatter, key2) {
5198
5769
  function reservedFrontmatterKeys(mode) {
5199
5770
  return mode === "passthrough" ? PASSTHROUGH_RESERVED_FRONTMATTER_KEYS : RESERVED_FRONTMATTER_KEYS;
5200
5771
  }
5201
- function setOwnValue(record, key2, value) {
5772
+ function setOwnValue2(record, key2, value) {
5202
5773
  Object.defineProperty(record, key2, {
5203
5774
  value,
5204
5775
  enumerable: true,
@@ -5211,7 +5782,7 @@ function metadataFromFrontmatter(frontmatter, mode) {
5211
5782
  const reservedKeys = reservedFrontmatterKeys(mode);
5212
5783
  for (const [key2, value] of Object.entries(frontmatter)) {
5213
5784
  if (!reservedKeys.has(key2)) {
5214
- setOwnValue(metadata, key2, value);
5785
+ setOwnValue2(metadata, key2, value);
5215
5786
  }
5216
5787
  }
5217
5788
  return metadata;
@@ -5225,7 +5796,7 @@ function createTask(list, id, frontmatter, body, mode, sourcePath) {
5225
5796
  state: frontmatter.state,
5226
5797
  description: body,
5227
5798
  metadata: metadataFromFrontmatter(frontmatter, mode),
5228
- ...sourcePath !== void 0 && { sourcePath: path7.resolve(sourcePath) }
5799
+ ...sourcePath !== void 0 && { sourcePath: path8.resolve(sourcePath) }
5229
5800
  };
5230
5801
  }
5231
5802
  function serializeTaskDocument(frontmatter, description) {
@@ -5234,9 +5805,9 @@ ${stringify2(frontmatter)}---
5234
5805
 
5235
5806
  ${description}`;
5236
5807
  }
5237
- async function readDirectoryNames(fs4, directoryPath) {
5808
+ async function readDirectoryNames(fs5, directoryPath) {
5238
5809
  try {
5239
- return sortStrings(await fs4.readdir(directoryPath));
5810
+ return sortStrings(await fs5.readdir(directoryPath));
5240
5811
  } catch (error3) {
5241
5812
  if (hasErrorCode(error3, "ENOENT")) {
5242
5813
  return [];
@@ -5252,9 +5823,9 @@ async function ensureRootPath(deps) {
5252
5823
  }
5253
5824
  await deps.fs.stat(deps.path);
5254
5825
  }
5255
- async function readTaskFile(fs4, list, id, filePath, validStates, initialState, mode) {
5256
- await rejectSymbolicLinkComponents(fs4, filePath);
5257
- const content = await fs4.readFile(filePath, "utf8");
5826
+ async function readTaskFile(fs5, list, id, filePath, validStates, initialState, mode) {
5827
+ await rejectSymbolicLinkComponents(fs5, filePath);
5828
+ const content = await fs5.readFile(filePath, "utf8");
5258
5829
  const document = splitTaskDocument(content, filePath, mode);
5259
5830
  const frontmatter = mode === "passthrough" && document.frontmatter.trim().length === 0 ? {} : readFrontmatter(document.frontmatter, filePath);
5260
5831
  if (mode !== "passthrough") {
@@ -5265,11 +5836,9 @@ async function readTaskFile(fs4, list, id, filePath, validStates, initialState,
5265
5836
  task: createTask(list, id, frontmatter, document.body, mode, filePath)
5266
5837
  };
5267
5838
  }
5268
- const parsedFilename = parseActiveFilename(path7.basename(filePath));
5269
- const defaultName = parsedFilename?.id ?? id;
5270
5839
  const effectiveFrontmatter = {
5271
5840
  ...frontmatter,
5272
- name: typeof frontmatter.name === "string" ? frontmatter.name : defaultName,
5841
+ name: typeof frontmatter.name === "string" ? frontmatter.name : id,
5273
5842
  state: typeof frontmatter.state === "string" && validStates.has(frontmatter.state) ? frontmatter.state : initialState
5274
5843
  };
5275
5844
  return {
@@ -5278,44 +5847,95 @@ async function readTaskFile(fs4, list, id, filePath, validStates, initialState,
5278
5847
  task: createTask(list, id, effectiveFrontmatter, document.body, mode, filePath)
5279
5848
  };
5280
5849
  }
5281
- async function findActiveTaskFilename(fs4, listDirectoryPath, id) {
5282
- const entries = await readDirectoryNames(fs4, listDirectoryPath);
5850
+ async function readPassthroughFrontmatter(fs5, filePath, mode) {
5851
+ if (mode !== "passthrough") {
5852
+ return {};
5853
+ }
5854
+ const content = await fs5.readFile(filePath, "utf8");
5855
+ const document = splitTaskDocument(content, filePath, mode);
5856
+ if (document.frontmatter.trim().length === 0) {
5857
+ return {};
5858
+ }
5859
+ return readFrontmatter(document.frontmatter, filePath);
5860
+ }
5861
+ async function resolveActiveFilenameEntry(fs5, entryName, entryPath, parsed, mode) {
5862
+ if (mode !== "passthrough" || parsed.order === null) {
5863
+ return parsed;
5864
+ }
5865
+ const frontmatter = await readPassthroughFrontmatter(fs5, entryPath, mode);
5866
+ if (Object.keys(frontmatter).length === 0 && orderedFilenamePrefixLength(entryName) <= MIN_PREFIX_WIDTH) {
5867
+ return parsed;
5868
+ }
5869
+ if (typeof frontmatter.state === "string" || hasOwnTaskField(frontmatter, "$schema") || hasOwnTaskField(frontmatter, "kind") || hasOwnTaskField(frontmatter, "version")) {
5870
+ return parsed;
5871
+ }
5872
+ return {
5873
+ id: entryName.slice(0, -MARKDOWN_EXTENSION.length),
5874
+ order: null,
5875
+ filename: parsed.filename
5876
+ };
5877
+ }
5878
+ function orderedFilenamePrefixLength(entryName) {
5879
+ const stem = entryName.slice(0, -MARKDOWN_EXTENSION.length);
5880
+ const separatorIndex = stem.indexOf("-");
5881
+ if (separatorIndex <= 0) {
5882
+ return Number.POSITIVE_INFINITY;
5883
+ }
5884
+ for (let index = 0; index < separatorIndex; index += 1) {
5885
+ const code = stem.charCodeAt(index);
5886
+ if (code < 48 || code > 57) {
5887
+ return Number.POSITIVE_INFINITY;
5888
+ }
5889
+ }
5890
+ return separatorIndex;
5891
+ }
5892
+ async function findActiveTaskFilename(fs5, listDirectoryPath, id, mode) {
5893
+ const entries = await readDirectoryNames(fs5, listDirectoryPath);
5283
5894
  for (const entryName of entries) {
5284
5895
  if (isHiddenEntry(entryName)) continue;
5285
5896
  const parsed = parseActiveFilename(entryName);
5286
- if (parsed?.id === id) {
5897
+ if (!parsed) continue;
5898
+ const entryPath = path8.join(listDirectoryPath, entryName);
5899
+ const resolved = await resolveActiveFilenameEntry(
5900
+ fs5,
5901
+ entryName,
5902
+ entryPath,
5903
+ { id: parsed.id, order: parsed.order, filename: entryName },
5904
+ mode
5905
+ );
5906
+ if (resolved.id === id) {
5287
5907
  return entryName;
5288
5908
  }
5289
5909
  }
5290
5910
  return void 0;
5291
5911
  }
5292
- async function findTaskLocation(fs4, rootPath, layout, list, id) {
5912
+ async function findTaskLocation(fs5, rootPath, layout, list, id, mode) {
5293
5913
  const listDirectoryPath = listPath(rootPath, layout, list);
5294
- await rejectSymbolicLinkComponents(fs4, listDirectoryPath);
5295
- const activeName = await findActiveTaskFilename(fs4, listDirectoryPath, id);
5914
+ await rejectSymbolicLinkComponents(fs5, listDirectoryPath);
5915
+ const activeName = await findActiveTaskFilename(fs5, listDirectoryPath, id, mode);
5296
5916
  if (activeName) {
5297
- const activePath = path7.join(listDirectoryPath, activeName);
5298
- await rejectSymbolicLinkComponents(fs4, activePath);
5299
- const activeStat = await statIfExists(fs4, activePath);
5917
+ const activePath = path8.join(listDirectoryPath, activeName);
5918
+ await rejectSymbolicLinkComponents(fs5, activePath);
5919
+ const activeStat = await statIfExists(fs5, activePath);
5300
5920
  if (activeStat?.isFile()) {
5301
5921
  return { archived: false, path: activePath };
5302
5922
  }
5303
5923
  }
5304
5924
  const archivedPath = archivedTaskPath(rootPath, layout, list, id);
5305
- await rejectSymbolicLinkComponents(fs4, archiveDirectoryPath(rootPath, layout, list));
5306
- await rejectSymbolicLinkComponents(fs4, archivedPath);
5307
- const archivedStat = await statIfExists(fs4, archivedPath);
5925
+ await rejectSymbolicLinkComponents(fs5, archiveDirectoryPath(rootPath, layout, list));
5926
+ await rejectSymbolicLinkComponents(fs5, archivedPath);
5927
+ const archivedStat = await statIfExists(fs5, archivedPath);
5308
5928
  if (archivedStat?.isFile()) {
5309
5929
  return { archived: true, path: archivedPath };
5310
5930
  }
5311
5931
  return void 0;
5312
5932
  }
5313
- async function readTaskAtLocation(fs4, rootPath, layout, list, id, validStates, initialState, mode) {
5314
- const location = await findTaskLocation(fs4, rootPath, layout, list, id);
5933
+ async function readTaskAtLocation(fs5, rootPath, layout, list, id, validStates, initialState, mode) {
5934
+ const location = await findTaskLocation(fs5, rootPath, layout, list, id, mode);
5315
5935
  if (!location) {
5316
5936
  throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
5317
5937
  }
5318
- return readTaskFile(fs4, list, id, location.path, validStates, initialState, mode);
5938
+ return readTaskFile(fs5, list, id, location.path, validStates, initialState, mode);
5319
5939
  }
5320
5940
  function createdFrontmatter(defaults2, input, initialState, mode) {
5321
5941
  const frontmatter = mode !== "passthrough" ? {
@@ -5331,12 +5951,12 @@ function createdFrontmatter(defaults2, input, initialState, mode) {
5331
5951
  const reservedKeys = reservedFrontmatterKeys(mode);
5332
5952
  for (const [key2, value] of Object.entries(defaults2.metadata)) {
5333
5953
  if (!reservedKeys.has(key2)) {
5334
- setOwnValue(frontmatter, key2, value);
5954
+ setOwnValue2(frontmatter, key2, value);
5335
5955
  }
5336
5956
  }
5337
5957
  for (const [key2, value] of Object.entries(input.metadata ?? {})) {
5338
5958
  if (!reservedKeys.has(key2)) {
5339
- setOwnValue(frontmatter, key2, value);
5959
+ setOwnValue2(frontmatter, key2, value);
5340
5960
  }
5341
5961
  }
5342
5962
  frontmatter.created = (/* @__PURE__ */ new Date()).toISOString();
@@ -5358,7 +5978,7 @@ function updatedFrontmatter(existingFrontmatter, task, patch, mode) {
5358
5978
  const reservedKeys = reservedFrontmatterKeys(mode);
5359
5979
  for (const [key2, value] of Object.entries(patch.metadata ?? {})) {
5360
5980
  if (!reservedKeys.has(key2)) {
5361
- setOwnValue(nextFrontmatter, key2, value);
5981
+ setOwnValue2(nextFrontmatter, key2, value);
5362
5982
  }
5363
5983
  }
5364
5984
  return nextFrontmatter;
@@ -5382,7 +6002,7 @@ function firedFrontmatter(existingFrontmatter, task, to, mode, metadataPatch) {
5382
6002
  const reservedKeys = reservedFrontmatterKeys(mode);
5383
6003
  for (const [key2, value] of Object.entries(metadataPatch ?? {})) {
5384
6004
  if (!reservedKeys.has(key2)) {
5385
- setOwnValue(nextFrontmatter, key2, value);
6005
+ setOwnValue2(nextFrontmatter, key2, value);
5386
6006
  }
5387
6007
  }
5388
6008
  return nextFrontmatter;
@@ -5416,11 +6036,19 @@ function createTasksView2(deps, layout, list) {
5416
6036
  if (isHiddenEntry(entryName)) continue;
5417
6037
  const parsed = parseActiveFilename(entryName);
5418
6038
  if (!parsed) continue;
5419
- const entryPath = path7.join(listDirectoryPath, entryName);
6039
+ const entryPath = path8.join(listDirectoryPath, entryName);
5420
6040
  await rejectSymbolicLinkComponents(deps.fs, entryPath);
5421
6041
  const entryStat = await statIfExists(deps.fs, entryPath);
5422
6042
  if (!entryStat?.isFile()) continue;
5423
- result.push({ id: parsed.id, order: parsed.order, filename: entryName });
6043
+ result.push(
6044
+ await resolveActiveFilenameEntry(
6045
+ deps.fs,
6046
+ entryName,
6047
+ entryPath,
6048
+ { id: parsed.id, order: parsed.order, filename: entryName },
6049
+ deps.frontmatterMode
6050
+ )
6051
+ );
5424
6052
  }
5425
6053
  result.sort((left, right) => {
5426
6054
  const leftOrder = left.order ?? Number.POSITIVE_INFINITY;
@@ -5434,7 +6062,7 @@ function createTasksView2(deps, layout, list) {
5434
6062
  const entries = await readActiveEntries();
5435
6063
  const tasks = /* @__PURE__ */ new Map();
5436
6064
  for (const entry of entries) {
5437
- const filePath = path7.join(listDirectoryPath, entry.filename);
6065
+ const filePath = path8.join(listDirectoryPath, entry.filename);
5438
6066
  const file = await readTaskFile(
5439
6067
  deps.fs,
5440
6068
  list,
@@ -5455,7 +6083,7 @@ function createTasksView2(deps, layout, list) {
5455
6083
  const result = [];
5456
6084
  for (const entryName of entries) {
5457
6085
  if (isHiddenEntry(entryName) || !isMarkdownFile(entryName)) continue;
5458
- const entryPath = path7.join(archivePath, entryName);
6086
+ const entryPath = path8.join(archivePath, entryName);
5459
6087
  await rejectSymbolicLinkComponents(deps.fs, entryPath);
5460
6088
  const entryStat = await statIfExists(deps.fs, entryPath);
5461
6089
  if (!entryStat?.isFile()) continue;
@@ -5485,15 +6113,20 @@ function createTasksView2(deps, layout, list) {
5485
6113
  if (desiredOrder === void 0) continue;
5486
6114
  const desiredFilename = activeTaskFilename(entry.id, desiredOrder, width);
5487
6115
  if (entry.filename !== desiredFilename) {
5488
- const fromPath = path7.join(listDirectoryPath, entry.filename);
5489
- const stagingPath = path7.join(
6116
+ const fromPath = path8.join(listDirectoryPath, entry.filename);
6117
+ const stagingPath = path8.join(
5490
6118
  listDirectoryPath,
5491
6119
  `${desiredFilename}.staging-${process.pid}-${index}`
5492
6120
  );
5493
- const targetPath = path7.join(listDirectoryPath, desiredFilename);
6121
+ const targetPath = path8.join(listDirectoryPath, desiredFilename);
5494
6122
  try {
5495
6123
  await deps.fs.rename(fromPath, stagingPath);
5496
- staged.push({ original: fromPath, staging: stagingPath, target: targetPath, finalized: false });
6124
+ staged.push({
6125
+ original: fromPath,
6126
+ staging: stagingPath,
6127
+ target: targetPath,
6128
+ finalized: false
6129
+ });
5497
6130
  } catch (error3) {
5498
6131
  for (const stagedEntry of staged.reverse()) {
5499
6132
  await deps.fs.rename(stagedEntry.staging, stagedEntry.original);
@@ -5628,8 +6261,7 @@ function createTasksView2(deps, layout, list) {
5628
6261
  if (filter?.state && entry.task.state !== filter.state) return false;
5629
6262
  return true;
5630
6263
  });
5631
- const orderedActiveTasks = applyOrder(orderedActive, filter?.order);
5632
- return [...orderedActiveTasks, ...filteredArchived.map((entry) => entry.task)];
6264
+ return applyOrder([...orderedActive, ...filteredArchived], filter?.order);
5633
6265
  },
5634
6266
  async get(id) {
5635
6267
  return (await getTaskFile(id)).task;
@@ -5638,9 +6270,17 @@ function createTasksView2(deps, layout, list) {
5638
6270
  assertCreateDoesNotSetState(input);
5639
6271
  assertCreateHasId(input);
5640
6272
  validateTaskId(input.id);
6273
+ validateTaskName(input.name);
5641
6274
  await rejectSymbolicLinkComponents(deps.fs, listDirectoryPath);
5642
- return withFileLock(deps.fs, path7.join(listDirectoryPath, ".transition.lock"), async () => {
5643
- const existing = await findTaskLocation(deps.fs, deps.path, layout, list, input.id);
6275
+ return withFileLock(deps.fs, path8.join(listDirectoryPath, ".transition.lock"), async () => {
6276
+ const existing = await findTaskLocation(
6277
+ deps.fs,
6278
+ deps.path,
6279
+ layout,
6280
+ list,
6281
+ input.id,
6282
+ deps.frontmatterMode
6283
+ );
5644
6284
  if (existing) {
5645
6285
  throw new TaskAlreadyExistsError(`Task "${list}/${input.id}" already exists.`);
5646
6286
  }
@@ -5652,7 +6292,7 @@ function createTasksView2(deps, layout, list) {
5652
6292
  const nextOrder = maxOrder + 1;
5653
6293
  const width = padWidthForCount(activeEntries.length + 1);
5654
6294
  const filename = activeTaskFilename(input.id, nextOrder, width);
5655
- const targetPath = path7.join(listDirectoryPath, filename);
6295
+ const targetPath = path8.join(listDirectoryPath, filename);
5656
6296
  const frontmatter = createdFrontmatter(
5657
6297
  deps.defaults,
5658
6298
  input,
@@ -5661,12 +6301,22 @@ function createTasksView2(deps, layout, list) {
5661
6301
  );
5662
6302
  const description = input.description ?? "";
5663
6303
  await writeAtomically(deps.fs, targetPath, serializeTaskDocument(frontmatter, description));
5664
- return createTask(list, input.id, frontmatter, description, deps.frontmatterMode, targetPath);
6304
+ return createTask(
6305
+ list,
6306
+ input.id,
6307
+ frontmatter,
6308
+ description,
6309
+ deps.frontmatterMode,
6310
+ targetPath
6311
+ );
5665
6312
  });
5666
6313
  },
5667
6314
  async update(id, patch) {
5668
6315
  assertUpdateDoesNotSetState(patch);
5669
6316
  validateTaskId(id);
6317
+ if (patch.name !== void 0) {
6318
+ validateTaskName(patch.name);
6319
+ }
5670
6320
  const existing = await getTaskFile(id);
5671
6321
  const nextFrontmatter = updatedFrontmatter(
5672
6322
  existing.frontmatter,
@@ -5752,7 +6402,14 @@ function createTasksView2(deps, layout, list) {
5752
6402
  };
5753
6403
  if (stateMachine.events[eventName]?.to === "archived") {
5754
6404
  validateTaskId(id);
5755
- const location = await findTaskLocation(deps.fs, deps.path, layout, list, id);
6405
+ const location = await findTaskLocation(
6406
+ deps.fs,
6407
+ deps.path,
6408
+ layout,
6409
+ list,
6410
+ id,
6411
+ deps.frontmatterMode
6412
+ );
5756
6413
  if (!location) {
5757
6414
  throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
5758
6415
  }
@@ -5760,7 +6417,7 @@ function createTasksView2(deps, layout, list) {
5760
6417
  validateTaskId(id);
5761
6418
  const { event, nextTask } = await withFileLock(
5762
6419
  deps.fs,
5763
- path7.join(listDirectoryPath, ".transition.lock"),
6420
+ path8.join(listDirectoryPath, ".transition.lock"),
5764
6421
  fireTask
5765
6422
  );
5766
6423
  await event.onEnter?.(nextTask);
@@ -5780,7 +6437,14 @@ function createTasksView2(deps, layout, list) {
5780
6437
  },
5781
6438
  async delete(id) {
5782
6439
  validateTaskId(id);
5783
- const location = await findTaskLocation(deps.fs, deps.path, layout, list, id);
6440
+ const location = await findTaskLocation(
6441
+ deps.fs,
6442
+ deps.path,
6443
+ layout,
6444
+ list,
6445
+ id,
6446
+ deps.frontmatterMode
6447
+ );
5784
6448
  if (!location) {
5785
6449
  throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
5786
6450
  }
@@ -5853,7 +6517,7 @@ async function markdownDirBackend(deps) {
5853
6517
  if (entryName === ARCHIVE_DIRECTORY_NAME || isHiddenEntry(entryName)) {
5854
6518
  continue;
5855
6519
  }
5856
- const entryPath = path7.join(deps.path, entryName);
6520
+ const entryPath = path8.join(deps.path, entryName);
5857
6521
  await rejectSymbolicLinkComponents(deps.fs, entryPath);
5858
6522
  const entryStat = await statIfExists(deps.fs, entryPath);
5859
6523
  if (entryStat?.isDirectory()) {
@@ -5895,12 +6559,26 @@ async function markdownDirBackend(deps) {
5895
6559
  }
5896
6560
  const targetListDir = listPath(deps.path, layout, targetListName);
5897
6561
  await rejectSymbolicLinkComponents(deps.fs, targetListDir);
5898
- return withFileLock(deps.fs, path7.join(targetListDir, ".transition.lock"), async () => {
5899
- const targetExisting = await findTaskLocation(deps.fs, deps.path, layout, targetListName, id);
6562
+ return withFileLock(deps.fs, path8.join(targetListDir, ".transition.lock"), async () => {
6563
+ const targetExisting = await findTaskLocation(
6564
+ deps.fs,
6565
+ deps.path,
6566
+ layout,
6567
+ targetListName,
6568
+ id,
6569
+ deps.frontmatterMode
6570
+ );
5900
6571
  if (targetExisting) {
5901
6572
  throw new TaskAlreadyExistsError(`Task "${targetListName}/${id}" already exists.`);
5902
6573
  }
5903
- const sourceLocation = await findTaskLocation(deps.fs, deps.path, layout, sourceListName, id);
6574
+ const sourceLocation = await findTaskLocation(
6575
+ deps.fs,
6576
+ deps.path,
6577
+ layout,
6578
+ sourceListName,
6579
+ id,
6580
+ deps.frontmatterMode
6581
+ );
5904
6582
  if (!sourceLocation) {
5905
6583
  throw new TaskNotFoundError(`Task "${sourceListName}/${id}" not found.`);
5906
6584
  }
@@ -5945,7 +6623,7 @@ async function markdownDirBackend(deps) {
5945
6623
  );
5946
6624
  const width = padWidthForCount(targetEntries.length + 1);
5947
6625
  const targetFilename = activeTaskFilename(id, maxOrder + 1, width);
5948
- const targetPath = path7.join(targetListDir, targetFilename);
6626
+ const targetPath = path8.join(targetListDir, targetFilename);
5949
6627
  await deps.fs.rename(sourceLocation.path, targetPath);
5950
6628
  return createTask(
5951
6629
  targetListName,
@@ -5967,7 +6645,7 @@ async function markdownDirBackend(deps) {
5967
6645
  }
5968
6646
 
5969
6647
  // ../task-list/src/backends/yaml-file.ts
5970
- import path8 from "node:path";
6648
+ import path9 from "node:path";
5971
6649
  import { isMap, parseDocument as parseDocument3 } from "yaml";
5972
6650
 
5973
6651
  // ../task-list/src/schema/store.schema.json
@@ -6027,7 +6705,7 @@ function malformedTask2(list, id, field) {
6027
6705
  return new MalformedTaskError(`Malformed task "${list}/${id}": invalid "${field}".`);
6028
6706
  }
6029
6707
  function validateListName2(name) {
6030
- if (name.length === 0 || name.startsWith(".") || name.includes("/") || name.includes("\\") || name.includes("..")) {
6708
+ if (!isTrimmedPrintableIdentifier(name) || name.startsWith(".") || name.includes("/") || name.includes("\\") || name.includes("..")) {
6031
6709
  throw new Error(`Invalid task list name "${name}".`);
6032
6710
  }
6033
6711
  return name;
@@ -6064,7 +6742,7 @@ function createTask2(list, id, taskRecord, sourcePath) {
6064
6742
  state: getOwnEntry(taskRecord, "state"),
6065
6743
  description: descriptionFromTaskRecord(taskRecord),
6066
6744
  metadata: metadataFromTaskRecord(taskRecord),
6067
- ...sourcePath !== void 0 && { sourcePath: path8.resolve(sourcePath) }
6745
+ ...sourcePath !== void 0 && { sourcePath: path9.resolve(sourcePath) }
6068
6746
  };
6069
6747
  }
6070
6748
  function matchesFilter(task, filter) {
@@ -6235,8 +6913,8 @@ function serializeDocument(document) {
6235
6913
  return serialized.endsWith("\n") ? serialized : `${serialized}
6236
6914
  `;
6237
6915
  }
6238
- async function readStore(fs4, filePath, validStates) {
6239
- const content = await fs4.readFile(filePath, "utf8");
6916
+ async function readStore(fs5, filePath, validStates) {
6917
+ const content = await fs5.readFile(filePath, "utf8");
6240
6918
  const document = parseStoreDocument(filePath, content);
6241
6919
  const store = document.toJS();
6242
6920
  assertValidStoreRecord(store, filePath);
@@ -6376,6 +7054,7 @@ function createTasksView3(deps, list) {
6376
7054
  assertCreateDoesNotSetState2(input);
6377
7055
  assertCreateHasId2(input);
6378
7056
  validateTaskId(input.id);
7057
+ validateTaskName(input.name);
6379
7058
  const { document, store } = await readStore(deps.fs, deps.path, validStates);
6380
7059
  if (getTaskRecord(store, list, input.id)) {
6381
7060
  throw new TaskAlreadyExistsError(`Task "${list}/${input.id}" already exists.`);
@@ -6388,6 +7067,9 @@ function createTasksView3(deps, list) {
6388
7067
  async update(id, patch) {
6389
7068
  assertUpdateDoesNotSetState2(patch);
6390
7069
  validateTaskId(id);
7070
+ if (patch.name !== void 0) {
7071
+ validateTaskName(patch.name);
7072
+ }
6391
7073
  const { document, store } = await readStore(deps.fs, deps.path, validStates);
6392
7074
  const existing = getTaskOrThrow(store, list, id);
6393
7075
  const nextTaskRecord = buildUpdatedTaskRecord(existing, patch);
@@ -6479,6 +7161,11 @@ function createTasksView3(deps, list) {
6479
7161
  insertIndex = anchor.position === "top" ? 0 : listNode.items.length;
6480
7162
  } else {
6481
7163
  const anchorId = "before" in anchor ? anchor.before : anchor.after;
7164
+ const activeIds = new Set(activeItemIds(listNode, validStates));
7165
+ if (!activeIds.has(anchorId)) {
7166
+ listNode.items.splice(fromIndex, 0, movedPair);
7167
+ throw new AnchorNotFoundError(anchorId);
7168
+ }
6482
7169
  const anchorIndex = findItemIndex(listNode, anchorId);
6483
7170
  if (anchorIndex < 0) {
6484
7171
  listNode.items.splice(fromIndex, 0, movedPair);
@@ -6663,7 +7350,7 @@ function isRecord4(value) {
6663
7350
 
6664
7351
  // ../task-list/src/move.ts
6665
7352
  import * as fsPromises2 from "node:fs/promises";
6666
- import path9 from "node:path";
7353
+ import path10 from "node:path";
6667
7354
 
6668
7355
  // ../toolcraft/src/human-in-loop/approval-tasks.ts
6669
7356
  import { randomBytes as randomBytes3 } from "node:crypto";
@@ -6850,7 +7537,7 @@ function areEqualStrings(left, right) {
6850
7537
  }
6851
7538
 
6852
7539
  // ../toolcraft/src/human-in-loop/runner.ts
6853
- import { access, lstat, readFile as readFile2, rename, unlink, writeFile as writeFile2 } from "node:fs/promises";
7540
+ import { access, lstat, readFile as readFile3, rename, unlink, writeFile as writeFile2 } from "node:fs/promises";
6854
7541
 
6855
7542
  // ../toolcraft/src/human-in-loop/default-provider.ts
6856
7543
  import process3 from "node:process";
@@ -6882,7 +7569,7 @@ on error number -128
6882
7569
  end try`;
6883
7570
  }
6884
7571
  function parseStdout(out) {
6885
- const value = out.endsWith("\r\n") ? out.slice(0, -2) : out.endsWith("\n") ? out.slice(0, -1) : out;
7572
+ const value = out.endsWith("\r\n") ? out.slice(0, -2) : out.endsWith("\n") ? out.slice(0, -1) : out.endsWith("\r") ? out.slice(0, -1) : out;
6886
7573
  switch (value) {
6887
7574
  case "Approve":
6888
7575
  case "APPROVED":
@@ -7162,13 +7849,13 @@ function formatAvailableApprovalCommandPaths(root) {
7162
7849
  }
7163
7850
  function enumerateApprovalCommandPaths(root) {
7164
7851
  const paths = [];
7165
- const visit = (node, path24) => {
7852
+ const visit = (node, path25) => {
7166
7853
  if (node.kind === "command") {
7167
- paths.push(path24.join("."));
7854
+ paths.push(path25.join("."));
7168
7855
  return;
7169
7856
  }
7170
7857
  for (const child of getVisibleCliChildren(node)) {
7171
- visit(child, [...path24, child.name]);
7858
+ visit(child, [...path25, child.name]);
7172
7859
  }
7173
7860
  };
7174
7861
  if (root.kind === "command") {
@@ -7203,21 +7890,21 @@ function createHandlerContext(command, params17) {
7203
7890
  }
7204
7891
  function createFs() {
7205
7892
  return {
7206
- readFile: async (path24, encoding = "utf8") => readFile2(path24, { encoding }),
7207
- writeFile: async (path24, contents, options) => {
7208
- await writeFile2(path24, contents, options);
7893
+ readFile: async (path25, encoding = "utf8") => readFile3(path25, { encoding }),
7894
+ writeFile: async (path25, contents, options) => {
7895
+ await writeFile2(path25, contents, options);
7209
7896
  },
7210
- exists: async (path24) => {
7897
+ exists: async (path25) => {
7211
7898
  try {
7212
- await access(path24);
7899
+ await access(path25);
7213
7900
  return true;
7214
7901
  } catch {
7215
7902
  return false;
7216
7903
  }
7217
7904
  },
7218
- lstat: async (path24) => lstat(path24),
7905
+ lstat: async (path25) => lstat(path25),
7219
7906
  rename: async (fromPath, toPath) => rename(fromPath, toPath),
7220
- unlink: async (path24) => unlink(path24)
7907
+ unlink: async (path25) => unlink(path25)
7221
7908
  };
7222
7909
  }
7223
7910
  function createEnv(values = process.env) {
@@ -7496,13 +8183,13 @@ function isMissingStateError(error3) {
7496
8183
  import { mkdir as mkdir2, realpath as realpath2, writeFile as writeFile4 } from "node:fs/promises";
7497
8184
  import { randomUUID as randomUUID5 } from "node:crypto";
7498
8185
  import os from "node:os";
7499
- import path13 from "node:path";
8186
+ import path14 from "node:path";
7500
8187
  import { CommanderError } from "commander";
7501
8188
 
7502
8189
  // ../toolcraft/src/mcp-proxy.ts
7503
8190
  import { existsSync as existsSync2 } from "node:fs";
7504
- import { lstat as lstat2, mkdir, readFile as readFile3, rename as rename2, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
7505
- import path12 from "node:path";
8191
+ import { lstat as lstat2, mkdir, readFile as readFile4, rename as rename2, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
8192
+ import path13 from "node:path";
7506
8193
  import { createHash as createHash3, randomUUID as randomUUID4 } from "node:crypto";
7507
8194
 
7508
8195
  // ../tiny-mcp-client/src/internal.ts
@@ -7511,13 +8198,13 @@ import { PassThrough as PassThrough2 } from "node:stream";
7511
8198
 
7512
8199
  // ../mcp-oauth/src/client/auth-store-session-store.ts
7513
8200
  import crypto from "node:crypto";
7514
- import path11 from "node:path";
8201
+ import path12 from "node:path";
7515
8202
 
7516
8203
  // ../auth-store/src/encrypted-file-store.ts
7517
8204
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes4, randomUUID as randomUUID3, scrypt } from "node:crypto";
7518
8205
  import { promises as fs } from "node:fs";
7519
8206
  import { homedir, hostname, userInfo } from "node:os";
7520
- import path10 from "node:path";
8207
+ import path11 from "node:path";
7521
8208
 
7522
8209
  // ../auth-store/src/error-codes.ts
7523
8210
  function hasOwnErrorCode3(error3, code) {
@@ -7546,10 +8233,13 @@ var EncryptedFileStore = class {
7546
8233
  if (input.filePath === void 0) {
7547
8234
  const homeDirectory = (input.getHomeDirectory ?? homedir)();
7548
8235
  const defaultDirectory = input.defaultDirectory ?? ".auth-store";
7549
- this.filePath = path10.join(
8236
+ const defaultFileName = input.defaultFileName ?? "credentials.enc";
8237
+ assertSafeDefaultDirectory(defaultDirectory);
8238
+ assertSafeDefaultFileName(defaultFileName);
8239
+ this.filePath = path11.join(
7550
8240
  homeDirectory,
7551
8241
  defaultDirectory,
7552
- input.defaultFileName ?? "credentials.enc"
8242
+ defaultFileName
7553
8243
  );
7554
8244
  this.symbolicLinkCheckStartPath = resolveDefaultDirectoryCheckStart(
7555
8245
  homeDirectory,
@@ -7609,7 +8299,7 @@ var EncryptedFileStore = class {
7609
8299
  authTag: authTag.toString("base64"),
7610
8300
  ciphertext: ciphertext.toString("base64")
7611
8301
  };
7612
- await this.fs.mkdir(path10.dirname(this.filePath), { recursive: true });
8302
+ await this.fs.mkdir(path11.dirname(this.filePath), { recursive: true });
7613
8303
  await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
7614
8304
  const temporaryPath = `${this.filePath}.${process.pid}.${randomUUID3()}.tmp`;
7615
8305
  let temporaryCreated = false;
@@ -7641,7 +8331,7 @@ var EncryptedFileStore = class {
7641
8331
  }
7642
8332
  }
7643
8333
  async assertCredentialPathHasNoSymbolicLinks(targetPath) {
7644
- const resolvedPath = path10.resolve(targetPath);
8334
+ const resolvedPath = path11.resolve(targetPath);
7645
8335
  const protectedPaths = getProtectedCredentialPaths(
7646
8336
  resolvedPath,
7647
8337
  this.symbolicLinkCheckStartPath
@@ -7675,27 +8365,62 @@ var EncryptedFileStore = class {
7675
8365
  };
7676
8366
  function resolveDefaultDirectoryCheckStart(homeDirectory, defaultDirectory) {
7677
8367
  const [firstSegment] = defaultDirectory.split(/[\\/]+/).filter(Boolean);
7678
- return path10.resolve(homeDirectory, firstSegment ?? ".");
8368
+ return path11.resolve(homeDirectory, firstSegment ?? ".");
7679
8369
  }
7680
8370
  function getProtectedCredentialPaths(resolvedPath, symbolicLinkCheckStartPath) {
7681
8371
  if (symbolicLinkCheckStartPath === null) {
7682
- return [path10.dirname(resolvedPath), resolvedPath];
8372
+ return getExplicitProtectedCredentialPaths(resolvedPath);
7683
8373
  }
7684
- const resolvedStartPath = path10.resolve(symbolicLinkCheckStartPath);
8374
+ const resolvedStartPath = path11.resolve(symbolicLinkCheckStartPath);
7685
8375
  if (!isPathInsideOrEqual(resolvedPath, resolvedStartPath)) {
7686
- return [path10.dirname(resolvedPath), resolvedPath];
8376
+ return [path11.dirname(resolvedPath), resolvedPath];
7687
8377
  }
7688
8378
  const protectedPaths = [resolvedStartPath];
7689
8379
  let currentPath = resolvedStartPath;
7690
- for (const segment of path10.relative(resolvedStartPath, resolvedPath).split(path10.sep).filter(Boolean)) {
7691
- currentPath = path10.join(currentPath, segment);
8380
+ for (const segment of path11.relative(resolvedStartPath, resolvedPath).split(path11.sep).filter(Boolean)) {
8381
+ currentPath = path11.join(currentPath, segment);
8382
+ protectedPaths.push(currentPath);
8383
+ }
8384
+ return protectedPaths;
8385
+ }
8386
+ function assertSafeDefaultDirectory(defaultDirectory) {
8387
+ if (path11.isAbsolute(defaultDirectory) || path11.win32.isAbsolute(defaultDirectory)) {
8388
+ throw new Error("defaultDirectory must be a relative path inside the home directory");
8389
+ }
8390
+ for (const segment of splitPathSegments(defaultDirectory)) {
8391
+ if (segment === "..") {
8392
+ throw new Error("defaultDirectory must be a relative path inside the home directory");
8393
+ }
8394
+ }
8395
+ }
8396
+ function assertSafeDefaultFileName(defaultFileName) {
8397
+ if (defaultFileName.trim().length === 0 || defaultFileName === "." || defaultFileName === ".." || splitPathSegments(defaultFileName).length !== 1) {
8398
+ throw new Error("defaultFileName must be a file name without path separators");
8399
+ }
8400
+ }
8401
+ function splitPathSegments(value) {
8402
+ return value.split("/").flatMap((segment) => segment.split("\\")).filter((segment) => segment.length > 0);
8403
+ }
8404
+ function getExplicitProtectedCredentialPaths(resolvedPath) {
8405
+ const parsed = path11.parse(resolvedPath);
8406
+ const segments = resolvedPath.slice(parsed.root.length).split(path11.sep).filter((segment) => segment.length > 0);
8407
+ if (segments.length <= 1) {
8408
+ return [resolvedPath];
8409
+ }
8410
+ const protectedPaths = [];
8411
+ let currentPath = parsed.root;
8412
+ for (const [index, segment] of segments.entries()) {
8413
+ currentPath = path11.join(currentPath, segment);
8414
+ if (index === 0) {
8415
+ continue;
8416
+ }
7692
8417
  protectedPaths.push(currentPath);
7693
8418
  }
7694
8419
  return protectedPaths;
7695
8420
  }
7696
8421
  function isPathInsideOrEqual(childPath, parentPath) {
7697
- const relativePath = path10.relative(parentPath, childPath);
7698
- return relativePath === "" || !relativePath.startsWith("..") && !path10.isAbsolute(relativePath);
8422
+ const relativePath = path11.relative(parentPath, childPath);
8423
+ return relativePath === "" || !relativePath.startsWith("..") && !path11.isAbsolute(relativePath);
7699
8424
  }
7700
8425
  async function removeIfPresent(fileSystem, filePath) {
7701
8426
  try {
@@ -7786,8 +8511,14 @@ var KeychainStore = class {
7786
8511
  account;
7787
8512
  constructor(input) {
7788
8513
  this.runCommand = input.runCommand ?? runSecurityCommand;
7789
- this.service = input.service;
7790
- this.account = input.account;
8514
+ this.service = input.service.trim();
8515
+ this.account = input.account.trim();
8516
+ if (this.service.length === 0) {
8517
+ throw new Error("Keychain service must not be empty");
8518
+ }
8519
+ if (this.account.length === 0) {
8520
+ throw new Error("Keychain account must not be empty");
8521
+ }
7791
8522
  }
7792
8523
  async get() {
7793
8524
  const result = await this.executeSecurityCommand(
@@ -7814,10 +8545,10 @@ var KeychainStore = class {
7814
8545
  "-a",
7815
8546
  this.account,
7816
8547
  "-U",
7817
- "-w"
8548
+ "-w",
8549
+ value
7818
8550
  ],
7819
- "store secret in macOS Keychain",
7820
- { stdin: value }
8551
+ "store secret in macOS Keychain"
7821
8552
  );
7822
8553
  if (getCommandExitCode(result) !== 0) {
7823
8554
  throw createSecurityCliFailure("store secret in macOS Keychain", result);
@@ -7962,13 +8693,14 @@ function createSecretStore(input) {
7962
8693
  function resolveBackend(input) {
7963
8694
  const envVar = input.backendEnvVar ?? DEFAULT_BACKEND_ENV_VAR;
7964
8695
  const configuredBackend = input.backend ?? getOwnEnvValue(input.env, envVar) ?? getOwnEnvValue(process.env, envVar);
7965
- if (configuredBackend === "keychain") {
8696
+ const backend = configuredBackend?.trim();
8697
+ if (backend === "keychain") {
7966
8698
  return "keychain";
7967
8699
  }
7968
- if (configuredBackend === void 0 || configuredBackend === "file") {
8700
+ if (backend === void 0 || backend === "file") {
7969
8701
  return "file";
7970
8702
  }
7971
- throw new Error(`Unsupported auth store backend: ${configuredBackend}`);
8703
+ throw new Error(`Unsupported auth store backend: ${backend}`);
7972
8704
  }
7973
8705
  function getOwnEnvValue(env, key2) {
7974
8706
  return env !== void 0 && Object.prototype.hasOwnProperty.call(env, key2) ? env[key2] : void 0;
@@ -7993,6 +8725,7 @@ var DEFAULT_KEYCHAIN_SERVICE = "poe-code-mcp-oauth";
7993
8725
  var DEFAULT_CLIENT_FILE_SALT = "poe-code:mcp-oauth:clients:v1";
7994
8726
  var DEFAULT_CLIENT_FILE_DIRECTORY = ".poe-code/mcp-oauth/clients";
7995
8727
  var DEFAULT_CLIENT_KEYCHAIN_SERVICE = "poe-code-mcp-oauth-clients";
8728
+ var MAX_JS_DATE_MS = 864e13;
7996
8729
  function createAuthStoreSessionStore(options = {}) {
7997
8730
  return {
7998
8731
  async load(resource) {
@@ -8002,10 +8735,10 @@ function createAuthStoreSessionStore(options = {}) {
8002
8735
  return null;
8003
8736
  }
8004
8737
  const parsed = JSON.parse(value);
8005
- if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
8738
+ if (isStoredOAuthSession(parsed)) {
8006
8739
  return parsed;
8007
8740
  }
8008
- throw new Error("Stored OAuth session must be a JSON object");
8741
+ throw new Error("Stored OAuth session must match the expected shape");
8009
8742
  },
8010
8743
  async save(resource, session) {
8011
8744
  const store = createResourceSecretStore(resource, options);
@@ -8049,10 +8782,10 @@ function createAuthStoreClientStore(options) {
8049
8782
  function createNamedSecretStore(key2, options, defaults2) {
8050
8783
  const hash = crypto.createHash("sha256").update(key2).digest("hex");
8051
8784
  const configuredFilePath = options.fileStore?.filePath;
8052
- const parsedFilePath = configuredFilePath === void 0 ? null : path11.parse(configuredFilePath);
8785
+ const parsedFilePath = configuredFilePath === void 0 ? null : path12.parse(configuredFilePath);
8053
8786
  const fileStore = {
8054
8787
  ...options.fileStore,
8055
- filePath: parsedFilePath === null ? void 0 : path11.join(
8788
+ filePath: parsedFilePath === null ? void 0 : path12.join(
8056
8789
  parsedFilePath.dir,
8057
8790
  `${parsedFilePath.name}-${hash}${parsedFilePath.ext || ".enc"}`
8058
8791
  ),
@@ -8068,28 +8801,20 @@ function createNamedSecretStore(key2, options, defaults2) {
8068
8801
  return createSecretStore({ ...options, fileStore, keychainStore }).store;
8069
8802
  }
8070
8803
  function createResourceSecretStore(resource, options) {
8071
- return createNamedSecretStore(
8072
- canonicalizeResourceIndicator(resource),
8073
- options,
8074
- {
8075
- salt: DEFAULT_FILE_SALT,
8076
- directory: DEFAULT_FILE_DIRECTORY,
8077
- service: DEFAULT_KEYCHAIN_SERVICE,
8078
- accountPrefix: "provider"
8079
- }
8080
- );
8804
+ return createNamedSecretStore(canonicalizeResourceIndicator(resource), options, {
8805
+ salt: DEFAULT_FILE_SALT,
8806
+ directory: DEFAULT_FILE_DIRECTORY,
8807
+ service: DEFAULT_KEYCHAIN_SERVICE,
8808
+ accountPrefix: "provider"
8809
+ });
8081
8810
  }
8082
8811
  function createIssuerSecretStore(issuer, options) {
8083
- return createNamedSecretStore(
8084
- issuer,
8085
- options,
8086
- {
8087
- salt: DEFAULT_CLIENT_FILE_SALT,
8088
- directory: DEFAULT_CLIENT_FILE_DIRECTORY,
8089
- service: DEFAULT_CLIENT_KEYCHAIN_SERVICE,
8090
- accountPrefix: "issuer"
8091
- }
8092
- );
8812
+ return createNamedSecretStore(issuer, options, {
8813
+ salt: DEFAULT_CLIENT_FILE_SALT,
8814
+ directory: DEFAULT_CLIENT_FILE_DIRECTORY,
8815
+ service: DEFAULT_CLIENT_KEYCHAIN_SERVICE,
8816
+ accountPrefix: "issuer"
8817
+ });
8093
8818
  }
8094
8819
  function isObjectRecord(value) {
8095
8820
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -8101,6 +8826,50 @@ function getOwnString(record, key2) {
8101
8826
  const value = getOwnEntry4(record, key2);
8102
8827
  return typeof value === "string" ? value : void 0;
8103
8828
  }
8829
+ function isStoredOAuthSession(value) {
8830
+ if (!isObjectRecord(value)) {
8831
+ return false;
8832
+ }
8833
+ return isNonBlankOwnString(value, "resource") && isNonBlankOwnString(value, "authorizationServer") && isStoredOAuthClient(getOwnEntry4(value, "client")) && isStoredOAuthDiscovery(getOwnEntry4(value, "discovery")) && isStoredOAuthTokensOrMissing(getOwnEntry4(value, "tokens"));
8834
+ }
8835
+ function isStoredOAuthClient(value) {
8836
+ if (!isObjectRecord(value) || !isNonBlankOwnString(value, "clientId")) {
8837
+ return false;
8838
+ }
8839
+ const clientSecret = getOwnEntry4(value, "clientSecret");
8840
+ return clientSecret === void 0 || typeof clientSecret === "string" && clientSecret.trim().length > 0;
8841
+ }
8842
+ function isStoredOAuthDiscovery(value) {
8843
+ if (!isObjectRecord(value)) {
8844
+ return false;
8845
+ }
8846
+ return isNonBlankOwnString(value, "resourceMetadataUrl") && isObjectRecord(getOwnEntry4(value, "resourceMetadata")) && isObjectRecord(getOwnEntry4(value, "authorizationServerMetadata"));
8847
+ }
8848
+ function isStoredOAuthTokensOrMissing(value) {
8849
+ if (value === void 0) {
8850
+ return true;
8851
+ }
8852
+ if (!isObjectRecord(value)) {
8853
+ return false;
8854
+ }
8855
+ if (!isNonBlankOwnString(value, "accessToken") || getOwnString(value, "tokenType") !== "Bearer") {
8856
+ return false;
8857
+ }
8858
+ const expiresAt = getOwnEntry4(value, "expiresAt");
8859
+ if (expiresAt !== null && (typeof expiresAt !== "number" || !Number.isSafeInteger(expiresAt) || expiresAt > MAX_JS_DATE_MS || !Number.isFinite(new Date(expiresAt).getTime()))) {
8860
+ return false;
8861
+ }
8862
+ const refreshToken = getOwnEntry4(value, "refreshToken");
8863
+ if (refreshToken !== void 0 && (typeof refreshToken !== "string" || refreshToken.trim().length === 0)) {
8864
+ return false;
8865
+ }
8866
+ const scope = getOwnEntry4(value, "scope");
8867
+ return scope === void 0 || typeof scope === "string" && scope.trim().length > 0;
8868
+ }
8869
+ function isNonBlankOwnString(record, key2) {
8870
+ const value = getOwnString(record, key2);
8871
+ return value !== void 0 && value.trim().length > 0;
8872
+ }
8104
8873
 
8105
8874
  // ../mcp-oauth/src/client/default-oauth-client-provider.ts
8106
8875
  import { URL as URL2 } from "node:url";
@@ -8211,9 +8980,7 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
8211
8980
  } catch (error3) {
8212
8981
  res.writeHead(400);
8213
8982
  res.end(error3 instanceof Error ? error3.message : "Invalid OAuth callback");
8214
- if (callbackParameters.error === null) {
8215
- settle(() => reject(error3 instanceof Error ? error3 : new Error(String(error3))));
8216
- }
8983
+ settle(() => reject(error3 instanceof Error ? error3 : new Error(String(error3))));
8217
8984
  return;
8218
8985
  }
8219
8986
  const authorizationError = callbackParameters.error;
@@ -8225,7 +8992,10 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
8225
8992
  return;
8226
8993
  }
8227
8994
  try {
8228
- const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
8995
+ const code = validateAuthorizationCallbackParameters(
8996
+ callbackParameters,
8997
+ expectedAuthorization
8998
+ );
8229
8999
  res.writeHead(200, { "Content-Type": "text/html" });
8230
9000
  res.end(buildSuccessPage(options.landingPage));
8231
9001
  settle(() => resolve(code));
@@ -8248,7 +9018,10 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
8248
9018
  const description = callbackParameters.errorDescription ?? callbackParameters.error;
8249
9019
  throw createAuthorizationError(callbackParameters.error, description);
8250
9020
  }
8251
- const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
9021
+ const code = validateAuthorizationCallbackParameters(
9022
+ callbackParameters,
9023
+ expectedAuthorization
9024
+ );
8252
9025
  settle(() => resolve(code));
8253
9026
  } catch (error3) {
8254
9027
  settle(() => reject(error3 instanceof Error ? error3 : new Error(String(error3))));
@@ -8353,6 +9126,7 @@ function generateCodeChallenge(verifier) {
8353
9126
  }
8354
9127
 
8355
9128
  // ../mcp-oauth/src/client/token-endpoint.ts
9129
+ var MAX_JS_DATE_MS2 = 864e13;
8356
9130
  var OAuthError = class extends Error {
8357
9131
  error;
8358
9132
  errorDescription;
@@ -8430,22 +9204,32 @@ async function requestTokens(input) {
8430
9204
  if (typeof accessToken !== "string" || accessToken.trim().length === 0) {
8431
9205
  throw new Error("OAuth token response missing access_token");
8432
9206
  }
9207
+ const normalizedAccessToken = accessToken.trim();
8433
9208
  const tokenType = normalizeBearerTokenType(getOwnEntry6(payload, "token_type"));
8434
9209
  if (tokenType === null) {
8435
9210
  throw new Error("OAuth token response missing token_type=Bearer");
8436
9211
  }
8437
9212
  const expiresIn = getOwnEntry6(payload, "expires_in");
8438
- if (typeof expiresIn === "number" && Number.isFinite(expiresIn) && expiresIn < 0) {
8439
- throw new Error("OAuth token response has invalid expires_in");
9213
+ let expiresAt = null;
9214
+ if (expiresIn !== void 0) {
9215
+ if (typeof expiresIn !== "number" || !Number.isFinite(expiresIn) || !Number.isInteger(expiresIn) || expiresIn < 0) {
9216
+ throw new Error("OAuth token response has invalid expires_in");
9217
+ }
9218
+ expiresAt = input.now() + expiresIn * 1e3;
9219
+ if (!Number.isSafeInteger(expiresAt) || expiresAt > MAX_JS_DATE_MS2 || !Number.isFinite(new Date(expiresAt).getTime())) {
9220
+ throw new Error("OAuth token response has invalid expires_in");
9221
+ }
8440
9222
  }
8441
9223
  const refreshToken = getOwnEntry6(payload, "refresh_token");
8442
9224
  const scope = getOwnEntry6(payload, "scope");
9225
+ const normalizedRefreshToken = typeof refreshToken === "string" && refreshToken.trim().length > 0 ? refreshToken.trim() : void 0;
9226
+ const normalizedScope = typeof scope === "string" && scope.trim().length > 0 ? scope.trim() : void 0;
8443
9227
  return {
8444
- accessToken,
8445
- refreshToken: typeof refreshToken === "string" && refreshToken.length > 0 ? refreshToken : void 0,
9228
+ accessToken: normalizedAccessToken,
9229
+ refreshToken: normalizedRefreshToken === void 0 ? void 0 : normalizedRefreshToken,
8446
9230
  tokenType,
8447
- expiresAt: typeof expiresIn === "number" && Number.isFinite(expiresIn) ? input.now() + expiresIn * 1e3 : null,
8448
- scope: typeof scope === "string" && scope.length > 0 ? scope : void 0
9231
+ expiresAt,
9232
+ scope: normalizedScope === void 0 ? void 0 : normalizedScope
8449
9233
  };
8450
9234
  }
8451
9235
  async function readOAuthJsonObjectResponse(response) {
@@ -8496,6 +9280,7 @@ function normalizeBearerTokenType(value) {
8496
9280
  }
8497
9281
 
8498
9282
  // ../mcp-oauth/src/client/default-oauth-client-provider.ts
9283
+ var MAX_JS_DATE_MS3 = 864e13;
8499
9284
  function createOAuthClientProvider(options) {
8500
9285
  if (isProviderOptions(options)) {
8501
9286
  return options.provider;
@@ -8660,7 +9445,12 @@ function createDefaultOAuthClientProvider(options) {
8660
9445
  });
8661
9446
  let resolvedClient = null;
8662
9447
  try {
8663
- resolvedClient = await resolveClient(currentSession, discovery, loopback.redirectUri, fetch2);
9448
+ resolvedClient = await resolveClient(
9449
+ currentSession,
9450
+ discovery,
9451
+ loopback.redirectUri,
9452
+ fetch2
9453
+ );
8664
9454
  const sessionWithoutTokens = {
8665
9455
  resource,
8666
9456
  authorizationServer: discovery.authorizationServer,
@@ -8727,28 +9517,26 @@ function createDefaultOAuthClientProvider(options) {
8727
9517
  return finalPromise;
8728
9518
  }
8729
9519
  async function resolveClient(existingSession, discovery, redirectUri, fetch2) {
9520
+ const configuredClient = normalizeConfiguredClient(options.client);
8730
9521
  if (options.client.mode === "static") {
9522
+ if (configuredClient === null) {
9523
+ throw new Error("OAuth client_id must not be blank");
9524
+ }
8731
9525
  return {
8732
9526
  kind: "static",
8733
9527
  fromStoredRegistration: false,
8734
- client: {
8735
- clientId: options.client.clientId,
8736
- clientSecret: options.client.clientSecret
8737
- }
9528
+ client: configuredClient
8738
9529
  };
8739
9530
  }
8740
9531
  const registrationEndpoint = getOwnString2(
8741
9532
  discovery.authorizationServerMetadata,
8742
9533
  "registration_endpoint"
8743
9534
  );
8744
- if (registrationEndpoint === void 0 && options.client.clientId !== void 0) {
9535
+ if (registrationEndpoint === void 0 && configuredClient !== null) {
8745
9536
  return {
8746
9537
  kind: "static",
8747
9538
  fromStoredRegistration: false,
8748
- client: {
8749
- clientId: options.client.clientId,
8750
- clientSecret: options.client.clientSecret
8751
- }
9539
+ client: configuredClient
8752
9540
  };
8753
9541
  }
8754
9542
  const storedClient = await loadRegisteredClient(discovery.authorizationServer);
@@ -8770,7 +9558,7 @@ function createDefaultOAuthClientProvider(options) {
8770
9558
  throw new Error("Authorization server metadata is missing registration_endpoint");
8771
9559
  }
8772
9560
  if (existingSession !== null && existingSession.client.clientId.length > 0) {
8773
- const isConfiguredStaticFallback = options.client.clientId !== void 0 && existingSession.client.clientId === options.client.clientId && existingSession.client.clientSecret === options.client.clientSecret;
9561
+ const isConfiguredStaticFallback = configuredClient !== null && existingSession.client.clientId === configuredClient.clientId && existingSession.client.clientSecret === configuredClient.clientSecret;
8774
9562
  if (!isConfiguredStaticFallback) {
8775
9563
  await saveRegisteredClient(discovery.authorizationServer, existingSession.client);
8776
9564
  return {
@@ -8798,8 +9586,8 @@ function createDefaultOAuthClientProvider(options) {
8798
9586
  }
8799
9587
  const clientSecret = getOwnString2(payload, "client_secret");
8800
9588
  const registeredClient = {
8801
- clientId,
8802
- clientSecret: clientSecret !== void 0 && clientSecret.length > 0 ? clientSecret : void 0
9589
+ clientId: clientId.trim(),
9590
+ clientSecret: clientSecret !== void 0 && clientSecret.trim().length > 0 ? clientSecret.trim() : void 0
8803
9591
  };
8804
9592
  await saveRegisteredClient(discovery.authorizationServer, registeredClient);
8805
9593
  return {
@@ -8912,14 +9700,16 @@ function normalizeStoredClient(value) {
8912
9700
  if (clientId === void 0 || clientId.trim().length === 0) {
8913
9701
  return null;
8914
9702
  }
9703
+ const normalizedClientId = clientId.trim();
8915
9704
  const clientSecret = getOwnEntry7(value, "clientSecret");
8916
9705
  if (clientSecret === void 0) {
8917
- return { clientId };
9706
+ return { clientId: normalizedClientId };
8918
9707
  }
8919
9708
  if (typeof clientSecret !== "string" || clientSecret.trim().length === 0) {
8920
9709
  return null;
8921
9710
  }
8922
- return { clientId, clientSecret };
9711
+ const normalizedClientSecret = clientSecret.trim();
9712
+ return { clientId: normalizedClientId, clientSecret: normalizedClientSecret };
8923
9713
  }
8924
9714
  function normalizeStoredTokens(value) {
8925
9715
  if (value === void 0 || !isObjectRecord3(value)) {
@@ -8930,20 +9720,45 @@ function normalizeStoredTokens(value) {
8930
9720
  const expiresAt = getOwnEntry7(value, "expiresAt");
8931
9721
  const refreshToken = getOwnEntry7(value, "refreshToken");
8932
9722
  const scope = getOwnString2(value, "scope");
8933
- const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken : void 0;
8934
- if (accessToken === void 0 || accessToken.trim().length === 0 || tokenType !== "Bearer" || !(expiresAt === null || typeof expiresAt === "number" && Number.isFinite(expiresAt)) || refreshToken !== void 0 && (typeof refreshToken !== "string" || refreshToken.trim().length === 0)) {
9723
+ const normalizedAccessToken = accessToken?.trim();
9724
+ const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken.trim() : void 0;
9725
+ const normalizedScope = scope?.trim();
9726
+ if (accessToken === void 0 || normalizedAccessToken === void 0 || normalizedAccessToken.length === 0 || tokenType !== "Bearer" || !(expiresAt === null || typeof expiresAt === "number" && Number.isSafeInteger(expiresAt) && expiresAt <= MAX_JS_DATE_MS3 && Number.isFinite(new Date(expiresAt).getTime())) || refreshToken !== void 0 && (typeof refreshToken !== "string" || normalizedRefreshToken === void 0 || normalizedRefreshToken.length === 0)) {
8935
9727
  return void 0;
8936
9728
  }
8937
9729
  return {
8938
- accessToken,
9730
+ accessToken: normalizedAccessToken,
8939
9731
  tokenType,
8940
9732
  expiresAt,
8941
9733
  ...normalizedRefreshToken === void 0 ? {} : { refreshToken: normalizedRefreshToken },
8942
- ...scope === void 0 || scope.length === 0 ? {} : { scope }
9734
+ ...normalizedScope === void 0 || normalizedScope.length === 0 ? {} : { scope: normalizedScope }
9735
+ };
9736
+ }
9737
+ function getClientMetadata(client) {
9738
+ if (client.metadata === void 0) {
9739
+ return void 0;
9740
+ }
9741
+ return {
9742
+ clientName: normalizeOptionalOAuthString(client.metadata.clientName),
9743
+ scope: normalizeOptionalOAuthString(client.metadata.scope),
9744
+ softwareId: normalizeOptionalOAuthString(client.metadata.softwareId),
9745
+ softwareVersion: normalizeOptionalOAuthString(client.metadata.softwareVersion)
8943
9746
  };
8944
9747
  }
8945
- function getClientMetadata(client) {
8946
- return client.metadata;
9748
+ function normalizeConfiguredClient(client) {
9749
+ const clientId = normalizeOptionalOAuthString(client.clientId);
9750
+ if (clientId === void 0) {
9751
+ return null;
9752
+ }
9753
+ const clientSecret = normalizeOptionalOAuthString(client.clientSecret);
9754
+ return clientSecret === void 0 ? { clientId } : { clientId, clientSecret };
9755
+ }
9756
+ function normalizeOptionalOAuthString(value) {
9757
+ if (value === void 0) {
9758
+ return void 0;
9759
+ }
9760
+ const trimmed = value.trim();
9761
+ return trimmed.length === 0 ? void 0 : trimmed;
8947
9762
  }
8948
9763
  function getOwnEntry7(record, key2) {
8949
9764
  return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
@@ -8972,11 +9787,7 @@ function buildAuthorizationUrl(input) {
8972
9787
  "authorization_endpoint",
8973
9788
  "Authorization server metadata"
8974
9789
  );
8975
- const issuer = requireOwnString(
8976
- input.metadata,
8977
- "issuer",
8978
- "Authorization server metadata"
8979
- );
9790
+ const issuer = requireOwnString(input.metadata, "issuer", "Authorization server metadata");
8980
9791
  const url = new URL2(authorizationEndpoint);
8981
9792
  const resource = canonicalizeResourceIndicator(input.resource);
8982
9793
  const state = createAuthorizationState({
@@ -9584,7 +10395,7 @@ var McpClient = class {
9584
10395
  await onToolsChanged();
9585
10396
  });
9586
10397
  messageLayer.onNotification("notifications/resources/list_changed", async () => {
9587
- if (onResourcesChanged === void 0) {
10398
+ if (onResourcesChanged === void 0 || this.currentServerCapabilities?.resources?.listChanged !== true) {
9588
10399
  return;
9589
10400
  }
9590
10401
  await onResourcesChanged();
@@ -9603,7 +10414,7 @@ var McpClient = class {
9603
10414
  await onResourceUpdated(uri);
9604
10415
  });
9605
10416
  messageLayer.onNotification("notifications/prompts/list_changed", async () => {
9606
- if (onPromptsChanged === void 0) {
10417
+ if (onPromptsChanged === void 0 || this.currentServerCapabilities?.prompts?.listChanged !== true) {
9607
10418
  return;
9608
10419
  }
9609
10420
  await onPromptsChanged();
@@ -9834,7 +10645,11 @@ var McpClient = class {
9834
10645
  throw new Error("Server does not support resources");
9835
10646
  }
9836
10647
  const requestParams = params17.cursor === void 0 ? void 0 : { cursor: params17.cursor };
9837
- return await messageLayer.sendRequest("resources/list", requestParams);
10648
+ const result = await messageLayer.sendRequest("resources/list", requestParams);
10649
+ if (!isResourcesListResult(result)) {
10650
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid resources/list result");
10651
+ }
10652
+ return result;
9838
10653
  }
9839
10654
  async listResourceTemplates(params17 = {}) {
9840
10655
  const messageLayer = this.getMessageLayerOrThrow();
@@ -9843,7 +10658,11 @@ var McpClient = class {
9843
10658
  throw new Error("Server does not support resources");
9844
10659
  }
9845
10660
  const requestParams = params17.cursor === void 0 ? void 0 : { cursor: params17.cursor };
9846
- return await messageLayer.sendRequest("resources/templates/list", requestParams);
10661
+ const result = await messageLayer.sendRequest("resources/templates/list", requestParams);
10662
+ if (!isResourceTemplatesListResult(result)) {
10663
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid resources/templates/list result");
10664
+ }
10665
+ return result;
9847
10666
  }
9848
10667
  async readResource(params17) {
9849
10668
  const messageLayer = this.getMessageLayerOrThrow();
@@ -9851,7 +10670,11 @@ var McpClient = class {
9851
10670
  if (serverCapabilities.resources === void 0) {
9852
10671
  throw new Error("Server does not support resources");
9853
10672
  }
9854
- return await messageLayer.sendRequest("resources/read", params17);
10673
+ const result = await messageLayer.sendRequest("resources/read", params17);
10674
+ if (!isReadResourceResult(result)) {
10675
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid resources/read result");
10676
+ }
10677
+ return result;
9855
10678
  }
9856
10679
  async subscribe(uri) {
9857
10680
  const messageLayer = this.getMessageLayerOrThrow();
@@ -9886,7 +10709,11 @@ var McpClient = class {
9886
10709
  if (serverCapabilities.prompts === void 0) {
9887
10710
  throw new Error("Server does not support prompts");
9888
10711
  }
9889
- return await messageLayer.sendRequest("prompts/get", params17);
10712
+ const result = await messageLayer.sendRequest("prompts/get", params17);
10713
+ if (!isGetPromptResult(result)) {
10714
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid prompts/get result");
10715
+ }
10716
+ return result;
9890
10717
  }
9891
10718
  async complete(params17) {
9892
10719
  const messageLayer = this.getMessageLayerOrThrow();
@@ -9894,7 +10721,11 @@ var McpClient = class {
9894
10721
  if (serverCapabilities.completions === void 0) {
9895
10722
  throw new Error("Server does not support completions");
9896
10723
  }
9897
- return await messageLayer.sendRequest("completion/complete", params17);
10724
+ const result = await messageLayer.sendRequest("completion/complete", params17);
10725
+ if (!isCompleteResult(result)) {
10726
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid completion/complete result");
10727
+ }
10728
+ return result;
9898
10729
  }
9899
10730
  async setLogLevel(level) {
9900
10731
  const messageLayer = this.getMessageLayerOrThrow();
@@ -10885,6 +11716,44 @@ function isCallToolResult(value) {
10885
11716
  function isToolsListResult(value) {
10886
11717
  return isObjectRecord5(value) && Array.isArray(value.tools) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
10887
11718
  }
11719
+ function isResourcesListResult(value) {
11720
+ return isObjectRecord5(value) && Array.isArray(value.resources) && value.resources.every(isResource) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
11721
+ }
11722
+ function isResourceTemplatesListResult(value) {
11723
+ return isObjectRecord5(value) && Array.isArray(value.resourceTemplates) && value.resourceTemplates.every(isResourceTemplate) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
11724
+ }
11725
+ function isReadResourceResult(value) {
11726
+ return isObjectRecord5(value) && Array.isArray(value.contents) && value.contents.every(isResourceContents);
11727
+ }
11728
+ function isGetPromptResult(value) {
11729
+ return isObjectRecord5(value) && (value.description === void 0 || typeof value.description === "string") && Array.isArray(value.messages) && value.messages.every(isPromptMessage);
11730
+ }
11731
+ function isCompleteResult(value) {
11732
+ return isObjectRecord5(value) && isObjectRecord5(value.completion) && Array.isArray(value.completion.values) && value.completion.values.every((candidate) => typeof candidate === "string") && (value.completion.hasMore === void 0 || typeof value.completion.hasMore === "boolean") && (value.completion.total === void 0 || typeof value.completion.total === "number");
11733
+ }
11734
+ function isResource(value) {
11735
+ return isObjectRecord5(value) && typeof value.uri === "string" && typeof value.name === "string" && (value.description === void 0 || typeof value.description === "string") && (value.mimeType === void 0 || typeof value.mimeType === "string") && (value.size === void 0 || typeof value.size === "number");
11736
+ }
11737
+ function isResourceTemplate(value) {
11738
+ return isObjectRecord5(value) && typeof value.uriTemplate === "string" && typeof value.name === "string" && (value.description === void 0 || typeof value.description === "string") && (value.mimeType === void 0 || typeof value.mimeType === "string");
11739
+ }
11740
+ function isResourceContents(value) {
11741
+ if (!isObjectRecord5(value) || typeof value.uri !== "string") {
11742
+ return false;
11743
+ }
11744
+ if (value.mimeType !== void 0 && typeof value.mimeType !== "string") {
11745
+ return false;
11746
+ }
11747
+ const hasText = value.text !== void 0;
11748
+ const hasBlob = value.blob !== void 0;
11749
+ if (!hasText && !hasBlob) {
11750
+ return false;
11751
+ }
11752
+ return (!hasText || typeof value.text === "string") && (!hasBlob || typeof value.blob === "string");
11753
+ }
11754
+ function isPromptMessage(value) {
11755
+ return isObjectRecord5(value) && (value.role === "user" || value.role === "assistant") && isContentItem(value.content);
11756
+ }
10888
11757
  function isContentItem(value) {
10889
11758
  if (!isObjectRecord5(value)) {
10890
11759
  return false;
@@ -10898,7 +11767,7 @@ function isContentItem(value) {
10898
11767
  if (value.type !== "resource" || !isObjectRecord5(value.resource)) {
10899
11768
  return false;
10900
11769
  }
10901
- return typeof value.resource.uri === "string" && (value.resource.mimeType === void 0 || typeof value.resource.mimeType === "string") && (typeof value.resource.text === "string" || typeof value.resource.blob === "string");
11770
+ return isResourceContents(value.resource);
10902
11771
  }
10903
11772
  function hasOwn(value, property) {
10904
11773
  return Object.prototype.hasOwnProperty.call(value, property);
@@ -11038,13 +11907,13 @@ function convertJsonSchema(schema) {
11038
11907
  }
11039
11908
  return convertSchema(schema, schema, []);
11040
11909
  }
11041
- function convertSchema(schema, root, path24) {
11042
- const resolvedSchema = resolveReferencedSchema(schema, root, path24);
11910
+ function convertSchema(schema, root, path25) {
11911
+ const resolvedSchema = resolveReferencedSchema(schema, root, path25);
11043
11912
  const normalizedSchema = normalizeNullability(resolvedSchema);
11044
11913
  const composition = getComposition(normalizedSchema.schema);
11045
11914
  if (Array.isArray(normalizedSchema.schema.type)) {
11046
11915
  throw new Error(
11047
- `JSON Schema "${formatJsonSchemaPath(path24)}" has an unsupported type "${formatJsonSchemaType(
11916
+ `JSON Schema "${formatJsonSchemaPath(path25)}" has an unsupported type "${formatJsonSchemaType(
11048
11917
  normalizedSchema.schema.type
11049
11918
  )}". Supported: string, number, integer, boolean, array, object.`
11050
11919
  );
@@ -11056,13 +11925,13 @@ function convertSchema(schema, root, path24) {
11056
11925
  return convertEnumSchema(resolvedSchema, normalizedSchema.nullable);
11057
11926
  }
11058
11927
  if (composition !== void 0) {
11059
- return convertCompositionSchema(normalizedSchema.schema, root, normalizedSchema.nullable, path24);
11928
+ return convertCompositionSchema(normalizedSchema.schema, root, normalizedSchema.nullable, path25);
11060
11929
  }
11061
11930
  if (isRecordSchema(normalizedSchema.schema)) {
11062
11931
  return applyMetadata(
11063
11932
  S.Record(
11064
11933
  convertSchema(normalizedSchema.schema.additionalProperties, root, [
11065
- ...path24,
11934
+ ...path25,
11066
11935
  "additionalProperties"
11067
11936
  ])
11068
11937
  ),
@@ -11111,12 +11980,12 @@ function convertSchema(schema, root, path24) {
11111
11980
  if (normalizedSchema.schema.items === void 0) {
11112
11981
  throw new Error(
11113
11982
  `JSON Schema "${formatJsonSchemaPath(
11114
- path24
11983
+ path25
11115
11984
  )}" is an array but is missing the "items" field. Add "items": { ... } to declare the element type.`
11116
11985
  );
11117
11986
  }
11118
11987
  return S.Array(
11119
- convertSchema(normalizedSchema.schema.items, root, [...path24, "items"]),
11988
+ convertSchema(normalizedSchema.schema.items, root, [...path25, "items"]),
11120
11989
  createCommonOptions(
11121
11990
  normalizedSchema.schema,
11122
11991
  normalizedSchema.nullable,
@@ -11126,7 +11995,7 @@ function convertSchema(schema, root, path24) {
11126
11995
  case "object":
11127
11996
  return convertObjectSchema(normalizedSchema.schema, root, {
11128
11997
  nullable: normalizedSchema.nullable,
11129
- path: path24
11998
+ path: path25
11130
11999
  });
11131
12000
  case "null":
11132
12001
  return applyMetadata(S.Json(), normalizedSchema.schema, {
@@ -11141,12 +12010,12 @@ function convertSchema(schema, root, path24) {
11141
12010
  }
11142
12011
  throw new Error(
11143
12012
  `JSON Schema "${formatJsonSchemaPath(
11144
- path24
12013
+ path25
11145
12014
  )}" must declare one of: "type", "enum", "const", "oneOf", "anyOf", or "allOf".`
11146
12015
  );
11147
12016
  }
11148
12017
  throw new Error(
11149
- `JSON Schema "${formatJsonSchemaPath(path24)}" has an unsupported type "${formatJsonSchemaType(
12018
+ `JSON Schema "${formatJsonSchemaPath(path25)}" has an unsupported type "${formatJsonSchemaType(
11150
12019
  normalizedSchema.schema.type
11151
12020
  )}". Supported: string, number, integer, boolean, array, object.`
11152
12021
  );
@@ -11190,21 +12059,21 @@ function convertEnumSchema(schema, nullable) {
11190
12059
  )
11191
12060
  });
11192
12061
  }
11193
- function convertCompositionSchema(schema, root, nullable, path24) {
12062
+ function convertCompositionSchema(schema, root, nullable, path25) {
11194
12063
  const composition = getComposition(schema);
11195
12064
  const branchSchemas = composition?.branches ?? [];
11196
12065
  const keyword = composition?.keyword ?? "oneOf";
11197
12066
  const branches = branchSchemas.map(
11198
- (branch, index) => resolveReferencedSchema(branch, root, [...path24, keyword, String(index)])
12067
+ (branch, index) => resolveReferencedSchema(branch, root, [...path25, keyword, String(index)])
11199
12068
  );
11200
- const discriminator = findDiscriminator(branches, root, path24);
12069
+ const discriminator = findDiscriminator(branches, root, path25);
11201
12070
  if (discriminator !== void 0) {
11202
12071
  const convertedBranches = Object.fromEntries(
11203
12072
  branches.map((branch, index) => [
11204
12073
  getDiscriminatorLiteral(branch, discriminator, root),
11205
12074
  convertObjectSchema(branch, root, {
11206
12075
  omitProperty: discriminator,
11207
- path: [...path24, keyword, String(index)]
12076
+ path: [...path25, keyword, String(index)]
11208
12077
  })
11209
12078
  ])
11210
12079
  );
@@ -11223,7 +12092,7 @@ function convertCompositionSchema(schema, root, nullable, path24) {
11223
12092
  S.Union(
11224
12093
  branches.map(
11225
12094
  (branch, index) => convertObjectSchema(branch, root, {
11226
- path: [...path24, keyword, String(index)]
12095
+ path: [...path25, keyword, String(index)]
11227
12096
  })
11228
12097
  )
11229
12098
  ),
@@ -11337,11 +12206,11 @@ function getComposition(schema) {
11337
12206
  }
11338
12207
  return void 0;
11339
12208
  }
11340
- function formatJsonSchemaPath(path24) {
11341
- if (path24.length === 0) {
12209
+ function formatJsonSchemaPath(path25) {
12210
+ if (path25.length === 0) {
11342
12211
  return "#";
11343
12212
  }
11344
- return `#/${path24.map(escapeJsonPointerSegment).join("/")}`;
12213
+ return `#/${path25.map(escapeJsonPointerSegment).join("/")}`;
11345
12214
  }
11346
12215
  function formatJsonSchemaType(type2) {
11347
12216
  return Array.isArray(type2) ? JSON.stringify(type2) : String(type2);
@@ -11357,11 +12226,11 @@ function isRecordSchema(schema) {
11357
12226
  const propertyKeys = Object.keys(schema.properties ?? {});
11358
12227
  return schema.type === "object" && propertyKeys.length === 0 && typeof schema.additionalProperties === "object" && schema.additionalProperties !== null;
11359
12228
  }
11360
- function findDiscriminator(branches, root, path24) {
12229
+ function findDiscriminator(branches, root, path25) {
11361
12230
  const [firstBranch] = branches;
11362
12231
  if (firstBranch === void 0) {
11363
12232
  throw new Error(
11364
- `JSON Schema "${formatJsonSchemaPath(path24)}" uses oneOf/anyOf/allOf but has no branches.`
12233
+ `JSON Schema "${formatJsonSchemaPath(path25)}" uses oneOf/anyOf/allOf but has no branches.`
11365
12234
  );
11366
12235
  }
11367
12236
  const candidateKeys = Object.keys(firstBranch.properties ?? {});
@@ -11401,19 +12270,19 @@ function getDiscriminatorLiteral(branch, key2, root) {
11401
12270
  }
11402
12271
  return void 0;
11403
12272
  }
11404
- function resolveReferencedSchema(schema, root, path24) {
12273
+ function resolveReferencedSchema(schema, root, path25) {
11405
12274
  if (schema.$ref === void 0) {
11406
12275
  return schema;
11407
12276
  }
11408
12277
  const resolvedTarget = resolveLocalRef(root, schema.$ref);
11409
12278
  if (resolvedTarget === void 0) {
11410
12279
  throw new Error(
11411
- `JSON Schema "${formatJsonSchemaPath(path24)}" uses "$ref": ${schema.$ref}. toolcraft only supports internal refs like "#/components/schemas/Foo".`
12280
+ `JSON Schema "${formatJsonSchemaPath(path25)}" uses "$ref": ${schema.$ref}. toolcraft only supports internal refs like "#/components/schemas/Foo".`
11412
12281
  );
11413
12282
  }
11414
12283
  const { $ref: ignoredRef, ...siblingKeywords } = schema;
11415
12284
  void ignoredRef;
11416
- const resolvedSchema = resolveReferencedSchema(resolvedTarget, root, path24);
12285
+ const resolvedSchema = resolveReferencedSchema(resolvedTarget, root, path25);
11417
12286
  if (Object.keys(siblingKeywords).length === 0) {
11418
12287
  return resolvedSchema;
11419
12288
  }
@@ -11437,9 +12306,9 @@ function mergeJsonSchemas(base, overlay) {
11437
12306
  ...mergedRequired === void 0 ? {} : { required: mergedRequired }
11438
12307
  };
11439
12308
  }
11440
- function hasSelfReferencingRef(schema, root, path24 = "#", activePaths = /* @__PURE__ */ new Set()) {
12309
+ function hasSelfReferencingRef(schema, root, path25 = "#", activePaths = /* @__PURE__ */ new Set()) {
11441
12310
  const nextActivePaths = new Set(activePaths);
11442
- nextActivePaths.add(path24);
12311
+ nextActivePaths.add(path25);
11443
12312
  const localRefPath = getLocalRefPath(schema.$ref);
11444
12313
  if (localRefPath !== void 0) {
11445
12314
  if (nextActivePaths.has(localRefPath)) {
@@ -11450,13 +12319,13 @@ function hasSelfReferencingRef(schema, root, path24 = "#", activePaths = /* @__P
11450
12319
  return true;
11451
12320
  }
11452
12321
  }
11453
- if (schema.items !== void 0 && hasSelfReferencingRef(schema.items, root, `${path24}/items`, nextActivePaths)) {
12322
+ if (schema.items !== void 0 && hasSelfReferencingRef(schema.items, root, `${path25}/items`, nextActivePaths)) {
11454
12323
  return true;
11455
12324
  }
11456
12325
  if (typeof schema.additionalProperties === "object" && schema.additionalProperties !== null && hasSelfReferencingRef(
11457
12326
  schema.additionalProperties,
11458
12327
  root,
11459
- `${path24}/additionalProperties`,
12328
+ `${path25}/additionalProperties`,
11460
12329
  nextActivePaths
11461
12330
  )) {
11462
12331
  return true;
@@ -11465,7 +12334,7 @@ function hasSelfReferencingRef(schema, root, path24 = "#", activePaths = /* @__P
11465
12334
  if (hasSelfReferencingRef(
11466
12335
  childSchema,
11467
12336
  root,
11468
- `${path24}/properties/${escapeJsonPointerSegment(key2)}`,
12337
+ `${path25}/properties/${escapeJsonPointerSegment(key2)}`,
11469
12338
  nextActivePaths
11470
12339
  )) {
11471
12340
  return true;
@@ -11475,24 +12344,24 @@ function hasSelfReferencingRef(schema, root, path24 = "#", activePaths = /* @__P
11475
12344
  if (hasSelfReferencingRef(
11476
12345
  childSchema,
11477
12346
  root,
11478
- `${path24}/$defs/${escapeJsonPointerSegment(key2)}`,
12347
+ `${path25}/$defs/${escapeJsonPointerSegment(key2)}`,
11479
12348
  nextActivePaths
11480
12349
  )) {
11481
12350
  return true;
11482
12351
  }
11483
12352
  }
11484
12353
  for (const [index, childSchema] of (schema.oneOf ?? []).entries()) {
11485
- if (hasSelfReferencingRef(childSchema, root, `${path24}/oneOf/${index}`, nextActivePaths)) {
12354
+ if (hasSelfReferencingRef(childSchema, root, `${path25}/oneOf/${index}`, nextActivePaths)) {
11486
12355
  return true;
11487
12356
  }
11488
12357
  }
11489
12358
  for (const [index, childSchema] of (schema.anyOf ?? []).entries()) {
11490
- if (hasSelfReferencingRef(childSchema, root, `${path24}/anyOf/${index}`, nextActivePaths)) {
12359
+ if (hasSelfReferencingRef(childSchema, root, `${path25}/anyOf/${index}`, nextActivePaths)) {
11491
12360
  return true;
11492
12361
  }
11493
12362
  }
11494
12363
  for (const [index, childSchema] of (schema.allOf ?? []).entries()) {
11495
- if (hasSelfReferencingRef(childSchema, root, `${path24}/allOf/${index}`, nextActivePaths)) {
12364
+ if (hasSelfReferencingRef(childSchema, root, `${path25}/allOf/${index}`, nextActivePaths)) {
11496
12365
  return true;
11497
12366
  }
11498
12367
  }
@@ -11508,14 +12377,14 @@ function getLocalRefPath(ref) {
11508
12377
  return ref.startsWith("#/") ? ref : void 0;
11509
12378
  }
11510
12379
  function resolveLocalRef(root, ref) {
11511
- const path24 = getLocalRefPath(ref);
11512
- if (path24 === void 0) {
12380
+ const path25 = getLocalRefPath(ref);
12381
+ if (path25 === void 0) {
11513
12382
  return void 0;
11514
12383
  }
11515
- if (path24 === "#") {
12384
+ if (path25 === "#") {
11516
12385
  return root;
11517
12386
  }
11518
- const segments = path24.slice(2).split("/").map(unescapeJsonPointerSegment);
12387
+ const segments = path25.slice(2).split("/").map(unescapeJsonPointerSegment);
11519
12388
  let current = root;
11520
12389
  for (const segment of segments) {
11521
12390
  if (Array.isArray(current)) {
@@ -11561,15 +12430,15 @@ function getBooleanDefault(value) {
11561
12430
  return typeof value === "boolean" ? value : void 0;
11562
12431
  }
11563
12432
  function getArrayDefault(value) {
11564
- return Array.isArray(value) && value.every((item) => isJsonValue(item)) ? value : void 0;
12433
+ return Array.isArray(value) && value.every((item) => isJsonValue2(item)) ? value : void 0;
11565
12434
  }
11566
12435
  function getPrimitiveEnumDefault(value, candidates) {
11567
12436
  return isPrimitiveEnumValue(value) && candidates.includes(value) ? value : void 0;
11568
12437
  }
11569
12438
  function getJsonDefault(value) {
11570
- return isJsonValue(value) ? value : void 0;
12439
+ return isJsonValue2(value) ? value : void 0;
11571
12440
  }
11572
- function isJsonValue(value) {
12441
+ function isJsonValue2(value) {
11573
12442
  if (value === null) {
11574
12443
  return true;
11575
12444
  }
@@ -11577,12 +12446,12 @@ function isJsonValue(value) {
11577
12446
  return true;
11578
12447
  }
11579
12448
  if (Array.isArray(value)) {
11580
- return value.every((item) => isJsonValue(item));
12449
+ return value.every((item) => isJsonValue2(item));
11581
12450
  }
11582
12451
  if (!isPlainObject(value)) {
11583
12452
  return false;
11584
12453
  }
11585
- return Object.values(value).every((item) => isJsonValue(item));
12454
+ return Object.values(value).every((item) => isJsonValue2(item));
11586
12455
  }
11587
12456
  function isPlainObject(value) {
11588
12457
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -11677,6 +12546,7 @@ function createProxyCommand(parent, tool, commandName, connection) {
11677
12546
  kind: "command",
11678
12547
  name: commandName,
11679
12548
  description: tool.description,
12549
+ hidden: false,
11680
12550
  examples: [],
11681
12551
  aliases: [],
11682
12552
  positional: [],
@@ -11772,7 +12642,7 @@ async function ensureConnected(connection) {
11772
12642
  async function readCache(cachePath) {
11773
12643
  try {
11774
12644
  await assertCachePathHasNoSymlinks(cachePath);
11775
- const raw = await readFile3(cachePath, "utf8");
12645
+ const raw = await readFile4(cachePath, "utf8");
11776
12646
  const parsed = JSON.parse(raw);
11777
12647
  if (parsed === null || typeof parsed !== "object" || !Array.isArray(parsed.tools) || parsed.upstream === void 0 || typeof parsed.upstream.name !== "string" || typeof parsed.upstream.version !== "string") {
11778
12648
  return void 0;
@@ -11793,7 +12663,7 @@ async function readCache(cachePath) {
11793
12663
  }
11794
12664
  }
11795
12665
  async function writeCache(cachePath, cache) {
11796
- const directory = path12.dirname(cachePath);
12666
+ const directory = path13.dirname(cachePath);
11797
12667
  const tempPath = `${cachePath}.tmp-${randomUUID4()}`;
11798
12668
  let tempCreated = false;
11799
12669
  await assertCachePathHasNoSymlinks(cachePath);
@@ -11990,13 +12860,13 @@ function collectProxyGroups(root) {
11990
12860
  function findProjectRoot(from = process.cwd()) {
11991
12861
  let current = process.cwd();
11992
12862
  if (from !== current) {
11993
- current = path12.resolve(from);
12863
+ current = path13.resolve(from);
11994
12864
  }
11995
12865
  while (true) {
11996
- if (existsSync2(path12.join(current, "package.json"))) {
12866
+ if (existsSync2(path13.join(current, "package.json"))) {
11997
12867
  return current;
11998
12868
  }
11999
- const parent = path12.dirname(current);
12869
+ const parent = path13.dirname(current);
12000
12870
  if (parent === current) {
12001
12871
  return void 0;
12002
12872
  }
@@ -12013,7 +12883,7 @@ function resolveCachePath(name, projectRoot) {
12013
12883
  if (name.length === 0 || name === "." || name === ".." || name.includes("/") || name.includes("\\")) {
12014
12884
  throw new Error(`MCP proxy group name must be a file-safe name: "${name}".`);
12015
12885
  }
12016
- return path12.join(resolvedProjectRoot, ".toolcraft", "mcp", `${name}.json`);
12886
+ return path13.join(resolvedProjectRoot, ".toolcraft", "mcp", `${name}.json`);
12017
12887
  }
12018
12888
  async function assertCachePathHasNoSymlinks(filePath) {
12019
12889
  let currentPath = filePath;
@@ -12027,10 +12897,10 @@ async function assertCachePathHasNoSymlinks(filePath) {
12027
12897
  throw error3;
12028
12898
  }
12029
12899
  }
12030
- if (path12.basename(currentPath) === ".toolcraft") {
12900
+ if (path13.basename(currentPath) === ".toolcraft") {
12031
12901
  return;
12032
12902
  }
12033
- const parentPath = path12.dirname(currentPath);
12903
+ const parentPath = path13.dirname(currentPath);
12034
12904
  if (parentPath === currentPath) {
12035
12905
  return;
12036
12906
  }
@@ -12176,20 +13046,20 @@ function reportsEnabled(option, env) {
12176
13046
  function resolveReportDir(option, projectRoot) {
12177
13047
  const configuredDir = typeof option === "object" ? option.dir : void 0;
12178
13048
  if (configuredDir === void 0 || configuredDir.length === 0) {
12179
- return path13.join(projectRoot, ".toolcraft", "errors");
13049
+ return path14.join(projectRoot, ".toolcraft", "errors");
12180
13050
  }
12181
- return path13.isAbsolute(configuredDir) ? configuredDir : path13.join(projectRoot, configuredDir);
13051
+ return path14.isAbsolute(configuredDir) ? configuredDir : path14.join(projectRoot, configuredDir);
12182
13052
  }
12183
13053
  function reportDirMustStayWithinProject(option) {
12184
13054
  const configuredDir = typeof option === "object" ? option.dir : void 0;
12185
- return configuredDir === void 0 || configuredDir.length === 0 || !path13.isAbsolute(configuredDir);
13055
+ return configuredDir === void 0 || configuredDir.length === 0 || !path14.isAbsolute(configuredDir);
12186
13056
  }
12187
13057
  function isWithinDirectory(parent, child) {
12188
- const relative = path13.relative(parent, child);
12189
- return relative === "" || !path13.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path13.sep}`);
13058
+ const relative = path14.relative(parent, child);
13059
+ return relative === "" || !path14.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path14.sep}`);
12190
13060
  }
12191
13061
  async function assertReportDirWithinProject(projectRoot, reportDir) {
12192
- if (!isWithinDirectory(path13.resolve(projectRoot), path13.resolve(reportDir))) {
13062
+ if (!isWithinDirectory(path14.resolve(projectRoot), path14.resolve(reportDir))) {
12193
13063
  throw new Error("Error report directory resolves outside project root.");
12194
13064
  }
12195
13065
  const [canonicalProjectRoot, canonicalReportDir] = await Promise.all([
@@ -12240,7 +13110,7 @@ function slugifyCommandPath(commandPath) {
12240
13110
  return output.length === 0 ? "root" : output;
12241
13111
  }
12242
13112
  function relativeDisplayPath(projectRoot, absolutePath) {
12243
- const relative = path13.relative(projectRoot, absolutePath);
13113
+ const relative = path14.relative(projectRoot, absolutePath);
12244
13114
  return relative.length === 0 || relative.startsWith("..") ? absolutePath : relative;
12245
13115
  }
12246
13116
  function redactValue(value) {
@@ -12560,7 +13430,7 @@ async function writeErrorReport(context) {
12560
13430
  const projectRoot = resolveProjectRoot(context.projectRoot);
12561
13431
  const reportDir = resolveReportDir(context.errorReports, projectRoot);
12562
13432
  const fileName = `${formatTimestamp(/* @__PURE__ */ new Date())}-${slugifyCommandPath(context.commandPath)}-${randomUUID5()}.log`;
12563
- const absolutePath = path13.join(reportDir, fileName);
13433
+ const absolutePath = path14.join(reportDir, fileName);
12564
13434
  await mkdir2(reportDir, { recursive: true });
12565
13435
  if (reportDirMustStayWithinProject(context.errorReports)) {
12566
13436
  await assertReportDirWithinProject(projectRoot, reportDir);
@@ -13030,7 +13900,7 @@ function inferProgramName(argv) {
13030
13900
  if (typeof entrypoint !== "string" || entrypoint.length === 0) {
13031
13901
  return "toolcraft";
13032
13902
  }
13033
- const parsed = path14.parse(entrypoint);
13903
+ const parsed = path15.parse(entrypoint);
13034
13904
  return parsed.name.length > 0 ? parsed.name : "toolcraft";
13035
13905
  }
13036
13906
  function normalizeRoots(roots, argv) {
@@ -13088,11 +13958,11 @@ function formatSegment(segment, casing) {
13088
13958
  const separator = casing === "snake" ? "_" : "-";
13089
13959
  return splitWords3(segment).join(separator);
13090
13960
  }
13091
- function toOptionFlag(path24, casing) {
13092
- return `--${path24.map((segment) => formatSegment(segment, casing)).join(".")}`;
13961
+ function toOptionFlag(path25, casing) {
13962
+ return `--${path25.map((segment) => formatSegment(segment, casing)).join(".")}`;
13093
13963
  }
13094
- function toOptionAttribute(path24, casing) {
13095
- return path24.map((segment) => {
13964
+ function toOptionAttribute(path25, casing) {
13965
+ return path25.map((segment) => {
13096
13966
  const formatted = formatSegment(segment, casing);
13097
13967
  if (casing === "snake") {
13098
13968
  return formatted;
@@ -13103,23 +13973,23 @@ function toOptionAttribute(path24, casing) {
13103
13973
  ).join("");
13104
13974
  }).join(".");
13105
13975
  }
13106
- function toDisplayPath(path24) {
13107
- return path24.join(".");
13976
+ function toDisplayPath(path25) {
13977
+ return path25.join(".");
13108
13978
  }
13109
- function toUnionKindControlPath(path24) {
13110
- if (path24.length === 0) {
13979
+ function toUnionKindControlPath(path25) {
13980
+ if (path25.length === 0) {
13111
13981
  return ["kind"];
13112
13982
  }
13113
- const head = path24.slice(0, -1);
13114
- const tail = path24[path24.length - 1] ?? "";
13983
+ const head = path25.slice(0, -1);
13984
+ const tail = path25[path25.length - 1] ?? "";
13115
13985
  return [...head, `${tail}Kind`];
13116
13986
  }
13117
- function toUnionKindDisplayPath(path24) {
13118
- if (path24.length === 0) {
13987
+ function toUnionKindDisplayPath(path25) {
13988
+ if (path25.length === 0) {
13119
13989
  return "kind";
13120
13990
  }
13121
- const head = path24.slice(0, -1);
13122
- const tail = path24[path24.length - 1] ?? "";
13991
+ const head = path25.slice(0, -1);
13992
+ const tail = path25[path25.length - 1] ?? "";
13123
13993
  return [...head, `${tail}-kind`].join(".");
13124
13994
  }
13125
13995
  function createSyntheticEnumSchema(values) {
@@ -13135,14 +14005,14 @@ function getRequiredBranchFingerprint(branch, casing) {
13135
14005
  const requiredKeys = Object.entries(branch.shape).filter(([, schema]) => schema.kind !== "optional").map(([key2]) => formatSegment(key2, casing)).sort();
13136
14006
  return requiredKeys.join("+");
13137
14007
  }
13138
- function collectFields(schema, casing, globalLongOptionFlags, path24 = [], inheritedOptional = false, variantContext) {
14008
+ function collectFields(schema, casing, globalLongOptionFlags, path25 = [], inheritedOptional = false, variantContext) {
13139
14009
  const collected = {
13140
14010
  dynamicFields: [],
13141
14011
  fields: [],
13142
14012
  variants: []
13143
14013
  };
13144
14014
  for (const [key2, rawChildSchema] of Object.entries(schema.shape)) {
13145
- const nextPath = [...path24, key2];
14015
+ const nextPath = [...path25, key2];
13146
14016
  const runtimeOptional = inheritedOptional || rawChildSchema.kind === "optional";
13147
14017
  const childSchema = unwrapOptional2(rawChildSchema);
13148
14018
  const requiredWhenActive = rawChildSchema.kind !== "optional" && childSchema.default === void 0;
@@ -13328,9 +14198,9 @@ function collectFields(schema, casing, globalLongOptionFlags, path24 = [], inher
13328
14198
  }
13329
14199
  return collected;
13330
14200
  }
13331
- function toCommanderOptionAttribute(path24, casing, globalLongOptionFlags) {
13332
- const optionAttribute = toOptionAttribute(path24, casing);
13333
- const optionFlag = toOptionFlag(path24, casing);
14201
+ function toCommanderOptionAttribute(path25, casing, globalLongOptionFlags) {
14202
+ const optionAttribute = toOptionAttribute(path25, casing);
14203
+ const optionFlag = toOptionFlag(path25, casing);
13334
14204
  if (!globalLongOptionFlags.has(optionFlag)) {
13335
14205
  return optionAttribute;
13336
14206
  }
@@ -13603,6 +14473,20 @@ function parseArrayValue(value, schema, label) {
13603
14473
  (item) => parseScalarValue(item, itemSchema, label)
13604
14474
  );
13605
14475
  }
14476
+ function isNegativeNumericArrayToken(token, schema) {
14477
+ if (!token.startsWith("-") || token.startsWith("--")) {
14478
+ return false;
14479
+ }
14480
+ const itemSchema = unwrapOptional2(schema.item);
14481
+ if (itemSchema.kind !== "number") {
14482
+ return false;
14483
+ }
14484
+ const items = splitArrayInput(token);
14485
+ return items.length > 0 && items.every((item) => isValidNumberSchemaValue(Number(item), itemSchema));
14486
+ }
14487
+ function isNextArrayOptionToken(token, schema) {
14488
+ return token.startsWith("-") && !isNegativeNumericArrayToken(token, schema);
14489
+ }
13606
14490
  function validateArrayBounds(value, schema, label) {
13607
14491
  if (schema.minItems !== void 0 && value.length < schema.minItems) {
13608
14492
  throw new UserError(
@@ -13742,6 +14626,14 @@ function isNodeVisibleInScope(node, scope) {
13742
14626
  function getVisibleChildren(group, scope) {
13743
14627
  return group.children.filter((child) => isNodeVisibleInScope(child, scope));
13744
14628
  }
14629
+ function getHelpChildren(group, scope) {
14630
+ return getVisibleChildren(group, scope).filter((child) => {
14631
+ if (child.kind === "command") {
14632
+ return child.hidden !== true;
14633
+ }
14634
+ return true;
14635
+ });
14636
+ }
13745
14637
  function findVisibleChild(group, token, scope) {
13746
14638
  return getVisibleChildren(group, scope).find(
13747
14639
  (child) => child.name === token || child.aliases.includes(token)
@@ -13888,6 +14780,26 @@ function describeHelpValueToken(schema, field) {
13888
14780
  }
13889
14781
  return describeFieldNameValueToken(field.displayPath, field.optionFlag) ?? "value";
13890
14782
  }
14783
+ function formatCompactEnumSignatureToken(schema) {
14784
+ if (schema.kind !== "enum" || schema.values.length < 2 || schema.values.length > 3) {
14785
+ return void 0;
14786
+ }
14787
+ const tokens = schema.values.map((value) => String(value));
14788
+ const compact = tokens.every(
14789
+ (token) => token.length > 0 && token.length <= 24 && token.trim() === token && !token.includes("|") && !token.includes(" ") && !token.includes("\n") && !token.includes("\r") && !token.includes(" ")
14790
+ );
14791
+ return compact ? tokens.join("|") : void 0;
14792
+ }
14793
+ function formatCommandParameterFieldFlags(field, globalLongOptionFlags) {
14794
+ if (field.positionalIndex !== void 0 || field.schema.kind === "boolean") {
14795
+ return formatHelpFieldFlags(field, globalLongOptionFlags);
14796
+ }
14797
+ const enumToken = formatCompactEnumSignatureToken(field.schema);
14798
+ if (enumToken !== void 0) {
14799
+ return `${formatOptionFlags(field, globalLongOptionFlags)} ${enumToken}`;
14800
+ }
14801
+ return formatHelpFieldFlags(field, globalLongOptionFlags);
14802
+ }
13891
14803
  function describeDynamicFieldType(field) {
13892
14804
  if (field.schema.kind === "record") {
13893
14805
  const valueSchema = unwrapOptional2(field.schema.value);
@@ -14055,7 +14967,7 @@ function formatCommandParameterTokens(command, casing, globalLongOptionFlags) {
14055
14967
  const fields = assignPositionals(collected.fields, command.positional);
14056
14968
  return fields.filter((field) => field.global !== true).map(
14057
14969
  (field) => wrapOptionalCommandParameterToken(
14058
- formatHelpFieldFlags(field, globalLongOptionFlags),
14970
+ formatCommandParameterFieldFlags(field, globalLongOptionFlags),
14059
14971
  field.positionalIndex === void 0 && (field.optional || field.hasDefault)
14060
14972
  )
14061
14973
  ).concat(
@@ -14069,7 +14981,7 @@ function formatCommandRowName(node, casing, globalLongOptionFlags) {
14069
14981
  return name;
14070
14982
  }
14071
14983
  function formatCommandRows(group, scope, casing, globalLongOptionFlags) {
14072
- return getVisibleChildren(group, scope).map((child) => ({
14984
+ return getHelpChildren(group, scope).map((child) => ({
14073
14985
  name: formatCommandRowName(child, casing, globalLongOptionFlags),
14074
14986
  description: child.description ?? ""
14075
14987
  }));
@@ -14113,7 +15025,7 @@ function collectSchemaGlobalFieldRows(group, scope, casing, globalLongOptionFlag
14113
15025
  }
14114
15026
  return;
14115
15027
  }
14116
- for (const child of getVisibleChildren(node, scope)) {
15028
+ for (const child of getHelpChildren(node, scope)) {
14117
15029
  visit(child);
14118
15030
  }
14119
15031
  };
@@ -14136,6 +15048,17 @@ function buildUsageLine(breadcrumb, rootUsageName, suffix) {
14136
15048
  const tokens = [rootUsageName, subPath, suffix].filter((segment) => segment.length > 0);
14137
15049
  return tokens.join(" ");
14138
15050
  }
15051
+ function formatGroupUsageSuffix(group, scope, casing, globalLongOptionFlags) {
15052
+ if (group.default !== void 0 && group.default.hidden === true && group.default.scope.includes(scope)) {
15053
+ const parameterTokens = formatCommandParameterTokens(
15054
+ group.default,
15055
+ casing,
15056
+ globalLongOptionFlags
15057
+ );
15058
+ return ["[command]", "[OPTIONS]", ...parameterTokens].join(" ");
15059
+ }
15060
+ return "[command] [OPTIONS]";
15061
+ }
14139
15062
  function renderGroupHelp(group, breadcrumb, scope, casing, globalOptions, rootUsageName, isRoot) {
14140
15063
  const sections = [];
14141
15064
  const globalLongOptionFlags = getGlobalLongOptionFlags(
@@ -14169,7 +15092,11 @@ ${builtInLine}`
14169
15092
  return renderHelpDocument({
14170
15093
  breadcrumb,
14171
15094
  rootUsageName,
14172
- usageLine: buildUsageLine(breadcrumb, rootUsageName, "[command] [OPTIONS]"),
15095
+ usageLine: buildUsageLine(
15096
+ breadcrumb,
15097
+ rootUsageName,
15098
+ formatGroupUsageSuffix(group, scope, casing, globalLongOptionFlags)
15099
+ ),
14173
15100
  description: group.description,
14174
15101
  requiresAuth: group.requires?.auth === true,
14175
15102
  sections
@@ -14278,6 +15205,8 @@ function createNodeCommand(node, casing, globalLongOptionFlags, execute, presets
14278
15205
  return null;
14279
15206
  }
14280
15207
  const command = new CommanderCommand(node.name);
15208
+ Reflect.set(command, "_toolcraftHidden", node.hidden);
15209
+ Reflect.set(command, "_toolcraftOriginalName", node.name);
14281
15210
  const collected = collectFields(node.params, casing, globalLongOptionFlags);
14282
15211
  const fields = assignPositionals(collected.fields, node.positional);
14283
15212
  validateUniqueOptionFlags(fields, globalLongOptionFlags);
@@ -14321,6 +15250,7 @@ function createNodeCommand(node, casing, globalLongOptionFlags, execute, presets
14321
15250
  if (!isNodeVisibleInScope(node, "cli")) {
14322
15251
  return null;
14323
15252
  }
15253
+ const reservedChildNames = node.children.filter((child) => !isNodeVisibleInScope(child, "cli")).flatMap((child) => getNodeCommandNames(child));
14324
15254
  const visibleChildren = node.children.map(
14325
15255
  (child) => createNodeCommand(
14326
15256
  child,
@@ -14333,6 +15263,7 @@ function createNodeCommand(node, casing, globalLongOptionFlags, execute, presets
14333
15263
  )
14334
15264
  ).filter((child) => child !== null);
14335
15265
  const group = new CommanderCommand(node.name);
15266
+ Reflect.set(group, "_toolcraftReservedChildNames", reservedChildNames);
14336
15267
  if (node.description !== void 0) {
14337
15268
  group.description(node.description);
14338
15269
  }
@@ -14347,7 +15278,7 @@ function createNodeCommand(node, casing, globalLongOptionFlags, execute, presets
14347
15278
  return group;
14348
15279
  }
14349
15280
  function addCommanderChild(parent, child, isDefault, siblingNames) {
14350
- if (isDefault && child.name().length === 0) {
15281
+ if (isDefault && (child.name().length === 0 || isToolcraftHiddenCommander(child))) {
14351
15282
  let internalName = "__toolcraft_default__";
14352
15283
  let suffix = 2;
14353
15284
  while (siblingNames.has(internalName)) {
@@ -14355,10 +15286,37 @@ function addCommanderChild(parent, child, isDefault, siblingNames) {
14355
15286
  suffix += 1;
14356
15287
  }
14357
15288
  child.name(internalName);
15289
+ Reflect.set(
15290
+ parent,
15291
+ "_toolcraftHiddenDefaultNames",
15292
+ getToolcraftHiddenDefaultNames(parent).concat([
15293
+ ...new Set([Reflect.get(child, "_toolcraftOriginalName"), ...child.aliases()].filter(
15294
+ (name) => typeof name === "string" && name.length > 0
15295
+ ))
15296
+ ])
15297
+ );
14358
15298
  parent.addCommand(child, { hidden: true, isDefault: true });
14359
15299
  return;
14360
15300
  }
14361
- parent.addCommand(child, isDefault ? { isDefault: true } : void 0);
15301
+ const options = {
15302
+ ...isDefault ? { isDefault: true } : {},
15303
+ ...isToolcraftHiddenCommander(child) ? { hidden: true } : {}
15304
+ };
15305
+ parent.addCommand(child, Object.keys(options).length > 0 ? options : void 0);
15306
+ }
15307
+ function isToolcraftHiddenCommander(command) {
15308
+ return Reflect.get(command, "_toolcraftHidden") === true;
15309
+ }
15310
+ function getToolcraftHiddenDefaultNames(command) {
15311
+ const value = Reflect.get(command, "_toolcraftHiddenDefaultNames");
15312
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
15313
+ }
15314
+ function getToolcraftReservedChildNames(command) {
15315
+ const value = Reflect.get(command, "_toolcraftReservedChildNames");
15316
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
15317
+ }
15318
+ function getNodeCommandNames(node) {
15319
+ return [node.name, ...node.aliases].filter((name) => name.length > 0);
14362
15320
  }
14363
15321
  function addGlobalOptions(command, presetsEnabled, controls) {
14364
15322
  const options = [];
@@ -14410,10 +15368,10 @@ function parseDebugStackMode(value) {
14410
15368
  formatInvalidEnumMessage("--debug", String(value), ["raw"], { candidates: ["raw"] })
14411
15369
  );
14412
15370
  }
14413
- function setNestedValue(target, path24, value) {
15371
+ function setNestedValue(target, path25, value) {
14414
15372
  let cursor2 = target;
14415
- for (let index = 0; index < path24.length - 1; index += 1) {
14416
- const segment = path24[index] ?? "";
15373
+ for (let index = 0; index < path25.length - 1; index += 1) {
15374
+ const segment = path25[index] ?? "";
14417
15375
  const existing = Object.prototype.hasOwnProperty.call(cursor2, segment) ? cursor2[segment] : void 0;
14418
15376
  if (typeof existing === "object" && existing !== null) {
14419
15377
  cursor2 = existing;
@@ -14428,7 +15386,7 @@ function setNestedValue(target, path24, value) {
14428
15386
  });
14429
15387
  cursor2 = next;
14430
15388
  }
14431
- const leaf = path24[path24.length - 1];
15389
+ const leaf = path25[path25.length - 1];
14432
15390
  if (leaf !== void 0) {
14433
15391
  Object.defineProperty(cursor2, leaf, {
14434
15392
  value,
@@ -14520,6 +15478,37 @@ function resolveOutput(resolvedFlags) {
14520
15478
  }
14521
15479
  return "rich";
14522
15480
  }
15481
+ function resolveOutputFromArgv(argv) {
15482
+ for (let index = 0; index < argv.length; index += 1) {
15483
+ const token = argv[index] ?? "";
15484
+ if (token === "--json") {
15485
+ return "json";
15486
+ }
15487
+ if (token === "--md" || token === "--markdown") {
15488
+ return "md";
15489
+ }
15490
+ if (token === "--output") {
15491
+ const value = argv[index + 1];
15492
+ if (value === "rich" || value === "md" || value === "json") {
15493
+ return value;
15494
+ }
15495
+ if (value === "markdown") {
15496
+ return "md";
15497
+ }
15498
+ continue;
15499
+ }
15500
+ if (token.startsWith("--output=")) {
15501
+ const value = token.slice("--output=".length);
15502
+ if (value === "rich" || value === "md" || value === "json") {
15503
+ return value;
15504
+ }
15505
+ if (value === "markdown") {
15506
+ return "md";
15507
+ }
15508
+ }
15509
+ }
15510
+ return "rich";
15511
+ }
14523
15512
  var DESIGN_SYSTEM_OUTPUT_BY_MODE = {
14524
15513
  rich: "terminal",
14525
15514
  md: "markdown",
@@ -14545,21 +15534,21 @@ async function withOutputFormat2(output, fn) {
14545
15534
  }
14546
15535
  function createFs2() {
14547
15536
  return {
14548
- readFile: async (path24, encoding = "utf8") => readFile4(path24, { encoding }),
14549
- writeFile: async (path24, contents, options) => {
14550
- await writeFile5(path24, contents, options);
15537
+ readFile: async (path25, encoding = "utf8") => readFile5(path25, { encoding }),
15538
+ writeFile: async (path25, contents, options) => {
15539
+ await writeFile5(path25, contents, options);
14551
15540
  },
14552
- exists: async (path24) => {
15541
+ exists: async (path25) => {
14553
15542
  try {
14554
- await access2(path24);
15543
+ await access2(path25);
14555
15544
  return true;
14556
15545
  } catch {
14557
15546
  return false;
14558
15547
  }
14559
15548
  },
14560
- lstat: async (path24) => lstat3(path24),
15549
+ lstat: async (path25) => lstat3(path25),
14561
15550
  rename: async (fromPath, toPath) => rename3(fromPath, toPath),
14562
- unlink: async (path24) => unlink3(path24)
15551
+ unlink: async (path25) => unlink3(path25)
14563
15552
  };
14564
15553
  }
14565
15554
  function createEnv2(values = process.env) {
@@ -14575,9 +15564,9 @@ function isPlainObject4(value) {
14575
15564
  function hasFieldValue(value) {
14576
15565
  return value !== void 0;
14577
15566
  }
14578
- function hasNestedField(fields, path24) {
15567
+ function hasNestedField(fields, path25) {
14579
15568
  return fields.some(
14580
- (field) => path24.length < field.path.length && path24.every((segment, index) => field.path[index] === segment)
15569
+ (field) => path25.length < field.path.length && path25.every((segment, index) => field.path[index] === segment)
14581
15570
  );
14582
15571
  }
14583
15572
  function describeExpectedPresetValue(schema) {
@@ -14680,7 +15669,7 @@ function validatePresetFieldValue(value, field, presetPath) {
14680
15669
  async function loadPresetValues(fields, presetPath) {
14681
15670
  let rawPreset;
14682
15671
  try {
14683
- rawPreset = await readFile4(presetPath, {
15672
+ rawPreset = await readFile5(presetPath, {
14684
15673
  encoding: "utf8"
14685
15674
  });
14686
15675
  } catch (error3) {
@@ -14706,9 +15695,9 @@ async function loadPresetValues(fields, presetPath) {
14706
15695
  }
14707
15696
  const fieldByPath = new Map(fields.map((field) => [field.displayPath, field]));
14708
15697
  const presetValues = {};
14709
- function visitObject(current, path24) {
15698
+ function visitObject(current, path25) {
14710
15699
  for (const [key2, value] of Object.entries(current)) {
14711
- const nextPath = [...path24, key2];
15700
+ const nextPath = [...path25, key2];
14712
15701
  const displayPath = toDisplayPath(nextPath);
14713
15702
  const field = fieldByPath.get(displayPath);
14714
15703
  if (field !== void 0) {
@@ -14915,8 +15904,8 @@ function createFixtureService(definition) {
14915
15904
  );
14916
15905
  }
14917
15906
  function resolveFixturePath(commandPath) {
14918
- const parsed = path14.parse(commandPath);
14919
- return path14.join(parsed.dir, `${parsed.name}.fixture.json`);
15907
+ const parsed = path15.parse(commandPath);
15908
+ return path15.join(parsed.dir, `${parsed.name}.fixture.json`);
14920
15909
  }
14921
15910
  function selectFixtureScenario(scenarios, selector, fixturePath) {
14922
15911
  if (isNumericFixtureSelector(selector)) {
@@ -14947,7 +15936,7 @@ async function loadFixtureScenario(command, selector) {
14947
15936
  const fixturePath = resolveFixturePath(commandPath);
14948
15937
  let rawFixture;
14949
15938
  try {
14950
- rawFixture = await readFile4(fixturePath, {
15939
+ rawFixture = await readFile5(fixturePath, {
14951
15940
  encoding: "utf8"
14952
15941
  });
14953
15942
  } catch {
@@ -15041,6 +16030,44 @@ function renderApprovalDeclined(error3) {
15041
16030
  logger2.error(error3.message);
15042
16031
  process.exitCode = 1;
15043
16032
  }
16033
+ function renderCliErrorPattern(pattern) {
16034
+ const logger2 = createLogger();
16035
+ if (pattern.kind === "usage") {
16036
+ logger2.error(
16037
+ appendUsagePointer(pattern.message, {
16038
+ rootUsageName: pattern.rootUsageName,
16039
+ commandPath: pattern.commandPath
16040
+ })
16041
+ );
16042
+ process.exitCode = 1;
16043
+ return;
16044
+ }
16045
+ if (pattern.kind === "runtime-user") {
16046
+ logger2.error(pattern.message);
16047
+ process.exitCode = 1;
16048
+ return;
16049
+ }
16050
+ if (pattern.kind === "toolcraft-bug") {
16051
+ logger2.error(
16052
+ `toolcraft hit an internal invariant: ${pattern.error.message}
16053
+ This is a bug in toolcraft or in the command definition; it cannot be worked around by changing argv. Re-run with --debug for a stack trace and file an issue.`
16054
+ );
16055
+ if (pattern.debugStackMode !== void 0 && pattern.error.stack) {
16056
+ process.stderr.write(`${formatDebugStack(pattern.error.stack, pattern.debugStackMode)}
16057
+ `);
16058
+ }
16059
+ process.exitCode = 1;
16060
+ return;
16061
+ }
16062
+ logger2.error(
16063
+ pattern.debugStackMode !== void 0 ? pattern.message : `${pattern.message} Use --debug for a stack trace.`
16064
+ );
16065
+ if (pattern.debugStackMode !== void 0 && pattern.stack !== void 0) {
16066
+ process.stderr.write(`${formatDebugStack(pattern.stack, pattern.debugStackMode)}
16067
+ `);
16068
+ }
16069
+ process.exitCode = 1;
16070
+ }
15044
16071
  function validateServices(services) {
15045
16072
  for (const name of Object.keys(services)) {
15046
16073
  if (RESERVED_SERVICE_NAMES.has(name)) {
@@ -15050,8 +16077,8 @@ function validateServices(services) {
15050
16077
  }
15051
16078
  }
15052
16079
  }
15053
- function getNestedValue(target, path24) {
15054
- return path24.reduce(
16080
+ function getNestedValue(target, path25) {
16081
+ return path25.reduce(
15055
16082
  (current, segment) => current !== null && typeof current === "object" ? current[segment] : void 0,
15056
16083
  target
15057
16084
  );
@@ -15136,7 +16163,7 @@ function consumeFieldValue(args, index, schema, label, inlineValue) {
15136
16163
  let cursor2 = index + 1;
15137
16164
  while (cursor2 < args.length) {
15138
16165
  const token = args[cursor2] ?? "";
15139
- if (token.startsWith("-")) {
16166
+ if (isNextArrayOptionToken(token, schema)) {
15140
16167
  break;
15141
16168
  }
15142
16169
  const parsed = parseArrayValue(token, schema, label);
@@ -15961,73 +16988,82 @@ function renderHttpError(error3, options) {
15961
16988
  `);
15962
16989
  }
15963
16990
  }
15964
- function handleRunError(error3, options) {
16991
+ async function handleRunError(error3, options) {
15965
16992
  const logger2 = createLogger();
15966
- if (error3 instanceof UserError) {
15967
- logger2.error(
15968
- appendUsagePointer(error3.message, {
15969
- rootUsageName: options.rootUsageName,
15970
- commandPath: options.commandPath
15971
- })
15972
- );
15973
- process.exitCode = 1;
15974
- return;
15975
- }
15976
- if (error3 instanceof Error && error3.name === "ToolcraftBugError") {
15977
- logger2.error(
15978
- `toolcraft hit an internal invariant: ${error3.message}
15979
- This is a bug in toolcraft or in the command definition; it cannot be worked around by changing argv. Re-run with --debug for a stack trace and file an issue.`
15980
- );
15981
- if (options.debugStackMode !== void 0 && error3.stack) {
15982
- process.stderr.write(`${formatDebugStack(error3.stack, options.debugStackMode)}
15983
- `);
15984
- }
15985
- process.exitCode = 1;
15986
- return;
15987
- }
15988
- if (error3 instanceof CommanderError2) {
15989
- process.exitCode = error3.exitCode;
15990
- if (error3.code === "commander.helpDisplayed" || error3.code === "commander.version") {
16993
+ await withOutputFormat2(options.output, async () => {
16994
+ if (error3 instanceof UserError) {
16995
+ renderCliErrorPattern(
16996
+ options.userErrorPattern === "usage" ? {
16997
+ kind: "usage",
16998
+ message: error3.message,
16999
+ rootUsageName: options.rootUsageName,
17000
+ commandPath: options.commandPath
17001
+ } : {
17002
+ kind: "runtime-user",
17003
+ message: error3.message
17004
+ }
17005
+ );
15991
17006
  return;
15992
17007
  }
15993
- if (error3.code === "commander.unknownCommand") {
15994
- logger2.error(
15995
- appendUsagePointer(
15996
- formatUnknownCommandError(error3, options.program, options.argv ?? process.argv),
15997
- {
15998
- rootUsageName: options.rootUsageName,
15999
- commandPath: options.commandPath
16000
- }
16001
- )
16002
- );
17008
+ if (error3 instanceof Error && error3.name === "ToolcraftBugError") {
17009
+ renderCliErrorPattern({
17010
+ kind: "toolcraft-bug",
17011
+ error: error3,
17012
+ debugStackMode: options.debugStackMode
17013
+ });
16003
17014
  return;
16004
17015
  }
16005
- if (error3.code === "commander.unknownOption") {
16006
- const argv = options.argv ?? process.argv;
17016
+ if (error3 instanceof CommanderError2) {
17017
+ process.exitCode = error3.exitCode;
17018
+ if (error3.code === "commander.helpDisplayed" || error3.code === "commander.version") {
17019
+ return;
17020
+ }
17021
+ if (error3.code === "commander.unknownCommand") {
17022
+ logger2.error(
17023
+ appendUsagePointer(
17024
+ formatUnknownCommandError(error3, options.program, options.argv ?? process.argv),
17025
+ {
17026
+ rootUsageName: options.rootUsageName,
17027
+ commandPath: options.commandPath
17028
+ }
17029
+ )
17030
+ );
17031
+ return;
17032
+ }
17033
+ if (error3.code === "commander.unknownOption") {
17034
+ const argv = options.argv ?? process.argv;
17035
+ logger2.error(
17036
+ appendUsagePointer(formatUnknownOptionError(error3, options.program, argv), {
17037
+ rootUsageName: options.rootUsageName,
17038
+ commandPath: options.commandPath.length > 0 ? options.commandPath : findCurrentCommanderCommandPath(options.program, argv)
17039
+ })
17040
+ );
17041
+ return;
17042
+ }
16007
17043
  logger2.error(
16008
- appendUsagePointer(formatUnknownOptionError(error3, options.program, argv), {
17044
+ appendUsagePointer(formatCommanderErrorMessage(error3), {
16009
17045
  rootUsageName: options.rootUsageName,
16010
- commandPath: options.commandPath.length > 0 ? options.commandPath : findCurrentCommanderCommandPath(options.program, argv)
17046
+ commandPath: options.commandPath.length > 0 ? options.commandPath : findCurrentCommanderCommandPath(options.program, options.argv ?? process.argv)
16011
17047
  })
16012
17048
  );
16013
17049
  return;
16014
17050
  }
16015
- return;
16016
- }
16017
- if (isHttpErrorLike(error3)) {
16018
- renderHttpError(error3, options);
16019
- process.exitCode = 1;
16020
- return;
16021
- }
16022
- const message2 = error3 instanceof Error ? error3.message : String(error3);
16023
- logger2.error(
16024
- options.debugStackMode !== void 0 ? message2 : `${message2} Use --debug for a stack trace.`
16025
- );
16026
- if (options.debugStackMode !== void 0 && error3 instanceof Error && error3.stack) {
16027
- process.stderr.write(`${formatDebugStack(error3.stack, options.debugStackMode)}
16028
- `);
16029
- }
16030
- process.exitCode = 1;
17051
+ if (isHttpErrorLike(error3)) {
17052
+ renderHttpError(error3, options);
17053
+ process.exitCode = 1;
17054
+ return;
17055
+ }
17056
+ const message2 = error3 instanceof Error ? error3.message : String(error3);
17057
+ renderCliErrorPattern({
17058
+ kind: "unexpected",
17059
+ message: message2,
17060
+ stack: error3 instanceof Error ? error3.stack : void 0,
17061
+ debugStackMode: options.debugStackMode
17062
+ });
17063
+ });
17064
+ }
17065
+ function formatCommanderErrorMessage(error3) {
17066
+ return error3.message.startsWith("error:") ? error3.message : `error: ${error3.message}`;
16031
17067
  }
16032
17068
  function formatInvalidEnumMessage(label, value, values, opts = {}) {
16033
17069
  const suggestions = suggest(
@@ -16188,6 +17224,13 @@ function findUnknownCommanderCommand(program, argv) {
16188
17224
  }
16189
17225
  continue;
16190
17226
  }
17227
+ if (getToolcraftHiddenDefaultNames(current).includes(token) || getToolcraftReservedChildNames(current).includes(token)) {
17228
+ return {
17229
+ input: token,
17230
+ currentCommand: current,
17231
+ commandPath: pathSegments.join(" ")
17232
+ };
17233
+ }
16191
17234
  if (current.commands.length === 0 || getDefaultCommanderCommandName(current) !== void 0) {
16192
17235
  return void 0;
16193
17236
  }
@@ -16262,6 +17305,11 @@ async function runCLI(roots, options = {}) {
16262
17305
  if (version !== void 0) {
16263
17306
  program.version(version, "--version");
16264
17307
  }
17308
+ Reflect.set(
17309
+ program,
17310
+ "_toolcraftReservedChildNames",
17311
+ root.children.filter((child) => !isNodeVisibleInScope(child, "cli")).flatMap((child) => getNodeCommandNames(child))
17312
+ );
16265
17313
  let lastActionCommand;
16266
17314
  let resolvedCommandPath = "";
16267
17315
  let errorReportContext;
@@ -16336,13 +17384,15 @@ async function runCLI(roots, options = {}) {
16336
17384
  process.stderr.write(`Saved error report to ${report.displayPath}
16337
17385
  `);
16338
17386
  }
16339
- handleRunError(error3, {
17387
+ await handleRunError(error3, {
16340
17388
  debugStackMode: resolvedFlags !== void 0 ? resolveDebugStackMode(resolvedFlags.debug) : getDebugStackModeFromArgv(process.argv),
17389
+ output: resolvedFlags !== void 0 ? resolveOutput(resolvedFlags) : resolveOutputFromArgv(process.argv),
16341
17390
  verbose: resolvedFlags ? Boolean(resolvedFlags.verbose) : process.argv.includes("--verbose"),
16342
17391
  program,
16343
17392
  argv: process.argv,
16344
17393
  rootUsageName,
16345
- commandPath: resolvedCommandPath
17394
+ commandPath: resolvedCommandPath,
17395
+ userErrorPattern: errorReportContext?.params === void 0 ? "usage" : "runtime-user"
16346
17396
  });
16347
17397
  }
16348
17398
  }
@@ -16353,7 +17403,7 @@ import { randomUUID as randomUUID6 } from "node:crypto";
16353
17403
  // src/terminal-session.ts
16354
17404
  import { EventEmitter as EventEmitter2 } from "node:events";
16355
17405
  import { accessSync, chmodSync, constants } from "node:fs";
16356
- import { createRequire } from "node:module";
17406
+ import { createRequire as createRequire2 } from "node:module";
16357
17407
  import { dirname, join } from "node:path";
16358
17408
  import * as nodePty from "node-pty";
16359
17409
 
@@ -17492,8 +18542,8 @@ var spawnHelperChecked = false;
17492
18542
  function ensureSpawnHelperExecutable() {
17493
18543
  if (spawnHelperChecked) return;
17494
18544
  spawnHelperChecked = true;
17495
- const require3 = createRequire(import.meta.url);
17496
- const nodePtyDir = dirname(require3.resolve("node-pty"));
18545
+ const require4 = createRequire2(import.meta.url);
18546
+ const nodePtyDir = dirname(require4.resolve("node-pty"));
17497
18547
  const helper = join(nodePtyDir, "..", "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper");
17498
18548
  try {
17499
18549
  accessSync(helper, constants.X_OK);
@@ -17913,7 +18963,7 @@ var getSession = defineCommand({
17913
18963
 
17914
18964
  // ../agent-skill-config/src/configs.ts
17915
18965
  import os2 from "node:os";
17916
- import path15 from "node:path";
18966
+ import path16 from "node:path";
17917
18967
 
17918
18968
  // ../agent-defs/src/agents/claude-code.ts
17919
18969
  var claudeCodeAgent = {
@@ -18277,7 +19327,7 @@ var templateMutation = {
18277
19327
 
18278
19328
  // ../config-mutations/src/execution/apply-mutation.ts
18279
19329
  import { randomUUID as randomUUID7 } from "node:crypto";
18280
- import path17 from "node:path";
19330
+ import path18 from "node:path";
18281
19331
 
18282
19332
  // ../config-mutations/src/formats/json.ts
18283
19333
  import * as jsonc from "jsonc-parser";
@@ -18400,22 +19450,22 @@ function prune(obj, shape) {
18400
19450
  }
18401
19451
  return { changed, result };
18402
19452
  }
18403
- function modifyAtPath(content, path24, value) {
19453
+ function modifyAtPath(content, path25, value) {
18404
19454
  const indent = detectIndent(content);
18405
19455
  const formattingOptions = {
18406
19456
  tabSize: indent === " " ? 1 : indent.length,
18407
19457
  insertSpaces: indent !== " ",
18408
19458
  eol: "\n"
18409
19459
  };
18410
- const edits = jsonc.modify(content, path24, value, { formattingOptions });
19460
+ const edits = jsonc.modify(content, path25, value, { formattingOptions });
18411
19461
  let result = jsonc.applyEdits(content, edits);
18412
19462
  if (!result.endsWith("\n")) {
18413
19463
  result += "\n";
18414
19464
  }
18415
19465
  return result;
18416
19466
  }
18417
- function removeAtPath(content, path24) {
18418
- return modifyAtPath(content, path24, void 0);
19467
+ function removeAtPath(content, path25) {
19468
+ return modifyAtPath(content, path25, void 0);
18419
19469
  }
18420
19470
  function serializeUpdate(content, current, next) {
18421
19471
  let result = content || "{}";
@@ -18425,15 +19475,15 @@ function serializeUpdate(content, current, next) {
18425
19475
  }
18426
19476
  return result;
18427
19477
  }
18428
- function applyObjectUpdate(content, path24, current, next) {
19478
+ function applyObjectUpdate(content, path25, current, next) {
18429
19479
  let result = content;
18430
19480
  for (const key2 of Object.keys(current)) {
18431
19481
  if (!hasConfigEntry(next, key2)) {
18432
- result = removeAtPath(result, [...path24, key2]);
19482
+ result = removeAtPath(result, [...path25, key2]);
18433
19483
  }
18434
19484
  }
18435
19485
  for (const [key2, nextValue] of Object.entries(next)) {
18436
- const nextPath = [...path24, key2];
19486
+ const nextPath = [...path25, key2];
18437
19487
  const hasCurrent = hasConfigEntry(current, key2);
18438
19488
  const currentValue = hasCurrent ? current[key2] : void 0;
18439
19489
  if (hasCurrent && isConfigObject(currentValue) && isConfigObject(nextValue)) {
@@ -18633,20 +19683,20 @@ function getConfigFormat(pathOrFormat) {
18633
19683
  }
18634
19684
  return formatRegistry[formatName];
18635
19685
  }
18636
- function detectFormat(path24) {
18637
- const ext = getExtension(path24);
19686
+ function detectFormat(path25) {
19687
+ const ext = getExtension(path25);
18638
19688
  return extensionMap[ext];
18639
19689
  }
18640
- function getExtension(path24) {
18641
- const lastDot = path24.lastIndexOf(".");
19690
+ function getExtension(path25) {
19691
+ const lastDot = path25.lastIndexOf(".");
18642
19692
  if (lastDot === -1) {
18643
19693
  return "";
18644
19694
  }
18645
- return path24.slice(lastDot).toLowerCase();
19695
+ return path25.slice(lastDot).toLowerCase();
18646
19696
  }
18647
19697
 
18648
19698
  // ../config-mutations/src/execution/path-utils.ts
18649
- import path16 from "node:path";
19699
+ import path17 from "node:path";
18650
19700
  function expandHome(targetPath, homeDir) {
18651
19701
  if (!targetPath?.startsWith("~")) {
18652
19702
  return targetPath;
@@ -18663,7 +19713,7 @@ function expandHome(targetPath, homeDir) {
18663
19713
  remainder = remainder.slice(1);
18664
19714
  }
18665
19715
  }
18666
- return remainder.length === 0 ? homeDir : path16.join(homeDir, remainder);
19716
+ return remainder.length === 0 ? homeDir : path17.join(homeDir, remainder);
18667
19717
  }
18668
19718
  function validateHomePath(targetPath) {
18669
19719
  if (typeof targetPath !== "string" || targetPath.length === 0) {
@@ -18678,21 +19728,21 @@ function validateHomePath(targetPath) {
18678
19728
  function resolvePath(rawPath, homeDir, pathMapper) {
18679
19729
  validateHomePath(rawPath);
18680
19730
  const expanded = expandHome(rawPath, homeDir);
18681
- const canonicalHome = path16.resolve(homeDir);
18682
- const canonicalExpanded = path16.resolve(expanded);
18683
- const relative = path16.relative(canonicalHome, canonicalExpanded);
18684
- if (relative === ".." || relative.startsWith(`..${path16.sep}`) || path16.isAbsolute(relative)) {
19731
+ const canonicalHome = path17.resolve(homeDir);
19732
+ const canonicalExpanded = path17.resolve(expanded);
19733
+ const relative = path17.relative(canonicalHome, canonicalExpanded);
19734
+ if (relative === ".." || relative.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative)) {
18685
19735
  throw new Error(`Target path resolves outside home directory: "${rawPath}"`);
18686
19736
  }
18687
19737
  if (!pathMapper) {
18688
19738
  return canonicalExpanded;
18689
19739
  }
18690
- const rawDirectory = path16.dirname(expanded);
19740
+ const rawDirectory = path17.dirname(expanded);
18691
19741
  const mappedDirectory = pathMapper.mapTargetDirectory({
18692
19742
  targetDirectory: rawDirectory
18693
19743
  });
18694
- const filename = path16.basename(expanded);
18695
- return filename.length === 0 ? mappedDirectory : path16.join(mappedDirectory, filename);
19744
+ const filename = path17.basename(expanded);
19745
+ return filename.length === 0 ? mappedDirectory : path17.join(mappedDirectory, filename);
18696
19746
  }
18697
19747
 
18698
19748
  // ../config-mutations/src/error-codes.ts
@@ -18704,9 +19754,9 @@ function hasOwnErrorCode5(error3, code) {
18704
19754
  function isNotFound(error3) {
18705
19755
  return hasOwnErrorCode5(error3, "ENOENT");
18706
19756
  }
18707
- async function readFileIfExists(fs4, target) {
19757
+ async function readFileIfExists(fs5, target) {
18708
19758
  try {
18709
- return await fs4.readFile(target, "utf8");
19759
+ return await fs5.readFile(target, "utf8");
18710
19760
  } catch (error3) {
18711
19761
  if (isNotFound(error3)) {
18712
19762
  return null;
@@ -18714,9 +19764,9 @@ async function readFileIfExists(fs4, target) {
18714
19764
  throw error3;
18715
19765
  }
18716
19766
  }
18717
- async function pathExists(fs4, target) {
19767
+ async function pathExists(fs5, target) {
18718
19768
  try {
18719
- await fs4.stat(target);
19769
+ await fs5.stat(target);
18720
19770
  return true;
18721
19771
  } catch (error3) {
18722
19772
  if (isNotFound(error3)) {
@@ -18762,8 +19812,8 @@ function isAlreadyExists(error3) {
18762
19812
  return hasOwnErrorCode5(error3, "EEXIST");
18763
19813
  }
18764
19814
  async function assertRegularWriteTarget(context, targetPath) {
18765
- const boundary = path17.dirname(path17.resolve(context.homeDir));
18766
- let currentPath = path17.resolve(targetPath);
19815
+ const boundary = path18.dirname(path18.resolve(context.homeDir));
19816
+ let currentPath = path18.resolve(targetPath);
18767
19817
  while (currentPath !== boundary) {
18768
19818
  try {
18769
19819
  if ((await context.fs.lstat(currentPath)).isSymbolicLink()) {
@@ -18774,7 +19824,7 @@ async function assertRegularWriteTarget(context, targetPath) {
18774
19824
  throw error3;
18775
19825
  }
18776
19826
  }
18777
- const parentPath = path17.dirname(currentPath);
19827
+ const parentPath = path18.dirname(currentPath);
18778
19828
  if (parentPath === currentPath) {
18779
19829
  return;
18780
19830
  }
@@ -18839,6 +19889,56 @@ function describeMutation(kind, targetPath) {
18839
19889
  return "Operation";
18840
19890
  }
18841
19891
  }
19892
+ function mutationTargetPath(mutation, options) {
19893
+ switch (mutation.kind) {
19894
+ case "ensureDirectory":
19895
+ case "removeDirectory":
19896
+ return resolveValue(mutation.path, options);
19897
+ case "removeFile":
19898
+ case "chmod":
19899
+ case "backup":
19900
+ case "restoreBackup":
19901
+ case "configMerge":
19902
+ case "configPrune":
19903
+ case "configTransform":
19904
+ case "templateWrite":
19905
+ case "templateMergeToml":
19906
+ case "templateMergeJson":
19907
+ return resolveValue(mutation.target, options);
19908
+ default:
19909
+ return void 0;
19910
+ }
19911
+ }
19912
+ function resolveMutationDetails(mutation, context, options) {
19913
+ try {
19914
+ const rawTarget = mutationTargetPath(mutation, options);
19915
+ if (rawTarget === void 0) {
19916
+ return {
19917
+ kind: mutation.kind,
19918
+ label: mutation.label ?? mutation.kind
19919
+ };
19920
+ }
19921
+ try {
19922
+ const targetPath = resolvePath(rawTarget, context.homeDir, context.pathMapper);
19923
+ return {
19924
+ kind: mutation.kind,
19925
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
19926
+ targetPath
19927
+ };
19928
+ } catch {
19929
+ return {
19930
+ kind: mutation.kind,
19931
+ label: mutation.label ?? describeMutation(mutation.kind, rawTarget),
19932
+ targetPath: void 0
19933
+ };
19934
+ }
19935
+ } catch {
19936
+ return {
19937
+ kind: mutation.kind,
19938
+ label: mutation.label ?? mutation.kind
19939
+ };
19940
+ }
19941
+ }
18842
19942
  function pruneKeysByPrefix(table, prefix) {
18843
19943
  const result = {};
18844
19944
  for (const [key2, value] of Object.entries(table)) {
@@ -18929,6 +20029,7 @@ async function applyEnsureDirectory(mutation, context, options) {
18929
20029
  label: mutation.label ?? describeMutation(mutation.kind, targetPath),
18930
20030
  targetPath
18931
20031
  };
20032
+ await assertRegularWriteTarget(context, targetPath);
18932
20033
  const existed = await pathExists(context.fs, targetPath);
18933
20034
  if (!context.dryRun) {
18934
20035
  await context.fs.mkdir(targetPath, { recursive: true });
@@ -19045,6 +20146,7 @@ async function applyChmod(mutation, context, options) {
19045
20146
  };
19046
20147
  }
19047
20148
  try {
20149
+ await assertRegularWriteTarget(context, targetPath);
19048
20150
  const stat2 = await context.fs.stat(targetPath);
19049
20151
  const currentMode = typeof stat2.mode === "number" ? stat2.mode & 511 : null;
19050
20152
  if (currentMode === mutation.mode) {
@@ -19078,6 +20180,7 @@ async function applyBackup(mutation, context, options) {
19078
20180
  label: mutation.label ?? describeMutation(mutation.kind, targetPath),
19079
20181
  targetPath
19080
20182
  };
20183
+ await assertRegularWriteTarget(context, targetPath);
19081
20184
  if (mutation.once && await findLatestGeneratedBackup(context.fs, targetPath) !== null) {
19082
20185
  return {
19083
20186
  outcome: { changed: false, effect: "none", detail: "noop" },
@@ -19144,13 +20247,13 @@ async function applyRestoreBackup(mutation, context, options) {
19144
20247
  }
19145
20248
  return { outcome: { changed: true, effect: "copy", detail: "restore" }, details };
19146
20249
  }
19147
- async function findLatestGeneratedBackup(fs4, targetPath) {
20250
+ async function findLatestGeneratedBackup(fs5, targetPath) {
19148
20251
  const separatorIndex = targetPath.lastIndexOf("/");
19149
20252
  const directoryPath = separatorIndex <= 0 ? "/" : targetPath.slice(0, separatorIndex);
19150
20253
  const targetName = targetPath.slice(separatorIndex + 1);
19151
20254
  let entries;
19152
20255
  try {
19153
- entries = await fs4.readdir(directoryPath);
20256
+ entries = await fs5.readdir(directoryPath);
19154
20257
  } catch (error3) {
19155
20258
  if (isNotFound(error3)) {
19156
20259
  return null;
@@ -19214,6 +20317,9 @@ async function applyConfigMerge(mutation, context, options) {
19214
20317
  preserveContent = null;
19215
20318
  }
19216
20319
  const value = resolveValue(mutation.value, options);
20320
+ if (!isConfigObject4(value)) {
20321
+ throw new Error(`configMerge value must be an object for "${rawPath}".`);
20322
+ }
19217
20323
  let merged;
19218
20324
  if (mutation.pruneByPrefix) {
19219
20325
  merged = mergeWithPruneByPrefix(current, value, mutation.pruneByPrefix);
@@ -19347,6 +20453,13 @@ async function applyConfigTransform(mutation, context, options) {
19347
20453
  };
19348
20454
  }
19349
20455
  const serialized = serializeConfigUpdate(format, preserveContent, current, transformed);
20456
+ const serializedChanged = serialized !== rawContent;
20457
+ if (!serializedChanged) {
20458
+ return {
20459
+ outcome: { changed: false, effect: "none", detail: "noop" },
20460
+ details
20461
+ };
20462
+ }
19350
20463
  if (!context.dryRun) {
19351
20464
  await writeAtomically2(context, targetPath, serialized);
19352
20465
  }
@@ -19463,25 +20576,14 @@ async function runMutations(mutations, context, options) {
19463
20576
  };
19464
20577
  }
19465
20578
  async function executeMutation(mutation, context, options) {
19466
- context.observers?.onStart?.({
19467
- kind: mutation.kind,
19468
- label: mutation.label ?? mutation.kind,
19469
- targetPath: void 0
19470
- // Will be resolved during apply
19471
- });
20579
+ const pendingDetails = resolveMutationDetails(mutation, context, options);
20580
+ context.observers?.onStart?.(pendingDetails);
19472
20581
  try {
19473
20582
  const { outcome, details } = await applyMutation(mutation, context, options);
19474
20583
  context.observers?.onComplete?.(details, outcome);
19475
20584
  return { outcome, details };
19476
20585
  } catch (error3) {
19477
- context.observers?.onError?.(
19478
- {
19479
- kind: mutation.kind,
19480
- label: mutation.label ?? mutation.kind,
19481
- targetPath: void 0
19482
- },
19483
- error3
19484
- );
20586
+ context.observers?.onError?.(pendingDetails, error3);
19485
20587
  throw error3;
19486
20588
  }
19487
20589
  }
@@ -19492,8 +20594,8 @@ function hasOwnErrorCode6(error3, code) {
19492
20594
  }
19493
20595
 
19494
20596
  // ../agent-skill-config/src/templates.ts
19495
- import { readFile as readFile5, stat } from "node:fs/promises";
19496
- import path18 from "node:path";
20597
+ import { readFile as readFile6, stat } from "node:fs/promises";
20598
+ import path19 from "node:path";
19497
20599
  import { fileURLToPath as fileURLToPath3 } from "node:url";
19498
20600
 
19499
20601
  // ../agent-skill-config/src/apply.ts
@@ -19510,9 +20612,9 @@ function toHomeRelative(localSkillDir) {
19510
20612
  const normalized = localSkillDir.startsWith("./") ? localSkillDir.slice(2) : localSkillDir;
19511
20613
  return `~/${normalized}`;
19512
20614
  }
19513
- async function pathExists2(fs4, targetPath) {
20615
+ async function pathExists2(fs5, targetPath) {
19514
20616
  try {
19515
- await fs4.stat(targetPath);
20617
+ await fs5.stat(targetPath);
19516
20618
  return true;
19517
20619
  } catch (error3) {
19518
20620
  if (hasOwnErrorCode6(error3, "ENOENT")) {
@@ -19529,7 +20631,7 @@ async function installSkill(agentId, skill, options) {
19529
20631
  }
19530
20632
  const scope = options.scope ?? "local";
19531
20633
  const config2 = support.config;
19532
- if (skill.name.length === 0 || skill.name === "." || skill.name === ".." || skill.name.includes("/") || skill.name.includes("\\") || skill.name.includes("\n") || skill.name.includes("\r")) {
20634
+ if (skill.name.length === 0 || skill.name !== skill.name.trim() || skill.name === "." || skill.name === ".." || skill.name.includes("/") || skill.name.includes("\\") || skill.name.includes("\n") || skill.name.includes("\r")) {
19533
20635
  throw new Error(`Invalid skill name: ${skill.name}`);
19534
20636
  }
19535
20637
  const skillDir = scope === "global" ? config2.globalSkillDir : toHomeRelative(config2.localSkillDir);
@@ -19565,29 +20667,29 @@ async function installSkill(agentId, skill, options) {
19565
20667
  }
19566
20668
  }
19567
20669
  );
19568
- return { skillPath: skillFilePath, displayPath };
20670
+ return { skillPath: absoluteSkillPath, displayPath };
19569
20671
  }
19570
20672
 
19571
20673
  // ../agent-skill-config/src/resolve-skill-reference.ts
19572
- import { statSync as statSync2 } from "node:fs";
19573
- import path19 from "node:path";
20674
+ import * as fs2 from "node:fs";
20675
+ import path20 from "node:path";
19574
20676
 
19575
20677
  // ../agent-skill-config/src/git-exclude.ts
19576
20678
  import { execFileSync } from "node:child_process";
19577
20679
  import { randomUUID as randomUUID8 } from "node:crypto";
19578
- import * as fs2 from "node:fs";
19579
- import path20 from "node:path";
20680
+ import * as fs3 from "node:fs";
20681
+ import path21 from "node:path";
19580
20682
 
19581
20683
  // ../agent-skill-config/src/bridge-active-skills.ts
19582
- import * as fs3 from "node:fs";
20684
+ import * as fs4 from "node:fs";
19583
20685
  import { createHash as createHash4, randomUUID as randomUUID9 } from "node:crypto";
19584
- import path21 from "node:path";
20686
+ import path22 from "node:path";
19585
20687
 
19586
20688
  // src/commands/installer.ts
19587
20689
  import os3 from "node:os";
19588
- import path22 from "node:path";
20690
+ import path23 from "node:path";
19589
20691
  import * as nodeFs2 from "node:fs/promises";
19590
- import { readFile as readFile6 } from "node:fs/promises";
20692
+ import { readFile as readFile7 } from "node:fs/promises";
19591
20693
  var DEFAULT_INSTALL_AGENT = "claude-code";
19592
20694
  var DEFAULT_INSTALL_SCOPE = "local";
19593
20695
  var TERMINAL_PILOT_SKILL_NAME = "terminal-pilot";
@@ -19637,7 +20739,7 @@ async function loadTerminalPilotTemplate() {
19637
20739
  ];
19638
20740
  for (const candidate of candidates) {
19639
20741
  try {
19640
- terminalPilotTemplateCache = await readFile6(candidate, "utf8");
20742
+ terminalPilotTemplateCache = await readFile7(candidate, "utf8");
19641
20743
  return terminalPilotTemplateCache;
19642
20744
  } catch (error3) {
19643
20745
  if (!isNotFoundError2(error3)) {
@@ -19652,7 +20754,7 @@ function resolveHomeRelativePath(targetPath, homeDir) {
19652
20754
  return homeDir;
19653
20755
  }
19654
20756
  if (targetPath.startsWith("~/")) {
19655
- return path22.join(homeDir, targetPath.slice(2));
20757
+ return path23.join(homeDir, targetPath.slice(2));
19656
20758
  }
19657
20759
  return targetPath;
19658
20760
  }
@@ -19662,22 +20764,22 @@ function getSkillFolderWithHome(agent, scope, cwd, homeDir) {
19662
20764
  throwUnsupportedAgent(agent);
19663
20765
  }
19664
20766
  return {
19665
- displayPath: path22.join(
20767
+ displayPath: path23.join(
19666
20768
  scope === "global" ? config2.globalSkillDir : config2.localSkillDir,
19667
20769
  TERMINAL_PILOT_SKILL_NAME
19668
20770
  ),
19669
- fullPath: path22.join(
19670
- scope === "global" ? resolveHomeRelativePath(config2.globalSkillDir, homeDir) : path22.resolve(cwd, config2.localSkillDir),
20771
+ fullPath: path23.join(
20772
+ scope === "global" ? resolveHomeRelativePath(config2.globalSkillDir, homeDir) : path23.resolve(cwd, config2.localSkillDir),
19671
20773
  TERMINAL_PILOT_SKILL_NAME
19672
20774
  )
19673
20775
  };
19674
20776
  }
19675
- async function assertNoSymbolicLinkPath(fs4, targetPath) {
19676
- const rootPath = path22.parse(targetPath).root;
20777
+ async function assertNoSymbolicLinkPath(fs5, targetPath) {
20778
+ const rootPath = path23.parse(targetPath).root;
19677
20779
  let currentPath = targetPath;
19678
20780
  while (currentPath !== rootPath) {
19679
20781
  try {
19680
- if ((await fs4.lstat(currentPath)).isSymbolicLink()) {
20782
+ if ((await fs5.lstat(currentPath)).isSymbolicLink()) {
19681
20783
  throw new UserError(`Refusing terminal-pilot skill operation through symbolic link: ${currentPath}`);
19682
20784
  }
19683
20785
  } catch (error3) {
@@ -19685,7 +20787,7 @@ async function assertNoSymbolicLinkPath(fs4, targetPath) {
19685
20787
  throw error3;
19686
20788
  }
19687
20789
  }
19688
- currentPath = path22.dirname(currentPath);
20790
+ currentPath = path23.dirname(currentPath);
19689
20791
  }
19690
20792
  }
19691
20793
 
@@ -20384,11 +21486,11 @@ import { Resvg } from "@resvg/resvg-js";
20384
21486
 
20385
21487
  // ../terminal-png/src/font.ts
20386
21488
  import { readFileSync as readFileSync4 } from "node:fs";
20387
- import { createRequire as createRequire2 } from "node:module";
21489
+ import { createRequire as createRequire3 } from "node:module";
20388
21490
  import { dirname as dirname2, join as join2 } from "node:path";
20389
21491
  import { fileURLToPath as fileURLToPath4 } from "node:url";
20390
- var require2 = createRequire2(import.meta.url);
20391
- var fontPackageRoot = dirname2(require2.resolve("jetbrains-mono/package.json"));
21492
+ var require3 = createRequire3(import.meta.url);
21493
+ var fontPackageRoot = dirname2(require3.resolve("jetbrains-mono/package.json"));
20392
21494
  var webfontRoot = join2(fontPackageRoot, "fonts/webfonts");
20393
21495
  function readWebfontBase64(filename) {
20394
21496
  return readFileSync4(join2(webfontRoot, filename)).toString("base64");
@@ -21098,9 +22200,9 @@ var uninstall = defineCommand({
21098
22200
  };
21099
22201
  }
21100
22202
  });
21101
- async function folderExists(fs4, folderPath) {
22203
+ async function folderExists(fs5, folderPath) {
21102
22204
  try {
21103
- await fs4.stat(folderPath);
22205
+ await fs5.stat(folderPath);
21104
22206
  return true;
21105
22207
  } catch (error3) {
21106
22208
  if (hasOwnErrorCode4(error3, "ENOENT")) {
@@ -21245,7 +22347,7 @@ async function isDirectExecution(argv) {
21245
22347
  try {
21246
22348
  const modulePath = fileURLToPath5(import.meta.url);
21247
22349
  const [resolvedEntryPoint, resolvedModulePath] = await Promise.all([
21248
- realpath3(path23.resolve(entryPoint)),
22350
+ realpath3(path24.resolve(entryPoint)),
21249
22351
  realpath3(modulePath)
21250
22352
  ]);
21251
22353
  return resolvedEntryPoint === resolvedModulePath;