@untangle-code/cli 0.0.0-stage → 0.1.1

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 (571) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +90 -0
  3. package/README.md +451 -2
  4. package/THIRD_PARTY_LICENSES.md +152 -0
  5. package/dist/cli/args.d.ts +48 -0
  6. package/dist/cli/args.d.ts.map +1 -0
  7. package/dist/cli/args.js +167 -0
  8. package/dist/cli/args.js.map +1 -0
  9. package/dist/cli/command.d.ts +69 -0
  10. package/dist/cli/command.d.ts.map +1 -0
  11. package/dist/cli/command.js +82 -0
  12. package/dist/cli/command.js.map +1 -0
  13. package/dist/cli/deadline.d.ts +33 -0
  14. package/dist/cli/deadline.d.ts.map +1 -0
  15. package/dist/cli/deadline.js +49 -0
  16. package/dist/cli/deadline.js.map +1 -0
  17. package/dist/cli/embedder-deadline.d.ts +72 -0
  18. package/dist/cli/embedder-deadline.d.ts.map +1 -0
  19. package/dist/cli/embedder-deadline.js +117 -0
  20. package/dist/cli/embedder-deadline.js.map +1 -0
  21. package/dist/cli/exit.d.ts +71 -0
  22. package/dist/cli/exit.d.ts.map +1 -0
  23. package/dist/cli/exit.js +81 -0
  24. package/dist/cli/exit.js.map +1 -0
  25. package/dist/cli/graphs.d.ts +65 -0
  26. package/dist/cli/graphs.d.ts.map +1 -0
  27. package/dist/cli/graphs.js +108 -0
  28. package/dist/cli/graphs.js.map +1 -0
  29. package/dist/cli/index-freshness.d.ts +13 -0
  30. package/dist/cli/index-freshness.d.ts.map +1 -0
  31. package/dist/cli/index-freshness.js +226 -0
  32. package/dist/cli/index-freshness.js.map +1 -0
  33. package/dist/cli/index-refresh.d.ts +10 -0
  34. package/dist/cli/index-refresh.d.ts.map +1 -0
  35. package/dist/cli/index-refresh.js +76 -0
  36. package/dist/cli/index-refresh.js.map +1 -0
  37. package/dist/cli/index-state.d.ts +184 -0
  38. package/dist/cli/index-state.d.ts.map +1 -0
  39. package/dist/cli/index-state.js +852 -0
  40. package/dist/cli/index-state.js.map +1 -0
  41. package/dist/cli/io.d.ts +29 -0
  42. package/dist/cli/io.d.ts.map +1 -0
  43. package/dist/cli/io.js +42 -0
  44. package/dist/cli/io.js.map +1 -0
  45. package/dist/cli/language-support.d.ts +77 -0
  46. package/dist/cli/language-support.d.ts.map +1 -0
  47. package/dist/cli/language-support.js +152 -0
  48. package/dist/cli/language-support.js.map +1 -0
  49. package/dist/cli/renewing-lease.d.ts +26 -0
  50. package/dist/cli/renewing-lease.d.ts.map +1 -0
  51. package/dist/cli/renewing-lease.js +102 -0
  52. package/dist/cli/renewing-lease.js.map +1 -0
  53. package/dist/cli/search-graph-enrichment.d.ts +16 -0
  54. package/dist/cli/search-graph-enrichment.d.ts.map +1 -0
  55. package/dist/cli/search-graph-enrichment.js +428 -0
  56. package/dist/cli/search-graph-enrichment.js.map +1 -0
  57. package/dist/cli/system.d.ts +34 -0
  58. package/dist/cli/system.d.ts.map +1 -0
  59. package/dist/cli/system.js +89 -0
  60. package/dist/cli/system.js.map +1 -0
  61. package/dist/cli/vector-store-policy.d.ts +116 -0
  62. package/dist/cli/vector-store-policy.d.ts.map +1 -0
  63. package/dist/cli/vector-store-policy.js +160 -0
  64. package/dist/cli/vector-store-policy.js.map +1 -0
  65. package/dist/cli/version.d.ts +3 -0
  66. package/dist/cli/version.d.ts.map +1 -0
  67. package/dist/cli/version.js +3 -0
  68. package/dist/cli/version.js.map +1 -0
  69. package/dist/cli/workspace.d.ts +105 -0
  70. package/dist/cli/workspace.d.ts.map +1 -0
  71. package/dist/cli/workspace.js +215 -0
  72. package/dist/cli/workspace.js.map +1 -0
  73. package/dist/commands/complexity.d.ts +72 -0
  74. package/dist/commands/complexity.d.ts.map +1 -0
  75. package/dist/commands/complexity.js +580 -0
  76. package/dist/commands/complexity.js.map +1 -0
  77. package/dist/commands/doctor.d.ts +66 -0
  78. package/dist/commands/doctor.d.ts.map +1 -0
  79. package/dist/commands/doctor.js +764 -0
  80. package/dist/commands/doctor.js.map +1 -0
  81. package/dist/commands/doctor.languages.d.ts +37 -0
  82. package/dist/commands/doctor.languages.d.ts.map +1 -0
  83. package/dist/commands/doctor.languages.js +143 -0
  84. package/dist/commands/doctor.languages.js.map +1 -0
  85. package/dist/commands/doctor.storage.d.ts +17 -0
  86. package/dist/commands/doctor.storage.d.ts.map +1 -0
  87. package/dist/commands/doctor.storage.js +91 -0
  88. package/dist/commands/doctor.storage.js.map +1 -0
  89. package/dist/commands/extensions/add.d.ts +10 -0
  90. package/dist/commands/extensions/add.d.ts.map +1 -0
  91. package/dist/commands/extensions/add.js +213 -0
  92. package/dist/commands/extensions/add.js.map +1 -0
  93. package/dist/commands/extensions/configure.d.ts +5 -0
  94. package/dist/commands/extensions/configure.d.ts.map +1 -0
  95. package/dist/commands/extensions/configure.js +58 -0
  96. package/dist/commands/extensions/configure.js.map +1 -0
  97. package/dist/commands/extensions/container.d.ts +15 -0
  98. package/dist/commands/extensions/container.d.ts.map +1 -0
  99. package/dist/commands/extensions/container.js +135 -0
  100. package/dist/commands/extensions/container.js.map +1 -0
  101. package/dist/commands/extensions/context.d.ts +37 -0
  102. package/dist/commands/extensions/context.d.ts.map +1 -0
  103. package/dist/commands/extensions/context.js +72 -0
  104. package/dist/commands/extensions/context.js.map +1 -0
  105. package/dist/commands/extensions/enable.d.ts +6 -0
  106. package/dist/commands/extensions/enable.d.ts.map +1 -0
  107. package/dist/commands/extensions/enable.js +180 -0
  108. package/dist/commands/extensions/enable.js.map +1 -0
  109. package/dist/commands/extensions/environment.d.ts +74 -0
  110. package/dist/commands/extensions/environment.d.ts.map +1 -0
  111. package/dist/commands/extensions/environment.js +168 -0
  112. package/dist/commands/extensions/environment.js.map +1 -0
  113. package/dist/commands/extensions/feature-scan.d.ts +48 -0
  114. package/dist/commands/extensions/feature-scan.d.ts.map +1 -0
  115. package/dist/commands/extensions/feature-scan.js +156 -0
  116. package/dist/commands/extensions/feature-scan.js.map +1 -0
  117. package/dist/commands/extensions/invoke.d.ts +60 -0
  118. package/dist/commands/extensions/invoke.d.ts.map +1 -0
  119. package/dist/commands/extensions/invoke.js +275 -0
  120. package/dist/commands/extensions/invoke.js.map +1 -0
  121. package/dist/commands/extensions/list.d.ts +5 -0
  122. package/dist/commands/extensions/list.d.ts.map +1 -0
  123. package/dist/commands/extensions/list.js +125 -0
  124. package/dist/commands/extensions/list.js.map +1 -0
  125. package/dist/commands/extensions/logs.d.ts +5 -0
  126. package/dist/commands/extensions/logs.d.ts.map +1 -0
  127. package/dist/commands/extensions/logs.js +74 -0
  128. package/dist/commands/extensions/logs.js.map +1 -0
  129. package/dist/commands/extensions/provision.d.ts +36 -0
  130. package/dist/commands/extensions/provision.d.ts.map +1 -0
  131. package/dist/commands/extensions/provision.js +137 -0
  132. package/dist/commands/extensions/provision.js.map +1 -0
  133. package/dist/commands/extensions/remove.d.ts +5 -0
  134. package/dist/commands/extensions/remove.d.ts.map +1 -0
  135. package/dist/commands/extensions/remove.js +77 -0
  136. package/dist/commands/extensions/remove.js.map +1 -0
  137. package/dist/commands/extensions/render.d.ts +16 -0
  138. package/dist/commands/extensions/render.d.ts.map +1 -0
  139. package/dist/commands/extensions/render.js +25 -0
  140. package/dist/commands/extensions/render.js.map +1 -0
  141. package/dist/commands/extensions/run.d.ts +30 -0
  142. package/dist/commands/extensions/run.d.ts.map +1 -0
  143. package/dist/commands/extensions/run.js +292 -0
  144. package/dist/commands/extensions/run.js.map +1 -0
  145. package/dist/commands/extensions/secret-store.d.ts +15 -0
  146. package/dist/commands/extensions/secret-store.d.ts.map +1 -0
  147. package/dist/commands/extensions/secret-store.js +164 -0
  148. package/dist/commands/extensions/secret-store.js.map +1 -0
  149. package/dist/commands/extensions/setup.d.ts +17 -0
  150. package/dist/commands/extensions/setup.d.ts.map +1 -0
  151. package/dist/commands/extensions/setup.js +94 -0
  152. package/dist/commands/extensions/setup.js.map +1 -0
  153. package/dist/commands/extensions/source.d.ts +47 -0
  154. package/dist/commands/extensions/source.d.ts.map +1 -0
  155. package/dist/commands/extensions/source.js +142 -0
  156. package/dist/commands/extensions/source.js.map +1 -0
  157. package/dist/commands/extensions/state.d.ts +62 -0
  158. package/dist/commands/extensions/state.d.ts.map +1 -0
  159. package/dist/commands/extensions/state.js +177 -0
  160. package/dist/commands/extensions/state.js.map +1 -0
  161. package/dist/commands/extensions/status.d.ts +9 -0
  162. package/dist/commands/extensions/status.d.ts.map +1 -0
  163. package/dist/commands/extensions/status.js +239 -0
  164. package/dist/commands/extensions/status.js.map +1 -0
  165. package/dist/commands/extensions.d.ts +3 -0
  166. package/dist/commands/extensions.d.ts.map +1 -0
  167. package/dist/commands/extensions.js +223 -0
  168. package/dist/commands/extensions.js.map +1 -0
  169. package/dist/commands/flow/index.d.ts +3 -0
  170. package/dist/commands/flow/index.d.ts.map +1 -0
  171. package/dist/commands/flow/index.js +295 -0
  172. package/dist/commands/flow/index.js.map +1 -0
  173. package/dist/commands/flow/limits.d.ts +12 -0
  174. package/dist/commands/flow/limits.d.ts.map +1 -0
  175. package/dist/commands/flow/limits.js +13 -0
  176. package/dist/commands/flow/limits.js.map +1 -0
  177. package/dist/commands/flow/output.d.ts +8 -0
  178. package/dist/commands/flow/output.d.ts.map +1 -0
  179. package/dist/commands/flow/output.js +11 -0
  180. package/dist/commands/flow/output.js.map +1 -0
  181. package/dist/commands/flow/render.d.ts +51 -0
  182. package/dist/commands/flow/render.d.ts.map +1 -0
  183. package/dist/commands/flow/render.js +220 -0
  184. package/dist/commands/flow/render.js.map +1 -0
  185. package/dist/commands/flow/select.d.ts +31 -0
  186. package/dist/commands/flow/select.d.ts.map +1 -0
  187. package/dist/commands/flow/select.js +62 -0
  188. package/dist/commands/flow/select.js.map +1 -0
  189. package/dist/commands/graph/boundaries-input.d.ts +26 -0
  190. package/dist/commands/graph/boundaries-input.d.ts.map +1 -0
  191. package/dist/commands/graph/boundaries-input.js +54 -0
  192. package/dist/commands/graph/boundaries-input.js.map +1 -0
  193. package/dist/commands/graph/boundaries.d.ts +4 -0
  194. package/dist/commands/graph/boundaries.d.ts.map +1 -0
  195. package/dist/commands/graph/boundaries.js +141 -0
  196. package/dist/commands/graph/boundaries.js.map +1 -0
  197. package/dist/commands/graph/bounds.d.ts +16 -0
  198. package/dist/commands/graph/bounds.d.ts.map +1 -0
  199. package/dist/commands/graph/bounds.js +22 -0
  200. package/dist/commands/graph/bounds.js.map +1 -0
  201. package/dist/commands/graph/category-clusters.d.ts +20 -0
  202. package/dist/commands/graph/category-clusters.d.ts.map +1 -0
  203. package/dist/commands/graph/category-clusters.js +158 -0
  204. package/dist/commands/graph/category-clusters.js.map +1 -0
  205. package/dist/commands/graph/feature-3d.d.ts +22 -0
  206. package/dist/commands/graph/feature-3d.d.ts.map +1 -0
  207. package/dist/commands/graph/feature-3d.js +114 -0
  208. package/dist/commands/graph/feature-3d.js.map +1 -0
  209. package/dist/commands/graph/feature-clusters.d.ts +17 -0
  210. package/dist/commands/graph/feature-clusters.d.ts.map +1 -0
  211. package/dist/commands/graph/feature-clusters.js +94 -0
  212. package/dist/commands/graph/feature-clusters.js.map +1 -0
  213. package/dist/commands/graph/feature-html.d.ts +26 -0
  214. package/dist/commands/graph/feature-html.d.ts.map +1 -0
  215. package/dist/commands/graph/feature-html.js +314 -0
  216. package/dist/commands/graph/feature-html.js.map +1 -0
  217. package/dist/commands/graph/feature-map.d.ts +31 -0
  218. package/dist/commands/graph/feature-map.d.ts.map +1 -0
  219. package/dist/commands/graph/feature-map.js +217 -0
  220. package/dist/commands/graph/feature-map.js.map +1 -0
  221. package/dist/commands/graph/feature-model.d.ts +55 -0
  222. package/dist/commands/graph/feature-model.d.ts.map +1 -0
  223. package/dist/commands/graph/feature-model.js +167 -0
  224. package/dist/commands/graph/feature-model.js.map +1 -0
  225. package/dist/commands/graph/feature-untangle-motion.d.ts +33 -0
  226. package/dist/commands/graph/feature-untangle-motion.d.ts.map +1 -0
  227. package/dist/commands/graph/feature-untangle-motion.js +155 -0
  228. package/dist/commands/graph/feature-untangle-motion.js.map +1 -0
  229. package/dist/commands/graph/index.d.ts +3 -0
  230. package/dist/commands/graph/index.d.ts.map +1 -0
  231. package/dist/commands/graph/index.js +414 -0
  232. package/dist/commands/graph/index.js.map +1 -0
  233. package/dist/commands/graph/render.d.ts +63 -0
  234. package/dist/commands/graph/render.d.ts.map +1 -0
  235. package/dist/commands/graph/render.js +352 -0
  236. package/dist/commands/graph/render.js.map +1 -0
  237. package/dist/commands/graph/select.d.ts +34 -0
  238. package/dist/commands/graph/select.d.ts.map +1 -0
  239. package/dist/commands/graph/select.js +55 -0
  240. package/dist/commands/graph/select.js.map +1 -0
  241. package/dist/commands/index/index.d.ts +6 -0
  242. package/dist/commands/index/index.d.ts.map +1 -0
  243. package/dist/commands/index/index.js +461 -0
  244. package/dist/commands/index/index.js.map +1 -0
  245. package/dist/commands/index/render.d.ts +53 -0
  246. package/dist/commands/index/render.d.ts.map +1 -0
  247. package/dist/commands/index/render.js +205 -0
  248. package/dist/commands/index/render.js.map +1 -0
  249. package/dist/commands/index/target.d.ts +34 -0
  250. package/dist/commands/index/target.d.ts.map +1 -0
  251. package/dist/commands/index/target.js +97 -0
  252. package/dist/commands/index/target.js.map +1 -0
  253. package/dist/commands/index-watch.d.ts +30 -0
  254. package/dist/commands/index-watch.d.ts.map +1 -0
  255. package/dist/commands/index-watch.js +138 -0
  256. package/dist/commands/index-watch.js.map +1 -0
  257. package/dist/commands/init/command.d.ts +25 -0
  258. package/dist/commands/init/command.d.ts.map +1 -0
  259. package/dist/commands/init/command.js +198 -0
  260. package/dist/commands/init/command.js.map +1 -0
  261. package/dist/commands/init/config-draft.d.ts +48 -0
  262. package/dist/commands/init/config-draft.d.ts.map +1 -0
  263. package/dist/commands/init/config-draft.js +201 -0
  264. package/dist/commands/init/config-draft.js.map +1 -0
  265. package/dist/commands/init/diff.d.ts +33 -0
  266. package/dist/commands/init/diff.d.ts.map +1 -0
  267. package/dist/commands/init/diff.js +109 -0
  268. package/dist/commands/init/diff.js.map +1 -0
  269. package/dist/commands/init/http-probe.d.ts +26 -0
  270. package/dist/commands/init/http-probe.d.ts.map +1 -0
  271. package/dist/commands/init/http-probe.js +144 -0
  272. package/dist/commands/init/http-probe.js.map +1 -0
  273. package/dist/commands/init/ignore-rules.d.ts +70 -0
  274. package/dist/commands/init/ignore-rules.d.ts.map +1 -0
  275. package/dist/commands/init/ignore-rules.js +146 -0
  276. package/dist/commands/init/ignore-rules.js.map +1 -0
  277. package/dist/commands/init/index.d.ts +33 -0
  278. package/dist/commands/init/index.d.ts.map +1 -0
  279. package/dist/commands/init/index.js +32 -0
  280. package/dist/commands/init/index.js.map +1 -0
  281. package/dist/commands/init/integrations-apply.d.ts +50 -0
  282. package/dist/commands/init/integrations-apply.d.ts.map +1 -0
  283. package/dist/commands/init/integrations-apply.js +452 -0
  284. package/dist/commands/init/integrations-apply.js.map +1 -0
  285. package/dist/commands/init/integrations-plan.d.ts +68 -0
  286. package/dist/commands/init/integrations-plan.d.ts.map +1 -0
  287. package/dist/commands/init/integrations-plan.js +515 -0
  288. package/dist/commands/init/integrations-plan.js.map +1 -0
  289. package/dist/commands/init/integrations.d.ts +5 -0
  290. package/dist/commands/init/integrations.d.ts.map +1 -0
  291. package/dist/commands/init/integrations.js +4 -0
  292. package/dist/commands/init/integrations.js.map +1 -0
  293. package/dist/commands/init/languages.d.ts +55 -0
  294. package/dist/commands/init/languages.d.ts.map +1 -0
  295. package/dist/commands/init/languages.js +245 -0
  296. package/dist/commands/init/languages.js.map +1 -0
  297. package/dist/commands/init/product-context.d.ts +63 -0
  298. package/dist/commands/init/product-context.d.ts.map +1 -0
  299. package/dist/commands/init/product-context.js +390 -0
  300. package/dist/commands/init/product-context.js.map +1 -0
  301. package/dist/commands/init/render.d.ts +38 -0
  302. package/dist/commands/init/render.d.ts.map +1 -0
  303. package/dist/commands/init/render.js +501 -0
  304. package/dist/commands/init/render.js.map +1 -0
  305. package/dist/commands/init/report.d.ts +24 -0
  306. package/dist/commands/init/report.d.ts.map +1 -0
  307. package/dist/commands/init/report.js +163 -0
  308. package/dist/commands/init/report.js.map +1 -0
  309. package/dist/commands/init/run.d.ts +71 -0
  310. package/dist/commands/init/run.d.ts.map +1 -0
  311. package/dist/commands/init/run.js +253 -0
  312. package/dist/commands/init/run.js.map +1 -0
  313. package/dist/commands/init/services.d.ts +82 -0
  314. package/dist/commands/init/services.d.ts.map +1 -0
  315. package/dist/commands/init/services.js +209 -0
  316. package/dist/commands/init/services.js.map +1 -0
  317. package/dist/commands/init/storage.d.ts +8 -0
  318. package/dist/commands/init/storage.d.ts.map +1 -0
  319. package/dist/commands/init/storage.js +102 -0
  320. package/dist/commands/init/storage.js.map +1 -0
  321. package/dist/commands/init/toml.d.ts +65 -0
  322. package/dist/commands/init/toml.d.ts.map +1 -0
  323. package/dist/commands/init/toml.js +159 -0
  324. package/dist/commands/init/toml.js.map +1 -0
  325. package/dist/commands/init/topology.d.ts +54 -0
  326. package/dist/commands/init/topology.d.ts.map +1 -0
  327. package/dist/commands/init/topology.js +146 -0
  328. package/dist/commands/init/topology.js.map +1 -0
  329. package/dist/commands/init/types.d.ts +334 -0
  330. package/dist/commands/init/types.d.ts.map +1 -0
  331. package/dist/commands/init/types.js +31 -0
  332. package/dist/commands/init/types.js.map +1 -0
  333. package/dist/commands/init/wizard-terminal.d.ts +36 -0
  334. package/dist/commands/init/wizard-terminal.d.ts.map +1 -0
  335. package/dist/commands/init/wizard-terminal.js +163 -0
  336. package/dist/commands/init/wizard-terminal.js.map +1 -0
  337. package/dist/commands/init/wizard.d.ts +25 -0
  338. package/dist/commands/init/wizard.d.ts.map +1 -0
  339. package/dist/commands/init/wizard.js +358 -0
  340. package/dist/commands/init/wizard.js.map +1 -0
  341. package/dist/commands/mcp.d.ts +4 -0
  342. package/dist/commands/mcp.d.ts.map +1 -0
  343. package/dist/commands/mcp.js +111 -0
  344. package/dist/commands/mcp.js.map +1 -0
  345. package/dist/commands/product-test-runner.d.ts +4 -0
  346. package/dist/commands/product-test-runner.d.ts.map +1 -0
  347. package/dist/commands/product-test-runner.js +85 -0
  348. package/dist/commands/product-test-runner.js.map +1 -0
  349. package/dist/commands/product.d.ts +16 -0
  350. package/dist/commands/product.d.ts.map +1 -0
  351. package/dist/commands/product.js +262 -0
  352. package/dist/commands/product.js.map +1 -0
  353. package/dist/commands/query.d.ts +114 -0
  354. package/dist/commands/query.d.ts.map +1 -0
  355. package/dist/commands/query.js +783 -0
  356. package/dist/commands/query.js.map +1 -0
  357. package/dist/commands/scan.d.ts +10 -0
  358. package/dist/commands/scan.d.ts.map +1 -0
  359. package/dist/commands/scan.js +302 -0
  360. package/dist/commands/scan.js.map +1 -0
  361. package/dist/commands/sdd.d.ts +24 -0
  362. package/dist/commands/sdd.d.ts.map +1 -0
  363. package/dist/commands/sdd.js +195 -0
  364. package/dist/commands/sdd.js.map +1 -0
  365. package/dist/commands/unavailable.d.ts +40 -0
  366. package/dist/commands/unavailable.d.ts.map +1 -0
  367. package/dist/commands/unavailable.js +73 -0
  368. package/dist/commands/unavailable.js.map +1 -0
  369. package/dist/commands/watch/analyze.d.ts +69 -0
  370. package/dist/commands/watch/analyze.d.ts.map +1 -0
  371. package/dist/commands/watch/analyze.js +402 -0
  372. package/dist/commands/watch/analyze.js.map +1 -0
  373. package/dist/commands/watch/cli.d.ts +8 -0
  374. package/dist/commands/watch/cli.d.ts.map +1 -0
  375. package/dist/commands/watch/cli.js +97 -0
  376. package/dist/commands/watch/cli.js.map +1 -0
  377. package/dist/commands/watch/delta.d.ts +46 -0
  378. package/dist/commands/watch/delta.d.ts.map +1 -0
  379. package/dist/commands/watch/delta.js +170 -0
  380. package/dist/commands/watch/delta.js.map +1 -0
  381. package/dist/commands/watch/events.d.ts +214 -0
  382. package/dist/commands/watch/events.d.ts.map +1 -0
  383. package/dist/commands/watch/events.js +13 -0
  384. package/dist/commands/watch/events.js.map +1 -0
  385. package/dist/commands/watch/index.d.ts +19 -0
  386. package/dist/commands/watch/index.d.ts.map +1 -0
  387. package/dist/commands/watch/index.js +15 -0
  388. package/dist/commands/watch/index.js.map +1 -0
  389. package/dist/commands/watch/options.d.ts +43 -0
  390. package/dist/commands/watch/options.d.ts.map +1 -0
  391. package/dist/commands/watch/options.js +193 -0
  392. package/dist/commands/watch/options.js.map +1 -0
  393. package/dist/commands/watch/render.d.ts +26 -0
  394. package/dist/commands/watch/render.d.ts.map +1 -0
  395. package/dist/commands/watch/render.js +175 -0
  396. package/dist/commands/watch/render.js.map +1 -0
  397. package/dist/commands/watch/run.d.ts +14 -0
  398. package/dist/commands/watch/run.d.ts.map +1 -0
  399. package/dist/commands/watch/run.js +460 -0
  400. package/dist/commands/watch/run.js.map +1 -0
  401. package/dist/commands/watch/runtime.d.ts +67 -0
  402. package/dist/commands/watch/runtime.d.ts.map +1 -0
  403. package/dist/commands/watch/runtime.js +149 -0
  404. package/dist/commands/watch/runtime.js.map +1 -0
  405. package/dist/commands/watch-command.d.ts +3 -0
  406. package/dist/commands/watch-command.d.ts.map +1 -0
  407. package/dist/commands/watch-command.js +273 -0
  408. package/dist/commands/watch-command.js.map +1 -0
  409. package/dist/entry-point.d.ts +11 -0
  410. package/dist/entry-point.d.ts.map +1 -0
  411. package/dist/entry-point.js +65 -0
  412. package/dist/entry-point.js.map +1 -0
  413. package/dist/index.d.ts +38 -0
  414. package/dist/index.d.ts.map +1 -0
  415. package/dist/index.js +245 -0
  416. package/dist/index.js.map +1 -0
  417. package/dist/mcp/boundaries-schema.d.ts +262 -0
  418. package/dist/mcp/boundaries-schema.d.ts.map +1 -0
  419. package/dist/mcp/boundaries-schema.js +183 -0
  420. package/dist/mcp/boundaries-schema.js.map +1 -0
  421. package/dist/mcp/default-runtime.d.ts +16 -0
  422. package/dist/mcp/default-runtime.d.ts.map +1 -0
  423. package/dist/mcp/default-runtime.js +718 -0
  424. package/dist/mcp/default-runtime.js.map +1 -0
  425. package/dist/mcp/envelope.d.ts +13 -0
  426. package/dist/mcp/envelope.d.ts.map +1 -0
  427. package/dist/mcp/envelope.js +29 -0
  428. package/dist/mcp/envelope.js.map +1 -0
  429. package/dist/mcp/index.d.ts +8 -0
  430. package/dist/mcp/index.d.ts.map +1 -0
  431. package/dist/mcp/index.js +8 -0
  432. package/dist/mcp/index.js.map +1 -0
  433. package/dist/mcp/output-schemas.d.ts +5928 -0
  434. package/dist/mcp/output-schemas.d.ts.map +1 -0
  435. package/dist/mcp/output-schemas.js +2814 -0
  436. package/dist/mcp/output-schemas.js.map +1 -0
  437. package/dist/mcp/path-sandbox.d.ts +35 -0
  438. package/dist/mcp/path-sandbox.d.ts.map +1 -0
  439. package/dist/mcp/path-sandbox.js +128 -0
  440. package/dist/mcp/path-sandbox.js.map +1 -0
  441. package/dist/mcp/server.d.ts +155 -0
  442. package/dist/mcp/server.d.ts.map +1 -0
  443. package/dist/mcp/server.js +257 -0
  444. package/dist/mcp/server.js.map +1 -0
  445. package/dist/mcp/stdio.d.ts +20 -0
  446. package/dist/mcp/stdio.d.ts.map +1 -0
  447. package/dist/mcp/stdio.js +71 -0
  448. package/dist/mcp/stdio.js.map +1 -0
  449. package/dist/mcp/tools.d.ts +355 -0
  450. package/dist/mcp/tools.d.ts.map +1 -0
  451. package/dist/mcp/tools.js +319 -0
  452. package/dist/mcp/tools.js.map +1 -0
  453. package/dist/mcp/types.d.ts +15 -0
  454. package/dist/mcp/types.d.ts.map +1 -0
  455. package/dist/mcp/types.js +45 -0
  456. package/dist/mcp/types.js.map +1 -0
  457. package/package.json +99 -3
  458. package/src/cli/args.ts +231 -0
  459. package/src/cli/command.ts +146 -0
  460. package/src/cli/deadline.ts +56 -0
  461. package/src/cli/embedder-deadline.ts +187 -0
  462. package/src/cli/exit.ts +94 -0
  463. package/src/cli/graphs.ts +191 -0
  464. package/src/cli/index-freshness.ts +303 -0
  465. package/src/cli/index-refresh.ts +125 -0
  466. package/src/cli/index-state.ts +1217 -0
  467. package/src/cli/io.ts +56 -0
  468. package/src/cli/language-support.ts +203 -0
  469. package/src/cli/renewing-lease.ts +121 -0
  470. package/src/cli/search-graph-enrichment.ts +639 -0
  471. package/src/cli/system.ts +94 -0
  472. package/src/cli/vector-store-policy.ts +213 -0
  473. package/src/cli/version.ts +2 -0
  474. package/src/cli/workspace.ts +324 -0
  475. package/src/commands/complexity.ts +776 -0
  476. package/src/commands/doctor.languages.ts +187 -0
  477. package/src/commands/doctor.storage.ts +124 -0
  478. package/src/commands/doctor.ts +946 -0
  479. package/src/commands/extensions/add.ts +312 -0
  480. package/src/commands/extensions/configure.ts +82 -0
  481. package/src/commands/extensions/container.ts +209 -0
  482. package/src/commands/extensions/context.ts +109 -0
  483. package/src/commands/extensions/enable.ts +237 -0
  484. package/src/commands/extensions/environment.ts +218 -0
  485. package/src/commands/extensions/feature-scan.ts +232 -0
  486. package/src/commands/extensions/invoke.ts +368 -0
  487. package/src/commands/extensions/list.ts +158 -0
  488. package/src/commands/extensions/logs.ts +104 -0
  489. package/src/commands/extensions/provision.ts +206 -0
  490. package/src/commands/extensions/remove.ts +110 -0
  491. package/src/commands/extensions/render.ts +32 -0
  492. package/src/commands/extensions/run.ts +386 -0
  493. package/src/commands/extensions/secret-store.ts +223 -0
  494. package/src/commands/extensions/setup.ts +140 -0
  495. package/src/commands/extensions/source.ts +189 -0
  496. package/src/commands/extensions/state.ts +252 -0
  497. package/src/commands/extensions/status.ts +320 -0
  498. package/src/commands/extensions.ts +280 -0
  499. package/src/commands/flow/index.ts +402 -0
  500. package/src/commands/flow/limits.ts +14 -0
  501. package/src/commands/flow/output.ts +16 -0
  502. package/src/commands/flow/render.ts +318 -0
  503. package/src/commands/flow/select.ts +101 -0
  504. package/src/commands/graph/boundaries-input.ts +63 -0
  505. package/src/commands/graph/boundaries.ts +182 -0
  506. package/src/commands/graph/bounds.ts +25 -0
  507. package/src/commands/graph/category-clusters.ts +194 -0
  508. package/src/commands/graph/feature-3d.ts +141 -0
  509. package/src/commands/graph/feature-clusters.ts +125 -0
  510. package/src/commands/graph/feature-html.ts +336 -0
  511. package/src/commands/graph/feature-map.ts +270 -0
  512. package/src/commands/graph/feature-model.ts +234 -0
  513. package/src/commands/graph/feature-untangle-motion.ts +192 -0
  514. package/src/commands/graph/index.ts +562 -0
  515. package/src/commands/graph/render.ts +503 -0
  516. package/src/commands/graph/select.ts +77 -0
  517. package/src/commands/index/index.ts +595 -0
  518. package/src/commands/index/render.ts +325 -0
  519. package/src/commands/index/target.ts +136 -0
  520. package/src/commands/index-watch.ts +206 -0
  521. package/src/commands/init/command.ts +238 -0
  522. package/src/commands/init/config-draft.ts +235 -0
  523. package/src/commands/init/diff.ts +117 -0
  524. package/src/commands/init/http-probe.ts +150 -0
  525. package/src/commands/init/ignore-rules.ts +170 -0
  526. package/src/commands/init/index.ts +63 -0
  527. package/src/commands/init/integrations-apply.ts +618 -0
  528. package/src/commands/init/integrations-plan.ts +634 -0
  529. package/src/commands/init/integrations.ts +8 -0
  530. package/src/commands/init/languages.ts +320 -0
  531. package/src/commands/init/product-context.ts +576 -0
  532. package/src/commands/init/render.ts +598 -0
  533. package/src/commands/init/report.ts +204 -0
  534. package/src/commands/init/run.ts +349 -0
  535. package/src/commands/init/services.ts +271 -0
  536. package/src/commands/init/storage.ts +136 -0
  537. package/src/commands/init/toml.ts +174 -0
  538. package/src/commands/init/topology.ts +192 -0
  539. package/src/commands/init/types.ts +366 -0
  540. package/src/commands/init/wizard-terminal.ts +206 -0
  541. package/src/commands/init/wizard.ts +450 -0
  542. package/src/commands/mcp.ts +123 -0
  543. package/src/commands/product-test-runner.ts +80 -0
  544. package/src/commands/product.ts +331 -0
  545. package/src/commands/query.ts +1032 -0
  546. package/src/commands/scan.ts +360 -0
  547. package/src/commands/sdd.ts +243 -0
  548. package/src/commands/unavailable.ts +92 -0
  549. package/src/commands/watch/README.md +160 -0
  550. package/src/commands/watch/analyze.ts +600 -0
  551. package/src/commands/watch/cli.ts +108 -0
  552. package/src/commands/watch/delta.ts +186 -0
  553. package/src/commands/watch/events.ts +235 -0
  554. package/src/commands/watch/index.ts +53 -0
  555. package/src/commands/watch/options.ts +234 -0
  556. package/src/commands/watch/render.ts +240 -0
  557. package/src/commands/watch/run.ts +553 -0
  558. package/src/commands/watch/runtime.ts +167 -0
  559. package/src/commands/watch-command.ts +294 -0
  560. package/src/entry-point.ts +67 -0
  561. package/src/index.ts +291 -0
  562. package/src/mcp/boundaries-schema.ts +193 -0
  563. package/src/mcp/default-runtime.ts +1034 -0
  564. package/src/mcp/envelope.ts +57 -0
  565. package/src/mcp/index.ts +28 -0
  566. package/src/mcp/output-schemas.ts +3071 -0
  567. package/src/mcp/path-sandbox.ts +156 -0
  568. package/src/mcp/server.ts +358 -0
  569. package/src/mcp/stdio.ts +92 -0
  570. package/src/mcp/tools.ts +563 -0
  571. package/src/mcp/types.ts +66 -0
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Probing the two pieces of infrastructure Untangle needs.
3
+ *
4
+ * READ-ONLY, ON PURPOSE. `HttpProbePort` can issue a GET and nothing else, so
5
+ * `init` is structurally incapable of changing a service it finds — which is
6
+ * what spec.md §3.2 demands of External Infrastructure mode ("Untangle DARF in
7
+ * diesem Modus keine fremden Prozesse oder Container verändern").
8
+ *
9
+ * WHICH URLS ARE PROBED AT ALL IS NOT DECIDED HERE ANY MORE (WP-222). That
10
+ * rule lives in `cli/vector-store-policy.ts` and is the SAME rule
11
+ * `untangle doctor` obeys. It used to be written out twice — once here, once
12
+ * (by omission) in `doctor` — and the two disagreed: `init` refused upstream's
13
+ * default port 6333 citing spec.md §3.2, while `doctor` fell back onto it,
14
+ * found the foreign instance living there and reported it as healthy. Two
15
+ * commands of one tool, two answers to a safety question. One rule, one
16
+ * file, one answer.
17
+ *
18
+ * NOT FINDING EITHER SERVICE IS NOT AN ERROR (WP-125): the configuration is
19
+ * written regardless, and the command names exactly one next step.
20
+ */
21
+
22
+ import { compareCodepoints } from "@untangle-code/domain";
23
+
24
+ import { MANAGED_QDRANT_URL, qdrantProbePlan } from "../../cli/vector-store-policy.js";
25
+
26
+ import type {
27
+ EmbeddingModelInfoV1,
28
+ HttpProbePort,
29
+ InitLimitsV1,
30
+ OllamaFindingsV1,
31
+ QdrantFindingsV1,
32
+ } from "./types.js";
33
+
34
+ /** Native Ollama probe target (spec.md §3.1). */
35
+ export const DEFAULT_OLLAMA_URL = "http://127.0.0.1:11434";
36
+
37
+ /**
38
+ * Managed Qdrant REST port (spec.md §3.1) — re-exported, NOT redefined. The
39
+ * value belongs to the shared policy; a second copy here is exactly how the
40
+ * two commands drifted apart in the first place.
41
+ */
42
+ export const DEFAULT_QDRANT_URL = MANAGED_QDRANT_URL;
43
+
44
+ interface OllamaModelDetails {
45
+ context_length?: unknown;
46
+ embedding_length?: unknown;
47
+ }
48
+
49
+ interface OllamaModel {
50
+ name?: unknown;
51
+ capabilities?: unknown;
52
+ details?: OllamaModelDetails;
53
+ }
54
+
55
+ /**
56
+ * Reads `/api/tags` into the embedding models it describes.
57
+ *
58
+ * The provider reports `capabilities`, `embedding_length` and
59
+ * `context_length` per model, so the vector width is READ, never guessed and
60
+ * never obtained by sending the model something to embed. A model that
61
+ * predates the `capabilities` field is still recognised by the presence of an
62
+ * `embedding_length`, which only embedding models carry.
63
+ */
64
+ export function readEmbeddingModels(payload: unknown): EmbeddingModelInfoV1[] {
65
+ if (typeof payload !== "object" || payload === null) {
66
+ return [];
67
+ }
68
+ const models = (payload as { models?: unknown }).models;
69
+ if (!Array.isArray(models)) {
70
+ return [];
71
+ }
72
+ const found: EmbeddingModelInfoV1[] = [];
73
+ for (const raw of models as OllamaModel[]) {
74
+ if (typeof raw !== "object" || raw === null) {
75
+ continue;
76
+ }
77
+ const name = typeof raw.name === "string" ? raw.name : undefined;
78
+ if (name === undefined || name.length === 0) {
79
+ continue;
80
+ }
81
+ const capabilities = Array.isArray(raw.capabilities)
82
+ ? raw.capabilities.filter((item): item is string => typeof item === "string")
83
+ : [];
84
+ const details = typeof raw.details === "object" && raw.details !== null ? raw.details : {};
85
+ const dimensions = positiveInteger(details.embedding_length);
86
+ const contextLength = positiveInteger(details.context_length);
87
+ const isEmbedding = capabilities.includes("embedding") || dimensions !== undefined;
88
+ if (!isEmbedding) {
89
+ continue;
90
+ }
91
+ found.push({
92
+ name,
93
+ ...(dimensions === undefined ? {} : { dimensions }),
94
+ ...(contextLength === undefined ? {} : { contextLength }),
95
+ });
96
+ }
97
+ found.sort((a, b) => compareCodepoints(a.name, b.name));
98
+ return found;
99
+ }
100
+
101
+ export interface ModelChoiceV1 {
102
+ model: EmbeddingModelInfoV1;
103
+ reason: string;
104
+ }
105
+
106
+ /**
107
+ * Chooses one embedding model out of what the provider actually has.
108
+ *
109
+ * The rule, in order: the widest context window first, because a code chunk
110
+ * that does not fit is a chunk that gets truncated; then the widest vector,
111
+ * because that is the model with more to say; then codepoint order, so the
112
+ * decision never depends on the order the provider happened to list its
113
+ * models in. `preferred` (an explicit user choice) short-circuits all of it.
114
+ *
115
+ * Deliberately NOT "whatever the product default is called": on a machine
116
+ * that has three embedding models and not the default one, silently falling
117
+ * back to a name that is not installed produces a configuration that fails on
118
+ * first use.
119
+ */
120
+ export function chooseEmbeddingModel(
121
+ models: readonly EmbeddingModelInfoV1[],
122
+ preferred?: string,
123
+ ): ModelChoiceV1 | undefined {
124
+ if (models.length === 0) {
125
+ return undefined;
126
+ }
127
+ if (preferred !== undefined) {
128
+ const exact = models.find((model) => model.name === preferred);
129
+ if (exact !== undefined) {
130
+ return { model: exact, reason: "explicitly requested (--embedding-model)" };
131
+ }
132
+ }
133
+ const ranked = [...models].sort((a, b) => {
134
+ const contextDelta = (b.contextLength ?? 0) - (a.contextLength ?? 0);
135
+ if (contextDelta !== 0) {
136
+ return contextDelta;
137
+ }
138
+ const dimensionDelta = (b.dimensions ?? 0) - (a.dimensions ?? 0);
139
+ if (dimensionDelta !== 0) {
140
+ return dimensionDelta;
141
+ }
142
+ return compareCodepoints(a.name, b.name);
143
+ });
144
+ const model = ranked[0] as EmbeddingModelInfoV1;
145
+ return {
146
+ model,
147
+ reason:
148
+ models.length === 1
149
+ ? "the provider's only reported embedding model"
150
+ : `largest context window among ${String(models.length)} reported embedding models`,
151
+ };
152
+ }
153
+
154
+ export interface ProbeInput {
155
+ http: HttpProbePort;
156
+ limits: InitLimitsV1;
157
+ /** `UNTANGLE_OLLAMA_URL` when set. */
158
+ ollamaUrl: string;
159
+ /** `UNTANGLE_QDRANT_URL` when set — probed BEFORE the managed default. */
160
+ qdrantUrls: readonly string[];
161
+ /** Model name from `--embedding-model`, when given. */
162
+ preferredModel?: string;
163
+ }
164
+
165
+ /**
166
+ * WP-228: Erreichbarkeit heisst NICHT „benutzbar".
167
+ *
168
+ * Bis hierher fragte `init` nur `/api/version` und `/api/tags` — zwei
169
+ * Endpunkte, die der Indexlauf nie anfasst. Auf dem Rechner, an dem das
170
+ * gemessen wurde, antworteten beide sofort, waehrend `/api/embed` haengte:
171
+ * die geschriebene Konfiguration versprach einen Dienst, der keinen einzigen
172
+ * Chunk einbetten konnte. Deshalb wird jetzt der Endpunkt geprueft, den das
173
+ * Produkt WIRKLICH benutzt — mit kurzer Frist, und ein Fristablauf ist ein
174
+ * Befund, keine bestandene Pruefung.
175
+ */
176
+ export async function probeOllama(input: ProbeInput): Promise<OllamaFindingsV1> {
177
+ const { http, limits, ollamaUrl } = input;
178
+ const notProbed = (detail: string): OllamaFindingsV1["embedProbe"] => ({
179
+ outcome: "not-probed",
180
+ timeoutMs: limits.embedProbeTimeoutMs,
181
+ detail,
182
+ });
183
+
184
+ const version = await http.getJson(`${trimSlash(ollamaUrl)}/api/version`, limits.probeTimeoutMs);
185
+ if (version === null) {
186
+ return {
187
+ outcome: "unreachable",
188
+ url: ollamaUrl,
189
+ embeddingModels: [],
190
+ embedProbe: notProbed("the provider was already unreachable"),
191
+ };
192
+ }
193
+ const versionString = readString(version, "version");
194
+ const tags = await http.getJson(`${trimSlash(ollamaUrl)}/api/tags`, limits.probeTimeoutMs);
195
+ const embeddingModels = readEmbeddingModels(tags);
196
+ const choice = chooseEmbeddingModel(embeddingModels, input.preferredModel);
197
+
198
+ const embedProbe =
199
+ choice === undefined
200
+ ? notProbed("the provider reports no embedding model")
201
+ : await runEmbedProbe(http, ollamaUrl, choice.model.name, limits.embedProbeTimeoutMs);
202
+
203
+ return {
204
+ outcome: "reachable",
205
+ url: ollamaUrl,
206
+ ...(versionString === undefined ? {} : { version: versionString }),
207
+ embeddingModels,
208
+ ...(choice === undefined ? {} : { chosenModel: choice.model, chosenReason: choice.reason }),
209
+ embedProbe,
210
+ };
211
+ }
212
+
213
+ /** Ein winziges Probe-Embedding, mit Frist. Wirft nie — es antwortet. */
214
+ async function runEmbedProbe(
215
+ http: HttpProbePort,
216
+ ollamaUrl: string,
217
+ model: string,
218
+ timeoutMs: number,
219
+ ): Promise<OllamaFindingsV1["embedProbe"]> {
220
+ const result = await http.probeEmbedding(trimSlash(ollamaUrl), model, timeoutMs);
221
+ if (result.ok) {
222
+ return { outcome: "ok", timeoutMs, dimensions: result.dimensions };
223
+ }
224
+ return {
225
+ outcome: result.timedOut ? "timeout" : "failed",
226
+ timeoutMs,
227
+ detail: result.detail,
228
+ };
229
+ }
230
+
231
+ export async function probeQdrant(input: ProbeInput): Promise<QdrantFindingsV1> {
232
+ const { http, limits, qdrantUrls } = input;
233
+ const probedUrls = [...qdrantUrls];
234
+ // The skipped list — with its reason — comes from the shared policy, so it
235
+ // can never claim something other than what the policy actually enforces.
236
+ const skippedUrls = qdrantProbePlan({}).skipped.filter(
237
+ (candidate) => !probedUrls.includes(candidate.url),
238
+ );
239
+
240
+ for (const url of probedUrls) {
241
+ const payload = await http.getJson(`${trimSlash(url)}/`, limits.probeTimeoutMs);
242
+ if (payload === null) {
243
+ continue;
244
+ }
245
+ const version = readString(payload, "version");
246
+ return {
247
+ outcome: "reachable",
248
+ probedUrls,
249
+ url,
250
+ ...(version === undefined ? {} : { version }),
251
+ skippedUrls,
252
+ };
253
+ }
254
+ return { outcome: "unreachable", probedUrls, skippedUrls };
255
+ }
256
+
257
+ function trimSlash(value: string): string {
258
+ return value.endsWith("/") ? value.slice(0, -1) : value;
259
+ }
260
+
261
+ function readString(payload: unknown, key: string): string | undefined {
262
+ if (typeof payload !== "object" || payload === null) {
263
+ return undefined;
264
+ }
265
+ const value = (payload as Record<string, unknown>)[key];
266
+ return typeof value === "string" && value.length > 0 ? value : undefined;
267
+ }
268
+
269
+ function positiveInteger(value: unknown): number | undefined {
270
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
271
+ }
@@ -0,0 +1,136 @@
1
+ import path from "node:path";
2
+
3
+ import {
4
+ DEFAULT_STORAGE_CONFIG,
5
+ buildEnvConfigLayer,
6
+ mergeConfigLayers,
7
+ parseConfigText,
8
+ resolveUserConfigDir,
9
+ type RawConfigLayer,
10
+ } from "@untangle-code/config";
11
+ import type { FileSystemPort } from "@untangle-code/domain";
12
+
13
+ import { OperationalError } from "../../cli/exit.js";
14
+
15
+ import type { StorageFindingsV1 } from "./types.js";
16
+
17
+ /** Explicit selection wins; an explicitly configured Qdrant remains opt-in. */
18
+ export function initStorageBackend(
19
+ explicit: StorageFindingsV1["backend"] | undefined,
20
+ env: Readonly<Record<string, string | undefined>>,
21
+ existing: RawConfigLayer = {},
22
+ ): StorageFindingsV1["backend"] {
23
+ const selected = explicit ?? env["UNTANGLE_STORAGE_BACKEND"] ?? existing.storage?.backend;
24
+ if (selected !== undefined) {
25
+ if (selected === "lancedb" || selected === "qdrant") return selected;
26
+ throw new OperationalError(
27
+ `Unknown storage backend ${JSON.stringify(selected)}.`,
28
+ "Select --storage=lancedb or --storage=qdrant.",
29
+ );
30
+ }
31
+ return existing.qdrant !== undefined ||
32
+ buildEnvConfigLayer(env as NodeJS.ProcessEnv).layer.qdrant !== undefined
33
+ ? "qdrant"
34
+ : "lancedb";
35
+ }
36
+
37
+ /** Inspect a local directory without opening a database or creating files. */
38
+ export async function inspectInitStorage(
39
+ fs: FileSystemPort,
40
+ root: string,
41
+ explicit: StorageFindingsV1["backend"] | undefined,
42
+ env: Readonly<Record<string, string | undefined>>,
43
+ signal?: AbortSignal,
44
+ ): Promise<StorageFindingsV1> {
45
+ signal?.throwIfAborted();
46
+ const { layer: existing, warnings } = await existingStorageConfig(fs, root, env, signal);
47
+ const backend = initStorageBackend(explicit, env, existing);
48
+ if (backend === "qdrant") {
49
+ const mode = env["UNTANGLE_QDRANT_MODE"] ?? existing.qdrant?.mode;
50
+ const url = env["UNTANGLE_QDRANT_URL"] ?? existing.qdrant?.url;
51
+ return {
52
+ backend,
53
+ ...(mode === "managed" || mode === "external" ? { qdrantMode: mode } : {}),
54
+ ...(url === undefined ? {} : { qdrantUrl: url }),
55
+ ...(warnings.length === 0 ? {} : { configurationWarnings: warnings }),
56
+ };
57
+ }
58
+ const localPath =
59
+ env["UNTANGLE_LANCEDB_PATH"] ?? existing.storage?.path ?? DEFAULT_STORAGE_CONFIG.path;
60
+ if (!localPath)
61
+ throw new OperationalError("The local storage path is empty.", "Set UNTANGLE_LANCEDB_PATH.");
62
+ const directory = path.resolve(root, localPath);
63
+ signal?.throwIfAborted();
64
+ try {
65
+ const entry = await fs.stat(directory);
66
+ signal?.throwIfAborted();
67
+ return {
68
+ backend,
69
+ path: localPath,
70
+ directory,
71
+ directoryStatus:
72
+ entry === null ? "missing" : entry.kind === "directory" ? "present" : "not-directory",
73
+ ...(warnings.length === 0 ? {} : { configurationWarnings: warnings }),
74
+ };
75
+ } catch (error) {
76
+ signal?.throwIfAborted();
77
+ return {
78
+ backend,
79
+ path: localPath,
80
+ directory,
81
+ directoryStatus: "unreadable",
82
+ detail: error instanceof Error ? error.message : String(error),
83
+ ...(warnings.length === 0 ? {} : { configurationWarnings: warnings }),
84
+ };
85
+ }
86
+ }
87
+
88
+ /** Read the same project layer formats/order as config loading, through init's filesystem port. */
89
+ async function existingStorageConfig(
90
+ fs: FileSystemPort,
91
+ root: string,
92
+ env: Readonly<Record<string, string | undefined>>,
93
+ signal?: AbortSignal,
94
+ ): Promise<{ layer: RawConfigLayer; warnings: string[] }> {
95
+ signal?.throwIfAborted();
96
+ const json = path.join(root, ".untangle.json");
97
+ const toml = path.join(root, "untangle.toml");
98
+ const legacyExists = (await fs.stat(json)) !== null || (await fs.stat(toml)) !== null;
99
+ const user = path.join(
100
+ resolveUserConfigDir(env as NodeJS.ProcessEnv, process.platform),
101
+ "config.json",
102
+ );
103
+ const paths = [
104
+ { path: user, format: "json" as const },
105
+ { path: toml, format: "toml" as const },
106
+ {
107
+ path: legacyExists ? json : path.join(root, ".untangle/config.json"),
108
+ format: "json" as const,
109
+ },
110
+ { path: path.join(root, ".untangle.local.json"), format: "json" as const },
111
+ ];
112
+ const layers: RawConfigLayer[] = [];
113
+ const warnings: string[] = [];
114
+ let legacyQdrant = false;
115
+ for (const file of paths) {
116
+ signal?.throwIfAborted();
117
+ try {
118
+ if ((await fs.stat(file.path))?.kind !== "file") continue;
119
+ const layer = parseConfigText(await fs.readTextFile(file.path), file.format);
120
+ if (layer.qdrant !== undefined) legacyQdrant = true;
121
+ layers.push(layer);
122
+ } catch {
123
+ signal?.throwIfAborted();
124
+ warnings.push(
125
+ `Storage selection could not be inspected in ${file.path}; existing configuration is preserved unless --force is selected.`,
126
+ );
127
+ }
128
+ }
129
+ return {
130
+ layer: mergeConfigLayers<RawConfigLayer>([
131
+ ...(legacyQdrant ? [{ storage: { backend: "qdrant" } }] : []),
132
+ ...layers,
133
+ ]),
134
+ warnings,
135
+ };
136
+ }
@@ -0,0 +1,174 @@
1
+ /**
2
+ * A small, purpose-built TOML emitter.
3
+ *
4
+ * WHY NOT A LIBRARY: the point of the file `init` writes is the COMMENTS —
5
+ * the user must be able to see what was decided and why. Every general TOML
6
+ * serializer takes a value and drops the prose, because prose is not part of
7
+ * the value. So the emitter here is a line builder that happens to know how
8
+ * to spell TOML scalars, not a serializer of an object graph.
9
+ *
10
+ * It is deliberately narrow: tables, array-of-tables, scalars and homogeneous
11
+ * scalar arrays. Anything outside that throws rather than guessing — a config
12
+ * file that silently loses a value would be worse than no config file at all.
13
+ */
14
+
15
+ export type TomlScalar = string | number | boolean;
16
+
17
+ const BARE_KEY = /^[A-Za-z0-9_-]+$/;
18
+
19
+ /**
20
+ * TOML basic-string escaping. `\` and `"` plus the control characters TOML
21
+ * names explicitly; everything else below U+0020 goes to `\uXXXX` because a
22
+ * raw control byte in a config file is unreadable and, in some cases,
23
+ * unparseable.
24
+ */
25
+ export function escapeTomlString(value: string): string {
26
+ let out = "";
27
+ for (const char of value) {
28
+ switch (char) {
29
+ case "\\":
30
+ out += "\\\\";
31
+ break;
32
+ case '"':
33
+ out += '\\"';
34
+ break;
35
+ case "\b":
36
+ out += "\\b";
37
+ break;
38
+ case "\t":
39
+ out += "\\t";
40
+ break;
41
+ case "\n":
42
+ out += "\\n";
43
+ break;
44
+ case "\f":
45
+ out += "\\f";
46
+ break;
47
+ case "\r":
48
+ out += "\\r";
49
+ break;
50
+ default: {
51
+ const code = char.codePointAt(0) ?? 0;
52
+ if (code < 0x20 || code === 0x7f) {
53
+ out += `\\u${code.toString(16).padStart(4, "0").toUpperCase()}`;
54
+ } else {
55
+ out += char;
56
+ }
57
+ }
58
+ }
59
+ }
60
+ return out;
61
+ }
62
+
63
+ /** A key is written bare when it can be, quoted when it must be. */
64
+ export function formatTomlKey(key: string): string {
65
+ return BARE_KEY.test(key) ? key : `"${escapeTomlString(key)}"`;
66
+ }
67
+
68
+ /**
69
+ * Formats a number the way TOML distinguishes integers from floats: an
70
+ * integral value stays integral, a fractional one keeps its decimal point.
71
+ * Non-finite numbers are rejected — TOML has `inf`/`nan` literals, but a
72
+ * config value that is either is a bug upstream, not something to serialize.
73
+ */
74
+ export function formatTomlNumber(value: number): string {
75
+ if (!Number.isFinite(value)) {
76
+ throw new Error(`cannot serialize non-finite number: ${String(value)}`);
77
+ }
78
+ if (Number.isInteger(value)) {
79
+ return value.toFixed(0);
80
+ }
81
+ return String(value);
82
+ }
83
+
84
+ export function formatTomlScalar(value: TomlScalar): string {
85
+ if (typeof value === "string") {
86
+ return `"${escapeTomlString(value)}"`;
87
+ }
88
+ if (typeof value === "boolean") {
89
+ return value ? "true" : "false";
90
+ }
91
+ return formatTomlNumber(value);
92
+ }
93
+
94
+ /**
95
+ * A line builder for commented TOML.
96
+ *
97
+ * Order is the order of the calls: this class never reorders anything, which
98
+ * is what lets the caller interleave prose and values so that each decision
99
+ * sits directly under its justification.
100
+ */
101
+ export class TomlWriter {
102
+ private readonly lines: string[] = [];
103
+
104
+ /** A `#` comment. An empty string yields a bare `#`, which reads as a spacer. */
105
+ public comment(text: string): this {
106
+ this.lines.push(text.length === 0 ? "#" : `# ${text}`);
107
+ return this;
108
+ }
109
+
110
+ /** Several comment lines at once; convenience for wrapped prose. */
111
+ public comments(texts: readonly string[]): this {
112
+ for (const text of texts) {
113
+ this.comment(text);
114
+ }
115
+ return this;
116
+ }
117
+
118
+ public blank(): this {
119
+ this.lines.push("");
120
+ return this;
121
+ }
122
+
123
+ /** A `[table.path]` header. */
124
+ public table(path: readonly string[]): this {
125
+ this.lines.push(`[${path.map(formatTomlKey).join(".")}]`);
126
+ return this;
127
+ }
128
+
129
+ /** A `[[table.path]]` array-of-tables header. */
130
+ public arrayTable(path: readonly string[]): this {
131
+ this.lines.push(`[[${path.map(formatTomlKey).join(".")}]]`);
132
+ return this;
133
+ }
134
+
135
+ public scalar(key: string, value: TomlScalar): this {
136
+ this.lines.push(`${formatTomlKey(key)} = ${formatTomlScalar(value)}`);
137
+ return this;
138
+ }
139
+
140
+ /**
141
+ * A single-line array. Written multi-line once it would be long, because a
142
+ * 200-column exclude list is not something a human edits.
143
+ */
144
+ public array(key: string, values: readonly TomlScalar[]): this {
145
+ const rendered = values.map(formatTomlScalar);
146
+ const inline = `${formatTomlKey(key)} = [${rendered.join(", ")}]`;
147
+ if (rendered.length === 0 || inline.length <= 96) {
148
+ this.lines.push(inline);
149
+ return this;
150
+ }
151
+ this.lines.push(`${formatTomlKey(key)} = [`);
152
+ for (const item of rendered) {
153
+ this.lines.push(` ${item},`);
154
+ }
155
+ this.lines.push("]");
156
+ return this;
157
+ }
158
+
159
+ /** An empty inline table — the honest way to write "nothing configured here". */
160
+ public emptyInlineTable(key: string): this {
161
+ this.lines.push(`${formatTomlKey(key)} = {}`);
162
+ return this;
163
+ }
164
+
165
+ /**
166
+ * The finished document. Always ends in exactly one newline: a trailing
167
+ * newline is what every line-oriented tool expects, and "exactly one" is
168
+ * what keeps the idempotency comparison from reporting phantom changes.
169
+ */
170
+ public render(): string {
171
+ const body = this.lines.join("\n").replace(/\n+$/u, "");
172
+ return `${body}\n`;
173
+ }
174
+ }