terminal-pilot 0.0.30 → 0.0.31

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 (328) hide show
  1. package/dist/cli.js +1375 -435
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.js +485 -6
  4. package/dist/commands/close-session.js.map +4 -4
  5. package/dist/commands/create-session.js +485 -6
  6. package/dist/commands/create-session.js.map +4 -4
  7. package/dist/commands/fill.js +485 -6
  8. package/dist/commands/fill.js.map +4 -4
  9. package/dist/commands/get-session.js +485 -6
  10. package/dist/commands/get-session.js.map +4 -4
  11. package/dist/commands/index.js +626 -44
  12. package/dist/commands/index.js.map +4 -4
  13. package/dist/commands/install.js +622 -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 +485 -6
  18. package/dist/commands/list-sessions.js.map +4 -4
  19. package/dist/commands/press-key.js +485 -6
  20. package/dist/commands/press-key.js.map +4 -4
  21. package/dist/commands/read-history.js +485 -6
  22. package/dist/commands/read-history.js.map +4 -4
  23. package/dist/commands/read-screen.js +485 -6
  24. package/dist/commands/read-screen.js.map +4 -4
  25. package/dist/commands/resize.js +485 -6
  26. package/dist/commands/resize.js.map +4 -4
  27. package/dist/commands/screenshot.js +485 -6
  28. package/dist/commands/screenshot.js.map +4 -4
  29. package/dist/commands/send-signal.js +485 -6
  30. package/dist/commands/send-signal.js.map +4 -4
  31. package/dist/commands/type.js +485 -6
  32. package/dist/commands/type.js.map +4 -4
  33. package/dist/commands/uninstall.js +550 -20
  34. package/dist/commands/uninstall.js.map +4 -4
  35. package/dist/commands/wait-for-exit.js +485 -6
  36. package/dist/commands/wait-for-exit.js.map +4 -4
  37. package/dist/commands/wait-for.js +485 -6
  38. package/dist/commands/wait-for.js.map +4 -4
  39. package/dist/testing/cli-repl.js +1375 -435
  40. package/dist/testing/cli-repl.js.map +4 -4
  41. package/dist/testing/qa-cli.js +1385 -445
  42. package/dist/testing/qa-cli.js.map +4 -4
  43. package/node_modules/@poe-code/agent-defs/README.md +35 -0
  44. package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.d.ts +2 -0
  45. package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.js +21 -0
  46. package/node_modules/@poe-code/agent-defs/dist/agents/claude-desktop.d.ts +2 -0
  47. package/node_modules/@poe-code/agent-defs/dist/agents/claude-desktop.js +18 -0
  48. package/node_modules/@poe-code/agent-defs/dist/agents/codex.d.ts +2 -0
  49. package/node_modules/@poe-code/agent-defs/dist/agents/codex.js +25 -0
  50. package/node_modules/@poe-code/agent-defs/dist/agents/cursor.d.ts +2 -0
  51. package/node_modules/@poe-code/agent-defs/dist/agents/cursor.js +15 -0
  52. package/node_modules/@poe-code/agent-defs/dist/agents/gemini-cli.d.ts +2 -0
  53. package/node_modules/@poe-code/agent-defs/dist/agents/gemini-cli.js +16 -0
  54. package/node_modules/@poe-code/agent-defs/dist/agents/goose.d.ts +2 -0
  55. package/node_modules/@poe-code/agent-defs/dist/agents/goose.js +16 -0
  56. package/node_modules/@poe-code/agent-defs/dist/agents/index.d.ts +9 -0
  57. package/node_modules/@poe-code/agent-defs/dist/agents/index.js +9 -0
  58. package/node_modules/@poe-code/agent-defs/dist/agents/kimi.d.ts +2 -0
  59. package/node_modules/@poe-code/agent-defs/dist/agents/kimi.js +16 -0
  60. package/node_modules/@poe-code/agent-defs/dist/agents/opencode.d.ts +2 -0
  61. package/node_modules/@poe-code/agent-defs/dist/agents/opencode.js +20 -0
  62. package/node_modules/@poe-code/agent-defs/dist/agents/poe-agent.d.ts +2 -0
  63. package/node_modules/@poe-code/agent-defs/dist/agents/poe-agent.js +14 -0
  64. package/node_modules/@poe-code/agent-defs/dist/index.d.ts +5 -0
  65. package/node_modules/@poe-code/agent-defs/dist/index.js +3 -0
  66. package/node_modules/@poe-code/agent-defs/dist/registry.d.ts +3 -0
  67. package/node_modules/@poe-code/agent-defs/dist/registry.js +45 -0
  68. package/node_modules/@poe-code/agent-defs/dist/specifier.d.ts +7 -0
  69. package/node_modules/@poe-code/agent-defs/dist/specifier.js +40 -0
  70. package/node_modules/@poe-code/agent-defs/dist/types.d.ts +28 -0
  71. package/node_modules/@poe-code/agent-defs/dist/types.js +1 -0
  72. package/node_modules/@poe-code/agent-defs/package.json +20 -0
  73. package/node_modules/@poe-code/agent-skill-config/dist/apply.js +2 -1
  74. package/node_modules/@poe-code/agent-skill-config/dist/bridge-active-skills.d.ts +1 -0
  75. package/node_modules/@poe-code/agent-skill-config/dist/bridge-active-skills.js +37 -18
  76. package/node_modules/@poe-code/agent-skill-config/dist/resolve-skill-reference.js +8 -4
  77. package/node_modules/@poe-code/agent-skill-config/package.json +1 -5
  78. package/node_modules/@poe-code/config-mutations/README.md +55 -0
  79. package/node_modules/@poe-code/config-mutations/dist/error-codes.d.ts +1 -0
  80. package/node_modules/@poe-code/config-mutations/dist/error-codes.js +6 -0
  81. package/node_modules/@poe-code/config-mutations/dist/execution/apply-mutation.d.ts +6 -0
  82. package/node_modules/@poe-code/config-mutations/dist/execution/apply-mutation.js +829 -0
  83. package/node_modules/@poe-code/config-mutations/dist/execution/path-utils.d.ts +17 -0
  84. package/node_modules/@poe-code/config-mutations/dist/execution/path-utils.js +64 -0
  85. package/node_modules/@poe-code/config-mutations/dist/execution/run-mutations.d.ts +7 -0
  86. package/node_modules/@poe-code/config-mutations/dist/execution/run-mutations.js +39 -0
  87. package/node_modules/@poe-code/config-mutations/dist/formats/index.d.ts +13 -0
  88. package/node_modules/@poe-code/config-mutations/dist/formats/index.js +49 -0
  89. package/node_modules/@poe-code/config-mutations/dist/formats/json.d.ts +32 -0
  90. package/node_modules/@poe-code/config-mutations/dist/formats/json.js +171 -0
  91. package/node_modules/@poe-code/config-mutations/dist/formats/object.d.ts +4 -0
  92. package/node_modules/@poe-code/config-mutations/dist/formats/object.js +27 -0
  93. package/node_modules/@poe-code/config-mutations/dist/formats/toml.d.ts +2 -0
  94. package/node_modules/@poe-code/config-mutations/dist/formats/toml.js +75 -0
  95. package/node_modules/@poe-code/config-mutations/dist/formats/yaml.d.ts +2 -0
  96. package/node_modules/@poe-code/config-mutations/dist/formats/yaml.js +76 -0
  97. package/node_modules/@poe-code/config-mutations/dist/fs-utils.d.ts +18 -0
  98. package/node_modules/@poe-code/config-mutations/dist/fs-utils.js +43 -0
  99. package/node_modules/@poe-code/config-mutations/dist/index.d.ts +8 -0
  100. package/node_modules/@poe-code/config-mutations/dist/index.js +8 -0
  101. package/node_modules/@poe-code/config-mutations/dist/mutations/config-mutation.d.ts +47 -0
  102. package/node_modules/@poe-code/config-mutations/dist/mutations/config-mutation.js +34 -0
  103. package/node_modules/@poe-code/config-mutations/dist/mutations/file-mutation.d.ts +62 -0
  104. package/node_modules/@poe-code/config-mutations/dist/mutations/file-mutation.js +55 -0
  105. package/node_modules/@poe-code/config-mutations/dist/mutations/template-mutation.d.ts +40 -0
  106. package/node_modules/@poe-code/config-mutations/dist/mutations/template-mutation.js +32 -0
  107. package/node_modules/@poe-code/config-mutations/dist/template/render.d.ts +6 -0
  108. package/node_modules/@poe-code/config-mutations/dist/template/render.js +8 -0
  109. package/node_modules/@poe-code/config-mutations/dist/testing/format-utils.d.ts +7 -0
  110. package/node_modules/@poe-code/config-mutations/dist/testing/format-utils.js +21 -0
  111. package/node_modules/@poe-code/config-mutations/dist/testing/index.d.ts +3 -0
  112. package/node_modules/@poe-code/config-mutations/dist/testing/index.js +2 -0
  113. package/node_modules/@poe-code/config-mutations/dist/testing/mock-fs.d.ts +25 -0
  114. package/node_modules/@poe-code/config-mutations/dist/testing/mock-fs.js +194 -0
  115. package/node_modules/@poe-code/config-mutations/dist/types.d.ts +168 -0
  116. package/node_modules/@poe-code/config-mutations/dist/types.js +6 -0
  117. package/node_modules/@poe-code/config-mutations/package.json +29 -0
  118. package/node_modules/@poe-code/frontmatter/README.md +35 -0
  119. package/node_modules/@poe-code/frontmatter/dist/fences.d.ts +25 -0
  120. package/node_modules/@poe-code/frontmatter/dist/fences.js +100 -0
  121. package/node_modules/@poe-code/frontmatter/dist/index.d.ts +3 -0
  122. package/node_modules/@poe-code/frontmatter/dist/index.js +3 -0
  123. package/node_modules/@poe-code/frontmatter/dist/parse.d.ts +20 -0
  124. package/node_modules/@poe-code/frontmatter/dist/parse.js +209 -0
  125. package/node_modules/@poe-code/frontmatter/dist/stringify.d.ts +1 -0
  126. package/node_modules/@poe-code/frontmatter/dist/stringify.js +48 -0
  127. package/node_modules/@poe-code/frontmatter/package.json +25 -0
  128. package/node_modules/toolcraft-design/README.md +160 -0
  129. package/node_modules/toolcraft-design/dist/acp/components.d.ts +12 -0
  130. package/node_modules/toolcraft-design/dist/acp/components.js +137 -0
  131. package/node_modules/toolcraft-design/dist/acp/index.d.ts +3 -0
  132. package/node_modules/toolcraft-design/dist/acp/index.js +2 -0
  133. package/node_modules/toolcraft-design/dist/acp/writer.d.ts +13 -0
  134. package/node_modules/toolcraft-design/dist/acp/writer.js +21 -0
  135. package/node_modules/toolcraft-design/dist/components/browser.d.ts +15 -0
  136. package/node_modules/toolcraft-design/dist/components/browser.js +31 -0
  137. package/node_modules/toolcraft-design/dist/components/catalog.d.ts +26 -0
  138. package/node_modules/toolcraft-design/dist/components/catalog.js +95 -0
  139. package/node_modules/toolcraft-design/dist/components/color.d.ts +31 -0
  140. package/node_modules/toolcraft-design/dist/components/color.js +102 -0
  141. package/node_modules/toolcraft-design/dist/components/command-errors.d.ts +16 -0
  142. package/node_modules/toolcraft-design/dist/components/command-errors.js +23 -0
  143. package/node_modules/toolcraft-design/dist/components/detail-card.d.ts +22 -0
  144. package/node_modules/toolcraft-design/dist/components/detail-card.js +45 -0
  145. package/node_modules/toolcraft-design/dist/components/help-formatter-plain.d.ts +5 -0
  146. package/node_modules/toolcraft-design/dist/components/help-formatter-plain.js +132 -0
  147. package/node_modules/toolcraft-design/dist/components/help-formatter.d.ts +33 -0
  148. package/node_modules/toolcraft-design/dist/components/help-formatter.js +213 -0
  149. package/node_modules/toolcraft-design/dist/components/index.d.ts +16 -0
  150. package/node_modules/toolcraft-design/dist/components/index.js +10 -0
  151. package/node_modules/toolcraft-design/dist/components/logger.d.ts +11 -0
  152. package/node_modules/toolcraft-design/dist/components/logger.js +60 -0
  153. package/node_modules/toolcraft-design/dist/components/symbols.d.ts +12 -0
  154. package/node_modules/toolcraft-design/dist/components/symbols.js +71 -0
  155. package/node_modules/toolcraft-design/dist/components/table.d.ts +15 -0
  156. package/node_modules/toolcraft-design/dist/components/table.js +302 -0
  157. package/node_modules/toolcraft-design/dist/components/template.d.ts +10 -0
  158. package/node_modules/toolcraft-design/dist/components/template.js +437 -0
  159. package/node_modules/toolcraft-design/dist/components/text.d.ts +16 -0
  160. package/node_modules/toolcraft-design/dist/components/text.js +145 -0
  161. package/node_modules/toolcraft-design/dist/dashboard/ansi.d.ts +18 -0
  162. package/node_modules/toolcraft-design/dist/dashboard/ansi.js +343 -0
  163. package/node_modules/toolcraft-design/dist/dashboard/buffer.d.ts +25 -0
  164. package/node_modules/toolcraft-design/dist/dashboard/buffer.js +219 -0
  165. package/node_modules/toolcraft-design/dist/dashboard/components/border.d.ts +9 -0
  166. package/node_modules/toolcraft-design/dist/dashboard/components/border.js +123 -0
  167. package/node_modules/toolcraft-design/dist/dashboard/components/footer.d.ts +8 -0
  168. package/node_modules/toolcraft-design/dist/dashboard/components/footer.js +56 -0
  169. package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.d.ts +12 -0
  170. package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.js +268 -0
  171. package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.d.ts +7 -0
  172. package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.js +107 -0
  173. package/node_modules/toolcraft-design/dist/dashboard/dashboard.d.ts +20 -0
  174. package/node_modules/toolcraft-design/dist/dashboard/dashboard.js +167 -0
  175. package/node_modules/toolcraft-design/dist/dashboard/demo.d.ts +13 -0
  176. package/node_modules/toolcraft-design/dist/dashboard/demo.js +145 -0
  177. package/node_modules/toolcraft-design/dist/dashboard/index.d.ts +8 -0
  178. package/node_modules/toolcraft-design/dist/dashboard/index.js +4 -0
  179. package/node_modules/toolcraft-design/dist/dashboard/keymap.d.ts +8 -0
  180. package/node_modules/toolcraft-design/dist/dashboard/keymap.js +233 -0
  181. package/node_modules/toolcraft-design/dist/dashboard/layout.d.ts +25 -0
  182. package/node_modules/toolcraft-design/dist/dashboard/layout.js +79 -0
  183. package/node_modules/toolcraft-design/dist/dashboard/should-use-dashboard.d.ts +10 -0
  184. package/node_modules/toolcraft-design/dist/dashboard/should-use-dashboard.js +7 -0
  185. package/node_modules/toolcraft-design/dist/dashboard/snapshot.d.ts +10 -0
  186. package/node_modules/toolcraft-design/dist/dashboard/snapshot.js +68 -0
  187. package/node_modules/toolcraft-design/dist/dashboard/store.d.ts +8 -0
  188. package/node_modules/toolcraft-design/dist/dashboard/store.js +51 -0
  189. package/node_modules/toolcraft-design/dist/dashboard/terminal-width.d.ts +4 -0
  190. package/node_modules/toolcraft-design/dist/dashboard/terminal-width.js +71 -0
  191. package/node_modules/toolcraft-design/dist/dashboard/terminal.d.ts +37 -0
  192. package/node_modules/toolcraft-design/dist/dashboard/terminal.js +264 -0
  193. package/node_modules/toolcraft-design/dist/dashboard/types.d.ts +38 -0
  194. package/node_modules/toolcraft-design/dist/dashboard/types.js +1 -0
  195. package/node_modules/toolcraft-design/dist/explorer/actions.d.ts +16 -0
  196. package/node_modules/toolcraft-design/dist/explorer/actions.js +39 -0
  197. package/node_modules/toolcraft-design/dist/explorer/demo.d.ts +13 -0
  198. package/node_modules/toolcraft-design/dist/explorer/demo.js +297 -0
  199. package/node_modules/toolcraft-design/dist/explorer/events.d.ts +67 -0
  200. package/node_modules/toolcraft-design/dist/explorer/events.js +1 -0
  201. package/node_modules/toolcraft-design/dist/explorer/filter.d.ts +10 -0
  202. package/node_modules/toolcraft-design/dist/explorer/filter.js +95 -0
  203. package/node_modules/toolcraft-design/dist/explorer/index.d.ts +8 -0
  204. package/node_modules/toolcraft-design/dist/explorer/index.js +8 -0
  205. package/node_modules/toolcraft-design/dist/explorer/jobs.d.ts +7 -0
  206. package/node_modules/toolcraft-design/dist/explorer/jobs.js +59 -0
  207. package/node_modules/toolcraft-design/dist/explorer/keymap.d.ts +21 -0
  208. package/node_modules/toolcraft-design/dist/explorer/keymap.js +376 -0
  209. package/node_modules/toolcraft-design/dist/explorer/layout.d.ts +20 -0
  210. package/node_modules/toolcraft-design/dist/explorer/layout.js +73 -0
  211. package/node_modules/toolcraft-design/dist/explorer/reducer.d.ts +9 -0
  212. package/node_modules/toolcraft-design/dist/explorer/reducer.js +782 -0
  213. package/node_modules/toolcraft-design/dist/explorer/render/detail.d.ts +4 -0
  214. package/node_modules/toolcraft-design/dist/explorer/render/detail.js +97 -0
  215. package/node_modules/toolcraft-design/dist/explorer/render/footer.d.ts +4 -0
  216. package/node_modules/toolcraft-design/dist/explorer/render/footer.js +73 -0
  217. package/node_modules/toolcraft-design/dist/explorer/render/header.d.ts +4 -0
  218. package/node_modules/toolcraft-design/dist/explorer/render/header.js +49 -0
  219. package/node_modules/toolcraft-design/dist/explorer/render/index.d.ts +8 -0
  220. package/node_modules/toolcraft-design/dist/explorer/render/index.js +53 -0
  221. package/node_modules/toolcraft-design/dist/explorer/render/list.d.ts +4 -0
  222. package/node_modules/toolcraft-design/dist/explorer/render/list.js +116 -0
  223. package/node_modules/toolcraft-design/dist/explorer/render/modal.d.ts +3 -0
  224. package/node_modules/toolcraft-design/dist/explorer/render/modal.js +87 -0
  225. package/node_modules/toolcraft-design/dist/explorer/render/test-fixtures.d.ts +8 -0
  226. package/node_modules/toolcraft-design/dist/explorer/render/test-fixtures.js +156 -0
  227. package/node_modules/toolcraft-design/dist/explorer/render/text.d.ts +12 -0
  228. package/node_modules/toolcraft-design/dist/explorer/render/text.js +81 -0
  229. package/node_modules/toolcraft-design/dist/explorer/runtime.d.ts +2 -0
  230. package/node_modules/toolcraft-design/dist/explorer/runtime.js +340 -0
  231. package/node_modules/toolcraft-design/dist/explorer/runtime.test-helpers.d.ts +50 -0
  232. package/node_modules/toolcraft-design/dist/explorer/runtime.test-helpers.js +101 -0
  233. package/node_modules/toolcraft-design/dist/explorer/state.d.ts +137 -0
  234. package/node_modules/toolcraft-design/dist/explorer/state.js +86 -0
  235. package/node_modules/toolcraft-design/dist/explorer/theme.d.ts +27 -0
  236. package/node_modules/toolcraft-design/dist/explorer/theme.js +29 -0
  237. package/node_modules/toolcraft-design/dist/index.d.ts +50 -0
  238. package/node_modules/toolcraft-design/dist/index.js +43 -0
  239. package/node_modules/toolcraft-design/dist/internal/color-support.d.ts +9 -0
  240. package/node_modules/toolcraft-design/dist/internal/color-support.js +12 -0
  241. package/node_modules/toolcraft-design/dist/internal/output-format.d.ts +6 -0
  242. package/node_modules/toolcraft-design/dist/internal/output-format.js +22 -0
  243. package/node_modules/toolcraft-design/dist/internal/strip-ansi.d.ts +1 -0
  244. package/node_modules/toolcraft-design/dist/internal/strip-ansi.js +50 -0
  245. package/node_modules/toolcraft-design/dist/internal/theme-detect.d.ts +12 -0
  246. package/node_modules/toolcraft-design/dist/internal/theme-detect.js +71 -0
  247. package/node_modules/toolcraft-design/dist/internal/theme-state.d.ts +12 -0
  248. package/node_modules/toolcraft-design/dist/internal/theme-state.js +35 -0
  249. package/node_modules/toolcraft-design/dist/prompts/index.d.ts +91 -0
  250. package/node_modules/toolcraft-design/dist/prompts/index.js +137 -0
  251. package/node_modules/toolcraft-design/dist/prompts/interactive/cancel-symbol.d.ts +2 -0
  252. package/node_modules/toolcraft-design/dist/prompts/interactive/cancel-symbol.js +4 -0
  253. package/node_modules/toolcraft-design/dist/prompts/interactive/confirm.d.ts +9 -0
  254. package/node_modules/toolcraft-design/dist/prompts/interactive/confirm.js +47 -0
  255. package/node_modules/toolcraft-design/dist/prompts/interactive/core.d.ts +55 -0
  256. package/node_modules/toolcraft-design/dist/prompts/interactive/core.js +274 -0
  257. package/node_modules/toolcraft-design/dist/prompts/interactive/glyphs.d.ts +20 -0
  258. package/node_modules/toolcraft-design/dist/prompts/interactive/glyphs.js +53 -0
  259. package/node_modules/toolcraft-design/dist/prompts/interactive/index.d.ts +6 -0
  260. package/node_modules/toolcraft-design/dist/prompts/interactive/index.js +6 -0
  261. package/node_modules/toolcraft-design/dist/prompts/interactive/keys.d.ts +2 -0
  262. package/node_modules/toolcraft-design/dist/prompts/interactive/keys.js +28 -0
  263. package/node_modules/toolcraft-design/dist/prompts/interactive/multiselect.d.ts +13 -0
  264. package/node_modules/toolcraft-design/dist/prompts/interactive/multiselect.js +131 -0
  265. package/node_modules/toolcraft-design/dist/prompts/interactive/pagination.d.ts +10 -0
  266. package/node_modules/toolcraft-design/dist/prompts/interactive/pagination.js +52 -0
  267. package/node_modules/toolcraft-design/dist/prompts/interactive/password.d.ts +10 -0
  268. package/node_modules/toolcraft-design/dist/prompts/interactive/password.js +55 -0
  269. package/node_modules/toolcraft-design/dist/prompts/interactive/select.d.ts +18 -0
  270. package/node_modules/toolcraft-design/dist/prompts/interactive/select.js +89 -0
  271. package/node_modules/toolcraft-design/dist/prompts/interactive/test-helpers.d.ts +21 -0
  272. package/node_modules/toolcraft-design/dist/prompts/interactive/test-helpers.js +32 -0
  273. package/node_modules/toolcraft-design/dist/prompts/interactive/text.d.ts +12 -0
  274. package/node_modules/toolcraft-design/dist/prompts/interactive/text.js +60 -0
  275. package/node_modules/toolcraft-design/dist/prompts/interactive/wrap.d.ts +4 -0
  276. package/node_modules/toolcraft-design/dist/prompts/interactive/wrap.js +18 -0
  277. package/node_modules/toolcraft-design/dist/prompts/primitives/cancel.d.ts +2 -0
  278. package/node_modules/toolcraft-design/dist/prompts/primitives/cancel.js +9 -0
  279. package/node_modules/toolcraft-design/dist/prompts/primitives/intro.d.ts +1 -0
  280. package/node_modules/toolcraft-design/dist/prompts/primitives/intro.js +16 -0
  281. package/node_modules/toolcraft-design/dist/prompts/primitives/log.d.ts +18 -0
  282. package/node_modules/toolcraft-design/dist/prompts/primitives/log.js +104 -0
  283. package/node_modules/toolcraft-design/dist/prompts/primitives/note.d.ts +1 -0
  284. package/node_modules/toolcraft-design/dist/prompts/primitives/note.js +39 -0
  285. package/node_modules/toolcraft-design/dist/prompts/primitives/outro.d.ts +1 -0
  286. package/node_modules/toolcraft-design/dist/prompts/primitives/outro.js +16 -0
  287. package/node_modules/toolcraft-design/dist/prompts/primitives/spinner.d.ts +6 -0
  288. package/node_modules/toolcraft-design/dist/prompts/primitives/spinner.js +74 -0
  289. package/node_modules/toolcraft-design/dist/prompts/theme.d.ts +11 -0
  290. package/node_modules/toolcraft-design/dist/prompts/theme.js +15 -0
  291. package/node_modules/toolcraft-design/dist/static/index.d.ts +4 -0
  292. package/node_modules/toolcraft-design/dist/static/index.js +2 -0
  293. package/node_modules/toolcraft-design/dist/static/menu.d.ts +11 -0
  294. package/node_modules/toolcraft-design/dist/static/menu.js +42 -0
  295. package/node_modules/toolcraft-design/dist/static/spinner.d.ts +14 -0
  296. package/node_modules/toolcraft-design/dist/static/spinner.js +52 -0
  297. package/node_modules/toolcraft-design/dist/terminal-markdown/ast.d.ts +92 -0
  298. package/node_modules/toolcraft-design/dist/terminal-markdown/ast.js +1 -0
  299. package/node_modules/toolcraft-design/dist/terminal-markdown/demo-content.d.ts +2 -0
  300. package/node_modules/toolcraft-design/dist/terminal-markdown/demo-content.js +139 -0
  301. package/node_modules/toolcraft-design/dist/terminal-markdown/index.d.ts +6 -0
  302. package/node_modules/toolcraft-design/dist/terminal-markdown/index.js +8 -0
  303. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/block.d.ts +7 -0
  304. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/block.js +1495 -0
  305. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/frontmatter.d.ts +8 -0
  306. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/frontmatter.js +36 -0
  307. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/inline.d.ts +10 -0
  308. package/node_modules/toolcraft-design/dist/terminal-markdown/parser/inline.js +1190 -0
  309. package/node_modules/toolcraft-design/dist/terminal-markdown/parser.d.ts +5 -0
  310. package/node_modules/toolcraft-design/dist/terminal-markdown/parser.js +42 -0
  311. package/node_modules/toolcraft-design/dist/terminal-markdown/renderer.d.ts +6 -0
  312. package/node_modules/toolcraft-design/dist/terminal-markdown/renderer.js +615 -0
  313. package/node_modules/toolcraft-design/dist/terminal-markdown/testing/theme-render-fixture.d.ts +1 -0
  314. package/node_modules/toolcraft-design/dist/terminal-markdown/testing/theme-render-fixture.js +27 -0
  315. package/node_modules/toolcraft-design/dist/tokens/brand.d.ts +5 -0
  316. package/node_modules/toolcraft-design/dist/tokens/brand.js +5 -0
  317. package/node_modules/toolcraft-design/dist/tokens/colors.d.ts +37 -0
  318. package/node_modules/toolcraft-design/dist/tokens/colors.js +85 -0
  319. package/node_modules/toolcraft-design/dist/tokens/index.d.ts +6 -0
  320. package/node_modules/toolcraft-design/dist/tokens/index.js +5 -0
  321. package/node_modules/toolcraft-design/dist/tokens/spacing.d.ts +6 -0
  322. package/node_modules/toolcraft-design/dist/tokens/spacing.js +6 -0
  323. package/node_modules/toolcraft-design/dist/tokens/typography.d.ts +7 -0
  324. package/node_modules/toolcraft-design/dist/tokens/typography.js +8 -0
  325. package/node_modules/toolcraft-design/dist/tokens/widths.d.ts +5 -0
  326. package/node_modules/toolcraft-design/dist/tokens/widths.js +5 -0
  327. package/node_modules/toolcraft-design/package.json +44 -0
  328. package/package.json +15 -5
