hyperclaw 5.2.0 → 5.2.2

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 (511) hide show
  1. package/README.md +227 -3
  2. package/dist/a2ui-protocol-A2xow5Ch.js +75 -0
  3. package/dist/a2ui-protocol-dTomAnFE.js +75 -0
  4. package/dist/agents-routing-95_s2yea.js +6 -0
  5. package/dist/agents-routing-Bz3SstlK.js +398 -0
  6. package/dist/agents-routing-DHDK2axt.js +6 -0
  7. package/dist/agents-routing-DRMS8Ol-.js +6 -0
  8. package/dist/agents-routing-biXULPch.js +398 -0
  9. package/dist/agents-routing-iQmIOe3k.js +398 -0
  10. package/dist/api-key-validation-BeQ2MZAT.js +64 -0
  11. package/dist/api-key-validation-C2WQk1oM.js +64 -0
  12. package/dist/api-keys-guide-2cD5Rf-K.js +149 -0
  13. package/dist/api-keys-guide-BdT2lfX6.js +149 -0
  14. package/dist/api-keys-guide-BwCIj8qd.js +149 -0
  15. package/dist/audit-1Anq45mH.js +441 -0
  16. package/dist/audit-BAVTInWP.js +441 -0
  17. package/dist/audit-CV0gLGaL.js +444 -0
  18. package/dist/audit-Dnt0XgZD.js +441 -0
  19. package/dist/audit-DqNGdIKU.js +441 -0
  20. package/dist/bounty-tools-Cx7BXUfz.js +211 -0
  21. package/dist/bounty-tools-DWvW3yc-.js +211 -0
  22. package/dist/bounty-tools-FI7DHmsS.js +211 -0
  23. package/dist/bounty-tools-cjmA3Hgk.js +211 -0
  24. package/dist/browser-tools-BGPBCApQ.js +5 -0
  25. package/dist/browser-tools-Btu_vB2d.js +179 -0
  26. package/dist/browser-tools-DF2nQ1hi.js +5 -0
  27. package/dist/browser-tools-DYx4p13A.js +179 -0
  28. package/dist/chat-4ZistSKP.js +310 -0
  29. package/dist/chat-BqiMMQc4.js +324 -0
  30. package/dist/chat-BxxYzPaz.js +324 -0
  31. package/dist/chat-C0W8lwhh.js +324 -0
  32. package/dist/chat-CKBxDWAQ.js +324 -0
  33. package/dist/chat-CkCcCkVG.js +324 -0
  34. package/dist/chat-DCOKsydK.js +310 -0
  35. package/dist/chat-DZcZ1Uli.js +310 -0
  36. package/dist/chat-DiIra4_i.js +324 -0
  37. package/dist/chat-R_NuOa1v.js +324 -0
  38. package/dist/claw-tasks-CIkuuhga.js +80 -0
  39. package/dist/claw-tasks-CquRilLP.js +80 -0
  40. package/dist/claw-tasks-xXtZpeY0.js +80 -0
  41. package/dist/config-BEz4yNRx.js +261 -0
  42. package/dist/config-Br73VMLb.js +261 -0
  43. package/dist/config-CXqmvq_H.js +7 -0
  44. package/dist/config-D5vF0kvV.js +261 -0
  45. package/dist/config-D_6MxFk3.js +7 -0
  46. package/dist/config-b2HmFrBr.js +7 -0
  47. package/dist/connector-1H0OW1h8.js +419 -0
  48. package/dist/connector-1qpQ5L-T.js +173 -0
  49. package/dist/connector-2OVpYt0c.js +213 -0
  50. package/dist/connector-8cFkE3X4.js +552 -0
  51. package/dist/connector-B2bZD1id.js +181 -0
  52. package/dist/connector-B3W7quzD.js +568 -0
  53. package/dist/connector-B4FWhOzd.js +189 -0
  54. package/dist/connector-B5fqvoZL.js +239 -0
  55. package/dist/connector-BA8ZbhPt.js +162 -0
  56. package/dist/connector-BFl0XIwB.js +182 -0
  57. package/dist/connector-BIGRhSuN.js +419 -0
  58. package/dist/connector-BK0qVbvh.js +498 -0
  59. package/dist/connector-BMtA4KSF.js +194 -0
  60. package/dist/connector-BPIrifW-.js +218 -0
  61. package/dist/connector-BRNU-rJ4.js +225 -0
  62. package/dist/connector-BS7lvyLd.js +213 -0
  63. package/dist/connector-BZ_-UPUL.js +305 -0
  64. package/dist/connector-Bd0NZ5bT.js +189 -0
  65. package/dist/connector-BjsPwu-Y.js +531 -0
  66. package/dist/connector-BnSsjz1D.js +167 -0
  67. package/dist/connector-BrogAqVQ.js +239 -0
  68. package/dist/connector-BsVTG3U3.js +181 -0
  69. package/dist/connector-By9pLJgR.js +340 -0
  70. package/dist/connector-C7c1ASzT.js +192 -0
  71. package/dist/connector-CIj28thK.js +182 -0
  72. package/dist/connector-CJkuYNd1.js +280 -0
  73. package/dist/connector-CPcUmIHz.js +552 -0
  74. package/dist/connector-CUlP4He3.js +194 -0
  75. package/dist/connector-CZg2I8Tn.js +350 -0
  76. package/dist/connector-C_NtpthL.js +498 -0
  77. package/dist/connector-CddDB9IK.js +192 -0
  78. package/dist/connector-ChQMspky.js +167 -0
  79. package/dist/connector-ClHFpI56.js +425 -0
  80. package/dist/connector-CmhUVhMT.js +531 -0
  81. package/dist/connector-CnX7lwCt.js +425 -0
  82. package/dist/connector-D36oGwnK.js +162 -0
  83. package/dist/connector-DDJ7Nxkq.js +286 -0
  84. package/dist/connector-DDn2QDuf.js +167 -0
  85. package/dist/connector-DO_bzgJn.js +167 -0
  86. package/dist/connector-DVcRo21Y.js +568 -0
  87. package/dist/connector-DhWs2anT.js +189 -0
  88. package/dist/connector-DsY1IXMz.js +508 -0
  89. package/dist/connector-DwRF3CQg.js +218 -0
  90. package/dist/connector-HG61cV9h.js +340 -0
  91. package/dist/connector-HR28FwA5.js +181 -0
  92. package/dist/connector-K0QGRYh5.js +85 -0
  93. package/dist/connector-NliR7NZZ.js +508 -0
  94. package/dist/connector-VolY_hP4.js +350 -0
  95. package/dist/connector-Wjx9ih70.js +286 -0
  96. package/dist/connector-dfqk7NYD.js +181 -0
  97. package/dist/connector-e0W4Mpmq.js +189 -0
  98. package/dist/connector-eK6_phVW.js +280 -0
  99. package/dist/connector-l7UmCYaL.js +225 -0
  100. package/dist/connector-n2YnOJYZ.js +305 -0
  101. package/dist/connector-orobFcqE.js +531 -0
  102. package/dist/connector-r1SRYSqX.js +173 -0
  103. package/dist/connector-tZgn5_Fk.js +85 -0
  104. package/dist/connector-wm4Oe1DK.js +181 -0
  105. package/dist/cost-tracker-DHTv6zpR.js +103 -0
  106. package/dist/cost-tracker-DJ1tiKcx.js +103 -0
  107. package/dist/cost-tracker-jbK_AoIV.js +103 -0
  108. package/dist/credentials-store-C0R-pQM7.js +5 -0
  109. package/dist/credentials-store-C9HwQSY2.js +5 -0
  110. package/dist/credentials-store-D5Xw3F75.js +89 -0
  111. package/dist/credentials-store-DIPxVk51.js +86 -0
  112. package/dist/credentials-store-DU2cVTiY.js +7 -0
  113. package/dist/credentials-store-Djqi3oXC.js +5 -0
  114. package/dist/credentials-store-HwLJ3GS2.js +87 -0
  115. package/dist/credentials-store-z16XvFZ2.js +86 -0
  116. package/dist/cron-tasks-4my0PJce.js +85 -0
  117. package/dist/cron-tasks-CJkI0lo3.js +82 -0
  118. package/dist/cron-tasks-DN1YjYhK.js +82 -0
  119. package/dist/cron-tasks-DuNdK89e.js +82 -0
  120. package/dist/daemon-3xj3FVuw.js +5 -0
  121. package/dist/daemon-3zd_nupj.js +333 -0
  122. package/dist/daemon-B9-h7ryw.js +7 -0
  123. package/dist/daemon-BLC4AL9L.js +401 -0
  124. package/dist/daemon-BR1uU7jH.js +333 -0
  125. package/dist/daemon-BRdtCOoC.js +7 -0
  126. package/dist/daemon-BnmNBHY5.js +384 -0
  127. package/dist/daemon-BwspQtiu.js +7 -0
  128. package/dist/daemon-Bx5HTGjk.js +404 -0
  129. package/dist/daemon-CCxpXxSb.js +7 -0
  130. package/dist/daemon-CEUxN3SQ.js +7 -0
  131. package/dist/daemon-CHk9_ezz.js +403 -0
  132. package/dist/daemon-CgrsZ0d9.js +320 -0
  133. package/dist/daemon-Cy7iD9au.js +7 -0
  134. package/dist/daemon-DCm9RCEz.js +401 -0
  135. package/dist/daemon-DNzuDyu8.js +7 -0
  136. package/dist/daemon-DWFWCLvh.js +7 -0
  137. package/dist/daemon-DgBZaFyi.js +355 -0
  138. package/dist/daemon-Dsyjad7g.js +7 -0
  139. package/dist/daemon-DwxPYrb6.js +404 -0
  140. package/dist/daemon-DxoPIGQG.js +333 -0
  141. package/dist/daemon-MXsEPeVa.js +7 -0
  142. package/dist/daemon-rpJ-J0bv.js +403 -0
  143. package/dist/daemon-sZVjFUoX.js +7 -0
  144. package/dist/delivery-8fo4GZ-j.js +95 -0
  145. package/dist/delivery-CkxNZIsF.js +95 -0
  146. package/dist/delivery-CtbHkJbB.js +95 -0
  147. package/dist/delivery-D1z3f3KW.js +4 -0
  148. package/dist/delivery-DKGpk5M4.js +4 -0
  149. package/dist/delivery-DReKOHyM.js +95 -0
  150. package/dist/delivery-Ddn-VajP.js +4 -0
  151. package/dist/delivery-DsoxcD2z.js +4 -0
  152. package/dist/destructive-gate-CEn4BsTd.js +101 -0
  153. package/dist/destructive-gate-CgCqfKuT.js +101 -0
  154. package/dist/destructive-gate-DcEpMEqP.js +101 -0
  155. package/dist/developer-keys-7rQ8M4Qo.js +127 -0
  156. package/dist/developer-keys-BeUpyenR.js +8 -0
  157. package/dist/developer-keys-CSmzA-dl.js +127 -0
  158. package/dist/developer-keys-KFGbGuZj.js +8 -0
  159. package/dist/device-auth-store-BDhzxuPc.js +5 -0
  160. package/dist/device-auth-store-Cjyn2XeY.js +86 -0
  161. package/dist/device-auth-store-DgSabRGa.js +7 -0
  162. package/dist/device-auth-store-LKgpU74c.js +88 -0
  163. package/dist/device-auth-store-UlkrF-9_.js +5 -0
  164. package/dist/device-auth-store-yvGLuYAl.js +86 -0
  165. package/dist/doctor-BcfmNAGV.js +233 -0
  166. package/dist/doctor-CEP3UQjn.js +227 -0
  167. package/dist/doctor-CmJh0JLr.js +6 -0
  168. package/dist/doctor-CtDvddSn.js +231 -0
  169. package/dist/doctor-DPoCaXsd.js +227 -0
  170. package/dist/doctor-DPvY68XB.js +6 -0
  171. package/dist/doctor-G6EMPukm.js +6 -0
  172. package/dist/doctor-tL9TXt9y.js +6 -0
  173. package/dist/engine-1fLMFUn2.js +7 -0
  174. package/dist/engine-7lSiOc0W.js +323 -0
  175. package/dist/engine-B83pxJM4.js +318 -0
  176. package/dist/engine-B8hxtYpN.js +323 -0
  177. package/dist/engine-BXqijc79.js +7 -0
  178. package/dist/engine-BfQ-vNqE.js +321 -0
  179. package/dist/engine-BlpKw8D4.js +7 -0
  180. package/dist/engine-BmN7L0jl.js +7 -0
  181. package/dist/engine-CRagwas6.js +321 -0
  182. package/dist/engine-CppTnNbG.js +7 -0
  183. package/dist/engine-CwAfDQbD.js +7 -0
  184. package/dist/engine-D5kY4hMJ.js +7 -0
  185. package/dist/engine-DJSfl_Hc.js +323 -0
  186. package/dist/engine-DQcMDIbU.js +305 -0
  187. package/dist/engine-W1I8kkgV.js +305 -0
  188. package/dist/engine-mVrq_pfQ.js +7 -0
  189. package/dist/env-resolve-BeamD7l5.js +10 -0
  190. package/dist/env-resolve-C0otwkgN.js +10 -0
  191. package/dist/env-resolve-CC_po9t5.js +10 -0
  192. package/dist/env-resolve-COjiKYD8.js +147 -0
  193. package/dist/env-resolve-CYiFHLAi.js +145 -0
  194. package/dist/env-resolve-ClZcv5-B.js +145 -0
  195. package/dist/env-resolve-DS92g2fk.js +151 -0
  196. package/dist/env-resolve-DkBUmcI3.js +10 -0
  197. package/dist/extraction-tools-6PREYSAK.js +5 -0
  198. package/dist/extraction-tools-B8F3nsLR.js +5 -0
  199. package/dist/extraction-tools-BX5HGgko.js +91 -0
  200. package/dist/extraction-tools-Co11UJdZ.js +91 -0
  201. package/dist/form_data-DDfyO9B0.js +8657 -0
  202. package/dist/form_data-DgWnyuDn.js +8657 -0
  203. package/dist/gateway-BfHcLG6d.js +194 -0
  204. package/dist/gateway-CzI8dnlS.js +196 -0
  205. package/dist/gateway-DNv10FFg.js +194 -0
  206. package/dist/gateway-DRh5v1KI.js +4 -0
  207. package/dist/gateway-DroPtqyM.js +6 -0
  208. package/dist/gateway-DyWwV0Nu.js +4 -0
  209. package/dist/gmail-watch-setup-BV4r_lgb.js +40 -0
  210. package/dist/gmail-watch-setup-CW_5D9g-.js +40 -0
  211. package/dist/gmail-watch-setup-xG9GkPwr.js +42 -0
  212. package/dist/health-CBy1PfzC.js +152 -0
  213. package/dist/health-Cq_yE5Ln.js +6 -0
  214. package/dist/heartbeat-engine-7I0dZeea.js +83 -0
  215. package/dist/heartbeat-engine-BZUNOanp.js +84 -0
  216. package/dist/heartbeat-engine-DNm8ggAs.js +83 -0
  217. package/dist/heartbeat-engine-tgK7xXmt.js +83 -0
  218. package/dist/hub-CI4qcd1b.js +515 -0
  219. package/dist/hub-CNQaC4JI.js +515 -0
  220. package/dist/hub-Co1SbxLs.js +6 -0
  221. package/dist/hub-eUh89obm.js +6 -0
  222. package/dist/hyperclawbot-Bkncybig.js +508 -0
  223. package/dist/hyperclawbot-C37Unss3.js +505 -0
  224. package/dist/hyperclawbot-CFHXZr12.js +505 -0
  225. package/dist/hyperclawbot-DGou0MZ6.js +508 -0
  226. package/dist/hyperclawbot-DnPIyjox.js +508 -0
  227. package/dist/hyperclawbot-GYFaTEgC.js +505 -0
  228. package/dist/hyperclawbot-mcLnyJyM.js +505 -0
  229. package/dist/hyperclawbot-xcastgTV.js +508 -0
  230. package/dist/hyperclawbot-y0i_joQK.js +505 -0
  231. package/dist/inference-BvmMO9dq.js +8 -0
  232. package/dist/inference-C2HOfRf8.js +2848 -0
  233. package/dist/inference-CKvR5Ik5.js +2841 -0
  234. package/dist/inference-DVVmhQn5.js +2841 -0
  235. package/dist/inference-DoM_iai-.js +2848 -0
  236. package/dist/inference-DwgXrvBb.js +6 -0
  237. package/dist/inference-Go1G6tnF.js +8 -0
  238. package/dist/inference-_ptQe0oG.js +2841 -0
  239. package/dist/inference-gK62s15E.js +6 -0
  240. package/dist/inference-lLDvSTR9.js +6 -0
  241. package/dist/knowledge-graph-4SxFnwEm.js +131 -0
  242. package/dist/knowledge-graph-BsH-HoUJ.js +131 -0
  243. package/dist/knowledge-graph-BxrAiV2B.js +134 -0
  244. package/dist/knowledge-graph-DCa91Nz5.js +131 -0
  245. package/dist/loader-7fz2fb92.js +400 -0
  246. package/dist/loader-B2jZXMBu.js +6 -0
  247. package/dist/loader-CbS0tIrR.js +4 -0
  248. package/dist/loader-Ckvv7vHF.js +410 -0
  249. package/dist/loader-CwOXDhFQ.js +400 -0
  250. package/dist/loader-DpEOgWXZ.js +4 -0
  251. package/dist/loader-DpYgmaul.js +4 -0
  252. package/dist/loader-DtyQP7wL.js +400 -0
  253. package/dist/logger-B3AqfQWG.js +84 -0
  254. package/dist/logger-B_q8yqmA.js +84 -0
  255. package/dist/logger-BxJklsDv.js +84 -0
  256. package/dist/logger-ry2oCfdf.js +86 -0
  257. package/dist/manager-9zwhTeQ5.js +233 -0
  258. package/dist/manager-B1RbCW6C.js +31 -0
  259. package/dist/manager-B90HEHxe.js +6 -0
  260. package/dist/manager-B94UWcTs.js +233 -0
  261. package/dist/manager-BDvL_oPs.js +4 -0
  262. package/dist/manager-BEatAtIB.js +31 -0
  263. package/dist/manager-BQf9drst.js +120 -0
  264. package/dist/manager-Bau1mIqb.js +6 -0
  265. package/dist/manager-BkqHak_e.js +247 -0
  266. package/dist/manager-BoFdZm-l.js +233 -0
  267. package/dist/manager-C2bq0AXc.js +233 -0
  268. package/dist/manager-CBe3W3eG.js +117 -0
  269. package/dist/manager-CoHr8_eJ.js +117 -0
  270. package/dist/manager-CuS13QUO.js +6 -0
  271. package/dist/manager-DO0pK2OI.js +117 -0
  272. package/dist/manager-DVetfBCH.js +6 -0
  273. package/dist/manager-Jd0qSzVe.js +35 -0
  274. package/dist/manager-TxFgaHT9.js +31 -0
  275. package/dist/manager-Yo6ZAofG.js +250 -0
  276. package/dist/mcp-B_WJiTZz.js +139 -0
  277. package/dist/mcp-DVhPLprc.js +139 -0
  278. package/dist/mcp-GWnLTVi-.js +142 -0
  279. package/dist/mcp-loader-B6xz7ftt.js +94 -0
  280. package/dist/mcp-loader-BLanJREp.js +94 -0
  281. package/dist/mcp-loader-Bx7FFxAU.js +94 -0
  282. package/dist/mcp-loader-CecsT-3O.js +93 -0
  283. package/dist/mcp-loader-Cr0LRQHE.js +93 -0
  284. package/dist/mcp-loader-D0rbtV3G.js +93 -0
  285. package/dist/memory-B47nvgOq.js +271 -0
  286. package/dist/memory-D-Py-cz5.js +273 -0
  287. package/dist/memory-D991eoj7.js +6 -0
  288. package/dist/memory-DoQoaHjo.js +4 -0
  289. package/dist/memory-auto-5aBZQJQY.js +5 -0
  290. package/dist/memory-auto-BTeOoLsb.js +306 -0
  291. package/dist/memory-auto-BvjfaflZ.js +5 -0
  292. package/dist/memory-auto-CSUt3aas.js +306 -0
  293. package/dist/memory-auto-CfpACu6s.js +306 -0
  294. package/dist/memory-auto-DI9Xpd-x.js +306 -0
  295. package/dist/memory-auto-D_mPVYqI.js +5 -0
  296. package/dist/memory-auto-PmKetZuo.js +5 -0
  297. package/dist/memory-auto-_Jv-Diw_.js +306 -0
  298. package/dist/memory-auto-rLBheyC0.js +5 -0
  299. package/dist/memory-integration-UFc6CdRA.js +91 -0
  300. package/dist/memory-integration-_NOy60Fj.js +91 -0
  301. package/dist/memory-integration-nbQ8esDu.js +91 -0
  302. package/dist/moltbook-B4znBD46.js +81 -0
  303. package/dist/moltbook-CGtA7Lb3.js +81 -0
  304. package/dist/moltbook-EZOfIwcN.js +81 -0
  305. package/dist/node-BvA5_2f_.js +222 -0
  306. package/dist/node-CRaZw_av.js +225 -0
  307. package/dist/node-CSOPY84m.js +222 -0
  308. package/dist/node-FPkFXYdU.js +225 -0
  309. package/dist/nodes-registry--DkZbn41.js +52 -0
  310. package/dist/nodes-registry-DYEH1aWn.js +52 -0
  311. package/dist/nodes-registry-jK7T0THg.js +52 -0
  312. package/dist/oauth-flow-B3S4T_SJ.js +147 -0
  313. package/dist/oauth-flow-CuQHP_RD.js +150 -0
  314. package/dist/oauth-flow-D_iqT6nr.js +150 -0
  315. package/dist/oauth-flow-Du2N6B2V.js +150 -0
  316. package/dist/oauth-provider-B2RBpiXg.js +111 -0
  317. package/dist/oauth-provider-C1qk9SI-.js +110 -0
  318. package/dist/oauth-provider-CDOMIZgF.js +110 -0
  319. package/dist/observability-4CyDqBWi.js +89 -0
  320. package/dist/observability-BfhV3r9r.js +89 -0
  321. package/dist/observability-DAnU8Ung.js +89 -0
  322. package/dist/onboard-3SoScSbC.js +11 -0
  323. package/dist/onboard-BAhuTUMO.js +4240 -0
  324. package/dist/onboard-BHKBzytX.js +13 -0
  325. package/dist/onboard-BVYo6E_l.js +3865 -0
  326. package/dist/onboard-Bf3ht6ct.js +11 -0
  327. package/dist/onboard-Bmpa_pxc.js +3865 -0
  328. package/dist/onboard-BwFFnEDj.js +13 -0
  329. package/dist/onboard-C-0A7RKN.js +4211 -0
  330. package/dist/onboard-CCuETEUr.js +3865 -0
  331. package/dist/onboard-CDi3B996.js +13 -0
  332. package/dist/onboard-CcXqOCHa.js +3862 -0
  333. package/dist/onboard-Cw85LmyN.js +13 -0
  334. package/dist/onboard-DU3acWAq.js +13 -0
  335. package/dist/onboard-DVEFIFRj.js +11 -0
  336. package/dist/onboard-DW8b3EUP.js +4250 -0
  337. package/dist/onboard-DfYWM7yN.js +13 -0
  338. package/dist/onboard-DiDTuD7m.js +13 -0
  339. package/dist/onboard-DqamkA0I.js +11 -0
  340. package/dist/onboard-DtDFU4lV.js +3865 -0
  341. package/dist/onboard-IdhgSexF.js +11 -0
  342. package/dist/onboard-Qh-qibLR.js +3861 -0
  343. package/dist/onboard-T54jLovz.js +13 -0
  344. package/dist/onboard-nQerZcpc.js +3862 -0
  345. package/dist/onboard-qXuXl5An.js +4250 -0
  346. package/dist/onboard-r2hLYfsL.js +3865 -0
  347. package/dist/onboard-xsSdyO6Y.js +3865 -0
  348. package/dist/onboard-yACJiQ6A.js +4215 -0
  349. package/dist/onboard-z1K8FTgh.js +13 -0
  350. package/dist/orchestrator-BIKrbOtx.js +6 -0
  351. package/dist/orchestrator-C71UI_0E.js +189 -0
  352. package/dist/orchestrator-C9I6EVhh.js +189 -0
  353. package/dist/orchestrator-CC6vuL6m.js +6 -0
  354. package/dist/orchestrator-CExmcac2.js +189 -0
  355. package/dist/orchestrator-CQm9v71d.js +6 -0
  356. package/dist/orchestrator-CSZnojZo.js +189 -0
  357. package/dist/orchestrator-Cc-gXExz.js +189 -0
  358. package/dist/orchestrator-CxySH0n5.js +6 -0
  359. package/dist/orchestrator-Cybvh-J0.js +189 -0
  360. package/dist/orchestrator-D-9pExNB.js +189 -0
  361. package/dist/orchestrator-DG-RjZIu.js +6 -0
  362. package/dist/orchestrator-DvEjhiJR.js +6 -0
  363. package/dist/orchestrator-FFpXJwSV.js +189 -0
  364. package/dist/orchestrator-f6IjivCr.js +6 -0
  365. package/dist/orchestrator-mPfwBFvX.js +6 -0
  366. package/dist/osint-BIGH02i8.js +277 -0
  367. package/dist/osint-Cc2Ju-o4.js +277 -0
  368. package/dist/osint-Cg3-CYHx.js +278 -0
  369. package/dist/pairing-BRPzVXzQ.js +198 -0
  370. package/dist/pairing-Cm78Tsdx.js +4 -0
  371. package/dist/pairing-D4sA3-Ha.js +6 -0
  372. package/dist/pairing-ouc_v-OX.js +196 -0
  373. package/dist/pc-access-BZvlAXYN.js +819 -0
  374. package/dist/pc-access-CziyndiO.js +8 -0
  375. package/dist/pc-access-D5k6dAfU.js +819 -0
  376. package/dist/pc-access-DoPSPiAK.js +8 -0
  377. package/dist/pending-approval-BaKZ0b_s.js +22 -0
  378. package/dist/pending-approval-CBVZcFJn.js +22 -0
  379. package/dist/pending-approval-DiZ96D8v.js +22 -0
  380. package/dist/providers-CFQC39vg.js +5 -0
  381. package/dist/providers-DP8T0QCR.js +1089 -0
  382. package/dist/reminders-store-BSIw5Y5z.js +58 -0
  383. package/dist/reminders-store-Bus52SjO.js +58 -0
  384. package/dist/renderer-CmMjrkqN.js +225 -0
  385. package/dist/renderer-_Y9mEqMM.js +225 -0
  386. package/dist/renderer-h3ar94cf.js +228 -0
  387. package/dist/rules-D3GcY_lt.js +103 -0
  388. package/dist/rules-DFoset7W.js +103 -0
  389. package/dist/rules-eJw9i4RF.js +106 -0
  390. package/dist/run-main.js +461 -333
  391. package/dist/runner-C-syOqBr.js +1273 -0
  392. package/dist/runner-C73am--A.js +1273 -0
  393. package/dist/runner-DKLq9jhv.js +1273 -0
  394. package/dist/runner-Im-aCXhh.js +1273 -0
  395. package/dist/runner-NvAzKXbv.js +1273 -0
  396. package/dist/security-2DPBzs5F.js +4 -0
  397. package/dist/security-BhhX8wJx.js +73 -0
  398. package/dist/server-7tmTtdPU.js +4 -0
  399. package/dist/server-A38RPbRE.js +1291 -0
  400. package/dist/server-B0k_pCt5.js +4 -0
  401. package/dist/server-BErPWJZ5.js +4 -0
  402. package/dist/server-BKo-zifC.js +4 -0
  403. package/dist/server-Bav63Eqx.js +4 -0
  404. package/dist/server-BbWQWOH4.js +4 -0
  405. package/dist/server-BfHtA0Y2.js +1278 -0
  406. package/dist/server-BiYaxlFV.js +1287 -0
  407. package/dist/server-C6htB4FI.js +4 -0
  408. package/dist/server-CB7cjcj4.js +1278 -0
  409. package/dist/server-CNiOi5dN.js +1285 -0
  410. package/dist/server-CSC4npaT.js +1285 -0
  411. package/dist/server-CZfP2Poz.js +1278 -0
  412. package/dist/server-C_YVts3e.js +4 -0
  413. package/dist/server-CbQl0M21.js +1278 -0
  414. package/dist/server-Cj45rxn-.js +1292 -0
  415. package/dist/server-Ct7Fl3SE.js +1285 -0
  416. package/dist/server-D9q-3mLF.js +1292 -0
  417. package/dist/server-DRc26z9e.js +4 -0
  418. package/dist/server-DT7JjjVD.js +4 -0
  419. package/dist/server-DacRJyZn.js +4 -0
  420. package/dist/server-PCtHMXe2.js +1292 -0
  421. package/dist/server-wXCH_TCU.js +4 -0
  422. package/dist/session-store-7ZPOoB81.js +5 -0
  423. package/dist/session-store-BOa2y_EQ.js +5 -0
  424. package/dist/session-store-BYEr8j52.js +139 -0
  425. package/dist/session-store-Bx7lBD_a.js +141 -0
  426. package/dist/session-store-C13h7I2r.js +136 -0
  427. package/dist/session-store-CUHgJ0Xr.js +5 -0
  428. package/dist/session-store-cbtK6hx9.js +136 -0
  429. package/dist/session-store-eecMioKI.js +5 -0
  430. package/dist/sessions-tools-B5_ow-s7.js +5 -0
  431. package/dist/sessions-tools-CG2mvJo6.js +95 -0
  432. package/dist/sessions-tools-DVSejkNU.js +95 -0
  433. package/dist/sessions-tools-fOL1N3Zu.js +5 -0
  434. package/dist/skill-loader-99egKAGN.js +160 -0
  435. package/dist/skill-loader-Bl6pYxNN.js +160 -0
  436. package/dist/skill-loader-D4D5kfDu.js +7 -0
  437. package/dist/skill-loader-DwbmjEDa.js +7 -0
  438. package/dist/skill-runtime-1CrUOOGv.js +5 -0
  439. package/dist/skill-runtime-B-2O7Vgb.js +102 -0
  440. package/dist/skill-runtime-B7PutgyZ.js +5 -0
  441. package/dist/skill-runtime-BGNtPD_L.js +102 -0
  442. package/dist/skill-runtime-BUhMkMzO.js +5 -0
  443. package/dist/skill-runtime-Bv7fCCx8.js +102 -0
  444. package/dist/skill-runtime-Bx2HHcta.js +102 -0
  445. package/dist/skill-runtime-C6HVvnmN.js +5 -0
  446. package/dist/skill-runtime-CtSykP3r.js +102 -0
  447. package/dist/skill-runtime-DUAt8JM_.js +5 -0
  448. package/dist/skill-runtime-DZ6uJXGW.js +102 -0
  449. package/dist/skill-runtime-DaLnq_Jm.js +5 -0
  450. package/dist/skill-runtime-DpDbjL7y.js +102 -0
  451. package/dist/skill-runtime-acmnZSq7.js +102 -0
  452. package/dist/skill-runtime-dzuLMVSw.js +5 -0
  453. package/dist/skill-runtime-wiVnzSoJ.js +5 -0
  454. package/dist/src-B5lCcPXX.js +63 -0
  455. package/dist/src-B7Kxqi35.js +20 -0
  456. package/dist/src-B8DEmVd6.js +458 -0
  457. package/dist/src-BqbwzQQj.js +63 -0
  458. package/dist/src-C63ECu1t.js +63 -0
  459. package/dist/src-C65-5rOW.js +458 -0
  460. package/dist/src-CbTAVbeI.js +20 -0
  461. package/dist/src-Cmnclt47.js +63 -0
  462. package/dist/src-D0kptBSa.js +458 -0
  463. package/dist/src-DZtpIvWJ.js +63 -0
  464. package/dist/src-DjzS20TD.js +63 -0
  465. package/dist/src-DmPjS2Z4.js +458 -0
  466. package/dist/src-DmbIgW0O.js +63 -0
  467. package/dist/src-DsaXFru7.js +63 -0
  468. package/dist/src-Dt0TXI8r.js +458 -0
  469. package/dist/src-PPagVWuK.js +63 -0
  470. package/dist/src-rktqvEBJ.js +458 -0
  471. package/dist/src-tI8EOp6-.js +458 -0
  472. package/dist/src-zUHOCQgl.js +458 -0
  473. package/dist/src-zWhGmJSN.js +458 -0
  474. package/dist/sub-agent-tools-9k60L5mn.js +39 -0
  475. package/dist/sub-agent-tools-BBJf8oPD.js +39 -0
  476. package/dist/sub-agent-tools-BVCARpnF.js +39 -0
  477. package/dist/sub-agent-tools-Cx5BB5IO.js +39 -0
  478. package/dist/sub-agent-tools-DMT7jjBc.js +39 -0
  479. package/dist/sub-agent-tools-F-04gxf8.js +39 -0
  480. package/dist/sub-agent-tools-iBQiRKg6.js +39 -0
  481. package/dist/sub-agent-tools-kr921YOA.js +39 -0
  482. package/dist/theme-CLXvI6Hr.js +183 -0
  483. package/dist/theme-DdZT-Bq4.js +10 -0
  484. package/dist/theme-GEpjn_0G.js +180 -0
  485. package/dist/theme-hOlG-hDL.js +8 -0
  486. package/dist/tool-policy-D1zWYBKm.js +189 -0
  487. package/dist/tool-policy-TmXx_fpp.js +189 -0
  488. package/dist/tool-policy-YgysHf5s.js +189 -0
  489. package/dist/tts-elevenlabs-BT4WrEwy.js +61 -0
  490. package/dist/tts-elevenlabs-C62Wnnrg.js +61 -0
  491. package/dist/tts-elevenlabs-DmEFFeR8.js +61 -0
  492. package/dist/update-check-BeAPt4-f.js +98 -0
  493. package/dist/update-check-CaHNCDqe.js +6 -0
  494. package/dist/vision-B5DQ5hYa.js +121 -0
  495. package/dist/vision-XOSSQe4m.js +121 -0
  496. package/dist/vision-sIO3kwFy.js +121 -0
  497. package/dist/vision-tools-BHogJPuK.js +5 -0
  498. package/dist/vision-tools-BZhV8wg3.js +51 -0
  499. package/dist/vision-tools-BiDKd0UA.js +5 -0
  500. package/dist/vision-tools-CdRxilYR.js +5 -0
  501. package/dist/vision-tools-DnUjpQhI.js +51 -0
  502. package/dist/vision-tools-gtUq6d-x.js +51 -0
  503. package/dist/voice-transcription-5_iQE-0C.js +138 -0
  504. package/dist/voice-transcription-C3SuzK96.js +138 -0
  505. package/dist/voice-transcription-CYFj4Iv3.js +138 -0
  506. package/dist/voice-transcription-ygmlOkky.js +138 -0
  507. package/dist/website-watch-tools-BF-wR0UI.js +5 -0
  508. package/dist/website-watch-tools-CVh7RA5-.js +139 -0
  509. package/dist/website-watch-tools-CthBrGPP.js +5 -0
  510. package/dist/website-watch-tools-Oxf8Mv4j.js +139 -0
  511. package/package.json +1 -1
