@andrew.ng/symbion 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 (417) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/apps/daemon/dist/boot/menu.d.ts +11 -0
  4. package/apps/daemon/dist/boot/menu.d.ts.map +1 -0
  5. package/apps/daemon/dist/boot/menu.js +32 -0
  6. package/apps/daemon/dist/boot/menu.js.map +1 -0
  7. package/apps/daemon/dist/fs/folderPick.d.ts +13 -0
  8. package/apps/daemon/dist/fs/folderPick.d.ts.map +1 -0
  9. package/apps/daemon/dist/fs/folderPick.js +4 -0
  10. package/apps/daemon/dist/fs/folderPick.js.map +1 -0
  11. package/apps/daemon/dist/fs/listDir.d.ts +13 -0
  12. package/apps/daemon/dist/fs/listDir.d.ts.map +1 -0
  13. package/apps/daemon/dist/fs/listDir.js +121 -0
  14. package/apps/daemon/dist/fs/listDir.js.map +1 -0
  15. package/apps/daemon/dist/fs/readTargetFiles.d.ts +20 -0
  16. package/apps/daemon/dist/fs/readTargetFiles.d.ts.map +1 -0
  17. package/apps/daemon/dist/fs/readTargetFiles.js +76 -0
  18. package/apps/daemon/dist/fs/readTargetFiles.js.map +1 -0
  19. package/apps/daemon/dist/fs/writeFiles.d.ts +32 -0
  20. package/apps/daemon/dist/fs/writeFiles.d.ts.map +1 -0
  21. package/apps/daemon/dist/fs/writeFiles.js +93 -0
  22. package/apps/daemon/dist/fs/writeFiles.js.map +1 -0
  23. package/apps/daemon/dist/git/status.d.ts +11 -0
  24. package/apps/daemon/dist/git/status.d.ts.map +1 -0
  25. package/apps/daemon/dist/git/status.js +30 -0
  26. package/apps/daemon/dist/git/status.js.map +1 -0
  27. package/apps/daemon/dist/index.d.ts +2 -0
  28. package/apps/daemon/dist/index.d.ts.map +1 -0
  29. package/apps/daemon/dist/index.js +69 -0
  30. package/apps/daemon/dist/index.js.map +1 -0
  31. package/apps/daemon/dist/llm/anthropicProvider.d.ts +26 -0
  32. package/apps/daemon/dist/llm/anthropicProvider.d.ts.map +1 -0
  33. package/apps/daemon/dist/llm/anthropicProvider.js +90 -0
  34. package/apps/daemon/dist/llm/anthropicProvider.js.map +1 -0
  35. package/apps/daemon/dist/llm/geminiProvider.d.ts +25 -0
  36. package/apps/daemon/dist/llm/geminiProvider.d.ts.map +1 -0
  37. package/apps/daemon/dist/llm/geminiProvider.js +89 -0
  38. package/apps/daemon/dist/llm/geminiProvider.js.map +1 -0
  39. package/apps/daemon/dist/llm/installInstructions.d.ts +40 -0
  40. package/apps/daemon/dist/llm/installInstructions.d.ts.map +1 -0
  41. package/apps/daemon/dist/llm/installInstructions.js +80 -0
  42. package/apps/daemon/dist/llm/installInstructions.js.map +1 -0
  43. package/apps/daemon/dist/llm/ollamaProvider.d.ts +55 -0
  44. package/apps/daemon/dist/llm/ollamaProvider.d.ts.map +1 -0
  45. package/apps/daemon/dist/llm/ollamaProvider.js +213 -0
  46. package/apps/daemon/dist/llm/ollamaProvider.js.map +1 -0
  47. package/apps/daemon/dist/llm/openaiProvider.d.ts +25 -0
  48. package/apps/daemon/dist/llm/openaiProvider.d.ts.map +1 -0
  49. package/apps/daemon/dist/llm/openaiProvider.js +90 -0
  50. package/apps/daemon/dist/llm/openaiProvider.js.map +1 -0
  51. package/apps/daemon/dist/llm/providerStatus.d.ts +60 -0
  52. package/apps/daemon/dist/llm/providerStatus.d.ts.map +1 -0
  53. package/apps/daemon/dist/llm/providerStatus.js +88 -0
  54. package/apps/daemon/dist/llm/providerStatus.js.map +1 -0
  55. package/apps/daemon/dist/llm/registry.d.ts +14 -0
  56. package/apps/daemon/dist/llm/registry.d.ts.map +1 -0
  57. package/apps/daemon/dist/llm/registry.js +35 -0
  58. package/apps/daemon/dist/llm/registry.js.map +1 -0
  59. package/apps/daemon/dist/llm/remoteProvider.d.ts +25 -0
  60. package/apps/daemon/dist/llm/remoteProvider.d.ts.map +1 -0
  61. package/apps/daemon/dist/llm/remoteProvider.js +88 -0
  62. package/apps/daemon/dist/llm/remoteProvider.js.map +1 -0
  63. package/apps/daemon/dist/llm/secrets.d.ts +55 -0
  64. package/apps/daemon/dist/llm/secrets.d.ts.map +1 -0
  65. package/apps/daemon/dist/llm/secrets.js +167 -0
  66. package/apps/daemon/dist/llm/secrets.js.map +1 -0
  67. package/apps/daemon/dist/llm/types.d.ts +50 -0
  68. package/apps/daemon/dist/llm/types.d.ts.map +1 -0
  69. package/apps/daemon/dist/llm/types.js +16 -0
  70. package/apps/daemon/dist/llm/types.js.map +1 -0
  71. package/apps/daemon/dist/net/findOpenPort.d.ts +26 -0
  72. package/apps/daemon/dist/net/findOpenPort.d.ts.map +1 -0
  73. package/apps/daemon/dist/net/findOpenPort.js +37 -0
  74. package/apps/daemon/dist/net/findOpenPort.js.map +1 -0
  75. package/apps/daemon/dist/rpc/contract.d.ts +10 -0
  76. package/apps/daemon/dist/rpc/contract.d.ts.map +1 -0
  77. package/apps/daemon/dist/rpc/contract.js +2 -0
  78. package/apps/daemon/dist/rpc/contract.js.map +1 -0
  79. package/apps/daemon/dist/rpc/guard.d.ts +18 -0
  80. package/apps/daemon/dist/rpc/guard.d.ts.map +1 -0
  81. package/apps/daemon/dist/rpc/guard.js +75 -0
  82. package/apps/daemon/dist/rpc/guard.js.map +1 -0
  83. package/apps/daemon/dist/rpc/handlers.d.ts +118 -0
  84. package/apps/daemon/dist/rpc/handlers.d.ts.map +1 -0
  85. package/apps/daemon/dist/rpc/handlers.js +694 -0
  86. package/apps/daemon/dist/rpc/handlers.js.map +1 -0
  87. package/apps/daemon/dist/rpc/pathStyle.d.ts +27 -0
  88. package/apps/daemon/dist/rpc/pathStyle.d.ts.map +1 -0
  89. package/apps/daemon/dist/rpc/pathStyle.js +43 -0
  90. package/apps/daemon/dist/rpc/pathStyle.js.map +1 -0
  91. package/apps/daemon/dist/rpc/rpcError.d.ts +13 -0
  92. package/apps/daemon/dist/rpc/rpcError.d.ts.map +1 -0
  93. package/apps/daemon/dist/rpc/rpcError.js +16 -0
  94. package/apps/daemon/dist/rpc/rpcError.js.map +1 -0
  95. package/apps/daemon/dist/server.d.ts +18 -0
  96. package/apps/daemon/dist/server.d.ts.map +1 -0
  97. package/apps/daemon/dist/server.js +208 -0
  98. package/apps/daemon/dist/server.js.map +1 -0
  99. package/apps/daemon/dist/store/publishLog.d.ts +6 -0
  100. package/apps/daemon/dist/store/publishLog.d.ts.map +1 -0
  101. package/apps/daemon/dist/store/publishLog.js +27 -0
  102. package/apps/daemon/dist/store/publishLog.js.map +1 -0
  103. package/apps/daemon/dist/store/store.d.ts +35 -0
  104. package/apps/daemon/dist/store/store.d.ts.map +1 -0
  105. package/apps/daemon/dist/store/store.js +129 -0
  106. package/apps/daemon/dist/store/store.js.map +1 -0
  107. package/apps/daemon/dist/templates/githubFetch.d.ts +49 -0
  108. package/apps/daemon/dist/templates/githubFetch.d.ts.map +1 -0
  109. package/apps/daemon/dist/templates/githubFetch.js +168 -0
  110. package/apps/daemon/dist/templates/githubFetch.js.map +1 -0
  111. package/apps/web/out/404.html +1 -0
  112. package/apps/web/out/_next/static/IIw50lkv8jQuwHOBZJifS/_buildManifest.js +1 -0
  113. package/apps/web/out/_next/static/IIw50lkv8jQuwHOBZJifS/_ssgManifest.js +1 -0
  114. package/apps/web/out/_next/static/chunks/1dd3208c-6a745fea7bd2124a.js +1 -0
  115. package/apps/web/out/_next/static/chunks/426-deb95a16531d3b4b.js +25 -0
  116. package/apps/web/out/_next/static/chunks/528-6e64508688610bfe.js +2 -0
  117. package/apps/web/out/_next/static/chunks/656-fd1628581ad77b01.js +1 -0
  118. package/apps/web/out/_next/static/chunks/777-d587bc7cc0fc6be8.js +1 -0
  119. package/apps/web/out/_next/static/chunks/990-f2445c68c17fa077.js +1 -0
  120. package/apps/web/out/_next/static/chunks/app/_not-found/page-e0d77774c4eb9aef.js +1 -0
  121. package/apps/web/out/_next/static/chunks/app/layout-e5023aba6634ce53.js +1 -0
  122. package/apps/web/out/_next/static/chunks/app/page-a545c902535ac2e3.js +1 -0
  123. package/apps/web/out/_next/static/chunks/app/settings/page-a68ed4ae2ccb8840.js +1 -0
  124. package/apps/web/out/_next/static/chunks/app/templates/page-e5f0cefb905e5b72.js +1 -0
  125. package/apps/web/out/_next/static/chunks/baeaa4ff-28d2e32e4dd119b9.js +1 -0
  126. package/apps/web/out/_next/static/chunks/eb0351e1-329719bc902eaf71.js +1 -0
  127. package/apps/web/out/_next/static/chunks/framework-3664cab31236a9fa.js +1 -0
  128. package/apps/web/out/_next/static/chunks/main-app-d515c42ecb17b8e8.js +1 -0
  129. package/apps/web/out/_next/static/chunks/main-ff24788874d4ec1b.js +1 -0
  130. package/apps/web/out/_next/static/chunks/pages/_app-10a93ab5b7c32eb3.js +1 -0
  131. package/apps/web/out/_next/static/chunks/pages/_error-2d792b2a41857be4.js +1 -0
  132. package/apps/web/out/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  133. package/apps/web/out/_next/static/chunks/webpack-ae7ee8fe97fdceba.js +1 -0
  134. package/apps/web/out/_next/static/css/0a42edcfc2beb916.css +3 -0
  135. package/apps/web/out/_next/static/css/a275cc2b185e04f8.css +1 -0
  136. package/apps/web/out/_next/static/media/011e180705008d6f-s.woff2 +0 -0
  137. package/apps/web/out/_next/static/media/20535187d867b7b9-s.woff2 +0 -0
  138. package/apps/web/out/_next/static/media/26d4368bf94c0ec4-s.p.woff2 +0 -0
  139. package/apps/web/out/_next/static/media/2801417b65625cf5-s.woff2 +0 -0
  140. package/apps/web/out/_next/static/media/28793f5c5e3d822d-s.woff2 +0 -0
  141. package/apps/web/out/_next/static/media/5356a6a4f2c8c8d8-s.woff2 +0 -0
  142. package/apps/web/out/_next/static/media/58f386aa6b1a2a92-s.woff2 +0 -0
  143. package/apps/web/out/_next/static/media/73cb51aac9c97f90-s.woff2 +0 -0
  144. package/apps/web/out/_next/static/media/7b19b489dc6743ba-s.woff2 +0 -0
  145. package/apps/web/out/_next/static/media/7ba5fb2a8c88521c-s.woff2 +0 -0
  146. package/apps/web/out/_next/static/media/92eeb95d069020cc-s.woff2 +0 -0
  147. package/apps/web/out/_next/static/media/98e207f02528a563-s.p.woff2 +0 -0
  148. package/apps/web/out/_next/static/media/99dcf268bda04fe5-s.woff2 +0 -0
  149. package/apps/web/out/_next/static/media/b3bf17a9041d9433-s.woff2 +0 -0
  150. package/apps/web/out/_next/static/media/c9c3823090ec8b55-s.woff2 +0 -0
  151. package/apps/web/out/_next/static/media/d26bbd13d6b70f89-s.woff2 +0 -0
  152. package/apps/web/out/_next/static/media/d29838c109ef09b4-s.woff2 +0 -0
  153. package/apps/web/out/_next/static/media/d3ebbfd689654d3a-s.p.woff2 +0 -0
  154. package/apps/web/out/_next/static/media/db96af6b531dc71f-s.p.woff2 +0 -0
  155. package/apps/web/out/_next/static/media/e40af3453d7c920a-s.woff2 +0 -0
  156. package/apps/web/out/_next/static/media/ef4d5661765d0e49-s.woff2 +0 -0
  157. package/apps/web/out/index.html +1 -0
  158. package/apps/web/out/index.txt +6 -0
  159. package/apps/web/out/settings.html +1 -0
  160. package/apps/web/out/settings.txt +6 -0
  161. package/apps/web/out/templates.html +1 -0
  162. package/apps/web/out/templates.txt +6 -0
  163. package/bin/symbion.mjs +41 -0
  164. package/node_modules/@symbion/core/dist/adapters/claude.d.ts +3 -0
  165. package/node_modules/@symbion/core/dist/adapters/claude.d.ts.map +1 -0
  166. package/node_modules/@symbion/core/dist/adapters/claude.js +43 -0
  167. package/node_modules/@symbion/core/dist/adapters/claude.js.map +1 -0
  168. package/node_modules/@symbion/core/dist/adapters/codex.d.ts +3 -0
  169. package/node_modules/@symbion/core/dist/adapters/codex.d.ts.map +1 -0
  170. package/node_modules/@symbion/core/dist/adapters/codex.js +58 -0
  171. package/node_modules/@symbion/core/dist/adapters/codex.js.map +1 -0
  172. package/node_modules/@symbion/core/dist/adapters/registry.d.ts +5 -0
  173. package/node_modules/@symbion/core/dist/adapters/registry.d.ts.map +1 -0
  174. package/node_modules/@symbion/core/dist/adapters/registry.js +14 -0
  175. package/node_modules/@symbion/core/dist/adapters/registry.js.map +1 -0
  176. package/node_modules/@symbion/core/dist/adapters/types.d.ts +34 -0
  177. package/node_modules/@symbion/core/dist/adapters/types.d.ts.map +1 -0
  178. package/node_modules/@symbion/core/dist/adapters/types.js +2 -0
  179. package/node_modules/@symbion/core/dist/adapters/types.js.map +1 -0
  180. package/node_modules/@symbion/core/dist/diff/conflict.d.ts +19 -0
  181. package/node_modules/@symbion/core/dist/diff/conflict.d.ts.map +1 -0
  182. package/node_modules/@symbion/core/dist/diff/conflict.js +20 -0
  183. package/node_modules/@symbion/core/dist/diff/conflict.js.map +1 -0
  184. package/node_modules/@symbion/core/dist/diff/diff.d.ts +44 -0
  185. package/node_modules/@symbion/core/dist/diff/diff.d.ts.map +1 -0
  186. package/node_modules/@symbion/core/dist/diff/diff.js +124 -0
  187. package/node_modules/@symbion/core/dist/diff/diff.js.map +1 -0
  188. package/node_modules/@symbion/core/dist/generate/bodyPrompt.d.ts +27 -0
  189. package/node_modules/@symbion/core/dist/generate/bodyPrompt.d.ts.map +1 -0
  190. package/node_modules/@symbion/core/dist/generate/bodyPrompt.js +55 -0
  191. package/node_modules/@symbion/core/dist/generate/bodyPrompt.js.map +1 -0
  192. package/node_modules/@symbion/core/dist/generate/description.d.ts +18 -0
  193. package/node_modules/@symbion/core/dist/generate/description.d.ts.map +1 -0
  194. package/node_modules/@symbion/core/dist/generate/description.js +164 -0
  195. package/node_modules/@symbion/core/dist/generate/description.js.map +1 -0
  196. package/node_modules/@symbion/core/dist/index.d.ts +23 -0
  197. package/node_modules/@symbion/core/dist/index.d.ts.map +1 -0
  198. package/node_modules/@symbion/core/dist/index.js +24 -0
  199. package/node_modules/@symbion/core/dist/index.js.map +1 -0
  200. package/node_modules/@symbion/core/dist/ir/refs.d.ts +11 -0
  201. package/node_modules/@symbion/core/dist/ir/refs.d.ts.map +1 -0
  202. package/node_modules/@symbion/core/dist/ir/refs.js +25 -0
  203. package/node_modules/@symbion/core/dist/ir/refs.js.map +1 -0
  204. package/node_modules/@symbion/core/dist/ir/types.d.ts +107 -0
  205. package/node_modules/@symbion/core/dist/ir/types.d.ts.map +1 -0
  206. package/node_modules/@symbion/core/dist/ir/types.js +19 -0
  207. package/node_modules/@symbion/core/dist/ir/types.js.map +1 -0
  208. package/node_modules/@symbion/core/dist/ir/validate.d.ts +13 -0
  209. package/node_modules/@symbion/core/dist/ir/validate.d.ts.map +1 -0
  210. package/node_modules/@symbion/core/dist/ir/validate.js +114 -0
  211. package/node_modules/@symbion/core/dist/ir/validate.js.map +1 -0
  212. package/node_modules/@symbion/core/dist/parse/scan.d.ts +47 -0
  213. package/node_modules/@symbion/core/dist/parse/scan.d.ts.map +1 -0
  214. package/node_modules/@symbion/core/dist/parse/scan.js +109 -0
  215. package/node_modules/@symbion/core/dist/parse/scan.js.map +1 -0
  216. package/node_modules/@symbion/core/dist/render/frontmatter.d.ts +29 -0
  217. package/node_modules/@symbion/core/dist/render/frontmatter.d.ts.map +1 -0
  218. package/node_modules/@symbion/core/dist/render/frontmatter.js +99 -0
  219. package/node_modules/@symbion/core/dist/render/frontmatter.js.map +1 -0
  220. package/node_modules/@symbion/core/dist/render/marker.d.ts +30 -0
  221. package/node_modules/@symbion/core/dist/render/marker.d.ts.map +1 -0
  222. package/node_modules/@symbion/core/dist/render/marker.js +48 -0
  223. package/node_modules/@symbion/core/dist/render/marker.js.map +1 -0
  224. package/node_modules/@symbion/core/dist/render/render.d.ts +12 -0
  225. package/node_modules/@symbion/core/dist/render/render.d.ts.map +1 -0
  226. package/node_modules/@symbion/core/dist/render/render.js +10 -0
  227. package/node_modules/@symbion/core/dist/render/render.js.map +1 -0
  228. package/node_modules/@symbion/core/dist/runcommand/render.d.ts +13 -0
  229. package/node_modules/@symbion/core/dist/runcommand/render.d.ts.map +1 -0
  230. package/node_modules/@symbion/core/dist/runcommand/render.js +19 -0
  231. package/node_modules/@symbion/core/dist/runcommand/render.js.map +1 -0
  232. package/node_modules/@symbion/core/dist/templates/authorSource.d.ts +55 -0
  233. package/node_modules/@symbion/core/dist/templates/authorSource.d.ts.map +1 -0
  234. package/node_modules/@symbion/core/dist/templates/authorSource.js +24 -0
  235. package/node_modules/@symbion/core/dist/templates/authorSource.js.map +1 -0
  236. package/node_modules/@symbion/core/dist/templates/matchAuthorFolders.d.ts +28 -0
  237. package/node_modules/@symbion/core/dist/templates/matchAuthorFolders.d.ts.map +1 -0
  238. package/node_modules/@symbion/core/dist/templates/matchAuthorFolders.js +54 -0
  239. package/node_modules/@symbion/core/dist/templates/matchAuthorFolders.js.map +1 -0
  240. package/node_modules/@symbion/core/dist/templates/parseTemplate.d.ts +42 -0
  241. package/node_modules/@symbion/core/dist/templates/parseTemplate.d.ts.map +1 -0
  242. package/node_modules/@symbion/core/dist/templates/parseTemplate.js +56 -0
  243. package/node_modules/@symbion/core/dist/templates/parseTemplate.js.map +1 -0
  244. package/node_modules/@symbion/core/dist/templates/templateListItem.d.ts +39 -0
  245. package/node_modules/@symbion/core/dist/templates/templateListItem.d.ts.map +1 -0
  246. package/node_modules/@symbion/core/dist/templates/templateListItem.js +2 -0
  247. package/node_modules/@symbion/core/dist/templates/templateListItem.js.map +1 -0
  248. package/node_modules/@symbion/core/dist/util/sha256.d.ts +9 -0
  249. package/node_modules/@symbion/core/dist/util/sha256.d.ts.map +1 -0
  250. package/node_modules/@symbion/core/dist/util/sha256.js +91 -0
  251. package/node_modules/@symbion/core/dist/util/sha256.js.map +1 -0
  252. package/node_modules/@symbion/core/dist/version/semver.d.ts +18 -0
  253. package/node_modules/@symbion/core/dist/version/semver.d.ts.map +1 -0
  254. package/node_modules/@symbion/core/dist/version/semver.js +53 -0
  255. package/node_modules/@symbion/core/dist/version/semver.js.map +1 -0
  256. package/node_modules/@symbion/core/package.json +14 -0
  257. package/node_modules/@symbion/rpc-types/dist/index.d.ts +444 -0
  258. package/node_modules/@symbion/rpc-types/dist/index.d.ts.map +1 -0
  259. package/node_modules/@symbion/rpc-types/dist/index.js +2 -0
  260. package/node_modules/@symbion/rpc-types/dist/index.js.map +1 -0
  261. package/node_modules/@symbion/rpc-types/package.json +11 -0
  262. package/node_modules/yaml/dist/cli.d.ts +8 -0
  263. package/node_modules/yaml/dist/cli.mjs +201 -0
  264. package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  265. package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  266. package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  267. package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  268. package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  269. package/node_modules/yaml/dist/compose/compose-node.js +112 -0
  270. package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  271. package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  272. package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  273. package/node_modules/yaml/dist/compose/composer.js +224 -0
  274. package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  275. package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  276. package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  277. package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  278. package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  279. package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  280. package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  281. package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  282. package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  283. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  284. package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  285. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
  286. package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  287. package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  288. package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  289. package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  290. package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  291. package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  292. package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  293. package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  294. package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  295. package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  296. package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  297. package/node_modules/yaml/dist/doc/Document.js +337 -0
  298. package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  299. package/node_modules/yaml/dist/doc/anchors.js +76 -0
  300. package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  301. package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  302. package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  303. package/node_modules/yaml/dist/doc/createNode.js +90 -0
  304. package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  305. package/node_modules/yaml/dist/doc/directives.js +178 -0
  306. package/node_modules/yaml/dist/errors.d.ts +21 -0
  307. package/node_modules/yaml/dist/errors.js +62 -0
  308. package/node_modules/yaml/dist/index.d.ts +25 -0
  309. package/node_modules/yaml/dist/index.js +50 -0
  310. package/node_modules/yaml/dist/log.d.ts +3 -0
  311. package/node_modules/yaml/dist/log.js +19 -0
  312. package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  313. package/node_modules/yaml/dist/nodes/Alias.js +118 -0
  314. package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  315. package/node_modules/yaml/dist/nodes/Collection.js +151 -0
  316. package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  317. package/node_modules/yaml/dist/nodes/Node.js +40 -0
  318. package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  319. package/node_modules/yaml/dist/nodes/Pair.js +39 -0
  320. package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  321. package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  322. package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  323. package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  324. package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  325. package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  326. package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  327. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  328. package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  329. package/node_modules/yaml/dist/nodes/identity.js +53 -0
  330. package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  331. package/node_modules/yaml/dist/nodes/toJS.js +39 -0
  332. package/node_modules/yaml/dist/options.d.ts +350 -0
  333. package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  334. package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  335. package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  336. package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  337. package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  338. package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  339. package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  340. package/node_modules/yaml/dist/parse/cst.js +112 -0
  341. package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  342. package/node_modules/yaml/dist/parse/lexer.js +723 -0
  343. package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  344. package/node_modules/yaml/dist/parse/line-counter.js +41 -0
  345. package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  346. package/node_modules/yaml/dist/parse/parser.js +980 -0
  347. package/node_modules/yaml/dist/public-api.d.ts +44 -0
  348. package/node_modules/yaml/dist/public-api.js +107 -0
  349. package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  350. package/node_modules/yaml/dist/schema/Schema.js +39 -0
  351. package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  352. package/node_modules/yaml/dist/schema/common/map.js +19 -0
  353. package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  354. package/node_modules/yaml/dist/schema/common/null.js +17 -0
  355. package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  356. package/node_modules/yaml/dist/schema/common/seq.js +19 -0
  357. package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  358. package/node_modules/yaml/dist/schema/common/string.js +16 -0
  359. package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  360. package/node_modules/yaml/dist/schema/core/bool.js +21 -0
  361. package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  362. package/node_modules/yaml/dist/schema/core/float.js +47 -0
  363. package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  364. package/node_modules/yaml/dist/schema/core/int.js +42 -0
  365. package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  366. package/node_modules/yaml/dist/schema/core/schema.js +25 -0
  367. package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  368. package/node_modules/yaml/dist/schema/json/schema.js +64 -0
  369. package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  370. package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  371. package/node_modules/yaml/dist/schema/tags.js +99 -0
  372. package/node_modules/yaml/dist/schema/types.d.ts +92 -0
  373. package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  374. package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  375. package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  376. package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  377. package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  378. package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  379. package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  380. package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  381. package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  382. package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  383. package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  384. package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  385. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  386. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  387. package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  388. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  389. package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  390. package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  391. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  392. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  393. package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  394. package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  395. package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  396. package/node_modules/yaml/dist/stringify/stringify.js +132 -0
  397. package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  398. package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  399. package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  400. package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  401. package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  402. package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  403. package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  404. package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  405. package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  406. package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  407. package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  408. package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  409. package/node_modules/yaml/dist/test-events.d.ts +4 -0
  410. package/node_modules/yaml/dist/test-events.js +134 -0
  411. package/node_modules/yaml/dist/util.d.ts +16 -0
  412. package/node_modules/yaml/dist/util.js +28 -0
  413. package/node_modules/yaml/dist/visit.d.ts +102 -0
  414. package/node_modules/yaml/dist/visit.js +236 -0
  415. package/node_modules/yaml/package.json +20 -0
  416. package/node_modules/yaml/util.js +2 -0
  417. package/package.json +39 -0
