@hashicorp/kits 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/README.md +619 -0
  2. package/bin/kits.js +8 -0
  3. package/dist/adapters/base-adapter.d.ts +231 -0
  4. package/dist/adapters/base-adapter.d.ts.map +1 -0
  5. package/dist/adapters/base-adapter.js +703 -0
  6. package/dist/adapters/base-adapter.js.map +1 -0
  7. package/dist/adapters/claude-code/detection.d.ts +63 -0
  8. package/dist/adapters/claude-code/detection.d.ts.map +1 -0
  9. package/dist/adapters/claude-code/detection.js +154 -0
  10. package/dist/adapters/claude-code/detection.js.map +1 -0
  11. package/dist/adapters/claude-code/index.d.ts +178 -0
  12. package/dist/adapters/claude-code/index.d.ts.map +1 -0
  13. package/dist/adapters/claude-code/index.js +643 -0
  14. package/dist/adapters/claude-code/index.js.map +1 -0
  15. package/dist/adapters/claude-code/installer.d.ts +161 -0
  16. package/dist/adapters/claude-code/installer.d.ts.map +1 -0
  17. package/dist/adapters/claude-code/installer.js +413 -0
  18. package/dist/adapters/claude-code/installer.js.map +1 -0
  19. package/dist/adapters/claude-code/model-mapping.d.ts +7 -0
  20. package/dist/adapters/claude-code/model-mapping.d.ts.map +1 -0
  21. package/dist/adapters/claude-code/model-mapping.js +14 -0
  22. package/dist/adapters/claude-code/model-mapping.js.map +1 -0
  23. package/dist/adapters/claude-code/tool-mapping.d.ts +18 -0
  24. package/dist/adapters/claude-code/tool-mapping.d.ts.map +1 -0
  25. package/dist/adapters/claude-code/tool-mapping.js +31 -0
  26. package/dist/adapters/claude-code/tool-mapping.js.map +1 -0
  27. package/dist/adapters/codex/detection.d.ts +60 -0
  28. package/dist/adapters/codex/detection.d.ts.map +1 -0
  29. package/dist/adapters/codex/detection.js +146 -0
  30. package/dist/adapters/codex/detection.js.map +1 -0
  31. package/dist/adapters/codex/index.d.ts +167 -0
  32. package/dist/adapters/codex/index.d.ts.map +1 -0
  33. package/dist/adapters/codex/index.js +344 -0
  34. package/dist/adapters/codex/index.js.map +1 -0
  35. package/dist/adapters/codex/installer.d.ts +147 -0
  36. package/dist/adapters/codex/installer.d.ts.map +1 -0
  37. package/dist/adapters/codex/installer.js +229 -0
  38. package/dist/adapters/codex/installer.js.map +1 -0
  39. package/dist/adapters/codex/model-mapping.d.ts +7 -0
  40. package/dist/adapters/codex/model-mapping.d.ts.map +1 -0
  41. package/dist/adapters/codex/model-mapping.js +14 -0
  42. package/dist/adapters/codex/model-mapping.js.map +1 -0
  43. package/dist/adapters/codex/tool-mapping.d.ts +19 -0
  44. package/dist/adapters/codex/tool-mapping.d.ts.map +1 -0
  45. package/dist/adapters/codex/tool-mapping.js +32 -0
  46. package/dist/adapters/codex/tool-mapping.js.map +1 -0
  47. package/dist/adapters/command-parser.d.ts +72 -0
  48. package/dist/adapters/command-parser.d.ts.map +1 -0
  49. package/dist/adapters/command-parser.js +222 -0
  50. package/dist/adapters/command-parser.js.map +1 -0
  51. package/dist/adapters/file-operations.d.ts +164 -0
  52. package/dist/adapters/file-operations.d.ts.map +1 -0
  53. package/dist/adapters/file-operations.js +526 -0
  54. package/dist/adapters/file-operations.js.map +1 -0
  55. package/dist/adapters/gemini-cli/detection.d.ts +57 -0
  56. package/dist/adapters/gemini-cli/detection.d.ts.map +1 -0
  57. package/dist/adapters/gemini-cli/detection.js +143 -0
  58. package/dist/adapters/gemini-cli/detection.js.map +1 -0
  59. package/dist/adapters/gemini-cli/index.d.ts +182 -0
  60. package/dist/adapters/gemini-cli/index.d.ts.map +1 -0
  61. package/dist/adapters/gemini-cli/index.js +598 -0
  62. package/dist/adapters/gemini-cli/index.js.map +1 -0
  63. package/dist/adapters/gemini-cli/installer.d.ts +158 -0
  64. package/dist/adapters/gemini-cli/installer.d.ts.map +1 -0
  65. package/dist/adapters/gemini-cli/installer.js +457 -0
  66. package/dist/adapters/gemini-cli/installer.js.map +1 -0
  67. package/dist/adapters/gemini-cli/model-mapping.d.ts +7 -0
  68. package/dist/adapters/gemini-cli/model-mapping.d.ts.map +1 -0
  69. package/dist/adapters/gemini-cli/model-mapping.js +14 -0
  70. package/dist/adapters/gemini-cli/model-mapping.js.map +1 -0
  71. package/dist/adapters/gemini-cli/tool-mapping.d.ts +18 -0
  72. package/dist/adapters/gemini-cli/tool-mapping.d.ts.map +1 -0
  73. package/dist/adapters/gemini-cli/tool-mapping.js +31 -0
  74. package/dist/adapters/gemini-cli/tool-mapping.js.map +1 -0
  75. package/dist/adapters/github-copilot/detection.d.ts +58 -0
  76. package/dist/adapters/github-copilot/detection.d.ts.map +1 -0
  77. package/dist/adapters/github-copilot/detection.js +144 -0
  78. package/dist/adapters/github-copilot/detection.js.map +1 -0
  79. package/dist/adapters/github-copilot/index.d.ts +203 -0
  80. package/dist/adapters/github-copilot/index.d.ts.map +1 -0
  81. package/dist/adapters/github-copilot/index.js +595 -0
  82. package/dist/adapters/github-copilot/index.js.map +1 -0
  83. package/dist/adapters/github-copilot/installer.d.ts +124 -0
  84. package/dist/adapters/github-copilot/installer.d.ts.map +1 -0
  85. package/dist/adapters/github-copilot/installer.js +343 -0
  86. package/dist/adapters/github-copilot/installer.js.map +1 -0
  87. package/dist/adapters/github-copilot/model-mapping.d.ts +7 -0
  88. package/dist/adapters/github-copilot/model-mapping.d.ts.map +1 -0
  89. package/dist/adapters/github-copilot/model-mapping.js +14 -0
  90. package/dist/adapters/github-copilot/model-mapping.js.map +1 -0
  91. package/dist/adapters/github-copilot/tool-mapping.d.ts +18 -0
  92. package/dist/adapters/github-copilot/tool-mapping.d.ts.map +1 -0
  93. package/dist/adapters/github-copilot/tool-mapping.js +31 -0
  94. package/dist/adapters/github-copilot/tool-mapping.js.map +1 -0
  95. package/dist/adapters/index.d.ts +39 -0
  96. package/dist/adapters/index.d.ts.map +1 -0
  97. package/dist/adapters/index.js +76 -0
  98. package/dist/adapters/index.js.map +1 -0
  99. package/dist/adapters/interface.d.ts +9 -0
  100. package/dist/adapters/interface.d.ts.map +1 -0
  101. package/dist/adapters/interface.js +8 -0
  102. package/dist/adapters/interface.js.map +1 -0
  103. package/dist/adapters/model-templating.d.ts +16 -0
  104. package/dist/adapters/model-templating.d.ts.map +1 -0
  105. package/dist/adapters/model-templating.js +52 -0
  106. package/dist/adapters/model-templating.js.map +1 -0
  107. package/dist/adapters/opencode/detection.d.ts +57 -0
  108. package/dist/adapters/opencode/detection.d.ts.map +1 -0
  109. package/dist/adapters/opencode/detection.js +140 -0
  110. package/dist/adapters/opencode/detection.js.map +1 -0
  111. package/dist/adapters/opencode/index.d.ts +168 -0
  112. package/dist/adapters/opencode/index.d.ts.map +1 -0
  113. package/dist/adapters/opencode/index.js +494 -0
  114. package/dist/adapters/opencode/index.js.map +1 -0
  115. package/dist/adapters/opencode/installer.d.ts +91 -0
  116. package/dist/adapters/opencode/installer.d.ts.map +1 -0
  117. package/dist/adapters/opencode/installer.js +290 -0
  118. package/dist/adapters/opencode/installer.js.map +1 -0
  119. package/dist/adapters/opencode/model-mapping.d.ts +7 -0
  120. package/dist/adapters/opencode/model-mapping.d.ts.map +1 -0
  121. package/dist/adapters/opencode/model-mapping.js +14 -0
  122. package/dist/adapters/opencode/model-mapping.js.map +1 -0
  123. package/dist/adapters/opencode/tool-mapping.d.ts +18 -0
  124. package/dist/adapters/opencode/tool-mapping.d.ts.map +1 -0
  125. package/dist/adapters/opencode/tool-mapping.js +31 -0
  126. package/dist/adapters/opencode/tool-mapping.js.map +1 -0
  127. package/dist/adapters/registry.d.ts +154 -0
  128. package/dist/adapters/registry.d.ts.map +1 -0
  129. package/dist/adapters/registry.js +223 -0
  130. package/dist/adapters/registry.js.map +1 -0
  131. package/dist/adapters/skill-frontmatter.d.ts +34 -0
  132. package/dist/adapters/skill-frontmatter.d.ts.map +1 -0
  133. package/dist/adapters/skill-frontmatter.js +110 -0
  134. package/dist/adapters/skill-frontmatter.js.map +1 -0
  135. package/dist/adapters/subagent-frontmatter.d.ts +22 -0
  136. package/dist/adapters/subagent-frontmatter.d.ts.map +1 -0
  137. package/dist/adapters/subagent-frontmatter.js +80 -0
  138. package/dist/adapters/subagent-frontmatter.js.map +1 -0
  139. package/dist/adapters/tool-templating.d.ts +162 -0
  140. package/dist/adapters/tool-templating.d.ts.map +1 -0
  141. package/dist/adapters/tool-templating.js +273 -0
  142. package/dist/adapters/tool-templating.js.map +1 -0
  143. package/dist/adapters/types.d.ts +347 -0
  144. package/dist/adapters/types.d.ts.map +1 -0
  145. package/dist/adapters/types.js +33 -0
  146. package/dist/adapters/types.js.map +1 -0
  147. package/dist/cli/index.d.ts +10 -0
  148. package/dist/cli/index.d.ts.map +1 -0
  149. package/dist/cli/index.js +261 -0
  150. package/dist/cli/index.js.map +1 -0
  151. package/dist/cli/info.d.ts +20 -0
  152. package/dist/cli/info.d.ts.map +1 -0
  153. package/dist/cli/info.js +194 -0
  154. package/dist/cli/info.js.map +1 -0
  155. package/dist/cli/install.d.ts +21 -0
  156. package/dist/cli/install.d.ts.map +1 -0
  157. package/dist/cli/install.js +1624 -0
  158. package/dist/cli/install.js.map +1 -0
  159. package/dist/cli/list.d.ts +19 -0
  160. package/dist/cli/list.d.ts.map +1 -0
  161. package/dist/cli/list.js +216 -0
  162. package/dist/cli/list.js.map +1 -0
  163. package/dist/cli/types.d.ts +246 -0
  164. package/dist/cli/types.d.ts.map +1 -0
  165. package/dist/cli/types.js +25 -0
  166. package/dist/cli/types.js.map +1 -0
  167. package/dist/cli/uninstall.d.ts +20 -0
  168. package/dist/cli/uninstall.d.ts.map +1 -0
  169. package/dist/cli/uninstall.js +393 -0
  170. package/dist/cli/uninstall.js.map +1 -0
  171. package/dist/cli/upgrade.d.ts +20 -0
  172. package/dist/cli/upgrade.d.ts.map +1 -0
  173. package/dist/cli/upgrade.js +372 -0
  174. package/dist/cli/upgrade.js.map +1 -0
  175. package/dist/cli/validate.d.ts +14 -0
  176. package/dist/cli/validate.d.ts.map +1 -0
  177. package/dist/cli/validate.js +307 -0
  178. package/dist/cli/validate.js.map +1 -0
  179. package/dist/core/debug.d.ts +23 -0
  180. package/dist/core/debug.d.ts.map +1 -0
  181. package/dist/core/debug.js +69 -0
  182. package/dist/core/debug.js.map +1 -0
  183. package/dist/core/hook-instance.d.ts +8 -0
  184. package/dist/core/hook-instance.d.ts.map +1 -0
  185. package/dist/core/hook-instance.js +62 -0
  186. package/dist/core/hook-instance.js.map +1 -0
  187. package/dist/core/mcp-instance.d.ts +13 -0
  188. package/dist/core/mcp-instance.d.ts.map +1 -0
  189. package/dist/core/mcp-instance.js +80 -0
  190. package/dist/core/mcp-instance.js.map +1 -0
  191. package/dist/core/types.d.ts +461 -0
  192. package/dist/core/types.d.ts.map +1 -0
  193. package/dist/core/types.js +42 -0
  194. package/dist/core/types.js.map +1 -0
  195. package/dist/core/upgrade-executor.d.ts +70 -0
  196. package/dist/core/upgrade-executor.d.ts.map +1 -0
  197. package/dist/core/upgrade-executor.js +368 -0
  198. package/dist/core/upgrade-executor.js.map +1 -0
  199. package/dist/discovery/fetcher-registry.d.ts +87 -0
  200. package/dist/discovery/fetcher-registry.d.ts.map +1 -0
  201. package/dist/discovery/fetcher-registry.js +119 -0
  202. package/dist/discovery/fetcher-registry.js.map +1 -0
  203. package/dist/discovery/git-fetcher.d.ts +61 -0
  204. package/dist/discovery/git-fetcher.d.ts.map +1 -0
  205. package/dist/discovery/git-fetcher.js +150 -0
  206. package/dist/discovery/git-fetcher.js.map +1 -0
  207. package/dist/discovery/index.d.ts +13 -0
  208. package/dist/discovery/index.d.ts.map +1 -0
  209. package/dist/discovery/index.js +15 -0
  210. package/dist/discovery/index.js.map +1 -0
  211. package/dist/discovery/kit-scanner.d.ts +55 -0
  212. package/dist/discovery/kit-scanner.d.ts.map +1 -0
  213. package/dist/discovery/kit-scanner.js +305 -0
  214. package/dist/discovery/kit-scanner.js.map +1 -0
  215. package/dist/discovery/local-fetcher.d.ts +38 -0
  216. package/dist/discovery/local-fetcher.d.ts.map +1 -0
  217. package/dist/discovery/local-fetcher.js +100 -0
  218. package/dist/discovery/local-fetcher.js.map +1 -0
  219. package/dist/discovery/source-parser.d.ts +33 -0
  220. package/dist/discovery/source-parser.d.ts.map +1 -0
  221. package/dist/discovery/source-parser.js +136 -0
  222. package/dist/discovery/source-parser.js.map +1 -0
  223. package/dist/discovery/types.d.ts +145 -0
  224. package/dist/discovery/types.d.ts.map +1 -0
  225. package/dist/discovery/types.js +18 -0
  226. package/dist/discovery/types.js.map +1 -0
  227. package/dist/index.d.ts +13 -0
  228. package/dist/index.d.ts.map +1 -0
  229. package/dist/index.js +19 -0
  230. package/dist/index.js.map +1 -0
  231. package/dist/manifest/index.d.ts +79 -0
  232. package/dist/manifest/index.d.ts.map +1 -0
  233. package/dist/manifest/index.js +200 -0
  234. package/dist/manifest/index.js.map +1 -0
  235. package/dist/manifest/read.d.ts +32 -0
  236. package/dist/manifest/read.d.ts.map +1 -0
  237. package/dist/manifest/read.js +88 -0
  238. package/dist/manifest/read.js.map +1 -0
  239. package/dist/manifest/types.d.ts +119 -0
  240. package/dist/manifest/types.d.ts.map +1 -0
  241. package/dist/manifest/types.js +44 -0
  242. package/dist/manifest/types.js.map +1 -0
  243. package/dist/manifest/upgrade-check.d.ts +72 -0
  244. package/dist/manifest/upgrade-check.d.ts.map +1 -0
  245. package/dist/manifest/upgrade-check.js +215 -0
  246. package/dist/manifest/upgrade-check.js.map +1 -0
  247. package/dist/manifest/utils.d.ts +35 -0
  248. package/dist/manifest/utils.d.ts.map +1 -0
  249. package/dist/manifest/utils.js +57 -0
  250. package/dist/manifest/utils.js.map +1 -0
  251. package/dist/manifest/write.d.ts +44 -0
  252. package/dist/manifest/write.d.ts.map +1 -0
  253. package/dist/manifest/write.js +77 -0
  254. package/dist/manifest/write.js.map +1 -0
  255. package/dist/resolution/env-resolver.d.ts +81 -0
  256. package/dist/resolution/env-resolver.d.ts.map +1 -0
  257. package/dist/resolution/env-resolver.js +233 -0
  258. package/dist/resolution/env-resolver.js.map +1 -0
  259. package/dist/resolution/index.d.ts +55 -0
  260. package/dist/resolution/index.d.ts.map +1 -0
  261. package/dist/resolution/index.js +412 -0
  262. package/dist/resolution/index.js.map +1 -0
  263. package/dist/resolution/multi-kit-resolver.d.ts +43 -0
  264. package/dist/resolution/multi-kit-resolver.d.ts.map +1 -0
  265. package/dist/resolution/multi-kit-resolver.js +258 -0
  266. package/dist/resolution/multi-kit-resolver.js.map +1 -0
  267. package/dist/resolution/primitive-paths.d.ts +17 -0
  268. package/dist/resolution/primitive-paths.d.ts.map +1 -0
  269. package/dist/resolution/primitive-paths.js +59 -0
  270. package/dist/resolution/primitive-paths.js.map +1 -0
  271. package/dist/resolution/primitives-registry.d.ts +137 -0
  272. package/dist/resolution/primitives-registry.d.ts.map +1 -0
  273. package/dist/resolution/primitives-registry.js +295 -0
  274. package/dist/resolution/primitives-registry.js.map +1 -0
  275. package/dist/resolution/reference-parser.d.ts +62 -0
  276. package/dist/resolution/reference-parser.d.ts.map +1 -0
  277. package/dist/resolution/reference-parser.js +182 -0
  278. package/dist/resolution/reference-parser.js.map +1 -0
  279. package/dist/resolution/types.d.ts +77 -0
  280. package/dist/resolution/types.d.ts.map +1 -0
  281. package/dist/resolution/types.js +13 -0
  282. package/dist/resolution/types.js.map +1 -0
  283. package/dist/resolution/version-resolver.d.ts +76 -0
  284. package/dist/resolution/version-resolver.d.ts.map +1 -0
  285. package/dist/resolution/version-resolver.js +269 -0
  286. package/dist/resolution/version-resolver.js.map +1 -0
  287. package/dist/tui/compatibility.d.ts +80 -0
  288. package/dist/tui/compatibility.d.ts.map +1 -0
  289. package/dist/tui/compatibility.js +355 -0
  290. package/dist/tui/compatibility.js.map +1 -0
  291. package/dist/tui/env-prompt.d.ts +129 -0
  292. package/dist/tui/env-prompt.d.ts.map +1 -0
  293. package/dist/tui/env-prompt.js +488 -0
  294. package/dist/tui/env-prompt.js.map +1 -0
  295. package/dist/tui/harness-select.d.ts +54 -0
  296. package/dist/tui/harness-select.d.ts.map +1 -0
  297. package/dist/tui/harness-select.js +171 -0
  298. package/dist/tui/harness-select.js.map +1 -0
  299. package/dist/tui/index.d.ts +112 -0
  300. package/dist/tui/index.d.ts.map +1 -0
  301. package/dist/tui/index.js +213 -0
  302. package/dist/tui/index.js.map +1 -0
  303. package/dist/tui/kit-select.d.ts +72 -0
  304. package/dist/tui/kit-select.d.ts.map +1 -0
  305. package/dist/tui/kit-select.js +209 -0
  306. package/dist/tui/kit-select.js.map +1 -0
  307. package/dist/tui/progress.d.ts +75 -0
  308. package/dist/tui/progress.d.ts.map +1 -0
  309. package/dist/tui/progress.js +267 -0
  310. package/dist/tui/progress.js.map +1 -0
  311. package/dist/tui/resolution.d.ts +62 -0
  312. package/dist/tui/resolution.d.ts.map +1 -0
  313. package/dist/tui/resolution.js +261 -0
  314. package/dist/tui/resolution.js.map +1 -0
  315. package/dist/tui/scope-compatibility.d.ts +139 -0
  316. package/dist/tui/scope-compatibility.d.ts.map +1 -0
  317. package/dist/tui/scope-compatibility.js +230 -0
  318. package/dist/tui/scope-compatibility.js.map +1 -0
  319. package/dist/tui/scope-select.d.ts +67 -0
  320. package/dist/tui/scope-select.d.ts.map +1 -0
  321. package/dist/tui/scope-select.js +134 -0
  322. package/dist/tui/scope-select.js.map +1 -0
  323. package/dist/tui/spinner.d.ts +114 -0
  324. package/dist/tui/spinner.d.ts.map +1 -0
  325. package/dist/tui/spinner.js +186 -0
  326. package/dist/tui/spinner.js.map +1 -0
  327. package/dist/tui/summary.d.ts +71 -0
  328. package/dist/tui/summary.d.ts.map +1 -0
  329. package/dist/tui/summary.js +343 -0
  330. package/dist/tui/summary.js.map +1 -0
  331. package/dist/tui/types.d.ts +234 -0
  332. package/dist/tui/types.d.ts.map +1 -0
  333. package/dist/tui/types.js +7 -0
  334. package/dist/tui/types.js.map +1 -0
  335. package/dist/tui/upgrade-select.d.ts +73 -0
  336. package/dist/tui/upgrade-select.d.ts.map +1 -0
  337. package/dist/tui/upgrade-select.js +324 -0
  338. package/dist/tui/upgrade-select.js.map +1 -0
  339. package/dist/validation/index.d.ts +13 -0
  340. package/dist/validation/index.d.ts.map +1 -0
  341. package/dist/validation/index.js +13 -0
  342. package/dist/validation/index.js.map +1 -0
  343. package/dist/validation/source.d.ts +14 -0
  344. package/dist/validation/source.d.ts.map +1 -0
  345. package/dist/validation/source.js +51 -0
  346. package/dist/validation/source.js.map +1 -0
  347. package/dist/validation/utils.d.ts +29 -0
  348. package/dist/validation/utils.d.ts.map +1 -0
  349. package/dist/validation/utils.js +89 -0
  350. package/dist/validation/utils.js.map +1 -0
  351. package/dist/validation/validate-commands.d.ts +28 -0
  352. package/dist/validation/validate-commands.d.ts.map +1 -0
  353. package/dist/validation/validate-commands.js +151 -0
  354. package/dist/validation/validate-commands.js.map +1 -0
  355. package/dist/validation/validate-hooks.d.ts +13 -0
  356. package/dist/validation/validate-hooks.d.ts.map +1 -0
  357. package/dist/validation/validate-hooks.js +272 -0
  358. package/dist/validation/validate-hooks.js.map +1 -0
  359. package/dist/validation/validate-kits.d.ts +15 -0
  360. package/dist/validation/validate-kits.d.ts.map +1 -0
  361. package/dist/validation/validate-kits.js +185 -0
  362. package/dist/validation/validate-kits.js.map +1 -0
  363. package/dist/validation/validate-mcp.d.ts +12 -0
  364. package/dist/validation/validate-mcp.d.ts.map +1 -0
  365. package/dist/validation/validate-mcp.js +132 -0
  366. package/dist/validation/validate-mcp.js.map +1 -0
  367. package/dist/validation/validate-skills.d.ts +24 -0
  368. package/dist/validation/validate-skills.d.ts.map +1 -0
  369. package/dist/validation/validate-skills.js +223 -0
  370. package/dist/validation/validate-skills.js.map +1 -0
  371. package/dist/validation/validate-subagents.d.ts +27 -0
  372. package/dist/validation/validate-subagents.d.ts.map +1 -0
  373. package/dist/validation/validate-subagents.js +269 -0
  374. package/dist/validation/validate-subagents.js.map +1 -0
  375. package/package.json +91 -0
  376. package/schemas/command.schema.json +23 -0
  377. package/schemas/examples/hook-binding-valid.json +20 -0
  378. package/schemas/examples/hook-program-valid.json +25 -0
  379. package/schemas/examples/http-server-valid.json +82 -0
  380. package/schemas/examples/invalid-sensitive-header-no-envvar.json +16 -0
  381. package/schemas/examples/invalid-sensitive-header-with-value.json +17 -0
  382. package/schemas/examples/invalid-sensitive-var-with-default.json +19 -0
  383. package/schemas/examples/stdio-server-valid.json +55 -0
  384. package/schemas/hook-binding.schema.json +63 -0
  385. package/schemas/hook-program.schema.json +104 -0
  386. package/schemas/kit.schema.json +338 -0
  387. package/schemas/kits.schema.json +117 -0
  388. package/schemas/manifest.schema.json +200 -0
  389. package/schemas/mcp-server.schema.json +305 -0
  390. package/schemas/primitives.schema.json +118 -0
  391. package/schemas/skill.schema.json +96 -0
  392. package/schemas/subagent.schema.json +107 -0
