@poncho-ai/cli 0.2.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 (516) hide show
  1. package/.turbo/turbo-build.log +19 -0
  2. package/.turbo/turbo-test.log +389 -0
  3. package/CHANGELOG.md +17 -0
  4. package/LICENSE +21 -0
  5. package/dist/chunk-22OMLQUR.js +1249 -0
  6. package/dist/chunk-24JFN5RM.js +1887 -0
  7. package/dist/chunk-24TAT3US.js +2137 -0
  8. package/dist/chunk-26YBLT7G.js +997 -0
  9. package/dist/chunk-2EJIC6UW.js +1893 -0
  10. package/dist/chunk-2JNCF37R.js +1156 -0
  11. package/dist/chunk-2LVMUHJX.js +1874 -0
  12. package/dist/chunk-2OVSD65B.js +1269 -0
  13. package/dist/chunk-2RQ45LI6.js +1251 -0
  14. package/dist/chunk-2SMIRDLI.js +1854 -0
  15. package/dist/chunk-2UXPHBFI.js +1862 -0
  16. package/dist/chunk-2VFM7SSZ.js +1135 -0
  17. package/dist/chunk-2ZAUADNG.js +1456 -0
  18. package/dist/chunk-2ZNUT5WA.js +1862 -0
  19. package/dist/chunk-33ZQ7WTP.js +1834 -0
  20. package/dist/chunk-34ARQX3O.js +1156 -0
  21. package/dist/chunk-3BEWSRFW.js +1893 -0
  22. package/dist/chunk-3DVE5AG6.js +1862 -0
  23. package/dist/chunk-3KE6MHO6.js +1608 -0
  24. package/dist/chunk-3MOLPB7Z.js +997 -0
  25. package/dist/chunk-3OZZOYAZ.js +1884 -0
  26. package/dist/chunk-3VJYNZEF.js +2181 -0
  27. package/dist/chunk-3W27LOUH.js +997 -0
  28. package/dist/chunk-3WMAW74D.js +1163 -0
  29. package/dist/chunk-3Z4AHBPF.js +1569 -0
  30. package/dist/chunk-43NK6MB4.js +1977 -0
  31. package/dist/chunk-4E5M2IGA.js +1300 -0
  32. package/dist/chunk-4FVI4LVI.js +1862 -0
  33. package/dist/chunk-4GNQQJUP.js +1156 -0
  34. package/dist/chunk-4PGZFTVC.js +1234 -0
  35. package/dist/chunk-4QE2HDNC.js +1355 -0
  36. package/dist/chunk-4S2EL4ED.js +1135 -0
  37. package/dist/chunk-536SSOJ3.js +1797 -0
  38. package/dist/chunk-5CNEGIC5.js +997 -0
  39. package/dist/chunk-5CWN43YL.js +1147 -0
  40. package/dist/chunk-5HZCYTUZ.js +997 -0
  41. package/dist/chunk-5ICNG6RX.js +1885 -0
  42. package/dist/chunk-5OUIRXMN.js +997 -0
  43. package/dist/chunk-5T34JOWH.js +1460 -0
  44. package/dist/chunk-5XBAIQX3.js +1862 -0
  45. package/dist/chunk-65AIX3CS.js +1441 -0
  46. package/dist/chunk-67NBW4NG.js +1355 -0
  47. package/dist/chunk-6AFIL35M.js +1414 -0
  48. package/dist/chunk-6B3XMBKA.js +1716 -0
  49. package/dist/chunk-6CEJO4OM.js +1242 -0
  50. package/dist/chunk-6DQZUP3B.js +1460 -0
  51. package/dist/chunk-6ET624OE.js +1441 -0
  52. package/dist/chunk-6I7WFMAU.js +1862 -0
  53. package/dist/chunk-6MOKAYCL.js +1449 -0
  54. package/dist/chunk-6RFUALWB.js +1845 -0
  55. package/dist/chunk-73E57JUS.js +1231 -0
  56. package/dist/chunk-73SU7GT4.js +816 -0
  57. package/dist/chunk-74IRETUF.js +997 -0
  58. package/dist/chunk-77BYFMUN.js +1924 -0
  59. package/dist/chunk-7DAC2XE5.js +1460 -0
  60. package/dist/chunk-7GBQ4YSB.js +1024 -0
  61. package/dist/chunk-7TOJGUQ5.js +1803 -0
  62. package/dist/chunk-7W7KPLEG.js +1163 -0
  63. package/dist/chunk-7Y7ZXEN2.js +817 -0
  64. package/dist/chunk-A5WKH7H2.js +852 -0
  65. package/dist/chunk-A775UYQB.js +1886 -0
  66. package/dist/chunk-AC4OGTSK.js +1313 -0
  67. package/dist/chunk-ACCRUQ6J.js +1271 -0
  68. package/dist/chunk-AEAZZFTT.js +1886 -0
  69. package/dist/chunk-AIAC5Z55.js +1147 -0
  70. package/dist/chunk-AN34PI2R.js +1238 -0
  71. package/dist/chunk-APIA7MHJ.js +1355 -0
  72. package/dist/chunk-AQGIIT7R.js +1347 -0
  73. package/dist/chunk-ATXKV2NH.js +2111 -0
  74. package/dist/chunk-AVBKQZYR.js +1010 -0
  75. package/dist/chunk-AWIXDCZF.js +1329 -0
  76. package/dist/chunk-AXFHQBKT.js +2128 -0
  77. package/dist/chunk-AYDSTU4P.js +1156 -0
  78. package/dist/chunk-AZ35PK7E.js +1271 -0
  79. package/dist/chunk-BE6HB4IO.js +2155 -0
  80. package/dist/chunk-BIX2FI3S.js +1625 -0
  81. package/dist/chunk-BPPM5YPG.js +997 -0
  82. package/dist/chunk-BRCIVYKE.js +1420 -0
  83. package/dist/chunk-BRK2KKTF.js +1236 -0
  84. package/dist/chunk-BU7R2TVT.js +1862 -0
  85. package/dist/chunk-BXJQ4G5F.js +1901 -0
  86. package/dist/chunk-C3KTCROR.js +1128 -0
  87. package/dist/chunk-C42IGDJW.js +1032 -0
  88. package/dist/chunk-CBRPO2FE.js +1886 -0
  89. package/dist/chunk-CDNITKC6.js +1163 -0
  90. package/dist/chunk-CDVWUDFM.js +1389 -0
  91. package/dist/chunk-CH2IE453.js +1147 -0
  92. package/dist/chunk-CIHC46FS.js +1010 -0
  93. package/dist/chunk-CIYO754K.js +1687 -0
  94. package/dist/chunk-CJFNJ7U3.js +918 -0
  95. package/dist/chunk-CJN66CJY.js +1024 -0
  96. package/dist/chunk-CLJFTDJQ.js +1667 -0
  97. package/dist/chunk-CLNCOQNI.js +997 -0
  98. package/dist/chunk-CN4AUQL4.js +1460 -0
  99. package/dist/chunk-CQYGUBY6.js +1854 -0
  100. package/dist/chunk-CRJUMKVB.js +1862 -0
  101. package/dist/chunk-CZHUYI2J.js +997 -0
  102. package/dist/chunk-DIBSIWSR.js +1256 -0
  103. package/dist/chunk-DJGC3R4O.js +1836 -0
  104. package/dist/chunk-DJR2PEAQ.js +1884 -0
  105. package/dist/chunk-DKE7NWBK.js +1862 -0
  106. package/dist/chunk-DXYDN2OS.js +1147 -0
  107. package/dist/chunk-DZ3FEUJ7.js +1147 -0
  108. package/dist/chunk-EC47SFY3.js +1113 -0
  109. package/dist/chunk-ECAALEAK.js +1239 -0
  110. package/dist/chunk-ECEYIAQZ.js +997 -0
  111. package/dist/chunk-EKX7AV7O.js +1024 -0
  112. package/dist/chunk-EN6CTYUN.js +634 -0
  113. package/dist/chunk-EXCH47WX.js +1460 -0
  114. package/dist/chunk-EY2JOCTM.js +1862 -0
  115. package/dist/chunk-EYHB3LTH.js +1818 -0
  116. package/dist/chunk-F2AC5PKU.js +1446 -0
  117. package/dist/chunk-F5RCUJ62.js +1156 -0
  118. package/dist/chunk-F6OM65VA.js +1460 -0
  119. package/dist/chunk-FAEJ5CQU.js +997 -0
  120. package/dist/chunk-FB7X4KBF.js +1460 -0
  121. package/dist/chunk-FBSEEW3H.js +1862 -0
  122. package/dist/chunk-FBYY3TE5.js +1862 -0
  123. package/dist/chunk-FEA3GBGG.js +997 -0
  124. package/dist/chunk-FHPRGTOJ.js +1131 -0
  125. package/dist/chunk-FLAY6YWY.js +1389 -0
  126. package/dist/chunk-FNXIVJ3B.js +997 -0
  127. package/dist/chunk-FWRVG7RM.js +2160 -0
  128. package/dist/chunk-G47UW452.js +916 -0
  129. package/dist/chunk-G6V5O5AV.js +997 -0
  130. package/dist/chunk-GACQBIOO.js +1613 -0
  131. package/dist/chunk-GBFHLBWT.js +881 -0
  132. package/dist/chunk-GLJLTQMZ.js +997 -0
  133. package/dist/chunk-GN7DDBAT.js +1872 -0
  134. package/dist/chunk-GPTI42MM.js +1355 -0
  135. package/dist/chunk-GPXGCPVY.js +1834 -0
  136. package/dist/chunk-GRASQSCU.js +1886 -0
  137. package/dist/chunk-GU2WWG5C.js +1314 -0
  138. package/dist/chunk-GW3SAYT3.js +1679 -0
  139. package/dist/chunk-GZ4F2VI5.js +1447 -0
  140. package/dist/chunk-GZYXND4U.js +1322 -0
  141. package/dist/chunk-H27BRPVI.js +1862 -0
  142. package/dist/chunk-H4JRTOW7.js +1862 -0
  143. package/dist/chunk-HDS72SRU.js +1138 -0
  144. package/dist/chunk-HEUGSUL5.js +757 -0
  145. package/dist/chunk-HMZN5GPS.js +1024 -0
  146. package/dist/chunk-HN5SVGQO.js +1163 -0
  147. package/dist/chunk-HN6VQ5FI.js +242 -0
  148. package/dist/chunk-HNTQ66EL.js +2054 -0
  149. package/dist/chunk-HSDL3YK5.js +1134 -0
  150. package/dist/chunk-HVMIMERW.js +997 -0
  151. package/dist/chunk-HVWCQS2B.js +1834 -0
  152. package/dist/chunk-HVYMSOXQ.js +2156 -0
  153. package/dist/chunk-HYQITTK3.js +1862 -0
  154. package/dist/chunk-I4CCYPAI.js +1239 -0
  155. package/dist/chunk-IDG3X4UL.js +1229 -0
  156. package/dist/chunk-IDVRTQJ3.js +1514 -0
  157. package/dist/chunk-IEER23NN.js +1862 -0
  158. package/dist/chunk-IKLRYA4W.js +785 -0
  159. package/dist/chunk-IQBUSFBY.js +1270 -0
  160. package/dist/chunk-IUXQDZIR.js +1862 -0
  161. package/dist/chunk-IV74RJFV.js +1862 -0
  162. package/dist/chunk-IVEMIXXO.js +1854 -0
  163. package/dist/chunk-J4PNCGSP.js +1460 -0
  164. package/dist/chunk-J7ULLJUI.js +1862 -0
  165. package/dist/chunk-J7WHTBOM.js +983 -0
  166. package/dist/chunk-JBN6D7EG.js +1757 -0
  167. package/dist/chunk-JDKSD54C.js +1366 -0
  168. package/dist/chunk-JGWTOS7A.js +1507 -0
  169. package/dist/chunk-JHJ6FMSI.js +1804 -0
  170. package/dist/chunk-JJSHCP32.js +1282 -0
  171. package/dist/chunk-JLMAMC3V.js +1625 -0
  172. package/dist/chunk-JMTF7VV5.js +1919 -0
  173. package/dist/chunk-JO56GKTV.js +1133 -0
  174. package/dist/chunk-JRN3P6CS.js +1441 -0
  175. package/dist/chunk-JTKPRRSM.js +1024 -0
  176. package/dist/chunk-JVTFCTGO.js +1868 -0
  177. package/dist/chunk-JXH452LK.js +956 -0
  178. package/dist/chunk-K4SW5SP4.js +1147 -0
  179. package/dist/chunk-KANVHOQK.js +1880 -0
  180. package/dist/chunk-KBJZJWPZ.js +1143 -0
  181. package/dist/chunk-KFC4ZVRH.js +1798 -0
  182. package/dist/chunk-KHG6MSLS.js +1885 -0
  183. package/dist/chunk-KJJE6V5N.js +1886 -0
  184. package/dist/chunk-KKLEILZP.js +1868 -0
  185. package/dist/chunk-KW5QXXEN.js +1641 -0
  186. package/dist/chunk-KWMTK4N7.js +1147 -0
  187. package/dist/chunk-KYOW6LIV.js +1231 -0
  188. package/dist/chunk-KYWIUH3M.js +1355 -0
  189. package/dist/chunk-KZEA3HJL.js +1833 -0
  190. package/dist/chunk-L3KONBJE.js +1355 -0
  191. package/dist/chunk-L47B3OMM.js +1156 -0
  192. package/dist/chunk-LCQFWI6S.js +997 -0
  193. package/dist/chunk-LFIUZUI5.js +1138 -0
  194. package/dist/chunk-LHSLPQR4.js +1854 -0
  195. package/dist/chunk-LJGVAOFP.js +647 -0
  196. package/dist/chunk-LKJDYQPA.js +1687 -0
  197. package/dist/chunk-LOY6PWTR.js +1336 -0
  198. package/dist/chunk-LPFN3GNV.js +1147 -0
  199. package/dist/chunk-LPM7AN7S.js +1147 -0
  200. package/dist/chunk-LU6ES63L.js +1249 -0
  201. package/dist/chunk-M73DE7AU.js +1389 -0
  202. package/dist/chunk-M7OJ52WK.js +1448 -0
  203. package/dist/chunk-MCSM3DAE.js +1024 -0
  204. package/dist/chunk-MEP7OYUL.js +1417 -0
  205. package/dist/chunk-MFH6MVWX.js +1441 -0
  206. package/dist/chunk-MIHU3TFJ.js +1156 -0
  207. package/dist/chunk-MIU5FMSV.js +1329 -0
  208. package/dist/chunk-MJQMHH7Z.js +1976 -0
  209. package/dist/chunk-MLR2HUUY.js +1255 -0
  210. package/dist/chunk-MSBZHMUV.js +997 -0
  211. package/dist/chunk-MV4DZQRB.js +1163 -0
  212. package/dist/chunk-MWBLZDYK.js +1854 -0
  213. package/dist/chunk-N2MEPDSA.js +675 -0
  214. package/dist/chunk-N36ATUZM.js +1863 -0
  215. package/dist/chunk-NEHLM4WN.js +1610 -0
  216. package/dist/chunk-NHOJZ7FZ.js +1138 -0
  217. package/dist/chunk-NLPQBHHH.js +1282 -0
  218. package/dist/chunk-NMY3FWV7.js +1236 -0
  219. package/dist/chunk-NN2WDNCO.js +1138 -0
  220. package/dist/chunk-NNC7LH2Y.js +1258 -0
  221. package/dist/chunk-NQRWXPJ5.js +1275 -0
  222. package/dist/chunk-NR3G3D6Q.js +1238 -0
  223. package/dist/chunk-NRUAFOL3.js +2121 -0
  224. package/dist/chunk-NSCG7F6H.js +1862 -0
  225. package/dist/chunk-NXHVG7ZI.js +1113 -0
  226. package/dist/chunk-NYKPTBXA.js +1258 -0
  227. package/dist/chunk-O4AE4MFX.js +920 -0
  228. package/dist/chunk-O7GTMG3C.js +1467 -0
  229. package/dist/chunk-OBUP5UIM.js +997 -0
  230. package/dist/chunk-ONI2DTTL.js +1156 -0
  231. package/dist/chunk-OQHLTSVD.js +1776 -0
  232. package/dist/chunk-OVV6SHTA.js +997 -0
  233. package/dist/chunk-PAPAMVNI.js +1156 -0
  234. package/dist/chunk-PH7OXFMJ.js +997 -0
  235. package/dist/chunk-PHFLPSZU.js +1608 -0
  236. package/dist/chunk-PTVSK5DV.js +1854 -0
  237. package/dist/chunk-PUHWX6PD.js +1156 -0
  238. package/dist/chunk-PYDU2HN2.js +1803 -0
  239. package/dist/chunk-Q2AMIXBY.js +1250 -0
  240. package/dist/chunk-Q2EARVB7.js +1414 -0
  241. package/dist/chunk-Q4HFSYSN.js +1024 -0
  242. package/dist/chunk-Q65PNALY.js +1024 -0
  243. package/dist/chunk-QBQNHCYH.js +1791 -0
  244. package/dist/chunk-QGI55HK3.js +1433 -0
  245. package/dist/chunk-QIAODEAT.js +1862 -0
  246. package/dist/chunk-QLRJ2X3B.js +1800 -0
  247. package/dist/chunk-QTLVBIBL.js +1147 -0
  248. package/dist/chunk-QUPLQ7O4.js +1862 -0
  249. package/dist/chunk-QZGUSWLN.js +1415 -0
  250. package/dist/chunk-R7N3T7YR.js +1130 -0
  251. package/dist/chunk-RFS3GC46.js +239 -0
  252. package/dist/chunk-RJA7HIQO.js +1823 -0
  253. package/dist/chunk-RJLU3F7G.js +1156 -0
  254. package/dist/chunk-RLBXW5AY.js +1156 -0
  255. package/dist/chunk-RMKHLIMU.js +1147 -0
  256. package/dist/chunk-RS7F3BLO.js +1255 -0
  257. package/dist/chunk-RYLDHQQT.js +997 -0
  258. package/dist/chunk-RYYTEAQ7.js +1147 -0
  259. package/dist/chunk-S2KNKYQJ.js +1815 -0
  260. package/dist/chunk-S5R5IZJH.js +2056 -0
  261. package/dist/chunk-S5S7OBDZ.js +1355 -0
  262. package/dist/chunk-S6YKNJQG.js +1868 -0
  263. package/dist/chunk-SBDVWSWM.js +1251 -0
  264. package/dist/chunk-SBXSREFV.js +1237 -0
  265. package/dist/chunk-SDZJV47M.js +1238 -0
  266. package/dist/chunk-SMBILO75.js +1024 -0
  267. package/dist/chunk-SUSLSP3P.js +1456 -0
  268. package/dist/chunk-T4GPZ2AG.js +1128 -0
  269. package/dist/chunk-TA7EDJXT.js +1460 -0
  270. package/dist/chunk-TAW2ISST.js +1024 -0
  271. package/dist/chunk-TB6KKWS2.js +1138 -0
  272. package/dist/chunk-TBZCEX5O.js +1355 -0
  273. package/dist/chunk-TDOPKFNW.js +756 -0
  274. package/dist/chunk-TGY3JSDQ.js +1460 -0
  275. package/dist/chunk-THOIGUSY.js +666 -0
  276. package/dist/chunk-TLSGQKLO.js +1836 -0
  277. package/dist/chunk-TQ2QEU3G.js +1460 -0
  278. package/dist/chunk-TRJODOZM.js +1232 -0
  279. package/dist/chunk-TSBMRYLQ.js +1717 -0
  280. package/dist/chunk-TUL3R6KB.js +1024 -0
  281. package/dist/chunk-TWCD6YPP.js +2129 -0
  282. package/dist/chunk-TWQDGVLI.js +1323 -0
  283. package/dist/chunk-TZQLWQTW.js +769 -0
  284. package/dist/chunk-U22K555L.js +1803 -0
  285. package/dist/chunk-U3VXLQTW.js +1707 -0
  286. package/dist/chunk-U5QM4SRB.js +2054 -0
  287. package/dist/chunk-UCZLOOAW.js +997 -0
  288. package/dist/chunk-UDA2OZLK.js +1242 -0
  289. package/dist/chunk-UDASJ4IC.js +1355 -0
  290. package/dist/chunk-UGU2KSOQ.js +1113 -0
  291. package/dist/chunk-UJHB3CLA.js +1130 -0
  292. package/dist/chunk-UNUTAECX.js +1238 -0
  293. package/dist/chunk-UUUJVWXA.js +1806 -0
  294. package/dist/chunk-UV4WM7Q5.js +2039 -0
  295. package/dist/chunk-UXPGPOQ3.js +2113 -0
  296. package/dist/chunk-UYVWNYFB.js +1434 -0
  297. package/dist/chunk-UYWI4MPU.js +1460 -0
  298. package/dist/chunk-V2FNBN3P.js +997 -0
  299. package/dist/chunk-V6CF5XXG.js +1862 -0
  300. package/dist/chunk-V6UUV2SZ.js +1156 -0
  301. package/dist/chunk-VARTDMWQ.js +1862 -0
  302. package/dist/chunk-VC7ZYKMP.js +1156 -0
  303. package/dist/chunk-VCJNX77B.js +2038 -0
  304. package/dist/chunk-VDE2I72J.js +650 -0
  305. package/dist/chunk-VEO7FKEL.js +1156 -0
  306. package/dist/chunk-VIJYIU7E.js +2124 -0
  307. package/dist/chunk-VJX4WETG.js +1136 -0
  308. package/dist/chunk-VO3QDFU2.js +1276 -0
  309. package/dist/chunk-VOX2Q2V2.js +1933 -0
  310. package/dist/chunk-W7J5XM2X.js +1862 -0
  311. package/dist/chunk-WONM6P4N.js +1862 -0
  312. package/dist/chunk-WW576PYD.js +1862 -0
  313. package/dist/chunk-XCZCCA2D.js +997 -0
  314. package/dist/chunk-XHQOG4X6.js +1871 -0
  315. package/dist/chunk-XIYLHBWA.js +1163 -0
  316. package/dist/chunk-XKZ6XWSE.js +1907 -0
  317. package/dist/chunk-XLHKOBSF.js +1815 -0
  318. package/dist/chunk-XMMFUBB5.js +1270 -0
  319. package/dist/chunk-XQLK777K.js +1442 -0
  320. package/dist/chunk-XRN47M65.js +997 -0
  321. package/dist/chunk-XVBKUEXA.js +1441 -0
  322. package/dist/chunk-XY4ISIAV.js +1639 -0
  323. package/dist/chunk-Y2SOII6F.js +1156 -0
  324. package/dist/chunk-Y5TJU6YZ.js +1163 -0
  325. package/dist/chunk-YBPCMSUU.js +1147 -0
  326. package/dist/chunk-YDAZ3YZT.js +1004 -0
  327. package/dist/chunk-YH2QPUWO.js +1621 -0
  328. package/dist/chunk-YJX4O5CY.js +1355 -0
  329. package/dist/chunk-YNJMS3VK.js +997 -0
  330. package/dist/chunk-YNRZMOC3.js +997 -0
  331. package/dist/chunk-YNUF5JNP.js +1163 -0
  332. package/dist/chunk-YO7TJ6SG.js +2135 -0
  333. package/dist/chunk-YTUUFYVS.js +1842 -0
  334. package/dist/chunk-YXCOG54V.js +997 -0
  335. package/dist/chunk-Z7V254BA.js +1432 -0
  336. package/dist/chunk-ZBHRR3RS.js +1256 -0
  337. package/dist/chunk-ZM47X5PT.js +1236 -0
  338. package/dist/chunk-ZO6JUCLC.js +917 -0
  339. package/dist/chunk-ZOF4ERNI.js +2039 -0
  340. package/dist/chunk-ZOTRZN3T.js +1238 -0
  341. package/dist/chunk-ZPBA4JGE.js +1234 -0
  342. package/dist/chunk-ZTKGRHNV.js +1138 -0
  343. package/dist/chunk-ZW2JM2OY.js +997 -0
  344. package/dist/chunk-ZXYHUC7C.js +1722 -0
  345. package/dist/cli.d.ts +1 -0
  346. package/dist/cli.js +8 -0
  347. package/dist/index.d.ts +47 -0
  348. package/dist/index.js +37 -0
  349. package/dist/run-interactive-ink-2CDKFV6C.js +783 -0
  350. package/dist/run-interactive-ink-2JULLCIS.js +461 -0
  351. package/dist/run-interactive-ink-2KIHEGXT.js +451 -0
  352. package/dist/run-interactive-ink-2LX2NZRL.js +737 -0
  353. package/dist/run-interactive-ink-2OH6AV3C.js +756 -0
  354. package/dist/run-interactive-ink-2PLJ5XST.js +423 -0
  355. package/dist/run-interactive-ink-2ZI75VMK.js +462 -0
  356. package/dist/run-interactive-ink-3BHGPZ4B.js +423 -0
  357. package/dist/run-interactive-ink-3IUV3456.js +777 -0
  358. package/dist/run-interactive-ink-3QZK5PWY.js +168 -0
  359. package/dist/run-interactive-ink-3VLL4FNN.js +423 -0
  360. package/dist/run-interactive-ink-47Y2KAFZ.js +668 -0
  361. package/dist/run-interactive-ink-4CBTS636.js +423 -0
  362. package/dist/run-interactive-ink-4CHDJRAK.js +423 -0
  363. package/dist/run-interactive-ink-4E6GM5ST.js +423 -0
  364. package/dist/run-interactive-ink-4EKHIHGU.js +462 -0
  365. package/dist/run-interactive-ink-4NO7O233.js +744 -0
  366. package/dist/run-interactive-ink-55IZU2EZ.js +741 -0
  367. package/dist/run-interactive-ink-5A7BER6J.js +423 -0
  368. package/dist/run-interactive-ink-5NEFKF3R.js +423 -0
  369. package/dist/run-interactive-ink-5TCBH3Z4.js +462 -0
  370. package/dist/run-interactive-ink-5WOLWMGH.js +747 -0
  371. package/dist/run-interactive-ink-66JFIG2P.js +462 -0
  372. package/dist/run-interactive-ink-6R77DKEV.js +744 -0
  373. package/dist/run-interactive-ink-7B6HI7XT.js +679 -0
  374. package/dist/run-interactive-ink-7ICZH4E3.js +423 -0
  375. package/dist/run-interactive-ink-7LWBJYQE.js +423 -0
  376. package/dist/run-interactive-ink-7Y7MVKPA.js +438 -0
  377. package/dist/run-interactive-ink-A264MR35.js +423 -0
  378. package/dist/run-interactive-ink-A3NCKFFM.js +423 -0
  379. package/dist/run-interactive-ink-A4FBMTZ5.js +563 -0
  380. package/dist/run-interactive-ink-A7YPXRXR.js +462 -0
  381. package/dist/run-interactive-ink-AAER2EXR.js +451 -0
  382. package/dist/run-interactive-ink-ADVQJ2GF.js +423 -0
  383. package/dist/run-interactive-ink-ALV34HZF.js +451 -0
  384. package/dist/run-interactive-ink-ARDK3CO6.js +462 -0
  385. package/dist/run-interactive-ink-AVMVDBQK.js +462 -0
  386. package/dist/run-interactive-ink-AWV7ZOTC.js +423 -0
  387. package/dist/run-interactive-ink-AWZLJJLH.js +423 -0
  388. package/dist/run-interactive-ink-B25V52JO.js +462 -0
  389. package/dist/run-interactive-ink-BC6RGDCH.js +451 -0
  390. package/dist/run-interactive-ink-BMWLPUEU.js +451 -0
  391. package/dist/run-interactive-ink-BRT2MMN6.js +423 -0
  392. package/dist/run-interactive-ink-CB42OWV4.js +572 -0
  393. package/dist/run-interactive-ink-COZSBQND.js +777 -0
  394. package/dist/run-interactive-ink-CQFV44HM.js +451 -0
  395. package/dist/run-interactive-ink-CQMG45KQ.js +462 -0
  396. package/dist/run-interactive-ink-CQP3B7JM.js +669 -0
  397. package/dist/run-interactive-ink-CUCLNJCF.js +451 -0
  398. package/dist/run-interactive-ink-DEEZYQK5.js +423 -0
  399. package/dist/run-interactive-ink-DF5P6WZX.js +423 -0
  400. package/dist/run-interactive-ink-DFITKRY4.js +423 -0
  401. package/dist/run-interactive-ink-DG6TTEQQ.js +462 -0
  402. package/dist/run-interactive-ink-DH7ECECB.js +438 -0
  403. package/dist/run-interactive-ink-DMTUJHP6.js +423 -0
  404. package/dist/run-interactive-ink-DNSBSWLT.js +451 -0
  405. package/dist/run-interactive-ink-DV3TZEM3.js +742 -0
  406. package/dist/run-interactive-ink-E4AYCUDK.js +451 -0
  407. package/dist/run-interactive-ink-E4GPBTSL.js +462 -0
  408. package/dist/run-interactive-ink-ECVTPOIE.js +462 -0
  409. package/dist/run-interactive-ink-ELPCCGT3.js +423 -0
  410. package/dist/run-interactive-ink-ELWVRJZS.js +451 -0
  411. package/dist/run-interactive-ink-ENBMPAV7.js +462 -0
  412. package/dist/run-interactive-ink-EOVWUC3C.js +451 -0
  413. package/dist/run-interactive-ink-EVHWEXM4.js +451 -0
  414. package/dist/run-interactive-ink-F7SBCWE3.js +423 -0
  415. package/dist/run-interactive-ink-FCHXZ3JW.js +423 -0
  416. package/dist/run-interactive-ink-G27WWB5V.js +423 -0
  417. package/dist/run-interactive-ink-GDFTNYRC.js +462 -0
  418. package/dist/run-interactive-ink-GHGZAYSM.js +533 -0
  419. package/dist/run-interactive-ink-GK4IVHVT.js +684 -0
  420. package/dist/run-interactive-ink-GNCZNR6W.js +423 -0
  421. package/dist/run-interactive-ink-GQ53M5SW.js +605 -0
  422. package/dist/run-interactive-ink-GT7R7X2P.js +762 -0
  423. package/dist/run-interactive-ink-GWZTEIEZ.js +462 -0
  424. package/dist/run-interactive-ink-HA45VNUD.js +703 -0
  425. package/dist/run-interactive-ink-HB44RGFJ.js +423 -0
  426. package/dist/run-interactive-ink-HCVGKG23.js +462 -0
  427. package/dist/run-interactive-ink-HYKJ4PZ3.js +462 -0
  428. package/dist/run-interactive-ink-IGEBXARA.js +423 -0
  429. package/dist/run-interactive-ink-IGU7UVL5.js +462 -0
  430. package/dist/run-interactive-ink-JNVKOJRV.js +462 -0
  431. package/dist/run-interactive-ink-JYON5JQQ.js +461 -0
  432. package/dist/run-interactive-ink-K47CRELE.js +423 -0
  433. package/dist/run-interactive-ink-KCHMEHVH.js +547 -0
  434. package/dist/run-interactive-ink-KEB6ENSZ.js +423 -0
  435. package/dist/run-interactive-ink-KEWSKPTE.js +451 -0
  436. package/dist/run-interactive-ink-KJUHMADH.js +423 -0
  437. package/dist/run-interactive-ink-KW5NPJ32.js +423 -0
  438. package/dist/run-interactive-ink-L3EDWKF6.js +687 -0
  439. package/dist/run-interactive-ink-L4BCC6WG.js +462 -0
  440. package/dist/run-interactive-ink-LQPEZ6PR.js +520 -0
  441. package/dist/run-interactive-ink-LQXS5GMO.js +253 -0
  442. package/dist/run-interactive-ink-M4SOBC5E.js +817 -0
  443. package/dist/run-interactive-ink-MJGAQA2R.js +423 -0
  444. package/dist/run-interactive-ink-MPJB6PCJ.js +451 -0
  445. package/dist/run-interactive-ink-MXWZBG3F.js +461 -0
  446. package/dist/run-interactive-ink-N4XIVCWV.js +562 -0
  447. package/dist/run-interactive-ink-ND3PWHDU.js +462 -0
  448. package/dist/run-interactive-ink-NJTAWS3L.js +462 -0
  449. package/dist/run-interactive-ink-OBWWSIZ5.js +423 -0
  450. package/dist/run-interactive-ink-OD7YJBYI.js +423 -0
  451. package/dist/run-interactive-ink-OE23JGIN.js +451 -0
  452. package/dist/run-interactive-ink-OJ4EUMR5.js +462 -0
  453. package/dist/run-interactive-ink-OOC74RCY.js +423 -0
  454. package/dist/run-interactive-ink-P2PHTOX6.js +462 -0
  455. package/dist/run-interactive-ink-PE3XWCVU.js +423 -0
  456. package/dist/run-interactive-ink-PJBWWQF3.js +423 -0
  457. package/dist/run-interactive-ink-PLLZW6BV.js +678 -0
  458. package/dist/run-interactive-ink-PTXNQZ57.js +451 -0
  459. package/dist/run-interactive-ink-PWN5Q6T6.js +423 -0
  460. package/dist/run-interactive-ink-PZK4RD77.js +423 -0
  461. package/dist/run-interactive-ink-QBSXVTCG.js +462 -0
  462. package/dist/run-interactive-ink-QHOQB55Q.js +727 -0
  463. package/dist/run-interactive-ink-QIAC6ZMT.js +451 -0
  464. package/dist/run-interactive-ink-QLLGPIUL.js +462 -0
  465. package/dist/run-interactive-ink-R5W3ZEMY.js +818 -0
  466. package/dist/run-interactive-ink-RHDW3EHS.js +462 -0
  467. package/dist/run-interactive-ink-RLRKPNTS.js +668 -0
  468. package/dist/run-interactive-ink-RORQKBWV.js +425 -0
  469. package/dist/run-interactive-ink-RS6OZ66I.js +423 -0
  470. package/dist/run-interactive-ink-RVGRYBNQ.js +684 -0
  471. package/dist/run-interactive-ink-S35BKUZB.js +423 -0
  472. package/dist/run-interactive-ink-SS6RAQDE.js +423 -0
  473. package/dist/run-interactive-ink-SVP37E33.js +451 -0
  474. package/dist/run-interactive-ink-T53KH7FU.js +423 -0
  475. package/dist/run-interactive-ink-TCQUCJVS.js +423 -0
  476. package/dist/run-interactive-ink-TLUBKTTN.js +423 -0
  477. package/dist/run-interactive-ink-U2BAAHUU.js +438 -0
  478. package/dist/run-interactive-ink-U2KXGJ5S.js +451 -0
  479. package/dist/run-interactive-ink-U73PEMAO.js +423 -0
  480. package/dist/run-interactive-ink-UFTOTXIX.js +669 -0
  481. package/dist/run-interactive-ink-UJNQ54ZU.js +451 -0
  482. package/dist/run-interactive-ink-V63D5IV5.js +423 -0
  483. package/dist/run-interactive-ink-VLBITT4H.js +451 -0
  484. package/dist/run-interactive-ink-VSAX3XFR.js +462 -0
  485. package/dist/run-interactive-ink-WBJOY622.js +729 -0
  486. package/dist/run-interactive-ink-WERR64KP.js +451 -0
  487. package/dist/run-interactive-ink-WHTQ5OV6.js +732 -0
  488. package/dist/run-interactive-ink-WJBK4XIO.js +423 -0
  489. package/dist/run-interactive-ink-WQLCJ34D.js +462 -0
  490. package/dist/run-interactive-ink-WRKQJIAG.js +733 -0
  491. package/dist/run-interactive-ink-XG3P25DM.js +423 -0
  492. package/dist/run-interactive-ink-XPVJ22HP.js +462 -0
  493. package/dist/run-interactive-ink-XS5I2CGI.js +423 -0
  494. package/dist/run-interactive-ink-XVK7DXPB.js +785 -0
  495. package/dist/run-interactive-ink-YB3USTSB.js +706 -0
  496. package/dist/run-interactive-ink-YCBRQCG2.js +423 -0
  497. package/dist/run-interactive-ink-YOPSMTYJ.js +423 -0
  498. package/dist/run-interactive-ink-YYPCL65X.js +665 -0
  499. package/dist/run-interactive-ink-YYZT5L4Z.js +462 -0
  500. package/dist/run-interactive-ink-ZBPYRTJK.js +462 -0
  501. package/dist/run-interactive-ink-ZCCKFR2A.js +451 -0
  502. package/dist/run-interactive-ink-ZKYQ4CJW.js +423 -0
  503. package/dist/run-interactive-ink-ZMO2352Q.js +685 -0
  504. package/dist/run-interactive-ink-ZTDQ773P.js +423 -0
  505. package/dist/run-interactive-ink-ZWH74XDY.js +674 -0
  506. package/package.json +50 -0
  507. package/src/cli.ts +4 -0
  508. package/src/index.ts +1800 -0
  509. package/src/init-feature-context.ts +153 -0
  510. package/src/init-onboarding.ts +529 -0
  511. package/src/interactive-ink.tsx +5 -0
  512. package/src/run-interactive-ink.ts +618 -0
  513. package/src/web-ui.ts +1975 -0
  514. package/test/cli.test.ts +587 -0
  515. package/test/init-onboarding.contract.test.ts +48 -0
  516. package/tsconfig.json +9 -0