@@ -8,7 +8,7 @@ var __export = (target, all) => {
8
8
  import assert from "node:assert/strict";
9
9
  import { rm as rm2 } from "node:fs/promises";
10
10
  import os4 from "node:os";
11
- import path24 from "node:path";
11
+ import path25 from "node:path";
12
12
  import { fileURLToPath as fileURLToPath6 } from "node:url";
13
13
 
14
14
  // src/ansi.ts
@@ -86,12 +86,12 @@ function consumeTerminatedString(input, index, allowBellTerminator) {
86
86
 
87
87
  // src/cli.ts
88
88
  import { realpath as realpath3 } from "node:fs/promises";
89
- import path23 from "node:path";
89
+ import path24 from "node:path";
90
90
  import { fileURLToPath as fileURLToPath5 } from "node:url";
91
91
 
92
92
  // ../toolcraft/src/cli.ts
93
- import { access as access2, lstat as lstat3, readFile as readFile4, rename as rename3, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
94
- import path14 from "node:path";
93
+ import { access as access2, lstat as lstat3, readFile as readFile5, rename as rename3, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
94
+ import path15 from "node:path";
95
95
  import {
96
96
  Command as CommanderCommand,
97
97
  CommanderError as CommanderError2,
@@ -457,7 +457,8 @@ function renderMarkdownCode(content) {
457
457
  currentRun = 0;
458
458
  }
459
459
  const delimiter = "`".repeat(longestRun + 1);
460
- return `${delimiter}${value}${delimiter}`;
460
+ const paddedValue = value.startsWith("`") || value.endsWith("`") ? ` ${value} ` : value;
461
+ return `${delimiter}${paddedValue}${delimiter}`;
461
462
  }
462
463
  function renderMarkdownLink(content) {
463
464
  const value = renderMarkdownInline(content);
@@ -612,7 +613,54 @@ var symbols = {
612
613
 
613
614
  // ../toolcraft-design/src/internal/strip-ansi.ts
614
615
  function stripAnsi2(value) {
615
- return value.replace(/\u001b\[[0-9;]*m/g, "");
616
+ let output = "";
617
+ let index = 0;
618
+ while (index < value.length) {
619
+ const char = value[index];
620
+ if (char === "\x1B") {
621
+ index = skipEscapeSequence(value, index);
622
+ continue;
623
+ }
624
+ if (char === "\x9B") {
625
+ index = skipCsiSequence(value, index + 1);
626
+ continue;
627
+ }
628
+ output += char;
629
+ index += char.length;
630
+ }
631
+ return output;
632
+ }
633
+ function skipEscapeSequence(value, index) {
634
+ const next = value[index + 1];
635
+ if (next === "[") {
636
+ return skipCsiSequence(value, index + 2);
637
+ }
638
+ if (next === "]") {
639
+ return skipOscSequence(value, index + 2);
640
+ }
641
+ return Math.min(value.length, index + 2);
642
+ }
643
+ function skipCsiSequence(value, index) {
644
+ while (index < value.length) {
645
+ const codePoint = value.charCodeAt(index);
646
+ index += 1;
647
+ if (codePoint >= 64 && codePoint <= 126) {
648
+ break;
649
+ }
650
+ }
651
+ return index;
652
+ }
653
+ function skipOscSequence(value, index) {
654
+ while (index < value.length) {
655
+ if (value[index] === "\x07") {
656
+ return index + 1;
657
+ }
658
+ if (value[index] === "\x1B" && value[index + 1] === "\\") {
659
+ return index + 2;
660
+ }
661
+ index += 1;
662
+ }
663
+ return index;
616
664
  }
617
665
 
618
666
  // ../toolcraft-design/src/prompts/primitives/log.ts
@@ -1401,38 +1449,14 @@ function renderTable(options) {
1401
1449
  }
1402
1450
 
1403
1451
  // ../toolcraft-design/src/components/detail-card.ts
1452
+ import stringWidth from "fast-string-width";
1453
+ import { wrapAnsi } from "fast-wrap-ansi";
1404
1454
  function wrap(value, width) {
1405
- const lines = [];
1406
- for (const paragraph of value.split("\n")) {
1407
- let line = "";
1408
- for (const rawWord of paragraph.split(" ")) {
1409
- const words = [];
1410
- let word = rawWord;
1411
- while (word.length > width) {
1412
- words.push(word.slice(0, width));
1413
- word = word.slice(width);
1414
- }
1415
- words.push(word);
1416
- for (const word2 of words) {
1417
- if (line.length === 0) {
1418
- line = word2;
1419
- continue;
1420
- }
1421
- if (`${line} ${word2}`.length <= width) {
1422
- line = `${line} ${word2}`;
1423
- continue;
1424
- }
1425
- lines.push(line);
1426
- line = word2;
1427
- }
1428
- }
1429
- lines.push(line);
1430
- }
1431
- return lines;
1455
+ return wrapAnsi(value, Math.max(1, width), { hard: true, trim: true }).split("\n");
1432
1456
  }
1433
1457
  function renderRows(rows, theme, width) {
1434
1458
  if (rows.length === 0) return [];
1435
- const labelWidth = Math.max(...rows.map((row) => row.label.length));
1459
+ const labelWidth = Math.max(...rows.map((row) => stringWidth(row.label)));
1436
1460
  const valueWidth = Math.max(20, width - labelWidth - 2);
1437
1461
  const continuation = " ".repeat(labelWidth + 2);
1438
1462
  return rows.flatMap((row) => {
@@ -1453,12 +1477,16 @@ function renderDetailCard(options) {
1453
1477
  ${options.theme.muted(options.badges.map((badge) => badge[0] + badge.slice(1).toLowerCase()).join(" \xB7 "))}` : identity;
1454
1478
  const blocks = [hero];
1455
1479
  for (const prose of options.prose ?? []) {
1456
- blocks.push(prose.title ? [options.theme.header(prose.title), wrap(prose.value, width).join("\n")].join("\n") : wrap(prose.value, width).join("\n"));
1480
+ blocks.push(
1481
+ prose.title ? [options.theme.header(prose.title), wrap(prose.value, width).join("\n")].join("\n") : wrap(prose.value, width).join("\n")
1482
+ );
1457
1483
  }
1458
1484
  for (const section of options.sections ?? []) {
1459
1485
  if (section.rows.length === 0) continue;
1460
1486
  const rows = renderRows(section.rows, options.theme, width);
1461
- blocks.push(section.title ? [options.theme.header(section.title), ...rows].join("\n") : rows.join("\n"));
1487
+ blocks.push(
1488
+ section.title ? [options.theme.header(section.title), ...rows].join("\n") : rows.join("\n")
1489
+ );
1462
1490
  }
1463
1491
  return blocks.join("\n\n");
1464
1492
  }
@@ -1885,13 +1913,13 @@ import { LineCounter, parse, parseDocument } from "yaml";
1885
1913
  // ../frontmatter/src/stringify.ts
1886
1914
  import { stringify } from "yaml";
1887
1915
 
1916
+ // ../toolcraft-design/src/dashboard/terminal-width.ts
1917
+ var graphemeSegmenter3 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1918
+
1888
1919
  // ../toolcraft-design/src/acp/writer.ts
1889
1920
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1890
1921
  var storage = new AsyncLocalStorage2();
1891
1922
 
1892
- // ../toolcraft-design/src/dashboard/terminal-width.ts
1893
- var graphemeSegmenter3 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1894
-
1895
1923
  // ../toolcraft-design/src/dashboard/terminal.ts
1896
1924
  import readline from "node:readline";
1897
1925
  import { PassThrough } from "node:stream";
@@ -1988,8 +2016,8 @@ function mapKey(name, char) {
1988
2016
  }
1989
2017
 
1990
2018
  // ../toolcraft-design/src/prompts/interactive/wrap.ts
1991
- import { wrapAnsi } from "fast-wrap-ansi";
1992
- import stringWidth from "fast-string-width";
2019
+ import { wrapAnsi as wrapAnsi2 } from "fast-wrap-ansi";
2020
+ import stringWidth2 from "fast-string-width";
1993
2021
  function getColumns(output) {
1994
2022
  return Math.max(1, output.columns ?? 80);
1995
2023
  }
@@ -1997,7 +2025,7 @@ function getRows(output) {
1997
2025
  return Math.max(1, output.rows ?? 20);
1998
2026
  }
1999
2027
  function wrapFrame(output, frame) {
2000
- return wrapAnsi(frame, getColumns(output), { hard: true, trim: false });
2028
+ return wrapAnsi2(frame, getColumns(output), { hard: true, trim: false });
2001
2029
  }
2002
2030
 
2003
2031
  // ../toolcraft-design/src/prompts/interactive/core.ts
@@ -2318,7 +2346,7 @@ function confirmPrompt(opts) {
2318
2346
  }
2319
2347
 
2320
2348
  // ../toolcraft-design/src/prompts/interactive/pagination.ts
2321
- import { wrapAnsi as wrapAnsi2 } from "fast-wrap-ansi";
2349
+ import { wrapAnsi as wrapAnsi3 } from "fast-wrap-ansi";
2322
2350
  function countLines(values) {
2323
2351
  return values.reduce((sum, value) => sum + value.split("\n").length, 0);
2324
2352
  }
@@ -2361,7 +2389,7 @@ function limitOptions(opts) {
2361
2389
  }
2362
2390
  const hasTopMarker = cappedVisibleCount < options.length && start > 0;
2363
2391
  const hasBottomMarker = cappedVisibleCount < options.length && start + cappedVisibleCount < options.length;
2364
- const visible = options.slice(start, start + cappedVisibleCount).map((option, index) => wrapAnsi2(style(option, start + index === cursor2), columns, { hard: true, trim: false }));
2392
+ const visible = options.slice(start, start + cappedVisibleCount).map((option, index) => wrapAnsi3(style(option, start + index === cursor2), columns, { hard: true, trim: false }));
2365
2393
  const trimmed = trimToRows(
2366
2394
  visible,
2367
2395
  Math.max(cursor2 - start, 0),
@@ -2744,6 +2772,9 @@ function isOptionalSchema(schema) {
2744
2772
  function getRequiredKeys(schema) {
2745
2773
  return Object.keys(schema.shape).filter((key2) => !isOptionalSchema(schema.shape[key2])).sort();
2746
2774
  }
2775
+ function getRequiredKeyFingerprint(schema) {
2776
+ return getRequiredKeys(schema).join("+");
2777
+ }
2747
2778
  function assertUniqueRequiredKeyFingerprints(branches) {
2748
2779
  const fingerprints = /* @__PURE__ */ new Map();
2749
2780
  branches.forEach((branch, index) => {
@@ -2781,6 +2812,451 @@ function Union(branches) {
2781
2812
  };
2782
2813
  }
2783
2814
 
2815
+ // ../toolcraft-schema/src/validate.ts
2816
+ var missingValue = /* @__PURE__ */ Symbol("missingValue");
2817
+ function validate(schema, value) {
2818
+ const state = { issues: [] };
2819
+ const result = walkSchema(schema, value, [], state);
2820
+ if (state.issues.length > 0) {
2821
+ return { ok: false, issues: state.issues };
2822
+ }
2823
+ return { ok: true, value: result.present ? result.value : void 0 };
2824
+ }
2825
+ function walkSchema(schema, value, path26, state) {
2826
+ if (schema.kind === "optional") {
2827
+ return walkOptional(schema, value, path26, state);
2828
+ }
2829
+ if (value === missingValue) {
2830
+ addIssue(
2831
+ state,
2832
+ path26,
2833
+ expectedFor(schema),
2834
+ "missing",
2835
+ `Expected ${expectedFor(schema)} at ${formatPath(path26)}`
2836
+ );
2837
+ return { present: false };
2838
+ }
2839
+ if (value === null && schema.nullable === true) {
2840
+ return { present: true, value };
2841
+ }
2842
+ switch (schema.kind) {
2843
+ case "string":
2844
+ return walkString(schema, value, path26, state);
2845
+ case "number":
2846
+ return walkNumber(schema, value, path26, state);
2847
+ case "boolean":
2848
+ return walkBoolean(value, path26, state);
2849
+ case "enum":
2850
+ return walkEnum(schema, value, path26, state);
2851
+ case "array":
2852
+ return walkArray(schema, value, path26, state);
2853
+ case "object":
2854
+ return walkObject(schema, value, path26, state);
2855
+ case "oneOf":
2856
+ return walkOneOf(schema, value, path26, state);
2857
+ case "union":
2858
+ return walkUnion(schema, value, path26, state);
2859
+ case "record":
2860
+ return walkRecord(schema, value, path26, state);
2861
+ case "json":
2862
+ return walkJson(value, path26, state);
2863
+ }
2864
+ }
2865
+ function walkOptional(schema, value, path26, state) {
2866
+ if (value === missingValue || value === void 0) {
2867
+ const defaultValue = getDefault(schema.inner);
2868
+ if (defaultValue.present) {
2869
+ return walkSchema(schema.inner, cloneDefault(defaultValue.value), path26, state);
2870
+ }
2871
+ return { present: false };
2872
+ }
2873
+ return walkSchema(schema.inner, value, path26, state);
2874
+ }
2875
+ function walkString(schema, value, path26, state) {
2876
+ if (typeof value !== "string") {
2877
+ addExpectedIssue(state, path26, "string", value);
2878
+ return { present: true, value };
2879
+ }
2880
+ if (schema.minLength !== void 0 && value.length < schema.minLength) {
2881
+ const expected = `string with length at least ${schema.minLength}`;
2882
+ addIssue(
2883
+ state,
2884
+ path26,
2885
+ expected,
2886
+ `string with length ${value.length}`,
2887
+ `Expected ${expected} at ${formatPath(path26)}`
2888
+ );
2889
+ }
2890
+ if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
2891
+ const expected = `string with length at most ${schema.maxLength}`;
2892
+ addIssue(
2893
+ state,
2894
+ path26,
2895
+ expected,
2896
+ `string with length ${value.length}`,
2897
+ `Expected ${expected} at ${formatPath(path26)}`
2898
+ );
2899
+ }
2900
+ if (schema.pattern !== void 0) {
2901
+ const pattern = compilePattern(schema.pattern);
2902
+ if (pattern === void 0 || !pattern.test(value)) {
2903
+ const expected = `string matching pattern ${schema.pattern}`;
2904
+ addIssue(state, path26, expected, value, `Expected ${expected} at ${formatPath(path26)}`);
2905
+ }
2906
+ }
2907
+ return { present: true, value };
2908
+ }
2909
+ function walkNumber(schema, value, path26, state) {
2910
+ if (typeof value !== "number" || !Number.isFinite(value)) {
2911
+ addExpectedIssue(state, path26, schema.jsonType === "integer" ? "integer" : "number", value);
2912
+ return { present: true, value };
2913
+ }
2914
+ if (schema.jsonType === "integer" && !Number.isInteger(value)) {
2915
+ addExpectedIssue(state, path26, "integer", value);
2916
+ }
2917
+ if (schema.minimum !== void 0 && value < schema.minimum) {
2918
+ const expected = `number greater than or equal to ${schema.minimum}`;
2919
+ addIssue(state, path26, expected, String(value), `Expected ${expected} at ${formatPath(path26)}`);
2920
+ }
2921
+ if (schema.maximum !== void 0 && value > schema.maximum) {
2922
+ const expected = `number less than or equal to ${schema.maximum}`;
2923
+ addIssue(state, path26, expected, String(value), `Expected ${expected} at ${formatPath(path26)}`);
2924
+ }
2925
+ return { present: true, value };
2926
+ }
2927
+ function walkBoolean(value, path26, state) {
2928
+ if (typeof value !== "boolean") {
2929
+ addExpectedIssue(state, path26, "boolean", value);
2930
+ }
2931
+ return { present: true, value };
2932
+ }
2933
+ function walkEnum(schema, value, path26, state) {
2934
+ if (!schema.values.includes(value)) {
2935
+ const expected = `one of ${schema.values.join(", ")}`;
2936
+ addIssue(
2937
+ state,
2938
+ path26,
2939
+ expected,
2940
+ receivedValue(value),
2941
+ `Expected ${expected} at ${formatPath(path26)}`
2942
+ );
2943
+ }
2944
+ return { present: true, value };
2945
+ }
2946
+ function walkArray(schema, value, path26, state) {
2947
+ if (!Array.isArray(value)) {
2948
+ addExpectedIssue(state, path26, "array", value);
2949
+ return { present: true, value };
2950
+ }
2951
+ if (schema.minItems !== void 0 && value.length < schema.minItems) {
2952
+ const expected = `array with at least ${schema.minItems} items`;
2953
+ addIssue(
2954
+ state,
2955
+ path26,
2956
+ expected,
2957
+ `array with ${value.length} items`,
2958
+ `Expected ${expected} at ${formatPath(path26)}`
2959
+ );
2960
+ }
2961
+ if (schema.maxItems !== void 0 && value.length > schema.maxItems) {
2962
+ const expected = `array with at most ${schema.maxItems} items`;
2963
+ addIssue(
2964
+ state,
2965
+ path26,
2966
+ expected,
2967
+ `array with ${value.length} items`,
2968
+ `Expected ${expected} at ${formatPath(path26)}`
2969
+ );
2970
+ }
2971
+ const nextValue = value.map((item, index) => {
2972
+ const result = walkSchema(schema.item, item, [...path26, String(index)], state);
2973
+ return result.present ? result.value : item;
2974
+ });
2975
+ return { present: true, value: nextValue };
2976
+ }
2977
+ function walkObject(schema, value, path26, state, injectedProperties = {}) {
2978
+ if (!isPlainRecord(value)) {
2979
+ addExpectedIssue(state, path26, "object", value);
2980
+ return { present: true, value };
2981
+ }
2982
+ const nextValue = {};
2983
+ const allowedKeys = /* @__PURE__ */ new Set([...Object.keys(schema.shape), ...Object.keys(injectedProperties)]);
2984
+ for (const [key2, propertySchema] of Object.entries(schema.shape)) {
2985
+ const propertyValue = Object.hasOwn(value, key2) ? value[key2] : missingValue;
2986
+ const result = walkSchema(propertySchema, propertyValue, [...path26, key2], state);
2987
+ if (result.present) {
2988
+ setOwnValue(nextValue, key2, result.value);
2989
+ }
2990
+ }
2991
+ for (const [key2, injectedValue] of Object.entries(injectedProperties)) {
2992
+ if (Object.hasOwn(value, key2)) {
2993
+ setOwnValue(nextValue, key2, value[key2]);
2994
+ } else {
2995
+ setOwnValue(nextValue, key2, injectedValue);
2996
+ }
2997
+ }
2998
+ for (const [key2, propertyValue] of Object.entries(value)) {
2999
+ if (allowedKeys.has(key2)) {
3000
+ continue;
3001
+ }
3002
+ if (schema.additionalProperties === true) {
3003
+ setOwnValue(nextValue, key2, propertyValue);
3004
+ } else {
3005
+ addUnexpectedPropertyIssue(state, [...path26, key2]);
3006
+ }
3007
+ }
3008
+ return { present: true, value: nextValue };
3009
+ }
3010
+ function walkOneOf(schema, value, path26, state) {
3011
+ if (!isPlainRecord(value)) {
3012
+ addExpectedIssue(state, path26, "object", value);
3013
+ return { present: true, value };
3014
+ }
3015
+ const discriminatorValue = value[schema.discriminator];
3016
+ const discriminatorPath = [...path26, schema.discriminator];
3017
+ const branchValues = Object.keys(schema.branches);
3018
+ const expected = `one of ${branchValues.join(", ")}`;
3019
+ if (!Object.hasOwn(value, schema.discriminator)) {
3020
+ addIssueWithMessage(
3021
+ state,
3022
+ discriminatorPath,
3023
+ expected,
3024
+ "missing",
3025
+ `Missing discriminator "${schema.discriminator}" at ${formatPath(path26)}. Expected one of: ${branchValues.join(", ")}.`
3026
+ );
3027
+ return { present: true, value };
3028
+ }
3029
+ if (typeof discriminatorValue !== "string" || !Object.hasOwn(schema.branches, discriminatorValue)) {
3030
+ addIssueWithMessage(
3031
+ state,
3032
+ discriminatorPath,
3033
+ expected,
3034
+ receivedValue(discriminatorValue),
3035
+ `Expected ${expected} at ${formatPath(discriminatorPath)}, got ${formatReceivedDiscriminator(discriminatorValue)}`
3036
+ );
3037
+ return { present: true, value };
3038
+ }
3039
+ return walkObject(schema.branches[discriminatorValue], value, path26, state, {
3040
+ [schema.discriminator]: discriminatorValue
3041
+ });
3042
+ }
3043
+ function walkUnion(schema, value, path26, state) {
3044
+ if (isPlainRecord(value)) {
3045
+ const candidateBranches = schema.branches.filter((branch) => hasRequiredKeys(branch, value));
3046
+ if (candidateBranches.length === 1) {
3047
+ return walkObject(candidateBranches[0], value, path26, state);
3048
+ }
3049
+ }
3050
+ const matches = [];
3051
+ for (const branch of schema.branches) {
3052
+ const branchState = { issues: [] };
3053
+ const result = walkObject(branch, value, path26, branchState);
3054
+ if (branchState.issues.length === 0 && result.present) {
3055
+ matches.push({ fingerprint: getRequiredKeyFingerprint(branch), value: result.value });
3056
+ }
3057
+ }
3058
+ if (matches.length === 1) {
3059
+ return { present: true, value: matches[0].value };
3060
+ }
3061
+ if (matches.length === 0) {
3062
+ const branchDescriptions = schema.branches.map((branch) => getRequiredKeyFingerprint(branch));
3063
+ addIssueWithMessage(
3064
+ state,
3065
+ path26,
3066
+ "exactly one union branch",
3067
+ "0 matching branches",
3068
+ `No union branch matched at ${formatPath(path26)}. Tried ${schema.branches.length} branches. Expected one of: ${branchDescriptions.join(" | ")}.`
3069
+ );
3070
+ return { present: true, value };
3071
+ }
3072
+ addIssueWithMessage(
3073
+ state,
3074
+ path26,
3075
+ "exactly one union branch",
3076
+ `${matches.length} matching branches`,
3077
+ `Expected exactly one union branch at ${formatPath(path26)}, but matched more than one branch: ${matches.map((match) => match.fingerprint).join(" | ")}`
3078
+ );
3079
+ return { present: true, value };
3080
+ }
3081
+ function hasRequiredKeys(schema, value) {
3082
+ for (const [key2, propertySchema] of Object.entries(schema.shape)) {
3083
+ if (propertySchema.kind !== "optional" && !Object.hasOwn(value, key2)) {
3084
+ return false;
3085
+ }
3086
+ }
3087
+ return true;
3088
+ }
3089
+ function walkRecord(schema, value, path26, state) {
3090
+ if (!isPlainRecord(value)) {
3091
+ addExpectedIssue(state, path26, "object", value);
3092
+ return { present: true, value };
3093
+ }
3094
+ const nextValue = {};
3095
+ for (const [key2, propertyValue] of Object.entries(value)) {
3096
+ const result = walkSchema(schema.value, propertyValue, [...path26, key2], state);
3097
+ if (result.present) {
3098
+ setOwnValue(nextValue, key2, result.value);
3099
+ }
3100
+ }
3101
+ return { present: true, value: nextValue };
3102
+ }
3103
+ function walkJson(value, path26, state) {
3104
+ if (isJsonValue(value)) {
3105
+ return { present: true, value };
3106
+ }
3107
+ addExpectedIssue(state, path26, "JSON value", value);
3108
+ return { present: true, value };
3109
+ }
3110
+ function getDefault(schema) {
3111
+ if (schema.default !== void 0) {
3112
+ return { present: true, value: schema.default };
3113
+ }
3114
+ if (schema.kind === "optional") {
3115
+ return getDefault(schema.inner);
3116
+ }
3117
+ return { present: false };
3118
+ }
3119
+ function isPlainRecord(value) {
3120
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
3121
+ return false;
3122
+ }
3123
+ const prototype = Object.getPrototypeOf(value);
3124
+ return prototype === Object.prototype || prototype === null;
3125
+ }
3126
+ function isJsonValue(value, ancestors = /* @__PURE__ */ new Set()) {
3127
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3128
+ return typeof value !== "number" || Number.isFinite(value);
3129
+ }
3130
+ if (Array.isArray(value)) {
3131
+ if (ancestors.has(value)) {
3132
+ return false;
3133
+ }
3134
+ ancestors.add(value);
3135
+ const result = value.every((item) => isJsonValue(item, ancestors));
3136
+ ancestors.delete(value);
3137
+ return result;
3138
+ }
3139
+ if (isPlainRecord(value)) {
3140
+ if (ancestors.has(value)) {
3141
+ return false;
3142
+ }
3143
+ ancestors.add(value);
3144
+ const result = Object.values(value).every((item) => isJsonValue(item, ancestors));
3145
+ ancestors.delete(value);
3146
+ return result;
3147
+ }
3148
+ return false;
3149
+ }
3150
+ function cloneDefault(value) {
3151
+ return structuredClone(value);
3152
+ }
3153
+ function setOwnValue(target, key2, value) {
3154
+ Object.defineProperty(target, key2, {
3155
+ configurable: true,
3156
+ enumerable: true,
3157
+ writable: true,
3158
+ value
3159
+ });
3160
+ }
3161
+ function expectedFor(schema) {
3162
+ switch (schema.kind) {
3163
+ case "string":
3164
+ return "string";
3165
+ case "number":
3166
+ return schema.jsonType === "integer" ? "integer" : "number";
3167
+ case "boolean":
3168
+ return "boolean";
3169
+ case "enum":
3170
+ return `one of ${schema.values.join(", ")}`;
3171
+ case "array":
3172
+ return "array";
3173
+ case "object":
3174
+ case "oneOf":
3175
+ case "record":
3176
+ return "object";
3177
+ case "union":
3178
+ return "exactly one union branch";
3179
+ case "json":
3180
+ return "JSON value";
3181
+ case "optional":
3182
+ return expectedFor(schema.inner);
3183
+ }
3184
+ }
3185
+ function addExpectedIssue(state, path26, expected, value) {
3186
+ addIssue(
3187
+ state,
3188
+ path26,
3189
+ expected,
3190
+ receivedType(value),
3191
+ `Expected ${expected} at ${formatPath(path26)}`
3192
+ );
3193
+ }
3194
+ function addUnexpectedPropertyIssue(state, path26) {
3195
+ addIssue(
3196
+ state,
3197
+ path26,
3198
+ "no additional properties",
3199
+ "unknown property",
3200
+ `Unexpected property ${formatPath(path26)}`
3201
+ );
3202
+ }
3203
+ function addIssue(state, path26, expected, received, _message) {
3204
+ state.issues.push({
3205
+ path: path26,
3206
+ expected,
3207
+ received,
3208
+ message: formatIssueMessage(expected, path26, received)
3209
+ });
3210
+ }
3211
+ function addIssueWithMessage(state, path26, expected, received, message2) {
3212
+ state.issues.push({
3213
+ path: path26,
3214
+ expected,
3215
+ received,
3216
+ message: message2
3217
+ });
3218
+ }
3219
+ function formatIssueMessage(expected, path26, received) {
3220
+ return `Expected ${expected} at ${formatPath(path26)}, got ${received}`;
3221
+ }
3222
+ function formatPath(path26) {
3223
+ return path26.length === 0 ? "value" : path26.join(".");
3224
+ }
3225
+ function compilePattern(pattern) {
3226
+ try {
3227
+ return new RegExp(pattern);
3228
+ } catch {
3229
+ return void 0;
3230
+ }
3231
+ }
3232
+ function receivedType(value) {
3233
+ if (value === null) {
3234
+ return "null";
3235
+ }
3236
+ if (Array.isArray(value)) {
3237
+ return "array";
3238
+ }
3239
+ if (typeof value === "number" && Number.isInteger(value)) {
3240
+ return "integer";
3241
+ }
3242
+ return typeof value;
3243
+ }
3244
+ function receivedValue(value) {
3245
+ if (typeof value === "string") {
3246
+ return value;
3247
+ }
3248
+ if (value === void 0) {
3249
+ return "undefined";
3250
+ }
3251
+ return String(value);
3252
+ }
3253
+ function formatReceivedDiscriminator(value) {
3254
+ if (typeof value === "string") {
3255
+ return JSON.stringify(value);
3256
+ }
3257
+ return receivedValue(value);
3258
+ }
3259
+
2784
3260
  // ../toolcraft-schema/src/index.ts
2785
3261
  function assertValidEnumValues(values) {
2786
3262
  if (values.length === 0) {
@@ -2804,6 +3280,22 @@ function assertFiniteNumber(value, name) {
2804
3280
  throw new Error(`${name} must be finite`);
2805
3281
  }
2806
3282
  }
3283
+ function assertMinMaxOrder(minimum, maximum, minimumName, maximumName) {
3284
+ if (minimum !== void 0 && maximum !== void 0 && minimum > maximum) {
3285
+ throw new Error(`${minimumName} must be less than or equal to ${maximumName}`);
3286
+ }
3287
+ }
3288
+ function assertValidDefault(schema) {
3289
+ if (schema.default === void 0) {
3290
+ return;
3291
+ }
3292
+ const result = validate(schema, schema.default);
3293
+ if (!result.ok) {
3294
+ throw new Error(
3295
+ `default must satisfy schema: ${result.issues[0]?.message ?? "invalid default"}`
3296
+ );
3297
+ }
3298
+ }
2807
3299
  function assertPattern(pattern) {
2808
3300
  if (pattern === void 0) {
2809
3301
  return;
@@ -2818,56 +3310,71 @@ var S = {
2818
3310
  String(options = {}) {
2819
3311
  assertNonNegativeInteger(options.minLength, "minLength");
2820
3312
  assertNonNegativeInteger(options.maxLength, "maxLength");
3313
+ assertMinMaxOrder(options.minLength, options.maxLength, "minLength", "maxLength");
2821
3314
  assertPattern(options.pattern);
2822
- return {
3315
+ const schema = {
2823
3316
  kind: "string",
2824
3317
  ...options
2825
3318
  };
3319
+ assertValidDefault(schema);
3320
+ return schema;
2826
3321
  },
2827
3322
  Number(options = {}) {
2828
3323
  assertFiniteNumber(options.minimum, "minimum");
2829
3324
  assertFiniteNumber(options.maximum, "maximum");
3325
+ assertMinMaxOrder(options.minimum, options.maximum, "minimum", "maximum");
2830
3326
  assertFiniteNumber(options.default, "default");
2831
3327
  if (options.jsonType === "integer" && options.default !== void 0 && !Number.isInteger(options.default)) {
2832
3328
  throw new Error("default must be an integer");
2833
3329
  }
2834
- return {
3330
+ const schema = {
2835
3331
  kind: "number",
2836
3332
  ...options
2837
3333
  };
3334
+ assertValidDefault(schema);
3335
+ return schema;
2838
3336
  },
2839
3337
  Boolean(options = {}) {
2840
- return {
3338
+ const schema = {
2841
3339
  kind: "boolean",
2842
3340
  ...options
2843
3341
  };
3342
+ assertValidDefault(schema);
3343
+ return schema;
2844
3344
  },
2845
3345
  Enum(values, options = {}) {
2846
3346
  assertValidEnumValues(values);
2847
3347
  if (options.jsonType === "integer" && values.some((value) => typeof value !== "number" || !Number.isInteger(value))) {
2848
3348
  throw new Error("Integer enum values must be integers");
2849
3349
  }
2850
- return {
3350
+ const schema = {
2851
3351
  kind: "enum",
2852
3352
  values,
2853
3353
  ...options
2854
3354
  };
3355
+ assertValidDefault(schema);
3356
+ return schema;
2855
3357
  },
2856
3358
  Array(item, options = {}) {
2857
3359
  assertNonNegativeInteger(options.minItems, "minItems");
2858
3360
  assertNonNegativeInteger(options.maxItems, "maxItems");
2859
- return {
3361
+ assertMinMaxOrder(options.minItems, options.maxItems, "minItems", "maxItems");
3362
+ const schema = {
2860
3363
  kind: "array",
2861
3364
  item,
2862
3365
  ...options
2863
3366
  };
3367
+ assertValidDefault(schema);
3368
+ return schema;
2864
3369
  },
2865
3370
  Object(shape, options = {}) {
2866
- return {
3371
+ const schema = {
2867
3372
  kind: "object",
2868
3373
  shape,
2869
3374
  ...options
2870
3375
  };
3376
+ assertValidDefault(schema);
3377
+ return schema;
2871
3378
  },
2872
3379
  Optional(inner) {
2873
3380
  return {
@@ -3439,6 +3946,9 @@ function isRecord(value) {
3439
3946
  function isStateList(value) {
3440
3947
  return Array.isArray(value) && value.every((entry) => typeof entry === "string");
3441
3948
  }
3949
+ function hasVisibleName(value) {
3950
+ return value.trim().length > 0;
3951
+ }
3442
3952
  function canFireFromState(event, fromState) {
3443
3953
  if (event.from === "*") {
3444
3954
  return event.to !== fromState;
@@ -3453,6 +3963,9 @@ function validateMachine(machine) {
3453
3963
  throw new TypeError("State machine states must be a string array.");
3454
3964
  }
3455
3965
  const states = new Set(machine.states);
3966
+ if (machine.states.some((state) => !hasVisibleName(state))) {
3967
+ throw new Error("State names must not be empty.");
3968
+ }
3456
3969
  if (!hasOwnRecordField(machine, "initial") || typeof machine.initial !== "string") {
3457
3970
  throw new TypeError("State machine initial must be a string.");
3458
3971
  }
@@ -3463,6 +3976,9 @@ function validateMachine(machine) {
3463
3976
  throw new TypeError("State machine events must be an object.");
3464
3977
  }
3465
3978
  for (const [eventName, event] of Object.entries(machine.events)) {
3979
+ if (!hasVisibleName(eventName)) {
3980
+ throw new Error("Event names must not be empty.");
3981
+ }
3466
3982
  if (!isRecord(event)) {
3467
3983
  throw new TypeError(`Event "${eventName}" must be an object.`);
3468
3984
  }
@@ -3572,6 +4088,13 @@ import { text as text3 } from "node:stream/consumers";
3572
4088
  // ../process-runner/src/docker/context.ts
3573
4089
  import { execSync } from "node:child_process";
3574
4090
 
4091
+ // ../process-runner/src/docker/build-context.ts
4092
+ import { readdir, readFile } from "node:fs/promises";
4093
+ import { createRequire } from "node:module";
4094
+ import path2 from "node:path";
4095
+ var require2 = createRequire(import.meta.url);
4096
+ var createIgnore = require2("ignore");
4097
+
3575
4098
  // ../process-runner/src/docker/engine.ts
3576
4099
  import { execSync as execSync2 } from "node:child_process";
3577
4100
 
@@ -3580,19 +4103,19 @@ import * as childProcess from "node:child_process";
3580
4103
  import { randomBytes } from "node:crypto";
3581
4104
 
3582
4105
  // ../process-runner/src/docker/args.ts
3583
- import path2 from "node:path";
4106
+ import path3 from "node:path";
3584
4107
 
3585
4108
  // ../process-runner/src/docker/env-file.ts
3586
4109
  import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3587
4110
  import { tmpdir } from "node:os";
3588
- import path3 from "node:path";
4111
+ import path4 from "node:path";
3589
4112
 
3590
4113
  // ../process-runner/src/docker/docker-execution-env.ts
3591
4114
  import { createHash as createHash2, randomBytes as randomBytes2 } from "node:crypto";
3592
4115
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
3593
- import { readdir, readFile, realpath, writeFile } from "node:fs/promises";
4116
+ import { readFile as readFile2, realpath, writeFile } from "node:fs/promises";
3594
4117
  import { tmpdir as tmpdir2 } from "node:os";
3595
- import path5 from "node:path";
4118
+ import path6 from "node:path";
3596
4119
 
3597
4120
  // ../process-runner/src/host/host-runner.ts
3598
4121
  import { spawn as spawnChildProcess } from "node:child_process";
@@ -3725,7 +4248,7 @@ function bindAbortSignal(signal, onAbort) {
3725
4248
  // ../process-runner/src/workspace-transfer.ts
3726
4249
  import { createHash, randomUUID } from "node:crypto";
3727
4250
  import { promises as nodeFs } from "node:fs";
3728
- import path4 from "node:path";
4251
+ import path5 from "node:path";
3729
4252
 
3730
4253
  // ../process-runner/src/testing/mock-runner.ts
3731
4254
  import { Readable, Writable } from "node:stream";
@@ -3797,7 +4320,7 @@ function resolveEndpoint(options = {}) {
3797
4320
 
3798
4321
  // ../task-list/src/backends/utils.ts
3799
4322
  import { randomUUID as randomUUID2 } from "node:crypto";
3800
- import path6 from "node:path";
4323
+ import path7 from "node:path";
3801
4324
  function compareCreated(left, right) {
3802
4325
  const leftCreated = typeof left.raw.created === "string" ? left.raw.created : "";
3803
4326
  const rightCreated = typeof right.raw.created === "string" ? right.raw.created : "";
@@ -3829,15 +4352,33 @@ function sortStrings(values) {
3829
4352
  function sortTasks(tasks) {
3830
4353
  return [...tasks].sort((left, right) => left.qualifiedId.localeCompare(right.qualifiedId));
3831
4354
  }
4355
+ function isTrimmedPrintableIdentifier(value) {
4356
+ if (value.length === 0 || value !== value.trim()) {
4357
+ return false;
4358
+ }
4359
+ for (let index = 0; index < value.length; index += 1) {
4360
+ const code = value.charCodeAt(index);
4361
+ if (code < 32 || code === 127) {
4362
+ return false;
4363
+ }
4364
+ }
4365
+ return true;
4366
+ }
3832
4367
  function validateTaskId(id) {
3833
- if (id.length === 0 || id.startsWith(".") || id.includes("/") || id.includes("\\") || id.includes("..")) {
4368
+ if (!isTrimmedPrintableIdentifier(id) || id.startsWith(".") || id.includes("/") || id.includes("\\") || id.includes("..")) {
3834
4369
  throw new Error(`Invalid task id "${id}".`);
3835
4370
  }
3836
4371
  return id;
3837
4372
  }
3838
- async function statIfExists(fs4, filePath) {
4373
+ function validateTaskName(name) {
4374
+ if (name.trim().length === 0) {
4375
+ throw new Error("Task name must not be empty.");
4376
+ }
4377
+ return name;
4378
+ }
4379
+ async function statIfExists(fs5, filePath) {
3839
4380
  try {
3840
- return await fs4.stat(filePath);
4381
+ return await fs5.stat(filePath);
3841
4382
  } catch (error3) {
3842
4383
  if (hasErrorCode(error3, "ENOENT")) {
3843
4384
  return void 0;
@@ -3845,15 +4386,18 @@ async function statIfExists(fs4, filePath) {
3845
4386
  throw error3;
3846
4387
  }
3847
4388
  }
3848
- async function rejectSymbolicLinkComponents(fs4, filePath) {
3849
- const resolvedPath = path6.resolve(filePath);
3850
- const rootPath = path6.parse(resolvedPath).root;
3851
- const components = resolvedPath.slice(rootPath.length).split(path6.sep).filter(Boolean);
4389
+ async function rejectSymbolicLinkComponents(fs5, filePath) {
4390
+ const resolvedPath = path7.resolve(filePath);
4391
+ const rootPath = path7.parse(resolvedPath).root;
4392
+ const components = resolvedPath.slice(rootPath.length).split(path7.sep).filter(Boolean);
3852
4393
  let currentPath = rootPath;
3853
4394
  for (const component of components) {
3854
- currentPath = path6.join(currentPath, component);
4395
+ currentPath = path7.join(currentPath, component);
3855
4396
  try {
3856
- if ((await fs4.lstat(currentPath)).isSymbolicLink()) {
4397
+ if ((await fs5.lstat(currentPath)).isSymbolicLink()) {
4398
+ if (currentPath === "/tmp") {
4399
+ continue;
4400
+ }
3857
4401
  throw new Error(`Path "${filePath}" contains a symbolic link.`);
3858
4402
  }
3859
4403
  } catch (error3) {
@@ -3864,19 +4408,19 @@ async function rejectSymbolicLinkComponents(fs4, filePath) {
3864
4408
  }
3865
4409
  }
3866
4410
  }
3867
- async function writeAtomically(fs4, filePath, content) {
4411
+ async function writeAtomically(fs5, filePath, content) {
3868
4412
  const tempPath = `${filePath}.${process.pid}.${randomUUID2()}.tmp`;
3869
4413
  let tempCreated = false;
3870
- await fs4.mkdir(path6.dirname(filePath), { recursive: true });
4414
+ await fs5.mkdir(path7.dirname(filePath), { recursive: true });
3871
4415
  try {
3872
- await fs4.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
4416
+ await fs5.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
3873
4417
  tempCreated = true;
3874
- await fs4.rename(tempPath, filePath);
4418
+ await fs5.rename(tempPath, filePath);
3875
4419
  tempCreated = false;
3876
4420
  } catch (error3) {
3877
4421
  if (tempCreated || !hasErrorCode(error3, "EEXIST")) {
3878
4422
  try {
3879
- await fs4.unlink(tempPath);
4423
+ await fs5.unlink(tempPath);
3880
4424
  } catch (unlinkError) {
3881
4425
  if (!hasErrorCode(unlinkError, "ENOENT")) {
3882
4426
  throw unlinkError;
@@ -3886,18 +4430,18 @@ async function writeAtomically(fs4, filePath, content) {
3886
4430
  throw error3;
3887
4431
  }
3888
4432
  }
3889
- async function withFileLock(fs4, lockPath, operation) {
3890
- await fs4.mkdir(path6.dirname(lockPath), { recursive: true });
4433
+ async function withFileLock(fs5, lockPath, operation) {
4434
+ await fs5.mkdir(path7.dirname(lockPath), { recursive: true });
3891
4435
  for (; ; ) {
3892
4436
  try {
3893
- await fs4.writeFile(lockPath, String(process.pid), { encoding: "utf8", flag: "wx" });
4437
+ await fs5.writeFile(lockPath, String(process.pid), { encoding: "utf8", flag: "wx" });
3894
4438
  break;
3895
4439
  } catch (error3) {
3896
4440
  if (!hasErrorCode(error3, "EEXIST")) {
3897
- await fs4.unlink(lockPath).catch(() => void 0);
4441
+ await fs5.unlink(lockPath).catch(() => void 0);
3898
4442
  throw error3;
3899
4443
  }
3900
- if (await removeAbandonedLock(fs4, lockPath)) {
4444
+ if (await removeAbandonedLock(fs5, lockPath)) {
3901
4445
  continue;
3902
4446
  }
3903
4447
  await Promise.resolve();
@@ -3906,13 +4450,13 @@ async function withFileLock(fs4, lockPath, operation) {
3906
4450
  try {
3907
4451
  return await operation();
3908
4452
  } finally {
3909
- await fs4.unlink(lockPath);
4453
+ await fs5.unlink(lockPath);
3910
4454
  }
3911
4455
  }
3912
- async function removeAbandonedLock(fs4, lockPath) {
4456
+ async function removeAbandonedLock(fs5, lockPath) {
3913
4457
  let content;
3914
4458
  try {
3915
- content = await fs4.readFile(lockPath, "utf8");
4459
+ content = await fs5.readFile(lockPath, "utf8");
3916
4460
  } catch (error3) {
3917
4461
  if (hasErrorCode(error3, "ENOENT")) {
3918
4462
  return true;
@@ -3920,11 +4464,11 @@ async function removeAbandonedLock(fs4, lockPath) {
3920
4464
  throw error3;
3921
4465
  }
3922
4466
  const owner = Number(content);
3923
- if (!Number.isInteger(owner) || owner <= 0 || isProcessRunning(owner)) {
4467
+ if (Number.isInteger(owner) && owner > 0 && isProcessRunning(owner)) {
3924
4468
  return false;
3925
4469
  }
3926
4470
  try {
3927
- await fs4.unlink(lockPath);
4471
+ await fs5.unlink(lockPath);
3928
4472
  return true;
3929
4473
  } catch (error3) {
3930
4474
  if (hasErrorCode(error3, "ENOENT")) {
@@ -4192,6 +4736,9 @@ async function ghIssuesBackend(deps) {
4192
4736
  if (deps.state?.labelPrefix === "") {
4193
4737
  throw new Error("gh-issues state.labelPrefix must be a non-empty string when configured.");
4194
4738
  }
4739
+ if (deps.stateMachine !== void 0) {
4740
+ validateMachine(deps.stateMachine);
4741
+ }
4195
4742
  const client = createGhClient({
4196
4743
  token: deps.token,
4197
4744
  endpoint: deps.endpoint,
@@ -4351,7 +4898,9 @@ function createTasksView(name, session, context) {
4351
4898
  );
4352
4899
  projectItemId = added.addProjectV2ItemById?.item?.id ?? void 0;
4353
4900
  if (projectItemId === void 0) {
4354
- throw new Error("GitHub addProjectV2ItemById response did not include project item id.");
4901
+ throw new Error(
4902
+ "GitHub addProjectV2ItemById response did not include project item id."
4903
+ );
4355
4904
  }
4356
4905
  }
4357
4906
  if (session.labelPrefix === void 0) {
@@ -4580,12 +5129,15 @@ async function resolveProjectItemId(id, listName, session, context) {
4580
5129
  const issueNumber = parseIssueNumber(id, listName);
4581
5130
  let after;
4582
5131
  while (true) {
4583
- const result = await context.client.graphql(ISSUE_STATE_LABELS_QUERY, {
4584
- owner: context.repoOwner,
4585
- repo: context.repoName,
4586
- number: issueNumber,
4587
- after
4588
- });
5132
+ const result = await context.client.graphql(
5133
+ ISSUE_STATE_LABELS_QUERY,
5134
+ {
5135
+ owner: context.repoOwner,
5136
+ repo: context.repoName,
5137
+ number: issueNumber,
5138
+ after
5139
+ }
5140
+ );
4589
5141
  const issue = result.repository?.issue ?? null;
4590
5142
  if (issue === null) {
4591
5143
  throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
@@ -4862,12 +5414,27 @@ async function fetchIssueTask(id, listName, session, context) {
4862
5414
  });
4863
5415
  }
4864
5416
  function parseIssueNumber(id, listName) {
5417
+ if (!isCanonicalDecimalIssueId(id)) {
5418
+ throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
5419
+ }
4865
5420
  const issueNumber = Number(id);
4866
- if (!Number.isInteger(issueNumber) || issueNumber < 1) {
5421
+ if (!Number.isSafeInteger(issueNumber) || issueNumber < 1) {
4867
5422
  throw new TaskNotFoundError(`Task "${listName}/${id}" not found.`);
4868
5423
  }
4869
5424
  return issueNumber;
4870
5425
  }
5426
+ function isCanonicalDecimalIssueId(id) {
5427
+ if (id.length === 0 || id[0] === "0") {
5428
+ return false;
5429
+ }
5430
+ for (let index = 0; index < id.length; index += 1) {
5431
+ const charCode = id.charCodeAt(index);
5432
+ if (charCode < 48 || charCode > 57) {
5433
+ return false;
5434
+ }
5435
+ }
5436
+ return true;
5437
+ }
4871
5438
  function mapProjectItemToTask(item, listName, session) {
4872
5439
  const content = item.content;
4873
5440
  if (!isIssueNode(content)) {
@@ -4975,7 +5542,7 @@ function parseQualifiedId(qualifiedId, listName) {
4975
5542
  }
4976
5543
 
4977
5544
  // ../task-list/src/backends/markdown-dir.ts
4978
- import path7 from "node:path";
5545
+ import path8 from "node:path";
4979
5546
  import { parseDocument as parseDocument2, stringify as stringify2 } from "yaml";
4980
5547
 
4981
5548
  // ../task-list/src/schema/task.schema.json
@@ -5078,7 +5645,7 @@ function resolveListLayout(deps) {
5078
5645
  return deps.singleList ? { kind: "single", name: deps.singleList } : { kind: "multi" };
5079
5646
  }
5080
5647
  function validateListName(name) {
5081
- if (name.length === 0 || name === ARCHIVE_DIRECTORY_NAME || name.startsWith(".") || name.includes("/") || name.includes("\\") || name.includes("..")) {
5648
+ if (!isTrimmedPrintableIdentifier(name) || name === ARCHIVE_DIRECTORY_NAME || name.startsWith(".") || name.includes("/") || name.includes("\\") || name.includes("..")) {
5082
5649
  throw new Error(`Invalid task list name "${name}".`);
5083
5650
  }
5084
5651
  return name;
@@ -5094,16 +5661,16 @@ function parseQualifiedId2(qualifiedId) {
5094
5661
  };
5095
5662
  }
5096
5663
  function listPath(rootPath, layout, list) {
5097
- return layout.kind === "single" ? rootPath : path7.join(rootPath, list);
5664
+ return layout.kind === "single" ? rootPath : path8.join(rootPath, list);
5098
5665
  }
5099
5666
  function archiveDirectoryPath(rootPath, layout, list) {
5100
- return layout.kind === "single" ? path7.join(rootPath, ARCHIVE_DIRECTORY_NAME) : path7.join(rootPath, list, ARCHIVE_DIRECTORY_NAME);
5667
+ return layout.kind === "single" ? path8.join(rootPath, ARCHIVE_DIRECTORY_NAME) : path8.join(rootPath, list, ARCHIVE_DIRECTORY_NAME);
5101
5668
  }
5102
5669
  function activeTaskFilename(id, order, width) {
5103
5670
  return `${String(order).padStart(width, "0")}-${id}${MARKDOWN_EXTENSION}`;
5104
5671
  }
5105
5672
  function archivedTaskPath(rootPath, layout, list, id) {
5106
- return path7.join(archiveDirectoryPath(rootPath, layout, list), `${id}${MARKDOWN_EXTENSION}`);
5673
+ return path8.join(archiveDirectoryPath(rootPath, layout, list), `${id}${MARKDOWN_EXTENSION}`);
5107
5674
  }
5108
5675
  function isMarkdownFile(entryName) {
5109
5676
  return entryName.endsWith(MARKDOWN_EXTENSION);
@@ -5205,7 +5772,7 @@ function hasOwnTaskField(frontmatter, key2) {
5205
5772
  function reservedFrontmatterKeys(mode) {
5206
5773
  return mode === "passthrough" ? PASSTHROUGH_RESERVED_FRONTMATTER_KEYS : RESERVED_FRONTMATTER_KEYS;
5207
5774
  }
5208
- function setOwnValue(record, key2, value) {
5775
+ function setOwnValue2(record, key2, value) {
5209
5776
  Object.defineProperty(record, key2, {
5210
5777
  value,
5211
5778
  enumerable: true,
@@ -5218,7 +5785,7 @@ function metadataFromFrontmatter(frontmatter, mode) {
5218
5785
  const reservedKeys = reservedFrontmatterKeys(mode);
5219
5786
  for (const [key2, value] of Object.entries(frontmatter)) {
5220
5787
  if (!reservedKeys.has(key2)) {
5221
- setOwnValue(metadata, key2, value);
5788
+ setOwnValue2(metadata, key2, value);
5222
5789
  }
5223
5790
  }
5224
5791
  return metadata;
@@ -5232,7 +5799,7 @@ function createTask(list, id, frontmatter, body, mode, sourcePath) {
5232
5799
  state: frontmatter.state,
5233
5800
  description: body,
5234
5801
  metadata: metadataFromFrontmatter(frontmatter, mode),
5235
- ...sourcePath !== void 0 && { sourcePath: path7.resolve(sourcePath) }
5802
+ ...sourcePath !== void 0 && { sourcePath: path8.resolve(sourcePath) }
5236
5803
  };
5237
5804
  }
5238
5805
  function serializeTaskDocument(frontmatter, description) {
@@ -5241,9 +5808,9 @@ ${stringify2(frontmatter)}---
5241
5808
 
5242
5809
  ${description}`;
5243
5810
  }
5244
- async function readDirectoryNames(fs4, directoryPath) {
5811
+ async function readDirectoryNames(fs5, directoryPath) {
5245
5812
  try {
5246
- return sortStrings(await fs4.readdir(directoryPath));
5813
+ return sortStrings(await fs5.readdir(directoryPath));
5247
5814
  } catch (error3) {
5248
5815
  if (hasErrorCode(error3, "ENOENT")) {
5249
5816
  return [];
@@ -5259,9 +5826,9 @@ async function ensureRootPath(deps) {
5259
5826
  }
5260
5827
  await deps.fs.stat(deps.path);
5261
5828
  }
5262
- async function readTaskFile(fs4, list, id, filePath, validStates, initialState, mode) {
5263
- await rejectSymbolicLinkComponents(fs4, filePath);
5264
- const content = await fs4.readFile(filePath, "utf8");
5829
+ async function readTaskFile(fs5, list, id, filePath, validStates, initialState, mode) {
5830
+ await rejectSymbolicLinkComponents(fs5, filePath);
5831
+ const content = await fs5.readFile(filePath, "utf8");
5265
5832
  const document = splitTaskDocument(content, filePath, mode);
5266
5833
  const frontmatter = mode === "passthrough" && document.frontmatter.trim().length === 0 ? {} : readFrontmatter(document.frontmatter, filePath);
5267
5834
  if (mode !== "passthrough") {
@@ -5272,57 +5839,106 @@ async function readTaskFile(fs4, list, id, filePath, validStates, initialState,
5272
5839
  task: createTask(list, id, frontmatter, document.body, mode, filePath)
5273
5840
  };
5274
5841
  }
5275
- const parsedFilename = parseActiveFilename(path7.basename(filePath));
5276
- const defaultName = parsedFilename?.id ?? id;
5277
5842
  const effectiveFrontmatter = {
5278
5843
  ...frontmatter,
5279
- name: typeof frontmatter.name === "string" ? frontmatter.name : defaultName,
5844
+ name: typeof frontmatter.name === "string" ? frontmatter.name : id,
5280
5845
  state: typeof frontmatter.state === "string" && validStates.has(frontmatter.state) ? frontmatter.state : initialState
5281
5846
  };
5282
5847
  return {
5283
- path: filePath,
5284
- frontmatter,
5285
- task: createTask(list, id, effectiveFrontmatter, document.body, mode, filePath)
5848
+ path: filePath,
5849
+ frontmatter,
5850
+ task: createTask(list, id, effectiveFrontmatter, document.body, mode, filePath)
5851
+ };
5852
+ }
5853
+ async function readPassthroughFrontmatter(fs5, filePath, mode) {
5854
+ if (mode !== "passthrough") {
5855
+ return {};
5856
+ }
5857
+ const content = await fs5.readFile(filePath, "utf8");
5858
+ const document = splitTaskDocument(content, filePath, mode);
5859
+ if (document.frontmatter.trim().length === 0) {
5860
+ return {};
5861
+ }
5862
+ return readFrontmatter(document.frontmatter, filePath);
5863
+ }
5864
+ async function resolveActiveFilenameEntry(fs5, entryName, entryPath, parsed, mode) {
5865
+ if (mode !== "passthrough" || parsed.order === null) {
5866
+ return parsed;
5867
+ }
5868
+ const frontmatter = await readPassthroughFrontmatter(fs5, entryPath, mode);
5869
+ if (Object.keys(frontmatter).length === 0 && orderedFilenamePrefixLength(entryName) <= MIN_PREFIX_WIDTH) {
5870
+ return parsed;
5871
+ }
5872
+ if (typeof frontmatter.state === "string" || hasOwnTaskField(frontmatter, "$schema") || hasOwnTaskField(frontmatter, "kind") || hasOwnTaskField(frontmatter, "version")) {
5873
+ return parsed;
5874
+ }
5875
+ return {
5876
+ id: entryName.slice(0, -MARKDOWN_EXTENSION.length),
5877
+ order: null,
5878
+ filename: parsed.filename
5286
5879
  };
5287
5880
  }
5288
- async function findActiveTaskFilename(fs4, listDirectoryPath, id) {
5289
- const entries = await readDirectoryNames(fs4, listDirectoryPath);
5881
+ function orderedFilenamePrefixLength(entryName) {
5882
+ const stem = entryName.slice(0, -MARKDOWN_EXTENSION.length);
5883
+ const separatorIndex = stem.indexOf("-");
5884
+ if (separatorIndex <= 0) {
5885
+ return Number.POSITIVE_INFINITY;
5886
+ }
5887
+ for (let index = 0; index < separatorIndex; index += 1) {
5888
+ const code = stem.charCodeAt(index);
5889
+ if (code < 48 || code > 57) {
5890
+ return Number.POSITIVE_INFINITY;
5891
+ }
5892
+ }
5893
+ return separatorIndex;
5894
+ }
5895
+ async function findActiveTaskFilename(fs5, listDirectoryPath, id, mode) {
5896
+ const entries = await readDirectoryNames(fs5, listDirectoryPath);
5290
5897
  for (const entryName of entries) {
5291
5898
  if (isHiddenEntry(entryName)) continue;
5292
5899
  const parsed = parseActiveFilename(entryName);
5293
- if (parsed?.id === id) {
5900
+ if (!parsed) continue;
5901
+ const entryPath = path8.join(listDirectoryPath, entryName);
5902
+ const resolved = await resolveActiveFilenameEntry(
5903
+ fs5,
5904
+ entryName,
5905
+ entryPath,
5906
+ { id: parsed.id, order: parsed.order, filename: entryName },
5907
+ mode
5908
+ );
5909
+ if (resolved.id === id) {
5294
5910
  return entryName;
5295
5911
  }
5296
5912
  }
5297
5913
  return void 0;
5298
5914
  }
5299
- async function findTaskLocation(fs4, rootPath, layout, list, id) {
5915
+ async function findTaskLocation(fs5, rootPath, layout, list, id, mode) {
5300
5916
  const listDirectoryPath = listPath(rootPath, layout, list);
5301
- await rejectSymbolicLinkComponents(fs4, listDirectoryPath);
5302
- const activeName = await findActiveTaskFilename(fs4, listDirectoryPath, id);
5917
+ await rejectSymbolicLinkComponents(fs5, listDirectoryPath);
5918
+ const activeName = await findActiveTaskFilename(fs5, listDirectoryPath, id, mode);
5303
5919
  if (activeName) {
5304
- const activePath = path7.join(listDirectoryPath, activeName);
5305
- await rejectSymbolicLinkComponents(fs4, activePath);
5306
- const activeStat = await statIfExists(fs4, activePath);
5920
+ const activePath = path8.join(listDirectoryPath, activeName);
5921
+ await rejectSymbolicLinkComponents(fs5, activePath);
5922
+ const activeStat = await statIfExists(fs5, activePath);
5307
5923
  if (activeStat?.isFile()) {
5308
5924
  return { archived: false, path: activePath };
5309
5925
  }
5310
5926
  }
5311
5927
  const archivedPath = archivedTaskPath(rootPath, layout, list, id);
5312
- await rejectSymbolicLinkComponents(fs4, archiveDirectoryPath(rootPath, layout, list));
5313
- await rejectSymbolicLinkComponents(fs4, archivedPath);
5314
- const archivedStat = await statIfExists(fs4, archivedPath);
5928
+ await rejectSymbolicLinkComponents(fs5, archiveDirectoryPath(rootPath, layout, list));
5929
+ await rejectSymbolicLinkComponents(fs5, archivedPath);
5930
+ const archivedStat = await statIfExists(fs5, archivedPath);
5315
5931
  if (archivedStat?.isFile()) {
5316
5932
  return { archived: true, path: archivedPath };
5317
5933
  }
5318
5934
  return void 0;
5319
5935
  }
5320
- async function readTaskAtLocation(fs4, rootPath, layout, list, id, validStates, initialState, mode) {
5321
- const location = await findTaskLocation(fs4, rootPath, layout, list, id);
5936
+ async function readTaskAtLocation(fs5, rootPath, layout, list, id, validStates, initialState, mode) {
5937
+ const location = await findTaskLocation(fs5, rootPath, layout, list, id, mode);
5322
5938
  if (!location) {
5323
5939
  throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
5324
5940
  }
5325
- return readTaskFile(fs4, list, id, location.path, validStates, initialState, mode);
5941
+ return readTaskFile(fs5, list, id, location.path, validStates, initialState, mode);
5326
5942
  }
5327
5943
  function createdFrontmatter(defaults2, input, initialState, mode) {
5328
5944
  const frontmatter = mode !== "passthrough" ? {
@@ -5338,12 +5954,12 @@ function createdFrontmatter(defaults2, input, initialState, mode) {
5338
5954
  const reservedKeys = reservedFrontmatterKeys(mode);
5339
5955
  for (const [key2, value] of Object.entries(defaults2.metadata)) {
5340
5956
  if (!reservedKeys.has(key2)) {
5341
- setOwnValue(frontmatter, key2, value);
5957
+ setOwnValue2(frontmatter, key2, value);
5342
5958
  }
5343
5959
  }
5344
5960
  for (const [key2, value] of Object.entries(input.metadata ?? {})) {
5345
5961
  if (!reservedKeys.has(key2)) {
5346
- setOwnValue(frontmatter, key2, value);
5962
+ setOwnValue2(frontmatter, key2, value);
5347
5963
  }
5348
5964
  }
5349
5965
  frontmatter.created = (/* @__PURE__ */ new Date()).toISOString();
@@ -5365,7 +5981,7 @@ function updatedFrontmatter(existingFrontmatter, task, patch, mode) {
5365
5981
  const reservedKeys = reservedFrontmatterKeys(mode);
5366
5982
  for (const [key2, value] of Object.entries(patch.metadata ?? {})) {
5367
5983
  if (!reservedKeys.has(key2)) {
5368
- setOwnValue(nextFrontmatter, key2, value);
5984
+ setOwnValue2(nextFrontmatter, key2, value);
5369
5985
  }
5370
5986
  }
5371
5987
  return nextFrontmatter;
@@ -5389,7 +6005,7 @@ function firedFrontmatter(existingFrontmatter, task, to, mode, metadataPatch) {
5389
6005
  const reservedKeys = reservedFrontmatterKeys(mode);
5390
6006
  for (const [key2, value] of Object.entries(metadataPatch ?? {})) {
5391
6007
  if (!reservedKeys.has(key2)) {
5392
- setOwnValue(nextFrontmatter, key2, value);
6008
+ setOwnValue2(nextFrontmatter, key2, value);
5393
6009
  }
5394
6010
  }
5395
6011
  return nextFrontmatter;
@@ -5423,11 +6039,19 @@ function createTasksView2(deps, layout, list) {
5423
6039
  if (isHiddenEntry(entryName)) continue;
5424
6040
  const parsed = parseActiveFilename(entryName);
5425
6041
  if (!parsed) continue;
5426
- const entryPath = path7.join(listDirectoryPath, entryName);
6042
+ const entryPath = path8.join(listDirectoryPath, entryName);
5427
6043
  await rejectSymbolicLinkComponents(deps.fs, entryPath);
5428
6044
  const entryStat = await statIfExists(deps.fs, entryPath);
5429
6045
  if (!entryStat?.isFile()) continue;
5430
- result.push({ id: parsed.id, order: parsed.order, filename: entryName });
6046
+ result.push(
6047
+ await resolveActiveFilenameEntry(
6048
+ deps.fs,
6049
+ entryName,
6050
+ entryPath,
6051
+ { id: parsed.id, order: parsed.order, filename: entryName },
6052
+ deps.frontmatterMode
6053
+ )
6054
+ );
5431
6055
  }
5432
6056
  result.sort((left, right) => {
5433
6057
  const leftOrder = left.order ?? Number.POSITIVE_INFINITY;
@@ -5441,7 +6065,7 @@ function createTasksView2(deps, layout, list) {
5441
6065
  const entries = await readActiveEntries();
5442
6066
  const tasks = /* @__PURE__ */ new Map();
5443
6067
  for (const entry of entries) {
5444
- const filePath = path7.join(listDirectoryPath, entry.filename);
6068
+ const filePath = path8.join(listDirectoryPath, entry.filename);
5445
6069
  const file = await readTaskFile(
5446
6070
  deps.fs,
5447
6071
  list,
@@ -5462,7 +6086,7 @@ function createTasksView2(deps, layout, list) {
5462
6086
  const result = [];
5463
6087
  for (const entryName of entries) {
5464
6088
  if (isHiddenEntry(entryName) || !isMarkdownFile(entryName)) continue;
5465
- const entryPath = path7.join(archivePath, entryName);
6089
+ const entryPath = path8.join(archivePath, entryName);
5466
6090
  await rejectSymbolicLinkComponents(deps.fs, entryPath);
5467
6091
  const entryStat = await statIfExists(deps.fs, entryPath);
5468
6092
  if (!entryStat?.isFile()) continue;
@@ -5492,15 +6116,20 @@ function createTasksView2(deps, layout, list) {
5492
6116
  if (desiredOrder === void 0) continue;
5493
6117
  const desiredFilename = activeTaskFilename(entry.id, desiredOrder, width);
5494
6118
  if (entry.filename !== desiredFilename) {
5495
- const fromPath = path7.join(listDirectoryPath, entry.filename);
5496
- const stagingPath = path7.join(
6119
+ const fromPath = path8.join(listDirectoryPath, entry.filename);
6120
+ const stagingPath = path8.join(
5497
6121
  listDirectoryPath,
5498
6122
  `${desiredFilename}.staging-${process.pid}-${index}`
5499
6123
  );
5500
- const targetPath = path7.join(listDirectoryPath, desiredFilename);
6124
+ const targetPath = path8.join(listDirectoryPath, desiredFilename);
5501
6125
  try {
5502
6126
  await deps.fs.rename(fromPath, stagingPath);
5503
- staged.push({ original: fromPath, staging: stagingPath, target: targetPath, finalized: false });
6127
+ staged.push({
6128
+ original: fromPath,
6129
+ staging: stagingPath,
6130
+ target: targetPath,
6131
+ finalized: false
6132
+ });
5504
6133
  } catch (error3) {
5505
6134
  for (const stagedEntry of staged.reverse()) {
5506
6135
  await deps.fs.rename(stagedEntry.staging, stagedEntry.original);
@@ -5635,8 +6264,7 @@ function createTasksView2(deps, layout, list) {
5635
6264
  if (filter?.state && entry.task.state !== filter.state) return false;
5636
6265
  return true;
5637
6266
  });
5638
- const orderedActiveTasks = applyOrder(orderedActive, filter?.order);
5639
- return [...orderedActiveTasks, ...filteredArchived.map((entry) => entry.task)];
6267
+ return applyOrder([...orderedActive, ...filteredArchived], filter?.order);
5640
6268
  },
5641
6269
  async get(id) {
5642
6270
  return (await getTaskFile(id)).task;
@@ -5645,9 +6273,17 @@ function createTasksView2(deps, layout, list) {
5645
6273
  assertCreateDoesNotSetState(input);
5646
6274
  assertCreateHasId(input);
5647
6275
  validateTaskId(input.id);
6276
+ validateTaskName(input.name);
5648
6277
  await rejectSymbolicLinkComponents(deps.fs, listDirectoryPath);
5649
- return withFileLock(deps.fs, path7.join(listDirectoryPath, ".transition.lock"), async () => {
5650
- const existing = await findTaskLocation(deps.fs, deps.path, layout, list, input.id);
6278
+ return withFileLock(deps.fs, path8.join(listDirectoryPath, ".transition.lock"), async () => {
6279
+ const existing = await findTaskLocation(
6280
+ deps.fs,
6281
+ deps.path,
6282
+ layout,
6283
+ list,
6284
+ input.id,
6285
+ deps.frontmatterMode
6286
+ );
5651
6287
  if (existing) {
5652
6288
  throw new TaskAlreadyExistsError(`Task "${list}/${input.id}" already exists.`);
5653
6289
  }
@@ -5659,7 +6295,7 @@ function createTasksView2(deps, layout, list) {
5659
6295
  const nextOrder = maxOrder + 1;
5660
6296
  const width = padWidthForCount(activeEntries.length + 1);
5661
6297
  const filename = activeTaskFilename(input.id, nextOrder, width);
5662
- const targetPath = path7.join(listDirectoryPath, filename);
6298
+ const targetPath = path8.join(listDirectoryPath, filename);
5663
6299
  const frontmatter = createdFrontmatter(
5664
6300
  deps.defaults,
5665
6301
  input,
@@ -5668,12 +6304,22 @@ function createTasksView2(deps, layout, list) {
5668
6304
  );
5669
6305
  const description = input.description ?? "";
5670
6306
  await writeAtomically(deps.fs, targetPath, serializeTaskDocument(frontmatter, description));
5671
- return createTask(list, input.id, frontmatter, description, deps.frontmatterMode, targetPath);
6307
+ return createTask(
6308
+ list,
6309
+ input.id,
6310
+ frontmatter,
6311
+ description,
6312
+ deps.frontmatterMode,
6313
+ targetPath
6314
+ );
5672
6315
  });
5673
6316
  },
5674
6317
  async update(id, patch) {
5675
6318
  assertUpdateDoesNotSetState(patch);
5676
6319
  validateTaskId(id);
6320
+ if (patch.name !== void 0) {
6321
+ validateTaskName(patch.name);
6322
+ }
5677
6323
  const existing = await getTaskFile(id);
5678
6324
  const nextFrontmatter = updatedFrontmatter(
5679
6325
  existing.frontmatter,
@@ -5759,7 +6405,14 @@ function createTasksView2(deps, layout, list) {
5759
6405
  };
5760
6406
  if (stateMachine.events[eventName]?.to === "archived") {
5761
6407
  validateTaskId(id);
5762
- const location = await findTaskLocation(deps.fs, deps.path, layout, list, id);
6408
+ const location = await findTaskLocation(
6409
+ deps.fs,
6410
+ deps.path,
6411
+ layout,
6412
+ list,
6413
+ id,
6414
+ deps.frontmatterMode
6415
+ );
5763
6416
  if (!location) {
5764
6417
  throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
5765
6418
  }
@@ -5767,7 +6420,7 @@ function createTasksView2(deps, layout, list) {
5767
6420
  validateTaskId(id);
5768
6421
  const { event, nextTask } = await withFileLock(
5769
6422
  deps.fs,
5770
- path7.join(listDirectoryPath, ".transition.lock"),
6423
+ path8.join(listDirectoryPath, ".transition.lock"),
5771
6424
  fireTask
5772
6425
  );
5773
6426
  await event.onEnter?.(nextTask);
@@ -5787,7 +6440,14 @@ function createTasksView2(deps, layout, list) {
5787
6440
  },
5788
6441
  async delete(id) {
5789
6442
  validateTaskId(id);
5790
- const location = await findTaskLocation(deps.fs, deps.path, layout, list, id);
6443
+ const location = await findTaskLocation(
6444
+ deps.fs,
6445
+ deps.path,
6446
+ layout,
6447
+ list,
6448
+ id,
6449
+ deps.frontmatterMode
6450
+ );
5791
6451
  if (!location) {
5792
6452
  throw new TaskNotFoundError(`Task "${list}/${id}" not found.`);
5793
6453
  }
@@ -5860,7 +6520,7 @@ async function markdownDirBackend(deps) {
5860
6520
  if (entryName === ARCHIVE_DIRECTORY_NAME || isHiddenEntry(entryName)) {
5861
6521
  continue;
5862
6522
  }
5863
- const entryPath = path7.join(deps.path, entryName);
6523
+ const entryPath = path8.join(deps.path, entryName);
5864
6524
  await rejectSymbolicLinkComponents(deps.fs, entryPath);
5865
6525
  const entryStat = await statIfExists(deps.fs, entryPath);
5866
6526
  if (entryStat?.isDirectory()) {
@@ -5902,12 +6562,26 @@ async function markdownDirBackend(deps) {
5902
6562
  }
5903
6563
  const targetListDir = listPath(deps.path, layout, targetListName);
5904
6564
  await rejectSymbolicLinkComponents(deps.fs, targetListDir);
5905
- return withFileLock(deps.fs, path7.join(targetListDir, ".transition.lock"), async () => {
5906
- const targetExisting = await findTaskLocation(deps.fs, deps.path, layout, targetListName, id);
6565
+ return withFileLock(deps.fs, path8.join(targetListDir, ".transition.lock"), async () => {
6566
+ const targetExisting = await findTaskLocation(
6567
+ deps.fs,
6568
+ deps.path,
6569
+ layout,
6570
+ targetListName,
6571
+ id,
6572
+ deps.frontmatterMode
6573
+ );
5907
6574
  if (targetExisting) {
5908
6575
  throw new TaskAlreadyExistsError(`Task "${targetListName}/${id}" already exists.`);
5909
6576
  }
5910
- const sourceLocation = await findTaskLocation(deps.fs, deps.path, layout, sourceListName, id);
6577
+ const sourceLocation = await findTaskLocation(
6578
+ deps.fs,
6579
+ deps.path,
6580
+ layout,
6581
+ sourceListName,
6582
+ id,
6583
+ deps.frontmatterMode
6584
+ );
5911
6585
  if (!sourceLocation) {
5912
6586
  throw new TaskNotFoundError(`Task "${sourceListName}/${id}" not found.`);
5913
6587
  }
@@ -5952,7 +6626,7 @@ async function markdownDirBackend(deps) {
5952
6626
  );
5953
6627
  const width = padWidthForCount(targetEntries.length + 1);
5954
6628
  const targetFilename = activeTaskFilename(id, maxOrder + 1, width);
5955
- const targetPath = path7.join(targetListDir, targetFilename);
6629
+ const targetPath = path8.join(targetListDir, targetFilename);
5956
6630
  await deps.fs.rename(sourceLocation.path, targetPath);
5957
6631
  return createTask(
5958
6632
  targetListName,
@@ -5974,7 +6648,7 @@ async function markdownDirBackend(deps) {
5974
6648
  }
5975
6649
 
5976
6650
  // ../task-list/src/backends/yaml-file.ts
5977
- import path8 from "node:path";
6651
+ import path9 from "node:path";
5978
6652
  import { isMap, parseDocument as parseDocument3 } from "yaml";
5979
6653
 
5980
6654
  // ../task-list/src/schema/store.schema.json
@@ -6034,7 +6708,7 @@ function malformedTask2(list, id, field) {
6034
6708
  return new MalformedTaskError(`Malformed task "${list}/${id}": invalid "${field}".`);
6035
6709
  }
6036
6710
  function validateListName2(name) {
6037
- if (name.length === 0 || name.startsWith(".") || name.includes("/") || name.includes("\\") || name.includes("..")) {
6711
+ if (!isTrimmedPrintableIdentifier(name) || name.startsWith(".") || name.includes("/") || name.includes("\\") || name.includes("..")) {
6038
6712
  throw new Error(`Invalid task list name "${name}".`);
6039
6713
  }
6040
6714
  return name;
@@ -6071,7 +6745,7 @@ function createTask2(list, id, taskRecord, sourcePath) {
6071
6745
  state: getOwnEntry(taskRecord, "state"),
6072
6746
  description: descriptionFromTaskRecord(taskRecord),
6073
6747
  metadata: metadataFromTaskRecord(taskRecord),
6074
- ...sourcePath !== void 0 && { sourcePath: path8.resolve(sourcePath) }
6748
+ ...sourcePath !== void 0 && { sourcePath: path9.resolve(sourcePath) }
6075
6749
  };
6076
6750
  }
6077
6751
  function matchesFilter(task, filter) {
@@ -6242,8 +6916,8 @@ function serializeDocument(document) {
6242
6916
  return serialized.endsWith("\n") ? serialized : `${serialized}
6243
6917
  `;
6244
6918
  }
6245
- async function readStore(fs4, filePath, validStates) {
6246
- const content = await fs4.readFile(filePath, "utf8");
6919
+ async function readStore(fs5, filePath, validStates) {
6920
+ const content = await fs5.readFile(filePath, "utf8");
6247
6921
  const document = parseStoreDocument(filePath, content);
6248
6922
  const store = document.toJS();
6249
6923
  assertValidStoreRecord(store, filePath);
@@ -6383,6 +7057,7 @@ function createTasksView3(deps, list) {
6383
7057
  assertCreateDoesNotSetState2(input);
6384
7058
  assertCreateHasId2(input);
6385
7059
  validateTaskId(input.id);
7060
+ validateTaskName(input.name);
6386
7061
  const { document, store } = await readStore(deps.fs, deps.path, validStates);
6387
7062
  if (getTaskRecord(store, list, input.id)) {
6388
7063
  throw new TaskAlreadyExistsError(`Task "${list}/${input.id}" already exists.`);
@@ -6395,6 +7070,9 @@ function createTasksView3(deps, list) {
6395
7070
  async update(id, patch) {
6396
7071
  assertUpdateDoesNotSetState2(patch);
6397
7072
  validateTaskId(id);
7073
+ if (patch.name !== void 0) {
7074
+ validateTaskName(patch.name);
7075
+ }
6398
7076
  const { document, store } = await readStore(deps.fs, deps.path, validStates);
6399
7077
  const existing = getTaskOrThrow(store, list, id);
6400
7078
  const nextTaskRecord = buildUpdatedTaskRecord(existing, patch);
@@ -6486,6 +7164,11 @@ function createTasksView3(deps, list) {
6486
7164
  insertIndex = anchor.position === "top" ? 0 : listNode.items.length;
6487
7165
  } else {
6488
7166
  const anchorId = "before" in anchor ? anchor.before : anchor.after;
7167
+ const activeIds = new Set(activeItemIds(listNode, validStates));
7168
+ if (!activeIds.has(anchorId)) {
7169
+ listNode.items.splice(fromIndex, 0, movedPair);
7170
+ throw new AnchorNotFoundError(anchorId);
7171
+ }
6489
7172
  const anchorIndex = findItemIndex(listNode, anchorId);
6490
7173
  if (anchorIndex < 0) {
6491
7174
  listNode.items.splice(fromIndex, 0, movedPair);
@@ -6670,7 +7353,7 @@ function isRecord4(value) {
6670
7353
 
6671
7354
  // ../task-list/src/move.ts
6672
7355
  import * as fsPromises2 from "node:fs/promises";
6673
- import path9 from "node:path";
7356
+ import path10 from "node:path";
6674
7357
 
6675
7358
  // ../toolcraft/src/human-in-loop/approval-tasks.ts
6676
7359
  import { randomBytes as randomBytes3 } from "node:crypto";
@@ -6857,7 +7540,7 @@ function areEqualStrings(left, right) {
6857
7540
  }
6858
7541
 
6859
7542
  // ../toolcraft/src/human-in-loop/runner.ts
6860
- import { access, lstat, readFile as readFile2, rename, unlink, writeFile as writeFile2 } from "node:fs/promises";
7543
+ import { access, lstat, readFile as readFile3, rename, unlink, writeFile as writeFile2 } from "node:fs/promises";
6861
7544
 
6862
7545
  // ../toolcraft/src/human-in-loop/default-provider.ts
6863
7546
  import process3 from "node:process";
@@ -6889,7 +7572,7 @@ on error number -128
6889
7572
  end try`;
6890
7573
  }
6891
7574
  function parseStdout(out) {
6892
- const value = out.endsWith("\r\n") ? out.slice(0, -2) : out.endsWith("\n") ? out.slice(0, -1) : out;
7575
+ 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;
6893
7576
  switch (value) {
6894
7577
  case "Approve":
6895
7578
  case "APPROVED":
@@ -7169,13 +7852,13 @@ function formatAvailableApprovalCommandPaths(root) {
7169
7852
  }
7170
7853
  function enumerateApprovalCommandPaths(root) {
7171
7854
  const paths = [];
7172
- const visit = (node, path25) => {
7855
+ const visit = (node, path26) => {
7173
7856
  if (node.kind === "command") {
7174
- paths.push(path25.join("."));
7857
+ paths.push(path26.join("."));
7175
7858
  return;
7176
7859
  }
7177
7860
  for (const child of getVisibleCliChildren(node)) {
7178
- visit(child, [...path25, child.name]);
7861
+ visit(child, [...path26, child.name]);
7179
7862
  }
7180
7863
  };
7181
7864
  if (root.kind === "command") {
@@ -7210,21 +7893,21 @@ function createHandlerContext(command, params17) {
7210
7893
  }
7211
7894
  function createFs() {
7212
7895
  return {
7213
- readFile: async (path25, encoding = "utf8") => readFile2(path25, { encoding }),
7214
- writeFile: async (path25, contents, options) => {
7215
- await writeFile2(path25, contents, options);
7896
+ readFile: async (path26, encoding = "utf8") => readFile3(path26, { encoding }),
7897
+ writeFile: async (path26, contents, options) => {
7898
+ await writeFile2(path26, contents, options);
7216
7899
  },
7217
- exists: async (path25) => {
7900
+ exists: async (path26) => {
7218
7901
  try {
7219
- await access(path25);
7902
+ await access(path26);
7220
7903
  return true;
7221
7904
  } catch {
7222
7905
  return false;
7223
7906
  }
7224
7907
  },
7225
- lstat: async (path25) => lstat(path25),
7908
+ lstat: async (path26) => lstat(path26),
7226
7909
  rename: async (fromPath, toPath) => rename(fromPath, toPath),
7227
- unlink: async (path25) => unlink(path25)
7910
+ unlink: async (path26) => unlink(path26)
7228
7911
  };
7229
7912
  }
7230
7913
  function createEnv(values = process.env) {
@@ -7503,13 +8186,13 @@ function isMissingStateError(error3) {
7503
8186
  import { mkdir as mkdir2, realpath as realpath2, writeFile as writeFile4 } from "node:fs/promises";
7504
8187
  import { randomUUID as randomUUID5 } from "node:crypto";
7505
8188
  import os from "node:os";
7506
- import path13 from "node:path";
8189
+ import path14 from "node:path";
7507
8190
  import { CommanderError } from "commander";
7508
8191
 
7509
8192
  // ../toolcraft/src/mcp-proxy.ts
7510
8193
  import { existsSync as existsSync2 } from "node:fs";
7511
- import { lstat as lstat2, mkdir, readFile as readFile3, rename as rename2, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
7512
- import path12 from "node:path";
8194
+ import { lstat as lstat2, mkdir, readFile as readFile4, rename as rename2, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
8195
+ import path13 from "node:path";
7513
8196
  import { createHash as createHash3, randomUUID as randomUUID4 } from "node:crypto";
7514
8197
 
7515
8198
  // ../tiny-mcp-client/src/internal.ts
@@ -7518,13 +8201,13 @@ import { PassThrough as PassThrough2 } from "node:stream";
7518
8201
 
7519
8202
  // ../mcp-oauth/src/client/auth-store-session-store.ts
7520
8203
  import crypto from "node:crypto";
7521
- import path11 from "node:path";
8204
+ import path12 from "node:path";
7522
8205
 
7523
8206
  // ../auth-store/src/encrypted-file-store.ts
7524
8207
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes4, randomUUID as randomUUID3, scrypt } from "node:crypto";
7525
8208
  import { promises as fs } from "node:fs";
7526
8209
  import { homedir, hostname, userInfo } from "node:os";
7527
- import path10 from "node:path";
8210
+ import path11 from "node:path";
7528
8211
 
7529
8212
  // ../auth-store/src/error-codes.ts
7530
8213
  function hasOwnErrorCode3(error3, code) {
@@ -7553,10 +8236,13 @@ var EncryptedFileStore = class {
7553
8236
  if (input.filePath === void 0) {
7554
8237
  const homeDirectory = (input.getHomeDirectory ?? homedir)();
7555
8238
  const defaultDirectory = input.defaultDirectory ?? ".auth-store";
7556
- this.filePath = path10.join(
8239
+ const defaultFileName = input.defaultFileName ?? "credentials.enc";
8240
+ assertSafeDefaultDirectory(defaultDirectory);
8241
+ assertSafeDefaultFileName(defaultFileName);
8242
+ this.filePath = path11.join(
7557
8243
  homeDirectory,
7558
8244
  defaultDirectory,
7559
- input.defaultFileName ?? "credentials.enc"
8245
+ defaultFileName
7560
8246
  );
7561
8247
  this.symbolicLinkCheckStartPath = resolveDefaultDirectoryCheckStart(
7562
8248
  homeDirectory,
@@ -7616,7 +8302,7 @@ var EncryptedFileStore = class {
7616
8302
  authTag: authTag.toString("base64"),
7617
8303
  ciphertext: ciphertext.toString("base64")
7618
8304
  };
7619
- await this.fs.mkdir(path10.dirname(this.filePath), { recursive: true });
8305
+ await this.fs.mkdir(path11.dirname(this.filePath), { recursive: true });
7620
8306
  await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
7621
8307
  const temporaryPath = `${this.filePath}.${process.pid}.${randomUUID3()}.tmp`;
7622
8308
  let temporaryCreated = false;
@@ -7648,7 +8334,7 @@ var EncryptedFileStore = class {
7648
8334
  }
7649
8335
  }
7650
8336
  async assertCredentialPathHasNoSymbolicLinks(targetPath) {
7651
- const resolvedPath = path10.resolve(targetPath);
8337
+ const resolvedPath = path11.resolve(targetPath);
7652
8338
  const protectedPaths = getProtectedCredentialPaths(
7653
8339
  resolvedPath,
7654
8340
  this.symbolicLinkCheckStartPath
@@ -7682,27 +8368,62 @@ var EncryptedFileStore = class {
7682
8368
  };
7683
8369
  function resolveDefaultDirectoryCheckStart(homeDirectory, defaultDirectory) {
7684
8370
  const [firstSegment] = defaultDirectory.split(/[\\/]+/).filter(Boolean);
7685
- return path10.resolve(homeDirectory, firstSegment ?? ".");
8371
+ return path11.resolve(homeDirectory, firstSegment ?? ".");
7686
8372
  }
7687
8373
  function getProtectedCredentialPaths(resolvedPath, symbolicLinkCheckStartPath) {
7688
8374
  if (symbolicLinkCheckStartPath === null) {
7689
- return [path10.dirname(resolvedPath), resolvedPath];
8375
+ return getExplicitProtectedCredentialPaths(resolvedPath);
7690
8376
  }
7691
- const resolvedStartPath = path10.resolve(symbolicLinkCheckStartPath);
8377
+ const resolvedStartPath = path11.resolve(symbolicLinkCheckStartPath);
7692
8378
  if (!isPathInsideOrEqual(resolvedPath, resolvedStartPath)) {
7693
- return [path10.dirname(resolvedPath), resolvedPath];
8379
+ return [path11.dirname(resolvedPath), resolvedPath];
7694
8380
  }
7695
8381
  const protectedPaths = [resolvedStartPath];
7696
8382
  let currentPath = resolvedStartPath;
7697
- for (const segment of path10.relative(resolvedStartPath, resolvedPath).split(path10.sep).filter(Boolean)) {
7698
- currentPath = path10.join(currentPath, segment);
8383
+ for (const segment of path11.relative(resolvedStartPath, resolvedPath).split(path11.sep).filter(Boolean)) {
8384
+ currentPath = path11.join(currentPath, segment);
8385
+ protectedPaths.push(currentPath);
8386
+ }
8387
+ return protectedPaths;
8388
+ }
8389
+ function assertSafeDefaultDirectory(defaultDirectory) {
8390
+ if (path11.isAbsolute(defaultDirectory) || path11.win32.isAbsolute(defaultDirectory)) {
8391
+ throw new Error("defaultDirectory must be a relative path inside the home directory");
8392
+ }
8393
+ for (const segment of splitPathSegments(defaultDirectory)) {
8394
+ if (segment === "..") {
8395
+ throw new Error("defaultDirectory must be a relative path inside the home directory");
8396
+ }
8397
+ }
8398
+ }
8399
+ function assertSafeDefaultFileName(defaultFileName) {
8400
+ if (defaultFileName.trim().length === 0 || defaultFileName === "." || defaultFileName === ".." || splitPathSegments(defaultFileName).length !== 1) {
8401
+ throw new Error("defaultFileName must be a file name without path separators");
8402
+ }
8403
+ }
8404
+ function splitPathSegments(value) {
8405
+ return value.split("/").flatMap((segment) => segment.split("\\")).filter((segment) => segment.length > 0);
8406
+ }
8407
+ function getExplicitProtectedCredentialPaths(resolvedPath) {
8408
+ const parsed = path11.parse(resolvedPath);
8409
+ const segments = resolvedPath.slice(parsed.root.length).split(path11.sep).filter((segment) => segment.length > 0);
8410
+ if (segments.length <= 1) {
8411
+ return [resolvedPath];
8412
+ }
8413
+ const protectedPaths = [];
8414
+ let currentPath = parsed.root;
8415
+ for (const [index, segment] of segments.entries()) {
8416
+ currentPath = path11.join(currentPath, segment);
8417
+ if (index === 0) {
8418
+ continue;
8419
+ }
7699
8420
  protectedPaths.push(currentPath);
7700
8421
  }
7701
8422
  return protectedPaths;
7702
8423
  }
7703
8424
  function isPathInsideOrEqual(childPath, parentPath) {
7704
- const relativePath = path10.relative(parentPath, childPath);
7705
- return relativePath === "" || !relativePath.startsWith("..") && !path10.isAbsolute(relativePath);
8425
+ const relativePath = path11.relative(parentPath, childPath);
8426
+ return relativePath === "" || !relativePath.startsWith("..") && !path11.isAbsolute(relativePath);
7706
8427
  }
7707
8428
  async function removeIfPresent(fileSystem, filePath) {
7708
8429
  try {
@@ -7793,8 +8514,14 @@ var KeychainStore = class {
7793
8514
  account;
7794
8515
  constructor(input) {
7795
8516
  this.runCommand = input.runCommand ?? runSecurityCommand;
7796
- this.service = input.service;
7797
- this.account = input.account;
8517
+ this.service = input.service.trim();
8518
+ this.account = input.account.trim();
8519
+ if (this.service.length === 0) {
8520
+ throw new Error("Keychain service must not be empty");
8521
+ }
8522
+ if (this.account.length === 0) {
8523
+ throw new Error("Keychain account must not be empty");
8524
+ }
7798
8525
  }
7799
8526
  async get() {
7800
8527
  const result = await this.executeSecurityCommand(
@@ -7821,10 +8548,10 @@ var KeychainStore = class {
7821
8548
  "-a",
7822
8549
  this.account,
7823
8550
  "-U",
7824
- "-w"
8551
+ "-w",
8552
+ value
7825
8553
  ],
7826
- "store secret in macOS Keychain",
7827
- { stdin: value }
8554
+ "store secret in macOS Keychain"
7828
8555
  );
7829
8556
  if (getCommandExitCode(result) !== 0) {
7830
8557
  throw createSecurityCliFailure("store secret in macOS Keychain", result);
@@ -7969,13 +8696,14 @@ function createSecretStore(input) {
7969
8696
  function resolveBackend(input) {
7970
8697
  const envVar = input.backendEnvVar ?? DEFAULT_BACKEND_ENV_VAR;
7971
8698
  const configuredBackend = input.backend ?? getOwnEnvValue(input.env, envVar) ?? getOwnEnvValue(process.env, envVar);
7972
- if (configuredBackend === "keychain") {
8699
+ const backend = configuredBackend?.trim();
8700
+ if (backend === "keychain") {
7973
8701
  return "keychain";
7974
8702
  }
7975
- if (configuredBackend === void 0 || configuredBackend === "file") {
8703
+ if (backend === void 0 || backend === "file") {
7976
8704
  return "file";
7977
8705
  }
7978
- throw new Error(`Unsupported auth store backend: ${configuredBackend}`);
8706
+ throw new Error(`Unsupported auth store backend: ${backend}`);
7979
8707
  }
7980
8708
  function getOwnEnvValue(env, key2) {
7981
8709
  return env !== void 0 && Object.prototype.hasOwnProperty.call(env, key2) ? env[key2] : void 0;
@@ -8000,6 +8728,7 @@ var DEFAULT_KEYCHAIN_SERVICE = "poe-code-mcp-oauth";
8000
8728
  var DEFAULT_CLIENT_FILE_SALT = "poe-code:mcp-oauth:clients:v1";
8001
8729
  var DEFAULT_CLIENT_FILE_DIRECTORY = ".poe-code/mcp-oauth/clients";
8002
8730
  var DEFAULT_CLIENT_KEYCHAIN_SERVICE = "poe-code-mcp-oauth-clients";
8731
+ var MAX_JS_DATE_MS = 864e13;
8003
8732
  function createAuthStoreSessionStore(options = {}) {
8004
8733
  return {
8005
8734
  async load(resource) {
@@ -8009,10 +8738,10 @@ function createAuthStoreSessionStore(options = {}) {
8009
8738
  return null;
8010
8739
  }
8011
8740
  const parsed = JSON.parse(value);
8012
- if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
8741
+ if (isStoredOAuthSession(parsed)) {
8013
8742
  return parsed;
8014
8743
  }
8015
- throw new Error("Stored OAuth session must be a JSON object");
8744
+ throw new Error("Stored OAuth session must match the expected shape");
8016
8745
  },
8017
8746
  async save(resource, session) {
8018
8747
  const store = createResourceSecretStore(resource, options);
@@ -8056,10 +8785,10 @@ function createAuthStoreClientStore(options) {
8056
8785
  function createNamedSecretStore(key2, options, defaults2) {
8057
8786
  const hash = crypto.createHash("sha256").update(key2).digest("hex");
8058
8787
  const configuredFilePath = options.fileStore?.filePath;
8059
- const parsedFilePath = configuredFilePath === void 0 ? null : path11.parse(configuredFilePath);
8788
+ const parsedFilePath = configuredFilePath === void 0 ? null : path12.parse(configuredFilePath);
8060
8789
  const fileStore = {
8061
8790
  ...options.fileStore,
8062
- filePath: parsedFilePath === null ? void 0 : path11.join(
8791
+ filePath: parsedFilePath === null ? void 0 : path12.join(
8063
8792
  parsedFilePath.dir,
8064
8793
  `${parsedFilePath.name}-${hash}${parsedFilePath.ext || ".enc"}`
8065
8794
  ),
@@ -8075,28 +8804,20 @@ function createNamedSecretStore(key2, options, defaults2) {
8075
8804
  return createSecretStore({ ...options, fileStore, keychainStore }).store;
8076
8805
  }
8077
8806
  function createResourceSecretStore(resource, options) {
8078
- return createNamedSecretStore(
8079
- canonicalizeResourceIndicator(resource),
8080
- options,
8081
- {
8082
- salt: DEFAULT_FILE_SALT,
8083
- directory: DEFAULT_FILE_DIRECTORY,
8084
- service: DEFAULT_KEYCHAIN_SERVICE,
8085
- accountPrefix: "provider"
8086
- }
8087
- );
8807
+ return createNamedSecretStore(canonicalizeResourceIndicator(resource), options, {
8808
+ salt: DEFAULT_FILE_SALT,
8809
+ directory: DEFAULT_FILE_DIRECTORY,
8810
+ service: DEFAULT_KEYCHAIN_SERVICE,
8811
+ accountPrefix: "provider"
8812
+ });
8088
8813
  }
8089
8814
  function createIssuerSecretStore(issuer, options) {
8090
- return createNamedSecretStore(
8091
- issuer,
8092
- options,
8093
- {
8094
- salt: DEFAULT_CLIENT_FILE_SALT,
8095
- directory: DEFAULT_CLIENT_FILE_DIRECTORY,
8096
- service: DEFAULT_CLIENT_KEYCHAIN_SERVICE,
8097
- accountPrefix: "issuer"
8098
- }
8099
- );
8815
+ return createNamedSecretStore(issuer, options, {
8816
+ salt: DEFAULT_CLIENT_FILE_SALT,
8817
+ directory: DEFAULT_CLIENT_FILE_DIRECTORY,
8818
+ service: DEFAULT_CLIENT_KEYCHAIN_SERVICE,
8819
+ accountPrefix: "issuer"
8820
+ });
8100
8821
  }
8101
8822
  function isObjectRecord(value) {
8102
8823
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -8108,6 +8829,50 @@ function getOwnString(record, key2) {
8108
8829
  const value = getOwnEntry4(record, key2);
8109
8830
  return typeof value === "string" ? value : void 0;
8110
8831
  }
8832
+ function isStoredOAuthSession(value) {
8833
+ if (!isObjectRecord(value)) {
8834
+ return false;
8835
+ }
8836
+ return isNonBlankOwnString(value, "resource") && isNonBlankOwnString(value, "authorizationServer") && isStoredOAuthClient(getOwnEntry4(value, "client")) && isStoredOAuthDiscovery(getOwnEntry4(value, "discovery")) && isStoredOAuthTokensOrMissing(getOwnEntry4(value, "tokens"));
8837
+ }
8838
+ function isStoredOAuthClient(value) {
8839
+ if (!isObjectRecord(value) || !isNonBlankOwnString(value, "clientId")) {
8840
+ return false;
8841
+ }
8842
+ const clientSecret = getOwnEntry4(value, "clientSecret");
8843
+ return clientSecret === void 0 || typeof clientSecret === "string" && clientSecret.trim().length > 0;
8844
+ }
8845
+ function isStoredOAuthDiscovery(value) {
8846
+ if (!isObjectRecord(value)) {
8847
+ return false;
8848
+ }
8849
+ return isNonBlankOwnString(value, "resourceMetadataUrl") && isObjectRecord(getOwnEntry4(value, "resourceMetadata")) && isObjectRecord(getOwnEntry4(value, "authorizationServerMetadata"));
8850
+ }
8851
+ function isStoredOAuthTokensOrMissing(value) {
8852
+ if (value === void 0) {
8853
+ return true;
8854
+ }
8855
+ if (!isObjectRecord(value)) {
8856
+ return false;
8857
+ }
8858
+ if (!isNonBlankOwnString(value, "accessToken") || getOwnString(value, "tokenType") !== "Bearer") {
8859
+ return false;
8860
+ }
8861
+ const expiresAt = getOwnEntry4(value, "expiresAt");
8862
+ if (expiresAt !== null && (typeof expiresAt !== "number" || !Number.isSafeInteger(expiresAt) || expiresAt > MAX_JS_DATE_MS || !Number.isFinite(new Date(expiresAt).getTime()))) {
8863
+ return false;
8864
+ }
8865
+ const refreshToken = getOwnEntry4(value, "refreshToken");
8866
+ if (refreshToken !== void 0 && (typeof refreshToken !== "string" || refreshToken.trim().length === 0)) {
8867
+ return false;
8868
+ }
8869
+ const scope = getOwnEntry4(value, "scope");
8870
+ return scope === void 0 || typeof scope === "string" && scope.trim().length > 0;
8871
+ }
8872
+ function isNonBlankOwnString(record, key2) {
8873
+ const value = getOwnString(record, key2);
8874
+ return value !== void 0 && value.trim().length > 0;
8875
+ }
8111
8876
 
8112
8877
  // ../mcp-oauth/src/client/default-oauth-client-provider.ts
8113
8878
  import { URL as URL2 } from "node:url";
@@ -8218,9 +8983,7 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
8218
8983
  } catch (error3) {
8219
8984
  res.writeHead(400);
8220
8985
  res.end(error3 instanceof Error ? error3.message : "Invalid OAuth callback");
8221
- if (callbackParameters.error === null) {
8222
- settle(() => reject(error3 instanceof Error ? error3 : new Error(String(error3))));
8223
- }
8986
+ settle(() => reject(error3 instanceof Error ? error3 : new Error(String(error3))));
8224
8987
  return;
8225
8988
  }
8226
8989
  const authorizationError = callbackParameters.error;
@@ -8232,7 +8995,10 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
8232
8995
  return;
8233
8996
  }
8234
8997
  try {
8235
- const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
8998
+ const code = validateAuthorizationCallbackParameters(
8999
+ callbackParameters,
9000
+ expectedAuthorization
9001
+ );
8236
9002
  res.writeHead(200, { "Content-Type": "text/html" });
8237
9003
  res.end(buildSuccessPage(options.landingPage));
8238
9004
  settle(() => resolve(code));
@@ -8255,7 +9021,10 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
8255
9021
  const description = callbackParameters.errorDescription ?? callbackParameters.error;
8256
9022
  throw createAuthorizationError(callbackParameters.error, description);
8257
9023
  }
8258
- const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
9024
+ const code = validateAuthorizationCallbackParameters(
9025
+ callbackParameters,
9026
+ expectedAuthorization
9027
+ );
8259
9028
  settle(() => resolve(code));
8260
9029
  } catch (error3) {
8261
9030
  settle(() => reject(error3 instanceof Error ? error3 : new Error(String(error3))));
@@ -8360,6 +9129,7 @@ function generateCodeChallenge(verifier) {
8360
9129
  }
8361
9130
 
8362
9131
  // ../mcp-oauth/src/client/token-endpoint.ts
9132
+ var MAX_JS_DATE_MS2 = 864e13;
8363
9133
  var OAuthError = class extends Error {
8364
9134
  error;
8365
9135
  errorDescription;
@@ -8437,22 +9207,32 @@ async function requestTokens(input) {
8437
9207
  if (typeof accessToken !== "string" || accessToken.trim().length === 0) {
8438
9208
  throw new Error("OAuth token response missing access_token");
8439
9209
  }
9210
+ const normalizedAccessToken = accessToken.trim();
8440
9211
  const tokenType = normalizeBearerTokenType(getOwnEntry6(payload, "token_type"));
8441
9212
  if (tokenType === null) {
8442
9213
  throw new Error("OAuth token response missing token_type=Bearer");
8443
9214
  }
8444
9215
  const expiresIn = getOwnEntry6(payload, "expires_in");
8445
- if (typeof expiresIn === "number" && Number.isFinite(expiresIn) && expiresIn < 0) {
8446
- throw new Error("OAuth token response has invalid expires_in");
9216
+ let expiresAt = null;
9217
+ if (expiresIn !== void 0) {
9218
+ if (typeof expiresIn !== "number" || !Number.isFinite(expiresIn) || !Number.isInteger(expiresIn) || expiresIn < 0) {
9219
+ throw new Error("OAuth token response has invalid expires_in");
9220
+ }
9221
+ expiresAt = input.now() + expiresIn * 1e3;
9222
+ if (!Number.isSafeInteger(expiresAt) || expiresAt > MAX_JS_DATE_MS2 || !Number.isFinite(new Date(expiresAt).getTime())) {
9223
+ throw new Error("OAuth token response has invalid expires_in");
9224
+ }
8447
9225
  }
8448
9226
  const refreshToken = getOwnEntry6(payload, "refresh_token");
8449
9227
  const scope = getOwnEntry6(payload, "scope");
9228
+ const normalizedRefreshToken = typeof refreshToken === "string" && refreshToken.trim().length > 0 ? refreshToken.trim() : void 0;
9229
+ const normalizedScope = typeof scope === "string" && scope.trim().length > 0 ? scope.trim() : void 0;
8450
9230
  return {
8451
- accessToken,
8452
- refreshToken: typeof refreshToken === "string" && refreshToken.length > 0 ? refreshToken : void 0,
9231
+ accessToken: normalizedAccessToken,
9232
+ refreshToken: normalizedRefreshToken === void 0 ? void 0 : normalizedRefreshToken,
8453
9233
  tokenType,
8454
- expiresAt: typeof expiresIn === "number" && Number.isFinite(expiresIn) ? input.now() + expiresIn * 1e3 : null,
8455
- scope: typeof scope === "string" && scope.length > 0 ? scope : void 0
9234
+ expiresAt,
9235
+ scope: normalizedScope === void 0 ? void 0 : normalizedScope
8456
9236
  };
8457
9237
  }
8458
9238
  async function readOAuthJsonObjectResponse(response) {
@@ -8503,6 +9283,7 @@ function normalizeBearerTokenType(value) {
8503
9283
  }
8504
9284
 
8505
9285
  // ../mcp-oauth/src/client/default-oauth-client-provider.ts
9286
+ var MAX_JS_DATE_MS3 = 864e13;
8506
9287
  function createOAuthClientProvider(options) {
8507
9288
  if (isProviderOptions(options)) {
8508
9289
  return options.provider;
@@ -8667,7 +9448,12 @@ function createDefaultOAuthClientProvider(options) {
8667
9448
  });
8668
9449
  let resolvedClient = null;
8669
9450
  try {
8670
- resolvedClient = await resolveClient(currentSession, discovery, loopback.redirectUri, fetch2);
9451
+ resolvedClient = await resolveClient(
9452
+ currentSession,
9453
+ discovery,
9454
+ loopback.redirectUri,
9455
+ fetch2
9456
+ );
8671
9457
  const sessionWithoutTokens = {
8672
9458
  resource,
8673
9459
  authorizationServer: discovery.authorizationServer,
@@ -8734,28 +9520,26 @@ function createDefaultOAuthClientProvider(options) {
8734
9520
  return finalPromise;
8735
9521
  }
8736
9522
  async function resolveClient(existingSession, discovery, redirectUri, fetch2) {
9523
+ const configuredClient = normalizeConfiguredClient(options.client);
8737
9524
  if (options.client.mode === "static") {
9525
+ if (configuredClient === null) {
9526
+ throw new Error("OAuth client_id must not be blank");
9527
+ }
8738
9528
  return {
8739
9529
  kind: "static",
8740
9530
  fromStoredRegistration: false,
8741
- client: {
8742
- clientId: options.client.clientId,
8743
- clientSecret: options.client.clientSecret
8744
- }
9531
+ client: configuredClient
8745
9532
  };
8746
9533
  }
8747
9534
  const registrationEndpoint = getOwnString2(
8748
9535
  discovery.authorizationServerMetadata,
8749
9536
  "registration_endpoint"
8750
9537
  );
8751
- if (registrationEndpoint === void 0 && options.client.clientId !== void 0) {
9538
+ if (registrationEndpoint === void 0 && configuredClient !== null) {
8752
9539
  return {
8753
9540
  kind: "static",
8754
9541
  fromStoredRegistration: false,
8755
- client: {
8756
- clientId: options.client.clientId,
8757
- clientSecret: options.client.clientSecret
8758
- }
9542
+ client: configuredClient
8759
9543
  };
8760
9544
  }
8761
9545
  const storedClient = await loadRegisteredClient(discovery.authorizationServer);
@@ -8777,7 +9561,7 @@ function createDefaultOAuthClientProvider(options) {
8777
9561
  throw new Error("Authorization server metadata is missing registration_endpoint");
8778
9562
  }
8779
9563
  if (existingSession !== null && existingSession.client.clientId.length > 0) {
8780
- const isConfiguredStaticFallback = options.client.clientId !== void 0 && existingSession.client.clientId === options.client.clientId && existingSession.client.clientSecret === options.client.clientSecret;
9564
+ const isConfiguredStaticFallback = configuredClient !== null && existingSession.client.clientId === configuredClient.clientId && existingSession.client.clientSecret === configuredClient.clientSecret;
8781
9565
  if (!isConfiguredStaticFallback) {
8782
9566
  await saveRegisteredClient(discovery.authorizationServer, existingSession.client);
8783
9567
  return {
@@ -8805,8 +9589,8 @@ function createDefaultOAuthClientProvider(options) {
8805
9589
  }
8806
9590
  const clientSecret = getOwnString2(payload, "client_secret");
8807
9591
  const registeredClient = {
8808
- clientId,
8809
- clientSecret: clientSecret !== void 0 && clientSecret.length > 0 ? clientSecret : void 0
9592
+ clientId: clientId.trim(),
9593
+ clientSecret: clientSecret !== void 0 && clientSecret.trim().length > 0 ? clientSecret.trim() : void 0
8810
9594
  };
8811
9595
  await saveRegisteredClient(discovery.authorizationServer, registeredClient);
8812
9596
  return {
@@ -8919,14 +9703,16 @@ function normalizeStoredClient(value) {
8919
9703
  if (clientId === void 0 || clientId.trim().length === 0) {
8920
9704
  return null;
8921
9705
  }
9706
+ const normalizedClientId = clientId.trim();
8922
9707
  const clientSecret = getOwnEntry7(value, "clientSecret");
8923
9708
  if (clientSecret === void 0) {
8924
- return { clientId };
9709
+ return { clientId: normalizedClientId };
8925
9710
  }
8926
9711
  if (typeof clientSecret !== "string" || clientSecret.trim().length === 0) {
8927
9712
  return null;
8928
9713
  }
8929
- return { clientId, clientSecret };
9714
+ const normalizedClientSecret = clientSecret.trim();
9715
+ return { clientId: normalizedClientId, clientSecret: normalizedClientSecret };
8930
9716
  }
8931
9717
  function normalizeStoredTokens(value) {
8932
9718
  if (value === void 0 || !isObjectRecord3(value)) {
@@ -8937,20 +9723,45 @@ function normalizeStoredTokens(value) {
8937
9723
  const expiresAt = getOwnEntry7(value, "expiresAt");
8938
9724
  const refreshToken = getOwnEntry7(value, "refreshToken");
8939
9725
  const scope = getOwnString2(value, "scope");
8940
- const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken : void 0;
8941
- 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)) {
9726
+ const normalizedAccessToken = accessToken?.trim();
9727
+ const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken.trim() : void 0;
9728
+ const normalizedScope = scope?.trim();
9729
+ 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)) {
8942
9730
  return void 0;
8943
9731
  }
8944
9732
  return {
8945
- accessToken,
9733
+ accessToken: normalizedAccessToken,
8946
9734
  tokenType,
8947
9735
  expiresAt,
8948
9736
  ...normalizedRefreshToken === void 0 ? {} : { refreshToken: normalizedRefreshToken },
8949
- ...scope === void 0 || scope.length === 0 ? {} : { scope }
9737
+ ...normalizedScope === void 0 || normalizedScope.length === 0 ? {} : { scope: normalizedScope }
8950
9738
  };
8951
9739
  }
8952
9740
  function getClientMetadata(client) {
8953
- return client.metadata;
9741
+ if (client.metadata === void 0) {
9742
+ return void 0;
9743
+ }
9744
+ return {
9745
+ clientName: normalizeOptionalOAuthString(client.metadata.clientName),
9746
+ scope: normalizeOptionalOAuthString(client.metadata.scope),
9747
+ softwareId: normalizeOptionalOAuthString(client.metadata.softwareId),
9748
+ softwareVersion: normalizeOptionalOAuthString(client.metadata.softwareVersion)
9749
+ };
9750
+ }
9751
+ function normalizeConfiguredClient(client) {
9752
+ const clientId = normalizeOptionalOAuthString(client.clientId);
9753
+ if (clientId === void 0) {
9754
+ return null;
9755
+ }
9756
+ const clientSecret = normalizeOptionalOAuthString(client.clientSecret);
9757
+ return clientSecret === void 0 ? { clientId } : { clientId, clientSecret };
9758
+ }
9759
+ function normalizeOptionalOAuthString(value) {
9760
+ if (value === void 0) {
9761
+ return void 0;
9762
+ }
9763
+ const trimmed = value.trim();
9764
+ return trimmed.length === 0 ? void 0 : trimmed;
8954
9765
  }
8955
9766
  function getOwnEntry7(record, key2) {
8956
9767
  return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
@@ -8979,11 +9790,7 @@ function buildAuthorizationUrl(input) {
8979
9790
  "authorization_endpoint",
8980
9791
  "Authorization server metadata"
8981
9792
  );
8982
- const issuer = requireOwnString(
8983
- input.metadata,
8984
- "issuer",
8985
- "Authorization server metadata"
8986
- );
9793
+ const issuer = requireOwnString(input.metadata, "issuer", "Authorization server metadata");
8987
9794
  const url = new URL2(authorizationEndpoint);
8988
9795
  const resource = canonicalizeResourceIndicator(input.resource);
8989
9796
  const state = createAuthorizationState({
@@ -9591,7 +10398,7 @@ var McpClient = class {
9591
10398
  await onToolsChanged();
9592
10399
  });
9593
10400
  messageLayer.onNotification("notifications/resources/list_changed", async () => {
9594
- if (onResourcesChanged === void 0) {
10401
+ if (onResourcesChanged === void 0 || this.currentServerCapabilities?.resources?.listChanged !== true) {
9595
10402
  return;
9596
10403
  }
9597
10404
  await onResourcesChanged();
@@ -9610,7 +10417,7 @@ var McpClient = class {
9610
10417
  await onResourceUpdated(uri);
9611
10418
  });
9612
10419
  messageLayer.onNotification("notifications/prompts/list_changed", async () => {
9613
- if (onPromptsChanged === void 0) {
10420
+ if (onPromptsChanged === void 0 || this.currentServerCapabilities?.prompts?.listChanged !== true) {
9614
10421
  return;
9615
10422
  }
9616
10423
  await onPromptsChanged();
@@ -9841,7 +10648,11 @@ var McpClient = class {
9841
10648
  throw new Error("Server does not support resources");
9842
10649
  }
9843
10650
  const requestParams = params17.cursor === void 0 ? void 0 : { cursor: params17.cursor };
9844
- return await messageLayer.sendRequest("resources/list", requestParams);
10651
+ const result = await messageLayer.sendRequest("resources/list", requestParams);
10652
+ if (!isResourcesListResult(result)) {
10653
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid resources/list result");
10654
+ }
10655
+ return result;
9845
10656
  }
9846
10657
  async listResourceTemplates(params17 = {}) {
9847
10658
  const messageLayer = this.getMessageLayerOrThrow();
@@ -9850,7 +10661,11 @@ var McpClient = class {
9850
10661
  throw new Error("Server does not support resources");
9851
10662
  }
9852
10663
  const requestParams = params17.cursor === void 0 ? void 0 : { cursor: params17.cursor };
9853
- return await messageLayer.sendRequest("resources/templates/list", requestParams);
10664
+ const result = await messageLayer.sendRequest("resources/templates/list", requestParams);
10665
+ if (!isResourceTemplatesListResult(result)) {
10666
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid resources/templates/list result");
10667
+ }
10668
+ return result;
9854
10669
  }
9855
10670
  async readResource(params17) {
9856
10671
  const messageLayer = this.getMessageLayerOrThrow();
@@ -9858,7 +10673,11 @@ var McpClient = class {
9858
10673
  if (serverCapabilities.resources === void 0) {
9859
10674
  throw new Error("Server does not support resources");
9860
10675
  }
9861
- return await messageLayer.sendRequest("resources/read", params17);
10676
+ const result = await messageLayer.sendRequest("resources/read", params17);
10677
+ if (!isReadResourceResult(result)) {
10678
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid resources/read result");
10679
+ }
10680
+ return result;
9862
10681
  }
9863
10682
  async subscribe(uri) {
9864
10683
  const messageLayer = this.getMessageLayerOrThrow();
@@ -9893,7 +10712,11 @@ var McpClient = class {
9893
10712
  if (serverCapabilities.prompts === void 0) {
9894
10713
  throw new Error("Server does not support prompts");
9895
10714
  }
9896
- return await messageLayer.sendRequest("prompts/get", params17);
10715
+ const result = await messageLayer.sendRequest("prompts/get", params17);
10716
+ if (!isGetPromptResult(result)) {
10717
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid prompts/get result");
10718
+ }
10719
+ return result;
9897
10720
  }
9898
10721
  async complete(params17) {
9899
10722
  const messageLayer = this.getMessageLayerOrThrow();
@@ -9901,7 +10724,11 @@ var McpClient = class {
9901
10724
  if (serverCapabilities.completions === void 0) {
9902
10725
  throw new Error("Server does not support completions");
9903
10726
  }
9904
- return await messageLayer.sendRequest("completion/complete", params17);
10727
+ const result = await messageLayer.sendRequest("completion/complete", params17);
10728
+ if (!isCompleteResult(result)) {
10729
+ throw new McpError(ERROR_INVALID_REQUEST, "Invalid completion/complete result");
10730
+ }
10731
+ return result;
9905
10732
  }
9906
10733
  async setLogLevel(level) {
9907
10734
  const messageLayer = this.getMessageLayerOrThrow();
@@ -10892,6 +11719,44 @@ function isCallToolResult(value) {
10892
11719
  function isToolsListResult(value) {
10893
11720
  return isObjectRecord5(value) && Array.isArray(value.tools) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
10894
11721
  }
11722
+ function isResourcesListResult(value) {
11723
+ return isObjectRecord5(value) && Array.isArray(value.resources) && value.resources.every(isResource) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
11724
+ }
11725
+ function isResourceTemplatesListResult(value) {
11726
+ return isObjectRecord5(value) && Array.isArray(value.resourceTemplates) && value.resourceTemplates.every(isResourceTemplate) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
11727
+ }
11728
+ function isReadResourceResult(value) {
11729
+ return isObjectRecord5(value) && Array.isArray(value.contents) && value.contents.every(isResourceContents);
11730
+ }
11731
+ function isGetPromptResult(value) {
11732
+ return isObjectRecord5(value) && (value.description === void 0 || typeof value.description === "string") && Array.isArray(value.messages) && value.messages.every(isPromptMessage);
11733
+ }
11734
+ function isCompleteResult(value) {
11735
+ 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");
11736
+ }
11737
+ function isResource(value) {
11738
+ 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");
11739
+ }
11740
+ function isResourceTemplate(value) {
11741
+ 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");
11742
+ }
11743
+ function isResourceContents(value) {
11744
+ if (!isObjectRecord5(value) || typeof value.uri !== "string") {
11745
+ return false;
11746
+ }
11747
+ if (value.mimeType !== void 0 && typeof value.mimeType !== "string") {
11748
+ return false;
11749
+ }
11750
+ const hasText = value.text !== void 0;
11751
+ const hasBlob = value.blob !== void 0;
11752
+ if (!hasText && !hasBlob) {
11753
+ return false;
11754
+ }
11755
+ return (!hasText || typeof value.text === "string") && (!hasBlob || typeof value.blob === "string");
11756
+ }
11757
+ function isPromptMessage(value) {
11758
+ return isObjectRecord5(value) && (value.role === "user" || value.role === "assistant") && isContentItem(value.content);
11759
+ }
10895
11760
  function isContentItem(value) {
10896
11761
  if (!isObjectRecord5(value)) {
10897
11762
  return false;
@@ -10905,7 +11770,7 @@ function isContentItem(value) {
10905
11770
  if (value.type !== "resource" || !isObjectRecord5(value.resource)) {
10906
11771
  return false;
10907
11772
  }
10908
- 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");
11773
+ return isResourceContents(value.resource);
10909
11774
  }
10910
11775
  function hasOwn(value, property) {
10911
11776
  return Object.prototype.hasOwnProperty.call(value, property);
@@ -11045,13 +11910,13 @@ function convertJsonSchema(schema) {
11045
11910
  }
11046
11911
  return convertSchema(schema, schema, []);
11047
11912
  }
11048
- function convertSchema(schema, root, path25) {
11049
- const resolvedSchema = resolveReferencedSchema(schema, root, path25);
11913
+ function convertSchema(schema, root, path26) {
11914
+ const resolvedSchema = resolveReferencedSchema(schema, root, path26);
11050
11915
  const normalizedSchema = normalizeNullability(resolvedSchema);
11051
11916
  const composition = getComposition(normalizedSchema.schema);
11052
11917
  if (Array.isArray(normalizedSchema.schema.type)) {
11053
11918
  throw new Error(
11054
- `JSON Schema "${formatJsonSchemaPath(path25)}" has an unsupported type "${formatJsonSchemaType(
11919
+ `JSON Schema "${formatJsonSchemaPath(path26)}" has an unsupported type "${formatJsonSchemaType(
11055
11920
  normalizedSchema.schema.type
11056
11921
  )}". Supported: string, number, integer, boolean, array, object.`
11057
11922
  );
@@ -11063,13 +11928,13 @@ function convertSchema(schema, root, path25) {
11063
11928
  return convertEnumSchema(resolvedSchema, normalizedSchema.nullable);
11064
11929
  }
11065
11930
  if (composition !== void 0) {
11066
- return convertCompositionSchema(normalizedSchema.schema, root, normalizedSchema.nullable, path25);
11931
+ return convertCompositionSchema(normalizedSchema.schema, root, normalizedSchema.nullable, path26);
11067
11932
  }
11068
11933
  if (isRecordSchema(normalizedSchema.schema)) {
11069
11934
  return applyMetadata(
11070
11935
  S.Record(
11071
11936
  convertSchema(normalizedSchema.schema.additionalProperties, root, [
11072
- ...path25,
11937
+ ...path26,
11073
11938
  "additionalProperties"
11074
11939
  ])
11075
11940
  ),
@@ -11118,12 +11983,12 @@ function convertSchema(schema, root, path25) {
11118
11983
  if (normalizedSchema.schema.items === void 0) {
11119
11984
  throw new Error(
11120
11985
  `JSON Schema "${formatJsonSchemaPath(
11121
- path25
11986
+ path26
11122
11987
  )}" is an array but is missing the "items" field. Add "items": { ... } to declare the element type.`
11123
11988
  );
11124
11989
  }
11125
11990
  return S.Array(
11126
- convertSchema(normalizedSchema.schema.items, root, [...path25, "items"]),
11991
+ convertSchema(normalizedSchema.schema.items, root, [...path26, "items"]),
11127
11992
  createCommonOptions(
11128
11993
  normalizedSchema.schema,
11129
11994
  normalizedSchema.nullable,
@@ -11133,7 +11998,7 @@ function convertSchema(schema, root, path25) {
11133
11998
  case "object":
11134
11999
  return convertObjectSchema(normalizedSchema.schema, root, {
11135
12000
  nullable: normalizedSchema.nullable,
11136
- path: path25
12001
+ path: path26
11137
12002
  });
11138
12003
  case "null":
11139
12004
  return applyMetadata(S.Json(), normalizedSchema.schema, {
@@ -11148,12 +12013,12 @@ function convertSchema(schema, root, path25) {
11148
12013
  }
11149
12014
  throw new Error(
11150
12015
  `JSON Schema "${formatJsonSchemaPath(
11151
- path25
12016
+ path26
11152
12017
  )}" must declare one of: "type", "enum", "const", "oneOf", "anyOf", or "allOf".`
11153
12018
  );
11154
12019
  }
11155
12020
  throw new Error(
11156
- `JSON Schema "${formatJsonSchemaPath(path25)}" has an unsupported type "${formatJsonSchemaType(
12021
+ `JSON Schema "${formatJsonSchemaPath(path26)}" has an unsupported type "${formatJsonSchemaType(
11157
12022
  normalizedSchema.schema.type
11158
12023
  )}". Supported: string, number, integer, boolean, array, object.`
11159
12024
  );
@@ -11197,21 +12062,21 @@ function convertEnumSchema(schema, nullable) {
11197
12062
  )
11198
12063
  });
11199
12064
  }
11200
- function convertCompositionSchema(schema, root, nullable, path25) {
12065
+ function convertCompositionSchema(schema, root, nullable, path26) {
11201
12066
  const composition = getComposition(schema);
11202
12067
  const branchSchemas = composition?.branches ?? [];
11203
12068
  const keyword = composition?.keyword ?? "oneOf";
11204
12069
  const branches = branchSchemas.map(
11205
- (branch, index) => resolveReferencedSchema(branch, root, [...path25, keyword, String(index)])
12070
+ (branch, index) => resolveReferencedSchema(branch, root, [...path26, keyword, String(index)])
11206
12071
  );
11207
- const discriminator = findDiscriminator(branches, root, path25);
12072
+ const discriminator = findDiscriminator(branches, root, path26);
11208
12073
  if (discriminator !== void 0) {
11209
12074
  const convertedBranches = Object.fromEntries(
11210
12075
  branches.map((branch, index) => [
11211
12076
  getDiscriminatorLiteral(branch, discriminator, root),
11212
12077
  convertObjectSchema(branch, root, {
11213
12078
  omitProperty: discriminator,
11214
- path: [...path25, keyword, String(index)]
12079
+ path: [...path26, keyword, String(index)]
11215
12080
  })
11216
12081
  ])
11217
12082
  );
@@ -11230,7 +12095,7 @@ function convertCompositionSchema(schema, root, nullable, path25) {
11230
12095
  S.Union(
11231
12096
  branches.map(
11232
12097
  (branch, index) => convertObjectSchema(branch, root, {
11233
- path: [...path25, keyword, String(index)]
12098
+ path: [...path26, keyword, String(index)]
11234
12099
  })
11235
12100
  )
11236
12101
  ),
@@ -11344,11 +12209,11 @@ function getComposition(schema) {
11344
12209
  }
11345
12210
  return void 0;
11346
12211
  }
11347
- function formatJsonSchemaPath(path25) {
11348
- if (path25.length === 0) {
12212
+ function formatJsonSchemaPath(path26) {
12213
+ if (path26.length === 0) {
11349
12214
  return "#";
11350
12215
  }
11351
- return `#/${path25.map(escapeJsonPointerSegment).join("/")}`;
12216
+ return `#/${path26.map(escapeJsonPointerSegment).join("/")}`;
11352
12217
  }
11353
12218
  function formatJsonSchemaType(type2) {
11354
12219
  return Array.isArray(type2) ? JSON.stringify(type2) : String(type2);
@@ -11364,11 +12229,11 @@ function isRecordSchema(schema) {
11364
12229
  const propertyKeys = Object.keys(schema.properties ?? {});
11365
12230
  return schema.type === "object" && propertyKeys.length === 0 && typeof schema.additionalProperties === "object" && schema.additionalProperties !== null;
11366
12231
  }
11367
- function findDiscriminator(branches, root, path25) {
12232
+ function findDiscriminator(branches, root, path26) {
11368
12233
  const [firstBranch] = branches;
11369
12234
  if (firstBranch === void 0) {
11370
12235
  throw new Error(
11371
- `JSON Schema "${formatJsonSchemaPath(path25)}" uses oneOf/anyOf/allOf but has no branches.`
12236
+ `JSON Schema "${formatJsonSchemaPath(path26)}" uses oneOf/anyOf/allOf but has no branches.`
11372
12237
  );
11373
12238
  }
11374
12239
  const candidateKeys = Object.keys(firstBranch.properties ?? {});
@@ -11408,19 +12273,19 @@ function getDiscriminatorLiteral(branch, key2, root) {
11408
12273
  }
11409
12274
  return void 0;
11410
12275
  }
11411
- function resolveReferencedSchema(schema, root, path25) {
12276
+ function resolveReferencedSchema(schema, root, path26) {
11412
12277
  if (schema.$ref === void 0) {
11413
12278
  return schema;
11414
12279
  }
11415
12280
  const resolvedTarget = resolveLocalRef(root, schema.$ref);
11416
12281
  if (resolvedTarget === void 0) {
11417
12282
  throw new Error(
11418
- `JSON Schema "${formatJsonSchemaPath(path25)}" uses "$ref": ${schema.$ref}. toolcraft only supports internal refs like "#/components/schemas/Foo".`
12283
+ `JSON Schema "${formatJsonSchemaPath(path26)}" uses "$ref": ${schema.$ref}. toolcraft only supports internal refs like "#/components/schemas/Foo".`
11419
12284
  );
11420
12285
  }
11421
12286
  const { $ref: ignoredRef, ...siblingKeywords } = schema;
11422
12287
  void ignoredRef;
11423
- const resolvedSchema = resolveReferencedSchema(resolvedTarget, root, path25);
12288
+ const resolvedSchema = resolveReferencedSchema(resolvedTarget, root, path26);
11424
12289
  if (Object.keys(siblingKeywords).length === 0) {
11425
12290
  return resolvedSchema;
11426
12291
  }
@@ -11444,9 +12309,9 @@ function mergeJsonSchemas(base, overlay) {
11444
12309
  ...mergedRequired === void 0 ? {} : { required: mergedRequired }
11445
12310
  };
11446
12311
  }
11447
- function hasSelfReferencingRef(schema, root, path25 = "#", activePaths = /* @__PURE__ */ new Set()) {
12312
+ function hasSelfReferencingRef(schema, root, path26 = "#", activePaths = /* @__PURE__ */ new Set()) {
11448
12313
  const nextActivePaths = new Set(activePaths);
11449
- nextActivePaths.add(path25);
12314
+ nextActivePaths.add(path26);
11450
12315
  const localRefPath = getLocalRefPath(schema.$ref);
11451
12316
  if (localRefPath !== void 0) {
11452
12317
  if (nextActivePaths.has(localRefPath)) {
@@ -11457,13 +12322,13 @@ function hasSelfReferencingRef(schema, root, path25 = "#", activePaths = /* @__P
11457
12322
  return true;
11458
12323
  }
11459
12324
  }
11460
- if (schema.items !== void 0 && hasSelfReferencingRef(schema.items, root, `${path25}/items`, nextActivePaths)) {
12325
+ if (schema.items !== void 0 && hasSelfReferencingRef(schema.items, root, `${path26}/items`, nextActivePaths)) {
11461
12326
  return true;
11462
12327
  }
11463
12328
  if (typeof schema.additionalProperties === "object" && schema.additionalProperties !== null && hasSelfReferencingRef(
11464
12329
  schema.additionalProperties,
11465
12330
  root,
11466
- `${path25}/additionalProperties`,
12331
+ `${path26}/additionalProperties`,
11467
12332
  nextActivePaths
11468
12333
  )) {
11469
12334
  return true;
@@ -11472,7 +12337,7 @@ function hasSelfReferencingRef(schema, root, path25 = "#", activePaths = /* @__P
11472
12337
  if (hasSelfReferencingRef(
11473
12338
  childSchema,
11474
12339
  root,
11475
- `${path25}/properties/${escapeJsonPointerSegment(key2)}`,
12340
+ `${path26}/properties/${escapeJsonPointerSegment(key2)}`,
11476
12341
  nextActivePaths
11477
12342
  )) {
11478
12343
  return true;
@@ -11482,24 +12347,24 @@ function hasSelfReferencingRef(schema, root, path25 = "#", activePaths = /* @__P
11482
12347
  if (hasSelfReferencingRef(
11483
12348
  childSchema,
11484
12349
  root,
11485
- `${path25}/$defs/${escapeJsonPointerSegment(key2)}`,
12350
+ `${path26}/$defs/${escapeJsonPointerSegment(key2)}`,
11486
12351
  nextActivePaths
11487
12352
  )) {
11488
12353
  return true;
11489
12354
  }
11490
12355
  }
11491
12356
  for (const [index, childSchema] of (schema.oneOf ?? []).entries()) {
11492
- if (hasSelfReferencingRef(childSchema, root, `${path25}/oneOf/${index}`, nextActivePaths)) {
12357
+ if (hasSelfReferencingRef(childSchema, root, `${path26}/oneOf/${index}`, nextActivePaths)) {
11493
12358
  return true;
11494
12359
  }
11495
12360
  }
11496
12361
  for (const [index, childSchema] of (schema.anyOf ?? []).entries()) {
11497
- if (hasSelfReferencingRef(childSchema, root, `${path25}/anyOf/${index}`, nextActivePaths)) {
12362
+ if (hasSelfReferencingRef(childSchema, root, `${path26}/anyOf/${index}`, nextActivePaths)) {
11498
12363
  return true;
11499
12364
  }
11500
12365
  }
11501
12366
  for (const [index, childSchema] of (schema.allOf ?? []).entries()) {
11502
- if (hasSelfReferencingRef(childSchema, root, `${path25}/allOf/${index}`, nextActivePaths)) {
12367
+ if (hasSelfReferencingRef(childSchema, root, `${path26}/allOf/${index}`, nextActivePaths)) {
11503
12368
  return true;
11504
12369
  }
11505
12370
  }
@@ -11515,14 +12380,14 @@ function getLocalRefPath(ref) {
11515
12380
  return ref.startsWith("#/") ? ref : void 0;
11516
12381
  }
11517
12382
  function resolveLocalRef(root, ref) {
11518
- const path25 = getLocalRefPath(ref);
11519
- if (path25 === void 0) {
12383
+ const path26 = getLocalRefPath(ref);
12384
+ if (path26 === void 0) {
11520
12385
  return void 0;
11521
12386
  }
11522
- if (path25 === "#") {
12387
+ if (path26 === "#") {
11523
12388
  return root;
11524
12389
  }
11525
- const segments = path25.slice(2).split("/").map(unescapeJsonPointerSegment);
12390
+ const segments = path26.slice(2).split("/").map(unescapeJsonPointerSegment);
11526
12391
  let current = root;
11527
12392
  for (const segment of segments) {
11528
12393
  if (Array.isArray(current)) {
@@ -11568,15 +12433,15 @@ function getBooleanDefault(value) {
11568
12433
  return typeof value === "boolean" ? value : void 0;
11569
12434
  }
11570
12435
  function getArrayDefault(value) {
11571
- return Array.isArray(value) && value.every((item) => isJsonValue(item)) ? value : void 0;
12436
+ return Array.isArray(value) && value.every((item) => isJsonValue2(item)) ? value : void 0;
11572
12437
  }
11573
12438
  function getPrimitiveEnumDefault(value, candidates) {
11574
12439
  return isPrimitiveEnumValue(value) && candidates.includes(value) ? value : void 0;
11575
12440
  }
11576
12441
  function getJsonDefault(value) {
11577
- return isJsonValue(value) ? value : void 0;
12442
+ return isJsonValue2(value) ? value : void 0;
11578
12443
  }
11579
- function isJsonValue(value) {
12444
+ function isJsonValue2(value) {
11580
12445
  if (value === null) {
11581
12446
  return true;
11582
12447
  }
@@ -11584,12 +12449,12 @@ function isJsonValue(value) {
11584
12449
  return true;
11585
12450
  }
11586
12451
  if (Array.isArray(value)) {
11587
- return value.every((item) => isJsonValue(item));
12452
+ return value.every((item) => isJsonValue2(item));
11588
12453
  }
11589
12454
  if (!isPlainObject(value)) {
11590
12455
  return false;
11591
12456
  }
11592
- return Object.values(value).every((item) => isJsonValue(item));
12457
+ return Object.values(value).every((item) => isJsonValue2(item));
11593
12458
  }
11594
12459
  function isPlainObject(value) {
11595
12460
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -11779,7 +12644,7 @@ async function ensureConnected(connection) {
11779
12644
  async function readCache(cachePath) {
11780
12645
  try {
11781
12646
  await assertCachePathHasNoSymlinks(cachePath);
11782
- const raw = await readFile3(cachePath, "utf8");
12647
+ const raw = await readFile4(cachePath, "utf8");
11783
12648
  const parsed = JSON.parse(raw);
11784
12649
  if (parsed === null || typeof parsed !== "object" || !Array.isArray(parsed.tools) || parsed.upstream === void 0 || typeof parsed.upstream.name !== "string" || typeof parsed.upstream.version !== "string") {
11785
12650
  return void 0;
@@ -11800,7 +12665,7 @@ async function readCache(cachePath) {
11800
12665
  }
11801
12666
  }
11802
12667
  async function writeCache(cachePath, cache) {
11803
- const directory = path12.dirname(cachePath);
12668
+ const directory = path13.dirname(cachePath);
11804
12669
  const tempPath = `${cachePath}.tmp-${randomUUID4()}`;
11805
12670
  let tempCreated = false;
11806
12671
  await assertCachePathHasNoSymlinks(cachePath);
@@ -11997,13 +12862,13 @@ function collectProxyGroups(root) {
11997
12862
  function findProjectRoot(from = process.cwd()) {
11998
12863
  let current = process.cwd();
11999
12864
  if (from !== current) {
12000
- current = path12.resolve(from);
12865
+ current = path13.resolve(from);
12001
12866
  }
12002
12867
  while (true) {
12003
- if (existsSync2(path12.join(current, "package.json"))) {
12868
+ if (existsSync2(path13.join(current, "package.json"))) {
12004
12869
  return current;
12005
12870
  }
12006
- const parent = path12.dirname(current);
12871
+ const parent = path13.dirname(current);
12007
12872
  if (parent === current) {
12008
12873
  return void 0;
12009
12874
  }
@@ -12020,7 +12885,7 @@ function resolveCachePath(name, projectRoot) {
12020
12885
  if (name.length === 0 || name === "." || name === ".." || name.includes("/") || name.includes("\\")) {
12021
12886
  throw new Error(`MCP proxy group name must be a file-safe name: "${name}".`);
12022
12887
  }
12023
- return path12.join(resolvedProjectRoot, ".toolcraft", "mcp", `${name}.json`);
12888
+ return path13.join(resolvedProjectRoot, ".toolcraft", "mcp", `${name}.json`);
12024
12889
  }
12025
12890
  async function assertCachePathHasNoSymlinks(filePath) {
12026
12891
  let currentPath = filePath;
@@ -12034,10 +12899,10 @@ async function assertCachePathHasNoSymlinks(filePath) {
12034
12899
  throw error3;
12035
12900
  }
12036
12901
  }
12037
- if (path12.basename(currentPath) === ".toolcraft") {
12902
+ if (path13.basename(currentPath) === ".toolcraft") {
12038
12903
  return;
12039
12904
  }
12040
- const parentPath = path12.dirname(currentPath);
12905
+ const parentPath = path13.dirname(currentPath);
12041
12906
  if (parentPath === currentPath) {
12042
12907
  return;
12043
12908
  }
@@ -12183,20 +13048,20 @@ function reportsEnabled(option, env) {
12183
13048
  function resolveReportDir(option, projectRoot) {
12184
13049
  const configuredDir = typeof option === "object" ? option.dir : void 0;
12185
13050
  if (configuredDir === void 0 || configuredDir.length === 0) {
12186
- return path13.join(projectRoot, ".toolcraft", "errors");
13051
+ return path14.join(projectRoot, ".toolcraft", "errors");
12187
13052
  }
12188
- return path13.isAbsolute(configuredDir) ? configuredDir : path13.join(projectRoot, configuredDir);
13053
+ return path14.isAbsolute(configuredDir) ? configuredDir : path14.join(projectRoot, configuredDir);
12189
13054
  }
12190
13055
  function reportDirMustStayWithinProject(option) {
12191
13056
  const configuredDir = typeof option === "object" ? option.dir : void 0;
12192
- return configuredDir === void 0 || configuredDir.length === 0 || !path13.isAbsolute(configuredDir);
13057
+ return configuredDir === void 0 || configuredDir.length === 0 || !path14.isAbsolute(configuredDir);
12193
13058
  }
12194
13059
  function isWithinDirectory(parent, child) {
12195
- const relative = path13.relative(parent, child);
12196
- return relative === "" || !path13.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path13.sep}`);
13060
+ const relative = path14.relative(parent, child);
13061
+ return relative === "" || !path14.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path14.sep}`);
12197
13062
  }
12198
13063
  async function assertReportDirWithinProject(projectRoot, reportDir) {
12199
- if (!isWithinDirectory(path13.resolve(projectRoot), path13.resolve(reportDir))) {
13064
+ if (!isWithinDirectory(path14.resolve(projectRoot), path14.resolve(reportDir))) {
12200
13065
  throw new Error("Error report directory resolves outside project root.");
12201
13066
  }
12202
13067
  const [canonicalProjectRoot, canonicalReportDir] = await Promise.all([
@@ -12247,7 +13112,7 @@ function slugifyCommandPath(commandPath) {
12247
13112
  return output.length === 0 ? "root" : output;
12248
13113
  }
12249
13114
  function relativeDisplayPath(projectRoot, absolutePath) {
12250
- const relative = path13.relative(projectRoot, absolutePath);
13115
+ const relative = path14.relative(projectRoot, absolutePath);
12251
13116
  return relative.length === 0 || relative.startsWith("..") ? absolutePath : relative;
12252
13117
  }
12253
13118
  function redactValue(value) {
@@ -12567,7 +13432,7 @@ async function writeErrorReport(context) {
12567
13432
  const projectRoot = resolveProjectRoot(context.projectRoot);
12568
13433
  const reportDir = resolveReportDir(context.errorReports, projectRoot);
12569
13434
  const fileName = `${formatTimestamp(/* @__PURE__ */ new Date())}-${slugifyCommandPath(context.commandPath)}-${randomUUID5()}.log`;
12570
- const absolutePath = path13.join(reportDir, fileName);
13435
+ const absolutePath = path14.join(reportDir, fileName);
12571
13436
  await mkdir2(reportDir, { recursive: true });
12572
13437
  if (reportDirMustStayWithinProject(context.errorReports)) {
12573
13438
  await assertReportDirWithinProject(projectRoot, reportDir);
@@ -13037,7 +13902,7 @@ function inferProgramName(argv) {
13037
13902
  if (typeof entrypoint !== "string" || entrypoint.length === 0) {
13038
13903
  return "toolcraft";
13039
13904
  }
13040
- const parsed = path14.parse(entrypoint);
13905
+ const parsed = path15.parse(entrypoint);
13041
13906
  return parsed.name.length > 0 ? parsed.name : "toolcraft";
13042
13907
  }
13043
13908
  function normalizeRoots(roots, argv) {
@@ -13095,11 +13960,11 @@ function formatSegment(segment, casing) {
13095
13960
  const separator = casing === "snake" ? "_" : "-";
13096
13961
  return splitWords3(segment).join(separator);
13097
13962
  }
13098
- function toOptionFlag(path25, casing) {
13099
- return `--${path25.map((segment) => formatSegment(segment, casing)).join(".")}`;
13963
+ function toOptionFlag(path26, casing) {
13964
+ return `--${path26.map((segment) => formatSegment(segment, casing)).join(".")}`;
13100
13965
  }
13101
- function toOptionAttribute(path25, casing) {
13102
- return path25.map((segment) => {
13966
+ function toOptionAttribute(path26, casing) {
13967
+ return path26.map((segment) => {
13103
13968
  const formatted = formatSegment(segment, casing);
13104
13969
  if (casing === "snake") {
13105
13970
  return formatted;
@@ -13110,23 +13975,23 @@ function toOptionAttribute(path25, casing) {
13110
13975
  ).join("");
13111
13976
  }).join(".");
13112
13977
  }
13113
- function toDisplayPath(path25) {
13114
- return path25.join(".");
13978
+ function toDisplayPath(path26) {
13979
+ return path26.join(".");
13115
13980
  }
13116
- function toUnionKindControlPath(path25) {
13117
- if (path25.length === 0) {
13981
+ function toUnionKindControlPath(path26) {
13982
+ if (path26.length === 0) {
13118
13983
  return ["kind"];
13119
13984
  }
13120
- const head = path25.slice(0, -1);
13121
- const tail = path25[path25.length - 1] ?? "";
13985
+ const head = path26.slice(0, -1);
13986
+ const tail = path26[path26.length - 1] ?? "";
13122
13987
  return [...head, `${tail}Kind`];
13123
13988
  }
13124
- function toUnionKindDisplayPath(path25) {
13125
- if (path25.length === 0) {
13989
+ function toUnionKindDisplayPath(path26) {
13990
+ if (path26.length === 0) {
13126
13991
  return "kind";
13127
13992
  }
13128
- const head = path25.slice(0, -1);
13129
- const tail = path25[path25.length - 1] ?? "";
13993
+ const head = path26.slice(0, -1);
13994
+ const tail = path26[path26.length - 1] ?? "";
13130
13995
  return [...head, `${tail}-kind`].join(".");
13131
13996
  }
13132
13997
  function createSyntheticEnumSchema(values) {
@@ -13142,14 +14007,14 @@ function getRequiredBranchFingerprint(branch, casing) {
13142
14007
  const requiredKeys = Object.entries(branch.shape).filter(([, schema]) => schema.kind !== "optional").map(([key2]) => formatSegment(key2, casing)).sort();
13143
14008
  return requiredKeys.join("+");
13144
14009
  }
13145
- function collectFields(schema, casing, globalLongOptionFlags, path25 = [], inheritedOptional = false, variantContext) {
14010
+ function collectFields(schema, casing, globalLongOptionFlags, path26 = [], inheritedOptional = false, variantContext) {
13146
14011
  const collected = {
13147
14012
  dynamicFields: [],
13148
14013
  fields: [],
13149
14014
  variants: []
13150
14015
  };
13151
14016
  for (const [key2, rawChildSchema] of Object.entries(schema.shape)) {
13152
- const nextPath = [...path25, key2];
14017
+ const nextPath = [...path26, key2];
13153
14018
  const runtimeOptional = inheritedOptional || rawChildSchema.kind === "optional";
13154
14019
  const childSchema = unwrapOptional2(rawChildSchema);
13155
14020
  const requiredWhenActive = rawChildSchema.kind !== "optional" && childSchema.default === void 0;
@@ -13335,9 +14200,9 @@ function collectFields(schema, casing, globalLongOptionFlags, path25 = [], inher
13335
14200
  }
13336
14201
  return collected;
13337
14202
  }
13338
- function toCommanderOptionAttribute(path25, casing, globalLongOptionFlags) {
13339
- const optionAttribute = toOptionAttribute(path25, casing);
13340
- const optionFlag = toOptionFlag(path25, casing);
14203
+ function toCommanderOptionAttribute(path26, casing, globalLongOptionFlags) {
14204
+ const optionAttribute = toOptionAttribute(path26, casing);
14205
+ const optionFlag = toOptionFlag(path26, casing);
13341
14206
  if (!globalLongOptionFlags.has(optionFlag)) {
13342
14207
  return optionAttribute;
13343
14208
  }
@@ -13610,6 +14475,20 @@ function parseArrayValue(value, schema, label) {
13610
14475
  (item) => parseScalarValue(item, itemSchema, label)
13611
14476
  );
13612
14477
  }
14478
+ function isNegativeNumericArrayToken(token, schema) {
14479
+ if (!token.startsWith("-") || token.startsWith("--")) {
14480
+ return false;
14481
+ }
14482
+ const itemSchema = unwrapOptional2(schema.item);
14483
+ if (itemSchema.kind !== "number") {
14484
+ return false;
14485
+ }
14486
+ const items = splitArrayInput(token);
14487
+ return items.length > 0 && items.every((item) => isValidNumberSchemaValue(Number(item), itemSchema));
14488
+ }
14489
+ function isNextArrayOptionToken(token, schema) {
14490
+ return token.startsWith("-") && !isNegativeNumericArrayToken(token, schema);
14491
+ }
13613
14492
  function validateArrayBounds(value, schema, label) {
13614
14493
  if (schema.minItems !== void 0 && value.length < schema.minItems) {
13615
14494
  throw new UserError(
@@ -14417,10 +15296,10 @@ function parseDebugStackMode(value) {
14417
15296
  formatInvalidEnumMessage("--debug", String(value), ["raw"], { candidates: ["raw"] })
14418
15297
  );
14419
15298
  }
14420
- function setNestedValue(target, path25, value) {
15299
+ function setNestedValue(target, path26, value) {
14421
15300
  let cursor2 = target;
14422
- for (let index = 0; index < path25.length - 1; index += 1) {
14423
- const segment = path25[index] ?? "";
15301
+ for (let index = 0; index < path26.length - 1; index += 1) {
15302
+ const segment = path26[index] ?? "";
14424
15303
  const existing = Object.prototype.hasOwnProperty.call(cursor2, segment) ? cursor2[segment] : void 0;
14425
15304
  if (typeof existing === "object" && existing !== null) {
14426
15305
  cursor2 = existing;
@@ -14435,7 +15314,7 @@ function setNestedValue(target, path25, value) {
14435
15314
  });
14436
15315
  cursor2 = next;
14437
15316
  }
14438
- const leaf = path25[path25.length - 1];
15317
+ const leaf = path26[path26.length - 1];
14439
15318
  if (leaf !== void 0) {
14440
15319
  Object.defineProperty(cursor2, leaf, {
14441
15320
  value,
@@ -14552,21 +15431,21 @@ async function withOutputFormat2(output, fn) {
14552
15431
  }
14553
15432
  function createFs2() {
14554
15433
  return {
14555
- readFile: async (path25, encoding = "utf8") => readFile4(path25, { encoding }),
14556
- writeFile: async (path25, contents, options) => {
14557
- await writeFile5(path25, contents, options);
15434
+ readFile: async (path26, encoding = "utf8") => readFile5(path26, { encoding }),
15435
+ writeFile: async (path26, contents, options) => {
15436
+ await writeFile5(path26, contents, options);
14558
15437
  },
14559
- exists: async (path25) => {
15438
+ exists: async (path26) => {
14560
15439
  try {
14561
- await access2(path25);
15440
+ await access2(path26);
14562
15441
  return true;
14563
15442
  } catch {
14564
15443
  return false;
14565
15444
  }
14566
15445
  },
14567
- lstat: async (path25) => lstat3(path25),
15446
+ lstat: async (path26) => lstat3(path26),
14568
15447
  rename: async (fromPath, toPath) => rename3(fromPath, toPath),
14569
- unlink: async (path25) => unlink3(path25)
15448
+ unlink: async (path26) => unlink3(path26)
14570
15449
  };
14571
15450
  }
14572
15451
  function createEnv2(values = process.env) {
@@ -14582,9 +15461,9 @@ function isPlainObject4(value) {
14582
15461
  function hasFieldValue(value) {
14583
15462
  return value !== void 0;
14584
15463
  }
14585
- function hasNestedField(fields, path25) {
15464
+ function hasNestedField(fields, path26) {
14586
15465
  return fields.some(
14587
- (field) => path25.length < field.path.length && path25.every((segment, index) => field.path[index] === segment)
15466
+ (field) => path26.length < field.path.length && path26.every((segment, index) => field.path[index] === segment)
14588
15467
  );
14589
15468
  }
14590
15469
  function describeExpectedPresetValue(schema) {
@@ -14687,7 +15566,7 @@ function validatePresetFieldValue(value, field, presetPath) {
14687
15566
  async function loadPresetValues(fields, presetPath) {
14688
15567
  let rawPreset;
14689
15568
  try {
14690
- rawPreset = await readFile4(presetPath, {
15569
+ rawPreset = await readFile5(presetPath, {
14691
15570
  encoding: "utf8"
14692
15571
  });
14693
15572
  } catch (error3) {
@@ -14713,9 +15592,9 @@ async function loadPresetValues(fields, presetPath) {
14713
15592
  }
14714
15593
  const fieldByPath = new Map(fields.map((field) => [field.displayPath, field]));
14715
15594
  const presetValues = {};
14716
- function visitObject(current, path25) {
15595
+ function visitObject(current, path26) {
14717
15596
  for (const [key2, value] of Object.entries(current)) {
14718
- const nextPath = [...path25, key2];
15597
+ const nextPath = [...path26, key2];
14719
15598
  const displayPath = toDisplayPath(nextPath);
14720
15599
  const field = fieldByPath.get(displayPath);
14721
15600
  if (field !== void 0) {
@@ -14922,8 +15801,8 @@ function createFixtureService(definition) {
14922
15801
  );
14923
15802
  }
14924
15803
  function resolveFixturePath(commandPath) {
14925
- const parsed = path14.parse(commandPath);
14926
- return path14.join(parsed.dir, `${parsed.name}.fixture.json`);
15804
+ const parsed = path15.parse(commandPath);
15805
+ return path15.join(parsed.dir, `${parsed.name}.fixture.json`);
14927
15806
  }
14928
15807
  function selectFixtureScenario(scenarios, selector, fixturePath) {
14929
15808
  if (isNumericFixtureSelector(selector)) {
@@ -14954,7 +15833,7 @@ async function loadFixtureScenario(command, selector) {
14954
15833
  const fixturePath = resolveFixturePath(commandPath);
14955
15834
  let rawFixture;
14956
15835
  try {
14957
- rawFixture = await readFile4(fixturePath, {
15836
+ rawFixture = await readFile5(fixturePath, {
14958
15837
  encoding: "utf8"
14959
15838
  });
14960
15839
  } catch {
@@ -15057,8 +15936,8 @@ function validateServices(services) {
15057
15936
  }
15058
15937
  }
15059
15938
  }
15060
- function getNestedValue(target, path25) {
15061
- return path25.reduce(
15939
+ function getNestedValue(target, path26) {
15940
+ return path26.reduce(
15062
15941
  (current, segment) => current !== null && typeof current === "object" ? current[segment] : void 0,
15063
15942
  target
15064
15943
  );
@@ -15143,7 +16022,7 @@ function consumeFieldValue(args, index, schema, label, inlineValue) {
15143
16022
  let cursor2 = index + 1;
15144
16023
  while (cursor2 < args.length) {
15145
16024
  const token = args[cursor2] ?? "";
15146
- if (token.startsWith("-")) {
16025
+ if (isNextArrayOptionToken(token, schema)) {
15147
16026
  break;
15148
16027
  }
15149
16028
  const parsed = parseArrayValue(token, schema, label);
@@ -16019,6 +16898,12 @@ This is a bug in toolcraft or in the command definition; it cannot be worked aro
16019
16898
  );
16020
16899
  return;
16021
16900
  }
16901
+ logger2.error(
16902
+ appendUsagePointer(formatCommanderErrorMessage(error3), {
16903
+ rootUsageName: options.rootUsageName,
16904
+ commandPath: options.commandPath.length > 0 ? options.commandPath : findCurrentCommanderCommandPath(options.program, options.argv ?? process.argv)
16905
+ })
16906
+ );
16022
16907
  return;
16023
16908
  }
16024
16909
  if (isHttpErrorLike(error3)) {
@@ -16036,6 +16921,9 @@ This is a bug in toolcraft or in the command definition; it cannot be worked aro
16036
16921
  }
16037
16922
  process.exitCode = 1;
16038
16923
  }
16924
+ function formatCommanderErrorMessage(error3) {
16925
+ return error3.message.startsWith("error:") ? error3.message : `error: ${error3.message}`;
16926
+ }
16039
16927
  function formatInvalidEnumMessage(label, value, values, opts = {}) {
16040
16928
  const suggestions = suggest(
16041
16929
  value,
@@ -16360,7 +17248,7 @@ import { randomUUID as randomUUID6 } from "node:crypto";
16360
17248
  // src/terminal-session.ts
16361
17249
  import { EventEmitter as EventEmitter2 } from "node:events";
16362
17250
  import { accessSync, chmodSync, constants } from "node:fs";
16363
- import { createRequire } from "node:module";
17251
+ import { createRequire as createRequire2 } from "node:module";
16364
17252
  import { dirname, join } from "node:path";
16365
17253
  import * as nodePty from "node-pty";
16366
17254
 
@@ -17499,8 +18387,8 @@ var spawnHelperChecked = false;
17499
18387
  function ensureSpawnHelperExecutable() {
17500
18388
  if (spawnHelperChecked) return;
17501
18389
  spawnHelperChecked = true;
17502
- const require3 = createRequire(import.meta.url);
17503
- const nodePtyDir = dirname(require3.resolve("node-pty"));
18390
+ const require4 = createRequire2(import.meta.url);
18391
+ const nodePtyDir = dirname(require4.resolve("node-pty"));
17504
18392
  const helper = join(nodePtyDir, "..", "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper");
17505
18393
  try {
17506
18394
  accessSync(helper, constants.X_OK);
@@ -17920,7 +18808,7 @@ var getSession = defineCommand({
17920
18808
 
17921
18809
  // ../agent-skill-config/src/configs.ts
17922
18810
  import os2 from "node:os";
17923
- import path15 from "node:path";
18811
+ import path16 from "node:path";
17924
18812
 
17925
18813
  // ../agent-defs/src/agents/claude-code.ts
17926
18814
  var claudeCodeAgent = {
@@ -18284,7 +19172,7 @@ var templateMutation = {
18284
19172
 
18285
19173
  // ../config-mutations/src/execution/apply-mutation.ts
18286
19174
  import { randomUUID as randomUUID7 } from "node:crypto";
18287
- import path17 from "node:path";
19175
+ import path18 from "node:path";
18288
19176
 
18289
19177
  // ../config-mutations/src/formats/json.ts
18290
19178
  import * as jsonc from "jsonc-parser";
@@ -18407,22 +19295,22 @@ function prune(obj, shape) {
18407
19295
  }
18408
19296
  return { changed, result };
18409
19297
  }
18410
- function modifyAtPath(content, path25, value) {
19298
+ function modifyAtPath(content, path26, value) {
18411
19299
  const indent = detectIndent(content);
18412
19300
  const formattingOptions = {
18413
19301
  tabSize: indent === " " ? 1 : indent.length,
18414
19302
  insertSpaces: indent !== " ",
18415
19303
  eol: "\n"
18416
19304
  };
18417
- const edits = jsonc.modify(content, path25, value, { formattingOptions });
19305
+ const edits = jsonc.modify(content, path26, value, { formattingOptions });
18418
19306
  let result = jsonc.applyEdits(content, edits);
18419
19307
  if (!result.endsWith("\n")) {
18420
19308
  result += "\n";
18421
19309
  }
18422
19310
  return result;
18423
19311
  }
18424
- function removeAtPath(content, path25) {
18425
- return modifyAtPath(content, path25, void 0);
19312
+ function removeAtPath(content, path26) {
19313
+ return modifyAtPath(content, path26, void 0);
18426
19314
  }
18427
19315
  function serializeUpdate(content, current, next) {
18428
19316
  let result = content || "{}";
@@ -18432,15 +19320,15 @@ function serializeUpdate(content, current, next) {
18432
19320
  }
18433
19321
  return result;
18434
19322
  }
18435
- function applyObjectUpdate(content, path25, current, next) {
19323
+ function applyObjectUpdate(content, path26, current, next) {
18436
19324
  let result = content;
18437
19325
  for (const key2 of Object.keys(current)) {
18438
19326
  if (!hasConfigEntry(next, key2)) {
18439
- result = removeAtPath(result, [...path25, key2]);
19327
+ result = removeAtPath(result, [...path26, key2]);
18440
19328
  }
18441
19329
  }
18442
19330
  for (const [key2, nextValue] of Object.entries(next)) {
18443
- const nextPath = [...path25, key2];
19331
+ const nextPath = [...path26, key2];
18444
19332
  const hasCurrent = hasConfigEntry(current, key2);
18445
19333
  const currentValue = hasCurrent ? current[key2] : void 0;
18446
19334
  if (hasCurrent && isConfigObject(currentValue) && isConfigObject(nextValue)) {
@@ -18640,20 +19528,20 @@ function getConfigFormat(pathOrFormat) {
18640
19528
  }
18641
19529
  return formatRegistry[formatName];
18642
19530
  }
18643
- function detectFormat(path25) {
18644
- const ext = getExtension(path25);
19531
+ function detectFormat(path26) {
19532
+ const ext = getExtension(path26);
18645
19533
  return extensionMap[ext];
18646
19534
  }
18647
- function getExtension(path25) {
18648
- const lastDot = path25.lastIndexOf(".");
19535
+ function getExtension(path26) {
19536
+ const lastDot = path26.lastIndexOf(".");
18649
19537
  if (lastDot === -1) {
18650
19538
  return "";
18651
19539
  }
18652
- return path25.slice(lastDot).toLowerCase();
19540
+ return path26.slice(lastDot).toLowerCase();
18653
19541
  }
18654
19542
 
18655
19543
  // ../config-mutations/src/execution/path-utils.ts
18656
- import path16 from "node:path";
19544
+ import path17 from "node:path";
18657
19545
  function expandHome(targetPath, homeDir) {
18658
19546
  if (!targetPath?.startsWith("~")) {
18659
19547
  return targetPath;
@@ -18670,7 +19558,7 @@ function expandHome(targetPath, homeDir) {
18670
19558
  remainder = remainder.slice(1);
18671
19559
  }
18672
19560
  }
18673
- return remainder.length === 0 ? homeDir : path16.join(homeDir, remainder);
19561
+ return remainder.length === 0 ? homeDir : path17.join(homeDir, remainder);
18674
19562
  }
18675
19563
  function validateHomePath(targetPath) {
18676
19564
  if (typeof targetPath !== "string" || targetPath.length === 0) {
@@ -18685,21 +19573,21 @@ function validateHomePath(targetPath) {
18685
19573
  function resolvePath(rawPath, homeDir, pathMapper) {
18686
19574
  validateHomePath(rawPath);
18687
19575
  const expanded = expandHome(rawPath, homeDir);
18688
- const canonicalHome = path16.resolve(homeDir);
18689
- const canonicalExpanded = path16.resolve(expanded);
18690
- const relative = path16.relative(canonicalHome, canonicalExpanded);
18691
- if (relative === ".." || relative.startsWith(`..${path16.sep}`) || path16.isAbsolute(relative)) {
19576
+ const canonicalHome = path17.resolve(homeDir);
19577
+ const canonicalExpanded = path17.resolve(expanded);
19578
+ const relative = path17.relative(canonicalHome, canonicalExpanded);
19579
+ if (relative === ".." || relative.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative)) {
18692
19580
  throw new Error(`Target path resolves outside home directory: "${rawPath}"`);
18693
19581
  }
18694
19582
  if (!pathMapper) {
18695
19583
  return canonicalExpanded;
18696
19584
  }
18697
- const rawDirectory = path16.dirname(expanded);
19585
+ const rawDirectory = path17.dirname(expanded);
18698
19586
  const mappedDirectory = pathMapper.mapTargetDirectory({
18699
19587
  targetDirectory: rawDirectory
18700
19588
  });
18701
- const filename = path16.basename(expanded);
18702
- return filename.length === 0 ? mappedDirectory : path16.join(mappedDirectory, filename);
19589
+ const filename = path17.basename(expanded);
19590
+ return filename.length === 0 ? mappedDirectory : path17.join(mappedDirectory, filename);
18703
19591
  }
18704
19592
 
18705
19593
  // ../config-mutations/src/error-codes.ts
@@ -18711,9 +19599,9 @@ function hasOwnErrorCode5(error3, code) {
18711
19599
  function isNotFound(error3) {
18712
19600
  return hasOwnErrorCode5(error3, "ENOENT");
18713
19601
  }
18714
- async function readFileIfExists(fs4, target) {
19602
+ async function readFileIfExists(fs5, target) {
18715
19603
  try {
18716
- return await fs4.readFile(target, "utf8");
19604
+ return await fs5.readFile(target, "utf8");
18717
19605
  } catch (error3) {
18718
19606
  if (isNotFound(error3)) {
18719
19607
  return null;
@@ -18721,9 +19609,9 @@ async function readFileIfExists(fs4, target) {
18721
19609
  throw error3;
18722
19610
  }
18723
19611
  }
18724
- async function pathExists(fs4, target) {
19612
+ async function pathExists(fs5, target) {
18725
19613
  try {
18726
- await fs4.stat(target);
19614
+ await fs5.stat(target);
18727
19615
  return true;
18728
19616
  } catch (error3) {
18729
19617
  if (isNotFound(error3)) {
@@ -18769,8 +19657,8 @@ function isAlreadyExists(error3) {
18769
19657
  return hasOwnErrorCode5(error3, "EEXIST");
18770
19658
  }
18771
19659
  async function assertRegularWriteTarget(context, targetPath) {
18772
- const boundary = path17.dirname(path17.resolve(context.homeDir));
18773
- let currentPath = path17.resolve(targetPath);
19660
+ const boundary = path18.dirname(path18.resolve(context.homeDir));
19661
+ let currentPath = path18.resolve(targetPath);
18774
19662
  while (currentPath !== boundary) {
18775
19663
  try {
18776
19664
  if ((await context.fs.lstat(currentPath)).isSymbolicLink()) {
@@ -18781,7 +19669,7 @@ async function assertRegularWriteTarget(context, targetPath) {
18781
19669
  throw error3;
18782
19670
  }
18783
19671
  }
18784
- const parentPath = path17.dirname(currentPath);
19672
+ const parentPath = path18.dirname(currentPath);
18785
19673
  if (parentPath === currentPath) {
18786
19674
  return;
18787
19675
  }
@@ -18846,6 +19734,56 @@ function describeMutation(kind, targetPath) {
18846
19734
  return "Operation";
18847
19735
  }
18848
19736
  }
19737
+ function mutationTargetPath(mutation, options) {
19738
+ switch (mutation.kind) {
19739
+ case "ensureDirectory":
19740
+ case "removeDirectory":
19741
+ return resolveValue(mutation.path, options);
19742
+ case "removeFile":
19743
+ case "chmod":
19744
+ case "backup":
19745
+ case "restoreBackup":
19746
+ case "configMerge":
19747
+ case "configPrune":
19748
+ case "configTransform":
19749
+ case "templateWrite":
19750
+ case "templateMergeToml":
19751
+ case "templateMergeJson":
19752
+ return resolveValue(mutation.target, options);
19753
+ default:
19754
+ return void 0;
19755
+ }
19756
+ }
19757
+ function resolveMutationDetails(mutation, context, options) {
19758
+ try {
19759
+ const rawTarget = mutationTargetPath(mutation, options);
19760
+ if (rawTarget === void 0) {
19761
+ return {
19762
+ kind: mutation.kind,
19763
+ label: mutation.label ?? mutation.kind
19764
+ };
19765
+ }
19766
+ try {
19767
+ const targetPath = resolvePath(rawTarget, context.homeDir, context.pathMapper);
19768
+ return {
19769
+ kind: mutation.kind,
19770
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
19771
+ targetPath
19772
+ };
19773
+ } catch {
19774
+ return {
19775
+ kind: mutation.kind,
19776
+ label: mutation.label ?? describeMutation(mutation.kind, rawTarget),
19777
+ targetPath: void 0
19778
+ };
19779
+ }
19780
+ } catch {
19781
+ return {
19782
+ kind: mutation.kind,
19783
+ label: mutation.label ?? mutation.kind
19784
+ };
19785
+ }
19786
+ }
18849
19787
  function pruneKeysByPrefix(table, prefix) {
18850
19788
  const result = {};
18851
19789
  for (const [key2, value] of Object.entries(table)) {
@@ -18936,6 +19874,7 @@ async function applyEnsureDirectory(mutation, context, options) {
18936
19874
  label: mutation.label ?? describeMutation(mutation.kind, targetPath),
18937
19875
  targetPath
18938
19876
  };
19877
+ await assertRegularWriteTarget(context, targetPath);
18939
19878
  const existed = await pathExists(context.fs, targetPath);
18940
19879
  if (!context.dryRun) {
18941
19880
  await context.fs.mkdir(targetPath, { recursive: true });
@@ -19052,6 +19991,7 @@ async function applyChmod(mutation, context, options) {
19052
19991
  };
19053
19992
  }
19054
19993
  try {
19994
+ await assertRegularWriteTarget(context, targetPath);
19055
19995
  const stat2 = await context.fs.stat(targetPath);
19056
19996
  const currentMode = typeof stat2.mode === "number" ? stat2.mode & 511 : null;
19057
19997
  if (currentMode === mutation.mode) {
@@ -19085,6 +20025,7 @@ async function applyBackup(mutation, context, options) {
19085
20025
  label: mutation.label ?? describeMutation(mutation.kind, targetPath),
19086
20026
  targetPath
19087
20027
  };
20028
+ await assertRegularWriteTarget(context, targetPath);
19088
20029
  if (mutation.once && await findLatestGeneratedBackup(context.fs, targetPath) !== null) {
19089
20030
  return {
19090
20031
  outcome: { changed: false, effect: "none", detail: "noop" },
@@ -19151,13 +20092,13 @@ async function applyRestoreBackup(mutation, context, options) {
19151
20092
  }
19152
20093
  return { outcome: { changed: true, effect: "copy", detail: "restore" }, details };
19153
20094
  }
19154
- async function findLatestGeneratedBackup(fs4, targetPath) {
20095
+ async function findLatestGeneratedBackup(fs5, targetPath) {
19155
20096
  const separatorIndex = targetPath.lastIndexOf("/");
19156
20097
  const directoryPath = separatorIndex <= 0 ? "/" : targetPath.slice(0, separatorIndex);
19157
20098
  const targetName = targetPath.slice(separatorIndex + 1);
19158
20099
  let entries;
19159
20100
  try {
19160
- entries = await fs4.readdir(directoryPath);
20101
+ entries = await fs5.readdir(directoryPath);
19161
20102
  } catch (error3) {
19162
20103
  if (isNotFound(error3)) {
19163
20104
  return null;
@@ -19221,6 +20162,9 @@ async function applyConfigMerge(mutation, context, options) {
19221
20162
  preserveContent = null;
19222
20163
  }
19223
20164
  const value = resolveValue(mutation.value, options);
20165
+ if (!isConfigObject4(value)) {
20166
+ throw new Error(`configMerge value must be an object for "${rawPath}".`);
20167
+ }
19224
20168
  let merged;
19225
20169
  if (mutation.pruneByPrefix) {
19226
20170
  merged = mergeWithPruneByPrefix(current, value, mutation.pruneByPrefix);
@@ -19354,6 +20298,13 @@ async function applyConfigTransform(mutation, context, options) {
19354
20298
  };
19355
20299
  }
19356
20300
  const serialized = serializeConfigUpdate(format, preserveContent, current, transformed);
20301
+ const serializedChanged = serialized !== rawContent;
20302
+ if (!serializedChanged) {
20303
+ return {
20304
+ outcome: { changed: false, effect: "none", detail: "noop" },
20305
+ details
20306
+ };
20307
+ }
19357
20308
  if (!context.dryRun) {
19358
20309
  await writeAtomically2(context, targetPath, serialized);
19359
20310
  }
@@ -19470,25 +20421,14 @@ async function runMutations(mutations, context, options) {
19470
20421
  };
19471
20422
  }
19472
20423
  async function executeMutation(mutation, context, options) {
19473
- context.observers?.onStart?.({
19474
- kind: mutation.kind,
19475
- label: mutation.label ?? mutation.kind,
19476
- targetPath: void 0
19477
- // Will be resolved during apply
19478
- });
20424
+ const pendingDetails = resolveMutationDetails(mutation, context, options);
20425
+ context.observers?.onStart?.(pendingDetails);
19479
20426
  try {
19480
20427
  const { outcome, details } = await applyMutation(mutation, context, options);
19481
20428
  context.observers?.onComplete?.(details, outcome);
19482
20429
  return { outcome, details };
19483
20430
  } catch (error3) {
19484
- context.observers?.onError?.(
19485
- {
19486
- kind: mutation.kind,
19487
- label: mutation.label ?? mutation.kind,
19488
- targetPath: void 0
19489
- },
19490
- error3
19491
- );
20431
+ context.observers?.onError?.(pendingDetails, error3);
19492
20432
  throw error3;
19493
20433
  }
19494
20434
  }
@@ -19499,8 +20439,8 @@ function hasOwnErrorCode6(error3, code) {
19499
20439
  }
19500
20440
 
19501
20441
  // ../agent-skill-config/src/templates.ts
19502
- import { readFile as readFile5, stat } from "node:fs/promises";
19503
- import path18 from "node:path";
20442
+ import { readFile as readFile6, stat } from "node:fs/promises";
20443
+ import path19 from "node:path";
19504
20444
  import { fileURLToPath as fileURLToPath3 } from "node:url";
19505
20445
 
19506
20446
  // ../agent-skill-config/src/apply.ts
@@ -19517,9 +20457,9 @@ function toHomeRelative(localSkillDir) {
19517
20457
  const normalized = localSkillDir.startsWith("./") ? localSkillDir.slice(2) : localSkillDir;
19518
20458
  return `~/${normalized}`;
19519
20459
  }
19520
- async function pathExists2(fs4, targetPath) {
20460
+ async function pathExists2(fs5, targetPath) {
19521
20461
  try {
19522
- await fs4.stat(targetPath);
20462
+ await fs5.stat(targetPath);
19523
20463
  return true;
19524
20464
  } catch (error3) {
19525
20465
  if (hasOwnErrorCode6(error3, "ENOENT")) {
@@ -19536,7 +20476,7 @@ async function installSkill(agentId, skill, options) {
19536
20476
  }
19537
20477
  const scope = options.scope ?? "local";
19538
20478
  const config2 = support.config;
19539
- if (skill.name.length === 0 || skill.name === "." || skill.name === ".." || skill.name.includes("/") || skill.name.includes("\\") || skill.name.includes("\n") || skill.name.includes("\r")) {
20479
+ 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")) {
19540
20480
  throw new Error(`Invalid skill name: ${skill.name}`);
19541
20481
  }
19542
20482
  const skillDir = scope === "global" ? config2.globalSkillDir : toHomeRelative(config2.localSkillDir);
@@ -19572,29 +20512,29 @@ async function installSkill(agentId, skill, options) {
19572
20512
  }
19573
20513
  }
19574
20514
  );
19575
- return { skillPath: skillFilePath, displayPath };
20515
+ return { skillPath: absoluteSkillPath, displayPath };
19576
20516
  }
19577
20517
 
19578
20518
  // ../agent-skill-config/src/resolve-skill-reference.ts
19579
- import { statSync as statSync2 } from "node:fs";
19580
- import path19 from "node:path";
20519
+ import * as fs2 from "node:fs";
20520
+ import path20 from "node:path";
19581
20521
 
19582
20522
  // ../agent-skill-config/src/git-exclude.ts
19583
20523
  import { execFileSync } from "node:child_process";
19584
20524
  import { randomUUID as randomUUID8 } from "node:crypto";
19585
- import * as fs2 from "node:fs";
19586
- import path20 from "node:path";
20525
+ import * as fs3 from "node:fs";
20526
+ import path21 from "node:path";
19587
20527
 
19588
20528
  // ../agent-skill-config/src/bridge-active-skills.ts
19589
- import * as fs3 from "node:fs";
20529
+ import * as fs4 from "node:fs";
19590
20530
  import { createHash as createHash4, randomUUID as randomUUID9 } from "node:crypto";
19591
- import path21 from "node:path";
20531
+ import path22 from "node:path";
19592
20532
 
19593
20533
  // src/commands/installer.ts
19594
20534
  import os3 from "node:os";
19595
- import path22 from "node:path";
20535
+ import path23 from "node:path";
19596
20536
  import * as nodeFs2 from "node:fs/promises";
19597
- import { readFile as readFile6 } from "node:fs/promises";
20537
+ import { readFile as readFile7 } from "node:fs/promises";
19598
20538
  var DEFAULT_INSTALL_AGENT = "claude-code";
19599
20539
  var DEFAULT_INSTALL_SCOPE = "local";
19600
20540
  var TERMINAL_PILOT_SKILL_NAME = "terminal-pilot";
@@ -19644,7 +20584,7 @@ async function loadTerminalPilotTemplate() {
19644
20584
  ];
19645
20585
  for (const candidate of candidates) {
19646
20586
  try {
19647
- terminalPilotTemplateCache = await readFile6(candidate, "utf8");
20587
+ terminalPilotTemplateCache = await readFile7(candidate, "utf8");
19648
20588
  return terminalPilotTemplateCache;
19649
20589
  } catch (error3) {
19650
20590
  if (!isNotFoundError2(error3)) {
@@ -19659,7 +20599,7 @@ function resolveHomeRelativePath(targetPath, homeDir) {
19659
20599
  return homeDir;
19660
20600
  }
19661
20601
  if (targetPath.startsWith("~/")) {
19662
- return path22.join(homeDir, targetPath.slice(2));
20602
+ return path23.join(homeDir, targetPath.slice(2));
19663
20603
  }
19664
20604
  return targetPath;
19665
20605
  }
@@ -19669,22 +20609,22 @@ function getSkillFolderWithHome(agent, scope, cwd, homeDir) {
19669
20609
  throwUnsupportedAgent(agent);
19670
20610
  }
19671
20611
  return {
19672
- displayPath: path22.join(
20612
+ displayPath: path23.join(
19673
20613
  scope === "global" ? config2.globalSkillDir : config2.localSkillDir,
19674
20614
  TERMINAL_PILOT_SKILL_NAME
19675
20615
  ),
19676
- fullPath: path22.join(
19677
- scope === "global" ? resolveHomeRelativePath(config2.globalSkillDir, homeDir) : path22.resolve(cwd, config2.localSkillDir),
20616
+ fullPath: path23.join(
20617
+ scope === "global" ? resolveHomeRelativePath(config2.globalSkillDir, homeDir) : path23.resolve(cwd, config2.localSkillDir),
19678
20618
  TERMINAL_PILOT_SKILL_NAME
19679
20619
  )
19680
20620
  };
19681
20621
  }
19682
- async function assertNoSymbolicLinkPath(fs4, targetPath) {
19683
- const rootPath = path22.parse(targetPath).root;
20622
+ async function assertNoSymbolicLinkPath(fs5, targetPath) {
20623
+ const rootPath = path23.parse(targetPath).root;
19684
20624
  let currentPath = targetPath;
19685
20625
  while (currentPath !== rootPath) {
19686
20626
  try {
19687
- if ((await fs4.lstat(currentPath)).isSymbolicLink()) {
20627
+ if ((await fs5.lstat(currentPath)).isSymbolicLink()) {
19688
20628
  throw new UserError(`Refusing terminal-pilot skill operation through symbolic link: ${currentPath}`);
19689
20629
  }
19690
20630
  } catch (error3) {
@@ -19692,7 +20632,7 @@ async function assertNoSymbolicLinkPath(fs4, targetPath) {
19692
20632
  throw error3;
19693
20633
  }
19694
20634
  }
19695
- currentPath = path22.dirname(currentPath);
20635
+ currentPath = path23.dirname(currentPath);
19696
20636
  }
19697
20637
  }
19698
20638
 
@@ -20391,11 +21331,11 @@ import { Resvg } from "@resvg/resvg-js";
20391
21331
 
20392
21332
  // ../terminal-png/src/font.ts
20393
21333
  import { readFileSync as readFileSync4 } from "node:fs";
20394
- import { createRequire as createRequire2 } from "node:module";
21334
+ import { createRequire as createRequire3 } from "node:module";
20395
21335
  import { dirname as dirname2, join as join2 } from "node:path";
20396
21336
  import { fileURLToPath as fileURLToPath4 } from "node:url";
20397
- var require2 = createRequire2(import.meta.url);
20398
- var fontPackageRoot = dirname2(require2.resolve("jetbrains-mono/package.json"));
21337
+ var require3 = createRequire3(import.meta.url);
21338
+ var fontPackageRoot = dirname2(require3.resolve("jetbrains-mono/package.json"));
20399
21339
  var webfontRoot = join2(fontPackageRoot, "fonts/webfonts");
20400
21340
  function readWebfontBase64(filename) {
20401
21341
  return readFileSync4(join2(webfontRoot, filename)).toString("base64");
@@ -21105,9 +22045,9 @@ var uninstall = defineCommand({
21105
22045
  };
21106
22046
  }
21107
22047
  });
21108
- async function folderExists(fs4, folderPath) {
22048
+ async function folderExists(fs5, folderPath) {
21109
22049
  try {
21110
- await fs4.stat(folderPath);
22050
+ await fs5.stat(folderPath);
21111
22051
  return true;
21112
22052
  } catch (error3) {
21113
22053
  if (hasOwnErrorCode4(error3, "ENOENT")) {
@@ -21252,7 +22192,7 @@ async function isDirectExecution(argv) {
21252
22192
  try {
21253
22193
  const modulePath = fileURLToPath5(import.meta.url);
21254
22194
  const [resolvedEntryPoint, resolvedModulePath] = await Promise.all([
21255
- realpath3(path23.resolve(entryPoint)),
22195
+ realpath3(path24.resolve(entryPoint)),
21256
22196
  realpath3(modulePath)
21257
22197
  ]);
21258
22198
  return resolvedEntryPoint === resolvedModulePath;
@@ -21364,13 +22304,13 @@ function createTerminalPilotCliRepl() {
21364
22304
  }
21365
22305
 
21366
22306
  // src/testing/qa-cli.ts
21367
- var testingDirectory = path24.dirname(fileURLToPath6(import.meta.url));
21368
- var repoRoot = path24.resolve(testingDirectory, "../../../..");
21369
- var tsxPath = path24.join(repoRoot, "node_modules", ".bin", "tsx");
21370
- var testCliPath = path24.join(repoRoot, "packages/terminal-pilot/src/testing/test-cli.js");
21371
- var menuCliPath = path24.join(repoRoot, "packages/terminal-pilot/src/testing/menu-cli.js");
21372
- var vimSavedFile = path24.join(os4.tmpdir(), "terminal-pilot-qa-test.txt");
21373
- var vimDiscardFile = path24.join(os4.tmpdir(), "terminal-pilot-qa-discard.txt");
22307
+ var testingDirectory = path25.dirname(fileURLToPath6(import.meta.url));
22308
+ var repoRoot = path25.resolve(testingDirectory, "../../../..");
22309
+ var tsxPath = path25.join(repoRoot, "node_modules", ".bin", "tsx");
22310
+ var testCliPath = path25.join(repoRoot, "packages/terminal-pilot/src/testing/test-cli.js");
22311
+ var menuCliPath = path25.join(repoRoot, "packages/terminal-pilot/src/testing/menu-cli.js");
22312
+ var vimSavedFile = path25.join(os4.tmpdir(), "terminal-pilot-qa-test.txt");
22313
+ var vimDiscardFile = path25.join(os4.tmpdir(), "terminal-pilot-qa-discard.txt");
21374
22314
  var QaContext = class {
21375
22315
  repl = createTerminalPilotCliRepl();
21376
22316
  async close() {
@@ -22116,7 +23056,7 @@ var cases = [
22116
23056
  "VIM",
22117
23057
  "-t",
22118
23058
  "5000",
22119
- path24.basename(vimSavedFile)
23059
+ path25.basename(vimSavedFile)
22120
23060
  ]);
22121
23061
  await ctx.expectOk(["press-key", "-s", "VIM", "i"]);
22122
23062
  await ctx.expectOk(["type", "-s", "VIM", "hello from terminal-pilot"]);
@@ -22171,7 +23111,7 @@ var cases = [
22171
23111
  "VIM2",
22172
23112
  "-t",
22173
23113
  "5000",
22174
- path24.basename(vimDiscardFile)
23114
+ path25.basename(vimDiscardFile)
22175
23115
  ]);
22176
23116
  await ctx.expectOk(["press-key", "-s", "VIM2", "i"]);
22177
23117
  await ctx.expectOk(["type", "-s", "VIM2", "this should not be saved"]);