abtars 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +84 -0
  3. package/bundle/_registry.generated-M4WY2MMI.js +35 -0
  4. package/bundle/_registry.generated-M4WY2MMI.js.map +7 -0
  5. package/bundle/abtars-browser.js +162 -0
  6. package/bundle/abtars-browser.js.map +7 -0
  7. package/bundle/abtars-cli.js +1438 -0
  8. package/bundle/abtars-cli.js.map +7 -0
  9. package/bundle/abtars-restart.js +12 -0
  10. package/bundle/abtars-restart.js.map +7 -0
  11. package/bundle/abtars-rss.js +165 -0
  12. package/bundle/abtars-rss.js.map +7 -0
  13. package/bundle/abtars-task.js +258 -0
  14. package/bundle/abtars-task.js.map +7 -0
  15. package/bundle/abtars.js +4072 -0
  16. package/bundle/abtars.js.map +7 -0
  17. package/bundle/agent-api-rate-limit-OQNFMXTZ.js +38 -0
  18. package/bundle/agent-api-rate-limit-OQNFMXTZ.js.map +7 -0
  19. package/bundle/agent-registry-LT4JNQH6.js +18 -0
  20. package/bundle/agent-registry-LT4JNQH6.js.map +7 -0
  21. package/bundle/agents/default.md +29 -0
  22. package/bundle/anthropic-adapter-2APTH3LA.js +40 -0
  23. package/bundle/anthropic-adapter-2APTH3LA.js.map +7 -0
  24. package/bundle/bridge-lock-transport-4AC2G5G6.js +39 -0
  25. package/bundle/bridge-lock-transport-4AC2G5G6.js.map +7 -0
  26. package/bundle/browse-delivery-JXBY36GK.js +17 -0
  27. package/bundle/browse-delivery-JXBY36GK.js.map +7 -0
  28. package/bundle/browser-ELNDVPLC.js +18 -0
  29. package/bundle/browser-ELNDVPLC.js.map +7 -0
  30. package/bundle/capability-CIL3G4FI.js +17 -0
  31. package/bundle/capability-CIL3G4FI.js.map +7 -0
  32. package/bundle/chunk-265TPOPC.js +289 -0
  33. package/bundle/chunk-265TPOPC.js.map +7 -0
  34. package/bundle/chunk-2UENBO6M.js +223 -0
  35. package/bundle/chunk-2UENBO6M.js.map +7 -0
  36. package/bundle/chunk-2UPU3OW6.js +67 -0
  37. package/bundle/chunk-2UPU3OW6.js.map +7 -0
  38. package/bundle/chunk-2XU2X4OI.js +125 -0
  39. package/bundle/chunk-2XU2X4OI.js.map +7 -0
  40. package/bundle/chunk-3B7BBE4F.js +758 -0
  41. package/bundle/chunk-3B7BBE4F.js.map +7 -0
  42. package/bundle/chunk-3E545J66.js +69 -0
  43. package/bundle/chunk-3E545J66.js.map +7 -0
  44. package/bundle/chunk-5R2ANXQ7.js +510 -0
  45. package/bundle/chunk-5R2ANXQ7.js.map +7 -0
  46. package/bundle/chunk-6CPN4IGS.js +507 -0
  47. package/bundle/chunk-6CPN4IGS.js.map +7 -0
  48. package/bundle/chunk-6NR3OHEW.js +88 -0
  49. package/bundle/chunk-6NR3OHEW.js.map +7 -0
  50. package/bundle/chunk-6SETMHNN.js +206 -0
  51. package/bundle/chunk-6SETMHNN.js.map +7 -0
  52. package/bundle/chunk-6UCRKRWR.js +644 -0
  53. package/bundle/chunk-6UCRKRWR.js.map +7 -0
  54. package/bundle/chunk-AR6GO6YC.js +83 -0
  55. package/bundle/chunk-AR6GO6YC.js.map +7 -0
  56. package/bundle/chunk-AZJIODTQ.js +54 -0
  57. package/bundle/chunk-AZJIODTQ.js.map +7 -0
  58. package/bundle/chunk-BHMZ4RCC.js +3706 -0
  59. package/bundle/chunk-BHMZ4RCC.js.map +7 -0
  60. package/bundle/chunk-BQ2L4GMG.js +9175 -0
  61. package/bundle/chunk-BQ2L4GMG.js.map +7 -0
  62. package/bundle/chunk-BSSBCSCL.js +159 -0
  63. package/bundle/chunk-BSSBCSCL.js.map +7 -0
  64. package/bundle/chunk-BUUVFUPO.js +157 -0
  65. package/bundle/chunk-BUUVFUPO.js.map +7 -0
  66. package/bundle/chunk-CEVRHKJY.js +131 -0
  67. package/bundle/chunk-CEVRHKJY.js.map +7 -0
  68. package/bundle/chunk-CWOHNFUV.js +39 -0
  69. package/bundle/chunk-CWOHNFUV.js.map +7 -0
  70. package/bundle/chunk-D2DCBO6M.js +228 -0
  71. package/bundle/chunk-D2DCBO6M.js.map +7 -0
  72. package/bundle/chunk-FMWKEPM7.js +31 -0
  73. package/bundle/chunk-FMWKEPM7.js.map +7 -0
  74. package/bundle/chunk-GRNENTPA.js +145 -0
  75. package/bundle/chunk-GRNENTPA.js.map +7 -0
  76. package/bundle/chunk-GST5T3WZ.js +93 -0
  77. package/bundle/chunk-GST5T3WZ.js.map +7 -0
  78. package/bundle/chunk-GUQVJC3U.js +299 -0
  79. package/bundle/chunk-GUQVJC3U.js.map +7 -0
  80. package/bundle/chunk-HX7Y7EYP.js +3659 -0
  81. package/bundle/chunk-HX7Y7EYP.js.map +7 -0
  82. package/bundle/chunk-JCJS4ZIB.js +296 -0
  83. package/bundle/chunk-JCJS4ZIB.js.map +7 -0
  84. package/bundle/chunk-JW6RU47G.js +184 -0
  85. package/bundle/chunk-JW6RU47G.js.map +7 -0
  86. package/bundle/chunk-LSPKJQCI.js +24 -0
  87. package/bundle/chunk-LSPKJQCI.js.map +7 -0
  88. package/bundle/chunk-M6VBAPNT.js +16 -0
  89. package/bundle/chunk-M6VBAPNT.js.map +7 -0
  90. package/bundle/chunk-MPX525QO.js +129 -0
  91. package/bundle/chunk-MPX525QO.js.map +7 -0
  92. package/bundle/chunk-MW6WDLU7.js +130 -0
  93. package/bundle/chunk-MW6WDLU7.js.map +7 -0
  94. package/bundle/chunk-NT3OBORC.js +215 -0
  95. package/bundle/chunk-NT3OBORC.js.map +7 -0
  96. package/bundle/chunk-NWDBD4PA.js +50 -0
  97. package/bundle/chunk-NWDBD4PA.js.map +7 -0
  98. package/bundle/chunk-OP7BTAWY.js +29 -0
  99. package/bundle/chunk-OP7BTAWY.js.map +7 -0
  100. package/bundle/chunk-PLCY3GFH.js +77 -0
  101. package/bundle/chunk-PLCY3GFH.js.map +7 -0
  102. package/bundle/chunk-PNEDC45Y.js +97 -0
  103. package/bundle/chunk-PNEDC45Y.js.map +7 -0
  104. package/bundle/chunk-QBGBT5QS.js +81 -0
  105. package/bundle/chunk-QBGBT5QS.js.map +7 -0
  106. package/bundle/chunk-RVE2N7FA.js +70 -0
  107. package/bundle/chunk-RVE2N7FA.js.map +7 -0
  108. package/bundle/chunk-TZHIDLDS.js +71910 -0
  109. package/bundle/chunk-TZHIDLDS.js.map +7 -0
  110. package/bundle/chunk-UCQ2WC3B.js +126 -0
  111. package/bundle/chunk-UCQ2WC3B.js.map +7 -0
  112. package/bundle/chunk-UHRP745J.js +214 -0
  113. package/bundle/chunk-UHRP745J.js.map +7 -0
  114. package/bundle/chunk-V76TVMCM.js +58 -0
  115. package/bundle/chunk-V76TVMCM.js.map +7 -0
  116. package/bundle/chunk-VVEDVGCR.js +981 -0
  117. package/bundle/chunk-VVEDVGCR.js.map +7 -0
  118. package/bundle/chunk-W6FAL35D.js +102 -0
  119. package/bundle/chunk-W6FAL35D.js.map +7 -0
  120. package/bundle/chunk-X6TERNVJ.js +15902 -0
  121. package/bundle/chunk-X6TERNVJ.js.map +7 -0
  122. package/bundle/chunk-X76UX47U.js +47 -0
  123. package/bundle/chunk-X76UX47U.js.map +7 -0
  124. package/bundle/chunk-XREWVCUO.js +518 -0
  125. package/bundle/chunk-XREWVCUO.js.map +7 -0
  126. package/bundle/chunk-Y6XAEX2Q.js +408 -0
  127. package/bundle/chunk-Y6XAEX2Q.js.map +7 -0
  128. package/bundle/chunk-YOCTDKKL.js +28 -0
  129. package/bundle/chunk-YOCTDKKL.js.map +7 -0
  130. package/bundle/chunk-ZXPXCDA6.js +160 -0
  131. package/bundle/chunk-ZXPXCDA6.js.map +7 -0
  132. package/bundle/commands-BHVUOU3V.js +31 -0
  133. package/bundle/commands-BHVUOU3V.js.map +7 -0
  134. package/bundle/completion-buffer-P253ONKF.js +13 -0
  135. package/bundle/completion-buffer-P253ONKF.js.map +7 -0
  136. package/bundle/config-RGSDAPZN.js +19 -0
  137. package/bundle/config-RGSDAPZN.js.map +7 -0
  138. package/bundle/config-show-ERTATR6E.js +40 -0
  139. package/bundle/config-show-ERTATR6E.js.map +7 -0
  140. package/bundle/context-HCEGZNDC.js +72 -0
  141. package/bundle/context-HCEGZNDC.js.map +7 -0
  142. package/bundle/delegation-tools-GYTS2D6A.js +27 -0
  143. package/bundle/delegation-tools-GYTS2D6A.js.map +7 -0
  144. package/bundle/deploy-lib-import-32ZFKHWP.js +49 -0
  145. package/bundle/deploy-lib-import-32ZFKHWP.js.map +7 -0
  146. package/bundle/digital-signature-OFCGSHWO.js +13 -0
  147. package/bundle/digital-signature-OFCGSHWO.js.map +7 -0
  148. package/bundle/direct-api-transport-YR7SXXNN.js +860 -0
  149. package/bundle/direct-api-transport-YR7SXXNN.js.map +7 -0
  150. package/bundle/discord-adapter-YYWVMPPU.js +584 -0
  151. package/bundle/discord-adapter-YYWVMPPU.js.map +7 -0
  152. package/bundle/dist-MTMKARCP.js +1969 -0
  153. package/bundle/dist-MTMKARCP.js.map +7 -0
  154. package/bundle/dns-wakeup-27M7D2MR.js +107 -0
  155. package/bundle/dns-wakeup-27M7D2MR.js.map +7 -0
  156. package/bundle/doctor-QNUSDY73.js +248 -0
  157. package/bundle/doctor-QNUSDY73.js.map +7 -0
  158. package/bundle/ensure-invariants-NMXNS476.js +49 -0
  159. package/bundle/ensure-invariants-NMXNS476.js.map +7 -0
  160. package/bundle/env-schema-2KBHBDGN.js +19 -0
  161. package/bundle/env-schema-2KBHBDGN.js.map +7 -0
  162. package/bundle/esm-DDP6NCZG.js +100663 -0
  163. package/bundle/esm-DDP6NCZG.js.map +7 -0
  164. package/bundle/fallback-policy-L4QV2PEJ.js +46 -0
  165. package/bundle/fallback-policy-L4QV2PEJ.js.map +7 -0
  166. package/bundle/health-check-SPA7NT6N.js +56 -0
  167. package/bundle/health-check-SPA7NT6N.js.map +7 -0
  168. package/bundle/hook-system-6Q5YTR53.js +17 -0
  169. package/bundle/hook-system-6Q5YTR53.js.map +7 -0
  170. package/bundle/hotskills-K7BM4YLB.js +12 -0
  171. package/bundle/hotskills-K7BM4YLB.js.map +7 -0
  172. package/bundle/install-6HRZVKUM.js +15 -0
  173. package/bundle/install-6HRZVKUM.js.map +7 -0
  174. package/bundle/install-log-IAPHYKD4.js +28 -0
  175. package/bundle/install-log-IAPHYKD4.js.map +7 -0
  176. package/bundle/install-manifest-SPQRUNXL.js +102 -0
  177. package/bundle/install-manifest-SPQRUNXL.js.map +7 -0
  178. package/bundle/install-validate-PVLZXYLQ.js +53 -0
  179. package/bundle/install-validate-PVLZXYLQ.js.map +7 -0
  180. package/bundle/irc-adapter-OI5UZSQF.js +293 -0
  181. package/bundle/irc-adapter-OI5UZSQF.js.map +7 -0
  182. package/bundle/irc-config-55YO6EGB.js +88 -0
  183. package/bundle/irc-config-55YO6EGB.js.map +7 -0
  184. package/bundle/logs-ZNYXX5PA.js +19 -0
  185. package/bundle/logs-ZNYXX5PA.js.map +7 -0
  186. package/bundle/media-utils-XNNDTYFI.js +4662 -0
  187. package/bundle/media-utils-XNNDTYFI.js.map +7 -0
  188. package/bundle/message-pipeline-LLH5SYMO.js +33 -0
  189. package/bundle/message-pipeline-LLH5SYMO.js.map +7 -0
  190. package/bundle/meta.json +41304 -0
  191. package/bundle/model-health-registry-35LQNVQR.js +11 -0
  192. package/bundle/model-health-registry-35LQNVQR.js.map +7 -0
  193. package/bundle/notification-Y5S5MMLV.js +13 -0
  194. package/bundle/notification-Y5S5MMLV.js.map +7 -0
  195. package/bundle/openrouter-credits-EDY7ETAU.js +32 -0
  196. package/bundle/openrouter-credits-EDY7ETAU.js.map +7 -0
  197. package/bundle/passwd-RRFV4CC5.js +133 -0
  198. package/bundle/passwd-RRFV4CC5.js.map +7 -0
  199. package/bundle/paths-G33RZWZ7.js +17 -0
  200. package/bundle/paths-G33RZWZ7.js.map +7 -0
  201. package/bundle/peer-client-52XYMNI7.js +156 -0
  202. package/bundle/peer-client-52XYMNI7.js.map +7 -0
  203. package/bundle/peer-config-VK6EDLN5.js +16 -0
  204. package/bundle/peer-config-VK6EDLN5.js.map +7 -0
  205. package/bundle/peer-sessions-EAXTNQ36.js +49 -0
  206. package/bundle/peer-sessions-EAXTNQ36.js.map +7 -0
  207. package/bundle/pending-callback-RIMQZ7FJ.js +40 -0
  208. package/bundle/pending-callback-RIMQZ7FJ.js.map +7 -0
  209. package/bundle/phase-transport-KYERDL2O.js +22 -0
  210. package/bundle/phase-transport-KYERDL2O.js.map +7 -0
  211. package/bundle/public/css/dashboard.css +542 -0
  212. package/bundle/public/index.html +180 -0
  213. package/bundle/public/js/app.js +437 -0
  214. package/bundle/public/memory-universe.js +384 -0
  215. package/bundle/responses-adapter-AAQTY3K4.js +30 -0
  216. package/bundle/responses-adapter-AAQTY3K4.js.map +7 -0
  217. package/bundle/restore-ZE3SEPSS.js +46 -0
  218. package/bundle/restore-ZE3SEPSS.js.map +7 -0
  219. package/bundle/self-healer-utils-DMUUXC47.js +43 -0
  220. package/bundle/self-healer-utils-DMUUXC47.js.map +7 -0
  221. package/bundle/skill-stats-LLEXEXLR.js +22 -0
  222. package/bundle/skill-stats-LLEXEXLR.js.map +7 -0
  223. package/bundle/sleep-OYIUOVQD.js +19 -0
  224. package/bundle/sleep-OYIUOVQD.js.map +7 -0
  225. package/bundle/soul-loader-54WCVNLJ.js +16 -0
  226. package/bundle/soul-loader-54WCVNLJ.js.map +7 -0
  227. package/bundle/src-JL4PVO23.js +8 -0
  228. package/bundle/src-JL4PVO23.js.map +7 -0
  229. package/bundle/sse-parser-anthropic-P7CE2MH2.js +72 -0
  230. package/bundle/sse-parser-anthropic-P7CE2MH2.js.map +7 -0
  231. package/bundle/sse-parser-responses-EQQA5FWN.js +63 -0
  232. package/bundle/sse-parser-responses-EQQA5FWN.js.map +7 -0
  233. package/bundle/ssrf-guard-FZCBYIVW.js +64 -0
  234. package/bundle/ssrf-guard-FZCBYIVW.js.map +7 -0
  235. package/bundle/start-FH3GRMJ4.js +35 -0
  236. package/bundle/start-FH3GRMJ4.js.map +7 -0
  237. package/bundle/stream-single-WSG4D53C.js +33 -0
  238. package/bundle/stream-single-WSG4D53C.js.map +7 -0
  239. package/bundle/stt-2UH3RITX.js +14 -0
  240. package/bundle/stt-2UH3RITX.js.map +7 -0
  241. package/bundle/subagent-runtime-LE2ZXH3G.js +12 -0
  242. package/bundle/subagent-runtime-LE2ZXH3G.js.map +7 -0
  243. package/bundle/system-message-T5R3EYYN.js +30 -0
  244. package/bundle/system-message-T5R3EYYN.js.map +7 -0
  245. package/bundle/system-status-KQ6KHFJ6.js +189 -0
  246. package/bundle/system-status-KQ6KHFJ6.js.map +7 -0
  247. package/bundle/task-store-K7CQDEPI.js +22 -0
  248. package/bundle/task-store-K7CQDEPI.js.map +7 -0
  249. package/bundle/telegram-adapter-2V3XUMT5.js +1060 -0
  250. package/bundle/telegram-adapter-2V3XUMT5.js.map +7 -0
  251. package/bundle/tool-registry-MU3OX4UI.js +38 -0
  252. package/bundle/tool-registry-MU3OX4UI.js.map +7 -0
  253. package/bundle/tool-sandbox-VYOK4ZOA.js +20 -0
  254. package/bundle/tool-sandbox-VYOK4ZOA.js.map +7 -0
  255. package/bundle/transport-config-YLXU33RO.js +57 -0
  256. package/bundle/transport-config-YLXU33RO.js.map +7 -0
  257. package/bundle/update-QCW5LXRN.js +13 -0
  258. package/bundle/update-QCW5LXRN.js.map +7 -0
  259. package/bundle/update-check-27KZSAP6.js +12 -0
  260. package/bundle/update-check-27KZSAP6.js.map +7 -0
  261. package/bundle/usage-tracker-OVVEVMOY.js +17 -0
  262. package/bundle/usage-tracker-OVVEVMOY.js.map +7 -0
  263. package/bundle/user-registry-D4SD73UV.js +16 -0
  264. package/bundle/user-registry-D4SD73UV.js.map +7 -0
  265. package/core/professor.json +14 -0
  266. package/core/prompts/browsing_prompt.md +39 -0
  267. package/core/prompts/compaction.md +32 -0
  268. package/core/skills/memory/classification/SKILL.md +37 -0
  269. package/core/skills/memory/memory-anomalies/SKILL.md +39 -0
  270. package/core/skills/memory/memory-search/SKILL.md +48 -0
  271. package/core/skills/memory/topic-save/SKILL.md +44 -0
  272. package/core/skills/ops/cron/SKILL.md +51 -0
  273. package/core/skills/ops/gdrive-backup/SKILL.md +15 -0
  274. package/core/skills/ops/session-start/SKILL.md +11 -0
  275. package/core/skills/ops/skill-authoring/SKILL.md +54 -0
  276. package/core/skills/ops/system-health/SKILL.md +104 -0
  277. package/core/skills/ops/troubleshooting/SKILL.md +48 -0
  278. package/core/skills/ops/trust-gating/SKILL.md +30 -0
  279. package/core/skills/tools/a2a-communication/SKILL.md +68 -0
  280. package/core/skills/tools/browse-delegate/SKILL.md +27 -0
  281. package/core/skills/tools/browser/SKILL.md +36 -0
  282. package/core/skills/tools/clawhub/SKILL.md +44 -0
  283. package/core/skills/tools/delegation/SKILL.md +48 -0
  284. package/core/skills/tools/fxtwitter/SKILL.md +52 -0
  285. package/core/skills/tools/gmail/SKILL.md +44 -0
  286. package/core/skills/tools/irc-chat/SKILL.md +84 -0
  287. package/core/skills/tools/linear/SKILL.md +90 -0
  288. package/core/skills/tools/mcporter/SKILL.md +46 -0
  289. package/core/skills/tools/model-scout/SKILL.md +132 -0
  290. package/core/skills/tools/model-scout/scout-add-model.py +67 -0
  291. package/core/skills/tools/model-scout/scout-ollama.py +116 -0
  292. package/core/skills/tools/model-scout/scout-openrouter.py +85 -0
  293. package/core/skills/tools/nlm/SKILL.md +40 -0
  294. package/core/skills/tools/todo/SKILL.md +30 -0
  295. package/core/skills/tools/twitterX/SKILL.md +52 -0
  296. package/core/skills/tools/twitterX/scripts/abtars-tweet.js +532 -0
  297. package/core/skills/tools/twitterX/scripts/package.json +1 -0
  298. package/core/skills/tools/web-fetch/SKILL.md +29 -0
  299. package/package.json +59 -0
  300. package/scripts/abtars-daemon.service +23 -0
  301. package/scripts/abtars-fetch.sh +42 -0
  302. package/scripts/abtars-watchdog.service +13 -0
  303. package/scripts/abtars.sh +14 -0
  304. package/scripts/abtars@.service +21 -0
  305. package/scripts/browser-patchright.sh +79 -0
  306. package/scripts/com.abtars.daemon.plist +24 -0
  307. package/scripts/com.abtars.watchdog.plist +27 -0
  308. package/scripts/daily-backup.sh +62 -0
  309. package/scripts/doctor.sh +553 -0
  310. package/scripts/hooks/audit-logger.sh +22 -0
  311. package/scripts/upgrade-deps.sh +64 -0
  312. package/scripts/watchdog.sh +309 -0