@@ -0,0 +1,694 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { accessSync, constants } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { AUTHOR_REGISTRY, computeDiff as coreComputeDiff, parseClaudeDir, renderArtifacts, renderRunCommand as coreRenderRunCommand, validateAllArtifacts, } from "@symbion/core";
5
+ import { fetchAuthorTemplatesFromGithub } from "../templates/githubFetch.js";
6
+ import { createProjectStore, loadGlobalConfig, loadProjectStore, projectStoreExists, saveGlobalConfig, saveProjectStore, } from "../store/store.js";
7
+ import { appendPublishLogEntry } from "../store/publishLog.js";
8
+ import { gitStatus as coreGitStatus } from "../git/status.js";
9
+ import { browseFolder as nativeBrowseFolder } from "../fs/folderPick.js";
10
+ import { listDir as listDirImpl, makeDir as makeDirImpl } from "../fs/listDir.js";
11
+ import { extractForeignAgentsMdContent, readAgentsMd, readClaudeDirFilemap, readTargetFiles, } from "../fs/readTargetFiles.js";
12
+ import { writeFiles } from "../fs/writeFiles.js";
13
+ import { buildBodyGenerationPrompt } from "@symbion/core";
14
+ import { getProvider, listProviderDescriptors } from "../llm/registry.js";
15
+ import { LlmError } from "../llm/types.js";
16
+ import { checkApiKeyProviderReachable, checkOllamaReachable, resolveOllamaBaseUrlForStatusCheck, } from "../llm/providerStatus.js";
17
+ import { detectHostEnvironment, getOllamaInstallInstructions } from "../llm/installInstructions.js";
18
+ import { clearProviderKey as secretsClearProviderKey, loadProvidersConfig, maskKey, ProviderNotConfiguredError, setActiveProvider as secretsSetActiveProvider, setProviderKey as secretsSetProviderKey, } from "../llm/secrets.js";
19
+ import { RpcError } from "./rpcError.js";
20
+ import { isUncPath } from "./pathStyle.js";
21
+ export { RpcError };
22
+ function randomId() {
23
+ const hex = () => Math.floor(Math.random() * 16).toString(16);
24
+ const tpl = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
25
+ return tpl.replace(/[xy]/g, (c) => c === "y" ? ((Math.floor(Math.random() * 4) + 8) % 16).toString(16) : hex());
26
+ }
27
+ function findProjectPath(projectId) {
28
+ const config = loadGlobalConfig();
29
+ const entry = config.projects.find((p) => p.id === projectId);
30
+ if (!entry) {
31
+ throw new Error(`Không tìm thấy project: ${projectId}`);
32
+ }
33
+ return entry.path;
34
+ }
35
+ /**
36
+ * Runtime guards for the LLM RPC surface (generateBody/listModels). TypeScript's
37
+ * `"agent" | "command"` / the 4-id provider unions give zero enforcement once
38
+ * JSON is parsed off the wire — an unrecognized value must fail cleanly with
39
+ * RpcError("invalid-params", ...) BEFORE reaching the prompt builder or provider
40
+ * registry, never fall through to the generic 500/internal-error catch-all (see
41
+ * docs/loops/auto-generate-body-STATE.md §13, MEDIUM finding).
42
+ */
43
+ const VALID_KINDS = new Set(["agent", "command"]);
44
+ const VALID_PROVIDER_IDS = new Set(["ollama", "openai", "anthropic", "gemini"]);
45
+ const VALID_API_KEY_PROVIDER_IDS = new Set(["openai", "anthropic", "gemini"]);
46
+ function assertValidKind(kind) {
47
+ if (typeof kind !== "string" || !VALID_KINDS.has(kind)) {
48
+ throw new RpcError("invalid-params", `Tham số "kind" không hợp lệ: phải là "agent" hoặc "command".`);
49
+ }
50
+ }
51
+ function assertValidProviderId(providerId) {
52
+ if (typeof providerId !== "string" || !VALID_PROVIDER_IDS.has(providerId)) {
53
+ throw new RpcError("invalid-params", `Tham số "providerId" không hợp lệ: phải là một trong "ollama", "openai", "anthropic", "gemini".`);
54
+ }
55
+ }
56
+ function assertValidApiKeyProviderId(providerId) {
57
+ if (typeof providerId !== "string" || !VALID_API_KEY_PROVIDER_IDS.has(providerId)) {
58
+ throw new RpcError("invalid-params", `Tham số "providerId" không hợp lệ: phải là một trong "openai", "anthropic", "gemini".`);
59
+ }
60
+ }
61
+ const PROVIDER_LABELS = {
62
+ ollama: "Ollama",
63
+ openai: "OpenAI",
64
+ anthropic: "Anthropic",
65
+ gemini: "Gemini",
66
+ };
67
+ /**
68
+ * buildProviderDescriptors — projects the daemon-internal ProvidersConfig
69
+ * (raw apiKey, never crosses the RPC boundary) into the masked
70
+ * `ProviderDescriptor[]` shape every provider-settings RPC returns. Single
71
+ * call site for this projection so `maskKey()` is applied exactly once, in
72
+ * exactly one place, never as an afterthought filter on an already-built
73
+ * response object (STATE §3.2's `listProviders` handler note + §9 security note).
74
+ */
75
+ function buildProviderDescriptors() {
76
+ const config = loadProvidersConfig();
77
+ return listProviderDescriptors().map((descriptor) => {
78
+ if (descriptor.kind === "local") {
79
+ return {
80
+ id: descriptor.id,
81
+ label: descriptor.id === "ollama" ? "Ollama" : PROVIDER_LABELS[descriptor.id],
82
+ kind: descriptor.kind,
83
+ configured: true, // ollama needs no key — always "configured" in the sense of "usable"
84
+ active: config.activeProviderId === descriptor.id,
85
+ };
86
+ }
87
+ const stored = config.providers[descriptor.id];
88
+ return {
89
+ id: descriptor.id,
90
+ label: PROVIDER_LABELS[descriptor.id],
91
+ kind: descriptor.kind,
92
+ configured: Boolean(stored),
93
+ active: config.activeProviderId === descriptor.id,
94
+ maskedKey: stored ? maskKey(stored.apiKey) : undefined,
95
+ model: stored?.model,
96
+ };
97
+ });
98
+ }
99
+ export const handlers = {
100
+ ping(_params, ctx) {
101
+ return { ok: true, version: ctx.version, port: ctx.port };
102
+ },
103
+ async browseFolder(params) {
104
+ const result = await nativeBrowseFolder(params.startPath);
105
+ if (result.cancelled || !result.path)
106
+ return { cancelled: true };
107
+ return { path: result.path };
108
+ },
109
+ validatePath(params) {
110
+ const { path } = params;
111
+ if (isUncPath(path)) {
112
+ return {
113
+ exists: false,
114
+ isDir: false,
115
+ isGitRepo: false,
116
+ hasClaudeDir: false,
117
+ hasAgentsMd: false,
118
+ writable: false,
119
+ reason: "unc-unsupported",
120
+ };
121
+ }
122
+ const exists = existsSync(path);
123
+ let isDir = false;
124
+ let writable = false;
125
+ if (exists) {
126
+ const stat = statSync(path);
127
+ isDir = stat.isDirectory();
128
+ try {
129
+ accessSync(path, constants.W_OK);
130
+ writable = true;
131
+ }
132
+ catch {
133
+ writable = false;
134
+ }
135
+ }
136
+ const isGitRepo = exists && isDir && existsSync(join(path, ".git"));
137
+ const hasClaudeDir = exists && isDir && existsSync(join(path, ".claude"));
138
+ const hasAgentsMd = exists && isDir && existsSync(join(path, "AGENTS.md"));
139
+ return { exists, isDir, isGitRepo, hasClaudeDir, hasAgentsMd, writable };
140
+ },
141
+ listDir(params) {
142
+ return listDirImpl(params.path);
143
+ },
144
+ makeDir(params) {
145
+ return makeDirImpl(params.path);
146
+ },
147
+ listProjects(_params) {
148
+ const config = loadGlobalConfig();
149
+ return { projects: config.projects };
150
+ },
151
+ createProject(params) {
152
+ const { name, path } = params;
153
+ if (!existsSync(path) || !statSync(path).isDirectory()) {
154
+ throw new RpcError("invalid-path", "Đường dẫn không tồn tại hoặc không phải thư mục.");
155
+ }
156
+ if (projectStoreExists(path)) {
157
+ throw new RpcError("already-a-project", "Thư mục này đã là một dự án Symbion.");
158
+ }
159
+ const id = randomId();
160
+ const project = createProjectStore(path, name, id);
161
+ const config = loadGlobalConfig();
162
+ config.projects.push({ id, name, path });
163
+ config.lastProjectId = id;
164
+ saveGlobalConfig(config);
165
+ return { project };
166
+ },
167
+ loadProject(params) {
168
+ const path = findProjectPath(params.id);
169
+ return { project: loadProjectStore(path) };
170
+ },
171
+ saveArtifact(params) {
172
+ const path = findProjectPath(params.projectId);
173
+ const store = loadProjectStore(path);
174
+ const idx = store.artifacts.findIndex((a) => a.id === params.artifact.id);
175
+ const now = new Date().toISOString();
176
+ const artifact = {
177
+ ...params.artifact,
178
+ meta: { ...params.artifact.meta, updatedAt: now },
179
+ };
180
+ // Server-side validation (defense in depth — never trust the client).
181
+ // Validate against the *would-be* full artifact set (siblings + this
182
+ // artifact updated/inserted) so duplicate-name etc. checks are accurate.
183
+ const candidateSiblings = store.artifacts.filter((a) => a.id !== artifact.id);
184
+ const issues = validateAllArtifacts([...candidateSiblings, artifact]);
185
+ const blocking = issues.filter((i) => i.level === "error" && i.artifactId === artifact.id);
186
+ if (blocking.length > 0) {
187
+ throw new RpcError("validation-failed", `Không thể lưu — vi phạm lint: ${blocking.map((i) => i.message).join("; ")}`);
188
+ }
189
+ if (idx >= 0) {
190
+ store.artifacts[idx] = artifact;
191
+ }
192
+ else {
193
+ store.artifacts.push(artifact);
194
+ }
195
+ saveProjectStore(path, store);
196
+ return { project: store };
197
+ },
198
+ deleteArtifact(params) {
199
+ const path = findProjectPath(params.projectId);
200
+ const store = loadProjectStore(path);
201
+ // v1: removing an artifact in Studio does NOT delete its on-disk file silently
202
+ // (STATE §7B) — this only removes it from the in-app store.
203
+ store.artifacts = store.artifacts.filter((a) => a.id !== params.artifactId);
204
+ saveProjectStore(path, store);
205
+ return { project: store };
206
+ },
207
+ updateSettings(params) {
208
+ if (params.projectId && params.settings) {
209
+ const path = findProjectPath(params.projectId);
210
+ const store = loadProjectStore(path);
211
+ store.settings = params.settings;
212
+ saveProjectStore(path, store);
213
+ return { project: store };
214
+ }
215
+ if (params.globalConfig) {
216
+ const config = loadGlobalConfig();
217
+ Object.assign(config, params.globalConfig);
218
+ saveGlobalConfig(config);
219
+ }
220
+ return {};
221
+ },
222
+ scanClaudeDir(params) {
223
+ const filemap = readClaudeDirFilemap(params.path);
224
+ const parsed = parseClaudeDir(filemap);
225
+ return { parsed };
226
+ },
227
+ importArtifacts(params) {
228
+ const path = findProjectPath(params.projectId);
229
+ const store = loadProjectStore(path);
230
+ const selected = params.scanned.filter((a) => params.selectedIds.includes(a.id));
231
+ // Server-side validation (defense in depth) over the resulting merged
232
+ // artifact set. Imported artifacts that would create blocking lint
233
+ // errors (e.g. duplicate name, missing required fields) are rejected
234
+ // wholesale rather than silently persisted invalid.
235
+ const existingOthers = store.artifacts.filter((a) => !selected.some((s) => s.id === a.id));
236
+ const merged = [...existingOthers, ...selected];
237
+ const issues = validateAllArtifacts(merged);
238
+ const selectedIds = new Set(selected.map((a) => a.id));
239
+ const blocking = issues.filter((i) => i.level === "error" && i.artifactId && selectedIds.has(i.artifactId));
240
+ if (blocking.length > 0) {
241
+ throw new RpcError("validation-failed", `Không thể nhập — vi phạm lint: ${blocking.map((i) => i.message).join("; ")}`);
242
+ }
243
+ for (const artifact of selected) {
244
+ const idx = store.artifacts.findIndex((a) => a.id === artifact.id);
245
+ if (idx >= 0) {
246
+ store.artifacts[idx] = artifact;
247
+ }
248
+ else {
249
+ store.artifacts.push(artifact);
250
+ }
251
+ }
252
+ saveProjectStore(path, store);
253
+ return { project: store };
254
+ },
255
+ /**
256
+ * applyTemplate — stages one bundled template (apps/web's static gallery)
257
+ * into a project's store as a new draft artifact, with server-side
258
+ * auto-suffix collision resolution. See packages/rpc-types's
259
+ * ApplyTemplateParams doc comment + docs/loops/templates-marketplace-STATE.md
260
+ * PLAN §0(b)/§2 for the full rationale (new RPC vs. extending
261
+ * importArtifacts; TOCTOU; never-block-never-overwrite collision policy).
262
+ *
263
+ * Defense-in-depth shape re-validation: the daemon never trusts the
264
+ * client's `template.kind`/`name`/`description` even though this content
265
+ * originates from the web app's own bundled, build-time-reviewed data
266
+ * (not arbitrary external input) — same posture as every other mutating
267
+ * handler in this file (see saveArtifact/importArtifacts comments above).
268
+ */
269
+ applyTemplate(params) {
270
+ const { projectId, template } = params;
271
+ if (!template || (template.kind !== "agent" && template.kind !== "command")) {
272
+ throw new RpcError("invalid-kind", "Chỉ Agent/Command hỗ trợ Áp dụng.");
273
+ }
274
+ if (typeof template.name !== "string" || template.name.trim().length === 0) {
275
+ throw new RpcError("invalid-template", "Template thiếu name.");
276
+ }
277
+ if (typeof template.description !== "string" || template.description.trim().length === 0) {
278
+ throw new RpcError("invalid-template", "Template thiếu description.");
279
+ }
280
+ if (typeof template.body !== "string" || template.body.trim().length === 0) {
281
+ throw new RpcError("invalid-template", "Template thiếu nội dung (body).");
282
+ }
283
+ if (typeof template.sourceTemplateId !== "string" || template.sourceTemplateId.trim().length === 0) {
284
+ throw new RpcError("invalid-template", "Template thiếu sourceTemplateId.");
285
+ }
286
+ // templates-authors PLAN §P6: server-side defense-in-depth mirror of the
287
+ // client-side license/attribution acknowledgment gate. The daemon looks
288
+ // up authorId in AUTHOR_REGISTRY itself (never trusts a client-asserted
289
+ // boolean about WHETHER the gate applies) — only an unrecognized/absent
290
+ // authorId or one whose registry entry is kind:"bundled" (Symbion) is
291
+ // treated as not-third-party, matching "never trust the client" posture.
292
+ const authorId = template.authorId ?? "symbion";
293
+ const author = AUTHOR_REGISTRY.find((a) => a.id === authorId);
294
+ // Conservative default: unknown authorId → treat as third-party (requires
295
+ // acknowledgment). A known "bundled" (Symbion) entry is the ONLY exempt case.
296
+ // This ensures "never trust the client about WHETHER the gate applies" even if a
297
+ // future registry entry is misspelled or a hand-crafted RPC sends an unrecognized id.
298
+ const isThirdParty = author === undefined || author.kind === "github";
299
+ if (isThirdParty && template.acknowledgedThirdParty !== true) {
300
+ throw new RpcError("license-not-acknowledged", "Cần xác nhận đã đọc thông báo về bản quyền nội dung của tác giả khác trước khi áp dụng.");
301
+ }
302
+ const path = findProjectPath(projectId);
303
+ const store = loadProjectStore(path); // fresh read — closes the TOCTOU gap a client-side calc would have
304
+ // Auto-suffix algorithm (THINK #4): first free "<name>", "<name>-2", "<name>-3", ...
305
+ // scoped to (kind, name) pairs, matching validate.ts's own duplicate rule
306
+ // (same kind + same name) so the suffix algorithm and the lint rule it's
307
+ // dodging stay in lockstep by construction.
308
+ const existingNames = new Set(store.artifacts.filter((a) => a.kind === template.kind).map((a) => a.name));
309
+ let finalName = template.name;
310
+ let n = 2;
311
+ while (existingNames.has(finalName)) {
312
+ finalName = `${template.name}-${n}`;
313
+ n++;
314
+ }
315
+ const wasRenamed = finalName !== template.name;
316
+ const now = new Date().toISOString();
317
+ const artifact = {
318
+ id: randomId(),
319
+ kind: template.kind,
320
+ name: finalName,
321
+ description: template.description,
322
+ tools: template.tools,
323
+ body: template.body,
324
+ meta: {
325
+ version: "draft",
326
+ status: "draft",
327
+ createdAt: now,
328
+ updatedAt: now,
329
+ sourceTemplateId: template.sourceTemplateId,
330
+ },
331
+ };
332
+ // Defense-in-depth: re-validate the FULL resulting set, same posture as
333
+ // importArtifacts/saveArtifact. Should never actually fail given the
334
+ // auto-suffix loop above already guarantees no name collision, but keeps
335
+ // the same "never trust, always re-check before persist" invariant as
336
+ // every other write path (a real safety net if e.g. FILENAME_SAFE_RE
337
+ // rejects a name with a space/slash the bundle author typo'd).
338
+ const merged = [...store.artifacts, artifact];
339
+ const issues = validateAllArtifacts(merged);
340
+ const blocking = issues.filter((i) => i.level === "error" && i.artifactId === artifact.id);
341
+ if (blocking.length > 0) {
342
+ throw new RpcError("validation-failed", `Không thể áp dụng — vi phạm lint: ${blocking.map((i) => i.message).join("; ")}`);
343
+ }
344
+ store.artifacts.push(artifact);
345
+ saveProjectStore(path, store);
346
+ return { project: store, appliedArtifactId: artifact.id, finalName, wasRenamed };
347
+ },
348
+ /**
349
+ * fetchAuthorTemplates — templates-authors v2 extension (PLAN §P2). Looks
350
+ * up `authorId` in AUTHOR_REGISTRY (packages/core) server-side — never
351
+ * trusts/reads any client-supplied owner/repo fields, even if a
352
+ * hand-crafted request sends them (PLAN §P8 SSRF finding #1(a)). An
353
+ * unknown authorId, or one resolving to a `kind: "bundled"` entry (e.g.
354
+ * "symbion" — the bundled author can't be routed through the network-fetch
355
+ * path), is a programming/client-bug error -> thrown RpcError, NOT a
356
+ * well-formed outcome. A known `kind: "github"` author always resolves
357
+ * (never throws) to a `FetchAuthorTemplatesOutcome` — every external
358
+ * failure mode (network/rate-limit/not-found/per-file/parse) is a
359
+ * well-formed, expected-to-sometimes-fail result, not a daemon bug.
360
+ */
361
+ async fetchAuthorTemplates(params) {
362
+ if (typeof params?.authorId !== "string" || params.authorId.trim().length === 0) {
363
+ throw new RpcError("invalid-author", "Thiếu authorId.");
364
+ }
365
+ const author = AUTHOR_REGISTRY.find((a) => a.id === params.authorId);
366
+ if (!author || author.kind !== "github") {
367
+ throw new RpcError("invalid-author", `authorId không hợp lệ hoặc không phải nguồn GitHub: "${params.authorId}".`);
368
+ }
369
+ const outcome = await fetchAuthorTemplatesFromGithub(author);
370
+ return { outcome };
371
+ },
372
+ render(params) {
373
+ const path = findProjectPath(params.projectId);
374
+ const store = loadProjectStore(path);
375
+ const files = [];
376
+ for (const target of params.targets) {
377
+ const existingForeignContent = target === "codex" ? extractForeignAgentsMdContent(readAgentsMd(path)) : undefined;
378
+ files.push(...renderArtifacts(store.artifacts, target, { version: params.version, existingForeignContent }));
379
+ }
380
+ return { files };
381
+ },
382
+ computeDiff(params) {
383
+ const path = findProjectPath(params.projectId);
384
+ const store = loadProjectStore(path);
385
+ const allFiles = [];
386
+ for (const target of params.targets) {
387
+ const existingForeignContent = target === "codex" ? extractForeignAgentsMdContent(readAgentsMd(path)) : undefined;
388
+ const rendered = renderArtifacts(store.artifacts, target, {
389
+ version: params.version,
390
+ existingForeignContent,
391
+ });
392
+ const mergedTargetRelPaths = target === "codex" ? new Set(rendered.map((f) => f.relPath)) : new Set();
393
+ const onDisk = readTargetFiles(path, rendered.map((f) => f.relPath), mergedTargetRelPaths);
394
+ allFiles.push(...coreComputeDiff(rendered, onDisk));
395
+ }
396
+ const conflicts = allFiles.filter((f) => f.status === "conflict").length;
397
+ return { files: allFiles, conflicts };
398
+ },
399
+ write(params) {
400
+ const path = findProjectPath(params.projectId);
401
+ const store = loadProjectStore(path);
402
+ const diffResult = handlers.computeDiff({
403
+ projectId: params.projectId,
404
+ targets: params.targets,
405
+ version: params.version,
406
+ });
407
+ const selectionByPath = new Map(params.files.map((f) => [f.relPath, f.resolution]));
408
+ const renderedByPath = new Map();
409
+ for (const target of params.targets) {
410
+ const existingForeignContent = target === "codex" ? extractForeignAgentsMdContent(readAgentsMd(path)) : undefined;
411
+ for (const file of renderArtifacts(store.artifacts, target, {
412
+ version: params.version,
413
+ existingForeignContent,
414
+ })) {
415
+ renderedByPath.set(file.relPath, file);
416
+ }
417
+ }
418
+ const tasks = [];
419
+ for (const diffFile of diffResult.files) {
420
+ if (!selectionByPath.has(diffFile.relPath))
421
+ continue; // not selected by user -> skip
422
+ const rendered = renderedByPath.get(diffFile.relPath);
423
+ if (!rendered)
424
+ continue;
425
+ // Determine which target this relPath belongs to (best-effort: Claude paths are
426
+ // .claude/...; everything else (AGENTS.md) is codex).
427
+ const target = diffFile.relPath.startsWith(".claude/") ? "claude" : "codex";
428
+ tasks.push({
429
+ target,
430
+ relPath: diffFile.relPath,
431
+ content: rendered.content,
432
+ contentHash: rendered.contentHash,
433
+ artifactId: rendered.artifactIds[0],
434
+ resolution: selectionByPath.get(diffFile.relPath),
435
+ isSame: diffFile.status === "same",
436
+ isUnresolvedConflict: diffFile.status === "conflict",
437
+ });
438
+ }
439
+ const outcome = writeFiles(tasks, {
440
+ projectRoot: path,
441
+ version: params.version,
442
+ backupBeforeWrite: store.settings.backupBeforeWrite,
443
+ });
444
+ appendPublishLogEntry(path, {
445
+ version: params.version,
446
+ timestamp: new Date().toISOString(),
447
+ targets: params.targets,
448
+ results: outcome.results,
449
+ backupDir: outcome.backupDir,
450
+ });
451
+ // update meta.publishedHashes + status for artifacts that were successfully written
452
+ for (const result of outcome.results) {
453
+ if (result.action !== "created" && result.action !== "updated")
454
+ continue;
455
+ if (!result.artifactId)
456
+ continue;
457
+ const artifact = store.artifacts.find((a) => a.id === result.artifactId);
458
+ if (!artifact)
459
+ continue;
460
+ artifact.meta.publishedHashes = {
461
+ ...artifact.meta.publishedHashes,
462
+ [result.target]: result.contentHash,
463
+ };
464
+ artifact.meta.status = "published";
465
+ artifact.meta.version = params.version;
466
+ }
467
+ saveProjectStore(path, store);
468
+ return { results: outcome.results, backupDir: outcome.backupDir, logEntryWritten: true };
469
+ },
470
+ gitStatus(params) {
471
+ return coreGitStatus(params.path);
472
+ },
473
+ renderRunCommand(params) {
474
+ return { prompt: coreRenderRunCommand(params) };
475
+ },
476
+ /**
477
+ * listModels — single source of truth for a provider's model list, so apps/web
478
+ * never hand-duplicates it (resolves STATE §10.7 Risk R1 per the user's
479
+ * amendment). For the 3 cloud providers this is still a static, hardcoded,
480
+ * zero-network-call list (unchanged, AC5). For Ollama, this now performs a real
481
+ * `GET /api/tags` network call against the local Ollama instance (per
482
+ * docs/loops/ollama-dynamic-models-STATE.md §6.2/§6.4) — bounded by a 3000ms
483
+ * timeout, never hangs indefinitely (AC6).
484
+ *
485
+ * Three resolved outcomes (never a thrown RpcError for these, since both are
486
+ * well-formed, expected facts about a reachable Ollama, not daemon bugs):
487
+ * - `{models, outcome:"ok"}` — non-empty list (cloud providers always land here).
488
+ * - `{models:[], outcome:"empty"}` — Ollama reachable, zero models pulled.
489
+ * - `{models:[], outcome:"fetch-failed", errorMessage}` — Ollama reachable but
490
+ * `/api/tags` itself failed (malformed JSON / non-2xx / missing `models` field).
491
+ *
492
+ * `provider-not-running` (Ollama unreachable) is the ONE case that still THROWS
493
+ * `RpcError("llm-provider-not-running", ...)` — unchanged shape, AC4.
494
+ */
495
+ async listModels(params) {
496
+ assertValidProviderId(params.providerId);
497
+ const provider = getProvider(params.providerId);
498
+ try {
499
+ const models = await provider.listModels();
500
+ return { models, outcome: models.length === 0 ? "empty" : "ok" };
501
+ }
502
+ catch (err) {
503
+ if (err instanceof LlmError) {
504
+ if (err.code === "provider-not-running") {
505
+ // unchanged existing path — Ollama unreachable still throws, AC4.
506
+ throw new RpcError(`llm-${err.code}`, humanMessageForLlmError(err));
507
+ }
508
+ // invalid-response (malformed JSON / non-2xx from /api/tags), or any other
509
+ // LlmError code reaching here — resolve with outcome:"fetch-failed" rather
510
+ // than throw, so the web layer can render a distinct, non-generic message.
511
+ return { models: [], outcome: "fetch-failed", errorMessage: humanMessageForLlmError(err) };
512
+ }
513
+ throw new RpcError("llm-unknown", "Lỗi không xác định khi lấy danh sách mô hình.");
514
+ }
515
+ },
516
+ /**
517
+ * generateBody — the first async, slow, externally-fallible RPC handler in the
518
+ * codebase (STATE §10.1/§10.2). Touches neither disk nor git: pure inference in,
519
+ * text out. Deliberately does NOT call findProjectPath/loadProjectStore — the
520
+ * request already carries all needed context inline (STATE §10.2).
521
+ */
522
+ async generateBody(params) {
523
+ // Runtime-validate the two "TS union, zero runtime enforcement" fields BEFORE
524
+ // touching the prompt builder or provider registry (STATE §13 MEDIUM finding) —
525
+ // an unrecognized kind/providerId must fail as a clean invalid-params RpcError,
526
+ // not a bare Error that falls through to the generic 500/internal-error path.
527
+ assertValidKind(params.kind);
528
+ assertValidProviderId(params.providerId);
529
+ // Defensive input-size cap (no daemon crash / runaway prompt on malformed/huge input —
530
+ // there is no pre-existing size-cap precedent elsewhere in the RPC surface to match,
531
+ // so this is a new, narrowly-scoped guard for this handler only).
532
+ const MAX_FIELD_LEN = 50_000;
533
+ for (const field of ["name", "description", "existingBody"]) {
534
+ const value = params[field];
535
+ if (typeof value !== "string" || value.length > MAX_FIELD_LEN) {
536
+ throw new RpcError("invalid-params", `Trường "${field}" không hợp lệ hoặc quá lớn.`);
537
+ }
538
+ }
539
+ if (typeof params.modelId !== "string" || params.modelId.length === 0 || params.modelId.length > 200) {
540
+ throw new RpcError("invalid-params", "modelId không hợp lệ.");
541
+ }
542
+ const { system, user } = buildBodyGenerationPrompt({
543
+ kind: params.kind,
544
+ name: params.name,
545
+ description: params.description,
546
+ existingBody: params.existingBody,
547
+ });
548
+ try {
549
+ // getProvider/the provider constructor can itself throw an LlmError (e.g. an
550
+ // env-var-sourced Ollama base URL that fails the loopback check — STATE §13 HIGH
551
+ // finding) — kept inside this try so any LlmError, whether thrown at construction
552
+ // time or during generate(), maps through the same clean RpcError taxonomy below
553
+ // instead of leaking via the generic 500/internal-error path.
554
+ const provider = getProvider(params.providerId);
555
+ const result = await provider.generate({
556
+ systemPrompt: system,
557
+ userPrompt: user,
558
+ model: params.modelId,
559
+ timeoutMs: 45_000,
560
+ });
561
+ return { body: result.text };
562
+ }
563
+ catch (err) {
564
+ if (err instanceof LlmError) {
565
+ throw new RpcError(`llm-${err.code}`, humanMessageForLlmError(err));
566
+ }
567
+ throw new RpcError("llm-unknown", "Lỗi không xác định khi gọi mô hình AI.");
568
+ }
569
+ },
570
+ /**
571
+ * checkProviderStatus — read-only liveness/auth check, widened per
572
+ * docs/loops/multi-provider-settings-STATE.md §3.2/§4b from the literal
573
+ * "ollama" to the 4-id union. Ollama keeps its exact existing path
574
+ * (checkOllamaReachable, unchanged). The 3 api-key providers: first check
575
+ * secrets.ts has a stored key (if not, short-circuit to
576
+ * { reachable:false, errorCode:"not-configured" } with ZERO network calls —
577
+ * never attempt a guaranteed-auth-failure round-trip); if a key exists,
578
+ * construct the provider (reads its own key internally) and perform ONE
579
+ * cheap authenticated call via checkApiKeyProviderReachable. Never throws
580
+ * on "not reachable" — that is a valid resolved result, not a server error.
581
+ */
582
+ async checkProviderStatus(params) {
583
+ assertValidProviderId(params?.providerId);
584
+ const { providerId } = params;
585
+ if (providerId === "ollama") {
586
+ const baseUrl = resolveOllamaBaseUrlForStatusCheck();
587
+ const reachable = await checkOllamaReachable(baseUrl, 3000);
588
+ const install = getOllamaInstallInstructions(detectHostEnvironment());
589
+ return { reachable, checkedBaseUrl: baseUrl, install, kind: "local" };
590
+ }
591
+ const config = loadProvidersConfig();
592
+ const hasKey = Boolean(config.providers[providerId]);
593
+ if (!hasKey) {
594
+ return { reachable: false, errorCode: "not-configured", kind: "api-key" };
595
+ }
596
+ const provider = getProvider(providerId);
597
+ const result = await checkApiKeyProviderReachable(provider, 3000);
598
+ return { reachable: result.reachable, errorCode: result.errorCode, kind: "api-key" };
599
+ },
600
+ /**
601
+ * listProviders — returns all 4 providers' static descriptor + current
602
+ * persisted state (masked key, model, configured/active) in one call,
603
+ * backing the Settings page's initial render and useActiveProvider()'s
604
+ * one-call-per-mount resolution (STATE §3.2/§4a/§4d).
605
+ */
606
+ listProviders(_params) {
607
+ return { providers: buildProviderDescriptors() };
608
+ },
609
+ /**
610
+ * saveProviderKey — validates providerId against the 3 api-key ids (ollama
611
+ * never has a stored key) and apiKey under a size cap (mirrors
612
+ * generateBody's MAX_FIELD_LEN pattern), then upserts via secrets.ts.
613
+ * Returns the masked descriptors — apiKey is NEVER serialized raw.
614
+ */
615
+ saveProviderKey(params) {
616
+ const providerIdRaw = params?.providerId;
617
+ assertValidApiKeyProviderId(providerIdRaw);
618
+ const providerId = providerIdRaw;
619
+ const model = params.model;
620
+ const MAX_API_KEY_LEN = 4000;
621
+ const apiKey = params.apiKey;
622
+ if (typeof apiKey !== "string" || apiKey.trim().length === 0 || apiKey.length > MAX_API_KEY_LEN) {
623
+ throw new RpcError("invalid-params", `Tham số "apiKey" không hợp lệ hoặc quá lớn.`);
624
+ }
625
+ if (model !== undefined && (typeof model !== "string" || model.length > 200)) {
626
+ throw new RpcError("invalid-params", `Tham số "model" không hợp lệ.`);
627
+ }
628
+ secretsSetProviderKey(providerId, apiKey, model ?? "");
629
+ return { providers: buildProviderDescriptors() };
630
+ },
631
+ /** clearProviderKey — removes one provider's stored key/model. If it was active,
632
+ * activeProviderId resets to null (no automatic fallback to ollama). */
633
+ clearProviderKey(params) {
634
+ const providerIdRaw = params?.providerId;
635
+ assertValidApiKeyProviderId(providerIdRaw);
636
+ const providerId = providerIdRaw;
637
+ secretsClearProviderKey(providerId);
638
+ return { providers: buildProviderDescriptors() };
639
+ },
640
+ /** setActiveProvider — rejects (invalid-params) if the target api-key provider has no
641
+ * stored key; ollama always succeeds (needs none). Never a silent no-op. */
642
+ setActiveProvider(params) {
643
+ assertValidProviderId(params?.providerId);
644
+ try {
645
+ secretsSetActiveProvider(params.providerId);
646
+ }
647
+ catch (err) {
648
+ if (err instanceof ProviderNotConfiguredError) {
649
+ throw new RpcError("invalid-params", "Chưa cấu hình API key cho nhà cung cấp này.");
650
+ }
651
+ throw err;
652
+ }
653
+ return { providers: buildProviderDescriptors() };
654
+ },
655
+ };
656
+ /**
657
+ * EC-4's exact error-code -> human-readable-Vietnamese-message taxonomy (STATE §10.5).
658
+ *
659
+ * Per-code fallback strings are used when `err.message` is empty, or for codes
660
+ * ("provider-not-running" / "timeout" / "auth" / "rate-limit" / "not-configured")
661
+ * whose throw sites across all 4 provider adapters (ollamaProvider.ts,
662
+ * openaiProvider.ts, anthropicProvider.ts, geminiProvider.ts) already construct a
663
+ * message that says exactly what the fallback says (provider name aside) — no extra
664
+ * detail to preserve there.
665
+ *
666
+ * For "invalid-response" and "network", the throw sites DO carry extra,
667
+ * user-relevant detail the generic fallback would otherwise discard (e.g. a 404
668
+ * "model not pulled" message naming the missing model) — confirmed root cause of
669
+ * the Generate Body 404 loop (docs/learnings.md). For those codes (and "unknown"),
670
+ * prefer the original `err.message` when present.
671
+ */
672
+ function humanMessageForLlmError(err) {
673
+ const code = err.code;
674
+ switch (code) {
675
+ case "provider-not-running":
676
+ return "Không thể kết nối tới Ollama — đảm bảo Ollama đang chạy trên máy.";
677
+ case "timeout":
678
+ return "Quá thời gian chờ (45s) — thử lại.";
679
+ case "auth":
680
+ return "Thiếu hoặc sai cấu hình API key cho nhà cung cấp AI.";
681
+ case "rate-limit":
682
+ return "Bị giới hạn tần suất gọi — thử lại sau.";
683
+ case "not-configured":
684
+ return "Chưa cấu hình nhà cung cấp AI nào — vào Cài đặt để thêm.";
685
+ case "invalid-response":
686
+ return err.message || "Phản hồi không hợp lệ từ mô hình.";
687
+ case "network":
688
+ case "unknown":
689
+ default:
690
+ return err.message || "Lỗi không xác định, thử lại.";
691
+ }
692
+ }
693
+ export { validateAllArtifacts };
694
+ //# sourceMappingURL=handlers.js.map