@@ -0,0 +1,3861 @@
1
+ const require_chunk = require('./chunk-jS-bbMI5.js');
2
+ const require_config = require('./config-BEz4yNRx.js');
3
+ const require_daemon = require('./daemon-DgBZaFyi.js');
4
+ const require_gateway = require('./gateway-DNv10FFg.js');
5
+ const require_providers = require('./providers-DP8T0QCR.js');
6
+ const require_theme = require('./theme-GEpjn_0G.js');
7
+ const chalk = require_chunk.__toESM(require("chalk"));
8
+ const inquirer = require_chunk.__toESM(require("inquirer"));
9
+ const ora = require_chunk.__toESM(require("ora"));
10
+ const boxen = require_chunk.__toESM(require("boxen"));
11
+ const fs_extra = require_chunk.__toESM(require("fs-extra"));
12
+ const path = require_chunk.__toESM(require("path"));
13
+ const os = require_chunk.__toESM(require("os"));
14
+ const crypto = require_chunk.__toESM(require("crypto"));
15
+ const https = require_chunk.__toESM(require("https"));
16
+ const gradient_string = require_chunk.__toESM(require("gradient-string"));
17
+ const figlet = require_chunk.__toESM(require("figlet"));
18
+
19
+ //#region src/cli/channels.ts
20
+ const CHANNEL_DEFS = [
21
+ {
22
+ id: "telegram",
23
+ name: "Telegram",
24
+ emoji: "✈️",
25
+ requiresGateway: false,
26
+ supportsDM: true,
27
+ platforms: ["all"],
28
+ tokenLabel: "Telegram Bot Token",
29
+ tokenHint: "Get from @BotFather → /newbot",
30
+ setupSteps: [
31
+ "1. Open Telegram → @BotFather → /newbot",
32
+ "2. Set name and username (must end in bot)",
33
+ "3. Copy the Bot Token",
34
+ " 🔗 t.me/BotFather"
35
+ ],
36
+ npmPackage: "node-telegram-bot-api",
37
+ defaultDMPolicy: "pairing"
38
+ },
39
+ {
40
+ id: "discord",
41
+ name: "Discord",
42
+ emoji: "🎮",
43
+ requiresGateway: false,
44
+ supportsDM: true,
45
+ platforms: ["all"],
46
+ tokenLabel: "Discord Bot Token",
47
+ tokenHint: "discord.com/developers/applications",
48
+ setupSteps: [
49
+ "1. discord.com/developers/applications → New Application",
50
+ "2. Bot → Add Bot → Reset Token",
51
+ "3. OAuth2 → General → copy Application ID",
52
+ " 🔗 discord.com/developers/applications"
53
+ ],
54
+ extraFields: [{
55
+ name: "clientId",
56
+ label: "Client ID",
57
+ required: true
58
+ }],
59
+ npmPackage: "discord.js",
60
+ defaultDMPolicy: "pairing"
61
+ },
62
+ {
63
+ id: "whatsapp",
64
+ name: "WhatsApp",
65
+ emoji: "📱",
66
+ requiresGateway: true,
67
+ supportsDM: true,
68
+ platforms: ["all"],
69
+ tokenLabel: "WhatsApp Business API key",
70
+ tokenHint: "business.whatsapp.com",
71
+ setupSteps: [
72
+ "1. developers.facebook.com → My Apps → Create App",
73
+ "2. WhatsApp → API Setup → Access Token",
74
+ " 🔗 business.whatsapp.com"
75
+ ],
76
+ npmPackage: "@whiskeysockets/baileys",
77
+ defaultDMPolicy: "pairing"
78
+ },
79
+ {
80
+ id: "slack",
81
+ name: "Slack",
82
+ emoji: "💼",
83
+ requiresGateway: true,
84
+ supportsDM: true,
85
+ platforms: ["all"],
86
+ tokenLabel: "Slack Bot Token (xoxb-...)",
87
+ tokenHint: "api.slack.com/apps",
88
+ setupSteps: [
89
+ "1. api.slack.com/apps → Create App → Bot",
90
+ "2. Install App → copy Bot Token (xoxb-)",
91
+ "3. Basic Information → Signing Secret",
92
+ " 🔗 api.slack.com/apps"
93
+ ],
94
+ extraFields: [{
95
+ name: "signingSecret",
96
+ label: "Signing Secret",
97
+ required: true
98
+ }],
99
+ defaultDMPolicy: "allowlist"
100
+ },
101
+ {
102
+ id: "signal",
103
+ name: "Signal",
104
+ emoji: "🔒",
105
+ requiresGateway: true,
106
+ supportsDM: true,
107
+ platforms: ["linux", "darwin"],
108
+ tokenLabel: "Registered phone number",
109
+ tokenHint: "Requires signal-cli installed",
110
+ setupSteps: [
111
+ "1. Install signal-cli or signald",
112
+ "2. Link your number (signal-cli link or signald register)",
113
+ " 🔗 github.com/AsamK/signal-cli"
114
+ ],
115
+ notes: "Needs signal-cli + registered number",
116
+ defaultDMPolicy: "pairing"
117
+ },
118
+ {
119
+ id: "imessage",
120
+ name: "iMessage",
121
+ emoji: "🍏",
122
+ requiresGateway: true,
123
+ supportsDM: true,
124
+ platforms: ["darwin"],
125
+ tokenLabel: "BlueBubbles server password",
126
+ tokenHint: "bluebubbles.app on macOS",
127
+ setupSteps: [
128
+ "1. Install BlueBubbles on a Mac",
129
+ "2. Configure and connect",
130
+ " 🔗 bluebubbles.app"
131
+ ],
132
+ notes: "macOS only via BlueBubbles",
133
+ defaultDMPolicy: "pairing"
134
+ },
135
+ {
136
+ id: "imessage-native",
137
+ name: "iMessage (imsg)",
138
+ emoji: "💬",
139
+ requiresGateway: true,
140
+ supportsDM: true,
141
+ platforms: ["darwin"],
142
+ tokenLabel: "Not required",
143
+ tokenHint: "Uses imsg CLI",
144
+ setupSteps: [
145
+ "1. Install imsg CLI: brew install steipete/imsg/imsg",
146
+ "2. No token required — uses native iMessage",
147
+ " 🔗 github.com/steipete/imsg"
148
+ ],
149
+ notes: "macOS only, native via imsg CLI (github.com/steipete/imsg). No BlueBubbles.",
150
+ defaultDMPolicy: "pairing"
151
+ },
152
+ {
153
+ id: "matrix",
154
+ name: "Matrix",
155
+ emoji: "🔢",
156
+ requiresGateway: true,
157
+ supportsDM: true,
158
+ platforms: ["all"],
159
+ tokenLabel: "Matrix access token",
160
+ tokenHint: "element.io → Settings → Help → Access Token",
161
+ setupSteps: [
162
+ "1. Element → Settings → Help & About → Access Token",
163
+ "2. Copy the access token",
164
+ " 🔗 element.io"
165
+ ],
166
+ extraFields: [{
167
+ name: "homeserver",
168
+ label: "Homeserver URL",
169
+ hint: "https://matrix.org",
170
+ required: true
171
+ }, {
172
+ name: "userId",
173
+ label: "User ID (@user:server)",
174
+ required: true
175
+ }],
176
+ defaultDMPolicy: "pairing"
177
+ },
178
+ {
179
+ id: "email",
180
+ name: "Email",
181
+ emoji: "📧",
182
+ requiresGateway: false,
183
+ supportsDM: true,
184
+ platforms: ["all"],
185
+ tokenLabel: "Gmail app password or IMAP password",
186
+ tokenHint: "Use app-specific password",
187
+ setupSteps: [
188
+ "1. Enable IMAP/SMTP in your email provider",
189
+ "2. Use app password if you have 2FA",
190
+ " 🔗 Gmail: myaccount.google.com/apppasswords"
191
+ ],
192
+ extraFields: [
193
+ {
194
+ name: "imapHost",
195
+ label: "IMAP host",
196
+ hint: "imap.gmail.com",
197
+ required: true
198
+ },
199
+ {
200
+ name: "smtpHost",
201
+ label: "SMTP host",
202
+ hint: "smtp.gmail.com",
203
+ required: true
204
+ },
205
+ {
206
+ name: "user",
207
+ label: "Email address",
208
+ required: true
209
+ }
210
+ ],
211
+ defaultDMPolicy: "allowlist"
212
+ },
213
+ {
214
+ id: "feishu",
215
+ name: "Feishu/Lark",
216
+ emoji: "🪶",
217
+ requiresGateway: true,
218
+ supportsDM: true,
219
+ platforms: ["all"],
220
+ tokenLabel: "Feishu App ID",
221
+ tokenHint: "open.feishu.cn",
222
+ setupSteps: [
223
+ "1. open.feishu.cn → Create application",
224
+ "2. Copy App ID and App Secret",
225
+ " 🔗 open.feishu.cn"
226
+ ],
227
+ extraFields: [{
228
+ name: "appSecret",
229
+ label: "App Secret",
230
+ required: true
231
+ }],
232
+ defaultDMPolicy: "pairing"
233
+ },
234
+ {
235
+ id: "msteams",
236
+ name: "MS Teams",
237
+ emoji: "🟦",
238
+ requiresGateway: true,
239
+ supportsDM: true,
240
+ platforms: ["all"],
241
+ tokenLabel: "Azure Bot App ID",
242
+ tokenHint: "portal.azure.com → Bot Services",
243
+ setupSteps: [
244
+ "1. dev.botframework.com → Register Bot",
245
+ "2. Azure Bot → Configuration → copy App ID & Secret",
246
+ " 🔗 dev.botframework.com"
247
+ ],
248
+ extraFields: [{
249
+ name: "appPassword",
250
+ label: "App Password",
251
+ required: true
252
+ }],
253
+ defaultDMPolicy: "allowlist"
254
+ },
255
+ {
256
+ id: "messenger",
257
+ name: "Messenger",
258
+ emoji: "💬",
259
+ requiresGateway: true,
260
+ supportsDM: true,
261
+ platforms: ["all"],
262
+ tokenLabel: "Page Access Token",
263
+ tokenHint: "developers.facebook.com",
264
+ setupSteps: [
265
+ "1. developers.facebook.com → My Apps → Create App",
266
+ "2. Add Messenger product → Page Access Token",
267
+ " 🔗 developers.facebook.com"
268
+ ],
269
+ extraFields: [{
270
+ name: "verifyToken",
271
+ label: "Webhook Verify Token",
272
+ required: true
273
+ }],
274
+ defaultDMPolicy: "pairing"
275
+ },
276
+ {
277
+ id: "nostr",
278
+ name: "Nostr",
279
+ emoji: "🌐",
280
+ requiresGateway: false,
281
+ supportsDM: true,
282
+ platforms: ["all"],
283
+ tokenLabel: "Nostr private key (hex or nsec)",
284
+ tokenHint: "Generate with: openssl rand -hex 32",
285
+ setupSteps: [
286
+ "1. Use existing nostr client or generate new keypair",
287
+ "2. Copy nsec (private key)",
288
+ " 🔗 nostr.com"
289
+ ],
290
+ notes: "Decentralized — no account needed",
291
+ defaultDMPolicy: "open"
292
+ },
293
+ {
294
+ id: "line",
295
+ name: "LINE",
296
+ emoji: "💚",
297
+ requiresGateway: true,
298
+ supportsDM: true,
299
+ platforms: ["all"],
300
+ tokenLabel: "LINE Channel Access Token",
301
+ tokenHint: "developers.line.biz",
302
+ setupSteps: [
303
+ "1. developers.line.biz → Add Messaging API channel",
304
+ "2. Copy Channel Secret & Access Token",
305
+ " 🔗 developers.line.biz"
306
+ ],
307
+ extraFields: [{
308
+ name: "channelSecret",
309
+ label: "Channel Secret",
310
+ required: true
311
+ }],
312
+ defaultDMPolicy: "pairing"
313
+ },
314
+ {
315
+ id: "viber",
316
+ name: "Viber",
317
+ emoji: "💜",
318
+ requiresGateway: true,
319
+ supportsDM: true,
320
+ platforms: ["all"],
321
+ tokenLabel: "Viber Auth Token",
322
+ tokenHint: "partners.viber.com",
323
+ setupSteps: [
324
+ "1. partners.viber.com → Create Bot",
325
+ "2. Copy the Auth Token",
326
+ " 🔗 partners.viber.com"
327
+ ],
328
+ defaultDMPolicy: "pairing"
329
+ },
330
+ {
331
+ id: "zalo",
332
+ name: "Zalo OA",
333
+ emoji: "🔵",
334
+ requiresGateway: true,
335
+ supportsDM: true,
336
+ platforms: ["all"],
337
+ tokenLabel: "Zalo OA Access Token",
338
+ tokenHint: "developers.zalo.me",
339
+ setupSteps: [
340
+ "1. developers.zalo.me → Create application",
341
+ "2. Copy App ID and Access Token",
342
+ " 🔗 developers.zalo.me"
343
+ ],
344
+ extraFields: [{
345
+ name: "secretKey",
346
+ label: "Secret Key",
347
+ required: true
348
+ }],
349
+ defaultDMPolicy: "pairing"
350
+ },
351
+ {
352
+ id: "twitter",
353
+ name: "Twitter/X DM",
354
+ emoji: "🐦",
355
+ requiresGateway: true,
356
+ supportsDM: true,
357
+ platforms: ["all"],
358
+ tokenLabel: "Twitter API Key",
359
+ tokenHint: "developer.twitter.com",
360
+ setupSteps: [
361
+ "1. developer.twitter.com → Developer Portal",
362
+ "2. Create Project & App → copy API keys",
363
+ " 🔗 developer.twitter.com"
364
+ ],
365
+ extraFields: [
366
+ {
367
+ name: "apiKeySecret",
368
+ label: "API Key Secret",
369
+ required: true
370
+ },
371
+ {
372
+ name: "accessToken",
373
+ label: "Access Token",
374
+ required: true
375
+ },
376
+ {
377
+ name: "accessTokenSecret",
378
+ label: "Access Token Secret",
379
+ required: true
380
+ }
381
+ ],
382
+ defaultDMPolicy: "allowlist"
383
+ },
384
+ {
385
+ id: "irc",
386
+ name: "IRC",
387
+ emoji: "📡",
388
+ requiresGateway: true,
389
+ supportsDM: true,
390
+ platforms: ["all"],
391
+ tokenLabel: "NickServ password (optional)",
392
+ tokenHint: "freenode, libera.chat, etc.",
393
+ setupSteps: [
394
+ "1. Choose IRC server (e.g. irc.libera.chat)",
395
+ "2. Configure nick and password if needed",
396
+ " 🔗 libera.chat"
397
+ ],
398
+ extraFields: [{
399
+ name: "server",
400
+ label: "IRC server",
401
+ hint: "irc.libera.chat",
402
+ required: true
403
+ }, {
404
+ name: "nick",
405
+ label: "Nickname",
406
+ required: true
407
+ }],
408
+ defaultDMPolicy: "allowlist"
409
+ },
410
+ {
411
+ id: "mattermost",
412
+ name: "Mattermost",
413
+ emoji: "🏗️",
414
+ requiresGateway: true,
415
+ supportsDM: true,
416
+ platforms: ["all"],
417
+ tokenLabel: "Mattermost bot token",
418
+ tokenHint: "Settings → Integrations → Bot Accounts",
419
+ setupSteps: [
420
+ "1. Mattermost → Account Settings → Security → Personal Access Tokens",
421
+ "2. Create token and copy it",
422
+ " 🔗 docs.mattermost.com"
423
+ ],
424
+ extraFields: [{
425
+ name: "serverUrl",
426
+ label: "Server URL",
427
+ required: true
428
+ }],
429
+ defaultDMPolicy: "allowlist"
430
+ },
431
+ {
432
+ id: "nextcloud",
433
+ name: "Nextcloud Talk",
434
+ emoji: "☁️",
435
+ requiresGateway: true,
436
+ supportsDM: true,
437
+ platforms: ["all"],
438
+ tokenLabel: "Nextcloud app password",
439
+ tokenHint: "Your Nextcloud server",
440
+ setupSteps: [
441
+ "1. Nextcloud Admin → OAuth → new client",
442
+ "2. Talk → view bot credentials",
443
+ " 🔗 nextcloud.com"
444
+ ],
445
+ extraFields: [{
446
+ name: "serverUrl",
447
+ label: "Nextcloud URL",
448
+ required: true
449
+ }, {
450
+ name: "username",
451
+ label: "Username",
452
+ required: true
453
+ }],
454
+ defaultDMPolicy: "allowlist"
455
+ },
456
+ {
457
+ id: "googlechat",
458
+ name: "Google Chat",
459
+ emoji: "🔵",
460
+ requiresGateway: true,
461
+ supportsDM: false,
462
+ platforms: ["all"],
463
+ tokenLabel: "Google Chat Webhook URL",
464
+ tokenHint: "chat.google.com → Space → Apps & Integrations",
465
+ setupSteps: [
466
+ "1. chat.google.com → Space → Apps & Integrations → Manage webhooks",
467
+ "2. Add webhook and copy the URL",
468
+ " 🔗 chat.google.com"
469
+ ],
470
+ defaultDMPolicy: "none"
471
+ },
472
+ {
473
+ id: "whatsapp-baileys",
474
+ name: "WhatsApp (Baileys)",
475
+ emoji: "📲",
476
+ requiresGateway: true,
477
+ supportsDM: true,
478
+ platforms: ["all"],
479
+ tokenLabel: "Not required — scans QR code on first run",
480
+ setupSteps: [
481
+ "1. No Meta Business API needed — uses WhatsApp Web protocol",
482
+ "2. Start the gateway — a QR code will appear in the terminal",
483
+ "3. Open WhatsApp on your phone → Linked Devices → Link a device",
484
+ "4. Scan the QR code. Session is saved — no QR needed on future starts",
485
+ " 🔗 github.com/WhiskeySockets/Baileys"
486
+ ],
487
+ notes: "WhatsApp Web via Baileys — no Meta Business needed. QR scan on first run.",
488
+ npmPackage: "@whiskeysockets/baileys",
489
+ defaultDMPolicy: "pairing"
490
+ },
491
+ {
492
+ id: "instagram",
493
+ name: "Instagram DMs",
494
+ emoji: "📸",
495
+ requiresGateway: true,
496
+ supportsDM: true,
497
+ platforms: ["all"],
498
+ tokenLabel: "Meta Page Access Token",
499
+ tokenHint: "developers.facebook.com → Instagram product",
500
+ setupSteps: [
501
+ "1. Meta for Developers → My Apps → Create App → Business",
502
+ "2. Add Instagram product → Connect Instagram Business account",
503
+ "3. Webhooks: subscribe to messages, URL: https://<host>/webhook/instagram",
504
+ "4. Copy Page Access Token from Graph API Explorer (pages_messaging scope)",
505
+ " 🔗 developers.facebook.com"
506
+ ],
507
+ extraFields: [{
508
+ name: "instagramAccountId",
509
+ label: "Instagram Business Account ID",
510
+ required: true
511
+ }, {
512
+ name: "verifyToken",
513
+ label: "Webhook Verify Token (any string)",
514
+ required: true
515
+ }],
516
+ notes: "Requires Instagram Business + Meta App",
517
+ defaultDMPolicy: "pairing"
518
+ },
519
+ {
520
+ id: "zalo-personal",
521
+ name: "Zalo Personal",
522
+ emoji: "🔵",
523
+ requiresGateway: true,
524
+ supportsDM: true,
525
+ platforms: ["all"],
526
+ tokenLabel: "Zalo cookie token",
527
+ tokenHint: "Extracted from browser session",
528
+ setupSteps: [
529
+ "1. Open Zalo Web in browser (chat.zalo.me)",
530
+ "2. Open DevTools → Application → Cookies → find zpw_sek or _zlang",
531
+ "3. Copy the session cookie value",
532
+ " ⚠ Unofficial API — may break on Zalo updates. Use at your own risk."
533
+ ],
534
+ notes: "Unofficial — uses Zalo Personal API. May break on updates.",
535
+ defaultDMPolicy: "pairing"
536
+ },
537
+ {
538
+ id: "voice-call",
539
+ name: "Voice Call",
540
+ emoji: "🎙️",
541
+ requiresGateway: true,
542
+ supportsDM: false,
543
+ platforms: ["all"],
544
+ tokenLabel: "Not required",
545
+ setupSteps: [
546
+ "1. No external account needed",
547
+ "2. Requires microphone + ElevenLabs API key for TTS (optional)",
548
+ "3. Start with: hyperclaw voice-call",
549
+ " 💡 Works in terminal — voice input → agent → voice output"
550
+ ],
551
+ notes: "Terminal voice session — hyperclaw voice-call",
552
+ defaultDMPolicy: "none"
553
+ },
554
+ {
555
+ id: "web",
556
+ name: "WebChat UI",
557
+ emoji: "🌐",
558
+ requiresGateway: true,
559
+ supportsDM: false,
560
+ platforms: ["all"],
561
+ setupSteps: [
562
+ "1. Built-in — no setup needed",
563
+ "2. Start gateway: hyperclaw gateway",
564
+ "3. Open: http://localhost:<port>/dashboard",
565
+ " 💡 Works in any browser on your local network"
566
+ ],
567
+ notes: "Built-in WebChat at http://localhost:<port>",
568
+ defaultDMPolicy: "none"
569
+ },
570
+ {
571
+ id: "cli",
572
+ name: "CLI / Terminal",
573
+ emoji: "🖥️",
574
+ requiresGateway: false,
575
+ supportsDM: false,
576
+ platforms: ["all"],
577
+ setupSteps: [
578
+ "1. Always active — no setup needed",
579
+ "2. Use: hyperclaw chat or hyperclaw agent --message \"...\"",
580
+ " 💡 Works offline without any channel configured"
581
+ ],
582
+ notes: "Always active — hyperclaw chat",
583
+ defaultDMPolicy: "none"
584
+ },
585
+ {
586
+ id: "chrome-extension",
587
+ name: "Chrome Extension",
588
+ emoji: "🔌",
589
+ requiresGateway: true,
590
+ supportsDM: false,
591
+ platforms: ["all"],
592
+ setupSteps: [
593
+ "1. Open Chrome → chrome://extensions → Enable Developer mode",
594
+ "2. Load unpacked → select: extensions/chrome-extension/",
595
+ "3. Extension connects to gateway via WebSocket automatically",
596
+ " 💡 Gives the agent access to your browser context"
597
+ ],
598
+ notes: "Load extensions/chrome-extension/ as unpacked extension in Chrome",
599
+ defaultDMPolicy: "none"
600
+ },
601
+ {
602
+ id: "synology-chat",
603
+ name: "Synology Chat",
604
+ emoji: "🖥️",
605
+ requiresGateway: true,
606
+ supportsDM: true,
607
+ platforms: ["all"],
608
+ tokenLabel: "Incoming Webhook URL",
609
+ tokenHint: "DSM → Synology Chat → Integration → Incoming Webhooks",
610
+ setupSteps: [
611
+ "1. Open Synology Chat (DSM package)",
612
+ "2. Top-right menu → Integration → Incoming Webhooks → Create",
613
+ "3. Copy the Webhook URL (used to POST messages from HyperClaw)",
614
+ "4. Outgoing Webhook: Integration → Outgoing Webhooks → Create",
615
+ " URL: http://<your-server>:7789/synology-hook",
616
+ " Method: POST",
617
+ " 🔗 kb.synology.com/synologychat"
618
+ ],
619
+ extraFields: [{
620
+ name: "webhookPort",
621
+ label: "Outgoing webhook port",
622
+ hint: "7789",
623
+ required: false
624
+ }, {
625
+ name: "webhookToken",
626
+ label: "Outgoing webhook token (optional HMAC)",
627
+ required: false
628
+ }],
629
+ notes: "Requires Synology Chat installed on your Synology NAS (DSM 7+)",
630
+ defaultDMPolicy: "pairing"
631
+ },
632
+ {
633
+ id: "tlon",
634
+ name: "Tlon (Urbit)",
635
+ emoji: "🪐",
636
+ requiresGateway: true,
637
+ supportsDM: true,
638
+ platforms: ["all"],
639
+ tokenLabel: "Urbit login code",
640
+ tokenHint: "From your Urbit ship: +code",
641
+ setupSteps: [
642
+ "1. Start your Urbit ship (e.g. via Port or urbit binary)",
643
+ "2. In the Dojo: +code → copy the code",
644
+ "3. Note your ship name (e.g. ~sampel-palnet) and ship URL",
645
+ "4. Optionally configure a group: ~sampel-palnet/my-group",
646
+ " 🔗 tlon.io · urbit.org/getting-started"
647
+ ],
648
+ extraFields: [
649
+ {
650
+ name: "shipUrl",
651
+ label: "Ship URL",
652
+ hint: "http://localhost:8080",
653
+ required: true
654
+ },
655
+ {
656
+ name: "ship",
657
+ label: "Ship name",
658
+ hint: "~sampel-palnet",
659
+ required: true
660
+ },
661
+ {
662
+ name: "group",
663
+ label: "Group path (optional)",
664
+ hint: "~sampel-palnet/my-group",
665
+ required: false
666
+ }
667
+ ],
668
+ notes: "Requires a running Urbit ship with Tlon/Groups installed",
669
+ defaultDMPolicy: "pairing"
670
+ },
671
+ {
672
+ id: "twitch",
673
+ name: "Twitch",
674
+ emoji: "🟣",
675
+ requiresGateway: true,
676
+ supportsDM: true,
677
+ platforms: ["all"],
678
+ tokenLabel: "OAuth token (oauth:xxxxxxx)",
679
+ tokenHint: "twitchapps.com/tmi → connect with your bot account",
680
+ setupSteps: [
681
+ "1. Create a Twitch bot account (or use your own)",
682
+ "2. Go to: twitchapps.com/tmi → Connect → copy the OAuth token",
683
+ "3. Token format: oauth:xxxxxxxxxxxxxxxxxxxxxx",
684
+ "4. Bot username = the Twitch account you logged in with",
685
+ " 💡 To receive commands, users type: !<message>",
686
+ " 💡 Moderators and the broadcaster bypass the allowlist by default",
687
+ " 🔗 twitchapps.com/tmi"
688
+ ],
689
+ extraFields: [
690
+ {
691
+ name: "username",
692
+ label: "Bot Twitch username (lowercase)",
693
+ required: true
694
+ },
695
+ {
696
+ name: "channels",
697
+ label: "Channel(s) to join (comma-separated)",
698
+ hint: "mychannel or mychannel,otherchannel",
699
+ required: true
700
+ },
701
+ {
702
+ name: "commandPrefix",
703
+ label: "Command prefix",
704
+ hint: "! (default)",
705
+ required: false
706
+ }
707
+ ],
708
+ notes: "Chat-based; uses Twitch IRC over WebSocket. Command prefix required (default: !)",
709
+ defaultDMPolicy: "pairing"
710
+ }
711
+ ];
712
+ async function getChannelStatus(def, configuredIds) {
713
+ const platform = os.default.platform();
714
+ if (!def.platforms.includes("all") && !def.platforms.includes(platform)) return "unavailable";
715
+ if (configuredIds.includes(def.id)) return "configured";
716
+ if (["telegram", "discord"].includes(def.id)) return "recommended";
717
+ return "available";
718
+ }
719
+ /** Human-readable reason why a channel is unavailable on this OS */
720
+ function unavailableReason(def) {
721
+ const platform = os.default.platform();
722
+ if (def.platforms.length === 1 && def.platforms[0] === "darwin") return "macOS only";
723
+ if (def.platforms.includes("linux") && def.platforms.includes("darwin") && !def.platforms.includes("win32")) return "Linux/macOS only";
724
+ if (!def.platforms.includes("all") && !def.platforms.includes(platform)) return `not supported on ${platform}`;
725
+ return "unavailable on this OS";
726
+ }
727
+ function statusBadge(status, def) {
728
+ switch (status) {
729
+ case "configured": return chalk.default.green("[configured]");
730
+ case "recommended": return chalk.default.cyan("[recommended]");
731
+ case "available": return chalk.default.gray("[available]");
732
+ case "unavailable": {
733
+ const reason = def ? unavailableReason(def) : "unavailable";
734
+ return chalk.default.red(`[${reason}]`);
735
+ }
736
+ }
737
+ }
738
+ const CHANNELS = CHANNEL_DEFS;
739
+ async function getAvailableChannels(configuredIds = []) {
740
+ const result = [];
741
+ for (const def of CHANNEL_DEFS) {
742
+ const status = await getChannelStatus(def, configuredIds);
743
+ result.push({
744
+ ...def,
745
+ status
746
+ });
747
+ }
748
+ return result;
749
+ }
750
+
751
+ //#endregion
752
+ //#region src/cli/memory.ts
753
+ const HC_DIR = path.default.join(os.default.homedir(), ".hyperclaw");
754
+ const AGENTS_FILE = path.default.join(HC_DIR, "AGENTS.md");
755
+ const MEMORY_FILE = path.default.join(HC_DIR, "MEMORY.md");
756
+ const SOUL_FILE = path.default.join(HC_DIR, "SOUL.md");
757
+ const LOG_DIR = path.default.join(HC_DIR, "logs");
758
+ var MemoryManager = class {
759
+ async init(opts = {}) {
760
+ await fs_extra.default.ensureDir(HC_DIR);
761
+ await fs_extra.default.ensureDir(LOG_DIR);
762
+ const agentName = opts.agentName || "HyperClaw";
763
+ const userName = opts.userName || os.default.userInfo().username;
764
+ const lang = opts.language || "English";
765
+ const personality = opts.personality || "Direct and efficient, helpful without being sycophantic, honest about uncertainty";
766
+ const rules = opts.rules && opts.rules.length > 0 ? opts.rules.map((r, i) => `${i + 1}. ${r}`).join("\n") : `1. Always respond in the user's preferred language unless asked otherwise
767
+ 2. Be concise unless detail is explicitly requested
768
+ 3. Never share API keys, tokens, or secrets in responses
769
+ 4. If unsure, ask before acting — especially for destructive operations
770
+ 5. Log all PC access actions to ~/.hyperclaw/pc-access.log`;
771
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
772
+ if (!await fs_extra.default.pathExists(AGENTS_FILE)) await fs_extra.default.writeFile(AGENTS_FILE, `# AGENTS.md — Global Rules
773
+ > All sessions and subagents must follow these rules.
774
+
775
+ ## Identity
776
+ - Agent name: ${agentName}
777
+ - User name: ${userName}
778
+ - Primary language: ${lang}
779
+ - Created: ${today}
780
+
781
+ ## Behavior Rules
782
+ ${rules}
783
+
784
+ ## DM Policy Default
785
+ - Require pairing before responding to unknown senders
786
+ - Allowlist: (add trusted IDs here)
787
+
788
+ ## Hierarchy
789
+ - SOUL.md: persona and values (read-only by subagents)
790
+ - AGENTS.md: operational rules (this file)
791
+ - MEMORY.md: accumulated facts about the user
792
+ `);
793
+ if (!await fs_extra.default.pathExists(MEMORY_FILE)) await fs_extra.default.writeFile(MEMORY_FILE, `# MEMORY.md — User Context
794
+ > Automatically updated by HyperClaw after each session.
795
+
796
+ ## User Profile
797
+ - Name: ${userName}
798
+ - Language: ${lang}
799
+ - Initialized: ${today}
800
+
801
+ ## Notes
802
+ (auto-populated from conversations)
803
+ `);
804
+ if (!await fs_extra.default.pathExists(SOUL_FILE)) await fs_extra.default.writeFile(SOUL_FILE, `# SOUL.md — Agent Persona
805
+ > Who I am and how I behave.
806
+
807
+ ## Name
808
+ ${agentName}
809
+
810
+ ## Personality
811
+ - ${personality.replace(/\n/g, "\n- ")}
812
+
813
+ ## Values
814
+ - User autonomy first
815
+ - Do no harm
816
+ - Transparency about capabilities and limits
817
+
818
+ ## Wake phrase
819
+ ${opts.wakeWord ? opts.wakeWord : `Wake up, ${agentName}! Your user ${userName} needs you.`}
820
+ `);
821
+ const logFile = path.default.join(LOG_DIR, `${today}.md`);
822
+ if (!await fs_extra.default.pathExists(logFile)) await fs_extra.default.writeFile(logFile, `# Session Log — ${today}\n\n`);
823
+ }
824
+ async load() {
825
+ if (!await fs_extra.default.pathExists(AGENTS_FILE)) return null;
826
+ const agents = await fs_extra.default.readFile(AGENTS_FILE, "utf8").catch(() => "");
827
+ const memory = await fs_extra.default.readFile(MEMORY_FILE, "utf8").catch(() => "");
828
+ const soul = await fs_extra.default.readFile(SOUL_FILE, "utf8").catch(() => void 0);
829
+ return {
830
+ agents,
831
+ memory,
832
+ soul
833
+ };
834
+ }
835
+ async appendRule(rule) {
836
+ await fs_extra.default.ensureDir(HC_DIR);
837
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
838
+ const line = `\n- ${today}: ${rule}\n`;
839
+ await fs_extra.default.appendFile(AGENTS_FILE, line);
840
+ console.log(chalk.default.green(` ✅ Rule added to AGENTS.md: ${rule}`));
841
+ }
842
+ async addMemory(fact) {
843
+ await fs_extra.default.ensureDir(HC_DIR);
844
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
845
+ await fs_extra.default.appendFile(MEMORY_FILE, `\n- ${today}: ${fact}\n`);
846
+ console.log(chalk.default.green(` ✅ Memory saved: ${fact}`));
847
+ }
848
+ async updateSoul(content) {
849
+ await fs_extra.default.ensureDir(HC_DIR);
850
+ await fs_extra.default.writeFile(SOUL_FILE, content);
851
+ console.log(chalk.default.green(" ✅ SOUL.md updated"));
852
+ }
853
+ async show() {
854
+ const data = await this.load();
855
+ if (!data) {
856
+ console.log(chalk.default.yellow("\n No memory initialized. Run: hyperclaw init\n"));
857
+ return;
858
+ }
859
+ console.log(chalk.default.bold.cyan("\n 🧠 MEMORY\n"));
860
+ for (const [label, content] of [
861
+ ["SOUL.md", data.soul],
862
+ ["AGENTS.md", data.agents],
863
+ ["MEMORY.md", data.memory]
864
+ ]) {
865
+ if (!content) continue;
866
+ console.log(chalk.default.bold.white(` ── ${label} ──`));
867
+ const lines = content.split("\n").slice(0, 20);
868
+ for (const line of lines) if (line.startsWith("#")) console.log(chalk.default.cyan(` ${line}`));
869
+ else if (line.startsWith("-")) console.log(chalk.default.gray(` ${line}`));
870
+ else console.log(` ${line}`);
871
+ console.log();
872
+ }
873
+ }
874
+ async runPersonaBootstrap() {
875
+ console.log(chalk.default.bold.cyan("\n 🌅 Wake up, my friend!\n"));
876
+ const { agentName } = await inquirer.default.prompt([{
877
+ type: "input",
878
+ name: "agentName",
879
+ message: "What should I call myself? (agent name)",
880
+ default: "HyperClaw"
881
+ }]);
882
+ const { userName } = await inquirer.default.prompt([{
883
+ type: "input",
884
+ name: "userName",
885
+ message: `What shall ${agentName} call you?`,
886
+ default: os.default.userInfo().username
887
+ }]);
888
+ console.log(chalk.default.green(`\n ✨ I am ${agentName}. Hello, ${userName}.\n`));
889
+ return {
890
+ agentName,
891
+ userName
892
+ };
893
+ }
894
+ async getContextForAI() {
895
+ let context = "";
896
+ for (const [label, file] of [
897
+ ["SOUL", SOUL_FILE],
898
+ ["AGENTS", AGENTS_FILE],
899
+ ["MEMORY", MEMORY_FILE]
900
+ ]) if (await fs_extra.default.pathExists(file)) {
901
+ const content = await fs_extra.default.readFile(file, "utf8");
902
+ context += `## ${label}.md\n${content}\n\n`;
903
+ }
904
+ return context;
905
+ }
906
+ async search(query) {
907
+ const data = await this.load();
908
+ if (!data) {
909
+ console.log(chalk.default.gray(" No memory\n"));
910
+ return;
911
+ }
912
+ const allText = [
913
+ data.agents,
914
+ data.memory,
915
+ data.soul || ""
916
+ ].join("\n");
917
+ const lines = allText.split("\n").filter((l) => l.toLowerCase().includes(query.toLowerCase()));
918
+ if (lines.length === 0) {
919
+ console.log(chalk.default.gray(` Nothing found for "${query}"\n`));
920
+ return;
921
+ }
922
+ console.log(chalk.default.bold.cyan(`\n 🔍 "${query}"\n`));
923
+ lines.forEach((l) => console.log(` ${l}`));
924
+ console.log();
925
+ }
926
+ async clear(file = "memory") {
927
+ const { confirm } = await inquirer.default.prompt([{
928
+ type: "confirm",
929
+ name: "confirm",
930
+ message: `Clear ${file === "all" ? "ALL memory files" : "MEMORY.md"}?`,
931
+ default: false
932
+ }]);
933
+ if (!confirm) return;
934
+ if (file === "all") {
935
+ await fs_extra.default.remove(AGENTS_FILE);
936
+ await fs_extra.default.remove(MEMORY_FILE);
937
+ await fs_extra.default.remove(SOUL_FILE);
938
+ console.log(chalk.default.green(" ✅ All memory cleared"));
939
+ } else {
940
+ await fs_extra.default.writeFile(MEMORY_FILE, "# MEMORY.md\n\n");
941
+ console.log(chalk.default.green(" ✅ MEMORY.md cleared"));
942
+ }
943
+ }
944
+ };
945
+
946
+ //#endregion
947
+ //#region src/cli/security.ts
948
+ let _securityDisclaimerShown = false;
949
+ async function showSecurityDisclaimer() {
950
+ if (_securityDisclaimerShown) return true;
951
+ _securityDisclaimerShown = true;
952
+ console.clear();
953
+ console.log(chalk.default.bgRed.white.bold("\n ⚠️ SECURITY NOTICE — READ CAREFULLY ⚠️ \n"));
954
+ console.log(chalk.default.white.bold(" A bad prompt can trick it into doing unsafe things\n"));
955
+ console.log(chalk.default.hex("#06b6d4")(" Protections to enable:"));
956
+ console.log(chalk.default.gray(" ● Pairing / allowlists — limit who can DM your agent"));
957
+ console.log(chalk.default.gray(" ● Sandbox + least privilege — restrict PC access level"));
958
+ console.log(chalk.default.gray(" ● Keep secrets out — never put tokens in SOUL.md"));
959
+ console.log(chalk.default.gray(" ● Use strongest model — smarter = better at refusing tricks\n"));
960
+ const { understood } = await inquirer.default.prompt([{
961
+ type: "list",
962
+ name: "understood",
963
+ message: chalk.default.bold("I understand this is powerful and inherently risky."),
964
+ choices: [{
965
+ name: chalk.default.green("Yes, continue — I understand the risks"),
966
+ value: true
967
+ }, {
968
+ name: chalk.default.gray("No, exit — I'll come back later"),
969
+ value: false
970
+ }],
971
+ default: false
972
+ }]);
973
+ if (!understood) console.log(chalk.default.gray("\n Aborted. Come back when ready.\n"));
974
+ return understood;
975
+ }
976
+ async function configureDMPolicy(channelName) {
977
+ const { configureDMPolicy: cdmp } = await Promise.resolve().then(() => require("./security-2DPBzs5F.js"));
978
+ const res = await cdmp(channelName);
979
+ return {
980
+ dmPolicy: res.policy,
981
+ allowFrom: res.allowFrom ?? []
982
+ };
983
+ }
984
+
985
+ //#endregion
986
+ //#region src/terminal/banner.ts
987
+ require_theme.init_theme();
988
+ var Banner = class {
989
+ async showNeonBanner(daemonMode = false) {
990
+ console.clear();
991
+ const t = require_theme.getTheme(daemonMode);
992
+ const icon$1 = daemonMode ? "??" : "??";
993
+ try {
994
+ const title = figlet.default.textSync("HYPERCLAW", { font: "ANSI Shadow" });
995
+ const g = (0, gradient_string.default)(t.gradient);
996
+ const lines = title.split("\n");
997
+ const first = lines[0] ?? "";
998
+ console.log(`\n ${icon$1} ` + g(first));
999
+ for (let i = 1; i < lines.length; i++) console.log(g(" " + (lines[i] ?? "")));
1000
+ } catch {
1001
+ console.log(chalk.default.bold.red(`\n ${icon$1} HYPERCLAW\n`));
1002
+ }
1003
+ const subtitle = daemonMode ? chalk.default.hex(t.daemonPrimary)(" ?? DAEMON MODE - ALWAYS WATCHING ?\n") : t.muted(" ?? HyperClaw Bot - AI Gateway v5.2.0 ?\n");
1004
+ console.log(subtitle);
1005
+ const boxOpts = {
1006
+ padding: 1,
1007
+ margin: {
1008
+ top: 1,
1009
+ bottom: 1
1010
+ },
1011
+ borderStyle: "round",
1012
+ borderColor: daemonMode ? t.daemonBorderColor : t.borderColor
1013
+ };
1014
+ if (t.boxBg) boxOpts.backgroundColor = t.boxBg;
1015
+ const { ConfigManager } = await Promise.resolve().then(() => require("./manager-CuS13QUO.js"));
1016
+ const { GatewayManager: GatewayManager$1 } = await Promise.resolve().then(() => require("./gateway-DRh5v1KI.js"));
1017
+ const cfg = await new ConfigManager().load().catch(() => null);
1018
+ const port = cfg?.gateway?.port ?? 18789;
1019
+ const gm = new GatewayManager$1();
1020
+ const running = await gm.isRunning(port);
1021
+ const chList = cfg?.gateway?.enabledChannels ?? cfg?.channels ?? [];
1022
+ const chCount = Array.isArray(chList) ? chList.length : 0;
1023
+ const providerCount = cfg?.providers?.length ?? (cfg?.provider ? 1 : 0);
1024
+ const box = (0, boxen.default)(`${t.a("?")} Gateway: ${running ? t.success("Running") : t.error("Stopped")} ${t.a("?")} Providers: ${providerCount} ${t.a("?")} Channels: ${chCount} ` + (daemonMode ? `${t.d("??")} DAEMON` : `${t.a("??")} HYPERCLAW`), boxOpts);
1025
+ console.log(box);
1026
+ console.log(t.muted(" One assistant. All your channels. ??\n"));
1027
+ const { maybeShowUpdateNotice } = await Promise.resolve().then(() => require("./update-check-CaHNCDqe.js"));
1028
+ maybeShowUpdateNotice(daemonMode);
1029
+ }
1030
+ async showMiniBanner() {
1031
+ await this.showNeonBanner(false);
1032
+ }
1033
+ async showWizardBanner() {
1034
+ console.clear();
1035
+ const t = require_theme.getTheme(false);
1036
+ const g = (0, gradient_string.default)(t.gradient);
1037
+ try {
1038
+ const title = figlet.default.textSync("HYPERCLAW", { font: "ANSI Shadow" });
1039
+ const lines = title.split("\n");
1040
+ const first = lines[0] ?? "";
1041
+ console.log("\n ?? " + g(first));
1042
+ for (let i = 1; i < lines.length; i++) console.log(g(" " + (lines[i] ?? "")));
1043
+ } catch {
1044
+ console.log(t.bold("\n ?? HYPERCLAW\n"));
1045
+ }
1046
+ console.log(t.muted(" ?? HyperClaw Bot - AI Gateway - SETUP WIZARD v5.2.0 ?\n"));
1047
+ const boxOpts = {
1048
+ padding: 1,
1049
+ margin: { bottom: 1 },
1050
+ borderStyle: "round",
1051
+ borderColor: t.borderColor
1052
+ };
1053
+ if (t.boxBg) boxOpts.backgroundColor = t.boxBg;
1054
+ const box = (0, boxen.default)(t.a("?") + " Provider - Channels - Gateway - Identity", boxOpts);
1055
+ console.log(box);
1056
+ }
1057
+ async showStatus() {
1058
+ const t = require_theme.getTheme(false);
1059
+ const { ConfigManager } = await Promise.resolve().then(() => require("./manager-CuS13QUO.js"));
1060
+ const { GatewayManager: GatewayManager$1 } = await Promise.resolve().then(() => require("./gateway-DRh5v1KI.js"));
1061
+ const cfg = await new ConfigManager().load();
1062
+ const gm = new GatewayManager$1();
1063
+ const port = cfg?.gateway?.port ?? 18789;
1064
+ const running = await gm.isRunning(port);
1065
+ const chList = cfg?.gateway?.enabledChannels ?? cfg?.channels ?? [];
1066
+ const chCount = Array.isArray(chList) ? chList.length : 0;
1067
+ console.log(t.bold("\n HyperClaw Status\n"));
1068
+ console.log(` Gateway: ${running ? t.success("Running") : t.error("Stopped")} port ${port}`);
1069
+ console.log(` Provider: ${t.c(cfg?.provider?.providerId ?? "none")}`);
1070
+ console.log(` Channels: ${t.c(String(chCount))}`);
1071
+ console.log();
1072
+ }
1073
+ };
1074
+
1075
+ //#endregion
1076
+ //#region src/infra/channel-icons.ts
1077
+ const CDN = "https://cdn.simpleicons.org";
1078
+ function icon(slug, name, color, darkColor) {
1079
+ return {
1080
+ slug,
1081
+ name,
1082
+ color,
1083
+ url: `${CDN}/${slug}`,
1084
+ darkColor
1085
+ };
1086
+ }
1087
+ const CHANNEL_ICONS = {
1088
+ "telegram": icon("telegram", "Telegram", "26A5E4"),
1089
+ "discord": icon("discord", "Discord", "5865F2"),
1090
+ "whatsapp": icon("whatsapp", "WhatsApp", "25D366"),
1091
+ "whatsapp-baileys": icon("whatsapp", "WhatsApp (Baileys)", "25D366"),
1092
+ "slack": icon("slack", "Slack", "4A154B"),
1093
+ "signal": icon("signal", "Signal", "3A76F0", "FFFFFF"),
1094
+ "imessage": icon("imessage", "iMessage", "29CC40"),
1095
+ "imessage-native": icon("imessage", "iMessage (native)", "29CC40"),
1096
+ "matrix": icon("matrix", "Matrix", "000000", "FFFFFF"),
1097
+ "email": icon("gmail", "Email", "EA4335"),
1098
+ "feishu": icon("lark", "Feishu / Lark", "00D6B9"),
1099
+ "msteams": icon("microsoftteams", "Microsoft Teams", "6264A7"),
1100
+ "messenger": icon("messenger", "Facebook Messenger", "00B2FF"),
1101
+ "nostr": icon("nostr", "Nostr", "8E44AD", "C39BD3"),
1102
+ "line": icon("line", "LINE", "00C300"),
1103
+ "viber": icon("viber", "Viber", "7360F2"),
1104
+ "zalo": icon("zalo", "Zalo", "0068FF"),
1105
+ "zalo-personal": icon("zalo", "Zalo Personal", "0068FF"),
1106
+ "twitter": icon("x", "Twitter / X", "000000", "FFFFFF"),
1107
+ "irc": icon("irc", "IRC", "1A3B5C", "FFFFFF"),
1108
+ "mattermost": icon("mattermost", "Mattermost", "0058CC"),
1109
+ "nextcloud": icon("nextcloud", "Nextcloud Talk", "0082C9"),
1110
+ "googlechat": icon("googlechat", "Google Chat", "00897B"),
1111
+ "instagram": icon("instagram", "Instagram", "E4405F"),
1112
+ "synology-chat": icon("synology", "Synology Chat", "B5B5B6", "FFFFFF"),
1113
+ "tlon": icon("urbit", "Tlon (Urbit)", "000000", "FFFFFF"),
1114
+ "twitch": icon("twitch", "Twitch", "9146FF"),
1115
+ "voice-call": icon("webrtc", "Voice Call", "333333", "FFFFFF"),
1116
+ "web": icon("googlechrome", "WebChat", "4285F4"),
1117
+ "cli": icon("gnubash", "CLI / Terminal", "4EAA25", "FFFFFF"),
1118
+ "chrome-extension": icon("googlechrome", "Chrome Extension", "4285F4")
1119
+ };
1120
+ const PROVIDER_ICONS = {
1121
+ "anthropic": icon("anthropic", "Anthropic (Claude)", "D4C5A9", "191919"),
1122
+ "openai": icon("openai", "OpenAI", "000000", "FFFFFF"),
1123
+ "openrouter": icon("openrouter", "OpenRouter", "6467F2"),
1124
+ "groq": icon("groq", "Groq", "F55036"),
1125
+ "xai": icon("x", "xAI (Grok)", "000000", "FFFFFF"),
1126
+ "custom": icon("jsonwebtokens", "Custom OpenAI API", "A0A0A0"),
1127
+ "ollama": icon("ollama", "Ollama (local)", "000000", "FFFFFF"),
1128
+ "mistral": icon("mistral", "Mistral AI", "FF7000"),
1129
+ "cohere": icon("cohere", "Cohere", "39594D", "FFFFFF"),
1130
+ "google": icon("googlegemini", "Google Gemini", "8E75B2"),
1131
+ "deepseek": icon("deepseek", "DeepSeek", "4D6BFE"),
1132
+ "together": icon("togetherai", "Together AI", "000000", "FFFFFF")
1133
+ };
1134
+
1135
+ //#endregion
1136
+ //#region src/cli/onboard.ts
1137
+ require_providers.init_providers();
1138
+ /** Brand-colored square - closest we can get to a real icon in a terminal */
1139
+ function brandIcon(id, type = "channel") {
1140
+ const map = type === "channel" ? CHANNEL_ICONS : PROVIDER_ICONS;
1141
+ const ic = map[id];
1142
+ if (!ic) return chalk.default.gray("●");
1143
+ return chalk.default.hex("#" + ic.color)("●");
1144
+ }
1145
+ var HyperClawWizard = class {
1146
+ config = new require_config.ConfigStore();
1147
+ daemon = new require_daemon.DaemonManager();
1148
+ gateway = new require_gateway.GatewayManager();
1149
+ async run(options) {
1150
+ const existingCfg = await this.config.load();
1151
+ const hasExistingConfig = !!(existingCfg && (existingCfg.provider || existingCfg.providers?.length));
1152
+ if (hasExistingConfig && !options.nonInteractive) {
1153
+ const { getConfigPath } = await Promise.resolve().then(() => require("./paths-D-QecARF.js"));
1154
+ console.log(chalk.default.yellow(`\n ? Existing config detected: ${chalk.default.bold(getConfigPath())}\n`));
1155
+ const { configAction } = await inquirer.default.prompt([{
1156
+ type: "list",
1157
+ name: "configAction",
1158
+ message: "What would you like to do?",
1159
+ choices: [
1160
+ {
1161
+ name: `${chalk.default.green("?")} Keep & modify ${chalk.default.gray("(keep existing config, change specific settings)")}`,
1162
+ value: "modify"
1163
+ },
1164
+ {
1165
+ name: ` Keep & continue ${chalk.default.gray("(re-run wizard, keep all current values as defaults)")}`,
1166
+ value: "keep"
1167
+ },
1168
+ {
1169
+ name: `${chalk.default.red("?")} Reset ${chalk.default.gray("(back up config and start fresh)")}`,
1170
+ value: "reset"
1171
+ }
1172
+ ]
1173
+ }]);
1174
+ if (configAction === "reset") {
1175
+ const { resetScope } = await inquirer.default.prompt([{
1176
+ type: "list",
1177
+ name: "resetScope",
1178
+ message: "Reset scope:",
1179
+ choices: [
1180
+ {
1181
+ name: "Config only",
1182
+ value: "config"
1183
+ },
1184
+ {
1185
+ name: "Config + credentials + sessions",
1186
+ value: "config+creds"
1187
+ },
1188
+ {
1189
+ name: "Full reset (config + credentials + workspace)",
1190
+ value: "full"
1191
+ }
1192
+ ]
1193
+ }]);
1194
+ const fs$3 = await import("fs-extra");
1195
+ const path$3 = await import("path");
1196
+ const { getHyperClawDir, getConfigPath: getConfigPath$1 } = await Promise.resolve().then(() => require("./paths-D-QecARF.js"));
1197
+ const hcDir = getHyperClawDir();
1198
+ const backupDir = path$3.join(hcDir, `backup-${Date.now()}`);
1199
+ await fs$3.ensureDir(backupDir);
1200
+ const toRemove = [getConfigPath$1()];
1201
+ if (resetScope !== "config") toRemove.push(path$3.join(hcDir, "credentials"), path$3.join(hcDir, "sessions"));
1202
+ if (resetScope === "full") toRemove.push(path$3.join(hcDir, "workspace"));
1203
+ for (const f of toRemove) if (await fs$3.pathExists(f)) await fs$3.move(f, path$3.join(backupDir, path$3.basename(f)));
1204
+ console.log(chalk.default.green(`\n ? Config backed up to ${backupDir}\n Starting fresh...\n`));
1205
+ } else if (configAction === "modify") console.log(chalk.default.gray("\n Continuing with existing config as defaults...\n"));
1206
+ }
1207
+ const proceed = await showSecurityDisclaimer();
1208
+ if (!proceed) return;
1209
+ const { allThemes, getThemeName, setThemeName } = await Promise.resolve().then(() => require("./theme-hOlG-hDL.js"));
1210
+ const currentTheme = getThemeName();
1211
+ const { chosenTheme } = await inquirer.default.prompt([{
1212
+ type: "list",
1213
+ name: "chosenTheme",
1214
+ message: "Choose a color theme:",
1215
+ default: currentTheme,
1216
+ choices: [
1217
+ {
1218
+ name: `${chalk.default.hex("#06b6d4")("●")} Dark Professional ${chalk.default.gray("(neon cyan on black)")}`,
1219
+ value: "dark"
1220
+ },
1221
+ {
1222
+ name: `${chalk.default.hex("#64748b")("●")} Grey Professional ${chalk.default.gray("(muted cyan, neutral)")}`,
1223
+ value: "grey"
1224
+ },
1225
+ {
1226
+ name: `${chalk.default.hex("#0284c7")("●")} White / Light ${chalk.default.gray("(deep cyan, light bg)")}`,
1227
+ value: "white"
1228
+ }
1229
+ ]
1230
+ }]);
1231
+ if (chosenTheme !== currentTheme) await setThemeName(chosenTheme);
1232
+ await new Banner().showWizardBanner();
1233
+ const { mode } = await inquirer.default.prompt([{
1234
+ type: "list",
1235
+ name: "mode",
1236
+ message: "Setup mode:",
1237
+ choices: [{
1238
+ name: `${chalk.default.green("?")} QuickStart ${chalk.default.gray("(Recommended)")}`,
1239
+ value: "quick"
1240
+ }, {
1241
+ name: ` Manual ${chalk.default.gray("(Full control)")}`,
1242
+ value: "manual"
1243
+ }]
1244
+ }]);
1245
+ if (mode === "quick") return this.quickSetup(options);
1246
+ return this.fullSetup(options);
1247
+ }
1248
+ async quickstart(options) {
1249
+ const proceed = await showSecurityDisclaimer();
1250
+ if (!proceed) return;
1251
+ return this.quickSetup(options);
1252
+ }
1253
+ stepHeader(n, total, title) {
1254
+ const { getTheme: getTheme$1 } = (require_theme.init_theme(), require_chunk.__toCommonJS(require_theme.theme_exports));
1255
+ const t = getTheme$1(false);
1256
+ const bar = chalk.default.gray("-".repeat(52));
1257
+ console.log(`\n${bar}`);
1258
+ console.log(` ${t.c(`Step ${n} / ${total}`)} — ${chalk.default.bold(title)}`);
1259
+ console.log(`${bar}\n`);
1260
+ }
1261
+ async quickSetup(options) {
1262
+ const STEPS = 8;
1263
+ this.stepHeader(1, STEPS, "Workspace");
1264
+ const { workspaceName } = await inquirer.default.prompt([{
1265
+ type: "input",
1266
+ name: "workspaceName",
1267
+ message: "Workspace name:",
1268
+ default: "my-hyperclaw"
1269
+ }]);
1270
+ this.stepHeader(2, STEPS, "AI Providers & Models");
1271
+ const { providers: allProviders, primary: providerConfig } = await this.selectProvidersAndModels();
1272
+ this.stepHeader(3, STEPS, "Gateway (optional)");
1273
+ const gatewayConfig = await this.configureGateway(false);
1274
+ this.stepHeader(4, STEPS, "Channels");
1275
+ const channelConfigs = await this.selectChannels();
1276
+ this.stepHeader(5, STEPS, "Agent Identity & Persona");
1277
+ const identity = await this.configureIdentity();
1278
+ this.stepHeader(6, STEPS, "Skills & Hooks");
1279
+ const { hooks, heartbeat: heartbeatEnabled } = await this.configureSkillsAndHooks();
1280
+ this.stepHeader(7, STEPS, "Launch");
1281
+ let installDaemon = options.installDaemon ?? false;
1282
+ let startNow = false;
1283
+ if (!installDaemon) {
1284
+ const { wantDaemon } = await inquirer.default.prompt([{
1285
+ type: "confirm",
1286
+ name: "wantDaemon",
1287
+ message: "Install as system daemon (auto-start on boot)?",
1288
+ default: false
1289
+ }]);
1290
+ installDaemon = wantDaemon;
1291
+ }
1292
+ if (installDaemon || !Object.keys(channelConfigs).length) startNow = true;
1293
+ else {
1294
+ const { wantStart } = await inquirer.default.prompt([{
1295
+ type: "confirm",
1296
+ name: "wantStart",
1297
+ message: "Start the bot now? (Telegram/Discord will respond once running)",
1298
+ default: true
1299
+ }]);
1300
+ startNow = wantStart;
1301
+ }
1302
+ this.stepHeader(8, STEPS, "Extras");
1303
+ const { skipExtras } = await inquirer.default.prompt([{
1304
+ type: "confirm",
1305
+ name: "skipExtras",
1306
+ message: "Skip optional extras for now? (web search, memory, services, etc. — configure later)",
1307
+ default: true
1308
+ }]);
1309
+ let webSearch, memoryIntegration, serviceApiKeys, hyperclawbotConfig, talkModeConfig;
1310
+ let pcAccess, updateChannel, groupSandbox, rateLimit;
1311
+ if (!skipExtras) {
1312
+ webSearch = await this.configureWebSearch(options.skipSearch);
1313
+ memoryIntegration = await this.configureMemoryIntegration();
1314
+ serviceApiKeys = await this.configureServiceApiKeys();
1315
+ hyperclawbotConfig = await this.configureHyperClawBot(gatewayConfig, channelConfigs);
1316
+ talkModeConfig = await this.configureTalkMode();
1317
+ pcAccess = await this.configurePcAccess();
1318
+ updateChannel = await this.configureUpdateChannel();
1319
+ groupSandbox = await this.configureGroupSandbox();
1320
+ await this.configureSkillHub();
1321
+ await this.configureMcpServers();
1322
+ await this.configureWorkspaceTemplate();
1323
+ await this.configureCronTasks();
1324
+ await this.configureAutoReply();
1325
+ await this.configureWebhooks();
1326
+ await this.configureNodes();
1327
+ await this.configureOAuth();
1328
+ await this.configureAgentBindings();
1329
+ rateLimit = await this.configureRateLimiting();
1330
+ await this.configureDeveloperKey();
1331
+ await this.configureVoiceCall();
1332
+ await this.configureCanvas();
1333
+ await this.configureDeploy();
1334
+ }
1335
+ await this.saveAll({
1336
+ workspaceName,
1337
+ providerConfig,
1338
+ providers: allProviders,
1339
+ channelConfigs,
1340
+ gatewayConfig,
1341
+ identity,
1342
+ hooks,
1343
+ heartbeatEnabled,
1344
+ webSearch,
1345
+ memoryIntegration,
1346
+ serviceApiKeys,
1347
+ hyperclawbotConfig,
1348
+ talkModeConfig,
1349
+ pcAccess,
1350
+ updateChannel,
1351
+ groupSandbox,
1352
+ rateLimit,
1353
+ installDaemon,
1354
+ startNow
1355
+ }, options);
1356
+ }
1357
+ async fullSetup(options) {
1358
+ const STEPS = 9;
1359
+ this.stepHeader(1, STEPS, "Workspace");
1360
+ const { workspaceName } = await inquirer.default.prompt([{
1361
+ type: "input",
1362
+ name: "workspaceName",
1363
+ message: "Workspace directory:",
1364
+ default: "my-hyperclaw"
1365
+ }]);
1366
+ this.stepHeader(2, STEPS, "AI Providers & Models");
1367
+ const { providers: allProviders, primary: providerConfig } = await this.selectProvidersAndModels();
1368
+ this.stepHeader(3, STEPS, "Gateway");
1369
+ const gatewayConfig = await this.configureGateway(true);
1370
+ this.stepHeader(4, STEPS, "Channels");
1371
+ const { configureChannels } = await inquirer.default.prompt([{
1372
+ type: "confirm",
1373
+ name: "configureChannels",
1374
+ message: "Configure chat channels now?",
1375
+ default: true
1376
+ }]);
1377
+ const channelConfigs = configureChannels ? await this.selectChannels(true) : {};
1378
+ if (configureChannels) {
1379
+ const { configureDM } = await inquirer.default.prompt([{
1380
+ type: "confirm",
1381
+ name: "configureDM",
1382
+ message: "Configure DM access policies now?",
1383
+ default: true
1384
+ }]);
1385
+ if (configureDM) for (const [channelId] of Object.entries(channelConfigs)) {
1386
+ const ch = CHANNELS.find((c) => c.id === channelId);
1387
+ if (ch?.supportsDM) {
1388
+ const dm = await configureDMPolicy(ch.name);
1389
+ channelConfigs[channelId].dmPolicy = dm;
1390
+ }
1391
+ }
1392
+ }
1393
+ this.stepHeader(5, STEPS, "Agent Identity & Persona");
1394
+ const identity = await this.configureIdentity();
1395
+ this.stepHeader(6, STEPS, "Skills & Hooks");
1396
+ const { hooks, heartbeat: heartbeatEnabled } = await this.configureSkillsAndHooks();
1397
+ this.stepHeader(7, STEPS, "Services & Daemon");
1398
+ let installDaemon = options.installDaemon ?? false;
1399
+ let daemonRuntime = options.daemonRuntime ?? "node";
1400
+ if (!installDaemon) {
1401
+ console.log(chalk.default.gray(" The daemon runs the gateway as a background service that starts on boot.\n"));
1402
+ const ans = await inquirer.default.prompt([{
1403
+ type: "confirm",
1404
+ name: "installDaemon",
1405
+ message: "Install as system daemon (auto-start on boot)?",
1406
+ default: false
1407
+ }, {
1408
+ type: "list",
1409
+ name: "daemonRuntime",
1410
+ message: "Daemon runtime:",
1411
+ default: "node",
1412
+ choices: [{
1413
+ name: `Node.js ${chalk.default.green("(recommended)")} — required for WhatsApp/Telegram`,
1414
+ value: "node"
1415
+ }, {
1416
+ name: `Bun ${chalk.default.gray("(faster startup, experimental)")}`,
1417
+ value: "bun"
1418
+ }],
1419
+ when: (answers) => answers.installDaemon
1420
+ }]);
1421
+ installDaemon = ans.installDaemon;
1422
+ if (ans.daemonRuntime) daemonRuntime = ans.daemonRuntime;
1423
+ } else console.log(chalk.default.green(` ? Daemon will be installed (runtime: ${daemonRuntime})\n`));
1424
+ this.stepHeader(8, STEPS, "Extras");
1425
+ const { skipExtras } = await inquirer.default.prompt([{
1426
+ type: "confirm",
1427
+ name: "skipExtras",
1428
+ message: "Skip optional extras for now? (web search, memory, services, etc. — configure later)",
1429
+ default: true
1430
+ }]);
1431
+ let webSearch, memoryIntegration, serviceApiKeys, hyperclawbotConfig, talkModeConfig;
1432
+ let pcAccess, updateChannel, groupSandbox, rateLimit;
1433
+ if (!skipExtras) {
1434
+ webSearch = await this.configureWebSearch(options.skipSearch);
1435
+ memoryIntegration = await this.configureMemoryIntegration();
1436
+ serviceApiKeys = await this.configureServiceApiKeys();
1437
+ hyperclawbotConfig = await this.configureHyperClawBot(gatewayConfig, channelConfigs);
1438
+ talkModeConfig = await this.configureTalkMode();
1439
+ pcAccess = await this.configurePcAccess();
1440
+ updateChannel = await this.configureUpdateChannel();
1441
+ groupSandbox = await this.configureGroupSandbox();
1442
+ await this.configureSkillHub();
1443
+ await this.configureMcpServers();
1444
+ await this.configureWorkspaceTemplate();
1445
+ await this.configureCronTasks();
1446
+ await this.configureAutoReply();
1447
+ await this.configureWebhooks();
1448
+ await this.configureNodes();
1449
+ await this.configureOAuth();
1450
+ await this.configureAgentBindings();
1451
+ rateLimit = await this.configureRateLimiting();
1452
+ await this.configureDeveloperKey();
1453
+ await this.configureVoiceCall();
1454
+ await this.configureCanvas();
1455
+ await this.configureDeploy();
1456
+ }
1457
+ this.stepHeader(9, STEPS, "Launch");
1458
+ const launchChoices = [{
1459
+ name: "Dashboard — terminal status",
1460
+ value: "tui"
1461
+ }];
1462
+ if (gatewayConfig && !gatewayConfig.remote) launchChoices.push({
1463
+ name: `Web — browser at http://localhost:${gatewayConfig.port}`,
1464
+ value: "web"
1465
+ });
1466
+ launchChoices.push({
1467
+ name: chalk.default.gray("Do this later — I will start manually"),
1468
+ value: "skip"
1469
+ });
1470
+ const { hatchMode } = await inquirer.default.prompt([{
1471
+ type: "list",
1472
+ name: "hatchMode",
1473
+ message: "How do you want to hatch your bot?",
1474
+ choices: launchChoices
1475
+ }]);
1476
+ await this.saveAll({
1477
+ workspaceName,
1478
+ providerConfig,
1479
+ providers: allProviders,
1480
+ channelConfigs,
1481
+ gatewayConfig: gatewayConfig ? {
1482
+ ...gatewayConfig,
1483
+ hooks: hooks.length > 0
1484
+ } : null,
1485
+ identity,
1486
+ hooks,
1487
+ heartbeatEnabled,
1488
+ installDaemon,
1489
+ daemonRuntime,
1490
+ hatchMode,
1491
+ webSearch,
1492
+ memoryIntegration,
1493
+ serviceApiKeys,
1494
+ hyperclawbotConfig,
1495
+ talkModeConfig,
1496
+ pcAccess,
1497
+ updateChannel,
1498
+ groupSandbox,
1499
+ rateLimit
1500
+ }, options);
1501
+ }
1502
+ async selectProvidersAndModels() {
1503
+ const { getTheme: getTheme$1 } = (require_theme.init_theme(), require_chunk.__toCommonJS(require_theme.theme_exports));
1504
+ const t = getTheme$1(false);
1505
+ console.log(chalk.default.gray(" Select one or more AI providers. The first one will be primary.\n"));
1506
+ const { selectedProviderIds } = await inquirer.default.prompt([{
1507
+ type: "checkbox",
1508
+ name: "selectedProviderIds",
1509
+ message: "Select AI providers:",
1510
+ validate: (v) => v.length > 0 || "Select at least one provider",
1511
+ choices: require_providers.PROVIDERS.map((p) => ({
1512
+ name: `${brandIcon(p.id, "provider")} ${p.displayName.replace(/^.{1,2}\s/, "").padEnd(18)}${p.supportsTranscription ? chalk.default.gray(" ??") : ""}`,
1513
+ value: p.id,
1514
+ checked: p.id === "openrouter"
1515
+ }))
1516
+ }]);
1517
+ const configured = [];
1518
+ for (let i = 0; i < selectedProviderIds.length; i++) {
1519
+ const pid = selectedProviderIds[i];
1520
+ const provider = require_providers.getProvider(pid);
1521
+ const isPrimary = i === 0;
1522
+ console.log(`\n ${t.c("?")} ${chalk.default.bold(provider.displayName)} ${isPrimary ? chalk.default.green("(primary)") : chalk.default.gray(`(#${i + 1})`)}\n`);
1523
+ if (provider.authHint) console.log(chalk.default.gray(` ?? ${provider.authHint}\n`));
1524
+ let apiKey = "";
1525
+ let baseUrl;
1526
+ let modelId = "";
1527
+ if (pid === "anthropic-oauth") {
1528
+ const fs$3 = await import("fs-extra");
1529
+ const path$3 = await import("path");
1530
+ const os$4 = await import("os");
1531
+ const credPath = path$3.join(os$4.homedir(), ".claude", ".credentials.json");
1532
+ const credExists = await fs$3.pathExists(credPath);
1533
+ if (credExists) {
1534
+ console.log(chalk.default.green(` ? Found Claude credentials: ${credPath}`));
1535
+ console.log(chalk.default.gray(" HyperClaw will reuse these credentials automatically.\n"));
1536
+ apiKey = "__claude_oauth__";
1537
+ } else {
1538
+ console.log(chalk.default.yellow(` ? ~/.claude/.credentials.json not found.\n`));
1539
+ console.log(chalk.default.gray(" Run `claude` CLI on this machine first to authenticate,\n or paste a setup-token (use \"Anthropic setup-token\" provider instead).\n"));
1540
+ apiKey = "__claude_oauth__";
1541
+ }
1542
+ } else if (pid === "anthropic-setup-token") {
1543
+ console.log(chalk.default.gray(" Run `claude setup-token` on any machine > paste the token below.\n"));
1544
+ const r = await inquirer.default.prompt([{
1545
+ type: "password",
1546
+ name: "apiKey",
1547
+ message: " Setup token (sk-ant-setup-...):",
1548
+ mask: "?",
1549
+ validate: (v) => v.trim().length > 10 || "Required"
1550
+ }]);
1551
+ apiKey = r.apiKey.trim();
1552
+ } else if (provider.authType === "api_key") if (pid === "custom") {
1553
+ const r = await inquirer.default.prompt([
1554
+ {
1555
+ type: "input",
1556
+ name: "baseUrl",
1557
+ message: " Base URL:",
1558
+ validate: (v) => v.trim().length > 5 || "Required"
1559
+ },
1560
+ {
1561
+ type: "password",
1562
+ name: "apiKey",
1563
+ message: ` ${provider.authLabel}:`,
1564
+ mask: "?",
1565
+ validate: (v) => v.trim().length > 5 || "Required"
1566
+ },
1567
+ {
1568
+ type: "input",
1569
+ name: "modelId",
1570
+ message: " Model ID:",
1571
+ validate: (v) => v.trim().length > 0 || "Required"
1572
+ }
1573
+ ]);
1574
+ baseUrl = r.baseUrl.trim().replace(/\/$/, "");
1575
+ apiKey = r.apiKey;
1576
+ modelId = r.modelId.trim();
1577
+ } else {
1578
+ const { validateApiKeyFormat } = await Promise.resolve().then(() => require("./api-key-validation-BeQ2MZAT.js"));
1579
+ const r = await inquirer.default.prompt([{
1580
+ type: "password",
1581
+ name: "apiKey",
1582
+ message: ` ${provider.authLabel}:`,
1583
+ mask: "●",
1584
+ validate: (v) => {
1585
+ const t$1 = (v || "").trim();
1586
+ if (t$1.length < 5) return "Required";
1587
+ const err = validateApiKeyFormat(pid, t$1);
1588
+ return err || true;
1589
+ }
1590
+ }]);
1591
+ apiKey = r.apiKey;
1592
+ }
1593
+ if (!modelId) {
1594
+ const modelChoices = provider.models.filter((m) => m.id !== "__manual__").length ? [...provider.models.filter((m) => m.id !== "__manual__").map((m) => ({
1595
+ name: require_providers.formatModel(m),
1596
+ value: m.id
1597
+ })), {
1598
+ name: chalk.default.gray("Enter manually..."),
1599
+ value: "__manual__"
1600
+ }] : [{
1601
+ name: chalk.default.gray("Enter model ID manually"),
1602
+ value: "__manual__"
1603
+ }];
1604
+ const { modelChoice } = await inquirer.default.prompt([{
1605
+ type: "list",
1606
+ name: "modelChoice",
1607
+ message: " Default model:",
1608
+ choices: modelChoices
1609
+ }]);
1610
+ if (modelChoice === "__manual__") {
1611
+ const { manual } = await inquirer.default.prompt([{
1612
+ type: "input",
1613
+ name: "manual",
1614
+ message: " Model ID:",
1615
+ default: provider.models[0]?.id || ""
1616
+ }]);
1617
+ modelId = manual;
1618
+ } else modelId = modelChoice;
1619
+ }
1620
+ const apiKeys = [];
1621
+ if (apiKey) {
1622
+ const { wantRotation } = await inquirer.default.prompt([{
1623
+ type: "confirm",
1624
+ name: "wantRotation",
1625
+ message: ` Add extra API keys for rate-limit rotation? ${chalk.default.gray("(gateway cycles through on 429)")}`,
1626
+ default: false
1627
+ }]);
1628
+ if (wantRotation) {
1629
+ let addMore = true;
1630
+ while (addMore) {
1631
+ const { extraKey } = await inquirer.default.prompt([{
1632
+ type: "password",
1633
+ name: "extraKey",
1634
+ message: ` Extra key #${apiKeys.length + 1}:`,
1635
+ mask: "?"
1636
+ }]);
1637
+ if (extraKey.trim()) apiKeys.push(extraKey.trim());
1638
+ const { more } = await inquirer.default.prompt([{
1639
+ type: "confirm",
1640
+ name: "more",
1641
+ message: " Add another?",
1642
+ default: false
1643
+ }]);
1644
+ addMore = more;
1645
+ }
1646
+ if (apiKeys.length > 0) console.log(chalk.default.green(` ? ${apiKeys.length} extra key(s) added for rotation\n`));
1647
+ }
1648
+ }
1649
+ let thinking;
1650
+ if (["anthropic", "openai"].includes(pid)) {
1651
+ const { thinkingLevel } = await inquirer.default.prompt([{
1652
+ type: "list",
1653
+ name: "thinkingLevel",
1654
+ message: ` Extended thinking / reasoning:`,
1655
+ choices: [
1656
+ {
1657
+ name: `Off ${chalk.default.gray("(standard responses)")}`,
1658
+ value: "off"
1659
+ },
1660
+ {
1661
+ name: `Standard ${chalk.default.gray("(~8 000 token budget)")}`,
1662
+ value: "standard"
1663
+ },
1664
+ {
1665
+ name: `Extended ${chalk.default.gray("(~32 000 token budget — slower, deeper)")}`,
1666
+ value: "extended"
1667
+ }
1668
+ ],
1669
+ default: "off"
1670
+ }]);
1671
+ if (thinkingLevel !== "off") {
1672
+ thinking = {
1673
+ enabled: true,
1674
+ budgetTokens: thinkingLevel === "extended" ? 32e3 : 8e3
1675
+ };
1676
+ console.log(chalk.default.green(` ? Thinking: ${thinkingLevel} (${thinking.budgetTokens.toLocaleString()} tokens)\n`));
1677
+ }
1678
+ }
1679
+ configured.push({
1680
+ providerId: pid,
1681
+ apiKey,
1682
+ modelId,
1683
+ ...baseUrl ? { baseUrl } : {},
1684
+ ...apiKeys.length > 0 ? { apiKeys } : {},
1685
+ ...thinking ? { thinking } : {}
1686
+ });
1687
+ console.log(t.c(` ? ${provider.displayName} > ${modelId}\n`));
1688
+ }
1689
+ return {
1690
+ providers: configured,
1691
+ primary: configured[0]
1692
+ };
1693
+ }
1694
+ async configureGateway(full = false) {
1695
+ const { gatewayMode } = await inquirer.default.prompt([{
1696
+ type: "list",
1697
+ name: "gatewayMode",
1698
+ message: "Gateway setup:",
1699
+ choices: [
1700
+ {
1701
+ name: `Local gateway ${chalk.default.gray("(run on this machine)")}`,
1702
+ value: "local"
1703
+ },
1704
+ {
1705
+ name: `Remote gateway ${chalk.default.gray("(info-only — connect to existing server)")}`,
1706
+ value: "remote"
1707
+ },
1708
+ {
1709
+ name: chalk.default.gray("Skip (no gateway — CLI-only mode)"),
1710
+ value: "skip"
1711
+ }
1712
+ ]
1713
+ }]);
1714
+ if (gatewayMode === "skip") {
1715
+ console.log(chalk.default.gray(" ? Gateway skipped. Enable later: hyperclaw gateway start\n"));
1716
+ return null;
1717
+ }
1718
+ if (gatewayMode === "remote") {
1719
+ const { remoteUrl } = await inquirer.default.prompt([{
1720
+ type: "input",
1721
+ name: "remoteUrl",
1722
+ message: "Remote gateway URL (e.g. wss://myserver.com:18789 or http://127.0.0.1:18789 for SSH tunnel):",
1723
+ validate: (v) => v.startsWith("ws") || v.startsWith("http") || "Must start with ws://, wss:// or http://"
1724
+ }]);
1725
+ const { remoteToken } = await inquirer.default.prompt([{
1726
+ type: "password",
1727
+ name: "remoteToken",
1728
+ message: "Remote gateway auth token:",
1729
+ mask: "?"
1730
+ }]);
1731
+ const httpUrl = remoteUrl.startsWith("http") ? remoteUrl : remoteUrl.replace(/^ws/, "http");
1732
+ console.log(chalk.default.green(" ? Remote gateway configured\n"));
1733
+ return {
1734
+ port: 18789,
1735
+ bind: "127.0.0.1",
1736
+ authToken: "",
1737
+ tailscaleExposure: "off",
1738
+ runtime: "node",
1739
+ enabledChannels: [],
1740
+ hooks: true,
1741
+ mode: "remote",
1742
+ remote: {
1743
+ url: httpUrl,
1744
+ token: remoteToken || void 0
1745
+ }
1746
+ };
1747
+ }
1748
+ const { useGateway } = await inquirer.default.prompt([{
1749
+ type: "confirm",
1750
+ name: "useGateway",
1751
+ message: "Enable the local WebSocket gateway? (needed for channels, web UI, mobile apps)",
1752
+ default: true
1753
+ }]);
1754
+ if (!useGateway) {
1755
+ console.log(chalk.default.gray(" ? Gateway skipped. You can enable it later: hyperclaw gateway start\n"));
1756
+ return null;
1757
+ }
1758
+ const running = await this.gateway.isRunning(18789);
1759
+ if (running) console.log(chalk.default.gray(` ? Gateway already running at ws://127.0.0.1:18789`));
1760
+ const detectedRuntime = await this.gateway.detectRuntime();
1761
+ const questions = [{
1762
+ type: "input",
1763
+ name: "port",
1764
+ message: "Gateway port:",
1765
+ default: String(18789),
1766
+ validate: (v) => Number(v) > 1024 && Number(v) < 65535 ? true : "Enter valid port (1024-65535)"
1767
+ }];
1768
+ if (full) questions.push({
1769
+ type: "list",
1770
+ name: "bind",
1771
+ message: "Bind address:",
1772
+ choices: [
1773
+ {
1774
+ name: `127.0.0.1 ${chalk.default.gray("Loopback only (secure)")}`,
1775
+ value: "127.0.0.1"
1776
+ },
1777
+ {
1778
+ name: `0.0.0.0 ${chalk.default.gray("All interfaces (LAN)")}`,
1779
+ value: "0.0.0.0"
1780
+ },
1781
+ {
1782
+ name: `Tailscale ${chalk.default.gray("VPN peers only")}`,
1783
+ value: "tailscale"
1784
+ },
1785
+ {
1786
+ name: `Custom ${chalk.default.gray("Enter IP manually")}`,
1787
+ value: "custom"
1788
+ }
1789
+ ],
1790
+ default: "127.0.0.1"
1791
+ }, {
1792
+ type: "list",
1793
+ name: "tailscaleExposure",
1794
+ message: "Tailscale exposure:",
1795
+ choices: [
1796
+ {
1797
+ name: this.gateway.exposureLabel("off"),
1798
+ value: "off"
1799
+ },
1800
+ {
1801
+ name: this.gateway.exposureLabel("serve"),
1802
+ value: "serve"
1803
+ },
1804
+ {
1805
+ name: this.gateway.exposureLabel("funnel"),
1806
+ value: "funnel"
1807
+ }
1808
+ ],
1809
+ default: "off",
1810
+ when: (a) => a.bind === "tailscale"
1811
+ }, {
1812
+ type: "list",
1813
+ name: "runtime",
1814
+ message: "Runtime:",
1815
+ choices: [
1816
+ {
1817
+ name: `Node.js ${detectedRuntime === "node" ? chalk.default.green("(detected)") : ""}`,
1818
+ value: "node"
1819
+ },
1820
+ {
1821
+ name: `Bun ${detectedRuntime === "bun" ? chalk.default.green("(detected)") : chalk.default.gray("(faster)")}`,
1822
+ value: "bun"
1823
+ },
1824
+ {
1825
+ name: `Deno ${detectedRuntime === "deno" ? chalk.default.green("(detected)") : ""}`,
1826
+ value: "deno"
1827
+ }
1828
+ ],
1829
+ default: detectedRuntime
1830
+ });
1831
+ questions.push({
1832
+ type: "password",
1833
+ name: "authToken",
1834
+ message: `Auth token: ${chalk.default.gray("(blank = auto-generate)")}`,
1835
+ mask: "?"
1836
+ });
1837
+ const answers = await inquirer.default.prompt(questions);
1838
+ const token = answers.authToken || this.gateway.generateToken();
1839
+ if (!answers.authToken) console.log(chalk.default.green(" ? Auth token auto-generated\n"));
1840
+ const { wantSshTunnel } = await inquirer.default.prompt([{
1841
+ type: "confirm",
1842
+ name: "wantSshTunnel",
1843
+ message: `SSH reverse tunnel for remote access? ${chalk.default.gray("(alternative to Tailscale)")}`,
1844
+ default: false
1845
+ }]);
1846
+ let sshTunnel;
1847
+ if (wantSshTunnel) {
1848
+ const sshAns = await inquirer.default.prompt([
1849
+ {
1850
+ type: "input",
1851
+ name: "host",
1852
+ message: " Remote SSH host (e.g. myserver.com):",
1853
+ validate: (v) => v.trim().length > 3 || "Required"
1854
+ },
1855
+ {
1856
+ type: "input",
1857
+ name: "user",
1858
+ message: " SSH user:",
1859
+ default: process.env.USER || process.env.USERNAME || "ubuntu"
1860
+ },
1861
+ {
1862
+ type: "input",
1863
+ name: "remotePort",
1864
+ message: " Remote port (forwarded on server):",
1865
+ default: String(Number(answers.port) || 18789),
1866
+ validate: (v) => Number(v) > 1024 && Number(v) < 65535 ? true : "Valid port required"
1867
+ }
1868
+ ]);
1869
+ sshTunnel = {
1870
+ enabled: true,
1871
+ host: sshAns.host.trim(),
1872
+ user: sshAns.user.trim(),
1873
+ remotePort: Number(sshAns.remotePort)
1874
+ };
1875
+ console.log(chalk.default.green(` ? SSH tunnel: ${sshTunnel.user}@${sshTunnel.host}:${sshTunnel.remotePort}\n`));
1876
+ console.log(chalk.default.gray(` Run: ssh -R ${sshTunnel.remotePort}:localhost:${Number(answers.port)} ${sshTunnel.user}@${sshTunnel.host}\n`));
1877
+ }
1878
+ return {
1879
+ port: Number(answers.port),
1880
+ bind: answers.bind || "127.0.0.1",
1881
+ authToken: token,
1882
+ tailscaleExposure: answers.tailscaleExposure || "off",
1883
+ runtime: answers.runtime || detectedRuntime,
1884
+ enabledChannels: [],
1885
+ hooks: true,
1886
+ ...sshTunnel ? { sshTunnel } : {}
1887
+ };
1888
+ }
1889
+ async selectChannels(full = false) {
1890
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Communication Channels\n"));
1891
+ const available = await getAvailableChannels();
1892
+ const { selectedChannels } = await inquirer.default.prompt([{
1893
+ type: "checkbox",
1894
+ name: "selectedChannels",
1895
+ message: "Enable channels:",
1896
+ choices: available.map((ch) => {
1897
+ const isUnavailable = ch.status === "unavailable";
1898
+ const reason = isUnavailable ? unavailableReason(ch) : "";
1899
+ const icon$1 = brandIcon(ch.id, "channel");
1900
+ return {
1901
+ name: `${icon$1} ${ch.name.padEnd(18)} ${statusBadge(ch.status, ch)}${ch.requiresGateway && !isUnavailable ? chalk.default.gray(" [needs gateway]") : ""}`,
1902
+ value: ch.id,
1903
+ checked: ch.status === "recommended",
1904
+ disabled: isUnavailable ? reason : false
1905
+ };
1906
+ })
1907
+ }]);
1908
+ const channelConfigs = {};
1909
+ for (const channelId of selectedChannels) {
1910
+ const ch = CHANNELS.find((c) => c.id === channelId);
1911
+ if (!ch || !ch.tokenLabel) continue;
1912
+ console.log(chalk.default.hex("#06b6d4")(`\n ${ch.emoji} ${ch.name}`));
1913
+ if (ch.setupSteps?.length) ch.setupSteps.forEach((s) => console.log(chalk.default.gray(` ${s}`)));
1914
+ else if (ch.tokenHint) console.log(chalk.default.gray(` ?? ${ch.tokenHint}`));
1915
+ const fields = [{
1916
+ type: "password",
1917
+ name: "token",
1918
+ message: `${ch.tokenLabel}:`,
1919
+ mask: "?"
1920
+ }];
1921
+ for (const f of ch.extraFields || []) fields.push({
1922
+ type: "input",
1923
+ name: f.name,
1924
+ message: `${f.label}:${f.hint ? chalk.default.gray(` (${f.hint})`) : ""}`,
1925
+ ...f.required ? { validate: (v) => v.trim().length > 0 || `${f.label} is required` } : {}
1926
+ });
1927
+ channelConfigs[channelId] = await inquirer.default.prompt(fields);
1928
+ }
1929
+ if (selectedChannels.includes("twitch") && channelConfigs["twitch"]?.channels) {
1930
+ const raw = channelConfigs["twitch"].channels;
1931
+ channelConfigs["twitch"].channels = raw.split(",").map((s) => s.trim().replace(/^#/, "").toLowerCase()).filter(Boolean);
1932
+ }
1933
+ if (selectedChannels.includes("email")) {
1934
+ const { wantGmailOAuth } = await inquirer.default.prompt([{
1935
+ type: "confirm",
1936
+ name: "wantGmailOAuth",
1937
+ message: "Enable Gmail OAuth for Pub/Sub real-time (send via hyperclaw gmail watch-setup)?",
1938
+ default: false
1939
+ }]);
1940
+ if (wantGmailOAuth) {
1941
+ console.log(chalk.default.gray(" Running OAuth flow for google-gmail..."));
1942
+ try {
1943
+ const { runOAuthFlow } = await Promise.resolve().then(() => require("./oauth-flow-Du2N6B2V.js"));
1944
+ const { writeOAuthToken } = await Promise.resolve().then(() => require("./oauth-provider-B2RBpiXg.js"));
1945
+ const tokens = await runOAuthFlow("google-gmail", {});
1946
+ const now = Math.floor(Date.now() / 1e3);
1947
+ const expires_at = tokens.expires_in ? now + tokens.expires_in : void 0;
1948
+ await writeOAuthToken("google-gmail", {
1949
+ access_token: tokens.access_token,
1950
+ refresh_token: tokens.refresh_token,
1951
+ expires_at,
1952
+ token_url: "https://oauth2.googleapis.com/token"
1953
+ });
1954
+ console.log(chalk.default.green(" ? Gmail OAuth configured — next: hyperclaw gmail watch-setup"));
1955
+ } catch (e) {
1956
+ console.log(chalk.default.yellow(` ? OAuth failed — you can run it later: hyperclaw auth oauth google-gmail`));
1957
+ }
1958
+ }
1959
+ }
1960
+ return channelConfigs;
1961
+ }
1962
+ async configureWebSearch(skip = false) {
1963
+ if (skip) return null;
1964
+ const { wantSearch } = await inquirer.default.prompt([{
1965
+ type: "confirm",
1966
+ name: "wantSearch",
1967
+ message: "Configure a web search provider for the agent?",
1968
+ default: false
1969
+ }]);
1970
+ if (!wantSearch) return null;
1971
+ const SEARCH_PROVIDERS = [
1972
+ {
1973
+ id: "tavily",
1974
+ name: "Tavily",
1975
+ hint: "app.tavily.com — best for agents",
1976
+ prefix: "tvly-"
1977
+ },
1978
+ {
1979
+ id: "perplexity",
1980
+ name: "Perplexity",
1981
+ hint: "perplexity.ai/settings/api",
1982
+ prefix: "pplx-"
1983
+ },
1984
+ {
1985
+ id: "brave",
1986
+ name: "Brave Search",
1987
+ hint: "api.search.brave.com",
1988
+ prefix: "BSA"
1989
+ },
1990
+ {
1991
+ id: "gemini",
1992
+ name: "Gemini",
1993
+ hint: "aistudio.google.com/app/apikey",
1994
+ prefix: "AIza"
1995
+ },
1996
+ {
1997
+ id: "grok",
1998
+ name: "Grok/xAI",
1999
+ hint: "console.x.ai — same key as xAI provider",
2000
+ prefix: "xai-"
2001
+ },
2002
+ {
2003
+ id: "kimi",
2004
+ name: "Kimi (Moonshot)",
2005
+ hint: "platform.moonshot.cn/user-center/api-keys",
2006
+ prefix: "sk-"
2007
+ }
2008
+ ];
2009
+ const { searchProvider } = await inquirer.default.prompt([{
2010
+ type: "list",
2011
+ name: "searchProvider",
2012
+ message: "Select web search provider:",
2013
+ choices: SEARCH_PROVIDERS.map((p) => ({
2014
+ name: `${p.name.padEnd(14)} ${chalk.default.gray(p.hint)}`,
2015
+ value: p.id
2016
+ }))
2017
+ }]);
2018
+ const chosen = SEARCH_PROVIDERS.find((p) => p.id === searchProvider);
2019
+ const { searchKey } = await inquirer.default.prompt([{
2020
+ type: "password",
2021
+ name: "searchKey",
2022
+ message: `${chosen.name} API key (starts with ${chalk.default.gray(chosen.prefix)}):`,
2023
+ mask: "?",
2024
+ validate: (v) => v.trim().length > 4 || "Required"
2025
+ }]);
2026
+ console.log(chalk.default.green(` ? Web search: ${chosen.name}`));
2027
+ return {
2028
+ provider: searchProvider,
2029
+ apiKey: searchKey.trim()
2030
+ };
2031
+ }
2032
+ async configureServiceApiKeys() {
2033
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Service API Keys — any app with an API key\n"));
2034
+ console.log(chalk.default.gray(" Stored securely in config. How they work:\n"));
2035
+ console.log(chalk.default.gray(" ● Wizard: add keys here\n"));
2036
+ console.log(chalk.default.gray(" ● Config: ~/.hyperclaw/hyperclaw.json > skills.apiKeys\n"));
2037
+ console.log(chalk.default.gray(" ● Env: HACKERONE_*, BUGCROWD_*, SYNACK_*, or CUSTOM_ID_API_KEY\n"));
2038
+ console.log(chalk.default.gray(" ● Tools: built-in tools read them automatically for research.\n"));
2039
+ const { wantServiceKeys } = await inquirer.default.prompt([{
2040
+ type: "confirm",
2041
+ name: "wantServiceKeys",
2042
+ message: "Add API keys for external services (HackerOne, Bugcrowd, Synack, or custom)?",
2043
+ default: false
2044
+ }]);
2045
+ if (!wantServiceKeys) return {};
2046
+ const KNOWN_SERVICES = [
2047
+ {
2048
+ id: "hackerone",
2049
+ name: "HackerOne",
2050
+ hint: "username:token (Basic auth)"
2051
+ },
2052
+ {
2053
+ id: "bugcrowd",
2054
+ name: "Bugcrowd",
2055
+ hint: "Token from Bugcrowd API Credentials"
2056
+ },
2057
+ {
2058
+ id: "synack",
2059
+ name: "Synack",
2060
+ hint: "API token from Synack"
2061
+ },
2062
+ {
2063
+ id: "__custom__",
2064
+ name: "Other (custom)",
2065
+ hint: "Any app with an API key"
2066
+ }
2067
+ ];
2068
+ const { servicesToAdd } = await inquirer.default.prompt([{
2069
+ type: "checkbox",
2070
+ name: "servicesToAdd",
2071
+ message: "Select services:",
2072
+ choices: KNOWN_SERVICES.filter((s) => s.id !== "__custom__").map((s) => ({
2073
+ name: `${s.name} ${chalk.default.gray(`(${s.hint})`)}`,
2074
+ value: s.id
2075
+ })),
2076
+ validate: (v) => true
2077
+ }]);
2078
+ const apiKeys = {};
2079
+ for (const sid of servicesToAdd || []) {
2080
+ const svc = KNOWN_SERVICES.find((s) => s.id === sid);
2081
+ const r = await inquirer.default.prompt([{
2082
+ type: "password",
2083
+ name: "key",
2084
+ message: `${svc?.name || sid} API key:`,
2085
+ mask: "?",
2086
+ validate: (v) => v.trim().length > 3 || "Required"
2087
+ }]);
2088
+ apiKeys[sid] = r.key.trim();
2089
+ }
2090
+ const { addCustom } = await inquirer.default.prompt([{
2091
+ type: "confirm",
2092
+ name: "addCustom",
2093
+ message: "Add a custom service (any app)?",
2094
+ default: false
2095
+ }]);
2096
+ if (addCustom) {
2097
+ const { customId, customKey } = await inquirer.default.prompt([{
2098
+ type: "input",
2099
+ name: "customId",
2100
+ message: "Service ID (e.g. my-app, ads-power):",
2101
+ validate: (v) => /^[a-z0-9_-]+$/i.test(v?.trim() || "") || "Letters, numbers, - _ only"
2102
+ }, {
2103
+ type: "password",
2104
+ name: "customKey",
2105
+ message: "API key:",
2106
+ mask: "?",
2107
+ validate: (v) => v.trim().length > 3 || "Required"
2108
+ }]);
2109
+ apiKeys[customId.trim().toLowerCase()] = customKey.trim();
2110
+ }
2111
+ if (Object.keys(apiKeys).length > 0) console.log(chalk.default.green(` ? Saved ${Object.keys(apiKeys).length} API key(s)`));
2112
+ return apiKeys;
2113
+ }
2114
+ async configureHyperClawBot(gatewayConfig, existingChannelConfigs) {
2115
+ console.log(chalk.default.hex("#06b6d4")("\n ?? HyperClaw Bot — Remote control via Telegram\n"));
2116
+ const trans = require_providers.getTranscriptionProviders();
2117
+ if (trans.length > 0) {
2118
+ console.log(chalk.default.gray(" ?? Voice notes: " + trans.map((p) => `${p.displayName}`).join(", ") + " — if you have their API key, voice messages will be transcribed to text."));
2119
+ console.log();
2120
+ }
2121
+ const { wantHyperClawBot } = await inquirer.default.prompt([{
2122
+ type: "confirm",
2123
+ name: "wantHyperClawBot",
2124
+ message: "Enable HyperClaw Bot for remote control (status, restart, /agent from mobile)?",
2125
+ default: false
2126
+ }]);
2127
+ if (!wantHyperClawBot) return void 0;
2128
+ const existingTelegramToken = existingChannelConfigs?.["telegram"]?.token;
2129
+ let token;
2130
+ if (existingTelegramToken) {
2131
+ const { reuseToken } = await inquirer.default.prompt([{
2132
+ type: "confirm",
2133
+ name: "reuseToken",
2134
+ message: "Use the same Telegram bot you already configured above?",
2135
+ default: true
2136
+ }]);
2137
+ if (reuseToken) {
2138
+ token = existingTelegramToken;
2139
+ console.log(chalk.default.green(" ? Reusing existing Telegram bot token\n"));
2140
+ } else {
2141
+ const r = await inquirer.default.prompt([{
2142
+ type: "input",
2143
+ name: "token",
2144
+ message: "Telegram Bot token (from @BotFather):",
2145
+ validate: (v) => v.trim().length > 10 || "Required"
2146
+ }]);
2147
+ token = r.token.trim();
2148
+ }
2149
+ } else {
2150
+ const r = await inquirer.default.prompt([{
2151
+ type: "input",
2152
+ name: "token",
2153
+ message: "Telegram Bot token (from @BotFather):",
2154
+ validate: (v) => v.trim().length > 10 || "Required"
2155
+ }]);
2156
+ token = r.token.trim();
2157
+ }
2158
+ const { userIds } = await inquirer.default.prompt([{
2159
+ type: "input",
2160
+ name: "userIds",
2161
+ message: "Allowed user IDs (comma-separated, leave empty = everyone):",
2162
+ default: ""
2163
+ }]);
2164
+ const gatewayUrl = `http://localhost:${gatewayConfig?.port || 18789}`;
2165
+ const { saveBotConfig } = await Promise.resolve().then(() => require("./hyperclawbot-CFHXZr12.js"));
2166
+ await saveBotConfig({
2167
+ platform: "telegram",
2168
+ token: token.trim(),
2169
+ gatewayUrl,
2170
+ allowedUsers: userIds ? userIds.split(",").map((s) => s.trim()).filter(Boolean) : [],
2171
+ gatewayToken: void 0,
2172
+ enabled: true,
2173
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
2174
+ });
2175
+ console.log(chalk.default.green(" ? HyperClaw Bot configured — Start: hyperclaw bot start"));
2176
+ return { token: token.trim() };
2177
+ }
2178
+ async configureTalkMode() {
2179
+ console.log(chalk.default.hex("#06b6d4")("\n ??? Talk Mode — ElevenLabs TTS\n"));
2180
+ const { wantTalkMode } = await inquirer.default.prompt([{
2181
+ type: "confirm",
2182
+ name: "wantTalkMode",
2183
+ message: "Enable Talk Mode (voice responses via ElevenLabs)?",
2184
+ default: false
2185
+ }]);
2186
+ if (!wantTalkMode) return void 0;
2187
+ const { apiKey } = await inquirer.default.prompt([{
2188
+ type: "password",
2189
+ name: "apiKey",
2190
+ message: "ElevenLabs API key (elevenlabs.io):",
2191
+ mask: "?",
2192
+ validate: (v) => v.trim().length > 10 || "Required"
2193
+ }]);
2194
+ console.log(chalk.default.green(" ? Talk Mode configured"));
2195
+ return {
2196
+ apiKey: apiKey.trim(),
2197
+ voiceId: "21m00Tcm4TlvDq8ikWAM",
2198
+ modelId: "eleven_multilingual_v2"
2199
+ };
2200
+ }
2201
+ async configureMemoryIntegration() {
2202
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Memory Integration (Obsidian / Raycast / Hazel)\n"));
2203
+ const { vaultPath } = await inquirer.default.prompt([{
2204
+ type: "input",
2205
+ name: "vaultPath",
2206
+ message: "Sync memory to vault? Enter path or leave empty to skip:",
2207
+ default: ""
2208
+ }]);
2209
+ const vaultDir = String(vaultPath || "").trim();
2210
+ if (!vaultDir) return void 0;
2211
+ const { dailyNotes } = await inquirer.default.prompt([{
2212
+ type: "confirm",
2213
+ name: "dailyNotes",
2214
+ message: "Write daily notes with session summaries?",
2215
+ default: true
2216
+ }]);
2217
+ return {
2218
+ vaultDir,
2219
+ dailyNotes,
2220
+ syncOnAppend: true
2221
+ };
2222
+ }
2223
+ async configureIdentity() {
2224
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Agent Identity\n"));
2225
+ const identity = await inquirer.default.prompt([
2226
+ {
2227
+ type: "input",
2228
+ name: "userName",
2229
+ message: "Your name:",
2230
+ default: "Boss"
2231
+ },
2232
+ {
2233
+ type: "input",
2234
+ name: "agentName",
2235
+ message: "Agent name:",
2236
+ default: "Hyper"
2237
+ },
2238
+ {
2239
+ type: "input",
2240
+ name: "wakeWord",
2241
+ message: "Wake word for voice:",
2242
+ default: (a) => `Hey ${a.agentName || "Hyper"}`
2243
+ },
2244
+ {
2245
+ type: "list",
2246
+ name: "personality",
2247
+ message: "Personality:",
2248
+ choices: [
2249
+ "Professional and concise",
2250
+ "Friendly and casual",
2251
+ "Witty with humor",
2252
+ "Direct and no-nonsense",
2253
+ "Custom"
2254
+ ]
2255
+ },
2256
+ {
2257
+ type: "input",
2258
+ name: "customPersonality",
2259
+ message: "Describe personality:",
2260
+ when: (a) => a.personality === "Custom"
2261
+ },
2262
+ {
2263
+ type: "list",
2264
+ name: "language",
2265
+ message: "Primary language:",
2266
+ choices: [
2267
+ "English",
2268
+ "Greek",
2269
+ "Spanish",
2270
+ "French",
2271
+ "German",
2272
+ "Chinese",
2273
+ "Japanese",
2274
+ "Arabic"
2275
+ ]
2276
+ }
2277
+ ]);
2278
+ console.log(chalk.default.gray("\n This is the greeting sent to your channels when the agent starts.\n"));
2279
+ const { wakeUpMessage } = await inquirer.default.prompt([{
2280
+ type: "input",
2281
+ name: "wakeUpMessage",
2282
+ message: "Agent wake-up message:",
2283
+ default: (identity.agentName || "Hyper") + " is online. How can I help you today?"
2284
+ }]);
2285
+ const { wantSystemPrompt } = await inquirer.default.prompt([{
2286
+ type: "confirm",
2287
+ name: "wantSystemPrompt",
2288
+ message: "Add a custom system prompt / instructions for the agent?",
2289
+ default: false
2290
+ }]);
2291
+ let systemPrompt = "";
2292
+ if (wantSystemPrompt) {
2293
+ console.log(chalk.default.gray(" Tip: describe role, restrictions, tone, specific knowledge, etc.\n"));
2294
+ const r = await inquirer.default.prompt([{
2295
+ type: "editor",
2296
+ name: "systemPrompt",
2297
+ message: "System prompt (opens editor — save & close to continue):"
2298
+ }]);
2299
+ systemPrompt = r.systemPrompt?.trim() || "";
2300
+ }
2301
+ const globalRules = [
2302
+ "Always respond in the user's preferred language",
2303
+ "Never reveal the gateway auth token or API keys",
2304
+ "Confirm before destructive or irreversible actions",
2305
+ "Respect user privacy — never share conversation data",
2306
+ "All subagents inherit these rules — cannot be overridden"
2307
+ ];
2308
+ const { addRules } = await inquirer.default.prompt([{
2309
+ type: "confirm",
2310
+ name: "addRules",
2311
+ message: "Add custom rules to AGENTS.md?",
2312
+ default: false
2313
+ }]);
2314
+ let customRules = [];
2315
+ if (addRules) {
2316
+ const { rules } = await inquirer.default.prompt([{
2317
+ type: "input",
2318
+ name: "rules",
2319
+ message: "Rules (semicolon-separated):",
2320
+ filter: (v) => v.split(";").map((r) => r.trim()).filter(Boolean)
2321
+ }]);
2322
+ customRules = rules;
2323
+ }
2324
+ const personality = identity.personality === "Custom" ? identity.customPersonality || "Custom" : identity.personality;
2325
+ return {
2326
+ agentName: identity.agentName,
2327
+ userName: identity.userName,
2328
+ language: identity.language,
2329
+ personality,
2330
+ wakeUpMessage: wakeUpMessage.trim(),
2331
+ systemPrompt: systemPrompt || void 0,
2332
+ rules: [...globalRules, ...customRules]
2333
+ };
2334
+ }
2335
+ async configureSkillsAndHooks() {
2336
+ const { wantSkills } = await inquirer.default.prompt([{
2337
+ type: "confirm",
2338
+ name: "wantSkills",
2339
+ message: "Configure skills & hooks now?",
2340
+ default: false
2341
+ }]);
2342
+ if (!wantSkills) {
2343
+ console.log(chalk.default.gray(" ? Skipped — enable later: hyperclaw hooks enable <name>\n"));
2344
+ return {
2345
+ hooks: [],
2346
+ heartbeat: false
2347
+ };
2348
+ }
2349
+ const { selectedHooks } = await inquirer.default.prompt([{
2350
+ type: "checkbox",
2351
+ name: "selectedHooks",
2352
+ message: "Select hooks to enable:",
2353
+ choices: [
2354
+ {
2355
+ name: `${"boot.md".padEnd(22)} ${chalk.default.gray("Run commands on agent startup")}`,
2356
+ value: "boot"
2357
+ },
2358
+ {
2359
+ name: `${"command-logger".padEnd(22)} ${chalk.default.gray("Log every tool call to file")}`,
2360
+ value: "command-logger"
2361
+ },
2362
+ {
2363
+ name: `${"session-memory".padEnd(22)} ${chalk.default.gray("Persist session context across restarts")}`,
2364
+ value: "session-memory"
2365
+ },
2366
+ {
2367
+ name: `${"morning-briefing".padEnd(22)} ${chalk.default.gray("Daily proactive summary to HEARTBEAT.md")}`,
2368
+ value: "morning-briefing"
2369
+ }
2370
+ ]
2371
+ }]);
2372
+ const heartbeat = selectedHooks.includes("morning-briefing");
2373
+ try {
2374
+ const { HookLoader } = await Promise.resolve().then(() => require("./loader-CbS0tIrR.js"));
2375
+ const loader = new HookLoader();
2376
+ for (const h of selectedHooks) loader.enable(h);
2377
+ } catch {}
2378
+ if (selectedHooks.length > 0) console.log(chalk.default.green(` ? Enabled: ${selectedHooks.join(", ")}\n`));
2379
+ return {
2380
+ hooks: selectedHooks,
2381
+ heartbeat
2382
+ };
2383
+ }
2384
+ async configurePcAccess() {
2385
+ console.log(chalk.default.hex("#06b6d4")("\n ?? PC Access Level\n"));
2386
+ console.log(chalk.default.gray(" Controls what the agent can do on your computer.\n"));
2387
+ const { level } = await inquirer.default.prompt([{
2388
+ type: "list",
2389
+ name: "level",
2390
+ message: "PC access level:",
2391
+ choices: [
2392
+ {
2393
+ name: `Full ${chalk.default.gray("(bash, file read/write, screenshots — recommended for power users)")}`,
2394
+ value: "full"
2395
+ },
2396
+ {
2397
+ name: `Sandboxed ${chalk.default.gray("(read files, limited shell, no destructive writes)")}`,
2398
+ value: "sandboxed"
2399
+ },
2400
+ {
2401
+ name: `Read-only ${chalk.default.gray("(read files only — safest)")}`,
2402
+ value: "read-only"
2403
+ }
2404
+ ],
2405
+ default: "full"
2406
+ }]);
2407
+ const { confirmDestructive } = await inquirer.default.prompt([{
2408
+ type: "confirm",
2409
+ name: "confirmDestructive",
2410
+ message: "Require confirmation before destructive actions (delete files, overwrite)?",
2411
+ default: level !== "full"
2412
+ }]);
2413
+ console.log(chalk.default.green(` ? PC access: ${level}${confirmDestructive ? " + confirm destructive" : ""}\n`));
2414
+ return {
2415
+ level,
2416
+ confirmDestructive
2417
+ };
2418
+ }
2419
+ async configureSkillHub() {
2420
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Skill Hub (ClawHub)\n"));
2421
+ console.log(chalk.default.gray(" Install skills from the ClawHub marketplace (AI tools, workflows, integrations).\n"));
2422
+ const { wantSkills } = await inquirer.default.prompt([{
2423
+ type: "confirm",
2424
+ name: "wantSkills",
2425
+ message: "Install skills from the Skill Hub?",
2426
+ default: false
2427
+ }]);
2428
+ if (!wantSkills) return;
2429
+ try {
2430
+ const { SkillHub } = await Promise.resolve().then(() => require("./hub-Co1SbxLs.js"));
2431
+ const hub = new SkillHub();
2432
+ const FEATURED = [
2433
+ {
2434
+ name: `web-search ${chalk.default.gray("(Google/Bing/DuckDuckGo search)")}`,
2435
+ value: "web-search"
2436
+ },
2437
+ {
2438
+ name: `file-manager ${chalk.default.gray("(read, write, list files)")}`,
2439
+ value: "file-manager"
2440
+ },
2441
+ {
2442
+ name: `code-runner ${chalk.default.gray("(run Python/JS snippets safely)")}`,
2443
+ value: "code-runner"
2444
+ },
2445
+ {
2446
+ name: `github-tools ${chalk.default.gray("(repos, issues, PRs via API)")}`,
2447
+ value: "github-tools"
2448
+ },
2449
+ {
2450
+ name: `calendar-tools ${chalk.default.gray("(Google Calendar read/write)")}`,
2451
+ value: "calendar-tools"
2452
+ },
2453
+ {
2454
+ name: `summarizer ${chalk.default.gray("(summarize URLs, PDFs, text)")}`,
2455
+ value: "summarizer"
2456
+ },
2457
+ {
2458
+ name: `custom ${chalk.default.gray("(enter skill ID manually)")}`,
2459
+ value: "__custom__"
2460
+ }
2461
+ ];
2462
+ const { selectedSkills } = await inquirer.default.prompt([{
2463
+ type: "checkbox",
2464
+ name: "selectedSkills",
2465
+ message: "Select skills to install:",
2466
+ choices: FEATURED
2467
+ }]);
2468
+ for (const skillId of selectedSkills) if (skillId === "__custom__") {
2469
+ const { customId } = await inquirer.default.prompt([{
2470
+ type: "input",
2471
+ name: "customId",
2472
+ message: " Skill ID from ClawHub:",
2473
+ validate: (v) => v.trim().length > 0 || "Required"
2474
+ }]);
2475
+ if (customId.trim()) {
2476
+ const s = (0, ora.default)(`Installing ${customId.trim()}...`).start();
2477
+ try {
2478
+ await hub.install(customId.trim(), false);
2479
+ s.succeed(`Installed: ${customId.trim()}`);
2480
+ } catch (e) {
2481
+ s.fail(e.message);
2482
+ }
2483
+ }
2484
+ } else {
2485
+ const s = (0, ora.default)(`Installing ${skillId}...`).start();
2486
+ try {
2487
+ await hub.install(skillId, false);
2488
+ s.succeed(`Installed: ${skillId}`);
2489
+ } catch (e) {
2490
+ s.warn(`${skillId}: ${e.message} (install later: hyperclaw skill install ${skillId})`);
2491
+ }
2492
+ }
2493
+ if (selectedSkills.length > 0) console.log();
2494
+ } catch {
2495
+ console.log(chalk.default.yellow(` ? Skill Hub unavailable — install later: hyperclaw hub\n`));
2496
+ }
2497
+ }
2498
+ async configureRateLimiting() {
2499
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Rate Limiting\n"));
2500
+ console.log(chalk.default.gray(" Limit how many messages the agent processes per channel per minute/hour.\n"));
2501
+ const { wantRateLimit } = await inquirer.default.prompt([{
2502
+ type: "confirm",
2503
+ name: "wantRateLimit",
2504
+ message: "Configure rate limits?",
2505
+ default: false
2506
+ }]);
2507
+ if (!wantRateLimit) return void 0;
2508
+ const { maxPerMinute, maxPerHour } = await inquirer.default.prompt([{
2509
+ type: "input",
2510
+ name: "maxPerMinute",
2511
+ message: " Max messages per minute per user (0 = unlimited):",
2512
+ default: "0",
2513
+ validate: (v) => !isNaN(Number(v)) || "Enter a number"
2514
+ }, {
2515
+ type: "input",
2516
+ name: "maxPerHour",
2517
+ message: " Max messages per hour per user (0 = unlimited):",
2518
+ default: "0",
2519
+ validate: (v) => !isNaN(Number(v)) || "Enter a number"
2520
+ }]);
2521
+ const mpm = Number(maxPerMinute);
2522
+ const mph = Number(maxPerHour);
2523
+ if (mpm === 0 && mph === 0) return void 0;
2524
+ console.log(chalk.default.green(` ? Rate limit: ${mpm > 0 ? `${mpm}/min` : ""}${mpm > 0 && mph > 0 ? ", " : ""}${mph > 0 ? `${mph}/hr` : ""}\n`));
2525
+ return {
2526
+ ...mpm > 0 ? { maxPerMinute: mpm } : {},
2527
+ ...mph > 0 ? { maxPerHour: mph } : {}
2528
+ };
2529
+ }
2530
+ async configureDeveloperKey() {
2531
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Developer API Key\n"));
2532
+ console.log(chalk.default.gray(" Create a key for embedding HyperClaw in apps or managed hosting.\n"));
2533
+ const { wantDevKey } = await inquirer.default.prompt([{
2534
+ type: "confirm",
2535
+ name: "wantDevKey",
2536
+ message: "Create a developer API key?",
2537
+ default: false
2538
+ }]);
2539
+ if (!wantDevKey) return;
2540
+ try {
2541
+ const developerKeys = await Promise.resolve().then(() => require("./developer-keys-KFGbGuZj.js"));
2542
+ const { name } = await inquirer.default.prompt([{
2543
+ type: "input",
2544
+ name: "name",
2545
+ message: " Key name:",
2546
+ default: "default"
2547
+ }]);
2548
+ const { id, key } = await developerKeys.createDeveloperKey(name.trim() || "default");
2549
+ console.log(chalk.default.green(` ? Developer key created`));
2550
+ console.log(chalk.default.gray(` ID: ${id}`));
2551
+ console.log(chalk.default.yellow(` Key: ${key}`));
2552
+ console.log(chalk.default.gray(` Store securely — shown once. Use: Authorization: Bearer <key>\n`));
2553
+ } catch {
2554
+ console.log(chalk.default.yellow(` ? Could not create key — run: hyperclaw developer-key create\n`));
2555
+ }
2556
+ }
2557
+ async configureVoiceCall() {
2558
+ console.log(chalk.default.hex("#06b6d4")("\n ??? Voice Call\n"));
2559
+ console.log(chalk.default.gray(" Terminal voice call mode — speaks directly to the gateway.\n"));
2560
+ const { wantVoiceCall } = await inquirer.default.prompt([{
2561
+ type: "confirm",
2562
+ name: "wantVoiceCall",
2563
+ message: "Configure voice call settings?",
2564
+ default: false
2565
+ }]);
2566
+ if (!wantVoiceCall) return;
2567
+ const { gatewayUrl } = await inquirer.default.prompt([{
2568
+ type: "input",
2569
+ name: "gatewayUrl",
2570
+ message: " Gateway URL for voice calls:",
2571
+ default: "http://localhost:18789"
2572
+ }]);
2573
+ const cfg = await this.config.load();
2574
+ await this.config.patch({ channelConfigs: {
2575
+ ...cfg.channelConfigs || {},
2576
+ "voice-call": { gatewayUrl: gatewayUrl.trim() }
2577
+ } });
2578
+ console.log(chalk.default.green(` ? Voice call: ${gatewayUrl.trim()}\n`));
2579
+ console.log(chalk.default.gray(` Start: hyperclaw voice-call --gateway-url ${gatewayUrl.trim()}\n`));
2580
+ }
2581
+ async configureCanvas() {
2582
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Canvas (AI-driven UI)\n"));
2583
+ console.log(chalk.default.gray(" Live canvas for displaying AI-generated cards, charts, and components.\n"));
2584
+ const { wantCanvas } = await inquirer.default.prompt([{
2585
+ type: "confirm",
2586
+ name: "wantCanvas",
2587
+ message: "Enable canvas features?",
2588
+ default: false
2589
+ }]);
2590
+ if (!wantCanvas) return;
2591
+ const { canvasMode } = await inquirer.default.prompt([{
2592
+ type: "list",
2593
+ name: "canvasMode",
2594
+ message: " Default canvas mode:",
2595
+ choices: [
2596
+ {
2597
+ name: `Auto ${chalk.default.gray("(show canvas when AI generates structured output)")}`,
2598
+ value: "auto"
2599
+ },
2600
+ {
2601
+ name: `Always ${chalk.default.gray("(always show canvas panel)")}`,
2602
+ value: "always"
2603
+ },
2604
+ {
2605
+ name: `Manual ${chalk.default.gray("(show only via hyperclaw canvas show)")}`,
2606
+ value: "manual"
2607
+ }
2608
+ ],
2609
+ default: "auto"
2610
+ }]);
2611
+ await this.config.patch({ channelConfigs: {
2612
+ ...(await this.config.load()).channelConfigs || {},
2613
+ canvas: { mode: canvasMode }
2614
+ } });
2615
+ console.log(chalk.default.green(` ? Canvas mode: ${canvasMode}\n`));
2616
+ }
2617
+ async configureDeploy() {
2618
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Cloud Deploy\n"));
2619
+ console.log(chalk.default.gray(" Deploy the gateway to a cloud platform (Fly.io or Render).\n"));
2620
+ const { wantDeploy } = await inquirer.default.prompt([{
2621
+ type: "confirm",
2622
+ name: "wantDeploy",
2623
+ message: "Set up cloud deployment?",
2624
+ default: false
2625
+ }]);
2626
+ if (!wantDeploy) return;
2627
+ const { platform } = await inquirer.default.prompt([{
2628
+ type: "list",
2629
+ name: "platform",
2630
+ message: " Platform:",
2631
+ choices: [{
2632
+ name: `Fly.io ${chalk.default.gray("(recommended — fast global edge)")}`,
2633
+ value: "fly"
2634
+ }, {
2635
+ name: `Render ${chalk.default.gray("(free tier available — GitHub integration)")}`,
2636
+ value: "render"
2637
+ }]
2638
+ }]);
2639
+ if (platform === "fly") {
2640
+ console.log(chalk.default.gray("\n Fly.io deployment steps:"));
2641
+ console.log(chalk.default.gray(" 1. Install: curl -L https://fly.io/install.sh | sh"));
2642
+ console.log(chalk.default.gray(" 2. Login: fly auth login"));
2643
+ console.log(chalk.default.gray(" 3. Launch: fly launch"));
2644
+ console.log(chalk.default.gray(" 4. Secrets: fly secrets set ANTHROPIC_API_KEY=... HYPERCLAW_GATEWAY_TOKEN=..."));
2645
+ console.log(chalk.default.gray(" 5. Deploy: fly deploy"));
2646
+ console.log(chalk.default.gray("\n Or: hyperclaw deploy --platform fly\n"));
2647
+ } else {
2648
+ console.log(chalk.default.gray("\n Render deployment steps:"));
2649
+ console.log(chalk.default.gray(" 1. Push to GitHub"));
2650
+ console.log(chalk.default.gray(" 2. Connect at https://render.com > New Web Service > select repo"));
2651
+ console.log(chalk.default.gray(" 3. Set env: ANTHROPIC_API_KEY, HYPERCLAW_GATEWAY_TOKEN"));
2652
+ console.log(chalk.default.gray("\n Or: hyperclaw deploy --platform render\n"));
2653
+ }
2654
+ await this.config.patch({ channelConfigs: {
2655
+ ...(await this.config.load()).channelConfigs || {},
2656
+ deploy: { platform }
2657
+ } });
2658
+ console.log(chalk.default.green(` ? Deploy target saved: ${platform}\n`));
2659
+ }
2660
+ async configureMcpServers() {
2661
+ console.log(chalk.default.hex("#06b6d4")("\n ?? MCP Servers (Model Context Protocol)\n"));
2662
+ console.log(chalk.default.gray(" Register external tool servers the agent can call (filesystem, browser, APIs).\n"));
2663
+ const { wantMcp } = await inquirer.default.prompt([{
2664
+ type: "confirm",
2665
+ name: "wantMcp",
2666
+ message: "Add MCP servers now?",
2667
+ default: false
2668
+ }]);
2669
+ if (!wantMcp) return;
2670
+ const { mcpAdd } = await Promise.resolve().then(() => require("./mcp-B_WJiTZz.js"));
2671
+ let addMore = true;
2672
+ while (addMore) {
2673
+ await mcpAdd();
2674
+ const { more } = await inquirer.default.prompt([{
2675
+ type: "confirm",
2676
+ name: "more",
2677
+ message: " Add another MCP server?",
2678
+ default: false
2679
+ }]);
2680
+ addMore = more;
2681
+ }
2682
+ }
2683
+ async configureWorkspaceTemplate() {
2684
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Workspace Template\n"));
2685
+ console.log(chalk.default.gray(" Initialize workspace files (SOUL.md, USER.md, TOOLS.md, HEARTBEAT.md).\n"));
2686
+ const { wantTemplate } = await inquirer.default.prompt([{
2687
+ type: "confirm",
2688
+ name: "wantTemplate",
2689
+ message: "Initialize workspace template files now?",
2690
+ default: false
2691
+ }]);
2692
+ if (!wantTemplate) return;
2693
+ const { selectedFiles } = await inquirer.default.prompt([{
2694
+ type: "checkbox",
2695
+ name: "selectedFiles",
2696
+ message: "Select template files to create:",
2697
+ choices: [
2698
+ {
2699
+ name: `SOUL.md ${chalk.default.gray("Agent core values, purpose & boundaries")}`,
2700
+ value: "SOUL",
2701
+ checked: true
2702
+ },
2703
+ {
2704
+ name: `USER.md ${chalk.default.gray("User profile, preferences & context")}`,
2705
+ value: "USER",
2706
+ checked: true
2707
+ },
2708
+ {
2709
+ name: `TOOLS.md ${chalk.default.gray("Tool inventory & usage guidelines")}`,
2710
+ value: "TOOLS",
2711
+ checked: false
2712
+ },
2713
+ {
2714
+ name: `HEARTBEAT.md ${chalk.default.gray("Daily status / morning briefing target")}`,
2715
+ value: "HEARTBEAT",
2716
+ checked: false
2717
+ },
2718
+ {
2719
+ name: `AGENTS.md ${chalk.default.gray("Rules & subagent configuration")}`,
2720
+ value: "AGENTS",
2721
+ checked: false
2722
+ }
2723
+ ]
2724
+ }]);
2725
+ if (selectedFiles.length > 0) try {
2726
+ const { initWorkspaceFiles } = await Promise.resolve().then(() => require("./memory-DoQoaHjo.js"));
2727
+ const os$4 = (await import("os")).default;
2728
+ const path$3 = (await import("path")).default;
2729
+ const targetDir = path$3.join(os$4.homedir(), ".hyperclaw");
2730
+ await initWorkspaceFiles({
2731
+ agentName: "Hyper",
2732
+ personality: "helpful and concise",
2733
+ language: "English",
2734
+ userName: "User",
2735
+ rules: []
2736
+ }, targetDir, selectedFiles);
2737
+ console.log(chalk.default.green(` ? Workspace files initialized in ${targetDir}\n`));
2738
+ } catch {
2739
+ console.log(chalk.default.yellow(` ? Could not initialize workspace — run: hyperclaw workspace init\n`));
2740
+ }
2741
+ }
2742
+ async configureCronTasks() {
2743
+ console.log(chalk.default.hex("#06b6d4")("\n ? Scheduled Tasks (Cron)\n"));
2744
+ console.log(chalk.default.gray(" Schedule recurring agent prompts (e.g. daily briefing, weekly report).\n"));
2745
+ const PRESETS = [
2746
+ {
2747
+ name: `Morning briefing ${chalk.default.gray("(Mon-Fri 9am)")}`,
2748
+ schedule: "0 9 * * 1-5",
2749
+ prompt: "Give me a morning briefing: check calendar, news, tasks."
2750
+ },
2751
+ {
2752
+ name: `Daily summary ${chalk.default.gray("(daily 6pm)")}`,
2753
+ schedule: "0 18 * * *",
2754
+ prompt: "Summarize today's activity and pending tasks."
2755
+ },
2756
+ {
2757
+ name: `Weekly report ${chalk.default.gray("(Mon 8am)")}`,
2758
+ schedule: "0 8 * * 1",
2759
+ prompt: "Generate a weekly summary of completed tasks and goals."
2760
+ },
2761
+ {
2762
+ name: `Custom ${chalk.default.gray("(enter manually)")}`,
2763
+ schedule: "__custom__",
2764
+ prompt: ""
2765
+ }
2766
+ ];
2767
+ const { wantCron } = await inquirer.default.prompt([{
2768
+ type: "confirm",
2769
+ name: "wantCron",
2770
+ message: "Add scheduled tasks?",
2771
+ default: false
2772
+ }]);
2773
+ if (!wantCron) return;
2774
+ const { selectedPresets } = await inquirer.default.prompt([{
2775
+ type: "checkbox",
2776
+ name: "selectedPresets",
2777
+ message: "Select tasks to schedule:",
2778
+ choices: PRESETS.map((p) => ({
2779
+ name: p.name,
2780
+ value: p.schedule
2781
+ }))
2782
+ }]);
2783
+ const tasksToAdd = [];
2784
+ for (const sch of selectedPresets) if (sch === "__custom__") {
2785
+ const r = await inquirer.default.prompt([
2786
+ {
2787
+ type: "input",
2788
+ name: "schedule",
2789
+ message: " Cron schedule (e.g. \"0 9 * * 1-5\"):",
2790
+ validate: (v) => v.trim().length > 0 || "Required"
2791
+ },
2792
+ {
2793
+ type: "input",
2794
+ name: "prompt",
2795
+ message: " Agent prompt:",
2796
+ validate: (v) => v.trim().length > 0 || "Required"
2797
+ },
2798
+ {
2799
+ type: "input",
2800
+ name: "name",
2801
+ message: " Task name:",
2802
+ default: "Custom task"
2803
+ }
2804
+ ]);
2805
+ tasksToAdd.push({
2806
+ schedule: r.schedule.trim(),
2807
+ prompt: r.prompt.trim(),
2808
+ name: r.name.trim()
2809
+ });
2810
+ } else {
2811
+ const preset = PRESETS.find((p) => p.schedule === sch);
2812
+ tasksToAdd.push({
2813
+ schedule: preset.schedule,
2814
+ prompt: preset.prompt,
2815
+ name: preset.name.replace(/\s+\(.*\)/, "").trim()
2816
+ });
2817
+ }
2818
+ if (tasksToAdd.length > 0) try {
2819
+ const { loadCronTasks, addCronTask, saveCronTasks } = await Promise.resolve().then(() => require("./cron-tasks-DuNdK89e.js"));
2820
+ await loadCronTasks();
2821
+ for (const t of tasksToAdd) addCronTask(t.schedule, t.prompt, t.name);
2822
+ await saveCronTasks();
2823
+ console.log(chalk.default.green(` ? ${tasksToAdd.length} task(s) scheduled\n`));
2824
+ } catch {
2825
+ console.log(chalk.default.yellow(` ? Could not save tasks — run: hyperclaw cron add\n`));
2826
+ }
2827
+ }
2828
+ async configureAutoReply() {
2829
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Auto-reply Rules\n"));
2830
+ console.log(chalk.default.gray(" Automatic responses before the AI model is invoked.\n"));
2831
+ const { wantAutoReply } = await inquirer.default.prompt([{
2832
+ type: "confirm",
2833
+ name: "wantAutoReply",
2834
+ message: "Set up auto-reply rules?",
2835
+ default: false
2836
+ }]);
2837
+ if (!wantAutoReply) return;
2838
+ const PRESETS = [
2839
+ {
2840
+ name: `Away message ${chalk.default.gray("(reply to every message when offline)")}`,
2841
+ value: "away"
2842
+ },
2843
+ {
2844
+ name: `Keyword reply ${chalk.default.gray("(reply to specific keyword)")}`,
2845
+ value: "keyword"
2846
+ },
2847
+ {
2848
+ name: `Ignore channel ${chalk.default.gray("(silently ignore a channel)")}`,
2849
+ value: "ignore"
2850
+ }
2851
+ ];
2852
+ const { ruleType } = await inquirer.default.prompt([{
2853
+ type: "list",
2854
+ name: "ruleType",
2855
+ message: "Rule type:",
2856
+ choices: PRESETS
2857
+ }]);
2858
+ try {
2859
+ const { AutoReplyEngine } = await Promise.resolve().then(() => require("./rules-D3GcY_lt.js"));
2860
+ const engine = new AutoReplyEngine();
2861
+ await engine.load();
2862
+ const BASE = {
2863
+ enabled: true,
2864
+ priority: 10,
2865
+ stopOnMatch: true,
2866
+ conditionLogic: "OR"
2867
+ };
2868
+ if (ruleType === "away") {
2869
+ const { reply } = await inquirer.default.prompt([{
2870
+ type: "input",
2871
+ name: "reply",
2872
+ message: " Away message text:",
2873
+ default: "I'm currently unavailable. I'll get back to you soon.",
2874
+ validate: (v) => v.trim().length > 0 || "Required"
2875
+ }]);
2876
+ await engine.add({
2877
+ ...BASE,
2878
+ name: "Away message",
2879
+ conditions: [{ type: "always" }],
2880
+ action: {
2881
+ type: "reply",
2882
+ reply: reply.trim()
2883
+ }
2884
+ });
2885
+ } else if (ruleType === "keyword") {
2886
+ const r = await inquirer.default.prompt([{
2887
+ type: "input",
2888
+ name: "keyword",
2889
+ message: " Trigger keyword:",
2890
+ validate: (v) => v.trim().length > 0 || "Required"
2891
+ }, {
2892
+ type: "input",
2893
+ name: "reply",
2894
+ message: " Reply text:",
2895
+ validate: (v) => v.trim().length > 0 || "Required"
2896
+ }]);
2897
+ await engine.add({
2898
+ ...BASE,
2899
+ name: `Keyword: ${r.keyword}`,
2900
+ conditions: [{
2901
+ type: "contains",
2902
+ value: r.keyword.trim()
2903
+ }],
2904
+ action: {
2905
+ type: "reply",
2906
+ reply: r.reply.trim()
2907
+ }
2908
+ });
2909
+ } else if (ruleType === "ignore") {
2910
+ const { channelId } = await inquirer.default.prompt([{
2911
+ type: "input",
2912
+ name: "channelId",
2913
+ message: " Channel ID to ignore:",
2914
+ validate: (v) => v.trim().length > 0 || "Required"
2915
+ }]);
2916
+ await engine.add({
2917
+ ...BASE,
2918
+ name: `Ignore channel: ${channelId}`,
2919
+ conditions: [{
2920
+ type: "channel",
2921
+ value: channelId.trim()
2922
+ }],
2923
+ action: { type: "ignore" }
2924
+ });
2925
+ }
2926
+ console.log(chalk.default.green(` ? Auto-reply rule added\n`));
2927
+ } catch {
2928
+ console.log(chalk.default.yellow(` ? Could not save rule — run: hyperclaw auto-reply list\n`));
2929
+ }
2930
+ }
2931
+ async configureWebhooks() {
2932
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Inbound Webhooks\n"));
2933
+ console.log(chalk.default.gray(" Register POST endpoints that trigger the agent (GitHub, Stripe, Linear, etc).\n"));
2934
+ const { wantWebhook } = await inquirer.default.prompt([{
2935
+ type: "confirm",
2936
+ name: "wantWebhook",
2937
+ message: "Register inbound webhook endpoints?",
2938
+ default: false
2939
+ }]);
2940
+ if (!wantWebhook) return;
2941
+ try {
2942
+ const { WebhookManager } = await Promise.resolve().then(() => require("./manager-CBe3W3eG.js"));
2943
+ const manager = new WebhookManager();
2944
+ await manager.load();
2945
+ let addMore = true;
2946
+ while (addMore) {
2947
+ const r = await inquirer.default.prompt([
2948
+ {
2949
+ type: "input",
2950
+ name: "name",
2951
+ message: " Webhook name (e.g. GitHub push):",
2952
+ validate: (v) => v.trim().length > 0 || "Required"
2953
+ },
2954
+ {
2955
+ type: "list",
2956
+ name: "format",
2957
+ message: " Payload format:",
2958
+ choices: [
2959
+ {
2960
+ name: "GitHub",
2961
+ value: "github"
2962
+ },
2963
+ {
2964
+ name: "Stripe",
2965
+ value: "stripe"
2966
+ },
2967
+ {
2968
+ name: "Linear",
2969
+ value: "linear"
2970
+ },
2971
+ {
2972
+ name: "Notion",
2973
+ value: "notion"
2974
+ },
2975
+ {
2976
+ name: "JSON (generic)",
2977
+ value: "json"
2978
+ },
2979
+ {
2980
+ name: "Raw",
2981
+ value: "raw"
2982
+ }
2983
+ ]
2984
+ },
2985
+ {
2986
+ type: "input",
2987
+ name: "template",
2988
+ message: " Message template (use {{body.field}}):",
2989
+ default: "Webhook received: {{body}}"
2990
+ }
2991
+ ]);
2992
+ await manager.add({
2993
+ name: r.name.trim(),
2994
+ format: r.format,
2995
+ template: r.template.trim(),
2996
+ routeTo: {
2997
+ type: "channel",
2998
+ target: "default"
2999
+ }
3000
+ });
3001
+ const { more } = await inquirer.default.prompt([{
3002
+ type: "confirm",
3003
+ name: "more",
3004
+ message: " Add another webhook?",
3005
+ default: false
3006
+ }]);
3007
+ addMore = more;
3008
+ }
3009
+ console.log(chalk.default.green(` ? Webhook(s) registered — route: POST /webhook/<id>\n`));
3010
+ } catch {
3011
+ console.log(chalk.default.yellow(` ? Could not save webhooks — run: hyperclaw webhooks list\n`));
3012
+ }
3013
+ }
3014
+ async configureNodes() {
3015
+ console.log(chalk.default.hex("#06b6d4")("\n ??? Nodes (Remote Compute / Mobile)\n"));
3016
+ console.log(chalk.default.gray(" Add VPS, Raspberry Pi, Android, or VM nodes for distributed inference.\n"));
3017
+ const { wantNode } = await inquirer.default.prompt([{
3018
+ type: "confirm",
3019
+ name: "wantNode",
3020
+ message: "Add compute nodes?",
3021
+ default: false
3022
+ }]);
3023
+ if (!wantNode) return;
3024
+ const { nodeAdd } = await Promise.resolve().then(() => require("./node-CSOPY84m.js"));
3025
+ let addMore = true;
3026
+ while (addMore) {
3027
+ await nodeAdd();
3028
+ const { more } = await inquirer.default.prompt([{
3029
+ type: "confirm",
3030
+ name: "more",
3031
+ message: " Add another node?",
3032
+ default: false
3033
+ }]);
3034
+ addMore = more;
3035
+ }
3036
+ }
3037
+ async configureOAuth() {
3038
+ console.log(chalk.default.hex("#06b6d4")("\n ?? OAuth / External Auth\n"));
3039
+ console.log(chalk.default.gray(" Connect Google, GitHub or other accounts for the agent to act on your behalf.\n"));
3040
+ const { wantOAuth } = await inquirer.default.prompt([{
3041
+ type: "confirm",
3042
+ name: "wantOAuth",
3043
+ message: "Set up OAuth / external auth now?",
3044
+ default: false
3045
+ }]);
3046
+ if (!wantOAuth) return;
3047
+ const { selectedProviders } = await inquirer.default.prompt([{
3048
+ type: "checkbox",
3049
+ name: "selectedProviders",
3050
+ message: "Select providers to connect:",
3051
+ choices: [
3052
+ {
3053
+ name: `Google Calendar ${chalk.default.gray("(read/create events)")}`,
3054
+ value: "google-calendar"
3055
+ },
3056
+ {
3057
+ name: `Google Drive ${chalk.default.gray("(read/write files)")}`,
3058
+ value: "google-drive"
3059
+ },
3060
+ {
3061
+ name: `GitHub ${chalk.default.gray("(repos, issues, PRs)")}`,
3062
+ value: "github"
3063
+ },
3064
+ {
3065
+ name: `Notion ${chalk.default.gray("(pages & databases)")}`,
3066
+ value: "notion"
3067
+ },
3068
+ {
3069
+ name: `Linear ${chalk.default.gray("(issues & projects)")}`,
3070
+ value: "linear"
3071
+ }
3072
+ ]
3073
+ }]);
3074
+ for (const provider of selectedProviders) {
3075
+ console.log(chalk.default.gray(`\n Starting OAuth flow for ${provider}...`));
3076
+ try {
3077
+ const { runOAuthFlow } = await Promise.resolve().then(() => require("./oauth-flow-Du2N6B2V.js"));
3078
+ const { writeOAuthToken } = await Promise.resolve().then(() => require("./oauth-provider-B2RBpiXg.js"));
3079
+ const tokens = await runOAuthFlow(provider, {});
3080
+ const now = Math.floor(Date.now() / 1e3);
3081
+ const TOKEN_URLS = {
3082
+ "google-calendar": "https://oauth2.googleapis.com/token",
3083
+ "google-drive": "https://oauth2.googleapis.com/token",
3084
+ "github": "https://github.com/login/oauth/access_token",
3085
+ "notion": "https://api.notion.com/v1/oauth/token",
3086
+ "linear": "https://api.linear.app/oauth/token"
3087
+ };
3088
+ await writeOAuthToken(provider, {
3089
+ access_token: tokens.access_token,
3090
+ refresh_token: tokens.refresh_token,
3091
+ expires_at: tokens.expires_in ? now + tokens.expires_in : void 0,
3092
+ token_url: TOKEN_URLS[provider] ?? "https://oauth2.googleapis.com/token"
3093
+ });
3094
+ console.log(chalk.default.green(` ? ${provider} connected\n`));
3095
+ } catch {
3096
+ console.log(chalk.default.yellow(` ? ${provider} OAuth failed — run later: hyperclaw auth oauth ${provider}\n`));
3097
+ }
3098
+ }
3099
+ }
3100
+ async configureAgentBindings() {
3101
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Multi-agent Bindings\n"));
3102
+ console.log(chalk.default.gray(" Route specific channels to different agent personas or models.\n"));
3103
+ const { wantBindings } = await inquirer.default.prompt([{
3104
+ type: "confirm",
3105
+ name: "wantBindings",
3106
+ message: "Configure channel > agent bindings?",
3107
+ default: false
3108
+ }]);
3109
+ if (!wantBindings) return;
3110
+ try {
3111
+ const { AgentRouter } = await Promise.resolve().then(() => require("./agents-routing-DHDK2axt.js"));
3112
+ await new AgentRouter().bind();
3113
+ return;
3114
+ } catch {
3115
+ const r = await inquirer.default.prompt([
3116
+ {
3117
+ type: "input",
3118
+ name: "channel",
3119
+ message: " Channel ID (e.g. telegram):",
3120
+ validate: (v) => v.trim().length > 0 || "Required"
3121
+ },
3122
+ {
3123
+ type: "input",
3124
+ name: "agentName",
3125
+ message: " Agent name / persona for this channel:",
3126
+ default: "Hyper"
3127
+ },
3128
+ {
3129
+ type: "input",
3130
+ name: "modelId",
3131
+ message: " Override model ID (leave blank = use primary):",
3132
+ default: ""
3133
+ }
3134
+ ]);
3135
+ if (r.channel) {
3136
+ const cfg = await this.config.load();
3137
+ const bindings = Array.isArray(cfg?.bindings) ? [...cfg.bindings] : [];
3138
+ bindings.push({
3139
+ match: { channel: r.channel.trim() },
3140
+ agentId: r.agentName.trim()
3141
+ });
3142
+ await this.config.patch({ bindings });
3143
+ console.log(chalk.default.green(` Binding: ${r.channel} > ${r.agentName}\n`));
3144
+ }
3145
+ }
3146
+ }
3147
+ async configureGroupSandbox() {
3148
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Group Sandbox (Docker)\n"));
3149
+ console.log(chalk.default.gray(" Isolates group chat sessions in Docker containers for security.\n"));
3150
+ const { wantSandbox } = await inquirer.default.prompt([{
3151
+ type: "confirm",
3152
+ name: "wantSandbox",
3153
+ message: "Enable Docker sandboxing for group chat sessions?",
3154
+ default: false
3155
+ }]);
3156
+ if (!wantSandbox) return void 0;
3157
+ const { image, memoryLimit } = await inquirer.default.prompt([{
3158
+ type: "input",
3159
+ name: "image",
3160
+ message: " Docker image:",
3161
+ default: "node:22-alpine"
3162
+ }, {
3163
+ type: "input",
3164
+ name: "memoryLimit",
3165
+ message: " Memory limit per container:",
3166
+ default: "256m"
3167
+ }]);
3168
+ console.log(chalk.default.green(` ? Group sandbox: ${image} (${memoryLimit})\n`));
3169
+ return {
3170
+ enabled: true,
3171
+ image: image.trim(),
3172
+ memoryLimit: memoryLimit.trim()
3173
+ };
3174
+ }
3175
+ async configureUpdateChannel() {
3176
+ console.log(chalk.default.hex("#06b6d4")("\n ?? Update Channel\n"));
3177
+ const { channel } = await inquirer.default.prompt([{
3178
+ type: "list",
3179
+ name: "channel",
3180
+ message: "Update channel:",
3181
+ choices: [
3182
+ {
3183
+ name: `Stable ${chalk.default.gray("(recommended — tested releases)")}`,
3184
+ value: "stable"
3185
+ },
3186
+ {
3187
+ name: `Beta ${chalk.default.gray("(early access — new features, may have bugs)")}`,
3188
+ value: "beta"
3189
+ },
3190
+ {
3191
+ name: `Dev ${chalk.default.gray("(bleeding edge — for contributors)")}`,
3192
+ value: "dev"
3193
+ }
3194
+ ],
3195
+ default: "stable"
3196
+ }]);
3197
+ console.log(chalk.default.green(` ? Update channel: ${channel}\n`));
3198
+ return channel;
3199
+ }
3200
+ async saveAll(data, options) {
3201
+ console.log();
3202
+ const spinner = (0, ora.default)("Saving configuration...").start();
3203
+ const current = await this.config.load();
3204
+ const skillsPatch = { installed: current?.skills?.installed || [] };
3205
+ if (data.serviceApiKeys && Object.keys(data.serviceApiKeys).length > 0) skillsPatch.apiKeys = {
3206
+ ...current?.skills?.apiKeys || {},
3207
+ ...data.serviceApiKeys
3208
+ };
3209
+ if (current?.skills?.vtApiKey) skillsPatch.vtApiKey = current.skills.vtApiKey;
3210
+ const finalSkills = skillsPatch.apiKeys || skillsPatch.vtApiKey ? skillsPatch : current?.skills || { installed: [] };
3211
+ const pkgVersion = await fs_extra.default.readJson(path.default.join(__dirname, "../package.json")).then((p) => p.version).catch(() => "5.2.0");
3212
+ const channelIds = Object.keys(data.channelConfigs || {});
3213
+ let gatewayToSave = data.gatewayConfig ? {
3214
+ ...data.gatewayConfig,
3215
+ enabledChannels: channelIds
3216
+ } : current?.gateway ? { ...current.gateway } : void 0;
3217
+ if (gatewayToSave && channelIds.length > 0) gatewayToSave.enabledChannels = channelIds;
3218
+ await this.config.save({
3219
+ ...current,
3220
+ version: pkgVersion,
3221
+ workspaceName: data.workspaceName,
3222
+ provider: data.providerConfig,
3223
+ providers: data.providers || (data.providerConfig ? [data.providerConfig] : []),
3224
+ gateway: gatewayToSave,
3225
+ channels: channelIds,
3226
+ channelConfigs: data.channelConfigs,
3227
+ skills: finalSkills,
3228
+ enabledHooks: data.hooks || [],
3229
+ identity: {
3230
+ agentName: data.identity?.agentName,
3231
+ userName: data.identity?.userName,
3232
+ language: data.identity?.language,
3233
+ wakeWord: data.identity?.wakeWord || `Hey ${data.identity?.agentName || "Hyper"}`,
3234
+ wakeUpMessage: data.identity?.wakeUpMessage,
3235
+ systemPrompt: data.identity?.systemPrompt,
3236
+ personality: data.identity?.personality,
3237
+ rules: data.identity?.rules
3238
+ },
3239
+ memoryIntegration: data.memoryIntegration,
3240
+ talkMode: data.talkModeConfig,
3241
+ pcAccess: {
3242
+ enabled: true,
3243
+ level: data.pcAccess?.level || "full",
3244
+ allowedPaths: [],
3245
+ allowedCommands: [],
3246
+ confirmDestructive: data.pcAccess?.confirmDestructive ?? false,
3247
+ maxOutputBytes: 5e4
3248
+ },
3249
+ updateChannel: data.updateChannel || "stable",
3250
+ groupSandbox: data.groupSandbox,
3251
+ ...data.webSearch ? { webSearch: data.webSearch } : {},
3252
+ ...data.rateLimit ? { rateLimit: data.rateLimit } : {},
3253
+ hatchMode: data.hatchMode || "tui",
3254
+ installedAt: (/* @__PURE__ */ new Date()).toISOString()
3255
+ });
3256
+ spinner.succeed("Configuration saved");
3257
+ const memory = new MemoryManager();
3258
+ await memory.init(data.identity);
3259
+ if (data.heartbeatEnabled) try {
3260
+ const { HookLoader } = await Promise.resolve().then(() => require("./loader-CbS0tIrR.js"));
3261
+ const loader = new HookLoader();
3262
+ loader.enable("morning-briefing");
3263
+ console.log(chalk.default.gray(" ? Morning Briefing hook enabled"));
3264
+ } catch {}
3265
+ await this.testConnections(data.channelConfigs || {});
3266
+ await this.setupIntegrations();
3267
+ const isRemoteMode = data.gatewayConfig?.mode === "remote";
3268
+ if (!isRemoteMode && (data.installDaemon || options.daemon || options.installDaemon)) {
3269
+ const runtime = options.daemonRuntime ?? data.daemonRuntime ?? "node";
3270
+ const s = (0, ora.default)(`Installing system daemon (runtime: ${runtime})...`).start();
3271
+ await this.daemon.install();
3272
+ s.succeed(chalk.default.red(`System daemon installed (runtime: ${runtime}, starts on boot)`));
3273
+ }
3274
+ if (!isRemoteMode && data.gatewayConfig?.tailscaleExposure && data.gatewayConfig.tailscaleExposure !== "off") await this.gateway.applyTailscaleExposure(data.gatewayConfig.tailscaleExposure, data.gatewayConfig.port);
3275
+ if (data.gatewayConfig && !isRemoteMode && (options.startNow || data.startNow || data.installDaemon)) {
3276
+ const s = (0, ora.default)("Starting gateway...").start();
3277
+ await this.daemon.start();
3278
+ s.succeed(`Gateway running at ws://localhost:${data.gatewayConfig.port}`);
3279
+ } else if (isRemoteMode) {
3280
+ const remoteUrl = data.gatewayConfig?.remote?.url;
3281
+ console.log(chalk.default.green(` Remote mode: connect to ${remoteUrl || "(configured URL)"}\n`));
3282
+ }
3283
+ console.log(chalk.default.gray("\n Running health check...\n"));
3284
+ const healthResults = {};
3285
+ try {
3286
+ const { runDoctor } = await Promise.resolve().then(() => require("./doctor-CmJh0JLr.js"));
3287
+ await runDoctor(true);
3288
+ healthResults.doctor = "ok";
3289
+ } catch {
3290
+ healthResults.doctor = "failed";
3291
+ }
3292
+ if (data.gatewayConfig) try {
3293
+ const { resolveGatewayUrl } = await Promise.resolve().then(() => require("./health-Cq_yE5Ln.js"));
3294
+ const { gatewayUrl } = resolveGatewayUrl({ gateway: data.gatewayConfig });
3295
+ const reachable = await new Promise((resolve) => {
3296
+ const u = new URL(gatewayUrl);
3297
+ const mod = u.protocol === "https:" ? require("https") : require("http");
3298
+ const req = mod.get(`${gatewayUrl}/api/status`, () => resolve(true));
3299
+ req.on("error", () => resolve(false));
3300
+ req.setTimeout(5e3, () => {
3301
+ req.destroy();
3302
+ resolve(false);
3303
+ });
3304
+ });
3305
+ healthResults.gateway = reachable ? "reachable" : "unreachable";
3306
+ if (reachable) console.log(chalk.default.green(` Gateway reachable at ${gatewayUrl}`));
3307
+ else console.log(chalk.default.yellow(` Gateway not reachable at ${gatewayUrl}`));
3308
+ } catch {
3309
+ healthResults.gateway = "error";
3310
+ }
3311
+ if (options.jsonOutput) {
3312
+ const result = {
3313
+ ok: true,
3314
+ version: pkgVersion,
3315
+ provider: data.providerConfig?.providerId,
3316
+ model: data.providerConfig?.modelId,
3317
+ gateway: data.gatewayConfig ? {
3318
+ port: data.gatewayConfig.port,
3319
+ bind: data.gatewayConfig.bind
3320
+ } : null,
3321
+ channels: Object.keys(data.channelConfigs || {}),
3322
+ hooks: data.hooks || [],
3323
+ daemonInstalled: !!(data.installDaemon || options.installDaemon),
3324
+ health: healthResults
3325
+ };
3326
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
3327
+ return;
3328
+ }
3329
+ this.showSuccessScreen(data, healthResults.gateway === "reachable");
3330
+ const { launchChat } = await inquirer.default.prompt([{
3331
+ type: "confirm",
3332
+ name: "launchChat",
3333
+ message: chalk.default.cyan("Launch HyperClaw Chat now?"),
3334
+ default: true
3335
+ }]);
3336
+ if (launchChat) {
3337
+ console.log(chalk.default.gray("\n Starting chat...\n"));
3338
+ const { runChat } = await Promise.resolve().then(() => require("./chat-C0W8lwhh.js"));
3339
+ await runChat({});
3340
+ }
3341
+ }
3342
+ async setupIntegrations() {
3343
+ console.log();
3344
+ const { configure } = await inquirer.default.prompt([{
3345
+ type: "confirm",
3346
+ name: "configure",
3347
+ message: chalk.default.cyan("Configure integrations now?") + chalk.default.gray(" (Spotify, Home Assistant, GitHub, Trello, etc.)"),
3348
+ default: false
3349
+ }]);
3350
+ if (!configure) {
3351
+ console.log(chalk.default.gray(" Skipped — configure later by telling the agent or running: hyperclaw config set-key KEY value\n"));
3352
+ return;
3353
+ }
3354
+ const INTEGRATIONS = [
3355
+ {
3356
+ name: "Spotify",
3357
+ value: "spotify",
3358
+ instructions: [
3359
+ "1. Go to → https://developer.spotify.com/dashboard",
3360
+ "2. Log in and click \"Create App\"",
3361
+ "3. Fill in name/description, set Redirect URI to http://localhost:8888/callback",
3362
+ "4. Click \"Settings\" → copy your Client ID and Client Secret",
3363
+ "5. To get a Refresh Token, run this after saving Client ID/Secret:",
3364
+ " npx spotify-token (or use the Spotify OAuth Playground)"
3365
+ ],
3366
+ keys: [
3367
+ {
3368
+ env: "SPOTIFY_CLIENT_ID",
3369
+ label: "Client ID"
3370
+ },
3371
+ {
3372
+ env: "SPOTIFY_CLIENT_SECRET",
3373
+ label: "Client Secret",
3374
+ secret: true
3375
+ },
3376
+ {
3377
+ env: "SPOTIFY_REFRESH_TOKEN",
3378
+ label: "Refresh Token",
3379
+ secret: true
3380
+ }
3381
+ ]
3382
+ },
3383
+ {
3384
+ name: "Home Assistant",
3385
+ value: "ha",
3386
+ instructions: [
3387
+ "1. Open Home Assistant in your browser",
3388
+ "2. Go to → Profile (bottom left) → Long-lived access tokens",
3389
+ "3. Click \"Create Token\", give it a name (e.g. HyperClaw)",
3390
+ "4. Copy the token immediately — it won't be shown again",
3391
+ "5. Your URL is usually http://homeassistant.local:8123 or your local IP"
3392
+ ],
3393
+ keys: [{
3394
+ env: "HA_URL",
3395
+ label: "URL (e.g. http://homeassistant.local:8123)"
3396
+ }, {
3397
+ env: "HA_TOKEN",
3398
+ label: "Long-lived Access Token",
3399
+ secret: true
3400
+ }]
3401
+ },
3402
+ {
3403
+ name: "GitHub",
3404
+ value: "github",
3405
+ instructions: [
3406
+ "1. Go to → https://github.com/settings/tokens",
3407
+ "2. Click \"Generate new token (classic)\"",
3408
+ "3. Give it a name (e.g. HyperClaw)",
3409
+ "4. Select scopes: repo, read:user, read:org (or as needed)",
3410
+ "5. Click \"Generate token\" and copy it — shown only once"
3411
+ ],
3412
+ keys: [{
3413
+ env: "GITHUB_TOKEN",
3414
+ label: "Personal Access Token",
3415
+ secret: true
3416
+ }]
3417
+ },
3418
+ {
3419
+ name: "Trello",
3420
+ value: "trello",
3421
+ instructions: [
3422
+ "1. Go to → https://trello.com/app-key",
3423
+ "2. Copy your API Key from the top of the page",
3424
+ "3. On the same page, click \"Token\" link to generate a Token",
3425
+ "4. Authorize the app and copy the token"
3426
+ ],
3427
+ keys: [{
3428
+ env: "TRELLO_API_KEY",
3429
+ label: "API Key"
3430
+ }, {
3431
+ env: "TRELLO_TOKEN",
3432
+ label: "Token",
3433
+ secret: true
3434
+ }]
3435
+ },
3436
+ {
3437
+ name: "Obsidian",
3438
+ value: "obsidian",
3439
+ instructions: [
3440
+ "1. Open Obsidian → Settings → Community Plugins",
3441
+ "2. Search for \"Local REST API\" and install it",
3442
+ "3. Enable the plugin and go to its settings",
3443
+ "4. Copy the API Key shown in the plugin settings",
3444
+ "5. The default port is 27123 (leave blank to use default)"
3445
+ ],
3446
+ keys: [{
3447
+ env: "OBSIDIAN_API_KEY",
3448
+ label: "Local REST API Key",
3449
+ secret: true
3450
+ }, {
3451
+ env: "OBSIDIAN_PORT",
3452
+ label: "Port (press Enter for default 27123)"
3453
+ }]
3454
+ },
3455
+ {
3456
+ name: "Philips Hue",
3457
+ value: "hue",
3458
+ instructions: [
3459
+ "1. Find your Hue Bridge IP: open the Hue app → Settings → My Hue System → Bridge",
3460
+ " OR check your router's device list for \"Philips-hue\"",
3461
+ "2. Go to → http://<BRIDGE_IP>/debug/clip.html",
3462
+ "3. In the URL field type: /api",
3463
+ " Body: {\"devicetype\":\"hyperclaw#mydevice\"}",
3464
+ "4. Press the physical button on the bridge, then click POST",
3465
+ "5. Copy the \"username\" value from the response — that's your HUE_USERNAME"
3466
+ ],
3467
+ keys: [{
3468
+ env: "HUE_BRIDGE_IP",
3469
+ label: "Bridge IP (e.g. 192.168.1.100)"
3470
+ }, {
3471
+ env: "HUE_USERNAME",
3472
+ label: "Username (from bridge pairing)"
3473
+ }]
3474
+ },
3475
+ {
3476
+ name: "8Sleep",
3477
+ value: "eightsleep",
3478
+ instructions: [
3479
+ "1. Use your Eight Sleep account email and password",
3480
+ "2. These are the same credentials you use in the Eight Sleep app",
3481
+ " Note: 8Sleep has rate limits — don't query too frequently"
3482
+ ],
3483
+ keys: [{
3484
+ env: "EIGHTSLEEP_EMAIL",
3485
+ label: "Email"
3486
+ }, {
3487
+ env: "EIGHTSLEEP_PASSWORD",
3488
+ label: "Password",
3489
+ secret: true
3490
+ }]
3491
+ },
3492
+ {
3493
+ name: "Sonos",
3494
+ value: "sonos",
3495
+ instructions: [
3496
+ "1. Find your Sonos speaker's local IP address",
3497
+ "2. Open the Sonos app → System → (your room) → About My System",
3498
+ " OR check your router's device list for your Sonos device",
3499
+ "3. The IP looks like: 192.168.1.x"
3500
+ ],
3501
+ keys: [{
3502
+ env: "SONOS_IP",
3503
+ label: "Speaker IP (e.g. 192.168.1.50)"
3504
+ }]
3505
+ },
3506
+ {
3507
+ name: "Giphy / GIF search",
3508
+ value: "giphy",
3509
+ instructions: [
3510
+ "Option A — Giphy:",
3511
+ "1. Go to → https://developers.giphy.com",
3512
+ "2. Log in or sign up → Dashboard → Create an App → API",
3513
+ "3. Copy your API Key",
3514
+ "",
3515
+ "Option B — Tenor (Google):",
3516
+ "1. Go to → https://console.cloud.google.com",
3517
+ "2. Enable the \"Tenor API\" → Create credentials → API Key",
3518
+ " (You can leave one blank and only fill the other)"
3519
+ ],
3520
+ keys: [{
3521
+ env: "GIPHY_API_KEY",
3522
+ label: "Giphy API Key (leave blank to skip)"
3523
+ }, {
3524
+ env: "TENOR_API_KEY",
3525
+ label: "Tenor API Key (leave blank to skip)"
3526
+ }]
3527
+ },
3528
+ {
3529
+ name: "1Password",
3530
+ value: "1password",
3531
+ instructions: [
3532
+ "1. Install the 1Password CLI: https://developer.1password.com/docs/cli/get-started/",
3533
+ "2. Go to → https://my.1password.com → Integrations → Service Accounts",
3534
+ "3. Create a new Service Account, give it read access to the vaults you need",
3535
+ "4. Copy the Service Account Token — shown only once",
3536
+ "5. Verify the CLI works: op account list"
3537
+ ],
3538
+ keys: [{
3539
+ env: "OP_SERVICE_ACCOUNT_TOKEN",
3540
+ label: "Service Account Token",
3541
+ secret: true
3542
+ }]
3543
+ },
3544
+ {
3545
+ name: "Image Generation (DALL-E / Stability AI)",
3546
+ value: "image_gen",
3547
+ instructions: [
3548
+ "Option A — OpenAI DALL-E 3 (recommended):",
3549
+ "1. Go to → https://platform.openai.com/api-keys",
3550
+ "2. Click \"Create new secret key\", give it a name",
3551
+ "3. Copy the key — shown only once (starts with sk-...)",
3552
+ " Note: DALL-E 3 requires a paid OpenAI plan",
3553
+ "",
3554
+ "Option B — Stability AI (Stable Diffusion):",
3555
+ "1. Go to → https://platform.stability.ai/account/keys",
3556
+ "2. Create an account and click \"Create API Key\"",
3557
+ "3. Copy the key",
3558
+ " (You can set both — the agent will prefer DALL-E if both are present)"
3559
+ ],
3560
+ keys: [{
3561
+ env: "OPENAI_API_KEY",
3562
+ label: "OpenAI API Key (for DALL-E 3, leave blank to skip)",
3563
+ secret: true
3564
+ }, {
3565
+ env: "STABILITY_API_KEY",
3566
+ label: "Stability AI Key (for Stable Diffusion, leave blank to skip)",
3567
+ secret: true
3568
+ }]
3569
+ },
3570
+ {
3571
+ name: "Gmail",
3572
+ value: "gmail",
3573
+ instructions: [
3574
+ "1. Go to → https://console.cloud.google.com",
3575
+ "2. Create a project (or select an existing one)",
3576
+ "3. Enable APIs: \"Gmail API\" and \"Cloud Pub/Sub API\"",
3577
+ "4. Go to → APIs & Services → Credentials → Create OAuth 2.0 Client ID",
3578
+ " Application type: Desktop App",
3579
+ "5. Download the JSON credentials file",
3580
+ "6. Set GOOGLE_CREDENTIALS_PATH to the path of that file",
3581
+ "7. For Pub/Sub (push notifications), create a topic and subscription:",
3582
+ " gcloud pubsub topics create hyperclaw-gmail",
3583
+ " gcloud pubsub subscriptions create hyperclaw-sub --topic=hyperclaw-gmail",
3584
+ " Then set GMAIL_PUBSUB_TOPIC to projects/<project-id>/topics/hyperclaw-gmail"
3585
+ ],
3586
+ keys: [{
3587
+ env: "GOOGLE_CREDENTIALS_PATH",
3588
+ label: "Path to credentials JSON file (e.g. ~/Downloads/credentials.json)"
3589
+ }, {
3590
+ env: "GMAIL_PUBSUB_TOPIC",
3591
+ label: "Pub/Sub topic (leave blank to skip push notifications)"
3592
+ }]
3593
+ }
3594
+ ];
3595
+ console.log(chalk.default.gray("\n Free / built-in (no key needed):"));
3596
+ console.log(chalk.default.gray(" • Weather (Open-Meteo) • Music search (iTunes) • Canvas • Browser"));
3597
+ console.log(chalk.default.gray(" • Apple Notes / Reminders / Things 3 / Bear (macOS) • iMessage (macOS)\n"));
3598
+ const { chosen } = await inquirer.default.prompt([{
3599
+ type: "checkbox",
3600
+ name: "chosen",
3601
+ message: "Select integrations to configure (need API keys):",
3602
+ choices: [...INTEGRATIONS.map((i) => ({
3603
+ name: i.name,
3604
+ value: i.value
3605
+ }))],
3606
+ pageSize: 14
3607
+ }]);
3608
+ if (chosen.length === 0) {
3609
+ console.log(chalk.default.gray(" No integrations selected. You can add them later with: hyperclaw config set-key KEY value\n"));
3610
+ return;
3611
+ }
3612
+ const envPath = path.default.join(os.default.homedir(), ".hyperclaw", ".env");
3613
+ const envLines = [];
3614
+ try {
3615
+ const existing = await fs_extra.default.readFile(envPath, "utf8").catch(() => "");
3616
+ envLines.push(...existing.split("\n").filter((l) => l.trim()));
3617
+ } catch {}
3618
+ for (const id of chosen) {
3619
+ const integration = INTEGRATIONS.find((i) => i.value === id);
3620
+ console.log("\n" + chalk.default.bold.cyan(` ── ${integration.name} ──`));
3621
+ if (integration.instructions.length > 0) {
3622
+ console.log(chalk.default.gray("\n How to get your credentials:\n"));
3623
+ for (const line of integration.instructions) if (line === "") console.log();
3624
+ else if (/^\d+\./.test(line.trim())) console.log(chalk.default.white(` ${line}`));
3625
+ else console.log(chalk.default.gray(` ${line}`));
3626
+ console.log();
3627
+ const { ready } = await inquirer.default.prompt([{
3628
+ type: "confirm",
3629
+ name: "ready",
3630
+ message: ` Ready to enter your ${integration.name} credentials?`,
3631
+ default: true
3632
+ }]);
3633
+ if (!ready) {
3634
+ console.log(chalk.default.gray(` Skipped — add later: hyperclaw config set-key KEY value\n`));
3635
+ continue;
3636
+ }
3637
+ }
3638
+ for (const key of integration.keys) {
3639
+ const { val } = await inquirer.default.prompt([{
3640
+ type: key.secret ? "password" : "input",
3641
+ name: "val",
3642
+ message: ` ${key.label}:`,
3643
+ mask: key.secret ? "*" : void 0
3644
+ }]);
3645
+ if (val && val.trim()) {
3646
+ const line = `${key.env}=${val.trim()}`;
3647
+ const idx = envLines.findIndex((l) => l.startsWith(`${key.env}=`));
3648
+ if (idx >= 0) envLines[idx] = line;
3649
+ else envLines.push(line);
3650
+ console.log(chalk.default.green(` ✔ ${key.env} saved`));
3651
+ } else console.log(chalk.default.gray(` – ${key.env} skipped`));
3652
+ }
3653
+ }
3654
+ await fs_extra.default.ensureDir(path.default.dirname(envPath));
3655
+ await fs_extra.default.writeFile(envPath, envLines.filter(Boolean).join("\n") + "\n", "utf8");
3656
+ console.log(chalk.default.green(`\n ✔ Integration keys saved to ~/.hyperclaw/.env`));
3657
+ console.log(chalk.default.gray(" To add more later: hyperclaw config set-key KEY value\n"));
3658
+ }
3659
+ async testConnections(configs) {
3660
+ for (const [channelId, cfg] of Object.entries(configs)) {
3661
+ const ch = CHANNELS.find((c) => c.id === channelId);
3662
+ if (!ch) continue;
3663
+ const skipIds = [
3664
+ "whatsapp-baileys",
3665
+ "voice-call",
3666
+ "web",
3667
+ "imessage-native",
3668
+ "irc",
3669
+ "signal",
3670
+ "tlon"
3671
+ ];
3672
+ if (skipIds.includes(channelId)) {
3673
+ console.log(chalk.default.gray(` ${ch.emoji} ${ch.name} — skipped (requires runtime setup)`));
3674
+ continue;
3675
+ }
3676
+ if (!cfg?.token) {
3677
+ console.log(chalk.default.gray(` ${ch.emoji} ${ch.name} — skipped (no token)`));
3678
+ continue;
3679
+ }
3680
+ const s = (0, ora.default)(` Testing ${ch.emoji} ${ch.name}...`).start();
3681
+ try {
3682
+ const ok = await this.validateChannelToken(channelId, cfg);
3683
+ if (ok) s.succeed(chalk.default.green(`${ch.emoji} ${ch.name} — token valid`));
3684
+ else {
3685
+ s.fail(chalk.default.red(`${ch.emoji} ${ch.name} — invalid token or wrong credentials`));
3686
+ console.log(chalk.default.gray(` Fix: hyperclaw channels add ${channelId}`));
3687
+ console.log(chalk.default.gray(` Or edit: ~/.hyperclaw/hyperclaw.json (channelConfigs.${channelId})`));
3688
+ }
3689
+ } catch (e) {
3690
+ s.warn(chalk.default.yellow(`${ch.emoji} ${ch.name} — could not verify (${e.message?.slice(0, 60) ?? "timeout"})`));
3691
+ }
3692
+ }
3693
+ }
3694
+ async validateChannelToken(channelId, cfg) {
3695
+ const token = cfg.token ?? "";
3696
+ const timeout = 8e3;
3697
+ const fetchWithTimeout = async (url, init) => {
3698
+ const ctrl = new AbortController();
3699
+ const t = setTimeout(() => ctrl.abort(), timeout);
3700
+ try {
3701
+ return await fetch(url, {
3702
+ ...init,
3703
+ signal: ctrl.signal
3704
+ });
3705
+ } finally {
3706
+ clearTimeout(t);
3707
+ }
3708
+ };
3709
+ switch (channelId) {
3710
+ case "telegram": {
3711
+ const r = await fetchWithTimeout(`https://api.telegram.org/bot${token}/getMe`);
3712
+ const j = await r.json();
3713
+ return j?.ok === true;
3714
+ }
3715
+ case "discord": {
3716
+ const r = await fetchWithTimeout("https://discord.com/api/v10/users/@me", { headers: { Authorization: `Bot ${token}` } });
3717
+ const j = await r.json();
3718
+ return !!j?.id;
3719
+ }
3720
+ case "slack": {
3721
+ const r = await fetchWithTimeout("https://slack.com/api/auth.test", {
3722
+ method: "POST",
3723
+ headers: {
3724
+ Authorization: `Bearer ${token}`,
3725
+ "Content-Type": "application/json"
3726
+ }
3727
+ });
3728
+ const j = await r.json();
3729
+ return j?.ok === true;
3730
+ }
3731
+ case "matrix": {
3732
+ const homeserver = (cfg.homeserver ?? "").replace(/\/$/, "");
3733
+ if (!homeserver) return false;
3734
+ const r = await fetchWithTimeout(`${homeserver}/_matrix/client/v3/account/whoami`, { headers: { Authorization: `Bearer ${token}` } });
3735
+ const j = await r.json();
3736
+ return !!j?.user_id;
3737
+ }
3738
+ case "line": {
3739
+ const r = await fetchWithTimeout("https://api.line.me/v2/bot/info", { headers: { Authorization: `Bearer ${token}` } });
3740
+ const j = await r.json();
3741
+ return !!j?.userId;
3742
+ }
3743
+ case "viber": {
3744
+ const r = await fetchWithTimeout("https://chatapi.viber.com/pa/get_account_info", {
3745
+ method: "POST",
3746
+ headers: {
3747
+ "X-Viber-Auth-Token": token,
3748
+ "Content-Type": "application/json"
3749
+ },
3750
+ body: JSON.stringify({})
3751
+ });
3752
+ const j = await r.json();
3753
+ return j?.status === 0;
3754
+ }
3755
+ case "mattermost": {
3756
+ const serverUrl = (cfg.serverUrl ?? "").replace(/\/$/, "");
3757
+ if (!serverUrl) return false;
3758
+ const r = await fetchWithTimeout(`${serverUrl}/api/v4/users/me`, { headers: { Authorization: `Bearer ${token}` } });
3759
+ const j = await r.json();
3760
+ return !!j?.id;
3761
+ }
3762
+ case "messenger":
3763
+ case "instagram":
3764
+ case "whatsapp": {
3765
+ const r = await fetchWithTimeout(`https://graph.facebook.com/me?access_token=${token}`);
3766
+ const j = await r.json();
3767
+ return !!j?.id;
3768
+ }
3769
+ case "feishu": {
3770
+ const appSecret = cfg.appSecret ?? "";
3771
+ const r = await fetchWithTimeout("https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal", {
3772
+ method: "POST",
3773
+ headers: { "Content-Type": "application/json" },
3774
+ body: JSON.stringify({
3775
+ app_id: token,
3776
+ app_secret: appSecret
3777
+ })
3778
+ });
3779
+ const j = await r.json();
3780
+ return j?.code === 0;
3781
+ }
3782
+ case "googlechat": return /^https:\/\/chat\.googleapis\.com\/v1\/spaces\/.+\/messages/.test(token);
3783
+ case "nostr": return /^[0-9a-f]{64}$/.test(token) || token.startsWith("nsec");
3784
+ case "email": {
3785
+ const user = cfg.user ?? "";
3786
+ const imapHost = cfg.imapHost ?? "";
3787
+ const smtpHost = cfg.smtpHost ?? "";
3788
+ return /^[^@]+@[^@]+\.[^@]+$/.test(user) && imapHost.length > 3 && smtpHost.length > 3 && token.length > 3;
3789
+ }
3790
+ case "nextcloud": {
3791
+ const serverUrl = (cfg.serverUrl ?? "").replace(/\/$/, "");
3792
+ const username = cfg.username ?? "";
3793
+ if (!serverUrl || !username) return false;
3794
+ const creds = Buffer.from(`${username}:${token}`).toString("base64");
3795
+ const r = await fetchWithTimeout(`${serverUrl}/ocs/v1.php/cloud/user?format=json`, { headers: {
3796
+ Authorization: `Basic ${creds}`,
3797
+ "OCS-APIREQUEST": "true"
3798
+ } });
3799
+ const j = await r.json();
3800
+ return j?.ocs?.meta?.status === "ok";
3801
+ }
3802
+ case "twitter": return token.length > 0 && (cfg.apiKeySecret ?? "").length > 0 && (cfg.accessToken ?? "").length > 0 && (cfg.accessTokenSecret ?? "").length > 0;
3803
+ case "msteams": return token.length > 8 && (cfg.appPassword ?? "").length > 3;
3804
+ case "zalo": return token.length > 0 && (cfg.secretKey ?? "").length > 0;
3805
+ case "imessage": return token.length > 3;
3806
+ default: return token.length > 0;
3807
+ }
3808
+ }
3809
+ showSuccessScreen(data, gatewayReachable = false) {
3810
+ const channels = Object.keys(data.channelConfigs || {});
3811
+ const gwUrl = `ws://localhost:${data.gatewayConfig?.port ?? 18789}`;
3812
+ const hasEmail = channels.includes("email");
3813
+ const hasHyperClawBot = !!data.hyperclawbotConfig?.token;
3814
+ const isRemoteMode = data.gatewayConfig?.mode === "remote";
3815
+ const needsStart = data.gatewayConfig && !isRemoteMode && !gatewayReachable && channels.length > 0;
3816
+ const cmdLines = [
3817
+ chalk.default.gray(" hyperclaw dashboard Dashboard (terminal)"),
3818
+ chalk.default.gray(" hyperclaw hub — Skill hub"),
3819
+ chalk.default.gray(" hyperclaw gateway status — Gateway panel"),
3820
+ chalk.default.gray(" hyperclaw ") + chalk.default.red("daemon") + chalk.default.gray(" status — Service status"),
3821
+ chalk.default.gray(" hyperclaw voice — Voice settings"),
3822
+ chalk.default.gray(" hyperclaw canvas show — AI canvas")
3823
+ ];
3824
+ if (needsStart) cmdLines.unshift(chalk.default.yellow(" hyperclaw daemon start ") + chalk.default.bold("Start your bot (Telegram/Discord need this!)"));
3825
+ if (hasHyperClawBot) cmdLines.push(chalk.default.gray(" hyperclaw bot start — HyperClawBot remote control"));
3826
+ if (hasEmail) cmdLines.push(chalk.default.gray(" hyperclaw gmail watch-setup — Gmail Pub/Sub (real-time)"));
3827
+ cmdLines.push(chalk.default.gray(" hyperclaw nodes — Mobile nodes (Connect tab)"));
3828
+ cmdLines.push(chalk.default.gray(" hyperclaw cron list — Scheduled tasks"));
3829
+ const lines = [
3830
+ `${chalk.default.gray("Agent:")} ${chalk.default.hex("#06b6d4")(data.identity?.agentName)} (you: ${data.identity?.userName})`,
3831
+ `${chalk.default.gray("Model:")} ${data.providerConfig?.modelId}`,
3832
+ `${chalk.default.gray("Provider:")} ${data.providerConfig?.providerId}`,
3833
+ `${chalk.default.gray("Gateway:")} ${gwUrl}`,
3834
+ `${chalk.default.gray("Channels:")} ${channels.length ? channels.join(", ") : "CLI only"}`,
3835
+ "",
3836
+ chalk.default.hex("#06b6d4")("Commands:"),
3837
+ ...cmdLines
3838
+ ].join("\n");
3839
+ console.log("\n" + (0, boxen.default)(chalk.default.hex("#06b6d4")("🦅 HyperClaw v5.2.0 ready!\n\n") + lines, {
3840
+ padding: 1,
3841
+ borderStyle: "round",
3842
+ borderColor: "cyan",
3843
+ margin: 1,
3844
+ backgroundColor: "#0a0a0a"
3845
+ }));
3846
+ }
3847
+ };
3848
+
3849
+ //#endregion
3850
+ Object.defineProperty(exports, 'Banner', {
3851
+ enumerable: true,
3852
+ get: function () {
3853
+ return Banner;
3854
+ }
3855
+ });
3856
+ Object.defineProperty(exports, 'HyperClawWizard', {
3857
+ enumerable: true,
3858
+ get: function () {
3859
+ return HyperClawWizard;
3860
+ }
3861
+ });