@@ -0,0 +1,1438 @@
1
+ import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
2
+ import {
3
+ showHintOnce,
4
+ update
5
+ } from "./chunk-5R2ANXQ7.js";
6
+ import {
7
+ install
8
+ } from "./chunk-XREWVCUO.js";
9
+ import {
10
+ acquireLock,
11
+ activate,
12
+ emptyManifest,
13
+ inspectLock,
14
+ packagePaths,
15
+ readCurrent,
16
+ readManifest,
17
+ releaseExists,
18
+ writeManifest
19
+ } from "./chunk-265TPOPC.js";
20
+ import {
21
+ restart
22
+ } from "./chunk-ZXPXCDA6.js";
23
+ import {
24
+ init_log_and_swallow,
25
+ logAndSwallow
26
+ } from "./chunk-FMWKEPM7.js";
27
+ import "./chunk-BUUVFUPO.js";
28
+ import {
29
+ abtarsHome,
30
+ init_paths
31
+ } from "./chunk-X76UX47U.js";
32
+ import {
33
+ __require
34
+ } from "./chunk-NWDBD4PA.js";
35
+
36
+ // src/cli/commands/doctor.ts
37
+ import { spawn } from "node:child_process";
38
+ import { stat } from "node:fs/promises";
39
+ import { join } from "node:path";
40
+ async function pathExists(p) {
41
+ try {
42
+ await stat(p);
43
+ return true;
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+ async function doctor(args = []) {
49
+ const paths = packagePaths("abtars");
50
+ const installed = join(paths.home, "scripts", "doctor.sh");
51
+ const repo = join(process.cwd(), "scripts", "doctor.sh");
52
+ const candidate = await pathExists(installed) ? installed : await pathExists(repo) ? repo : null;
53
+ if (candidate === null) {
54
+ process.stderr.write(
55
+ `doctor.sh not found (looked in ${installed} and ${repo}).
56
+ Run from an abtars checkout or after 'abtars install'.
57
+ `
58
+ );
59
+ return 2;
60
+ }
61
+ return new Promise((resolve) => {
62
+ const child = spawn(candidate, [...args], { stdio: "inherit", env: process.env });
63
+ child.on("exit", (code) => resolve(code ?? 1));
64
+ child.on("error", (err) => {
65
+ process.stderr.write(`doctor.sh spawn failed: ${err.message}
66
+ `);
67
+ resolve(1);
68
+ });
69
+ });
70
+ }
71
+
72
+ // src/cli/commands/uninstall.ts
73
+ import { existsSync as existsSync2, readdirSync, unlinkSync as unlinkSync2, readlinkSync, rmSync } from "node:fs";
74
+ import { join as join3 } from "node:path";
75
+ import { createInterface } from "node:readline";
76
+
77
+ // src/cli/commands/stop.ts
78
+ init_log_and_swallow();
79
+ import { existsSync, readFileSync, unlinkSync } from "node:fs";
80
+ import { execFileSync } from "node:child_process";
81
+ import { join as join2 } from "node:path";
82
+ import { homedir } from "node:os";
83
+ function abtarsHome2() {
84
+ return process.env["ABTARS_HOME"] ?? join2(process.env["HOME"] ?? "", ".abtars");
85
+ }
86
+ function readJsonField(file, field) {
87
+ try {
88
+ const data = JSON.parse(readFileSync(file, "utf-8"));
89
+ return data[field];
90
+ } catch {
91
+ return void 0;
92
+ }
93
+ }
94
+ function pidAlive(pid) {
95
+ try {
96
+ process.kill(pid, 0);
97
+ return true;
98
+ } catch {
99
+ return false;
100
+ }
101
+ }
102
+ function pidLooksLike(pid, needles) {
103
+ try {
104
+ const cmdline = readFileSync(`/proc/${pid}/cmdline`, "utf-8");
105
+ return needles.some((n) => cmdline.includes(n));
106
+ } catch {
107
+ return true;
108
+ }
109
+ }
110
+ async function killGracefully(pid, needles) {
111
+ if (!pidAlive(pid)) return "not-running";
112
+ if (!pidLooksLike(pid, needles)) return "stale";
113
+ try {
114
+ process.kill(pid, "SIGTERM");
115
+ } catch {
116
+ return "not-running";
117
+ }
118
+ for (let i = 0; i < 10; i++) {
119
+ await new Promise((r) => setTimeout(r, 500));
120
+ if (!pidAlive(pid)) return "killed";
121
+ }
122
+ try {
123
+ process.kill(pid, "SIGKILL");
124
+ } catch {
125
+ }
126
+ await new Promise((r) => setTimeout(r, 500));
127
+ return pidAlive(pid) ? "not-running" : "forced";
128
+ }
129
+ function removeLock(path) {
130
+ try {
131
+ if (existsSync(path)) unlinkSync(path);
132
+ } catch (err) {
133
+ logAndSwallow("stop", "op", err);
134
+ }
135
+ }
136
+ async function stop(opts) {
137
+ const home = abtarsHome2();
138
+ const manifestPath = join2(home, "manifest.json");
139
+ const watchdogLock = join2(home, "watchdog.lock");
140
+ const bridgeLock = join2(home, "bridge.lock");
141
+ const force = opts.force ?? false;
142
+ const installMode = readJsonField(manifestPath, "installMode");
143
+ if (installMode === "supervised-daemon" && !force) {
144
+ process.stderr.write(`Bridge runs under supervised-daemon \u2014 use supervisor stop (supervisor will respawn if you kill the process directly).
145
+ `);
146
+ if (process.platform === "darwin") {
147
+ process.stderr.write(` sudo -k launchctl bootout system/com.abtars.daemon
148
+ `);
149
+ } else {
150
+ process.stderr.write(` sudo -k systemctl stop abtars
151
+ `);
152
+ }
153
+ process.stderr.write(`
154
+ Use 'abtars stop --force' to kill the process anyway (supervisor will respawn).
155
+ `);
156
+ return 1;
157
+ }
158
+ if (force && process.platform === "darwin") {
159
+ try {
160
+ execFileSync("launchctl", ["bootout", `gui/${process.getuid()}`, join2(homedir(), "Library", "LaunchAgents", "com.abtars.watchdog.plist")], { timeout: 5e3 });
161
+ } catch {
162
+ }
163
+ }
164
+ const wdPid = readJsonField(watchdogLock, "pid");
165
+ let wdResult = "not-running";
166
+ let wdPidActual;
167
+ if (wdPid && wdPid > 0) {
168
+ wdPidActual = wdPid;
169
+ wdResult = await killGracefully(wdPid, ["watchdog.sh"]);
170
+ if (wdResult === "killed" || wdResult === "forced") {
171
+ removeLock(watchdogLock);
172
+ } else if (wdResult === "stale") {
173
+ process.stdout.write(`\u26A0\uFE0F watchdog.lock PID ${wdPid} is not watchdog.sh \u2014 stale lock, removing
174
+ `);
175
+ removeLock(watchdogLock);
176
+ }
177
+ }
178
+ const brPid = readJsonField(bridgeLock, "pid");
179
+ let brResult = "not-running";
180
+ let brPidActual;
181
+ if (brPid && brPid > 0) {
182
+ brPidActual = brPid;
183
+ brResult = await killGracefully(brPid, ["abtars", "main.js", "bundle"]);
184
+ if (brResult === "killed" || brResult === "forced") {
185
+ removeLock(bridgeLock);
186
+ } else if (brResult === "stale") {
187
+ process.stdout.write(`\u26A0\uFE0F bridge.lock PID ${brPid} is not abtars \u2014 stale lock, removing
188
+ `);
189
+ removeLock(bridgeLock);
190
+ }
191
+ }
192
+ const wdMsg = formatResult("Watchdog", wdResult, wdPidActual);
193
+ const brMsg = formatResult("Bridge", brResult, brPidActual);
194
+ if (wdResult === "not-running" && brResult === "not-running") {
195
+ process.stdout.write(`Nothing to stop \u2014 neither watchdog nor bridge running.
196
+ `);
197
+ return 0;
198
+ }
199
+ process.stdout.write(`\u{1F6D1} ${wdMsg}
200
+ ${brMsg}
201
+ `);
202
+ if (force && process.platform === "darwin") {
203
+ process.stdout.write(` LaunchAgent unloaded. To restart: launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.abtars.watchdog.plist
204
+ `);
205
+ }
206
+ const allDown = (wdResult === "not-running" || wdResult === "killed" || wdResult === "forced" || wdResult === "stale") && (brResult === "not-running" || brResult === "killed" || brResult === "forced" || brResult === "stale");
207
+ return allDown ? 0 : 1;
208
+ }
209
+ function formatResult(label, result, pid) {
210
+ switch (result) {
211
+ case "killed":
212
+ return `${label} stopped (PID ${pid}, SIGTERM)`;
213
+ case "forced":
214
+ return `${label} stopped (PID ${pid}, SIGKILL)`;
215
+ case "stale":
216
+ return `${label} lock was stale (PID ${pid} not ours)`;
217
+ case "not-running":
218
+ return `${label} was not running`;
219
+ case "gone":
220
+ return `${label} kill failed \u2014 PID ${pid} still alive`;
221
+ }
222
+ }
223
+
224
+ // src/cli/commands/uninstall.ts
225
+ function abtarsHome3() {
226
+ return process.env["ABTARS_HOME"] ?? join3(process.env["HOME"] ?? "", ".abtars");
227
+ }
228
+ function binDir() {
229
+ return join3(process.env["HOME"] ?? "", ".local", "bin");
230
+ }
231
+ async function confirm() {
232
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
233
+ return new Promise((resolve) => {
234
+ rl.question("\u26A0\uFE0F This will DELETE ~/.abtars/ entirely. Type 'uninstall' to confirm: ", (answer) => {
235
+ rl.close();
236
+ resolve(answer.trim() === "uninstall");
237
+ });
238
+ });
239
+ }
240
+ function removeSymlinks() {
241
+ const dir = binDir();
242
+ if (!existsSync2(dir)) return [];
243
+ const home = abtarsHome3();
244
+ const removed = [];
245
+ for (const entry of readdirSync(dir)) {
246
+ if (!entry.startsWith("abtars")) continue;
247
+ const full = join3(dir, entry);
248
+ try {
249
+ const target = readlinkSync(full);
250
+ if (target.includes(home) || target.includes(".abtars")) {
251
+ unlinkSync2(full);
252
+ removed.push(entry);
253
+ }
254
+ } catch {
255
+ }
256
+ }
257
+ return removed;
258
+ }
259
+ function unloadLaunchd() {
260
+ if (process.platform !== "darwin") return;
261
+ const plist = join3(process.env["HOME"] ?? "", "Library", "LaunchAgents", "com.abtars.watchdog.plist");
262
+ if (!existsSync2(plist)) return;
263
+ try {
264
+ const { execSync } = __require("node:child_process");
265
+ execSync(`launchctl bootout gui/$(id -u) "${plist}" 2>/dev/null`, { stdio: "ignore" });
266
+ unlinkSync2(plist);
267
+ } catch {
268
+ }
269
+ }
270
+ async function uninstall(opts) {
271
+ const home = abtarsHome3();
272
+ if (!existsSync2(home)) {
273
+ process.stdout.write("Nothing to uninstall \u2014 ~/.abtars/ does not exist.\n");
274
+ return 0;
275
+ }
276
+ if (!opts.yes) {
277
+ const confirmed = await confirm();
278
+ if (!confirmed) {
279
+ process.stdout.write("Aborted.\n");
280
+ return 1;
281
+ }
282
+ }
283
+ await stop({ force: true });
284
+ unloadLaunchd();
285
+ const removed = removeSymlinks();
286
+ rmSync(home, { recursive: true, force: true });
287
+ process.stdout.write(`
288
+ \u2713 Uninstalled abtars
289
+ `);
290
+ process.stdout.write(` Removed: ${home}/
291
+ `);
292
+ if (removed.length > 0) {
293
+ process.stdout.write(` Symlinks removed: ${removed.join(", ")}
294
+ `);
295
+ }
296
+ process.stdout.write(`
297
+ Source repo (~/abtars/) is untouched.
298
+ `);
299
+ return 0;
300
+ }
301
+
302
+ // src/cli/commands/backup.ts
303
+ init_paths();
304
+ import { existsSync as existsSync3, mkdirSync, readdirSync as readdirSync2, statSync, renameSync, unlinkSync as unlinkSync3, copyFileSync } from "node:fs";
305
+ import { join as join4, dirname } from "node:path";
306
+ import { spawnSync } from "node:child_process";
307
+ var AB_SAVE = ["config", "secret", "tasks", "logo", "workspace", "skills/custom", "skills/self"];
308
+ var DEFAULT_PRUNE_DAYS = 7;
309
+ async function backup(outputDir, pruneDays) {
310
+ const abHome = abtarsHome();
311
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
312
+ const destDir = outputDir ?? join4(dirname(abHome), ".backup-abtars");
313
+ mkdirSync(destDir, { recursive: true });
314
+ const abmindPaths = [
315
+ join4(dirname(abHome), ".abmind", "lib", "node_modules", "abmind", "dist", "cli", "abmind-backup.js"),
316
+ join4(dirname(abHome), "workspace", "ab", "abmind", "dist", "cli", "abmind-backup.js")
317
+ ];
318
+ const abmindBin = abmindPaths.find((p) => existsSync3(p));
319
+ let abmResult;
320
+ if (abmindBin) {
321
+ abmResult = spawnSync("node", [abmindBin], { encoding: "utf-8", env: { ...process.env } });
322
+ } else {
323
+ abmResult = spawnSync("abmind", ["backup"], { encoding: "utf-8", env: { ...process.env } });
324
+ }
325
+ if (abmResult.status !== 0) {
326
+ process.stderr.write(`\u26A0\uFE0F abmind backup failed: ${abmResult.stderr || abmResult.stdout}
327
+ `);
328
+ return 1;
329
+ }
330
+ const abmindBackupsDir = join4(dirname(abHome), ".abmind", "backups");
331
+ let abmFile;
332
+ if (existsSync3(abmindBackupsDir)) {
333
+ const abmFiles = readdirSync2(abmindBackupsDir).filter((f) => f.endsWith(".abm")).sort().reverse();
334
+ if (abmFiles.length > 0) abmFile = abmFiles[0];
335
+ }
336
+ if (abmFile) {
337
+ const src = join4(abmindBackupsDir, abmFile);
338
+ const dest = join4(destDir, `abmind-${date}.abm`);
339
+ renameSync(src, dest);
340
+ const size = (statSync(dest).size / 1024).toFixed(0);
341
+ process.stdout.write(`\u2713 abmind-${date}.abm (${size}KB, encrypted)
342
+ `);
343
+ } else {
344
+ process.stderr.write(`\u26A0\uFE0F abmind backup produced no .abm file
345
+ `);
346
+ }
347
+ const files = [];
348
+ for (const dir of AB_SAVE) {
349
+ const abs = join4(abHome, dir);
350
+ if (existsSync3(abs)) collectDir(abs, dir, files);
351
+ }
352
+ if (files.length === 0) {
353
+ process.stderr.write("Nothing to zip from abtars.\n");
354
+ return 1;
355
+ }
356
+ const tmpDir = join4(process.env["TMPDIR"] ?? "/tmp", `abtars-backup-${Date.now()}`);
357
+ mkdirSync(tmpDir, { recursive: true });
358
+ for (const f of files) {
359
+ const dest = join4(tmpDir, f.zipPath);
360
+ mkdirSync(dirname(dest), { recursive: true });
361
+ copyFileSync(f.absPath, dest);
362
+ }
363
+ const zipPath = join4(destDir, `abtars-${date}.zip`);
364
+ const has7z = spawnSync("which", ["7z"], { encoding: "utf-8" }).status === 0;
365
+ let zipOk;
366
+ if (has7z) {
367
+ const r = spawnSync("7z", ["a", zipPath.replace(/\.zip$/, ".7z"), "."], { cwd: tmpDir, encoding: "utf-8" });
368
+ zipOk = r.status === 0;
369
+ } else {
370
+ const r = spawnSync("zip", ["-r", zipPath, "."], { cwd: tmpDir, encoding: "utf-8" });
371
+ zipOk = r.status === 0;
372
+ }
373
+ spawnSync("rm", ["-rf", tmpDir]);
374
+ if (!zipOk) {
375
+ process.stderr.write(`\u26A0\uFE0F zip/7z failed
376
+ `);
377
+ return 1;
378
+ }
379
+ const actualZip = has7z ? zipPath.replace(/\.zip$/, ".7z") : zipPath;
380
+ const sizeMb = (statSync(actualZip).size / 1024 / 1024).toFixed(1);
381
+ process.stdout.write(`\u2713 ${actualZip.split("/").pop()} (${sizeMb}MB, ${files.length} files)
382
+ `);
383
+ const maxAge = (pruneDays ?? DEFAULT_PRUNE_DAYS) * 864e5;
384
+ const now = Date.now();
385
+ for (const f of readdirSync2(destDir)) {
386
+ if (!(f.startsWith("abtars-") || f.startsWith("abmind-"))) continue;
387
+ if (!(f.endsWith(".zip") || f.endsWith(".7z") || f.endsWith(".abm"))) continue;
388
+ const fPath = join4(destDir, f);
389
+ try {
390
+ if (now - statSync(fPath).mtimeMs > maxAge) {
391
+ unlinkSync3(fPath);
392
+ process.stdout.write(` \u{1F5D1} pruned ${f}
393
+ `);
394
+ }
395
+ } catch {
396
+ }
397
+ }
398
+ return 0;
399
+ }
400
+ function collectDir(dir, prefix, out) {
401
+ for (const entry of readdirSync2(dir, { withFileTypes: true })) {
402
+ const abs = join4(dir, entry.name);
403
+ const rel = `${prefix}/${entry.name}`;
404
+ if (entry.isDirectory()) {
405
+ collectDir(abs, rel, out);
406
+ } else if (entry.isFile()) {
407
+ out.push({ absPath: abs, zipPath: rel });
408
+ }
409
+ }
410
+ }
411
+
412
+ // src/cli/commands/onboard.ts
413
+ init_log_and_swallow();
414
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
415
+ import { dirname as dirname2, join as join5 } from "node:path";
416
+ import { fileURLToPath } from "node:url";
417
+ var VALID_PROVIDERS = ["openrouter", "anthropic", "openai", "ollama", "kiro", "gemini"];
418
+ var PROVIDER_TRANSPORT_NAME = {
419
+ openrouter: "openrouter",
420
+ anthropic: "anthropic",
421
+ openai: "openai",
422
+ ollama: "ollama",
423
+ kiro: "kiro",
424
+ gemini: "gemini"
425
+ };
426
+ var DEFAULT_MODELS = {
427
+ openrouter: "google/gemini-2.5-flash",
428
+ anthropic: "claude-sonnet-4-5-20250929",
429
+ openai: "gpt-4o",
430
+ ollama: "kimi-k2.5:cloud",
431
+ kiro: "claude-sonnet-4.6",
432
+ gemini: "gemini-2.5-flash"
433
+ };
434
+ var API_PROVIDERS = /* @__PURE__ */ new Set(["openrouter", "anthropic", "openai", "ollama"]);
435
+ var PROVIDER_ENDPOINT = {
436
+ openrouter: "https://openrouter.ai/api/v1",
437
+ anthropic: "https://api.anthropic.com/v1",
438
+ openai: "https://api.openai.com/v1",
439
+ ollama: "http://localhost:11434/v1"
440
+ };
441
+ var PROVIDER_API_KEY_ENV = {
442
+ openrouter: "OPENROUTER_API_KEY",
443
+ anthropic: "ANTHROPIC_API_KEY",
444
+ openai: "OPENAI_API_KEY",
445
+ ollama: "OLLAMA_API_KEY",
446
+ kiro: "KIRO_API_KEY",
447
+ gemini: "GEMINI_API_KEY"
448
+ };
449
+ async function runInteractive(existing) {
450
+ const { intro, outro, text, select, confirm: confirm2, isCancel, cancel } = await import("./dist-MTMKARCP.js");
451
+ intro("abtars onboard \u2014 first-time setup");
452
+ const noteEmpty = "press Enter to skip";
453
+ const { packagePaths: pp, readManifest: rm } = await import("./deploy-lib-import-32ZFKHWP.js");
454
+ const mfPaths = pp("abtars");
455
+ const mf = await rm(mfPaths.manifest);
456
+ const installMode = mf?.installMode ?? "supervised";
457
+ const userName = await text({
458
+ message: "Your name",
459
+ placeholder: "your name",
460
+ initialValue: existing?.userName ?? ""
461
+ });
462
+ if (isCancel(userName)) {
463
+ cancel("Cancelled.");
464
+ return null;
465
+ }
466
+ const passphrase = "";
467
+ const securityMode = await select({
468
+ message: "Security mode \u2014 restrict agent file/command access?",
469
+ options: [
470
+ { value: "guardrails", label: "guardrails \u2014 path guard + command blocklist (recommended)" },
471
+ { value: "off", label: "off \u2014 no restrictions (legacy)" }
472
+ ],
473
+ initialValue: existing?.securityMode ?? "guardrails"
474
+ });
475
+ if (isCancel(securityMode)) {
476
+ cancel("Cancelled.");
477
+ return null;
478
+ }
479
+ const trustMode = await confirm2({
480
+ message: "Trust mode \u2014 auto-approve agent permission requests? (recommended for personal use)",
481
+ initialValue: true
482
+ });
483
+ if (isCancel(trustMode)) {
484
+ cancel("Cancelled.");
485
+ return null;
486
+ }
487
+ const telegramToken = await text({
488
+ message: `Telegram bot token (@BotFather \u2192 /mybots \u2192 API Token, ${noteEmpty})`,
489
+ placeholder: "123456789:ABCdefGHI...",
490
+ initialValue: existing?.telegramToken,
491
+ validate: (v) => !v || v.trim() === "" || v.includes(":") ? void 0 : 'expected format "<id>:<secret>" or empty'
492
+ });
493
+ if (isCancel(telegramToken)) {
494
+ cancel("Cancelled.");
495
+ return null;
496
+ }
497
+ let detectedChatId = existing?.telegramChatId ?? "";
498
+ if (telegramToken && telegramToken.trim() && !detectedChatId) {
499
+ const botUrl = `https://api.telegram.org/bot${telegramToken.trim()}`;
500
+ try {
501
+ await fetch(`${botUrl}/deleteWebhook?drop_pending_updates=true`);
502
+ } catch {
503
+ }
504
+ process.stdout.write("\nSend /start to your bot on Telegram now... (waiting 30s)\n");
505
+ try {
506
+ const res = await fetch(`${botUrl}/getUpdates?timeout=30&allowed_updates=["message"]`);
507
+ const data = await res.json();
508
+ const id = data.result?.find((u) => u.message?.chat?.id)?.message?.chat?.id;
509
+ if (id) {
510
+ detectedChatId = String(id);
511
+ process.stdout.write(`\u2713 Detected your chat ID: ${detectedChatId}
512
+ `);
513
+ } else {
514
+ process.stdout.write("\u26A0 No message received \u2014 enter manually below.\n");
515
+ }
516
+ } catch {
517
+ process.stdout.write("\u26A0 Could not reach Telegram API \u2014 enter manually below.\n");
518
+ }
519
+ }
520
+ const telegramChatId = await text({
521
+ message: `Your Telegram user ID (${noteEmpty})`,
522
+ placeholder: "123456789",
523
+ initialValue: detectedChatId,
524
+ validate: (v) => !v || v.trim() === "" || /^-?\d+$/.test(v.trim()) ? void 0 : "expected numeric user ID or empty"
525
+ });
526
+ if (isCancel(telegramChatId)) {
527
+ cancel("Cancelled.");
528
+ return null;
529
+ }
530
+ const discordBotToken = await text({
531
+ message: `Discord bot token (${noteEmpty})`,
532
+ placeholder: "MTIzNDU2...",
533
+ initialValue: existing?.discordBotToken
534
+ });
535
+ if (isCancel(discordBotToken)) {
536
+ cancel("Cancelled.");
537
+ return null;
538
+ }
539
+ const discordAppId = await text({
540
+ message: `Discord app ID (${noteEmpty})`,
541
+ placeholder: "987654321098765432",
542
+ initialValue: existing?.discordAppId,
543
+ validate: (v) => !v || v.trim() === "" || /^\d{10,20}$/.test(v.trim()) ? void 0 : "expected Discord snowflake or empty"
544
+ });
545
+ if (isCancel(discordAppId)) {
546
+ cancel("Cancelled.");
547
+ return null;
548
+ }
549
+ const discordA2aChannel = await text({
550
+ message: `Discord allowed channel ID (${noteEmpty})`,
551
+ placeholder: "987654321098765432",
552
+ initialValue: existing?.discordA2aChannel,
553
+ validate: (v) => !v || v.trim() === "" || /^\d{10,20}$/.test(v.trim()) ? void 0 : "expected Discord snowflake or empty"
554
+ });
555
+ if (isCancel(discordA2aChannel)) {
556
+ cancel("Cancelled.");
557
+ return null;
558
+ }
559
+ const defaultProvider = await select({
560
+ message: "Default transport provider",
561
+ options: [
562
+ { value: "openrouter", label: "openrouter \u2014 many models via API key" },
563
+ { value: "anthropic", label: "anthropic \u2014 Claude API (direct)" },
564
+ { value: "openai", label: "openai \u2014 GPT API (direct)" },
565
+ { value: "ollama", label: "ollama \u2014 local/cloud Ollama endpoint" },
566
+ { value: "kiro", label: "kiro \u2014 Kiro CLI (free or paid; tier via model)" },
567
+ { value: "gemini", label: "gemini \u2014 Gemini CLI (free or paid; tier via model)" }
568
+ ],
569
+ initialValue: existing?.defaultProvider ?? "kiro"
570
+ });
571
+ if (isCancel(defaultProvider)) {
572
+ cancel("Cancelled.");
573
+ return null;
574
+ }
575
+ const defaultModel = await text({
576
+ message: `Default model (for ${defaultProvider})`,
577
+ placeholder: DEFAULT_MODELS[defaultProvider],
578
+ initialValue: existing?.defaultModel ?? DEFAULT_MODELS[defaultProvider]
579
+ });
580
+ if (isCancel(defaultModel)) {
581
+ cancel("Cancelled.");
582
+ return null;
583
+ }
584
+ const apiKeyEnv = PROVIDER_API_KEY_ENV[defaultProvider];
585
+ let providerApiKey = existing?.providerApiKey ?? "";
586
+ {
587
+ const v = await text({
588
+ message: `${apiKeyEnv} (${noteEmpty})`,
589
+ placeholder: existing?.providerApiKey ? "(keep existing)" : "sk-or-v1-... or leave blank",
590
+ initialValue: existing?.providerApiKey
591
+ });
592
+ if (isCancel(v)) {
593
+ cancel("Cancelled.");
594
+ return null;
595
+ }
596
+ providerApiKey = String(v ?? "").trim() || existing?.providerApiKey || "";
597
+ }
598
+ const modelStr = String(defaultModel).trim() || DEFAULT_MODELS[defaultProvider];
599
+ if (API_PROVIDERS.has(defaultProvider) && providerApiKey) {
600
+ const check = await confirm2({ message: "Check availability (GET /v1/models)?", initialValue: true });
601
+ if (isCancel(check)) {
602
+ cancel("Cancelled.");
603
+ return null;
604
+ }
605
+ if (check) {
606
+ const endpoint = PROVIDER_ENDPOINT[defaultProvider] ?? "";
607
+ const result = await checkModelAvailability(endpoint, providerApiKey, modelStr);
608
+ process.stdout.write(result.ok ? `\u2713 ${modelStr} available on ${defaultProvider}
609
+ ` : `\u26A0\uFE0F ${result.message}
610
+ `);
611
+ }
612
+ }
613
+ const hailMary = await text({
614
+ message: `Ultimate fallback model \u2014 hailMary (${noteEmpty}; uses same provider + key as above)`,
615
+ placeholder: "google/gemini-2.5-flash",
616
+ initialValue: existing?.hailMaryModel ?? "google/gemini-2.5-flash"
617
+ });
618
+ if (isCancel(hailMary)) {
619
+ cancel("Cancelled.");
620
+ return null;
621
+ }
622
+ const hailMaryModel = String(hailMary ?? "").trim();
623
+ if (hailMaryModel && API_PROVIDERS.has(defaultProvider) && providerApiKey) {
624
+ const check = await confirm2({ message: `Check hailMary availability (${hailMaryModel})?`, initialValue: true });
625
+ if (isCancel(check)) {
626
+ cancel("Cancelled.");
627
+ return null;
628
+ }
629
+ if (check) {
630
+ const endpoint = PROVIDER_ENDPOINT[defaultProvider] ?? "";
631
+ const result = await checkModelAvailability(endpoint, providerApiKey, hailMaryModel);
632
+ process.stdout.write(result.ok ? `\u2713 ${hailMaryModel} available
633
+ ` : `\u26A0\uFE0F ${result.message}
634
+ `);
635
+ }
636
+ }
637
+ const bedTime = await text({
638
+ message: `Bed time HH:MM \u2014 daily sleep trigger (${noteEmpty} for default 0:30)`,
639
+ placeholder: "0:30",
640
+ initialValue: existing?.bedTime,
641
+ validate: (v) => !v || /^\d{1,2}:\d{2}$/.test(v.trim()) ? void 0 : "expected H:MM format"
642
+ });
643
+ if (isCancel(bedTime)) {
644
+ cancel("Cancelled.");
645
+ return null;
646
+ }
647
+ const wakeTime = await text({
648
+ message: `Wake time HH:MM (${noteEmpty} for default 7:00)`,
649
+ placeholder: "7:00",
650
+ initialValue: existing?.wakeTime,
651
+ validate: (v) => !v || /^\d{1,2}:\d{2}$/.test(v.trim()) ? void 0 : "expected H:MM format"
652
+ });
653
+ if (isCancel(wakeTime)) {
654
+ cancel("Cancelled.");
655
+ return null;
656
+ }
657
+ const groqApiKey = await text({
658
+ message: `GROQ_API_KEY for voice-note transcription (${noteEmpty})`,
659
+ placeholder: existing?.groqApiKey ? "(keep existing)" : "gsk_...",
660
+ initialValue: existing?.groqApiKey
661
+ });
662
+ if (isCancel(groqApiKey)) {
663
+ cancel("Cancelled.");
664
+ return null;
665
+ }
666
+ const embeddingEnabled = false;
667
+ const mask = (s) => s ? s.length > 8 ? `${s.slice(0, 4)}\u2026${s.slice(-4)}` : "***" : "(skipped)";
668
+ const lines = [
669
+ "",
670
+ "\u2500\u2500 Summary \u2500\u2500",
671
+ ` Deployment mode: ${installMode}`,
672
+ ` Your name: ${String(userName ?? "") || "(skipped)"}`,
673
+ ` Telegram token: ${mask(String(telegramToken ?? ""))}`,
674
+ ` Telegram chat ID: ${String(telegramChatId ?? "") || "(skipped)"}`,
675
+ ` Discord bot token: ${mask(String(discordBotToken ?? ""))}`,
676
+ ` Discord app ID: ${String(discordAppId ?? "") || "(skipped)"}`,
677
+ ` Discord channel ID: ${String(discordA2aChannel ?? "") || "(skipped)"}`,
678
+ ` Provider: ${defaultProvider}`,
679
+ ` Default model: ${modelStr}`,
680
+ ` ${apiKeyEnv}: ${mask(providerApiKey)}`,
681
+ ` hailMary model: ${hailMaryModel || "(skipped)"}`,
682
+ ` Bed time: ${String(bedTime ?? "") || "(default 0:30)"}`,
683
+ ` Wake time: ${String(wakeTime ?? "") || "(default 7:00)"}`,
684
+ ` GROQ_API_KEY: ${mask(String(groqApiKey ?? ""))}`,
685
+ ` Embeddings: ${embeddingEnabled ? "enabled" : "disabled"}`,
686
+ ` Trust mode: ${trustMode ? "true (auto-approve)" : "false (prompt user)"}`,
687
+ ""
688
+ ];
689
+ process.stdout.write(lines.join("\n"));
690
+ const ok = await confirm2({ message: "Looks good? Write config?", initialValue: true });
691
+ if (isCancel(ok) || !ok) {
692
+ cancel("Cancelled \u2014 no files written.");
693
+ return null;
694
+ }
695
+ outro("Writing config\u2026");
696
+ return {
697
+ installMode,
698
+ userName: String(userName ?? "").trim(),
699
+ passphrase: String(passphrase ?? ""),
700
+ telegramToken: String(telegramToken ?? "").trim(),
701
+ telegramChatId: String(telegramChatId ?? "").trim(),
702
+ discordBotToken: String(discordBotToken ?? "").trim(),
703
+ discordAppId: String(discordAppId ?? "").trim(),
704
+ discordA2aChannel: String(discordA2aChannel ?? "").trim(),
705
+ defaultProvider,
706
+ defaultModel: modelStr,
707
+ providerApiKey,
708
+ hailMaryModel,
709
+ bedTime: String(bedTime ?? "").trim(),
710
+ wakeTime: String(wakeTime ?? "").trim(),
711
+ groqApiKey: String(groqApiKey ?? "").trim() || existing?.groqApiKey || "",
712
+ embeddingEnabled: false,
713
+ securityMode: String(securityMode ?? "guardrails"),
714
+ trustMode: trustMode === true
715
+ };
716
+ }
717
+ async function checkModelAvailability(endpoint, apiKey, model) {
718
+ try {
719
+ const res = await fetch(`${endpoint}/models`, {
720
+ headers: { Authorization: `Bearer ${apiKey}` },
721
+ signal: AbortSignal.timeout(8e3)
722
+ });
723
+ if (!res.ok) return { ok: false, message: `provider returned ${res.status}` };
724
+ const json = await res.json();
725
+ const ids = (json.data ?? []).map((m) => m.id);
726
+ return ids.includes(model) ? { ok: true, message: "available" } : { ok: false, message: `"${model}" not found in provider's model list` };
727
+ } catch (err) {
728
+ return { ok: false, message: `check failed: ${err instanceof Error ? err.message : String(err)}` };
729
+ }
730
+ }
731
+ function validateNonInteractive(opts) {
732
+ if (!opts.acceptRisk) {
733
+ return "--non-interactive requires --accept-risk (you are bypassing safety prompts)";
734
+ }
735
+ const provider = opts.defaultProvider ?? "openrouter";
736
+ if (!VALID_PROVIDERS.includes(provider)) {
737
+ return `--default-provider must be one of: ${VALID_PROVIDERS.join(", ")}`;
738
+ }
739
+ return {
740
+ installMode: "supervised",
741
+ userName: "",
742
+ passphrase: "",
743
+ telegramToken: opts.telegramToken ?? "",
744
+ telegramChatId: opts.telegramChatId ?? "",
745
+ discordBotToken: "",
746
+ discordAppId: "",
747
+ discordA2aChannel: opts.discordA2aChannel ?? "",
748
+ defaultProvider: provider,
749
+ defaultModel: opts.defaultModel ?? DEFAULT_MODELS[provider],
750
+ providerApiKey: "",
751
+ hailMaryModel: "",
752
+ bedTime: "",
753
+ wakeTime: "",
754
+ groqApiKey: "",
755
+ embeddingEnabled: false,
756
+ securityMode: "guardrails",
757
+ trustMode: true
758
+ };
759
+ }
760
+ async function readExisting(envPath) {
761
+ try {
762
+ const content = await readFile(envPath, "utf-8");
763
+ const kv = /* @__PURE__ */ new Map();
764
+ for (const line of content.split("\n")) {
765
+ const m = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
766
+ if (m && m[1] !== void 0 && m[2] !== void 0) kv.set(m[1], m[2]);
767
+ }
768
+ const provider = kv.get("DEFAULT_PROVIDER") ?? "openrouter";
769
+ if (!VALID_PROVIDERS.includes(provider)) return null;
770
+ const apiKeyEnv = PROVIDER_API_KEY_ENV[provider];
771
+ return {
772
+ installMode: "simple",
773
+ userName: kv.get("USER_DISPLAY_NAME") ?? "",
774
+ passphrase: "",
775
+ telegramToken: kv.get("TELEGRAM_BOT_TOKEN") ?? "",
776
+ telegramChatId: kv.get("MAIN_CHAT_ID") ?? "",
777
+ discordBotToken: kv.get("DISCORD_BOT_TOKEN") ?? "",
778
+ discordAppId: kv.get("DISCORD_APP_ID") ?? "",
779
+ discordA2aChannel: kv.get("DISCORD_A2A_CHANNEL_ID") ?? "",
780
+ defaultProvider: provider,
781
+ defaultModel: kv.get("DEFAULT_MODEL") ?? DEFAULT_MODELS[provider],
782
+ providerApiKey: apiKeyEnv ? kv.get(apiKeyEnv) ?? "" : "",
783
+ hailMaryModel: "",
784
+ bedTime: kv.get("BED_TIME") ?? "",
785
+ wakeTime: kv.get("WAKE_TIME") ?? "",
786
+ groqApiKey: kv.get("GROQ_API_KEY") ?? "",
787
+ embeddingEnabled: kv.get("EMBEDDING_ENABLED") === "true",
788
+ securityMode: kv.get("SECURITY_MODE") ?? "guardrails",
789
+ trustMode: kv.get("TRUST_MODE") === "true"
790
+ };
791
+ } catch {
792
+ return null;
793
+ }
794
+ }
795
+ function mergeEnvContent(existing, answers) {
796
+ const owned = /* @__PURE__ */ new Set([
797
+ "MAIN_CHAT_ID",
798
+ "DISCORD_APP_ID",
799
+ "DISCORD_A2A_CHANNEL_ID",
800
+ "DEFAULT_PROVIDER",
801
+ "DEFAULT_MODEL",
802
+ "BED_TIME",
803
+ "WAKE_TIME",
804
+ "HEARTBEAT_INTERVAL_SEC",
805
+ "EMBEDDING_ENABLED",
806
+ "TRUST_MODE"
807
+ ]);
808
+ const keptLines = [];
809
+ for (const line of existing.split("\n")) {
810
+ const m = line.match(/^([A-Z_][A-Z0-9_]*)=/);
811
+ if (m && m[1] !== void 0 && owned.has(m[1])) continue;
812
+ keptLines.push(line);
813
+ }
814
+ while (keptLines.length > 0 && keptLines[keptLines.length - 1] === "") keptLines.pop();
815
+ const newBlock = [
816
+ "",
817
+ "# --- abtars onboard-managed ---",
818
+ `DEFAULT_PROVIDER=${answers.defaultProvider}`,
819
+ `DEFAULT_MODEL=${answers.defaultModel}`
820
+ ];
821
+ if (answers.telegramChatId) newBlock.push(`MAIN_CHAT_ID=${answers.telegramChatId}`);
822
+ else if (answers.discordA2aChannel) newBlock.push(`MAIN_CHAT_ID=${answers.discordA2aChannel}`);
823
+ if (answers.discordAppId) newBlock.push(`DISCORD_APP_ID=${answers.discordAppId}`);
824
+ if (answers.discordA2aChannel) newBlock.push(`DISCORD_A2A_CHANNEL_ID=${answers.discordA2aChannel}`);
825
+ if (answers.bedTime) newBlock.push(`BED_TIME=${answers.bedTime}`);
826
+ if (answers.wakeTime) newBlock.push(`WAKE_TIME=${answers.wakeTime}`);
827
+ newBlock.push(`HEARTBEAT_INTERVAL_SEC=300`);
828
+ newBlock.push(`EMBEDDING_ENABLED=${answers.embeddingEnabled ? "true" : "false"}`);
829
+ newBlock.push(`SECURITY_MODE=${answers.securityMode}`);
830
+ newBlock.push(`TRUST_MODE=${answers.trustMode ? "true" : "false"}`);
831
+ return [...keptLines, ...newBlock, ""].join("\n");
832
+ }
833
+ async function onboard(opts) {
834
+ const paths = packagePaths("abtars");
835
+ const { initInstallLog, logInstall, logInstallHeader } = await import("./install-log-IAPHYKD4.js");
836
+ initInstallLog(paths.home);
837
+ logInstallHeader("onboard");
838
+ const _origWrite = process.stdout.write.bind(process.stdout);
839
+ process.stdout.write = (chunk, ...args) => {
840
+ if (typeof chunk === "string" && (chunk.startsWith("\u2713") || chunk.startsWith("\u26A0") || chunk.startsWith("\u2022"))) logInstall(chunk.trimEnd());
841
+ return _origWrite(chunk, ...args);
842
+ };
843
+ const manifest = await readManifest(paths.manifest);
844
+ if (!manifest) {
845
+ process.stderr.write(
846
+ `Not installed yet. Run 'abtars install' first.
847
+ (Manifest not found at ${paths.manifest}.)
848
+ `
849
+ );
850
+ return 2;
851
+ }
852
+ const envPath = join5(paths.config, ".env");
853
+ const existing = await readExisting(envPath);
854
+ const secretDir = join5(paths.home, "secret");
855
+ const { existsSync: secretExists } = await import("node:fs");
856
+ const hasSecretToken = secretExists(join5(secretDir, "TELEGRAM_BOT_TOKEN")) || secretExists(join5(secretDir, "DISCORD_BOT_TOKEN"));
857
+ const hasUserConfig = existing !== null && (existing.telegramToken || existing.discordBotToken || hasSecretToken);
858
+ if (hasUserConfig && !opts.force) {
859
+ showHintOnce("onboard-reoffer", "Re-running onboard overwrites config. Use --force to confirm, or edit ~/.abtars/config/.env directly.");
860
+ if (opts.nonInteractive) {
861
+ process.stderr.write(`config/.env already configured. Re-run with --force to overwrite.
862
+ `);
863
+ return 3;
864
+ }
865
+ }
866
+ let answers;
867
+ if (opts.nonInteractive) {
868
+ const result = validateNonInteractive(opts);
869
+ if (typeof result === "string") {
870
+ process.stderr.write(`error: ${result}
871
+ `);
872
+ return 4;
873
+ }
874
+ answers = result;
875
+ } else {
876
+ answers = await runInteractive(existing);
877
+ if (answers === null) return 1;
878
+ }
879
+ let currentContent = "";
880
+ try {
881
+ currentContent = await readFile(envPath, "utf-8");
882
+ } catch {
883
+ currentContent = "";
884
+ }
885
+ const next = mergeEnvContent(currentContent, answers);
886
+ await writeFile(envPath, next, { mode: 384 });
887
+ process.stdout.write(`
888
+ \u2713 Wrote ${envPath}
889
+ `);
890
+ const secretDirPath = join5(paths.home, "secret");
891
+ await mkdir(secretDirPath, { recursive: true });
892
+ const secrets = [];
893
+ if (answers.telegramToken) secrets.push(["TELEGRAM_BOT_TOKEN", answers.telegramToken]);
894
+ if (answers.discordBotToken) secrets.push(["DISCORD_BOT_TOKEN", answers.discordBotToken]);
895
+ if (answers.providerApiKey) {
896
+ const providerKeyName = PROVIDER_API_KEY_ENV[answers.defaultProvider];
897
+ if (providerKeyName) secrets.push([providerKeyName, answers.providerApiKey]);
898
+ }
899
+ if (answers.groqApiKey) secrets.push(["GROQ_API_KEY", answers.groqApiKey]);
900
+ for (const [name, value] of secrets) {
901
+ await writeFile(join5(secretDirPath, name), value, { mode: 384 });
902
+ }
903
+ if (secrets.length > 0) process.stdout.write(`\u2713 ${secrets.length} secrets \u2192 ${secretDirPath}
904
+ `);
905
+ const { writeManifest: writeManifest2 } = await import("./deploy-lib-import-32ZFKHWP.js");
906
+ const mf = await readManifest(paths.manifest);
907
+ if (mf) await writeManifest2(paths.manifest, { ...mf, installMode: answers.installMode });
908
+ process.stdout.write(`\u2713 install mode: ${answers.installMode}
909
+ `);
910
+ {
911
+ const transportPath = join5(paths.config, "transport.json");
912
+ let tc = {};
913
+ try {
914
+ tc = JSON.parse(await readFile(transportPath, "utf-8"));
915
+ } catch (err) {
916
+ logAndSwallow("onboard", "op", err);
917
+ }
918
+ if (!tc["providers"]) {
919
+ tc["providers"] = {
920
+ "kiro": { "transport": "acp", "cli": "kiro-cli" },
921
+ "ollama": { "transport": "api", "endpoint": "http://localhost:11434/v1" },
922
+ "openrouter": { "transport": "api", "endpoint": "https://openrouter.ai/api/v1", "apiKeyEnv": "OPENROUTER_API_KEY" }
923
+ };
924
+ }
925
+ if (!tc["agents"]) {
926
+ const provName = PROVIDER_TRANSPORT_NAME[answers.defaultProvider] ?? answers.defaultProvider;
927
+ tc["agents"] = {
928
+ "professor": { "model": answers.defaultModel, "provider": provName },
929
+ "dreamy": { "model": answers.defaultModel, "provider": provName },
930
+ "browsie": { "model": answers.defaultModel, "provider": provName },
931
+ "coding": { "model": answers.defaultModel, "provider": provName }
932
+ };
933
+ }
934
+ if (answers.hailMaryModel) {
935
+ const provName = PROVIDER_TRANSPORT_NAME[answers.defaultProvider] ?? answers.defaultProvider;
936
+ tc["hailMary"] = { model: answers.hailMaryModel, provider: provName };
937
+ }
938
+ await writeFile(transportPath, JSON.stringify(tc, null, 2) + "\n", { mode: 384 });
939
+ process.stdout.write(`\u2713 transport.json \u2192 ${transportPath}
940
+ `);
941
+ }
942
+ {
943
+ const usersPath = join5(paths.config, "users.json");
944
+ const userId = answers.userName.toLowerCase().replace(/[^a-z0-9]/g, "") || "user";
945
+ const platforms = {};
946
+ if (answers.telegramChatId) platforms["telegram"] = parseInt(answers.telegramChatId, 10) || answers.telegramChatId;
947
+ if (answers.discordAppId) platforms["discord"] = answers.discordAppId;
948
+ const users = {
949
+ users: [{
950
+ userId,
951
+ displayName: answers.userName || userId,
952
+ role: "master",
953
+ maxClass: 3,
954
+ tools: ["all"],
955
+ platforms,
956
+ allowedChats: []
957
+ }]
958
+ };
959
+ await writeFile(usersPath, JSON.stringify(users, null, 2) + "\n", { mode: 384 });
960
+ process.stdout.write(`\u2713 users.json \u2192 ${usersPath}
961
+ `);
962
+ }
963
+ if (answers.userName) {
964
+ const abmindHome = process.env["ABMIND_HOME"] ?? join5(dirname2(paths.home), ".abmind");
965
+ const profileDir = join5(abmindHome, "memory", "core");
966
+ const { existsSync: profileExists } = await import("node:fs");
967
+ if (profileExists(profileDir)) {
968
+ const profilePath = join5(profileDir, "user_profile.md");
969
+ if (!profileExists(profilePath)) {
970
+ await writeFile(profilePath, `# User Profile
971
+
972
+ Name: ${answers.userName}
973
+ `, { mode: 384 });
974
+ process.stdout.write(`\u2713 user_profile.md \u2192 ${profilePath}
975
+ `);
976
+ }
977
+ }
978
+ }
979
+ if (answers.passphrase && answers.userName) {
980
+ try {
981
+ const { deriveFromPassphrase, writeKeyVerify } = await import("abmind");
982
+ const { writeToKeyring } = await import("abmind");
983
+ const key = deriveFromPassphrase(answers.passphrase, answers.userName);
984
+ writeKeyVerify(key);
985
+ const stored = writeToKeyring(answers.passphrase);
986
+ process.stdout.write(`\u2713 Encryption key derived from passphrase${stored ? " (stored in keyring)" : ""}
987
+ `);
988
+ } catch (err) {
989
+ process.stdout.write(`\u26A0 Key init failed: ${err instanceof Error ? err.message : String(err)}
990
+ `);
991
+ }
992
+ }
993
+ if (answers.telegramChatId) {
994
+ await seedDefaultTasks(answers.telegramChatId, paths.home);
995
+ }
996
+ const agentsDir = join5(paths.home, "agents");
997
+ const agentRulesPath = join5(agentsDir, "default.md");
998
+ const { existsSync: agentRulesExists } = await import("node:fs");
999
+ if (!agentRulesExists(agentRulesPath)) {
1000
+ await mkdir(agentsDir, { recursive: true });
1001
+ const bundledPath = join5(dirname2(fileURLToPath(import.meta.url)), "agents", "default.md");
1002
+ const fallbackPath = join5(dirname2(fileURLToPath(import.meta.url)), "..", "..", "agents", "default.md");
1003
+ let content = "# Agent-to-Agent API\n\n<!-- See docs for configuration -->\n";
1004
+ try {
1005
+ content = await readFile(bundledPath, "utf-8");
1006
+ } catch {
1007
+ try {
1008
+ content = await readFile(fallbackPath, "utf-8");
1009
+ } catch {
1010
+ }
1011
+ }
1012
+ await writeFile(agentRulesPath, content);
1013
+ process.stdout.write(`\u2713 agents/default.md \u2192 ${agentRulesPath}
1014
+ `);
1015
+ }
1016
+ process.stdout.write(`
1017
+ \u{1F4A1} To edit providers, agents, hailMary, fallback chains \u2014 edit:
1018
+ ${join5(paths.config, "transport.json")}
1019
+ Docs: https://aksika.github.io/abtars/
1020
+ `);
1021
+ if (opts.nonInteractive) {
1022
+ process.stdout.write(`
1023
+ Next: 'abtars update' to build, then start the bridge.
1024
+ `);
1025
+ return 0;
1026
+ }
1027
+ const { existsSync: existsSync4 } = await import("node:fs");
1028
+ const inRepo = existsSync4(join5(process.cwd(), ".git")) && existsSync4(join5(process.cwd(), "package.json"));
1029
+ if (!inRepo) {
1030
+ process.stdout.write(`
1031
+ Next: cd into the abtars repo and run 'abtars update' to build and activate.
1032
+ `);
1033
+ return 0;
1034
+ }
1035
+ process.stdout.write(`
1036
+ \u2500\u2500 Running 'abtars update' \u2500\u2500
1037
+ `);
1038
+ const { update: update2 } = await import("./update-QCW5LXRN.js");
1039
+ const updRc = await update2({ source: "local", fromLocal: true, allowAbmindMismatch: false });
1040
+ if (updRc !== 0) {
1041
+ process.stderr.write(`
1042
+ \u26A0\uFE0F 'abtars update' exited with code ${updRc}. Fix and re-run manually.
1043
+ `);
1044
+ return updRc;
1045
+ }
1046
+ try {
1047
+ const { spawnSync: spawnSync2 } = await import("node:child_process");
1048
+ const which = spawnSync2("which", ["abmind"], { encoding: "utf-8" });
1049
+ if (which.status === 0) {
1050
+ process.stdout.write(`
1051
+ \u2500\u2500 Running 'abmind install' \u2500\u2500
1052
+ `);
1053
+ const r = spawnSync2("abmind", ["install"], { stdio: "inherit" });
1054
+ if (r.status !== 0) process.stdout.write(`\u26A0 abmind install exited with code ${r.status}
1055
+ `);
1056
+ } else {
1057
+ process.stdout.write(`
1058
+ \u2139\uFE0F abmind not installed. Run 'npm install -g abmind && abmind install' later to enable persistent memory.
1059
+ `);
1060
+ }
1061
+ } catch {
1062
+ }
1063
+ const { confirm: confirm2 } = await import("./dist-MTMKARCP.js");
1064
+ const startCmds = [];
1065
+ if (answers.installMode === "simple") {
1066
+ startCmds.push("abtars start");
1067
+ } else {
1068
+ if (process.platform === "darwin") {
1069
+ startCmds.push(`launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.abtars.watchdog.plist`);
1070
+ } else if (process.platform === "linux") {
1071
+ startCmds.push(`systemctl --user daemon-reload`);
1072
+ startCmds.push(`systemctl --user enable --now abtars-watchdog`);
1073
+ }
1074
+ }
1075
+ process.stdout.write(`
1076
+ \u2500\u2500 Start the bridge \u2500\u2500
1077
+ `);
1078
+ const { spawn: spawn2 } = await import("node:child_process");
1079
+ if (startCmds.length > 0) {
1080
+ for (const cmd of startCmds) process.stdout.write(` \u2192 ${cmd}
1081
+ `);
1082
+ const run = await confirm2({ message: `Enable and start the watchdog service?`, initialValue: true });
1083
+ if (run === true) {
1084
+ for (const cmd of startCmds) {
1085
+ await new Promise((resolve) => {
1086
+ const child = spawn2("bash", ["-lc", cmd], { stdio: "inherit" });
1087
+ child.on("exit", () => resolve());
1088
+ });
1089
+ }
1090
+ } else {
1091
+ process.stdout.write(` \u2192 skipped (run manually)
1092
+ `);
1093
+ }
1094
+ }
1095
+ process.stdout.write(`
1096
+ \u2713 Onboarding complete.
1097
+ `);
1098
+ return 0;
1099
+ }
1100
+ async function seedDefaultTasks(chatId, abtarsHome4) {
1101
+ const { existsSync: existsSync4 } = await import("node:fs");
1102
+ const tasksJson = join5(abtarsHome4, "state", "tasks.json");
1103
+ if (existsSync4(tasksJson)) {
1104
+ process.stdout.write(`\u2022 tasks.json exists \u2014 skipping default-task seed
1105
+ `);
1106
+ return;
1107
+ }
1108
+ const { fileURLToPath: fileURLToPath2 } = await import("node:url");
1109
+ const here = dirname2(fileURLToPath2(import.meta.url));
1110
+ const candidates = [
1111
+ join5(here, "..", "..", "..", "tasks.default.json"),
1112
+ join5(here, "..", "..", "tasks.default.json")
1113
+ ];
1114
+ let templatePath = null;
1115
+ for (const p of candidates) {
1116
+ if (existsSync4(p)) {
1117
+ templatePath = p;
1118
+ break;
1119
+ }
1120
+ }
1121
+ if (!templatePath) {
1122
+ process.stdout.write(`\u2022 tasks.default.json not found \u2014 skipping default-task seed
1123
+ `);
1124
+ return;
1125
+ }
1126
+ let template;
1127
+ try {
1128
+ const raw = await readFile(templatePath, "utf-8");
1129
+ template = JSON.parse(raw);
1130
+ } catch (err) {
1131
+ process.stdout.write(`\u2022 Failed to read tasks.default.json: ${err instanceof Error ? err.message : String(err)}
1132
+ `);
1133
+ return;
1134
+ }
1135
+ const { spawnSync: spawnSync2 } = await import("node:child_process");
1136
+ let seeded = 0;
1137
+ for (const entry of template) {
1138
+ const args = [
1139
+ "add",
1140
+ "--schedule",
1141
+ entry.schedule,
1142
+ "--message",
1143
+ entry.message,
1144
+ "--chat-id",
1145
+ chatId,
1146
+ "--type",
1147
+ entry.type,
1148
+ "--executor",
1149
+ entry.executor
1150
+ ];
1151
+ if (entry.id) args.push("--id", entry.id);
1152
+ if (entry.title) args.push("--title", entry.title);
1153
+ if (entry.maxRunsPerDay) args.push("--max-runs-per-day", String(entry.maxRunsPerDay));
1154
+ const result = spawnSync2("abtars-task", args, {
1155
+ encoding: "utf-8",
1156
+ env: { ...process.env, ABTARS_HOME: abtarsHome4 }
1157
+ });
1158
+ if (result.status === 0) {
1159
+ seeded++;
1160
+ } else {
1161
+ const err = result.error?.message ?? result.stderr?.trim() ?? result.stdout?.trim() ?? `exit ${result.status}`;
1162
+ process.stdout.write(` \u26A0\uFE0F failed to seed task "${entry.message.slice(0, 40)}": ${err}
1163
+ `);
1164
+ }
1165
+ }
1166
+ if (seeded > 0) {
1167
+ process.stdout.write(`\u2713 seeded ${seeded} default task${seeded === 1 ? "" : "s"}
1168
+ `);
1169
+ }
1170
+ }
1171
+
1172
+ // src/cli/commands/rollback.ts
1173
+ import { hostname } from "node:os";
1174
+ async function rollback(opts) {
1175
+ const paths = packagePaths("abtars");
1176
+ const manifest = await readManifest(paths.manifest);
1177
+ if (!manifest || !manifest.version) {
1178
+ process.stderr.write(`No active release; nothing to roll back.
1179
+ `);
1180
+ return 2;
1181
+ }
1182
+ if (manifest.priorReleases.length === 0 && opts.to === void 0) {
1183
+ process.stderr.write(`No prior releases recorded; nothing to roll back to.
1184
+ `);
1185
+ return 2;
1186
+ }
1187
+ const target = opts.to ?? manifest.priorReleases[0].version;
1188
+ if (target === manifest.version) {
1189
+ process.stdout.write(`Already at ${target}; no-op.
1190
+ `);
1191
+ return 0;
1192
+ }
1193
+ if (!await releaseExists(paths.releases, target)) {
1194
+ const available = [manifest.version, ...manifest.priorReleases.map((r) => r.version)];
1195
+ process.stderr.write(
1196
+ `Target release '${target}' does not exist in ${paths.releases}.
1197
+ Available: ${available.join(", ")}
1198
+ If pruned, rebuild from the target's git SHA with 'abtars update' instead.
1199
+ `
1200
+ );
1201
+ return 2;
1202
+ }
1203
+ const targetRecord = target === manifest.version ? {
1204
+ version: manifest.version,
1205
+ commit: manifest.commit,
1206
+ activatedAt: manifest.activatedAt,
1207
+ packageLockHash: manifest.packageLockHash
1208
+ } : manifest.priorReleases.find((r) => r.version === target) ?? null;
1209
+ if (manifest.packageLockHash && targetRecord?.packageLockHash && manifest.packageLockHash !== targetRecord.packageLockHash) {
1210
+ process.stderr.write(
1211
+ `v${manifest.version} pinned different deps than v${target} (package-lock hashes differ).
1212
+ Rollback via symlink is unsafe. Instead:
1213
+ git checkout ${targetRecord.commit ?? "<commit-from-manifest>"}
1214
+ abtars update --from-local
1215
+ This rebuilds node_modules/ to match the target release.
1216
+ `
1217
+ );
1218
+ return 3;
1219
+ }
1220
+ const release = await acquireLock(paths.lock, `rollback --to ${target}`);
1221
+ try {
1222
+ await activate(paths.current, target);
1223
+ process.stdout.write(`\u2713 current -> releases/${target}
1224
+ `);
1225
+ const newPrior = {
1226
+ version: manifest.version,
1227
+ commit: manifest.commit,
1228
+ activatedAt: manifest.activatedAt,
1229
+ packageLockHash: manifest.packageLockHash
1230
+ };
1231
+ const remainingPriors = manifest.priorReleases.filter((r) => r.version !== target);
1232
+ await writeManifest(paths.manifest, {
1233
+ ...manifest,
1234
+ version: target,
1235
+ commit: targetRecord?.commit ?? null,
1236
+ packageLockHash: targetRecord?.packageLockHash ?? null,
1237
+ activatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1238
+ priorReleases: [newPrior, ...remainingPriors]
1239
+ });
1240
+ process.stdout.write(`\u2713 manifest updated
1241
+ `);
1242
+ process.stdout.write(`
1243
+ Rollback complete: ${target}
1244
+ `);
1245
+ void emptyManifest;
1246
+ void hostname;
1247
+ return 0;
1248
+ } finally {
1249
+ await release();
1250
+ }
1251
+ }
1252
+
1253
+ // src/cli/commands/status.ts
1254
+ async function status() {
1255
+ const paths = packagePaths("abtars");
1256
+ const manifest = await readManifest(paths.manifest);
1257
+ const current = await readCurrent(paths.current);
1258
+ const lock = await inspectLock(paths.lock);
1259
+ if (!manifest) {
1260
+ process.stdout.write(
1261
+ `abtars: not installed (no manifest at ${paths.manifest})
1262
+ Run 'abtars install' to set up.
1263
+ `
1264
+ );
1265
+ return 1;
1266
+ }
1267
+ const lines = [
1268
+ `abtars status`,
1269
+ ` home: ${paths.home}`,
1270
+ ` version: ${manifest.version || "(unset \u2014 run update)"}`,
1271
+ ` commit: ${manifest.commit ?? "(unknown)"}`,
1272
+ ` branch: ${manifest.branch ?? "(unknown)"}`,
1273
+ ` source: ${manifest.source}`,
1274
+ ` activated: ${manifest.activatedAt}`,
1275
+ ` current ->: ${current ?? "(missing)"}`,
1276
+ ` host: ${manifest.host}`,
1277
+ ` prior: ${manifest.priorReleases.length > 0 ? manifest.priorReleases.map((r) => r.version).join(", ") : "(none)"}`
1278
+ ];
1279
+ if (lock.held) {
1280
+ lines.push(
1281
+ ` lock: HELD by pid ${lock.content.pid} (${lock.content.cmd})${lock.stale ? " \u2014 STALE" : ""}`
1282
+ );
1283
+ } else {
1284
+ lines.push(` lock: not held`);
1285
+ }
1286
+ process.stdout.write(`${lines.join("\n")}
1287
+ `);
1288
+ if (current !== null && manifest.version !== "" && current !== manifest.version) {
1289
+ process.stderr.write(
1290
+ `
1291
+ Warning: current symlink points at '${current}' but manifest says '${manifest.version}'.
1292
+ Re-run 'abtars update' or 'abtars rollback' to reconcile.
1293
+ `
1294
+ );
1295
+ return 1;
1296
+ }
1297
+ return 0;
1298
+ }
1299
+
1300
+ // src/cli/abtars.ts
1301
+ process.umask(63);
1302
+ function parseArgs(argv) {
1303
+ const command = argv[0] ?? "";
1304
+ const flags = /* @__PURE__ */ new Map();
1305
+ for (let i = 1; i < argv.length; i++) {
1306
+ const a = argv[i];
1307
+ if (a === void 0) continue;
1308
+ if (a.startsWith("--")) {
1309
+ const eqIdx = a.indexOf("=");
1310
+ if (eqIdx > 2) {
1311
+ flags.set(a.slice(2, eqIdx), a.slice(eqIdx + 1));
1312
+ } else {
1313
+ const next = argv[i + 1];
1314
+ if (next !== void 0 && !next.startsWith("--")) {
1315
+ flags.set(a.slice(2), next);
1316
+ i++;
1317
+ } else {
1318
+ flags.set(a.slice(2), true);
1319
+ }
1320
+ }
1321
+ }
1322
+ }
1323
+ return { command, flags };
1324
+ }
1325
+ function printUsage() {
1326
+ process.stdout.write(
1327
+ `abtars \u2014 install/update CLI (#158)
1328
+
1329
+ Usage:
1330
+ abtars install [--force] [--mode=simple|supervised|supervised-daemon] [--restore <backup.zip>]
1331
+ abtars uninstall [--yes]
1332
+ abtars update [--source local|npm|github] [--from-local]
1333
+ abtars rollback [--to <version>]
1334
+ abtars backup
1335
+ abtars restore <file.zip|.7z>
1336
+ abtars doctor [<args passed to doctor.sh>...]
1337
+ abtars onboard [--non-interactive --accept-risk --telegram-token ... --telegram-chat-id ...]
1338
+ abtars restart [--cold]
1339
+ abtars start
1340
+ abtars stop [--force]
1341
+ abtars status
1342
+ abtars logs
1343
+ abtars config
1344
+ `
1345
+ );
1346
+ }
1347
+ async function main(argv) {
1348
+ const { command, flags } = parseArgs(argv);
1349
+ try {
1350
+ switch (command) {
1351
+ case "install":
1352
+ return await install({
1353
+ restore: typeof flags.get("restore") === "string" ? flags.get("restore") : void 0,
1354
+ force: flags.get("force") === true,
1355
+ dryRun: flags.get("dry-run") === true,
1356
+ mode: flags.get("mode") === "simple" ? "simple" : flags.get("mode") === "supervised" ? "supervised" : flags.get("mode") === "supervised-daemon" ? "supervised-daemon" : void 0
1357
+ });
1358
+ case "uninstall":
1359
+ return await uninstall({ yes: flags.get("yes") === true });
1360
+ case "update":
1361
+ return await update({
1362
+ source: flags.get("source") ?? "local",
1363
+ fromLocal: flags.get("from-local") === true,
1364
+ allowAbmindMismatch: flags.get("allow-abmind-mismatch") === true
1365
+ });
1366
+ case "rollback":
1367
+ return await rollback({
1368
+ to: typeof flags.get("to") === "string" ? flags.get("to") : void 0
1369
+ });
1370
+ case "backup":
1371
+ return await backup(typeof flags.get("output") === "string" ? flags.get("output") : void 0);
1372
+ case "restore": {
1373
+ const { restore } = await import("./restore-ZE3SEPSS.js");
1374
+ return await restore(argv[1] ?? "");
1375
+ }
1376
+ case "doctor":
1377
+ return await doctor(argv.slice(1).filter((a) => a !== ""));
1378
+ case "onboard":
1379
+ return await onboard({
1380
+ nonInteractive: flags.get("non-interactive") === true,
1381
+ acceptRisk: flags.get("accept-risk") === true,
1382
+ telegramToken: typeof flags.get("telegram-token") === "string" ? flags.get("telegram-token") : void 0,
1383
+ telegramChatId: typeof flags.get("telegram-chat-id") === "string" ? flags.get("telegram-chat-id") : void 0,
1384
+ defaultProvider: typeof flags.get("default-provider") === "string" ? flags.get("default-provider") : void 0,
1385
+ defaultModel: typeof flags.get("default-model") === "string" ? flags.get("default-model") : void 0,
1386
+ discordA2aChannel: typeof flags.get("discord-a2a-channel") === "string" ? flags.get("discord-a2a-channel") : void 0,
1387
+ force: flags.get("force") === true
1388
+ });
1389
+ case "status":
1390
+ return await status();
1391
+ case "restart":
1392
+ return await restart({ cold: flags.get("cold") === true });
1393
+ case "stop":
1394
+ return await stop({ force: flags.get("force") === true });
1395
+ case "start": {
1396
+ const { start: startCmd } = await import("./start-FH3GRMJ4.js");
1397
+ return await startCmd();
1398
+ }
1399
+ case "logs": {
1400
+ const { logs } = await import("./logs-ZNYXX5PA.js");
1401
+ return await logs();
1402
+ }
1403
+ case "config": {
1404
+ const { configShow } = await import("./config-show-ERTATR6E.js");
1405
+ return await configShow();
1406
+ }
1407
+ case "passwd": {
1408
+ const { passwd } = await import("./passwd-RRFV4CC5.js");
1409
+ return await passwd();
1410
+ }
1411
+ case "":
1412
+ case "help":
1413
+ case "--help":
1414
+ case "-h":
1415
+ printUsage();
1416
+ return 0;
1417
+ default:
1418
+ process.stderr.write(`unknown subcommand: ${command}
1419
+
1420
+ `);
1421
+ printUsage();
1422
+ return 2;
1423
+ }
1424
+ } catch (err) {
1425
+ const msg = err instanceof Error ? err.message : String(err);
1426
+ process.stderr.write(`error: ${msg}
1427
+ `);
1428
+ return 1;
1429
+ }
1430
+ }
1431
+ var isDirectRun = typeof process.argv[1] === "string" && (process.argv[1].endsWith("abtars.js") || process.argv[1].endsWith("abtars-cli.js") || process.argv[1].endsWith("abtars") || process.argv[1].endsWith("abtars.ts"));
1432
+ if (isDirectRun && process.env["VITEST"] === void 0) {
1433
+ void main(process.argv.slice(2)).then((code) => process.exit(code));
1434
+ }
1435
+ export {
1436
+ main
1437
+ };
1438
+ //# sourceMappingURL=abtars-cli.js.map