@@ -0,0 +1,1933 @@
1
+ // src/index.ts
2
+ import { spawn } from "child_process";
3
+ import { access, cp, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
4
+ import {
5
+ createServer
6
+ } from "http";
7
+ import { dirname as dirname2, resolve as resolve2 } from "path";
8
+ import { createRequire } from "module";
9
+ import { fileURLToPath } from "url";
10
+ import {
11
+ AgentHarness,
12
+ TelemetryEmitter,
13
+ createStateStore,
14
+ loadAgentlConfig
15
+ } from "@agentl/harness";
16
+ import { Command } from "commander";
17
+ import dotenv from "dotenv";
18
+ import YAML from "yaml";
19
+
20
+ // src/web-ui.ts
21
+ import { createHash, randomUUID, timingSafeEqual } from "crypto";
22
+ import { mkdir, readFile, writeFile } from "fs/promises";
23
+ import { basename, dirname, resolve } from "path";
24
+ import { homedir } from "os";
25
+ var DEFAULT_OWNER = "local-owner";
26
+ var FileConversationStore = class {
27
+ filePath;
28
+ conversations = /* @__PURE__ */ new Map();
29
+ loaded = false;
30
+ writing = Promise.resolve();
31
+ constructor(workingDir) {
32
+ const projectName = basename(workingDir).replace(/[^a-zA-Z0-9_-]+/g, "-") || "project";
33
+ const projectHash = createHash("sha256").update(workingDir).digest("hex").slice(0, 12);
34
+ this.filePath = resolve(
35
+ homedir(),
36
+ ".agentl",
37
+ "state",
38
+ `${projectName}-${projectHash}-web-ui-state.json`
39
+ );
40
+ }
41
+ async ensureLoaded() {
42
+ if (this.loaded) {
43
+ return;
44
+ }
45
+ this.loaded = true;
46
+ try {
47
+ const content = await readFile(this.filePath, "utf8");
48
+ const parsed = JSON.parse(content);
49
+ for (const conversation of parsed.conversations ?? []) {
50
+ this.conversations.set(conversation.conversationId, conversation);
51
+ }
52
+ } catch {
53
+ }
54
+ }
55
+ async persist() {
56
+ const payload = {
57
+ conversations: Array.from(this.conversations.values())
58
+ };
59
+ this.writing = this.writing.then(async () => {
60
+ await mkdir(dirname(this.filePath), { recursive: true });
61
+ await writeFile(this.filePath, JSON.stringify(payload, null, 2), "utf8");
62
+ });
63
+ await this.writing;
64
+ }
65
+ async list(ownerId = DEFAULT_OWNER) {
66
+ await this.ensureLoaded();
67
+ return Array.from(this.conversations.values()).filter((conversation) => conversation.ownerId === ownerId).sort((a, b) => b.updatedAt - a.updatedAt);
68
+ }
69
+ async get(conversationId) {
70
+ await this.ensureLoaded();
71
+ return this.conversations.get(conversationId);
72
+ }
73
+ async create(ownerId = DEFAULT_OWNER, title) {
74
+ await this.ensureLoaded();
75
+ const now = Date.now();
76
+ const conversation = {
77
+ conversationId: randomUUID(),
78
+ title: title && title.trim().length > 0 ? title.trim() : "New conversation",
79
+ messages: [],
80
+ ownerId,
81
+ tenantId: null,
82
+ createdAt: now,
83
+ updatedAt: now
84
+ };
85
+ this.conversations.set(conversation.conversationId, conversation);
86
+ await this.persist();
87
+ return conversation;
88
+ }
89
+ async update(conversation) {
90
+ await this.ensureLoaded();
91
+ this.conversations.set(conversation.conversationId, {
92
+ ...conversation,
93
+ updatedAt: Date.now()
94
+ });
95
+ await this.persist();
96
+ }
97
+ async rename(conversationId, title) {
98
+ await this.ensureLoaded();
99
+ const existing = this.conversations.get(conversationId);
100
+ if (!existing) {
101
+ return void 0;
102
+ }
103
+ const updated = {
104
+ ...existing,
105
+ title: title.trim().length > 0 ? title.trim() : existing.title,
106
+ updatedAt: Date.now()
107
+ };
108
+ this.conversations.set(conversationId, updated);
109
+ await this.persist();
110
+ return updated;
111
+ }
112
+ async delete(conversationId) {
113
+ await this.ensureLoaded();
114
+ const removed = this.conversations.delete(conversationId);
115
+ if (removed) {
116
+ await this.persist();
117
+ }
118
+ return removed;
119
+ }
120
+ };
121
+ var SessionStore = class {
122
+ sessions = /* @__PURE__ */ new Map();
123
+ ttlMs;
124
+ constructor(ttlMs = 1e3 * 60 * 60 * 8) {
125
+ this.ttlMs = ttlMs;
126
+ }
127
+ create(ownerId = DEFAULT_OWNER) {
128
+ const now = Date.now();
129
+ const session = {
130
+ sessionId: randomUUID(),
131
+ ownerId,
132
+ csrfToken: randomUUID(),
133
+ createdAt: now,
134
+ expiresAt: now + this.ttlMs,
135
+ lastSeenAt: now
136
+ };
137
+ this.sessions.set(session.sessionId, session);
138
+ return session;
139
+ }
140
+ get(sessionId) {
141
+ const session = this.sessions.get(sessionId);
142
+ if (!session) {
143
+ return void 0;
144
+ }
145
+ if (Date.now() > session.expiresAt) {
146
+ this.sessions.delete(sessionId);
147
+ return void 0;
148
+ }
149
+ session.lastSeenAt = Date.now();
150
+ return session;
151
+ }
152
+ delete(sessionId) {
153
+ this.sessions.delete(sessionId);
154
+ }
155
+ };
156
+ var LoginRateLimiter = class {
157
+ constructor(maxAttempts = 5, windowMs = 1e3 * 60 * 5, lockoutMs = 1e3 * 60 * 10) {
158
+ this.maxAttempts = maxAttempts;
159
+ this.windowMs = windowMs;
160
+ this.lockoutMs = lockoutMs;
161
+ }
162
+ attempts = /* @__PURE__ */ new Map();
163
+ canAttempt(key) {
164
+ const current = this.attempts.get(key);
165
+ if (!current) {
166
+ return { allowed: true };
167
+ }
168
+ if (current.lockedUntil && Date.now() < current.lockedUntil) {
169
+ return {
170
+ allowed: false,
171
+ retryAfterSeconds: Math.ceil((current.lockedUntil - Date.now()) / 1e3)
172
+ };
173
+ }
174
+ return { allowed: true };
175
+ }
176
+ registerFailure(key) {
177
+ const now = Date.now();
178
+ const current = this.attempts.get(key);
179
+ if (!current || now - current.firstFailureAt > this.windowMs) {
180
+ this.attempts.set(key, { count: 1, firstFailureAt: now });
181
+ return { locked: false };
182
+ }
183
+ const count = current.count + 1;
184
+ const next = {
185
+ ...current,
186
+ count
187
+ };
188
+ if (count >= this.maxAttempts) {
189
+ next.lockedUntil = now + this.lockoutMs;
190
+ this.attempts.set(key, next);
191
+ return { locked: true, retryAfterSeconds: Math.ceil(this.lockoutMs / 1e3) };
192
+ }
193
+ this.attempts.set(key, next);
194
+ return { locked: false };
195
+ }
196
+ registerSuccess(key) {
197
+ this.attempts.delete(key);
198
+ }
199
+ };
200
+ var parseCookies = (request) => {
201
+ const cookieHeader = request.headers.cookie ?? "";
202
+ const pairs = cookieHeader.split(";").map((part) => part.trim()).filter(Boolean);
203
+ const cookies = {};
204
+ for (const pair of pairs) {
205
+ const index = pair.indexOf("=");
206
+ if (index <= 0) {
207
+ continue;
208
+ }
209
+ const key = pair.slice(0, index);
210
+ const value = pair.slice(index + 1);
211
+ cookies[key] = decodeURIComponent(value);
212
+ }
213
+ return cookies;
214
+ };
215
+ var setCookie = (response, name, value, options) => {
216
+ const segments = [`${name}=${encodeURIComponent(value)}`];
217
+ segments.push(`Path=${options.path ?? "/"}`);
218
+ if (typeof options.maxAge === "number") {
219
+ segments.push(`Max-Age=${Math.max(0, Math.floor(options.maxAge))}`);
220
+ }
221
+ if (options.httpOnly) {
222
+ segments.push("HttpOnly");
223
+ }
224
+ if (options.secure) {
225
+ segments.push("Secure");
226
+ }
227
+ if (options.sameSite) {
228
+ segments.push(`SameSite=${options.sameSite}`);
229
+ }
230
+ const previous = response.getHeader("Set-Cookie");
231
+ const serialized = segments.join("; ");
232
+ if (!previous) {
233
+ response.setHeader("Set-Cookie", serialized);
234
+ return;
235
+ }
236
+ if (Array.isArray(previous)) {
237
+ response.setHeader("Set-Cookie", [...previous, serialized]);
238
+ return;
239
+ }
240
+ response.setHeader("Set-Cookie", [String(previous), serialized]);
241
+ };
242
+ var verifyPassphrase = (provided, expected) => {
243
+ const providedBuffer = Buffer.from(provided);
244
+ const expectedBuffer = Buffer.from(expected);
245
+ if (providedBuffer.length !== expectedBuffer.length) {
246
+ const zero = Buffer.alloc(expectedBuffer.length);
247
+ return timingSafeEqual(expectedBuffer, zero) && false;
248
+ }
249
+ return timingSafeEqual(providedBuffer, expectedBuffer);
250
+ };
251
+ var getRequestIp = (request) => {
252
+ const forwarded = request.headers["x-forwarded-for"];
253
+ if (typeof forwarded === "string" && forwarded.trim().length > 0) {
254
+ return forwarded.split(",")[0]?.trim() ?? "unknown";
255
+ }
256
+ if (Array.isArray(forwarded) && forwarded[0]) {
257
+ return forwarded[0];
258
+ }
259
+ return request.socket.remoteAddress ?? "unknown";
260
+ };
261
+ var inferConversationTitle = (text) => {
262
+ const normalized = text.trim().replace(/\s+/g, " ");
263
+ if (!normalized) {
264
+ return "New conversation";
265
+ }
266
+ return normalized.length <= 48 ? normalized : `${normalized.slice(0, 48)}...`;
267
+ };
268
+ var renderWebUiHtml = () => `<!doctype html>
269
+ <html lang="en">
270
+ <head>
271
+ <meta charset="utf-8" />
272
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
273
+ <title>AgentL Web UI</title>
274
+ <style>
275
+ :root { color-scheme: dark; }
276
+ * { box-sizing: border-box; }
277
+ body { margin: 0; font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, sans-serif; background: #0f1117; color: #e9edf5; }
278
+ .shell { display: grid; grid-template-columns: 320px 1fr; min-height: 100vh; }
279
+ .sidebar { border-right: 1px solid #252a38; background: #121624; padding: 12px; display: flex; flex-direction: column; gap: 12px; }
280
+ .conversation-list { overflow: auto; display: flex; flex-direction: column; gap: 6px; }
281
+ .conversation-item { border: 1px solid #2c3347; border-radius: 8px; padding: 8px 10px; cursor: pointer; background: #171d2c; }
282
+ .conversation-item.active { border-color: #5b7cff; background: #1f2a4a; }
283
+ .conversation-title { font-size: 13px; font-weight: 600; margin-bottom: 2px; }
284
+ .conversation-meta { font-size: 11px; color: #9ca6bf; }
285
+ .conversation-actions { margin-top: 6px; display: flex; gap: 6px; }
286
+ .main { display: grid; grid-template-rows: auto 1fr auto; min-height: 100vh; }
287
+ .topbar { border-bottom: 1px solid #252a38; padding: 12px 16px; display: flex; justify-content: space-between; align-items: center; }
288
+ .status { color: #9ca6bf; font-size: 12px; }
289
+ .messages { padding: 20px; overflow: auto; display: flex; flex-direction: column; gap: 12px; }
290
+ .message { max-width: 760px; border-radius: 10px; padding: 10px 12px; white-space: pre-wrap; line-height: 1.35; }
291
+ .message.user { align-self: flex-end; background: #27417f; }
292
+ .message.assistant { align-self: flex-start; background: #1b2233; border: 1px solid #2c3347; }
293
+ .composer { border-top: 1px solid #252a38; padding: 12px 16px; display: grid; gap: 8px; }
294
+ textarea { width: 100%; min-height: 78px; border-radius: 10px; border: 1px solid #2c3347; background: #121624; color: #e9edf5; padding: 10px; resize: vertical; }
295
+ button { border: 1px solid #2c3347; background: #1a2133; color: #e9edf5; padding: 7px 10px; border-radius: 8px; cursor: pointer; }
296
+ button.primary { border-color: #4b6bff; background: #3656dd; }
297
+ button.danger { border-color: #6d2b3a; background: #3a1b24; }
298
+ button:disabled { opacity: 0.6; cursor: default; }
299
+ .row { display: flex; gap: 8px; align-items: center; }
300
+ .hidden { display: none !important; }
301
+ .auth { min-height: 100vh; display: grid; place-items: center; }
302
+ .auth-card { width: min(420px, 90vw); border: 1px solid #2c3347; background: #121624; border-radius: 12px; padding: 20px; display: grid; gap: 10px; }
303
+ input { width: 100%; border-radius: 10px; border: 1px solid #2c3347; background: #0f1117; color: #e9edf5; padding: 10px; }
304
+ .error { color: #ff9aa9; font-size: 12px; min-height: 16px; }
305
+ .empty { color: #9ca6bf; font-size: 13px; }
306
+ @media (max-width: 860px) {
307
+ .shell { grid-template-columns: 1fr; }
308
+ .sidebar { min-height: 220px; border-right: none; border-bottom: 1px solid #252a38; }
309
+ .main { min-height: calc(100vh - 220px); }
310
+ }
311
+ </style>
312
+ </head>
313
+ <body>
314
+ <div id="auth" class="auth hidden">
315
+ <form id="login-form" class="auth-card">
316
+ <h2 style="margin: 0">AgentL login</h2>
317
+ <p style="margin: 0; color: #9ca6bf; font-size: 13px">Enter the configured passphrase to use this UI.</p>
318
+ <input id="passphrase" type="password" autocomplete="current-password" placeholder="Passphrase" required />
319
+ <button class="primary" type="submit">Sign in</button>
320
+ <div id="login-error" class="error"></div>
321
+ </form>
322
+ </div>
323
+
324
+ <div id="app" class="shell hidden">
325
+ <aside class="sidebar">
326
+ <div class="row">
327
+ <button id="new-chat" class="primary">New chat</button>
328
+ <button id="refresh-list">Refresh</button>
329
+ </div>
330
+ <div id="conversation-list" class="conversation-list"></div>
331
+ </aside>
332
+
333
+ <section class="main">
334
+ <div class="topbar">
335
+ <div id="chat-title">AgentL</div>
336
+ <div class="row">
337
+ <span id="connection-status" class="status">idle</span>
338
+ <button id="rename-chat">Rename</button>
339
+ <button id="delete-chat" class="danger">Delete</button>
340
+ <button id="logout">Logout</button>
341
+ </div>
342
+ </div>
343
+ <div id="messages" class="messages">
344
+ <div class="empty">Select or create a conversation to start chatting.</div>
345
+ </div>
346
+ <form id="composer" class="composer">
347
+ <textarea id="prompt" placeholder="Send a message..."></textarea>
348
+ <div class="row">
349
+ <button id="send" class="primary" type="submit">Send</button>
350
+ </div>
351
+ </form>
352
+ </section>
353
+ </div>
354
+
355
+ <script>
356
+ const state = {
357
+ csrfToken: "",
358
+ conversations: [],
359
+ activeConversationId: null,
360
+ isStreaming: false
361
+ };
362
+
363
+ const elements = {
364
+ auth: document.getElementById("auth"),
365
+ app: document.getElementById("app"),
366
+ loginForm: document.getElementById("login-form"),
367
+ passphrase: document.getElementById("passphrase"),
368
+ loginError: document.getElementById("login-error"),
369
+ list: document.getElementById("conversation-list"),
370
+ newChat: document.getElementById("new-chat"),
371
+ refreshList: document.getElementById("refresh-list"),
372
+ messages: document.getElementById("messages"),
373
+ chatTitle: document.getElementById("chat-title"),
374
+ renameChat: document.getElementById("rename-chat"),
375
+ deleteChat: document.getElementById("delete-chat"),
376
+ logout: document.getElementById("logout"),
377
+ composer: document.getElementById("composer"),
378
+ prompt: document.getElementById("prompt"),
379
+ send: document.getElementById("send"),
380
+ connectionStatus: document.getElementById("connection-status")
381
+ };
382
+
383
+ const mutatingMethods = new Set(["POST", "PATCH", "PUT", "DELETE"]);
384
+
385
+ const api = async (path, options = {}) => {
386
+ const method = (options.method || "GET").toUpperCase();
387
+ const headers = { ...(options.headers || {}) };
388
+ if (mutatingMethods.has(method) && state.csrfToken) {
389
+ headers["x-csrf-token"] = state.csrfToken;
390
+ }
391
+ if (options.body && !headers["Content-Type"]) {
392
+ headers["Content-Type"] = "application/json";
393
+ }
394
+ const response = await fetch(path, { credentials: "include", ...options, method, headers });
395
+ if (!response.ok) {
396
+ let payload = {};
397
+ try { payload = await response.json(); } catch {}
398
+ const error = new Error(payload.message || ("Request failed: " + response.status));
399
+ error.status = response.status;
400
+ error.payload = payload;
401
+ throw error;
402
+ }
403
+ const contentType = response.headers.get("content-type") || "";
404
+ if (contentType.includes("application/json")) {
405
+ return await response.json();
406
+ }
407
+ return await response.text();
408
+ };
409
+
410
+ const formatDate = (epoch) => {
411
+ try { return new Date(epoch).toLocaleString(); } catch { return ""; }
412
+ };
413
+
414
+ const renderConversationList = () => {
415
+ elements.list.innerHTML = "";
416
+ if (state.conversations.length === 0) {
417
+ const empty = document.createElement("div");
418
+ empty.className = "empty";
419
+ empty.textContent = "No conversations yet.";
420
+ elements.list.appendChild(empty);
421
+ return;
422
+ }
423
+ for (const conversation of state.conversations) {
424
+ const item = document.createElement("div");
425
+ item.className = "conversation-item" + (conversation.conversationId === state.activeConversationId ? " active" : "");
426
+ item.innerHTML = '<div class="conversation-title"></div><div class="conversation-meta"></div>';
427
+ item.querySelector(".conversation-title").textContent = conversation.title;
428
+ item.querySelector(".conversation-meta").textContent = formatDate(conversation.updatedAt);
429
+ item.addEventListener("click", async () => {
430
+ state.activeConversationId = conversation.conversationId;
431
+ renderConversationList();
432
+ await loadConversation(conversation.conversationId);
433
+ });
434
+ elements.list.appendChild(item);
435
+ }
436
+ };
437
+
438
+ const renderMessages = (messages) => {
439
+ elements.messages.innerHTML = "";
440
+ if (!messages || messages.length === 0) {
441
+ const empty = document.createElement("div");
442
+ empty.className = "empty";
443
+ empty.textContent = "Start the conversation by sending a message.";
444
+ elements.messages.appendChild(empty);
445
+ return;
446
+ }
447
+ for (const message of messages) {
448
+ const node = document.createElement("div");
449
+ node.className = "message " + (message.role === "assistant" ? "assistant" : "user");
450
+ node.textContent = String(message.content || "");
451
+ elements.messages.appendChild(node);
452
+ }
453
+ elements.messages.scrollTop = elements.messages.scrollHeight;
454
+ };
455
+
456
+ const loadConversations = async () => {
457
+ const payload = await api("/api/conversations");
458
+ state.conversations = payload.conversations || [];
459
+ renderConversationList();
460
+ };
461
+
462
+ const loadConversation = async (conversationId) => {
463
+ const payload = await api("/api/conversations/" + encodeURIComponent(conversationId));
464
+ elements.chatTitle.textContent = payload.conversation.title;
465
+ renderMessages(payload.conversation.messages);
466
+ };
467
+
468
+ const createConversation = async (title) => {
469
+ const payload = await api("/api/conversations", {
470
+ method: "POST",
471
+ body: JSON.stringify(title ? { title } : {})
472
+ });
473
+ state.activeConversationId = payload.conversation.conversationId;
474
+ await loadConversations();
475
+ await loadConversation(state.activeConversationId);
476
+ return state.activeConversationId;
477
+ };
478
+
479
+ const parseSseChunk = (buffer, onEvent) => {
480
+ let rest = buffer;
481
+ while (true) {
482
+ const index = rest.indexOf("\\n\\n");
483
+ if (index < 0) {
484
+ return rest;
485
+ }
486
+ const raw = rest.slice(0, index);
487
+ rest = rest.slice(index + 2);
488
+ const lines = raw.split("\\n");
489
+ let eventName = "message";
490
+ let data = "";
491
+ for (const line of lines) {
492
+ if (line.startsWith("event:")) {
493
+ eventName = line.slice(6).trim();
494
+ } else if (line.startsWith("data:")) {
495
+ data += line.slice(5).trim();
496
+ }
497
+ }
498
+ if (data) {
499
+ try {
500
+ onEvent(eventName, JSON.parse(data));
501
+ } catch {}
502
+ }
503
+ }
504
+ };
505
+
506
+ const setStreaming = (value) => {
507
+ state.isStreaming = value;
508
+ elements.send.disabled = value;
509
+ elements.prompt.disabled = value;
510
+ elements.connectionStatus.textContent = value ? "streaming..." : "idle";
511
+ };
512
+
513
+ const sendMessage = async (text) => {
514
+ const messageText = (text || "").trim();
515
+ if (!messageText || state.isStreaming) {
516
+ return;
517
+ }
518
+ let conversationId = state.activeConversationId;
519
+ if (!conversationId) {
520
+ conversationId = await createConversation(messageText);
521
+ }
522
+ const existingPayload = await api("/api/conversations/" + encodeURIComponent(conversationId));
523
+ const localMessages = [...(existingPayload.conversation.messages || []), { role: "user", content: messageText }];
524
+ let assistantMessage = { role: "assistant", content: "" };
525
+ localMessages.push(assistantMessage);
526
+ renderMessages(localMessages);
527
+ setStreaming(true);
528
+ try {
529
+ const response = await fetch("/api/conversations/" + encodeURIComponent(conversationId) + "/messages", {
530
+ method: "POST",
531
+ credentials: "include",
532
+ headers: { "Content-Type": "application/json", "x-csrf-token": state.csrfToken },
533
+ body: JSON.stringify({ message: messageText })
534
+ });
535
+ if (!response.ok || !response.body) {
536
+ throw new Error("Failed to stream response");
537
+ }
538
+ const reader = response.body.getReader();
539
+ const decoder = new TextDecoder();
540
+ let buffer = "";
541
+ while (true) {
542
+ const { value, done } = await reader.read();
543
+ if (done) {
544
+ break;
545
+ }
546
+ buffer += decoder.decode(value, { stream: true });
547
+ buffer = parseSseChunk(buffer, (eventName, payload) => {
548
+ if (eventName === "model:chunk") {
549
+ assistantMessage.content += String(payload.content || "");
550
+ renderMessages(localMessages);
551
+ }
552
+ if (eventName === "run:completed" && (!assistantMessage.content || assistantMessage.content.length === 0)) {
553
+ assistantMessage.content = String(payload.result?.response || "");
554
+ renderMessages(localMessages);
555
+ }
556
+ });
557
+ }
558
+ await loadConversations();
559
+ await loadConversation(conversationId);
560
+ } finally {
561
+ setStreaming(false);
562
+ }
563
+ };
564
+
565
+ const requireAuth = async () => {
566
+ try {
567
+ const session = await api("/api/auth/session");
568
+ if (!session.authenticated) {
569
+ elements.auth.classList.remove("hidden");
570
+ elements.app.classList.add("hidden");
571
+ return false;
572
+ }
573
+ state.csrfToken = session.csrfToken || "";
574
+ elements.auth.classList.add("hidden");
575
+ elements.app.classList.remove("hidden");
576
+ return true;
577
+ } catch {
578
+ elements.auth.classList.remove("hidden");
579
+ elements.app.classList.add("hidden");
580
+ return false;
581
+ }
582
+ };
583
+
584
+ elements.loginForm.addEventListener("submit", async (event) => {
585
+ event.preventDefault();
586
+ elements.loginError.textContent = "";
587
+ try {
588
+ const result = await api("/api/auth/login", {
589
+ method: "POST",
590
+ body: JSON.stringify({ passphrase: elements.passphrase.value || "" })
591
+ });
592
+ state.csrfToken = result.csrfToken || "";
593
+ elements.passphrase.value = "";
594
+ elements.auth.classList.add("hidden");
595
+ elements.app.classList.remove("hidden");
596
+ await loadConversations();
597
+ if (state.conversations[0]) {
598
+ state.activeConversationId = state.conversations[0].conversationId;
599
+ await loadConversation(state.activeConversationId);
600
+ }
601
+ } catch (error) {
602
+ elements.loginError.textContent = error.message || "Login failed";
603
+ }
604
+ });
605
+
606
+ elements.newChat.addEventListener("click", async () => {
607
+ await createConversation();
608
+ });
609
+
610
+ elements.refreshList.addEventListener("click", async () => {
611
+ await loadConversations();
612
+ });
613
+
614
+ elements.renameChat.addEventListener("click", async () => {
615
+ if (!state.activeConversationId) {
616
+ return;
617
+ }
618
+ const nextTitle = window.prompt("Rename conversation");
619
+ if (!nextTitle) {
620
+ return;
621
+ }
622
+ await api("/api/conversations/" + encodeURIComponent(state.activeConversationId), {
623
+ method: "PATCH",
624
+ body: JSON.stringify({ title: nextTitle })
625
+ });
626
+ await loadConversations();
627
+ await loadConversation(state.activeConversationId);
628
+ });
629
+
630
+ elements.deleteChat.addEventListener("click", async () => {
631
+ if (!state.activeConversationId) {
632
+ return;
633
+ }
634
+ if (!window.confirm("Delete this conversation?")) {
635
+ return;
636
+ }
637
+ await api("/api/conversations/" + encodeURIComponent(state.activeConversationId), { method: "DELETE" });
638
+ state.activeConversationId = null;
639
+ elements.chatTitle.textContent = "AgentL";
640
+ renderMessages([]);
641
+ await loadConversations();
642
+ });
643
+
644
+ elements.logout.addEventListener("click", async () => {
645
+ await api("/api/auth/logout", { method: "POST" });
646
+ state.activeConversationId = null;
647
+ state.conversations = [];
648
+ state.csrfToken = "";
649
+ await requireAuth();
650
+ });
651
+
652
+ elements.composer.addEventListener("submit", async (event) => {
653
+ event.preventDefault();
654
+ const value = elements.prompt.value;
655
+ elements.prompt.value = "";
656
+ await sendMessage(value);
657
+ });
658
+
659
+ (async () => {
660
+ const authenticated = await requireAuth();
661
+ if (!authenticated) {
662
+ return;
663
+ }
664
+ await loadConversations();
665
+ if (state.conversations[0]) {
666
+ state.activeConversationId = state.conversations[0].conversationId;
667
+ await loadConversation(state.activeConversationId);
668
+ renderConversationList();
669
+ }
670
+ })();
671
+ </script>
672
+ </body>
673
+ </html>`;
674
+
675
+ // src/index.ts
676
+ var __dirname = dirname2(fileURLToPath(import.meta.url));
677
+ var require2 = createRequire(import.meta.url);
678
+ var writeJson = (response, statusCode, payload) => {
679
+ response.writeHead(statusCode, { "Content-Type": "application/json" });
680
+ response.end(JSON.stringify(payload));
681
+ };
682
+ var writeHtml = (response, statusCode, payload) => {
683
+ response.writeHead(statusCode, { "Content-Type": "text/html; charset=utf-8" });
684
+ response.end(payload);
685
+ };
686
+ var readRequestBody = async (request) => {
687
+ const chunks = [];
688
+ for await (const chunk of request) {
689
+ chunks.push(Buffer.from(chunk));
690
+ }
691
+ const body = Buffer.concat(chunks).toString("utf8");
692
+ return body.length > 0 ? JSON.parse(body) : {};
693
+ };
694
+ var resolveHarnessEnvironment = () => {
695
+ const value = (process.env.AGENTL_ENV ?? process.env.NODE_ENV ?? "development").toLowerCase();
696
+ if (value === "production" || value === "staging") {
697
+ return value;
698
+ }
699
+ return "development";
700
+ };
701
+ var listenOnAvailablePort = async (server, preferredPort) => await new Promise((resolveListen, rejectListen) => {
702
+ let currentPort = preferredPort;
703
+ const tryListen = () => {
704
+ const onListening = () => {
705
+ server.off("error", onError);
706
+ const address = server.address();
707
+ if (address && typeof address === "object" && typeof address.port === "number") {
708
+ resolveListen(address.port);
709
+ return;
710
+ }
711
+ resolveListen(currentPort);
712
+ };
713
+ const onError = (error) => {
714
+ server.off("listening", onListening);
715
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "EADDRINUSE") {
716
+ currentPort += 1;
717
+ if (currentPort > 65535) {
718
+ rejectListen(
719
+ new Error(
720
+ "No available ports found from the requested port up to 65535."
721
+ )
722
+ );
723
+ return;
724
+ }
725
+ setImmediate(tryListen);
726
+ return;
727
+ }
728
+ rejectListen(error);
729
+ };
730
+ server.once("listening", onListening);
731
+ server.once("error", onError);
732
+ server.listen(currentPort);
733
+ };
734
+ tryListen();
735
+ });
736
+ var parseParams = (values) => {
737
+ const params = {};
738
+ for (const value of values) {
739
+ const [key, ...rest] = value.split("=");
740
+ if (!key) {
741
+ continue;
742
+ }
743
+ params[key] = rest.join("=");
744
+ }
745
+ return params;
746
+ };
747
+ var AGENT_SKILL_GUIDANCE = `## Skill Authoring Guidance
748
+
749
+ When asked to create or update a skill:
750
+
751
+ 1. Inspect current skills under \`skills/\` first (\`list_directory\`, \`read_file\`).
752
+ 2. Decide skill type before writing files:
753
+ - **Instruction skill (no tool code)** for summarization, rewriting, classification, translation, planning, and other pure language tasks.
754
+ - **Tool-backed skill** only when external I/O, deterministic transforms, side effects, or integrations are required.
755
+ 3. If creating a tool-backed skill, create/update:
756
+ - \`skills/<skill-name>/SKILL.md\`
757
+ - \`skills/<skill-name>/tools/<tool-name>.ts\`
758
+ 4. Keep tool names and schemas explicit and stable.
759
+ 5. Never create placeholder tool handlers for tasks the model can already do directly.
760
+ 6. After writing files, verify by listing/reading the created paths.
761
+ 7. Ask the user to run \`agentl tools\` to confirm the new tool is discovered (when tools were added).
762
+
763
+ Skill file conventions:
764
+ - \`SKILL.md\` frontmatter should include \`name\`, \`description\`, and \`tools\`.
765
+ - Tool modules should export a default tool definition object with:
766
+ - \`name\`
767
+ - \`description\`
768
+ - \`inputSchema\`
769
+ - \`handler\``;
770
+ var AGENT_TEMPLATE = `---
771
+ name: my-agent
772
+ description: A helpful AgentL assistant
773
+ model:
774
+ provider: anthropic
775
+ name: claude-opus-4-5
776
+ temperature: 0.2
777
+ limits:
778
+ maxSteps: 50
779
+ timeout: 300
780
+ ---
781
+
782
+ # My Agent
783
+
784
+ You are a helpful assistant built with AgentL.
785
+
786
+ Working directory: {{runtime.workingDir}}
787
+ Environment: {{runtime.environment}}
788
+
789
+ ## Task Guidance
790
+
791
+ - Use tools when needed
792
+ - Explain your reasoning clearly
793
+ - Ask clarifying questions when requirements are ambiguous
794
+ - Never claim a file/tool change unless the corresponding tool call actually succeeded
795
+
796
+ ## Default Capabilities in a Fresh Project
797
+
798
+ - Built-in tools: \`list_directory\` and \`read_file\`
799
+ - \`write_file\` is available in development, and disabled by default in production
800
+ - A starter local skill is included (\`starter-echo\`)
801
+ - Bash/shell commands are **not** available unless you install and enable a shell tool/skill
802
+ - Git operations are only available if a git-capable tool/skill is configured
803
+
804
+ ${AGENT_SKILL_GUIDANCE}
805
+ `;
806
+ var CONFIG_TEMPLATE = `export default {
807
+ mcp: [],
808
+ auth: { required: false },
809
+ state: { provider: 'memory', ttl: 3600 },
810
+ telemetry: { enabled: true }
811
+ }
812
+ `;
813
+ var PACKAGE_TEMPLATE = (name) => JSON.stringify(
814
+ {
815
+ name,
816
+ private: true,
817
+ type: "module",
818
+ dependencies: {
819
+ "@agentl/harness": "^0.1.0",
820
+ "@agentl/sdk": "^0.1.0"
821
+ }
822
+ },
823
+ null,
824
+ 2
825
+ );
826
+ var ENV_TEMPLATE = "ANTHROPIC_API_KEY=sk-ant-...\n";
827
+ var GITIGNORE_TEMPLATE = ".env\nnode_modules\ndist\n";
828
+ var VERCEL_RUNTIME_DEPENDENCIES = {
829
+ "@anthropic-ai/sdk": "^0.74.0",
830
+ "@aws-sdk/client-dynamodb": "^3.988.0",
831
+ "@latitude-data/telemetry": "^2.0.2",
832
+ "@vercel/kv": "^3.0.0",
833
+ commander: "^12.0.0",
834
+ dotenv: "^16.4.0",
835
+ jiti: "^2.6.1",
836
+ mustache: "^4.2.0",
837
+ openai: "^6.3.0",
838
+ redis: "^5.10.0",
839
+ ws: "^8.18.0",
840
+ yaml: "^2.8.1"
841
+ };
842
+ var TEST_TEMPLATE = `tests:
843
+ - name: "Basic sanity"
844
+ task: "What is 2 + 2?"
845
+ expect:
846
+ contains: "4"
847
+ `;
848
+ var SKILL_TEMPLATE = `---
849
+ name: starter-skill
850
+ version: 1.0.0
851
+ description: Starter local skill template
852
+ tools:
853
+ - starter-echo
854
+ ---
855
+
856
+ # Starter Skill
857
+
858
+ This is a starter local skill created by \`agentl init\`.
859
+
860
+ ## Authoring Notes
861
+
862
+ - Keep the \`tools\` frontmatter list in sync with actual tool module names.
863
+ - Prefer narrow, explicit schemas for predictable tool calling.
864
+ - After edits, run \`agentl tools\` to confirm discovery.
865
+ `;
866
+ var SKILL_TOOL_TEMPLATE = `export default {
867
+ name: "starter-echo",
868
+ description: "Echoes a message for testing local skill wiring",
869
+ inputSchema: {
870
+ type: "object",
871
+ properties: {
872
+ message: { type: "string", description: "Message to echo" }
873
+ },
874
+ required: ["message"]
875
+ },
876
+ async handler(input) {
877
+ return { echoed: input.message };
878
+ }
879
+ };
880
+ `;
881
+ var ensureFile = async (path, content) => {
882
+ await mkdir2(dirname2(path), { recursive: true });
883
+ await writeFile2(path, content, { encoding: "utf8", flag: "wx" });
884
+ };
885
+ var copyIfExists = async (sourcePath, destinationPath) => {
886
+ try {
887
+ await access(sourcePath);
888
+ } catch {
889
+ return;
890
+ }
891
+ await mkdir2(dirname2(destinationPath), { recursive: true });
892
+ await cp(sourcePath, destinationPath, { recursive: true });
893
+ };
894
+ var resolveCliEntrypoint = async () => {
895
+ const sourceEntrypoint = resolve2(packageRoot, "src", "index.ts");
896
+ try {
897
+ await access(sourceEntrypoint);
898
+ return sourceEntrypoint;
899
+ } catch {
900
+ return resolve2(packageRoot, "dist", "index.js");
901
+ }
902
+ };
903
+ var buildVercelHandlerBundle = async (outDir) => {
904
+ const { build: esbuild } = await import("esbuild");
905
+ const cliEntrypoint = await resolveCliEntrypoint();
906
+ const tempEntry = resolve2(outDir, "api", "_entry.js");
907
+ await writeFile2(
908
+ tempEntry,
909
+ `import { startDevServer } from ${JSON.stringify(cliEntrypoint)};
910
+ let serverPromise;
911
+ export default async function handler(req, res) {
912
+ if (!serverPromise) {
913
+ serverPromise = startDevServer(0, { workingDir: process.cwd() });
914
+ }
915
+ const server = await serverPromise;
916
+ server.emit("request", req, res);
917
+ }
918
+ `,
919
+ "utf8"
920
+ );
921
+ await esbuild({
922
+ entryPoints: [tempEntry],
923
+ bundle: true,
924
+ platform: "node",
925
+ format: "esm",
926
+ target: "node20",
927
+ outfile: resolve2(outDir, "api", "index.js"),
928
+ sourcemap: false,
929
+ legalComments: "none",
930
+ external: [
931
+ ...Object.keys(VERCEL_RUNTIME_DEPENDENCIES),
932
+ "@anthropic-ai/sdk/*",
933
+ "child_process",
934
+ "fs",
935
+ "fs/promises",
936
+ "http",
937
+ "https",
938
+ "path",
939
+ "module",
940
+ "url",
941
+ "readline",
942
+ "readline/promises",
943
+ "crypto",
944
+ "stream",
945
+ "events",
946
+ "util",
947
+ "os",
948
+ "zlib",
949
+ "net",
950
+ "tls",
951
+ "dns",
952
+ "assert",
953
+ "buffer",
954
+ "timers",
955
+ "timers/promises",
956
+ "node:child_process",
957
+ "node:fs",
958
+ "node:fs/promises",
959
+ "node:http",
960
+ "node:https",
961
+ "node:path",
962
+ "node:module",
963
+ "node:url",
964
+ "node:readline",
965
+ "node:readline/promises",
966
+ "node:crypto",
967
+ "node:stream",
968
+ "node:events",
969
+ "node:util",
970
+ "node:os",
971
+ "node:zlib",
972
+ "node:net",
973
+ "node:tls",
974
+ "node:dns",
975
+ "node:assert",
976
+ "node:buffer",
977
+ "node:timers",
978
+ "node:timers/promises"
979
+ ]
980
+ });
981
+ };
982
+ var writeConfigFile = async (workingDir, config) => {
983
+ const serialized = `export default ${JSON.stringify(config, null, 2)}
984
+ `;
985
+ await writeFile2(resolve2(workingDir, "agentl.config.js"), serialized, "utf8");
986
+ };
987
+ var extractToken = (request, authConfig) => {
988
+ if (authConfig.type === "header") {
989
+ const headerName = (authConfig.headerName ?? "x-agent-api-key").toLowerCase();
990
+ const raw = request.headers[headerName];
991
+ return Array.isArray(raw) ? raw[0] ?? "" : raw ?? "";
992
+ }
993
+ const authHeader = request.headers.authorization ?? "";
994
+ if (authHeader.toLowerCase().startsWith("bearer ")) {
995
+ return authHeader.slice(7).trim();
996
+ }
997
+ return "";
998
+ };
999
+ var authorizeRequest = async (request, config) => {
1000
+ const authConfig = config?.auth;
1001
+ if (!authConfig?.required) {
1002
+ return true;
1003
+ }
1004
+ const token = extractToken(request, authConfig);
1005
+ if (!token) {
1006
+ return false;
1007
+ }
1008
+ if (authConfig.validate) {
1009
+ return await authConfig.validate(token, request);
1010
+ }
1011
+ return token === (process.env.AGENT_API_KEY ?? "");
1012
+ };
1013
+ var initProject = async (projectName, options) => {
1014
+ const baseDir = options?.workingDir ?? process.cwd();
1015
+ const projectDir = resolve2(baseDir, projectName);
1016
+ await mkdir2(projectDir, { recursive: true });
1017
+ await ensureFile(resolve2(projectDir, "AGENT.md"), AGENT_TEMPLATE);
1018
+ await ensureFile(resolve2(projectDir, "agentl.config.js"), CONFIG_TEMPLATE);
1019
+ await ensureFile(resolve2(projectDir, "package.json"), PACKAGE_TEMPLATE(projectName));
1020
+ await ensureFile(resolve2(projectDir, ".env.example"), ENV_TEMPLATE);
1021
+ await ensureFile(resolve2(projectDir, ".gitignore"), GITIGNORE_TEMPLATE);
1022
+ await ensureFile(resolve2(projectDir, "tests", "basic.yaml"), TEST_TEMPLATE);
1023
+ await ensureFile(resolve2(projectDir, "skills", "starter", "SKILL.md"), SKILL_TEMPLATE);
1024
+ await ensureFile(
1025
+ resolve2(projectDir, "skills", "starter", "tools", "starter-echo.ts"),
1026
+ SKILL_TOOL_TEMPLATE
1027
+ );
1028
+ process.stdout.write(`Initialized AgentL project at ${projectDir}
1029
+ `);
1030
+ };
1031
+ var updateAgentGuidance = async (workingDir) => {
1032
+ const agentPath = resolve2(workingDir, "AGENT.md");
1033
+ const content = await readFile2(agentPath, "utf8");
1034
+ const guidanceSectionPattern = /## Skill Authoring Guidance[\s\S]*?(?=\n## |\n# |$)/;
1035
+ const normalized = content.replace(/\s+$/g, "");
1036
+ const hasGuidance = guidanceSectionPattern.test(normalized);
1037
+ const updated = hasGuidance ? normalized.replace(guidanceSectionPattern, AGENT_SKILL_GUIDANCE) : `${normalized}
1038
+
1039
+ ${AGENT_SKILL_GUIDANCE}
1040
+ `;
1041
+ if (updated === normalized) {
1042
+ process.stdout.write("AGENT.md guidance is already up to date.\n");
1043
+ return false;
1044
+ }
1045
+ await writeFile2(agentPath, updated, "utf8");
1046
+ process.stdout.write("Updated AGENT.md with latest skill authoring guidance.\n");
1047
+ return true;
1048
+ };
1049
+ var formatSseEvent = (event) => `event: ${event.type}
1050
+ data: ${JSON.stringify(event)}
1051
+
1052
+ `;
1053
+ var startDevServer = async (port, options) => {
1054
+ const workingDir = options?.workingDir ?? process.cwd();
1055
+ dotenv.config({ path: resolve2(workingDir, ".env") });
1056
+ const config = await loadAgentlConfig(workingDir);
1057
+ const harness = new AgentHarness({ workingDir });
1058
+ await harness.initialize();
1059
+ const telemetry = new TelemetryEmitter(config?.telemetry);
1060
+ const stateStore = createStateStore(config?.state);
1061
+ const conversationStore = new FileConversationStore(workingDir);
1062
+ const sessionStore = new SessionStore();
1063
+ const loginRateLimiter = new LoginRateLimiter();
1064
+ const passphrase = process.env.AGENT_UI_PASSPHRASE ?? "";
1065
+ const isProduction = resolveHarnessEnvironment() === "production";
1066
+ if (isProduction && passphrase.length === 0) {
1067
+ throw new Error("AGENT_UI_PASSPHRASE is required when AGENTL_ENV/NODE_ENV is production.");
1068
+ }
1069
+ const requireUiAuth = passphrase.length > 0;
1070
+ const secureCookies = isProduction;
1071
+ const server = createServer(async (request, response) => {
1072
+ if (!request.url || !request.method) {
1073
+ writeJson(response, 404, { error: "Not found" });
1074
+ return;
1075
+ }
1076
+ const [pathname] = request.url.split("?");
1077
+ if (pathname === "/" && request.method === "GET") {
1078
+ writeHtml(response, 200, renderWebUiHtml());
1079
+ return;
1080
+ }
1081
+ if (pathname === "/health" && request.method === "GET") {
1082
+ writeJson(response, 200, { status: "ok" });
1083
+ return;
1084
+ }
1085
+ const cookies = parseCookies(request);
1086
+ const sessionId = cookies.agentl_session;
1087
+ const session = sessionId ? sessionStore.get(sessionId) : void 0;
1088
+ const ownerId = session?.ownerId ?? "local-owner";
1089
+ const requiresCsrfValidation = request.method !== "GET" && request.method !== "HEAD" && request.method !== "OPTIONS";
1090
+ if (pathname === "/api/auth/session" && request.method === "GET") {
1091
+ if (!requireUiAuth) {
1092
+ writeJson(response, 200, { authenticated: true, csrfToken: "" });
1093
+ return;
1094
+ }
1095
+ if (!session) {
1096
+ writeJson(response, 200, { authenticated: false });
1097
+ return;
1098
+ }
1099
+ writeJson(response, 200, {
1100
+ authenticated: true,
1101
+ sessionId: session.sessionId,
1102
+ ownerId: session.ownerId,
1103
+ csrfToken: session.csrfToken
1104
+ });
1105
+ return;
1106
+ }
1107
+ if (pathname === "/api/auth/login" && request.method === "POST") {
1108
+ if (!requireUiAuth) {
1109
+ writeJson(response, 200, { authenticated: true, csrfToken: "" });
1110
+ return;
1111
+ }
1112
+ const ip = getRequestIp(request);
1113
+ const canAttempt = loginRateLimiter.canAttempt(ip);
1114
+ if (!canAttempt.allowed) {
1115
+ writeJson(response, 429, {
1116
+ code: "AUTH_RATE_LIMIT",
1117
+ message: "Too many failed login attempts. Try again later.",
1118
+ retryAfterSeconds: canAttempt.retryAfterSeconds
1119
+ });
1120
+ return;
1121
+ }
1122
+ const body = await readRequestBody(request);
1123
+ const provided = body.passphrase ?? "";
1124
+ if (!verifyPassphrase(provided, passphrase)) {
1125
+ const failure = loginRateLimiter.registerFailure(ip);
1126
+ writeJson(response, 401, {
1127
+ code: "AUTH_ERROR",
1128
+ message: "Invalid passphrase",
1129
+ retryAfterSeconds: failure.retryAfterSeconds
1130
+ });
1131
+ return;
1132
+ }
1133
+ loginRateLimiter.registerSuccess(ip);
1134
+ const createdSession = sessionStore.create(ownerId);
1135
+ setCookie(response, "agentl_session", createdSession.sessionId, {
1136
+ httpOnly: true,
1137
+ secure: secureCookies,
1138
+ sameSite: "Lax",
1139
+ path: "/",
1140
+ maxAge: 60 * 60 * 8
1141
+ });
1142
+ writeJson(response, 200, {
1143
+ authenticated: true,
1144
+ csrfToken: createdSession.csrfToken
1145
+ });
1146
+ return;
1147
+ }
1148
+ if (pathname === "/api/auth/logout" && request.method === "POST") {
1149
+ if (session?.sessionId) {
1150
+ sessionStore.delete(session.sessionId);
1151
+ }
1152
+ setCookie(response, "agentl_session", "", {
1153
+ httpOnly: true,
1154
+ secure: secureCookies,
1155
+ sameSite: "Lax",
1156
+ path: "/",
1157
+ maxAge: 0
1158
+ });
1159
+ writeJson(response, 200, { ok: true });
1160
+ return;
1161
+ }
1162
+ if (pathname.startsWith("/api/")) {
1163
+ if (requireUiAuth && !session) {
1164
+ writeJson(response, 401, {
1165
+ code: "AUTH_ERROR",
1166
+ message: "Authentication required"
1167
+ });
1168
+ return;
1169
+ }
1170
+ if (requireUiAuth && requiresCsrfValidation && pathname !== "/api/auth/login" && request.headers["x-csrf-token"] !== session?.csrfToken) {
1171
+ writeJson(response, 403, {
1172
+ code: "CSRF_ERROR",
1173
+ message: "Invalid CSRF token"
1174
+ });
1175
+ return;
1176
+ }
1177
+ }
1178
+ if (pathname === "/api/conversations" && request.method === "GET") {
1179
+ const conversations = await conversationStore.list(ownerId);
1180
+ writeJson(response, 200, {
1181
+ conversations: conversations.map((conversation) => ({
1182
+ conversationId: conversation.conversationId,
1183
+ title: conversation.title,
1184
+ runtimeRunId: conversation.runtimeRunId,
1185
+ ownerId: conversation.ownerId,
1186
+ tenantId: conversation.tenantId,
1187
+ createdAt: conversation.createdAt,
1188
+ updatedAt: conversation.updatedAt,
1189
+ messageCount: conversation.messages.length
1190
+ }))
1191
+ });
1192
+ return;
1193
+ }
1194
+ if (pathname === "/api/conversations" && request.method === "POST") {
1195
+ const body = await readRequestBody(request);
1196
+ const conversation = await conversationStore.create(ownerId, body.title);
1197
+ writeJson(response, 201, { conversation });
1198
+ return;
1199
+ }
1200
+ const conversationPathMatch = pathname.match(/^\/api\/conversations\/([^/]+)$/);
1201
+ if (conversationPathMatch) {
1202
+ const conversationId = decodeURIComponent(conversationPathMatch[1] ?? "");
1203
+ const conversation = await conversationStore.get(conversationId);
1204
+ if (!conversation || conversation.ownerId !== ownerId) {
1205
+ writeJson(response, 404, {
1206
+ code: "CONVERSATION_NOT_FOUND",
1207
+ message: "Conversation not found"
1208
+ });
1209
+ return;
1210
+ }
1211
+ if (request.method === "GET") {
1212
+ writeJson(response, 200, { conversation });
1213
+ return;
1214
+ }
1215
+ if (request.method === "PATCH") {
1216
+ const body = await readRequestBody(request);
1217
+ if (!body.title || body.title.trim().length === 0) {
1218
+ writeJson(response, 400, {
1219
+ code: "VALIDATION_ERROR",
1220
+ message: "title is required"
1221
+ });
1222
+ return;
1223
+ }
1224
+ const updated = await conversationStore.rename(conversationId, body.title);
1225
+ writeJson(response, 200, { conversation: updated });
1226
+ return;
1227
+ }
1228
+ if (request.method === "DELETE") {
1229
+ await conversationStore.delete(conversationId);
1230
+ writeJson(response, 200, { ok: true });
1231
+ return;
1232
+ }
1233
+ }
1234
+ const conversationMessageMatch = pathname.match(/^\/api\/conversations\/([^/]+)\/messages$/);
1235
+ if (conversationMessageMatch && request.method === "POST") {
1236
+ const conversationId = decodeURIComponent(conversationMessageMatch[1] ?? "");
1237
+ const conversation = await conversationStore.get(conversationId);
1238
+ if (!conversation || conversation.ownerId !== ownerId) {
1239
+ writeJson(response, 404, {
1240
+ code: "CONVERSATION_NOT_FOUND",
1241
+ message: "Conversation not found"
1242
+ });
1243
+ return;
1244
+ }
1245
+ const body = await readRequestBody(request);
1246
+ const messageText = body.message?.trim() ?? "";
1247
+ if (!messageText) {
1248
+ writeJson(response, 400, {
1249
+ code: "VALIDATION_ERROR",
1250
+ message: "message is required"
1251
+ });
1252
+ return;
1253
+ }
1254
+ if (conversation.messages.length === 0 && (conversation.title === "New conversation" || conversation.title.trim().length === 0)) {
1255
+ conversation.title = inferConversationTitle(messageText);
1256
+ }
1257
+ response.writeHead(200, {
1258
+ "Content-Type": "text/event-stream",
1259
+ "Cache-Control": "no-cache",
1260
+ Connection: "keep-alive"
1261
+ });
1262
+ let latestRunId = conversation.runtimeRunId ?? "";
1263
+ let assistantResponse = "";
1264
+ try {
1265
+ for await (const event of harness.run({
1266
+ task: messageText,
1267
+ parameters: body.parameters,
1268
+ messages: conversation.messages
1269
+ })) {
1270
+ if (event.type === "run:started") {
1271
+ latestRunId = event.runId;
1272
+ }
1273
+ if (event.type === "model:chunk") {
1274
+ assistantResponse += event.content;
1275
+ }
1276
+ if (event.type === "run:completed" && assistantResponse.length === 0 && event.result.response) {
1277
+ assistantResponse = event.result.response;
1278
+ }
1279
+ await telemetry.emit(event);
1280
+ response.write(formatSseEvent(event));
1281
+ }
1282
+ conversation.messages = [
1283
+ ...conversation.messages,
1284
+ { role: "user", content: messageText },
1285
+ { role: "assistant", content: assistantResponse }
1286
+ ];
1287
+ conversation.runtimeRunId = latestRunId || conversation.runtimeRunId;
1288
+ conversation.updatedAt = Date.now();
1289
+ await conversationStore.update(conversation);
1290
+ } catch (error) {
1291
+ response.write(
1292
+ formatSseEvent({
1293
+ type: "run:error",
1294
+ runId: latestRunId || "run_unknown",
1295
+ error: {
1296
+ code: "RUN_ERROR",
1297
+ message: error instanceof Error ? error.message : "Unknown error"
1298
+ }
1299
+ })
1300
+ );
1301
+ } finally {
1302
+ response.end();
1303
+ }
1304
+ return;
1305
+ }
1306
+ if (!await authorizeRequest(request, config)) {
1307
+ writeJson(response, 401, {
1308
+ code: "AUTH_ERROR",
1309
+ message: "Authentication failed"
1310
+ });
1311
+ return;
1312
+ }
1313
+ if (pathname === "/run/sync" && request.method === "POST") {
1314
+ try {
1315
+ const input = await readRequestBody(request);
1316
+ const output = await harness.runToCompletion(input);
1317
+ await stateStore.set({
1318
+ runId: output.runId,
1319
+ messages: output.messages,
1320
+ updatedAt: Date.now()
1321
+ });
1322
+ for (const event of output.events) {
1323
+ await telemetry.emit(event);
1324
+ }
1325
+ writeJson(response, 200, {
1326
+ runId: output.runId,
1327
+ status: output.result.status,
1328
+ result: output.result
1329
+ });
1330
+ } catch (error) {
1331
+ writeJson(response, 500, {
1332
+ code: "RUN_ERROR",
1333
+ message: error instanceof Error ? error.message : "Unknown error"
1334
+ });
1335
+ }
1336
+ return;
1337
+ }
1338
+ if (pathname === "/run" && request.method === "POST") {
1339
+ response.writeHead(200, {
1340
+ "Content-Type": "text/event-stream",
1341
+ "Cache-Control": "no-cache",
1342
+ Connection: "keep-alive"
1343
+ });
1344
+ try {
1345
+ const input = await readRequestBody(request);
1346
+ let runId = "";
1347
+ let finalResponse = "";
1348
+ const baseMessages = [
1349
+ ...input.messages ?? [],
1350
+ { role: "user", content: input.task }
1351
+ ];
1352
+ for await (const event of harness.run(input)) {
1353
+ if (event.type === "run:started") {
1354
+ runId = event.runId;
1355
+ }
1356
+ if (event.type === "run:completed") {
1357
+ finalResponse = event.result.response ?? "";
1358
+ }
1359
+ await telemetry.emit(event);
1360
+ response.write(formatSseEvent(event));
1361
+ }
1362
+ if (runId) {
1363
+ await stateStore.set({
1364
+ runId,
1365
+ messages: [...baseMessages, { role: "assistant", content: finalResponse }],
1366
+ updatedAt: Date.now()
1367
+ });
1368
+ }
1369
+ } catch (error) {
1370
+ response.write(
1371
+ formatSseEvent({
1372
+ type: "run:error",
1373
+ runId: "run_unknown",
1374
+ error: {
1375
+ code: "RUN_ERROR",
1376
+ message: error instanceof Error ? error.message : "Unknown error"
1377
+ }
1378
+ })
1379
+ );
1380
+ } finally {
1381
+ response.end();
1382
+ }
1383
+ return;
1384
+ }
1385
+ if (pathname === "/continue" && request.method === "POST") {
1386
+ try {
1387
+ const body = await readRequestBody(request);
1388
+ if (!body.runId || !body.message) {
1389
+ writeJson(response, 400, {
1390
+ code: "VALIDATION_ERROR",
1391
+ message: "Both runId and message are required"
1392
+ });
1393
+ return;
1394
+ }
1395
+ const state = await stateStore.get(body.runId);
1396
+ if (!state) {
1397
+ writeJson(response, 404, {
1398
+ code: "RUN_NOT_FOUND",
1399
+ message: `No conversation found for runId ${body.runId}`
1400
+ });
1401
+ return;
1402
+ }
1403
+ const output = await harness.runToCompletion({
1404
+ task: body.message,
1405
+ parameters: body.parameters,
1406
+ messages: state.messages
1407
+ });
1408
+ await stateStore.set({
1409
+ runId: output.runId,
1410
+ messages: output.messages,
1411
+ updatedAt: Date.now()
1412
+ });
1413
+ for (const event of output.events) {
1414
+ await telemetry.emit(event);
1415
+ }
1416
+ writeJson(response, 200, {
1417
+ runId: output.runId,
1418
+ status: output.result.status,
1419
+ result: output.result
1420
+ });
1421
+ } catch (error) {
1422
+ writeJson(response, 500, {
1423
+ code: "CONTINUE_ERROR",
1424
+ message: error instanceof Error ? error.message : "Unknown error"
1425
+ });
1426
+ }
1427
+ return;
1428
+ }
1429
+ writeJson(response, 404, { error: "Not found" });
1430
+ });
1431
+ const actualPort = await listenOnAvailablePort(server, port);
1432
+ if (actualPort !== port) {
1433
+ process.stdout.write(
1434
+ `Port ${port} is in use, switched to ${actualPort}.
1435
+ `
1436
+ );
1437
+ }
1438
+ process.stdout.write(`AgentL dev server running at http://localhost:${actualPort}
1439
+ `);
1440
+ return server;
1441
+ };
1442
+ var runOnce = async (task, options) => {
1443
+ const workingDir = options.workingDir ?? process.cwd();
1444
+ dotenv.config({ path: resolve2(workingDir, ".env") });
1445
+ const config = await loadAgentlConfig(workingDir);
1446
+ const harness = new AgentHarness({ workingDir });
1447
+ const telemetry = new TelemetryEmitter(config?.telemetry);
1448
+ await harness.initialize();
1449
+ const fileBlobs = await Promise.all(
1450
+ options.filePaths.map(async (path) => {
1451
+ const content = await readFile2(resolve2(workingDir, path), "utf8");
1452
+ return `# File: ${path}
1453
+ ${content}`;
1454
+ })
1455
+ );
1456
+ const input = {
1457
+ task: fileBlobs.length > 0 ? `${task}
1458
+
1459
+ ${fileBlobs.join("\n\n")}` : task,
1460
+ parameters: options.params
1461
+ };
1462
+ if (options.json) {
1463
+ const output = await harness.runToCompletion(input);
1464
+ for (const event of output.events) {
1465
+ await telemetry.emit(event);
1466
+ }
1467
+ process.stdout.write(`${JSON.stringify(output, null, 2)}
1468
+ `);
1469
+ return;
1470
+ }
1471
+ for await (const event of harness.run(input)) {
1472
+ await telemetry.emit(event);
1473
+ if (event.type === "model:chunk") {
1474
+ process.stdout.write(event.content);
1475
+ }
1476
+ if (event.type === "run:error") {
1477
+ process.stderr.write(`
1478
+ Error: ${event.error.message}
1479
+ `);
1480
+ }
1481
+ if (event.type === "run:completed") {
1482
+ process.stdout.write("\n");
1483
+ }
1484
+ }
1485
+ };
1486
+ var runInteractive = async (workingDir, params) => {
1487
+ dotenv.config({ path: resolve2(workingDir, ".env") });
1488
+ let pendingApproval = null;
1489
+ let onApprovalRequest = null;
1490
+ const approvalHandler = async (request) => {
1491
+ return new Promise((resolveApproval) => {
1492
+ const req = {
1493
+ tool: request.tool,
1494
+ input: request.input,
1495
+ approvalId: request.approvalId,
1496
+ resolve: resolveApproval
1497
+ };
1498
+ pendingApproval = req;
1499
+ if (onApprovalRequest) {
1500
+ onApprovalRequest(req);
1501
+ }
1502
+ });
1503
+ };
1504
+ const harness = new AgentHarness({
1505
+ workingDir,
1506
+ environment: resolveHarnessEnvironment(),
1507
+ approvalHandler
1508
+ });
1509
+ await harness.initialize();
1510
+ try {
1511
+ const { runInteractiveInk } = await import("./run-interactive-ink-LQXS5GMO.js");
1512
+ await runInteractiveInk({
1513
+ harness,
1514
+ params,
1515
+ workingDir,
1516
+ onSetApprovalCallback: (cb) => {
1517
+ onApprovalRequest = cb;
1518
+ if (pendingApproval) {
1519
+ cb(pendingApproval);
1520
+ }
1521
+ }
1522
+ });
1523
+ } finally {
1524
+ await harness.shutdown();
1525
+ }
1526
+ };
1527
+ var listTools = async (workingDir) => {
1528
+ dotenv.config({ path: resolve2(workingDir, ".env") });
1529
+ const harness = new AgentHarness({ workingDir });
1530
+ await harness.initialize();
1531
+ const tools = harness.listTools();
1532
+ if (tools.length === 0) {
1533
+ process.stdout.write("No tools registered.\n");
1534
+ return;
1535
+ }
1536
+ process.stdout.write("Available tools:\n");
1537
+ for (const tool of tools) {
1538
+ process.stdout.write(`- ${tool.name}: ${tool.description}
1539
+ `);
1540
+ }
1541
+ };
1542
+ var runInstallCommand = async (workingDir, packageNameOrPath) => await new Promise((resolveInstall, rejectInstall) => {
1543
+ const child = spawn("pnpm", ["add", packageNameOrPath], {
1544
+ cwd: workingDir,
1545
+ stdio: "inherit",
1546
+ env: process.env
1547
+ });
1548
+ child.on("exit", (code) => {
1549
+ if (code === 0) {
1550
+ resolveInstall();
1551
+ return;
1552
+ }
1553
+ rejectInstall(new Error(`pnpm add failed with exit code ${code ?? -1}`));
1554
+ });
1555
+ });
1556
+ var validateSkillPackage = async (workingDir, packageNameOrPath) => {
1557
+ const packageJsonPath = packageNameOrPath.startsWith(".") || packageNameOrPath.startsWith("/") ? resolve2(workingDir, packageNameOrPath, "package.json") : require2.resolve(`${packageNameOrPath}/package.json`, {
1558
+ paths: [workingDir]
1559
+ });
1560
+ const skillRoot = resolve2(packageJsonPath, "..");
1561
+ const skillManifest = resolve2(skillRoot, "SKILL.md");
1562
+ try {
1563
+ await access(skillManifest);
1564
+ } catch {
1565
+ throw new Error(`Skill validation failed: missing SKILL.md in ${skillRoot}`);
1566
+ }
1567
+ };
1568
+ var addSkill = async (workingDir, packageNameOrPath) => {
1569
+ await runInstallCommand(workingDir, packageNameOrPath);
1570
+ await validateSkillPackage(workingDir, packageNameOrPath);
1571
+ process.stdout.write(`Added skill: ${packageNameOrPath}
1572
+ `);
1573
+ };
1574
+ var runTests = async (workingDir, filePath) => {
1575
+ dotenv.config({ path: resolve2(workingDir, ".env") });
1576
+ const testFilePath = filePath ?? resolve2(workingDir, "tests", "basic.yaml");
1577
+ const content = await readFile2(testFilePath, "utf8");
1578
+ const parsed = YAML.parse(content);
1579
+ const tests = parsed.tests ?? [];
1580
+ const harness = new AgentHarness({ workingDir });
1581
+ await harness.initialize();
1582
+ let passed = 0;
1583
+ let failed = 0;
1584
+ for (const testCase of tests) {
1585
+ try {
1586
+ const output = await harness.runToCompletion({ task: testCase.task });
1587
+ const response = output.result.response ?? "";
1588
+ const events = output.events;
1589
+ const expectation = testCase.expect ?? {};
1590
+ const checks = [];
1591
+ if (expectation.contains) {
1592
+ checks.push(response.includes(expectation.contains));
1593
+ }
1594
+ if (typeof expectation.maxSteps === "number") {
1595
+ checks.push(output.result.steps <= expectation.maxSteps);
1596
+ }
1597
+ if (typeof expectation.maxTokens === "number") {
1598
+ checks.push(
1599
+ output.result.tokens.input + output.result.tokens.output <= expectation.maxTokens
1600
+ );
1601
+ }
1602
+ if (expectation.refusal) {
1603
+ checks.push(
1604
+ response.toLowerCase().includes("can't") || response.toLowerCase().includes("cannot")
1605
+ );
1606
+ }
1607
+ if (expectation.toolCalled) {
1608
+ checks.push(
1609
+ events.some(
1610
+ (event) => event.type === "tool:started" && event.tool === expectation.toolCalled
1611
+ )
1612
+ );
1613
+ }
1614
+ const ok = checks.length === 0 ? output.result.status === "completed" : checks.every(Boolean);
1615
+ if (ok) {
1616
+ passed += 1;
1617
+ process.stdout.write(`PASS ${testCase.name}
1618
+ `);
1619
+ } else {
1620
+ failed += 1;
1621
+ process.stdout.write(`FAIL ${testCase.name}
1622
+ `);
1623
+ }
1624
+ } catch (error) {
1625
+ failed += 1;
1626
+ process.stdout.write(
1627
+ `FAIL ${testCase.name} (${error instanceof Error ? error.message : "Unknown test error"})
1628
+ `
1629
+ );
1630
+ }
1631
+ }
1632
+ process.stdout.write(`
1633
+ Test summary: ${passed} passed, ${failed} failed
1634
+ `);
1635
+ return { passed, failed };
1636
+ };
1637
+ var buildTarget = async (workingDir, target) => {
1638
+ const outDir = resolve2(workingDir, ".agentl-build", target);
1639
+ await mkdir2(outDir, { recursive: true });
1640
+ const serverEntrypoint = `import { startDevServer } from "agentl";
1641
+
1642
+ const port = Number.parseInt(process.env.PORT ?? "3000", 10);
1643
+ await startDevServer(Number.isNaN(port) ? 3000 : port, { workingDir: process.cwd() });
1644
+ `;
1645
+ const runtimePackageJson = JSON.stringify(
1646
+ {
1647
+ name: "agentl-runtime-bundle",
1648
+ private: true,
1649
+ type: "module",
1650
+ scripts: {
1651
+ start: "node server.js"
1652
+ },
1653
+ dependencies: {
1654
+ agentl: "^0.1.0"
1655
+ }
1656
+ },
1657
+ null,
1658
+ 2
1659
+ );
1660
+ if (target === "vercel") {
1661
+ await mkdir2(resolve2(outDir, "api"), { recursive: true });
1662
+ await copyIfExists(resolve2(workingDir, "AGENT.md"), resolve2(outDir, "AGENT.md"));
1663
+ await copyIfExists(
1664
+ resolve2(workingDir, "agentl.config.js"),
1665
+ resolve2(outDir, "agentl.config.js")
1666
+ );
1667
+ await copyIfExists(resolve2(workingDir, "skills"), resolve2(outDir, "skills"));
1668
+ await copyIfExists(resolve2(workingDir, "tests"), resolve2(outDir, "tests"));
1669
+ await writeFile2(
1670
+ resolve2(outDir, "vercel.json"),
1671
+ JSON.stringify(
1672
+ {
1673
+ version: 2,
1674
+ builds: [
1675
+ {
1676
+ src: "api/index.js",
1677
+ use: "@vercel/node@3.2.24",
1678
+ config: {
1679
+ includeFiles: [
1680
+ "AGENT.md",
1681
+ "agentl.config.js",
1682
+ "skills/**",
1683
+ "tests/**"
1684
+ ]
1685
+ }
1686
+ }
1687
+ ],
1688
+ routes: [{ src: "/(.*)", dest: "/api/index.js" }]
1689
+ },
1690
+ null,
1691
+ 2
1692
+ ),
1693
+ "utf8"
1694
+ );
1695
+ await buildVercelHandlerBundle(outDir);
1696
+ await writeFile2(
1697
+ resolve2(outDir, "package.json"),
1698
+ JSON.stringify(
1699
+ {
1700
+ private: true,
1701
+ type: "module",
1702
+ engines: {
1703
+ node: "20.x"
1704
+ },
1705
+ dependencies: VERCEL_RUNTIME_DEPENDENCIES
1706
+ },
1707
+ null,
1708
+ 2
1709
+ ),
1710
+ "utf8"
1711
+ );
1712
+ } else if (target === "docker") {
1713
+ await writeFile2(
1714
+ resolve2(outDir, "Dockerfile"),
1715
+ `FROM node:20-slim
1716
+ WORKDIR /app
1717
+ COPY package.json package.json
1718
+ COPY AGENT.md AGENT.md
1719
+ COPY agentl.config.js agentl.config.js
1720
+ COPY skills skills
1721
+ COPY tests tests
1722
+ COPY .env.example .env.example
1723
+ RUN corepack enable && npm install -g agentl
1724
+ COPY server.js server.js
1725
+ EXPOSE 3000
1726
+ CMD ["node","server.js"]
1727
+ `,
1728
+ "utf8"
1729
+ );
1730
+ await writeFile2(resolve2(outDir, "server.js"), serverEntrypoint, "utf8");
1731
+ await writeFile2(resolve2(outDir, "package.json"), runtimePackageJson, "utf8");
1732
+ } else if (target === "lambda") {
1733
+ await writeFile2(
1734
+ resolve2(outDir, "lambda-handler.js"),
1735
+ `import { startDevServer } from "agentl";
1736
+ let serverPromise;
1737
+ export const handler = async (event = {}) => {
1738
+ if (!serverPromise) {
1739
+ serverPromise = startDevServer(0, { workingDir: process.cwd() });
1740
+ }
1741
+ const body = JSON.stringify({
1742
+ status: "ready",
1743
+ route: event.rawPath ?? event.path ?? "/",
1744
+ });
1745
+ return { statusCode: 200, headers: { "content-type": "application/json" }, body };
1746
+ };
1747
+ `,
1748
+ "utf8"
1749
+ );
1750
+ await writeFile2(resolve2(outDir, "package.json"), runtimePackageJson, "utf8");
1751
+ } else if (target === "fly") {
1752
+ await writeFile2(
1753
+ resolve2(outDir, "fly.toml"),
1754
+ `app = "agentl-app"
1755
+ [env]
1756
+ PORT = "3000"
1757
+ [http_service]
1758
+ internal_port = 3000
1759
+ force_https = true
1760
+ auto_start_machines = true
1761
+ auto_stop_machines = "stop"
1762
+ min_machines_running = 0
1763
+ `,
1764
+ "utf8"
1765
+ );
1766
+ await writeFile2(
1767
+ resolve2(outDir, "Dockerfile"),
1768
+ `FROM node:20-slim
1769
+ WORKDIR /app
1770
+ COPY package.json package.json
1771
+ COPY AGENT.md AGENT.md
1772
+ COPY agentl.config.js agentl.config.js
1773
+ COPY skills skills
1774
+ COPY tests tests
1775
+ RUN npm install -g agentl
1776
+ COPY server.js server.js
1777
+ EXPOSE 3000
1778
+ CMD ["node","server.js"]
1779
+ `,
1780
+ "utf8"
1781
+ );
1782
+ await writeFile2(resolve2(outDir, "server.js"), serverEntrypoint, "utf8");
1783
+ await writeFile2(resolve2(outDir, "package.json"), runtimePackageJson, "utf8");
1784
+ } else {
1785
+ throw new Error(`Unsupported build target: ${target}`);
1786
+ }
1787
+ process.stdout.write(`Build artifacts generated at ${outDir}
1788
+ `);
1789
+ };
1790
+ var normalizeMcpName = (entry) => entry.name ?? entry.url ?? `mcp_${Date.now()}`;
1791
+ var mcpAdd = async (workingDir, options) => {
1792
+ const config = await loadAgentlConfig(workingDir) ?? { mcp: [] };
1793
+ const mcp = [...config.mcp ?? []];
1794
+ if (!options.url) {
1795
+ throw new Error("Remote MCP only: provide --url for a remote MCP server.");
1796
+ }
1797
+ mcp.push({
1798
+ name: options.name ?? normalizeMcpName({ url: options.url }),
1799
+ url: options.url,
1800
+ env: options.envVars ?? []
1801
+ });
1802
+ await writeConfigFile(workingDir, { ...config, mcp });
1803
+ process.stdout.write("MCP server added.\n");
1804
+ };
1805
+ var mcpList = async (workingDir) => {
1806
+ const config = await loadAgentlConfig(workingDir);
1807
+ const mcp = config?.mcp ?? [];
1808
+ if (mcp.length === 0) {
1809
+ process.stdout.write("No MCP servers configured.\n");
1810
+ return;
1811
+ }
1812
+ process.stdout.write("Configured MCP servers:\n");
1813
+ for (const entry of mcp) {
1814
+ process.stdout.write(`- ${entry.name ?? entry.url} (remote: ${entry.url})
1815
+ `);
1816
+ }
1817
+ };
1818
+ var mcpRemove = async (workingDir, name) => {
1819
+ const config = await loadAgentlConfig(workingDir) ?? { mcp: [] };
1820
+ const before = config.mcp ?? [];
1821
+ const filtered = before.filter((entry) => normalizeMcpName(entry) !== name);
1822
+ await writeConfigFile(workingDir, { ...config, mcp: filtered });
1823
+ process.stdout.write(`Removed MCP server: ${name}
1824
+ `);
1825
+ };
1826
+ var buildCli = () => {
1827
+ const program = new Command();
1828
+ program.name("agentl").description("CLI for building and running AgentL agents").version("0.1.0");
1829
+ program.command("init").argument("<name>", "project name").description("Scaffold a new AgentL project").action(async (name) => {
1830
+ await initProject(name);
1831
+ });
1832
+ program.command("dev").description("Run local development server").option("--port <port>", "server port", "3000").action(async (options) => {
1833
+ const port = Number.parseInt(options.port, 10);
1834
+ await startDevServer(Number.isNaN(port) ? 3e3 : port);
1835
+ });
1836
+ program.command("run").argument("[task]", "task to run").description("Execute the agent once").option("--param <keyValue>", "parameter key=value", (value, all) => {
1837
+ all.push(value);
1838
+ return all;
1839
+ }, []).option("--file <path>", "include file contents", (value, all) => {
1840
+ all.push(value);
1841
+ return all;
1842
+ }, []).option("--json", "output json", false).option("--interactive", "run in interactive mode", false).action(
1843
+ async (task, options) => {
1844
+ const params = parseParams(options.param);
1845
+ if (options.interactive) {
1846
+ await runInteractive(process.cwd(), params);
1847
+ return;
1848
+ }
1849
+ if (!task) {
1850
+ throw new Error("Task is required unless --interactive is used.");
1851
+ }
1852
+ await runOnce(task, {
1853
+ params,
1854
+ json: options.json,
1855
+ filePaths: options.file
1856
+ });
1857
+ }
1858
+ );
1859
+ program.command("tools").description("List all tools available to the agent").action(async () => {
1860
+ await listTools(process.cwd());
1861
+ });
1862
+ program.command("add").argument("<packageOrPath>", "skill package name/path").description("Add a skill package and validate SKILL.md").action(async (packageOrPath) => {
1863
+ await addSkill(process.cwd(), packageOrPath);
1864
+ });
1865
+ program.command("update-agent").description("Backfill latest default guidance into AGENT.md").action(async () => {
1866
+ await updateAgentGuidance(process.cwd());
1867
+ });
1868
+ program.command("test").argument("[file]", "test file path (yaml)").description("Run yaml-defined agent tests").action(async (file) => {
1869
+ const testFile = file ? resolve2(process.cwd(), file) : void 0;
1870
+ const result = await runTests(process.cwd(), testFile);
1871
+ if (result.failed > 0) {
1872
+ process.exitCode = 1;
1873
+ }
1874
+ });
1875
+ program.command("build").argument("<target>", "vercel|docker|lambda|fly").description("Generate build artifacts for deployment target").action(async (target) => {
1876
+ await buildTarget(process.cwd(), target);
1877
+ });
1878
+ const mcpCommand = program.command("mcp").description("Manage MCP servers");
1879
+ mcpCommand.command("add").requiredOption("--url <url>", "remote MCP url").option("--name <name>", "server name").option("--env <name>", "env variable (repeatable)", (value, all) => {
1880
+ all.push(value);
1881
+ return all;
1882
+ }, []).action(
1883
+ async (options) => {
1884
+ await mcpAdd(process.cwd(), {
1885
+ url: options.url,
1886
+ name: options.name,
1887
+ envVars: options.env
1888
+ });
1889
+ }
1890
+ );
1891
+ mcpCommand.command("list").description("List configured MCP servers").action(async () => {
1892
+ await mcpList(process.cwd());
1893
+ });
1894
+ mcpCommand.command("remove").argument("<name>", "server name").description("Remove an MCP server by name").action(async (name) => {
1895
+ await mcpRemove(process.cwd(), name);
1896
+ });
1897
+ return program;
1898
+ };
1899
+ var main = async (argv = process.argv) => {
1900
+ try {
1901
+ await buildCli().parseAsync(argv);
1902
+ } catch (error) {
1903
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "EADDRINUSE") {
1904
+ const message = "Port is already in use. Try `agentl dev --port 3001` or stop the process using port 3000.";
1905
+ process.stderr.write(`${message}
1906
+ `);
1907
+ process.exitCode = 1;
1908
+ return;
1909
+ }
1910
+ process.stderr.write(`${error instanceof Error ? error.message : "Unknown CLI error"}
1911
+ `);
1912
+ process.exitCode = 1;
1913
+ }
1914
+ };
1915
+ var packageRoot = resolve2(__dirname, "..");
1916
+
1917
+ export {
1918
+ initProject,
1919
+ updateAgentGuidance,
1920
+ startDevServer,
1921
+ runOnce,
1922
+ runInteractive,
1923
+ listTools,
1924
+ addSkill,
1925
+ runTests,
1926
+ buildTarget,
1927
+ mcpAdd,
1928
+ mcpList,
1929
+ mcpRemove,
1930
+ buildCli,
1931
+ main,
1932
+ packageRoot
1933
+ };