@@ -0,0 +1,164 @@
1
+ /**
2
+ * File operation utilities for adapter implementations.
3
+ *
4
+ * This module provides atomic file operations with rollback support
5
+ * for installing primitives into AI agent harnesses.
6
+ */
7
+ import type { FileOperationResult, FileOperation } from "./types.js";
8
+ /**
9
+ * A completed operation that can be rolled back.
10
+ */
11
+ export interface CompletedOperation {
12
+ type: "file" | "directory" | "backup";
13
+ path: string;
14
+ previousContent?: string;
15
+ createdNew: boolean;
16
+ }
17
+ /**
18
+ * Result of an atomic file operation batch.
19
+ */
20
+ export interface AtomicOperationResult {
21
+ success: boolean;
22
+ results: FileOperationResult[];
23
+ completedOps: CompletedOperation[];
24
+ error?: string;
25
+ }
26
+ /**
27
+ * Expand ~ to the user's home directory.
28
+ *
29
+ * @param filePath - Path that may contain ~
30
+ */
31
+ export declare function expandPath(filePath: string): string;
32
+ /**
33
+ * Check if a path exists.
34
+ *
35
+ * @param filePath - Path to check (supports ~)
36
+ */
37
+ export declare function pathExists(filePath: string): boolean;
38
+ /**
39
+ * Check if a path is a directory.
40
+ *
41
+ * @param filePath - Path to check
42
+ */
43
+ export declare function isDirectory(filePath: string): Promise<boolean>;
44
+ /**
45
+ * Check if a path is a file.
46
+ *
47
+ * @param filePath - Path to check
48
+ */
49
+ export declare function isFile(filePath: string): Promise<boolean>;
50
+ /**
51
+ * Ensure a directory exists, creating it if necessary.
52
+ *
53
+ * @param dirPath - Directory path to ensure (supports ~)
54
+ * @returns true if directory was created, false if it already existed
55
+ */
56
+ export declare function ensureDirectory(dirPath: string): Promise<boolean>;
57
+ /**
58
+ * Copy a single file.
59
+ *
60
+ * @param source - Source file path
61
+ * @param destination - Destination file path (supports ~)
62
+ * @param overwrite - Whether to overwrite existing files (default: true)
63
+ */
64
+ export declare function copyFile(source: string, destination: string, overwrite?: boolean): Promise<void>;
65
+ /**
66
+ * Copy a directory recursively.
67
+ *
68
+ * Used for skills which are directories containing SKILL.md and assets.
69
+ *
70
+ * @param source - Source directory path
71
+ * @param destination - Destination directory path (supports ~)
72
+ * @param overwrite - Whether to overwrite existing files (default: true)
73
+ */
74
+ export declare function copyDirectory(source: string, destination: string, overwrite?: boolean): Promise<void>;
75
+ /**
76
+ * Write transformed content to a file.
77
+ *
78
+ * @param destination - Destination file path (supports ~)
79
+ * @param content - Content to write
80
+ * @param encoding - File encoding (default: utf-8)
81
+ */
82
+ export declare function writeTransformed(destination: string, content: string, encoding?: BufferEncoding): Promise<void>;
83
+ /**
84
+ * Read file content.
85
+ *
86
+ * @param filePath - File path to read (supports ~)
87
+ * @param encoding - File encoding (default: utf-8)
88
+ */
89
+ export declare function readFile(filePath: string, encoding?: BufferEncoding): Promise<string>;
90
+ /**
91
+ * Create a timestamped backup of a file.
92
+ *
93
+ * @param filePath - File to backup (supports ~)
94
+ * @returns The backup file path, or undefined if file didn't exist
95
+ */
96
+ export declare function backupFile(filePath: string): Promise<string | undefined>;
97
+ /**
98
+ * Create a simple backup (with .backup extension).
99
+ *
100
+ * @param filePath - File to backup (supports ~)
101
+ * @returns The backup file path, or undefined if file didn't exist
102
+ */
103
+ export declare function createSimpleBackup(filePath: string): Promise<string | undefined>;
104
+ /**
105
+ * Restore a file from backup.
106
+ *
107
+ * @param backupPath - Path to backup file
108
+ * @param originalPath - Original file path to restore to
109
+ */
110
+ export declare function restoreFromBackup(backupPath: string, originalPath: string): Promise<void>;
111
+ /**
112
+ * Remove a file or directory.
113
+ *
114
+ * @param filePath - Path to remove (supports ~)
115
+ */
116
+ export declare function remove(filePath: string): Promise<void>;
117
+ /**
118
+ * Remove a directory if it's empty.
119
+ *
120
+ * @param dirPath - Directory path (supports ~)
121
+ * @returns true if directory was removed, false if not empty or didn't exist
122
+ */
123
+ export declare function removeIfEmpty(dirPath: string): Promise<boolean>;
124
+ /**
125
+ * Rollback a list of completed operations.
126
+ *
127
+ * Operations are rolled back in reverse order.
128
+ *
129
+ * @param completedOps - Operations to roll back
130
+ */
131
+ export declare function rollbackOperations(completedOps: CompletedOperation[]): Promise<void>;
132
+ /**
133
+ * Execute a list of file operations atomically.
134
+ *
135
+ * All operations succeed or all are rolled back.
136
+ *
137
+ * @param operations - Operations to execute
138
+ * @param options - Execution options
139
+ */
140
+ export declare function executeFileOperations(operations: FileOperation[], options?: {
141
+ createDirs?: boolean;
142
+ backup?: boolean;
143
+ }): Promise<AtomicOperationResult>;
144
+ /**
145
+ * Deep merge two objects.
146
+ *
147
+ * @param target - Target object
148
+ * @param source - Source object to merge in
149
+ */
150
+ export declare function deepMerge<T extends Record<string, unknown>>(target: T, source: Record<string, unknown>): T;
151
+ /**
152
+ * Get the size of a file or directory in bytes.
153
+ *
154
+ * @param filePath - Path to measure (supports ~)
155
+ */
156
+ export declare function getSize(filePath: string): Promise<number>;
157
+ /**
158
+ * List all files in a directory recursively.
159
+ *
160
+ * @param dirPath - Directory to list (supports ~)
161
+ * @param pattern - Optional glob pattern to filter files
162
+ */
163
+ export declare function listFiles(dirPath: string): Promise<string[]>;
164
+ //# sourceMappingURL=file-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-operations.d.ts","sourceRoot":"","sources":["../../src/adapters/file-operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYnD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOpE;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/D;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUvE;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,OAAc,GACxB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,OAAc,GACxB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,cAAwB,GACjC,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,cAAwB,GACjC,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAY9E;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsB7B;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5D;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBrE;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,kBAAkB,EAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,aAAa,EAAE,EAC3B,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CACb,GACL,OAAO,CAAC,qBAAqB,CAAC,CA6KhC;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,CAAC,CA2BH;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB/D;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBlE"}
@@ -0,0 +1,526 @@
1
+ /**
2
+ * File operation utilities for adapter implementations.
3
+ *
4
+ * This module provides atomic file operations with rollback support
5
+ * for installing primitives into AI agent harnesses.
6
+ */
7
+ import * as fs from "node:fs/promises";
8
+ import * as path from "node:path";
9
+ import { existsSync } from "node:fs";
10
+ import * as os from "node:os";
11
+ /**
12
+ * Expand ~ to the user's home directory.
13
+ *
14
+ * @param filePath - Path that may contain ~
15
+ */
16
+ export function expandPath(filePath) {
17
+ if (!filePath)
18
+ return filePath;
19
+ if (filePath === "~") {
20
+ return os.homedir();
21
+ }
22
+ if (filePath.startsWith("~/")) {
23
+ return path.join(os.homedir(), filePath.slice(2));
24
+ }
25
+ return filePath;
26
+ }
27
+ /**
28
+ * Check if a path exists.
29
+ *
30
+ * @param filePath - Path to check (supports ~)
31
+ */
32
+ export function pathExists(filePath) {
33
+ return existsSync(expandPath(filePath));
34
+ }
35
+ /**
36
+ * Check if a path is a directory.
37
+ *
38
+ * @param filePath - Path to check
39
+ */
40
+ export async function isDirectory(filePath) {
41
+ try {
42
+ const stats = await fs.stat(expandPath(filePath));
43
+ return stats.isDirectory();
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ /**
50
+ * Check if a path is a file.
51
+ *
52
+ * @param filePath - Path to check
53
+ */
54
+ export async function isFile(filePath) {
55
+ try {
56
+ const stats = await fs.stat(expandPath(filePath));
57
+ return stats.isFile();
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ /**
64
+ * Ensure a directory exists, creating it if necessary.
65
+ *
66
+ * @param dirPath - Directory path to ensure (supports ~)
67
+ * @returns true if directory was created, false if it already existed
68
+ */
69
+ export async function ensureDirectory(dirPath) {
70
+ const expanded = expandPath(dirPath);
71
+ const existed = existsSync(expanded);
72
+ if (!existed) {
73
+ await fs.mkdir(expanded, { recursive: true });
74
+ return true;
75
+ }
76
+ return false;
77
+ }
78
+ /**
79
+ * Copy a single file.
80
+ *
81
+ * @param source - Source file path
82
+ * @param destination - Destination file path (supports ~)
83
+ * @param overwrite - Whether to overwrite existing files (default: true)
84
+ */
85
+ export async function copyFile(source, destination, overwrite = true) {
86
+ const expandedDest = expandPath(destination);
87
+ // Ensure destination directory exists
88
+ await ensureDirectory(path.dirname(expandedDest));
89
+ // Check if destination exists and overwrite is false
90
+ if (!overwrite && existsSync(expandedDest)) {
91
+ throw new Error(`destination already exists; path=${expandedDest}`);
92
+ }
93
+ await fs.copyFile(source, expandedDest);
94
+ }
95
+ /**
96
+ * Copy a directory recursively.
97
+ *
98
+ * Used for skills which are directories containing SKILL.md and assets.
99
+ *
100
+ * @param source - Source directory path
101
+ * @param destination - Destination directory path (supports ~)
102
+ * @param overwrite - Whether to overwrite existing files (default: true)
103
+ */
104
+ export async function copyDirectory(source, destination, overwrite = true) {
105
+ const expandedDest = expandPath(destination);
106
+ // Ensure destination directory exists
107
+ await ensureDirectory(expandedDest);
108
+ // Get all entries in source directory
109
+ const entries = await fs.readdir(source, { withFileTypes: true });
110
+ for (const entry of entries) {
111
+ const srcPath = path.join(source, entry.name);
112
+ const destPath = path.join(expandedDest, entry.name);
113
+ if (entry.isDirectory()) {
114
+ await copyDirectory(srcPath, destPath, overwrite);
115
+ }
116
+ else {
117
+ if (!overwrite && existsSync(destPath)) {
118
+ continue; // Skip existing files if not overwriting
119
+ }
120
+ await fs.copyFile(srcPath, destPath);
121
+ }
122
+ }
123
+ }
124
+ /**
125
+ * Write transformed content to a file.
126
+ *
127
+ * @param destination - Destination file path (supports ~)
128
+ * @param content - Content to write
129
+ * @param encoding - File encoding (default: utf-8)
130
+ */
131
+ export async function writeTransformed(destination, content, encoding = "utf-8") {
132
+ const expandedDest = expandPath(destination);
133
+ // Ensure destination directory exists
134
+ await ensureDirectory(path.dirname(expandedDest));
135
+ await fs.writeFile(expandedDest, content, { encoding });
136
+ }
137
+ /**
138
+ * Read file content.
139
+ *
140
+ * @param filePath - File path to read (supports ~)
141
+ * @param encoding - File encoding (default: utf-8)
142
+ */
143
+ export async function readFile(filePath, encoding = "utf-8") {
144
+ const expanded = expandPath(filePath);
145
+ return fs.readFile(expanded, { encoding });
146
+ }
147
+ /**
148
+ * Create a timestamped backup of a file.
149
+ *
150
+ * @param filePath - File to backup (supports ~)
151
+ * @returns The backup file path, or undefined if file didn't exist
152
+ */
153
+ export async function backupFile(filePath) {
154
+ const expanded = expandPath(filePath);
155
+ if (!existsSync(expanded)) {
156
+ return undefined;
157
+ }
158
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
159
+ const backupPath = `${expanded}.backup.${timestamp}`;
160
+ await fs.copyFile(expanded, backupPath);
161
+ return backupPath;
162
+ }
163
+ /**
164
+ * Create a simple backup (with .backup extension).
165
+ *
166
+ * @param filePath - File to backup (supports ~)
167
+ * @returns The backup file path, or undefined if file didn't exist
168
+ */
169
+ export async function createSimpleBackup(filePath) {
170
+ const expanded = expandPath(filePath);
171
+ if (!existsSync(expanded)) {
172
+ return undefined;
173
+ }
174
+ const backupPath = `${expanded}.backup`;
175
+ // If backup already exists, remove it
176
+ if (existsSync(backupPath)) {
177
+ await fs.rm(backupPath, { recursive: true, force: true });
178
+ }
179
+ const stats = await fs.stat(expanded);
180
+ if (stats.isDirectory()) {
181
+ await copyDirectory(expanded, backupPath);
182
+ }
183
+ else {
184
+ await fs.copyFile(expanded, backupPath);
185
+ }
186
+ return backupPath;
187
+ }
188
+ /**
189
+ * Restore a file from backup.
190
+ *
191
+ * @param backupPath - Path to backup file
192
+ * @param originalPath - Original file path to restore to
193
+ */
194
+ export async function restoreFromBackup(backupPath, originalPath) {
195
+ const expandedBackup = expandPath(backupPath);
196
+ const expandedOriginal = expandPath(originalPath);
197
+ if (!existsSync(expandedBackup)) {
198
+ throw new Error(`backup not found; path=${expandedBackup}`);
199
+ }
200
+ const stats = await fs.stat(expandedBackup);
201
+ if (stats.isDirectory()) {
202
+ // Remove original directory if exists
203
+ if (existsSync(expandedOriginal)) {
204
+ await fs.rm(expandedOriginal, { recursive: true, force: true });
205
+ }
206
+ await copyDirectory(expandedBackup, expandedOriginal);
207
+ }
208
+ else {
209
+ await fs.copyFile(expandedBackup, expandedOriginal);
210
+ }
211
+ }
212
+ /**
213
+ * Remove a file or directory.
214
+ *
215
+ * @param filePath - Path to remove (supports ~)
216
+ */
217
+ export async function remove(filePath) {
218
+ const expanded = expandPath(filePath);
219
+ if (!existsSync(expanded)) {
220
+ return; // Already doesn't exist
221
+ }
222
+ await fs.rm(expanded, { recursive: true, force: true });
223
+ }
224
+ /**
225
+ * Remove a directory if it's empty.
226
+ *
227
+ * @param dirPath - Directory path (supports ~)
228
+ * @returns true if directory was removed, false if not empty or didn't exist
229
+ */
230
+ export async function removeIfEmpty(dirPath) {
231
+ const expanded = expandPath(dirPath);
232
+ if (!existsSync(expanded)) {
233
+ return false;
234
+ }
235
+ try {
236
+ const entries = await fs.readdir(expanded);
237
+ if (entries.length === 0) {
238
+ await fs.rmdir(expanded);
239
+ return true;
240
+ }
241
+ }
242
+ catch {
243
+ // Ignore errors (e.g., not a directory)
244
+ }
245
+ return false;
246
+ }
247
+ /**
248
+ * Rollback a list of completed operations.
249
+ *
250
+ * Operations are rolled back in reverse order.
251
+ *
252
+ * @param completedOps - Operations to roll back
253
+ */
254
+ export async function rollbackOperations(completedOps) {
255
+ // Rollback in reverse order
256
+ for (const op of completedOps.reverse()) {
257
+ try {
258
+ switch (op.type) {
259
+ case "file":
260
+ if (op.createdNew) {
261
+ // File was newly created - remove it
262
+ await remove(op.path);
263
+ }
264
+ else if (op.previousContent !== undefined) {
265
+ // File was modified - restore previous content
266
+ await writeTransformed(op.path, op.previousContent);
267
+ }
268
+ break;
269
+ case "directory":
270
+ if (op.createdNew) {
271
+ // Directory was newly created - remove if empty
272
+ await removeIfEmpty(op.path);
273
+ }
274
+ break;
275
+ case "backup":
276
+ {
277
+ // Restore from backup
278
+ const originalPath = op.path.replace(/\.backup(\.[^.]+)?$/, "");
279
+ await restoreFromBackup(op.path, originalPath);
280
+ }
281
+ break;
282
+ }
283
+ }
284
+ catch (error) {
285
+ // Log but continue rollback
286
+ console.error(`rollback failed for ${op.path}; error=${error}`);
287
+ }
288
+ }
289
+ }
290
+ /**
291
+ * Execute a list of file operations atomically.
292
+ *
293
+ * All operations succeed or all are rolled back.
294
+ *
295
+ * @param operations - Operations to execute
296
+ * @param options - Execution options
297
+ */
298
+ export async function executeFileOperations(operations, options = {}) {
299
+ const { createDirs = true, backup = true } = options;
300
+ const results = [];
301
+ const completedOps = [];
302
+ try {
303
+ for (const op of operations) {
304
+ const expandedDest = expandPath(op.destination);
305
+ // Create parent directories if needed
306
+ if (createDirs && op.type !== "mkdir") {
307
+ const dirPath = path.dirname(expandedDest);
308
+ const created = await ensureDirectory(dirPath);
309
+ if (created) {
310
+ completedOps.push({
311
+ type: "directory",
312
+ path: dirPath,
313
+ createdNew: true,
314
+ });
315
+ }
316
+ }
317
+ switch (op.type) {
318
+ case "copy": {
319
+ if (!op.source) {
320
+ throw new Error("copy operation requires source");
321
+ }
322
+ // Backup existing file if needed
323
+ const fileExisted = existsSync(expandedDest);
324
+ let previousContent;
325
+ if (backup && fileExisted) {
326
+ previousContent = await readFile(expandedDest);
327
+ }
328
+ await copyFile(op.source, expandedDest);
329
+ const completedOp = {
330
+ type: "file",
331
+ path: expandedDest,
332
+ createdNew: !fileExisted,
333
+ };
334
+ if (previousContent !== undefined) {
335
+ completedOp.previousContent = previousContent;
336
+ }
337
+ completedOps.push(completedOp);
338
+ results.push({
339
+ operation: "copy",
340
+ source: op.source,
341
+ destination: expandedDest,
342
+ success: true,
343
+ });
344
+ break;
345
+ }
346
+ case "transform": {
347
+ if (!op.source || !op.transform) {
348
+ throw new Error("transform operation requires source and transform function");
349
+ }
350
+ // Backup existing file if needed
351
+ const fileExisted = existsSync(expandedDest);
352
+ let previousContent;
353
+ if (backup && fileExisted) {
354
+ previousContent = await readFile(expandedDest);
355
+ }
356
+ // Read source, transform, and write
357
+ const sourceContent = await readFile(op.source);
358
+ const transformedContent = op.transform(sourceContent);
359
+ await writeTransformed(expandedDest, transformedContent);
360
+ const completedOp = {
361
+ type: "file",
362
+ path: expandedDest,
363
+ createdNew: !fileExisted,
364
+ };
365
+ if (previousContent !== undefined) {
366
+ completedOp.previousContent = previousContent;
367
+ }
368
+ completedOps.push(completedOp);
369
+ results.push({
370
+ operation: "transform",
371
+ source: op.source,
372
+ destination: expandedDest,
373
+ success: true,
374
+ });
375
+ break;
376
+ }
377
+ case "mkdir": {
378
+ const created = await ensureDirectory(expandedDest);
379
+ completedOps.push({
380
+ type: "directory",
381
+ path: expandedDest,
382
+ createdNew: created,
383
+ });
384
+ results.push({
385
+ operation: "mkdir",
386
+ destination: expandedDest,
387
+ success: true,
388
+ });
389
+ break;
390
+ }
391
+ case "merge": {
392
+ // Merge operations are typically handled by config merging
393
+ // For now, treat as a copy with merge strategy
394
+ if (!op.source) {
395
+ throw new Error("merge operation requires source");
396
+ }
397
+ const fileExisted = existsSync(expandedDest);
398
+ let previousContent;
399
+ if (fileExisted) {
400
+ previousContent = await readFile(expandedDest);
401
+ if (op.mergeStrategy === "deep-merge") {
402
+ // Deep merge JSON/YAML files
403
+ const existingContent = JSON.parse(previousContent);
404
+ const newContent = JSON.parse(await readFile(op.source));
405
+ const merged = deepMerge(existingContent, newContent);
406
+ await writeTransformed(expandedDest, JSON.stringify(merged, null, 2));
407
+ }
408
+ else {
409
+ // Replace strategy - just copy
410
+ await copyFile(op.source, expandedDest);
411
+ }
412
+ }
413
+ else {
414
+ await copyFile(op.source, expandedDest);
415
+ }
416
+ const completedOp = {
417
+ type: "file",
418
+ path: expandedDest,
419
+ createdNew: !fileExisted,
420
+ };
421
+ if (previousContent !== undefined) {
422
+ completedOp.previousContent = previousContent;
423
+ }
424
+ completedOps.push(completedOp);
425
+ results.push({
426
+ operation: "merge",
427
+ source: op.source,
428
+ destination: expandedDest,
429
+ success: true,
430
+ });
431
+ break;
432
+ }
433
+ }
434
+ }
435
+ return {
436
+ success: true,
437
+ results,
438
+ completedOps,
439
+ };
440
+ }
441
+ catch (error) {
442
+ // Rollback all completed operations
443
+ await rollbackOperations(completedOps);
444
+ return {
445
+ success: false,
446
+ results,
447
+ completedOps: [],
448
+ error: error instanceof Error ? error.message : String(error),
449
+ };
450
+ }
451
+ }
452
+ /**
453
+ * Deep merge two objects.
454
+ *
455
+ * @param target - Target object
456
+ * @param source - Source object to merge in
457
+ */
458
+ export function deepMerge(target, source) {
459
+ const result = { ...target };
460
+ for (const key of Object.keys(source)) {
461
+ const sourceValue = source[key];
462
+ const targetValue = result[key];
463
+ if (sourceValue &&
464
+ typeof sourceValue === "object" &&
465
+ !Array.isArray(sourceValue) &&
466
+ targetValue &&
467
+ typeof targetValue === "object" &&
468
+ !Array.isArray(targetValue)) {
469
+ // Recursively merge objects
470
+ result[key] = deepMerge(targetValue, sourceValue);
471
+ }
472
+ else {
473
+ // Override with source value
474
+ result[key] = sourceValue;
475
+ }
476
+ }
477
+ return result;
478
+ }
479
+ /**
480
+ * Get the size of a file or directory in bytes.
481
+ *
482
+ * @param filePath - Path to measure (supports ~)
483
+ */
484
+ export async function getSize(filePath) {
485
+ const expanded = expandPath(filePath);
486
+ const stats = await fs.stat(expanded);
487
+ if (stats.isFile()) {
488
+ return stats.size;
489
+ }
490
+ if (stats.isDirectory()) {
491
+ let totalSize = 0;
492
+ const entries = await fs.readdir(expanded, { withFileTypes: true });
493
+ for (const entry of entries) {
494
+ const entryPath = path.join(expanded, entry.name);
495
+ totalSize += await getSize(entryPath);
496
+ }
497
+ return totalSize;
498
+ }
499
+ return 0;
500
+ }
501
+ /**
502
+ * List all files in a directory recursively.
503
+ *
504
+ * @param dirPath - Directory to list (supports ~)
505
+ * @param pattern - Optional glob pattern to filter files
506
+ */
507
+ export async function listFiles(dirPath) {
508
+ const expanded = expandPath(dirPath);
509
+ const files = [];
510
+ if (!existsSync(expanded)) {
511
+ return files;
512
+ }
513
+ const entries = await fs.readdir(expanded, { withFileTypes: true });
514
+ for (const entry of entries) {
515
+ const entryPath = path.join(expanded, entry.name);
516
+ if (entry.isDirectory()) {
517
+ const subFiles = await listFiles(entryPath);
518
+ files.push(...subFiles);
519
+ }
520
+ else {
521
+ files.push(entryPath);
522
+ }
523
+ }
524
+ return files;
525
+ }
526
+ //# sourceMappingURL=file-operations.js.map