@openacp/cli 0.6.10 → 2026.326.3

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 (256) hide show
  1. package/dist/{action-detect-P7ZE4NEM.js → action-detect-QPA775HB.js} +2 -2
  2. package/dist/adapter-6ANPBSVU.js +16 -0
  3. package/dist/{discord-OMC52Y54.js → adapter-77ZCVABT.js} +520 -365
  4. package/dist/adapter-77ZCVABT.js.map +1 -0
  5. package/dist/{adapter-ZOANORGM.js → adapter-PQGHVG4K.js} +300 -93
  6. package/dist/adapter-PQGHVG4K.js.map +1 -0
  7. package/dist/{admin-6SYB6XCZ.js → admin-GBPZFFAU.js} +3 -3
  8. package/dist/agent-catalog-YHBFERYO.js +11 -0
  9. package/dist/{agent-dependencies-4OWBMZWZ.js → agent-dependencies-WS7Z2DFW.js} +2 -2
  10. package/dist/agent-registry-5LZT7CUB.js +9 -0
  11. package/dist/agent-store-VSHNY5GT.js +9 -0
  12. package/dist/{agents-QO7DKARJ.js → agents-BWU4MRRD.js} +3 -3
  13. package/dist/{api-client-CFQT5U7D.js → api-client-AQPNKXI2.js} +2 -2
  14. package/dist/api-server-3PYLRBCN.js +8 -0
  15. package/dist/api-server-CHVSUDBX.js +11 -0
  16. package/dist/{autostart-X33OGMX6.js → autostart-6JS565RY.js} +3 -3
  17. package/dist/chunk-2CX4IEEC.js +124 -0
  18. package/dist/chunk-2CX4IEEC.js.map +1 -0
  19. package/dist/{chunk-O7CPGUAI.js → chunk-4KGLKKQK.js} +4 -4
  20. package/dist/chunk-4KGLKKQK.js.map +1 -0
  21. package/dist/{chunk-W3EYKZNQ.js → chunk-4WXALZA3.js} +2 -2
  22. package/dist/chunk-4WXALZA3.js.map +1 -0
  23. package/dist/chunk-5OCGO27U.js +125 -0
  24. package/dist/chunk-5OCGO27U.js.map +1 -0
  25. package/dist/{chunk-OWP7RZ62.js → chunk-5ZOFBTOR.js} +118 -262
  26. package/dist/chunk-5ZOFBTOR.js.map +1 -0
  27. package/dist/chunk-6RXVEXF3.js +23 -0
  28. package/dist/chunk-6RXVEXF3.js.map +1 -0
  29. package/dist/{chunk-34M4OS5P.js → chunk-A6Y4GZM3.js} +3 -3
  30. package/dist/chunk-A6Y4GZM3.js.map +1 -0
  31. package/dist/chunk-AD3X6DGK.js +166 -0
  32. package/dist/chunk-AD3X6DGK.js.map +1 -0
  33. package/dist/{chunk-7QJS2XBD.js → chunk-AFKX424Q.js} +2 -2
  34. package/dist/chunk-AFKX424Q.js.map +1 -0
  35. package/dist/chunk-APS6UEFU.js +259 -0
  36. package/dist/chunk-APS6UEFU.js.map +1 -0
  37. package/dist/chunk-BLQUXO7S.js +113 -0
  38. package/dist/chunk-BLQUXO7S.js.map +1 -0
  39. package/dist/{chunk-WTZDAYZX.js → chunk-BQ6FR32N.js} +3 -3
  40. package/dist/chunk-BQ6FR32N.js.map +1 -0
  41. package/dist/chunk-FNRSWA2K.js +1 -0
  42. package/dist/chunk-FQEBWOZR.js +3557 -0
  43. package/dist/chunk-FQEBWOZR.js.map +1 -0
  44. package/dist/{chunk-4CTX774K.js → chunk-GJOY37U7.js} +4 -4
  45. package/dist/chunk-GJOY37U7.js.map +1 -0
  46. package/dist/{chunk-I7WC6E5S.js → chunk-HVBNCPAY.js} +2 -2
  47. package/dist/chunk-HVBNCPAY.js.map +1 -0
  48. package/dist/{chunk-2HMQOC7N.js → chunk-I3CGU5W7.js} +4 -4
  49. package/dist/chunk-I3CGU5W7.js.map +1 -0
  50. package/dist/{chunk-NVPG6JCL.js → chunk-L7YNNBI5.js} +3 -3
  51. package/dist/chunk-L7YNNBI5.js.map +1 -0
  52. package/dist/chunk-LGFWH3AE.js +26 -0
  53. package/dist/chunk-LGFWH3AE.js.map +1 -0
  54. package/dist/chunk-MLF4W5R6.js +101 -0
  55. package/dist/chunk-MLF4W5R6.js.map +1 -0
  56. package/dist/{chunk-KIRH7TUJ.js → chunk-MTSDOSXS.js} +3 -3
  57. package/dist/chunk-MTSDOSXS.js.map +1 -0
  58. package/dist/{chunk-J4SJTKIK.js → chunk-NAM4ERUW.js} +3 -3
  59. package/dist/chunk-NAM4ERUW.js.map +1 -0
  60. package/dist/{chunk-MKHUZLII.js → chunk-NBFIBGAT.js} +39 -25
  61. package/dist/chunk-NBFIBGAT.js.map +1 -0
  62. package/dist/{chunk-BNLGTZ34.js → chunk-O5RG4YZY.js} +3 -3
  63. package/dist/chunk-O5RG4YZY.js.map +1 -0
  64. package/dist/{chunk-JHYXKVV2.js → chunk-ODUM3D6X.js} +2 -2
  65. package/dist/chunk-ODUM3D6X.js.map +1 -0
  66. package/dist/chunk-OYSAN7UX.js +15 -0
  67. package/dist/chunk-OYSAN7UX.js.map +1 -0
  68. package/dist/chunk-P4SNGQNI.js +158 -0
  69. package/dist/chunk-P4SNGQNI.js.map +1 -0
  70. package/dist/{chunk-2CJ46J3C.js → chunk-PPSMUECX.js} +3 -3
  71. package/dist/chunk-PPSMUECX.js.map +1 -0
  72. package/dist/chunk-Q6ZXJTZB.js +56 -0
  73. package/dist/chunk-Q6ZXJTZB.js.map +1 -0
  74. package/dist/{chunk-XANPHG7W.js → chunk-QSDZDHNS.js} +7 -7
  75. package/dist/chunk-QSDZDHNS.js.map +1 -0
  76. package/dist/{chunk-33RP6K2O.js → chunk-QVMEF6FB.js} +6 -6
  77. package/dist/chunk-QVMEF6FB.js.map +1 -0
  78. package/dist/chunk-QWP76EBW.js +536 -0
  79. package/dist/chunk-QWP76EBW.js.map +1 -0
  80. package/dist/{chunk-V5GZQEIY.js → chunk-RBYBSSGO.js} +4 -4
  81. package/dist/chunk-RBYBSSGO.js.map +1 -0
  82. package/dist/{chunk-CS3KCJ5D.js → chunk-RKB2ZK6S.js} +555 -383
  83. package/dist/chunk-RKB2ZK6S.js.map +1 -0
  84. package/dist/{chunk-UKT3G5IA.js → chunk-SHTGQGAU.js} +7 -7
  85. package/dist/chunk-SHTGQGAU.js.map +1 -0
  86. package/dist/chunk-SNPYTMPR.js +51 -0
  87. package/dist/chunk-SNPYTMPR.js.map +1 -0
  88. package/dist/chunk-UB2QB6DE.js +124 -0
  89. package/dist/chunk-UB2QB6DE.js.map +1 -0
  90. package/dist/chunk-UNJUWWQO.js +1108 -0
  91. package/dist/chunk-UNJUWWQO.js.map +1 -0
  92. package/dist/chunk-V2M243KZ.js +445 -0
  93. package/dist/chunk-V2M243KZ.js.map +1 -0
  94. package/dist/chunk-V5JT5TPD.js +97 -0
  95. package/dist/chunk-V5JT5TPD.js.map +1 -0
  96. package/dist/chunk-W26AUH5B.js +61 -0
  97. package/dist/chunk-W26AUH5B.js.map +1 -0
  98. package/dist/chunk-WAAD23KY.js +222 -0
  99. package/dist/chunk-WAAD23KY.js.map +1 -0
  100. package/dist/chunk-WIIZNPCR.js +150 -0
  101. package/dist/chunk-WIIZNPCR.js.map +1 -0
  102. package/dist/chunk-WQCJTU2C.js +84 -0
  103. package/dist/chunk-WQCJTU2C.js.map +1 -0
  104. package/dist/chunk-WVLDNYOJ.js +150 -0
  105. package/dist/chunk-WVLDNYOJ.js.map +1 -0
  106. package/dist/chunk-WXVT3AOY.js +22 -0
  107. package/dist/chunk-WXVT3AOY.js.map +1 -0
  108. package/dist/{chunk-GAK6PIBW.js → chunk-XMMAGAT4.js} +2 -2
  109. package/dist/chunk-XMMAGAT4.js.map +1 -0
  110. package/dist/chunk-Y64XWMJ4.js +212 -0
  111. package/dist/chunk-Y64XWMJ4.js.map +1 -0
  112. package/dist/chunk-YEULD3SG.js +62 -0
  113. package/dist/chunk-YEULD3SG.js.map +1 -0
  114. package/dist/chunk-ZHGPZBS4.js +49 -0
  115. package/dist/chunk-ZHGPZBS4.js.map +1 -0
  116. package/dist/{chunk-JKBFUAJK.js → chunk-ZSLHHQPQ.js} +2 -2
  117. package/dist/chunk-ZSLHHQPQ.js.map +1 -0
  118. package/dist/cli.js +496 -150
  119. package/dist/cli.js.map +1 -1
  120. package/dist/{config-6S355X75.js → config-I4FMCJGZ.js} +3 -3
  121. package/dist/config-editor-HNEKXRLQ.js +11 -0
  122. package/dist/{config-registry-AHYI4MYL.js → config-registry-CUMNXFGK.js} +2 -2
  123. package/dist/context-XM6E22LM.js +10 -0
  124. package/dist/core-plugins-VEUNFTMB.js +27 -0
  125. package/dist/{daemon-4CS6HMB5.js → daemon-PXO5QPCR.js} +4 -4
  126. package/dist/dev-loader-RDC5E2CW.js +50 -0
  127. package/dist/dev-loader-RDC5E2CW.js.map +1 -0
  128. package/dist/discord-NOJQ5PZO.js +8 -0
  129. package/dist/doctor-H72BZOPA.js +10 -0
  130. package/dist/{doctor-OLYBO3V3.js → doctor-RF6BHMCC.js} +5 -5
  131. package/dist/file-service-EUODJAIT.js +9 -0
  132. package/dist/file-service-EUODJAIT.js.map +1 -0
  133. package/dist/index.d.ts +1293 -188
  134. package/dist/index.js +387 -48
  135. package/dist/index.js.map +1 -1
  136. package/dist/{install-cloudflared-Z7VCGOVG.js → install-cloudflared-AN24L4DP.js} +5 -5
  137. package/dist/install-cloudflared-AN24L4DP.js.map +1 -0
  138. package/dist/install-context-XPWTFT3J.js +78 -0
  139. package/dist/install-context-XPWTFT3J.js.map +1 -0
  140. package/dist/{install-jq-HUYSQWKR.js → install-jq-CRVDJGF3.js} +5 -5
  141. package/dist/install-jq-CRVDJGF3.js.map +1 -0
  142. package/dist/{integrate-PNEHRY2I.js → integrate-5C6KSU6D.js} +2 -2
  143. package/dist/integrate-5C6KSU6D.js.map +1 -0
  144. package/dist/{log-NXABYJTT.js → log-LZ7FTRKG.js} +2 -2
  145. package/dist/log-LZ7FTRKG.js.map +1 -0
  146. package/dist/main-T5WVCCFN.js +715 -0
  147. package/dist/main-T5WVCCFN.js.map +1 -0
  148. package/dist/{menu-YY5MKHEK.js → menu-YDQ2LWAR.js} +2 -2
  149. package/dist/menu-YDQ2LWAR.js.map +1 -0
  150. package/dist/{new-session-FEO4J4VU.js → new-session-AVQCNXRG.js} +5 -5
  151. package/dist/new-session-AVQCNXRG.js.map +1 -0
  152. package/dist/notifications-D5BRDNSU.js +9 -0
  153. package/dist/notifications-D5BRDNSU.js.map +1 -0
  154. package/dist/plugin-create-LYF5PP5W.js +327 -0
  155. package/dist/plugin-create-LYF5PP5W.js.map +1 -0
  156. package/dist/plugin-registry-WB3DR67H.js +8 -0
  157. package/dist/plugin-registry-WB3DR67H.js.map +1 -0
  158. package/dist/{post-upgrade-CJG5I7M2.js → post-upgrade-XLHZ6ZB7.js} +8 -8
  159. package/dist/post-upgrade-XLHZ6ZB7.js.map +1 -0
  160. package/dist/read-text-file-IRZM3QLM.js +8 -0
  161. package/dist/read-text-file-IRZM3QLM.js.map +1 -0
  162. package/dist/security-YNRBW6S7.js +9 -0
  163. package/dist/security-YNRBW6S7.js.map +1 -0
  164. package/dist/{session-IUSI7P5S.js → session-KZFA6Z26.js} +4 -4
  165. package/dist/session-KZFA6Z26.js.map +1 -0
  166. package/dist/{settings-RQPAM4KC.js → settings-MFYM7CZO.js} +4 -4
  167. package/dist/settings-MFYM7CZO.js.map +1 -0
  168. package/dist/settings-manager-MD2U4ZV2.js +8 -0
  169. package/dist/settings-manager-MD2U4ZV2.js.map +1 -0
  170. package/dist/{chunk-LCRLAV4G.js → setup-BAI2F24H.js} +154 -492
  171. package/dist/setup-BAI2F24H.js.map +1 -0
  172. package/dist/slack-KH7E3VBS.js +8 -0
  173. package/dist/slack-KH7E3VBS.js.map +1 -0
  174. package/dist/speech-2GHQNRIO.js +9 -0
  175. package/dist/speech-2GHQNRIO.js.map +1 -0
  176. package/dist/telegram-ZDC3JQF2.js +8 -0
  177. package/dist/telegram-ZDC3JQF2.js.map +1 -0
  178. package/dist/tunnel-M47I7H4B.js +8 -0
  179. package/dist/tunnel-M47I7H4B.js.map +1 -0
  180. package/dist/{tunnel-service-CJLUH6SZ.js → tunnel-service-WADYHREX.js} +17 -17
  181. package/dist/tunnel-service-WADYHREX.js.map +1 -0
  182. package/dist/usage-WYNK6ZC5.js +10 -0
  183. package/dist/usage-WYNK6ZC5.js.map +1 -0
  184. package/dist/validators-6CLEZUBD.js +8 -0
  185. package/dist/validators-6CLEZUBD.js.map +1 -0
  186. package/dist/validators-WSTBNKRW.js +12 -0
  187. package/dist/validators-WSTBNKRW.js.map +1 -0
  188. package/package.json +1 -1
  189. package/dist/adapter-ZOANORGM.js.map +0 -1
  190. package/dist/agent-catalog-FC3HGDEQ.js +0 -11
  191. package/dist/agent-registry-WT4NXPYG.js +0 -9
  192. package/dist/agent-store-VZLFPTZU.js +0 -9
  193. package/dist/chunk-2CJ46J3C.js.map +0 -1
  194. package/dist/chunk-2HMQOC7N.js.map +0 -1
  195. package/dist/chunk-33RP6K2O.js.map +0 -1
  196. package/dist/chunk-34M4OS5P.js.map +0 -1
  197. package/dist/chunk-4CTX774K.js.map +0 -1
  198. package/dist/chunk-7QJS2XBD.js.map +0 -1
  199. package/dist/chunk-BNLGTZ34.js.map +0 -1
  200. package/dist/chunk-CS3KCJ5D.js.map +0 -1
  201. package/dist/chunk-GAK6PIBW.js.map +0 -1
  202. package/dist/chunk-I7WC6E5S.js.map +0 -1
  203. package/dist/chunk-J4SJTKIK.js.map +0 -1
  204. package/dist/chunk-JHYXKVV2.js.map +0 -1
  205. package/dist/chunk-JKBFUAJK.js.map +0 -1
  206. package/dist/chunk-KIRH7TUJ.js.map +0 -1
  207. package/dist/chunk-LBIKITQT.js +0 -22
  208. package/dist/chunk-LBIKITQT.js.map +0 -1
  209. package/dist/chunk-LCRLAV4G.js.map +0 -1
  210. package/dist/chunk-LGP2YGRL.js +0 -4880
  211. package/dist/chunk-LGP2YGRL.js.map +0 -1
  212. package/dist/chunk-MKHUZLII.js.map +0 -1
  213. package/dist/chunk-NAMYZIS5.js +0 -1
  214. package/dist/chunk-NVPG6JCL.js.map +0 -1
  215. package/dist/chunk-O7CPGUAI.js.map +0 -1
  216. package/dist/chunk-OWP7RZ62.js.map +0 -1
  217. package/dist/chunk-UKT3G5IA.js.map +0 -1
  218. package/dist/chunk-V5GZQEIY.js.map +0 -1
  219. package/dist/chunk-VOIJ6OY4.js +0 -63
  220. package/dist/chunk-VOIJ6OY4.js.map +0 -1
  221. package/dist/chunk-W3EYKZNQ.js.map +0 -1
  222. package/dist/chunk-WTZDAYZX.js.map +0 -1
  223. package/dist/chunk-XANPHG7W.js.map +0 -1
  224. package/dist/config-editor-QQTZMWGD.js +0 -13
  225. package/dist/discord-OMC52Y54.js.map +0 -1
  226. package/dist/doctor-HZZ5BSHB.js +0 -10
  227. package/dist/install-cloudflared-Z7VCGOVG.js.map +0 -1
  228. package/dist/install-jq-HUYSQWKR.js.map +0 -1
  229. package/dist/integrate-PNEHRY2I.js.map +0 -1
  230. package/dist/main-XOZCLFUK.js +0 -238
  231. package/dist/main-XOZCLFUK.js.map +0 -1
  232. package/dist/post-upgrade-CJG5I7M2.js.map +0 -1
  233. package/dist/setup-XHS4OMPM.js +0 -37
  234. package/dist/tunnel-service-CJLUH6SZ.js.map +0 -1
  235. /package/dist/{action-detect-P7ZE4NEM.js.map → action-detect-QPA775HB.js.map} +0 -0
  236. /package/dist/{admin-6SYB6XCZ.js.map → adapter-6ANPBSVU.js.map} +0 -0
  237. /package/dist/{agent-catalog-FC3HGDEQ.js.map → admin-GBPZFFAU.js.map} +0 -0
  238. /package/dist/{agent-dependencies-4OWBMZWZ.js.map → agent-catalog-YHBFERYO.js.map} +0 -0
  239. /package/dist/{agent-registry-WT4NXPYG.js.map → agent-dependencies-WS7Z2DFW.js.map} +0 -0
  240. /package/dist/{agent-store-VZLFPTZU.js.map → agent-registry-5LZT7CUB.js.map} +0 -0
  241. /package/dist/{agents-QO7DKARJ.js.map → agent-store-VSHNY5GT.js.map} +0 -0
  242. /package/dist/{api-client-CFQT5U7D.js.map → agents-BWU4MRRD.js.map} +0 -0
  243. /package/dist/{autostart-X33OGMX6.js.map → api-client-AQPNKXI2.js.map} +0 -0
  244. /package/dist/{chunk-NAMYZIS5.js.map → api-server-3PYLRBCN.js.map} +0 -0
  245. /package/dist/{config-6S355X75.js.map → api-server-CHVSUDBX.js.map} +0 -0
  246. /package/dist/{config-editor-QQTZMWGD.js.map → autostart-6JS565RY.js.map} +0 -0
  247. /package/dist/{config-registry-AHYI4MYL.js.map → chunk-FNRSWA2K.js.map} +0 -0
  248. /package/dist/{daemon-4CS6HMB5.js.map → config-I4FMCJGZ.js.map} +0 -0
  249. /package/dist/{doctor-HZZ5BSHB.js.map → config-editor-HNEKXRLQ.js.map} +0 -0
  250. /package/dist/{doctor-OLYBO3V3.js.map → config-registry-CUMNXFGK.js.map} +0 -0
  251. /package/dist/{log-NXABYJTT.js.map → context-XM6E22LM.js.map} +0 -0
  252. /package/dist/{menu-YY5MKHEK.js.map → core-plugins-VEUNFTMB.js.map} +0 -0
  253. /package/dist/{new-session-FEO4J4VU.js.map → daemon-PXO5QPCR.js.map} +0 -0
  254. /package/dist/{session-IUSI7P5S.js.map → discord-NOJQ5PZO.js.map} +0 -0
  255. /package/dist/{settings-RQPAM4KC.js.map → doctor-H72BZOPA.js.map} +0 -0
  256. /package/dist/{setup-XHS4OMPM.js.map → doctor-RF6BHMCC.js.map} +0 -0
@@ -1,238 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- TelegramAdapter
4
- } from "./chunk-CS3KCJ5D.js";
5
- import "./chunk-OWP7RZ62.js";
6
- import {
7
- ApiServer,
8
- OpenACPCore,
9
- TopicManager
10
- } from "./chunk-LGP2YGRL.js";
11
- import "./chunk-LBIKITQT.js";
12
- import "./chunk-NVPG6JCL.js";
13
- import "./chunk-NAMYZIS5.js";
14
- import "./chunk-7QJS2XBD.js";
15
- import "./chunk-WTZDAYZX.js";
16
- import "./chunk-UKT3G5IA.js";
17
- import "./chunk-34M4OS5P.js";
18
- import "./chunk-MKHUZLII.js";
19
- import "./chunk-2CJ46J3C.js";
20
- import "./chunk-LCRLAV4G.js";
21
- import "./chunk-JKBFUAJK.js";
22
- import {
23
- loadAdapterFactory
24
- } from "./chunk-VOIJ6OY4.js";
25
- import "./chunk-JHYXKVV2.js";
26
- import {
27
- ConfigManager
28
- } from "./chunk-33RP6K2O.js";
29
- import {
30
- cleanupOldSessionLogs,
31
- initLogger,
32
- log,
33
- muteLogger,
34
- shutdownLogger,
35
- unmuteLogger
36
- } from "./chunk-GAK6PIBW.js";
37
- import "./chunk-VUNV25KB.js";
38
-
39
- // src/main.ts
40
- var RESTART_EXIT_CODE = 75;
41
- var shuttingDown = false;
42
- async function startServer() {
43
- if (process.argv.includes("--daemon-child")) {
44
- const { writePidFile, readPidFile, getPidPath, shouldAutoStart } = await import("./daemon-4CS6HMB5.js");
45
- if (!shouldAutoStart()) {
46
- process.exit(0);
47
- }
48
- const pidPath = getPidPath();
49
- const existingPid = readPidFile(pidPath);
50
- if (existingPid !== null && existingPid !== process.pid) {
51
- try {
52
- process.kill(existingPid, 0);
53
- console.error(`Another OpenACP instance is already running (PID ${existingPid}). Exiting.`);
54
- process.exit(1);
55
- } catch {
56
- }
57
- }
58
- writePidFile(pidPath, process.pid);
59
- }
60
- const configManager = new ConfigManager();
61
- const configExists = await configManager.exists();
62
- if (!configExists) {
63
- const { runSetup } = await import("./setup-XHS4OMPM.js");
64
- const shouldStart = await runSetup(configManager);
65
- if (!shouldStart) process.exit(0);
66
- }
67
- await configManager.load();
68
- const config = configManager.get();
69
- initLogger(config.logging);
70
- log.debug({ configPath: configManager.getConfigPath() }, "Config loaded");
71
- const isForegroundTTY = !!(process.stdout.isTTY && !process.env.NO_COLOR && config.runMode !== "daemon");
72
- if (isForegroundTTY) {
73
- const { printStartBanner } = await import("./setup-XHS4OMPM.js");
74
- await printStartBanner();
75
- }
76
- let spinner;
77
- if (isForegroundTTY) {
78
- muteLogger();
79
- const ora = (await import("ora")).default;
80
- spinner = ora({ text: "Starting OpenACP...", spinner: "dots" }).start();
81
- }
82
- try {
83
- const { runPostUpgradeChecks } = await import("./post-upgrade-CJG5I7M2.js");
84
- await runPostUpgradeChecks(config);
85
- } catch (err) {
86
- log.warn({ err }, "Post-upgrade check failed");
87
- }
88
- cleanupOldSessionLogs(config.logging.sessionLogRetentionDays).catch(
89
- (err) => log.warn({ err }, "Session log cleanup failed")
90
- );
91
- const core = new OpenACPCore(configManager);
92
- let tunnelService;
93
- if (config.tunnel.enabled) {
94
- const { TunnelService } = await import("./tunnel-service-CJLUH6SZ.js");
95
- tunnelService = new TunnelService(config.tunnel);
96
- const publicUrl = await tunnelService.start();
97
- core.tunnelService = tunnelService;
98
- log.info({ publicUrl }, "Tunnel started");
99
- }
100
- for (const [channelName, channelConfig] of Object.entries(config.channels)) {
101
- if (!channelConfig.enabled) continue;
102
- if (channelName === "telegram") {
103
- core.registerAdapter("telegram", new TelegramAdapter(core, channelConfig));
104
- log.info({ adapter: "telegram" }, "Adapter registered");
105
- } else if (channelName === "slack") {
106
- const { SlackAdapter } = await import("./adapter-ZOANORGM.js");
107
- const slackConfig = channelConfig;
108
- core.registerAdapter("slack", new SlackAdapter(core, slackConfig));
109
- log.info({ adapter: "slack" }, "Adapter registered");
110
- } else if (channelName === "discord") {
111
- const { DiscordAdapter } = await import("./discord-OMC52Y54.js");
112
- const discordConfig = channelConfig;
113
- core.registerAdapter("discord", new DiscordAdapter(core, discordConfig));
114
- log.info({ adapter: "discord" }, "Adapter registered");
115
- } else if (channelConfig.adapter) {
116
- const factory = await loadAdapterFactory(channelConfig.adapter);
117
- if (factory) {
118
- const adapter = factory.createAdapter(core, channelConfig);
119
- core.registerAdapter(channelName, adapter);
120
- log.info({ adapter: channelName, plugin: channelConfig.adapter }, "Adapter registered");
121
- } else {
122
- const name = channelName;
123
- const err = channelConfig.adapter;
124
- log.error({ adapter: name, err }, "Failed to load adapter");
125
- }
126
- } else {
127
- log.error({ adapter: channelName }, 'Channel has no built-in adapter; set "adapter" field to a plugin package');
128
- }
129
- }
130
- if (core.adapters.size === 0) {
131
- log.error("No channels enabled. Enable at least one channel in config.");
132
- process.exit(1);
133
- }
134
- let apiServer;
135
- const shutdown = async (signal, exitCode = 0) => {
136
- if (shuttingDown) return;
137
- shuttingDown = true;
138
- log.info({ signal, exitCode }, "Signal received, shutting down");
139
- try {
140
- if (apiServer) await apiServer.stop();
141
- await core.stop();
142
- if (tunnelService) await tunnelService.stop();
143
- } catch (err) {
144
- log.error({ err }, "Error during shutdown");
145
- }
146
- const isDaemon = process.argv.includes("--daemon-child");
147
- if (isDaemon) {
148
- const { removePidFile, getPidPath } = await import("./daemon-4CS6HMB5.js");
149
- removePidFile(getPidPath());
150
- }
151
- if (exitCode === RESTART_EXIT_CODE) {
152
- if (isDaemon) {
153
- const { spawn: spawnChild } = await import("child_process");
154
- const { expandHome } = await import("./config-6S355X75.js");
155
- const fs = await import("fs");
156
- const pathMod = await import("path");
157
- const cliPath = pathMod.resolve(process.argv[1]);
158
- const resolvedLogDir = expandHome(config.logging.logDir);
159
- fs.mkdirSync(resolvedLogDir, { recursive: true });
160
- const logFile = pathMod.join(resolvedLogDir, "openacp.log");
161
- const out = fs.openSync(logFile, "a");
162
- const err = fs.openSync(logFile, "a");
163
- const child = spawnChild(process.execPath, [cliPath, "--daemon-child"], {
164
- detached: true,
165
- stdio: ["ignore", out, err],
166
- env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: "1" }
167
- });
168
- fs.closeSync(out);
169
- fs.closeSync(err);
170
- child.unref();
171
- log.info({ newPid: child.pid }, "Respawned daemon for restart");
172
- } else if (!process.env.OPENACP_DEV_LOOP) {
173
- const { spawn: spawnChild } = await import("child_process");
174
- const child = spawnChild(process.execPath, process.argv.slice(1), {
175
- stdio: "inherit",
176
- env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: "1" }
177
- });
178
- await shutdownLogger();
179
- child.on("exit", (code) => process.exit(code ?? 0));
180
- return;
181
- }
182
- }
183
- await shutdownLogger();
184
- process.exit(exitCode);
185
- };
186
- core.requestRestart = () => shutdown("restart", RESTART_EXIT_CODE);
187
- process.on("SIGINT", () => shutdown("SIGINT"));
188
- process.on("SIGTERM", () => shutdown("SIGTERM"));
189
- process.on("uncaughtException", (err) => {
190
- log.error({ err }, "Uncaught exception");
191
- });
192
- process.on("unhandledRejection", (err) => {
193
- log.error({ err }, "Unhandled rejection");
194
- });
195
- await core.start();
196
- const updatedConfig = core.configManager.get();
197
- const telegramAdapter = core.adapters.get("telegram") ?? null;
198
- let topicManager;
199
- if (telegramAdapter) {
200
- const telegramCfg = updatedConfig.channels?.telegram;
201
- topicManager = new TopicManager(
202
- core.sessionManager,
203
- telegramAdapter,
204
- {
205
- notificationTopicId: telegramCfg?.notificationTopicId ?? null,
206
- assistantTopicId: telegramCfg?.assistantTopicId ?? null
207
- }
208
- );
209
- }
210
- apiServer = new ApiServer(core, config.api, void 0, topicManager);
211
- await apiServer.start();
212
- if (isForegroundTTY) {
213
- if (spinner) spinner.stop();
214
- const ok = (msg) => console.log(`\x1B[32m\u2713\x1B[0m ${msg}`);
215
- ok("Config loaded");
216
- ok("Dependencies checked");
217
- if (tunnelService) ok(`Tunnel ready \u2192 ${tunnelService.getPublicUrl()}`);
218
- for (const [name] of core.adapters) ok(`${name.charAt(0).toUpperCase() + name.slice(1)} connected`);
219
- if (apiServer) ok(`API server on port ${config.api.port}`);
220
- console.log(`
221
- OpenACP is running. Press Ctrl+C to stop.
222
- `);
223
- unmuteLogger();
224
- }
225
- log.debug({ agents: Object.keys(config.agents) }, "OpenACP started");
226
- }
227
- var isDirectExecution = process.argv[1]?.endsWith("main.js");
228
- if (isDirectExecution) {
229
- startServer().catch((err) => {
230
- log.error({ err }, "Fatal error");
231
- process.exit(1);
232
- });
233
- }
234
- export {
235
- RESTART_EXIT_CODE,
236
- startServer
237
- };
238
- //# sourceMappingURL=main-XOZCLFUK.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ConfigManager } from './core/config.js'\nimport { OpenACPCore } from './core/core.js'\nimport { loadAdapterFactory } from './core/plugin-manager.js'\nimport { initLogger, shutdownLogger, cleanupOldSessionLogs, log, muteLogger, unmuteLogger } from './core/log.js'\nimport { TelegramAdapter } from './adapters/telegram/index.js'\nimport type { TelegramChannelConfig } from './adapters/telegram/index.js'\nimport { ApiServer } from './core/api-server.js'\nimport { TopicManager } from './core/topic-manager.js'\n\nexport const RESTART_EXIT_CODE = 75\nlet shuttingDown = false\n\nexport async function startServer() {\n // 0. If running as daemon child, check state and write PID file\n if (process.argv.includes('--daemon-child')) {\n const { writePidFile, readPidFile, getPidPath, shouldAutoStart } = await import('./core/daemon.js')\n\n // Only auto-start if the daemon was previously running (user started it)\n if (!shouldAutoStart()) {\n process.exit(0)\n }\n\n const pidPath = getPidPath()\n const existingPid = readPidFile(pidPath)\n if (existingPid !== null && existingPid !== process.pid) {\n try {\n process.kill(existingPid, 0)\n console.error(`Another OpenACP instance is already running (PID ${existingPid}). Exiting.`)\n process.exit(1)\n } catch {\n // Stale PID file — safe to overwrite\n }\n }\n writePidFile(pidPath, process.pid)\n }\n\n // 1. Check config exists, run setup if not\n const configManager = new ConfigManager()\n const configExists = await configManager.exists()\n\n if (!configExists) {\n const { runSetup } = await import('./core/setup/index.js')\n const shouldStart = await runSetup(configManager)\n if (!shouldStart) process.exit(0)\n }\n\n // 2. Load config (validates with Zod)\n await configManager.load()\n const config = configManager.get()\n initLogger(config.logging)\n log.debug({ configPath: configManager.getConfigPath() }, 'Config loaded')\n\n // Show banner in foreground TTY mode (not daemon, not piped)\n const isForegroundTTY = !!(process.stdout.isTTY && !process.env.NO_COLOR && config.runMode !== 'daemon')\n if (isForegroundTTY) {\n const { printStartBanner } = await import('./core/setup/index.js')\n await printStartBanner()\n }\n\n // Mute pino during startup, show spinner instead\n let spinner: ReturnType<typeof import('ora').default> | undefined\n if (isForegroundTTY) {\n muteLogger()\n const ora = (await import('ora')).default\n spinner = ora({ text: 'Starting OpenACP...', spinner: 'dots' }).start()\n }\n\n // Post-upgrade dependency check (blocking — must complete before server start)\n try {\n const { runPostUpgradeChecks } = await import('./core/post-upgrade.js')\n await runPostUpgradeChecks(config)\n } catch (err) {\n log.warn({ err }, 'Post-upgrade check failed')\n }\n\n // Async cleanup of old session logs (non-blocking)\n cleanupOldSessionLogs(config.logging.sessionLogRetentionDays).catch(err =>\n log.warn({ err }, 'Session log cleanup failed')\n )\n\n // 3. Create core\n const core = new OpenACPCore(configManager)\n\n // 3.5 Start tunnel if configured\n let tunnelService: import('./tunnel/tunnel-service.js').TunnelService | undefined\n if (config.tunnel.enabled) {\n const { TunnelService } = await import('./tunnel/tunnel-service.js')\n tunnelService = new TunnelService(config.tunnel)\n const publicUrl = await tunnelService.start()\n core.tunnelService = tunnelService\n log.info({ publicUrl }, 'Tunnel started')\n }\n\n // 4. Register adapters from config\n for (const [channelName, channelConfig] of Object.entries(config.channels)) {\n if (!channelConfig.enabled) continue\n\n if (channelName === 'telegram') {\n core.registerAdapter('telegram', new TelegramAdapter(core, channelConfig as TelegramChannelConfig))\n log.info({ adapter: 'telegram' }, 'Adapter registered')\n } else if (channelName === 'slack') {\n const { SlackAdapter } = await import('./adapters/slack/adapter.js')\n const slackConfig = channelConfig as import('./adapters/slack/types.js').SlackChannelConfig\n core.registerAdapter('slack', new SlackAdapter(core, slackConfig))\n log.info({ adapter: 'slack' }, 'Adapter registered')\n } else if (channelName === 'discord') {\n const { DiscordAdapter } = await import('./adapters/discord/index.js')\n const discordConfig = channelConfig as import('./adapters/discord/types.js').DiscordChannelConfig\n core.registerAdapter('discord', new DiscordAdapter(core, discordConfig))\n log.info({ adapter: 'discord' }, 'Adapter registered')\n } else if (channelConfig.adapter) {\n // Plugin adapter\n const factory = await loadAdapterFactory(channelConfig.adapter)\n if (factory) {\n const adapter = factory.createAdapter(core, channelConfig)\n core.registerAdapter(channelName, adapter)\n log.info({ adapter: channelName, plugin: channelConfig.adapter }, 'Adapter registered')\n } else {\n const name = channelName\n const err = channelConfig.adapter\n log.error({ adapter: name, err }, 'Failed to load adapter')\n }\n } else {\n log.error({ adapter: channelName }, 'Channel has no built-in adapter; set \"adapter\" field to a plugin package')\n }\n }\n\n if (core.adapters.size === 0) {\n log.error('No channels enabled. Enable at least one channel in config.')\n process.exit(1)\n }\n\n // 5. Start\n let apiServer: ApiServer | undefined\n\n const shutdown = async (signal: string, exitCode = 0) => {\n if (shuttingDown) return\n shuttingDown = true\n log.info({ signal, exitCode }, 'Signal received, shutting down')\n\n try {\n if (apiServer) await apiServer.stop()\n await core.stop()\n if (tunnelService) await tunnelService.stop()\n } catch (err) {\n log.error({ err }, 'Error during shutdown')\n }\n\n const isDaemon = process.argv.includes('--daemon-child')\n\n // Clean up PID file if running as daemon\n if (isDaemon) {\n const { removePidFile, getPidPath } = await import('./core/daemon.js')\n removePidFile(getPidPath())\n }\n\n // Self-respawn on restart\n if (exitCode === RESTART_EXIT_CODE) {\n if (isDaemon) {\n // Daemon mode: spawn detached child writing to log file\n const { spawn: spawnChild } = await import('node:child_process')\n const { expandHome } = await import('./core/config.js')\n const fs = await import('node:fs')\n const pathMod = await import('node:path')\n\n const cliPath = pathMod.resolve(process.argv[1])\n const resolvedLogDir = expandHome(config.logging.logDir)\n fs.mkdirSync(resolvedLogDir, { recursive: true })\n const logFile = pathMod.join(resolvedLogDir, 'openacp.log')\n const out = fs.openSync(logFile, 'a')\n const err = fs.openSync(logFile, 'a')\n\n const child = spawnChild(process.execPath, [cliPath, '--daemon-child'], {\n detached: true,\n stdio: ['ignore', out, err],\n env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: '1' },\n })\n fs.closeSync(out)\n fs.closeSync(err)\n child.unref()\n log.info({ newPid: child.pid }, 'Respawned daemon for restart')\n } else if (!process.env.OPENACP_DEV_LOOP) {\n // Foreground production mode: spawn replacement process with inherited stdio\n const { spawn: spawnChild } = await import('node:child_process')\n const child = spawnChild(process.execPath, process.argv.slice(1), {\n stdio: 'inherit',\n env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: '1' },\n })\n await shutdownLogger()\n child.on('exit', (code) => process.exit(code ?? 0))\n return\n }\n }\n\n await shutdownLogger()\n process.exit(exitCode)\n }\n\n // Expose restart trigger for adapters (e.g. /restart command)\n core.requestRestart = () => shutdown('restart', RESTART_EXIT_CODE)\n\n process.on('SIGINT', () => shutdown('SIGINT'))\n process.on('SIGTERM', () => shutdown('SIGTERM'))\n\n process.on('uncaughtException', (err) => {\n log.error({ err }, 'Uncaught exception')\n })\n\n process.on('unhandledRejection', (err) => {\n log.error({ err }, 'Unhandled rejection')\n })\n\n await core.start()\n\n const updatedConfig = core.configManager.get()\n const telegramAdapter = core.adapters.get('telegram') ?? null\n let topicManager: TopicManager | undefined\n if (telegramAdapter) {\n const telegramCfg = updatedConfig.channels?.telegram as TelegramChannelConfig | undefined\n topicManager = new TopicManager(\n core.sessionManager,\n telegramAdapter,\n {\n notificationTopicId: telegramCfg?.notificationTopicId ?? null,\n assistantTopicId: telegramCfg?.assistantTopicId ?? null,\n },\n )\n }\n\n apiServer = new ApiServer(core, config.api, undefined, topicManager)\n await apiServer.start()\n\n // 6. Log ready\n if (isForegroundTTY) {\n if (spinner) spinner.stop()\n const ok = (msg: string) => console.log(`\\x1b[32m✓\\x1b[0m ${msg}`)\n ok('Config loaded')\n ok('Dependencies checked')\n if (tunnelService) ok(`Tunnel ready → ${tunnelService.getPublicUrl()}`)\n for (const [name] of core.adapters) ok(`${name.charAt(0).toUpperCase() + name.slice(1)} connected`)\n if (apiServer) ok(`API server on port ${config.api.port}`)\n console.log(`\\nOpenACP is running. Press Ctrl+C to stop.\\n`)\n unmuteLogger()\n }\n log.debug({ agents: Object.keys(config.agents) }, 'OpenACP started')\n}\n\n// Direct execution for dev (node dist/main.js)\nconst isDirectExecution = process.argv[1]?.endsWith('main.js')\nif (isDirectExecution) {\n startServer().catch((err) => {\n log.error({ err }, 'Fatal error')\n process.exit(1)\n })\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/post-upgrade.ts"],"sourcesContent":["import { createChildLogger } from \"./log.js\";\nimport { commandExists } from \"./agent-dependencies.js\";\nimport type { Config } from \"./config.js\";\n\nconst log = createChildLogger({ module: \"post-upgrade\" });\n\n/**\n * Post-upgrade dependency check — runs on every start.\n * Centralized source of truth for all binary dependency management.\n * Silent if everything is OK.\n */\nexport async function runPostUpgradeChecks(config: Config): Promise<void> {\n // 1. Tunnel provider binary\n if (config.tunnel.enabled) {\n if (config.tunnel.provider === \"cloudflare\") {\n try {\n const { ensureCloudflared } = await import(\n \"../tunnel/providers/install-cloudflared.js\"\n );\n await ensureCloudflared();\n } catch (err) {\n log.warn(\n { err: (err as Error).message },\n \"Could not install cloudflared. Tunnel may not work.\",\n );\n }\n } else {\n if (!commandExists(config.tunnel.provider)) {\n log.warn(\n `Tunnel provider \"${config.tunnel.provider}\" is not installed. Install it or switch to cloudflare (free, auto-installed).`,\n );\n }\n }\n }\n\n // 2. Claude CLI integration + jq\n try {\n const { getIntegration } = await import(\"../cli/integrate.js\");\n const integration = getIntegration(\"claude\");\n if (integration) {\n const allInstalled = integration.items.every((item) => item.isInstalled());\n if (!allInstalled) {\n log.info(\n 'Claude CLI integration not installed. Run \"openacp integrate claude\" for session transfer + tunnel skill.',\n );\n }\n\n const handoff = integration.items.find((i) => i.id === \"handoff\");\n if (handoff?.isInstalled() && !commandExists(\"jq\")) {\n try {\n const { ensureJq } = await import(\"./install-jq.js\");\n await ensureJq();\n } catch (err) {\n log.warn(\n { err: (err as Error).message },\n \"Could not install jq. Handoff hooks may not work.\",\n );\n }\n }\n }\n } catch {\n // integrate module not available — skip\n }\n\n // 3. unzip (needed for binary agent installs)\n if (!commandExists(\"unzip\")) {\n log.warn(\n \"unzip is not installed. Some agent installations (binary distribution) may fail. Install: brew install unzip (macOS) or apt install unzip (Linux)\",\n );\n }\n\n // 4. uvx (needed for Python-based agents)\n try {\n const { AgentStore } = await import(\"./agent-store.js\");\n const store = new AgentStore();\n store.load();\n const entries = store.getInstalled();\n const hasUvxAgent = Object.values(entries).some(\n (a: { distribution?: string }) => a.distribution === \"uvx\",\n );\n if (hasUvxAgent && !commandExists(\"uvx\")) {\n log.warn(\n \"uvx is not installed but you have Python-based agents. Install: pip install uv\",\n );\n }\n } catch {\n // skip\n }\n}\n"],"mappings":";;;;;;;;;AAIA,IAAM,MAAM,kBAAkB,EAAE,QAAQ,eAAe,CAAC;AAOxD,eAAsB,qBAAqB,QAA+B;AAExE,MAAI,OAAO,OAAO,SAAS;AACzB,QAAI,OAAO,OAAO,aAAa,cAAc;AAC3C,UAAI;AACF,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAClC,mCACF;AACA,cAAM,kBAAkB;AAAA,MAC1B,SAAS,KAAK;AACZ,YAAI;AAAA,UACF,EAAE,KAAM,IAAc,QAAQ;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,CAAC,cAAc,OAAO,OAAO,QAAQ,GAAG;AAC1C,YAAI;AAAA,UACF,oBAAoB,OAAO,OAAO,QAAQ;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACF,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,yBAAqB;AAC7D,UAAM,cAAc,eAAe,QAAQ;AAC3C,QAAI,aAAa;AACf,YAAM,eAAe,YAAY,MAAM,MAAM,CAAC,SAAS,KAAK,YAAY,CAAC;AACzE,UAAI,CAAC,cAAc;AACjB,YAAI;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,UAAU,YAAY,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AAChE,UAAI,SAAS,YAAY,KAAK,CAAC,cAAc,IAAI,GAAG;AAClD,YAAI;AACF,gBAAM,EAAE,SAAS,IAAI,MAAM,OAAO,0BAAiB;AACnD,gBAAM,SAAS;AAAA,QACjB,SAAS,KAAK;AACZ,cAAI;AAAA,YACF,EAAE,KAAM,IAAc,QAAQ;AAAA,YAC9B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI,CAAC,cAAc,OAAO,GAAG;AAC3B,QAAI;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACF,UAAM,EAAE,WAAW,IAAI,MAAM,OAAO,2BAAkB;AACtD,UAAM,QAAQ,IAAI,WAAW;AAC7B,UAAM,KAAK;AACX,UAAM,UAAU,MAAM,aAAa;AACnC,UAAM,cAAc,OAAO,OAAO,OAAO,EAAE;AAAA,MACzC,CAAC,MAAiC,EAAE,iBAAiB;AAAA,IACvD;AACA,QAAI,eAAe,CAAC,cAAc,KAAK,GAAG;AACxC,UAAI;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;","names":[]}
@@ -1,37 +0,0 @@
1
- import {
2
- detectAgents,
3
- printStartBanner,
4
- runReconfigure,
5
- runSetup,
6
- setupAgents,
7
- setupDiscord,
8
- setupRunMode,
9
- setupTelegram,
10
- setupWorkspace,
11
- validateAgentCommand,
12
- validateBotAdmin,
13
- validateBotToken,
14
- validateChatId,
15
- validateDiscordToken
16
- } from "./chunk-LCRLAV4G.js";
17
- import "./chunk-JKBFUAJK.js";
18
- import "./chunk-33RP6K2O.js";
19
- import "./chunk-GAK6PIBW.js";
20
- import "./chunk-VUNV25KB.js";
21
- export {
22
- detectAgents,
23
- printStartBanner,
24
- runReconfigure,
25
- runSetup,
26
- setupAgents,
27
- setupDiscord,
28
- setupRunMode,
29
- setupTelegram,
30
- setupWorkspace,
31
- validateAgentCommand,
32
- validateBotAdmin,
33
- validateBotToken,
34
- validateChatId,
35
- validateDiscordToken
36
- };
37
- //# sourceMappingURL=setup-XHS4OMPM.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/tunnel/tunnel-service.ts","../../src/tunnel/tunnel-registry.ts","../../src/tunnel/providers/cloudflare.ts","../../src/tunnel/providers/ngrok.ts","../../src/tunnel/providers/bore.ts","../../src/tunnel/providers/tailscale.ts","../../src/tunnel/viewer-store.ts","../../src/tunnel/server.ts","../../src/tunnel/templates/file-viewer.ts","../../src/tunnel/templates/diff-viewer.ts"],"sourcesContent":["import { serve } from '@hono/node-server'\nimport type { TunnelConfig } from '../core/config.js'\nimport { createChildLogger } from '../core/log.js'\nimport { TunnelRegistry, type TunnelEntry } from './tunnel-registry.js'\nimport { ViewerStore } from './viewer-store.js'\nimport { createTunnelServer } from './server.js'\n\nconst log = createChildLogger({ module: 'tunnel' })\n\nexport class TunnelService {\n private registry: TunnelRegistry\n private store: ViewerStore\n private server: ReturnType<typeof serve> | null = null\n private config: TunnelConfig\n private systemPort = 0\n\n constructor(config: TunnelConfig) {\n this.config = config\n this.store = new ViewerStore(config.storeTtlMinutes)\n this.registry = new TunnelRegistry({\n maxUserTunnels: config.maxUserTunnels ?? 5,\n providerOptions: config.options,\n })\n }\n\n async start(): Promise<string> {\n // 1. Start HTTP viewer server — try configured port, then auto-increment\n const authToken = this.config.auth.enabled ? this.config.auth.token : undefined\n const app = createTunnelServer(this.store, authToken)\n\n let actualPort = this.config.port\n const maxRetries = 10\n\n for (let i = 0; i < maxRetries; i++) {\n const port = this.config.port + i\n const server = serve({ fetch: app.fetch, port })\n\n const ok = await new Promise<boolean>((resolve) => {\n server.on('listening', () => resolve(true))\n server.on('error', () => resolve(false))\n })\n\n if (ok) {\n this.server = server\n actualPort = port\n if (i > 0) {\n log.info({ configuredPort: this.config.port, actualPort }, 'Configured port in use, using next available')\n }\n log.info({ port: actualPort }, 'Tunnel HTTP server started')\n break\n }\n\n server.close()\n }\n\n if (!this.server) {\n log.warn({ port: this.config.port }, 'Could not find available port for tunnel HTTP server')\n return `http://localhost:${this.config.port}`\n }\n\n this.systemPort = actualPort\n\n // 2. Register system tunnel (file viewer)\n try {\n await this.registry.add(actualPort, {\n type: 'system',\n provider: this.config.provider,\n label: 'File Viewer',\n })\n } catch (err) {\n log.warn({ err: (err as Error).message }, 'System tunnel failed, running on localhost')\n }\n\n // 3. Restore persisted user tunnels\n await this.registry.restore()\n\n const systemEntry = this.registry.getSystemEntry()\n return systemEntry?.publicUrl || `http://localhost:${actualPort}`\n }\n\n async stop(): Promise<void> {\n await this.registry.shutdown()\n this.registry.flush()\n if (this.server) {\n this.server.close()\n this.server = null\n }\n this.store.destroy()\n log.info('Tunnel service stopped')\n }\n\n // --- User tunnel management ---\n\n async addTunnel(port: number, opts?: { label?: string; sessionId?: string }): Promise<TunnelEntry> {\n return this.registry.add(port, {\n type: 'user',\n provider: this.config.provider,\n label: opts?.label,\n sessionId: opts?.sessionId,\n })\n }\n\n async stopTunnel(port: number): Promise<void> {\n return this.registry.stop(port)\n }\n\n async stopAllUser(): Promise<void> {\n return this.registry.stopAllUser()\n }\n\n async stopBySession(sessionId: string): Promise<TunnelEntry[]> {\n return this.registry.stopBySession(sessionId)\n }\n\n listTunnels(): TunnelEntry[] {\n return this.registry.list(false) // user only\n }\n\n getTunnel(port: number): TunnelEntry | null {\n return this.registry.get(port)\n }\n\n // --- Viewer (system tunnel) ---\n\n getPublicUrl(): string {\n const system = this.registry.getSystemEntry()\n return system?.publicUrl || `http://localhost:${this.systemPort || this.config.port}`\n }\n\n getStore(): ViewerStore {\n return this.store\n }\n\n fileUrl(entryId: string): string {\n return `${this.getPublicUrl()}/view/${entryId}`\n }\n\n diffUrl(entryId: string): string {\n return `${this.getPublicUrl()}/diff/${entryId}`\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { createChildLogger } from '../core/log.js'\nimport type { TunnelProvider } from './provider.js'\nimport { CloudflareTunnelProvider } from './providers/cloudflare.js'\nimport { NgrokTunnelProvider } from './providers/ngrok.js'\nimport { BoreTunnelProvider } from './providers/bore.js'\nimport { TailscaleTunnelProvider } from './providers/tailscale.js'\n\nconst log = createChildLogger({ module: 'tunnel-registry' })\n\nexport interface TunnelEntry {\n port: number\n type: 'system' | 'user'\n provider: string\n label?: string\n publicUrl?: string\n sessionId?: string\n status: 'stopped' | 'starting' | 'active' | 'failed'\n createdAt: string\n}\n\ninterface PersistedEntry {\n port: number\n type: 'system' | 'user'\n provider: string\n label?: string\n sessionId?: string\n createdAt: string\n}\n\ninterface LiveEntry {\n entry: TunnelEntry\n process: TunnelProvider | null\n spawnPromise: Promise<string> | null\n}\n\nconst REGISTRY_PATH = path.join(os.homedir(), '.openacp', 'tunnels.json')\n\nexport class TunnelRegistry {\n private entries: Map<number, LiveEntry> = new Map()\n private saveTimeout: ReturnType<typeof setTimeout> | null = null\n private maxUserTunnels: number\n private providerOptions: Record<string, unknown>\n\n constructor(opts: { maxUserTunnels?: number; providerOptions?: Record<string, unknown> } = {}) {\n this.maxUserTunnels = opts.maxUserTunnels ?? 5\n this.providerOptions = opts.providerOptions ?? {}\n }\n\n async add(port: number, opts: {\n type: 'system' | 'user'\n provider: string\n label?: string\n sessionId?: string\n }): Promise<TunnelEntry> {\n // Check if port already registered\n if (this.entries.has(port)) {\n const existing = this.entries.get(port)!\n if (existing.entry.status === 'active' || existing.entry.status === 'starting') {\n throw new Error(`Port ${port} is already tunneled → ${existing.entry.publicUrl || 'starting...'}`)\n }\n // Stopped/failed entry — remove and re-add\n this.entries.delete(port)\n }\n\n // Check max user tunnels\n if (opts.type === 'user') {\n const userCount = this.list(false).filter(e => e.status === 'active' || e.status === 'starting').length\n if (userCount >= this.maxUserTunnels) {\n throw new Error(`Max user tunnels (${this.maxUserTunnels}) reached. Stop a tunnel first.`)\n }\n }\n\n const entry: TunnelEntry = {\n port,\n type: opts.type,\n provider: opts.provider,\n label: opts.label,\n sessionId: opts.sessionId,\n status: 'starting',\n createdAt: new Date().toISOString(),\n }\n\n const provider = this.createProvider(opts.provider)\n const spawnPromise = provider.start(port).then(url => {\n entry.publicUrl = url\n entry.status = 'active'\n log.info({ port, url, label: opts.label }, 'Tunnel active')\n this.scheduleSave()\n return url\n }).catch(err => {\n entry.status = 'failed'\n log.error({ port, err: (err as Error).message }, 'Tunnel failed to start')\n this.scheduleSave()\n throw err\n })\n\n this.entries.set(port, { entry, process: provider, spawnPromise })\n this.scheduleSave()\n\n // Await spawn — caller gets the URL or error\n await spawnPromise\n return entry\n }\n\n async stop(port: number): Promise<void> {\n const live = this.entries.get(port)\n if (!live) return\n\n if (live.entry.type === 'system') {\n throw new Error('Cannot stop system tunnel')\n }\n\n // Wait for spawn to finish if still starting\n if (live.spawnPromise) {\n try { await live.spawnPromise } catch { /* ignore spawn error */ }\n }\n\n if (live.process) {\n await live.process.stop()\n }\n\n this.entries.delete(port)\n this.scheduleSave()\n log.info({ port, label: live.entry.label }, 'Tunnel stopped')\n }\n\n async stopBySession(sessionId: string): Promise<TunnelEntry[]> {\n const stopped: TunnelEntry[] = []\n const toStop = this.getBySession(sessionId)\n for (const entry of toStop) {\n try {\n await this.stop(entry.port)\n stopped.push(entry)\n } catch { /* ignore */ }\n }\n return stopped\n }\n\n async stopAllUser(): Promise<void> {\n const userEntries = this.list(false)\n for (const entry of userEntries) {\n try { await this.stop(entry.port) } catch { /* ignore */ }\n }\n }\n\n async shutdown(): Promise<void> {\n for (const [, live] of this.entries) {\n if (live.spawnPromise) {\n try { await live.spawnPromise } catch { /* ignore */ }\n }\n if (live.process) {\n await live.process.stop()\n }\n }\n this.entries.clear()\n this.scheduleSave()\n }\n\n list(includeSystem = false): TunnelEntry[] {\n const entries = Array.from(this.entries.values()).map(l => l.entry)\n if (includeSystem) return entries\n return entries.filter(e => e.type === 'user')\n }\n\n get(port: number): TunnelEntry | null {\n return this.entries.get(port)?.entry ?? null\n }\n\n getBySession(sessionId: string): TunnelEntry[] {\n return this.list(false).filter(e => e.sessionId === sessionId)\n }\n\n getSystemEntry(): TunnelEntry | null {\n for (const live of this.entries.values()) {\n if (live.entry.type === 'system') return live.entry\n }\n return null\n }\n\n async restore(): Promise<void> {\n if (!fs.existsSync(REGISTRY_PATH)) return\n\n try {\n const raw = JSON.parse(fs.readFileSync(REGISTRY_PATH, 'utf-8')) as PersistedEntry[]\n log.info({ count: raw.length }, 'Restoring tunnels')\n\n // Only restore user tunnels — system tunnel is registered separately by TunnelService.start()\n const userEntries = raw.filter(e => e.type === 'user')\n for (const persisted of userEntries) {\n try {\n await this.add(persisted.port, {\n type: persisted.type,\n provider: persisted.provider,\n label: persisted.label,\n sessionId: persisted.sessionId,\n })\n } catch (err) {\n log.warn({ port: persisted.port, err: (err as Error).message }, 'Failed to restore tunnel')\n }\n }\n } catch (err) {\n log.warn({ err: (err as Error).message }, 'Failed to read tunnels.json')\n }\n }\n\n private createProvider(name: string): TunnelProvider {\n switch (name) {\n case 'cloudflare':\n return new CloudflareTunnelProvider(this.providerOptions)\n case 'ngrok':\n return new NgrokTunnelProvider(this.providerOptions)\n case 'bore':\n return new BoreTunnelProvider(this.providerOptions)\n case 'tailscale':\n return new TailscaleTunnelProvider(this.providerOptions)\n default:\n log.warn({ provider: name }, 'Unknown provider, falling back to cloudflare')\n return new CloudflareTunnelProvider(this.providerOptions)\n }\n }\n\n private scheduleSave(): void {\n if (this.saveTimeout) clearTimeout(this.saveTimeout)\n this.saveTimeout = setTimeout(() => this.save(), 2000)\n }\n\n private save(): void {\n const data: PersistedEntry[] = Array.from(this.entries.values()).map(l => ({\n port: l.entry.port,\n type: l.entry.type,\n provider: l.entry.provider,\n label: l.entry.label,\n sessionId: l.entry.sessionId,\n createdAt: l.entry.createdAt,\n }))\n\n try {\n const dir = path.dirname(REGISTRY_PATH)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(REGISTRY_PATH, JSON.stringify(data, null, 2))\n } catch (err) {\n log.error({ err: (err as Error).message }, 'Failed to save tunnels.json')\n }\n }\n\n flush(): void {\n if (this.saveTimeout) {\n clearTimeout(this.saveTimeout)\n this.saveTimeout = null\n }\n this.save()\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { createChildLogger } from '../../core/log.js'\nimport { commandExists } from '../../core/agent-dependencies.js'\nimport type { TunnelProvider } from '../provider.js'\n\nconst log = createChildLogger({ module: 'cloudflare-tunnel' })\n\nexport class CloudflareTunnelProvider implements TunnelProvider {\n private child: ChildProcess | null = null\n private publicUrl = ''\n private options: Record<string, unknown>\n\n constructor(options: Record<string, unknown> = {}) {\n this.options = options\n }\n\n async start(localPort: number): Promise<string> {\n // Find binary — post-upgrade should have installed it, but fallback to ensureCloudflared() as safety net\n let binaryPath = this.findBinary()\n if (!binaryPath) {\n log.warn('cloudflared not found locally, attempting auto-install as fallback...')\n try {\n const { ensureCloudflared } = await import('./install-cloudflared.js')\n binaryPath = await ensureCloudflared()\n } catch (err) {\n throw new Error(`cloudflared is not installed and auto-install failed: ${(err as Error).message}`)\n }\n }\n\n const args = ['tunnel', '--url', `http://localhost:${localPort}`]\n if (this.options.domain) {\n args.push('--hostname', String(this.options.domain))\n }\n\n return new Promise<string>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.stop()\n reject(new Error('Cloudflare tunnel timed out after 30s'))\n }, 30_000)\n\n try {\n this.child = spawn(binaryPath, args, { stdio: ['ignore', 'pipe', 'pipe'] })\n } catch {\n clearTimeout(timeout)\n reject(new Error(`Failed to start cloudflared at ${binaryPath}`))\n return\n }\n\n const urlPattern = /https:\\/\\/[a-zA-Z0-9-]+\\.trycloudflare\\.com/\n\n const onData = (data: Buffer) => {\n const line = data.toString()\n log.debug(line.trim())\n const match = line.match(urlPattern)\n if (match) {\n clearTimeout(timeout)\n this.publicUrl = match[0]\n log.info({ url: this.publicUrl }, 'Cloudflare tunnel ready')\n resolve(this.publicUrl)\n }\n }\n\n this.child.stdout?.on('data', onData)\n this.child.stderr?.on('data', onData)\n\n this.child.on('error', (err) => {\n clearTimeout(timeout)\n reject(new Error(`cloudflared failed to start: ${err.message}`))\n })\n\n this.child.on('exit', (code) => {\n if (!this.publicUrl) {\n clearTimeout(timeout)\n reject(new Error(`cloudflared exited with code ${code} before establishing tunnel`))\n }\n })\n })\n }\n\n async stop(): Promise<void> {\n if (this.child) {\n this.child.kill('SIGTERM')\n this.child = null\n log.info('Cloudflare tunnel stopped')\n }\n }\n\n getPublicUrl(): string {\n return this.publicUrl\n }\n\n private findBinary(): string | null {\n // 1. Check PATH first (respects user's system install)\n if (commandExists('cloudflared')) return 'cloudflared'\n\n // 2. Check ~/.openacp/bin/ (installed by post-upgrade)\n const binPath = path.join(os.homedir(), '.openacp', 'bin', 'cloudflared')\n if (fs.existsSync(binPath)) return binPath\n\n // 3. Not found\n return null\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport { createChildLogger } from '../../core/log.js'\nimport type { TunnelProvider } from '../provider.js'\n\nconst log = createChildLogger({ module: 'ngrok-tunnel' })\n\nexport class NgrokTunnelProvider implements TunnelProvider {\n private child: ChildProcess | null = null\n private publicUrl = ''\n private options: Record<string, unknown>\n\n constructor(options: Record<string, unknown> = {}) {\n this.options = options\n }\n\n async start(localPort: number): Promise<string> {\n const args = ['http', String(localPort), '--log', 'stdout', '--log-format', 'json']\n if (this.options.authtoken) {\n args.push('--authtoken', String(this.options.authtoken))\n }\n if (this.options.domain) {\n args.push('--domain', String(this.options.domain))\n }\n if (this.options.region) {\n args.push('--region', String(this.options.region))\n }\n\n return new Promise<string>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.stop()\n reject(new Error('ngrok tunnel timed out after 30s. Is ngrok installed?'))\n }, 30_000)\n\n try {\n this.child = spawn('ngrok', args, { stdio: ['ignore', 'pipe', 'pipe'] })\n } catch {\n clearTimeout(timeout)\n reject(new Error(\n 'Failed to start ngrok. Install it from https://ngrok.com/download'\n ))\n return\n }\n\n const urlPattern = /https:\\/\\/[a-zA-Z0-9-]+\\.ngrok(-free)?\\.app/\n\n const onData = (data: Buffer) => {\n const line = data.toString()\n log.debug(line.trim())\n const match = line.match(urlPattern)\n if (match) {\n clearTimeout(timeout)\n this.publicUrl = match[0]\n log.info({ url: this.publicUrl }, 'ngrok tunnel ready')\n resolve(this.publicUrl)\n }\n }\n\n this.child.stdout?.on('data', onData)\n this.child.stderr?.on('data', onData)\n\n this.child.on('error', (err) => {\n clearTimeout(timeout)\n reject(new Error(\n `ngrok failed to start: ${err.message}. Install it from https://ngrok.com/download`\n ))\n })\n\n this.child.on('exit', (code) => {\n if (!this.publicUrl) {\n clearTimeout(timeout)\n reject(new Error(`ngrok exited with code ${code} before establishing tunnel`))\n }\n })\n })\n }\n\n async stop(): Promise<void> {\n if (this.child) {\n this.child.kill('SIGTERM')\n this.child = null\n log.info('ngrok tunnel stopped')\n }\n }\n\n getPublicUrl(): string {\n return this.publicUrl\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport { createChildLogger } from '../../core/log.js'\nimport type { TunnelProvider } from '../provider.js'\n\nconst log = createChildLogger({ module: 'bore-tunnel' })\n\nexport class BoreTunnelProvider implements TunnelProvider {\n private child: ChildProcess | null = null\n private publicUrl = ''\n private options: Record<string, unknown>\n\n constructor(options: Record<string, unknown> = {}) {\n this.options = options\n }\n\n async start(localPort: number): Promise<string> {\n const server = String(this.options.server || 'bore.pub')\n const args = ['local', String(localPort), '--to', server]\n if (this.options.port) {\n args.push('--port', String(this.options.port))\n }\n if (this.options.secret) {\n args.push('--secret', String(this.options.secret))\n }\n\n return new Promise<string>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.stop()\n reject(new Error('Bore tunnel timed out after 30s. Is bore installed?'))\n }, 30_000)\n\n try {\n this.child = spawn('bore', args, { stdio: ['ignore', 'pipe', 'pipe'] })\n } catch {\n clearTimeout(timeout)\n reject(new Error(\n 'Failed to start bore. Install it from https://github.com/ekzhang/bore'\n ))\n return\n }\n\n const urlPattern = /listening at ([^\\s]+):(\\d+)/\n\n const onData = (data: Buffer) => {\n const line = data.toString()\n log.debug(line.trim())\n const match = line.match(urlPattern)\n if (match) {\n clearTimeout(timeout)\n this.publicUrl = `http://${match[1]}:${match[2]}`\n log.info({ url: this.publicUrl }, 'Bore tunnel ready')\n resolve(this.publicUrl)\n }\n }\n\n this.child.stdout?.on('data', onData)\n this.child.stderr?.on('data', onData)\n\n this.child.on('error', (err) => {\n clearTimeout(timeout)\n reject(new Error(\n `bore failed to start: ${err.message}. Install it from https://github.com/ekzhang/bore`\n ))\n })\n\n this.child.on('exit', (code) => {\n if (!this.publicUrl) {\n clearTimeout(timeout)\n reject(new Error(`bore exited with code ${code} before establishing tunnel`))\n }\n })\n })\n }\n\n async stop(): Promise<void> {\n if (this.child) {\n this.child.kill('SIGTERM')\n this.child = null\n log.info('Bore tunnel stopped')\n }\n }\n\n getPublicUrl(): string {\n return this.publicUrl\n }\n}\n","import { spawn, execSync, type ChildProcess } from 'node:child_process'\nimport { createChildLogger } from '../../core/log.js'\nimport type { TunnelProvider } from '../provider.js'\n\nconst log = createChildLogger({ module: 'tailscale-tunnel' })\n\nexport class TailscaleTunnelProvider implements TunnelProvider {\n private child: ChildProcess | null = null\n private publicUrl = ''\n private options: Record<string, unknown>\n\n constructor(options: Record<string, unknown> = {}) {\n this.options = options\n }\n\n async start(localPort: number): Promise<string> {\n let hostname = ''\n try {\n const statusJson = execSync('tailscale status --json', { encoding: 'utf-8' })\n const status = JSON.parse(statusJson)\n hostname = String(status.Self.DNSName).replace(/\\.$/, '')\n log.debug({ hostname }, 'Resolved Tailscale hostname')\n } catch (err) {\n log.warn('Failed to resolve Tailscale hostname via status --json')\n }\n\n const args = ['funnel', String(localPort)]\n if (this.options.bg) {\n args.push('--bg')\n }\n\n return new Promise<string>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.stop()\n reject(new Error('Tailscale funnel timed out after 30s. Is tailscale installed?'))\n }, 30_000)\n\n try {\n this.child = spawn('tailscale', args, { stdio: ['ignore', 'pipe', 'pipe'] })\n } catch {\n clearTimeout(timeout)\n reject(new Error(\n 'Failed to start tailscale. Install it from https://tailscale.com/download'\n ))\n return\n }\n\n const urlPattern = /https:\\/\\/[^\\s]+/\n\n const onData = (data: Buffer) => {\n const line = data.toString()\n log.debug(line.trim())\n const match = line.match(urlPattern)\n if (match) {\n clearTimeout(timeout)\n this.publicUrl = match[0]\n log.info({ url: this.publicUrl }, 'Tailscale funnel ready')\n resolve(this.publicUrl)\n }\n }\n\n this.child.stdout?.on('data', onData)\n this.child.stderr?.on('data', onData)\n\n this.child.on('error', (err) => {\n clearTimeout(timeout)\n reject(new Error(\n `tailscale failed to start: ${err.message}. Install it from https://tailscale.com/download`\n ))\n })\n\n this.child.on('exit', (code) => {\n if (!this.publicUrl) {\n clearTimeout(timeout)\n if (hostname) {\n this.publicUrl = `https://${hostname}`\n log.info({ url: this.publicUrl }, 'Tailscale funnel ready (constructed from hostname)')\n resolve(this.publicUrl)\n } else {\n reject(new Error(`tailscale exited with code ${code} before establishing funnel`))\n }\n }\n })\n })\n }\n\n async stop(): Promise<void> {\n if (this.child) {\n this.child.kill('SIGTERM')\n this.child = null\n log.info('Tailscale funnel stopped')\n }\n }\n\n getPublicUrl(): string {\n return this.publicUrl\n }\n}\n","import * as path from 'node:path'\nimport { nanoid } from 'nanoid'\nimport { createChildLogger } from '../core/log.js'\n\nconst log = createChildLogger({ module: 'viewer-store' })\n\nconst MAX_CONTENT_SIZE = 1_000_000 // 1MB\n\nconst EXTENSION_LANGUAGE: Record<string, string> = {\n '.ts': 'typescript', '.tsx': 'typescript', '.js': 'javascript', '.jsx': 'javascript',\n '.py': 'python', '.rs': 'rust', '.go': 'go', '.java': 'java', '.kt': 'kotlin',\n '.rb': 'ruby', '.php': 'php', '.c': 'c', '.cpp': 'cpp', '.h': 'c', '.hpp': 'cpp',\n '.cs': 'csharp', '.swift': 'swift', '.sh': 'bash', '.zsh': 'bash', '.bash': 'bash',\n '.json': 'json', '.yaml': 'yaml', '.yml': 'yaml', '.toml': 'toml',\n '.xml': 'xml', '.html': 'html', '.css': 'css', '.scss': 'scss',\n '.sql': 'sql', '.md': 'markdown', '.dockerfile': 'dockerfile',\n '.tf': 'hcl', '.vue': 'xml', '.svelte': 'xml',\n}\n\nexport interface ViewerEntry {\n id: string\n type: 'file' | 'diff'\n filePath?: string\n content: string\n oldContent?: string\n language?: string\n sessionId: string\n workingDirectory: string\n createdAt: number\n expiresAt: number\n}\n\nexport class ViewerStore {\n private entries = new Map<string, ViewerEntry>()\n private cleanupTimer: ReturnType<typeof setInterval>\n private ttlMs: number\n\n constructor(ttlMinutes: number = 60) {\n this.ttlMs = ttlMinutes * 60 * 1000\n this.cleanupTimer = setInterval(() => this.cleanup(), 5 * 60 * 1000)\n }\n\n storeFile(sessionId: string, filePath: string, content: string, workingDirectory: string): string | null {\n if (!this.isPathAllowed(filePath, workingDirectory)) {\n log.warn({ filePath, workingDirectory }, 'Path outside workspace, rejecting')\n return null\n }\n if (content.length > MAX_CONTENT_SIZE) {\n log.debug({ filePath, size: content.length }, 'File too large for viewer')\n return null\n }\n\n const id = nanoid(12)\n const now = Date.now()\n this.entries.set(id, {\n id,\n type: 'file',\n filePath,\n content,\n language: this.detectLanguage(filePath),\n sessionId,\n workingDirectory,\n createdAt: now,\n expiresAt: now + this.ttlMs,\n })\n log.debug({ id, filePath }, 'Stored file for viewing')\n return id\n }\n\n storeDiff(sessionId: string, filePath: string, oldContent: string, newContent: string, workingDirectory: string): string | null {\n if (!this.isPathAllowed(filePath, workingDirectory)) {\n log.warn({ filePath, workingDirectory }, 'Path outside workspace, rejecting')\n return null\n }\n const combined = oldContent.length + newContent.length\n if (combined > MAX_CONTENT_SIZE) {\n log.debug({ filePath, size: combined }, 'Diff content too large for viewer')\n return null\n }\n\n const id = nanoid(12)\n const now = Date.now()\n this.entries.set(id, {\n id,\n type: 'diff',\n filePath,\n content: newContent,\n oldContent,\n language: this.detectLanguage(filePath),\n sessionId,\n workingDirectory,\n createdAt: now,\n expiresAt: now + this.ttlMs,\n })\n log.debug({ id, filePath }, 'Stored diff for viewing')\n return id\n }\n\n get(id: string): ViewerEntry | undefined {\n const entry = this.entries.get(id)\n if (!entry) return undefined\n if (Date.now() > entry.expiresAt) {\n this.entries.delete(id)\n return undefined\n }\n return entry\n }\n\n private cleanup(): void {\n const now = Date.now()\n let removed = 0\n for (const [id, entry] of this.entries) {\n if (now > entry.expiresAt) {\n this.entries.delete(id)\n removed++\n }\n }\n if (removed > 0) {\n log.debug({ removed, remaining: this.entries.size }, 'Cleaned up expired viewer entries')\n }\n }\n\n private isPathAllowed(filePath: string, workingDirectory: string): boolean {\n const resolved = path.resolve(workingDirectory, filePath)\n return resolved.startsWith(path.resolve(workingDirectory))\n }\n\n private detectLanguage(filePath: string): string | undefined {\n const ext = path.extname(filePath).toLowerCase()\n return EXTENSION_LANGUAGE[ext]\n }\n\n destroy(): void {\n clearInterval(this.cleanupTimer)\n this.entries.clear()\n }\n}\n","import { Hono } from 'hono'\nimport type { ViewerStore } from './viewer-store.js'\nimport { renderFileViewer } from './templates/file-viewer.js'\nimport { renderDiffViewer } from './templates/diff-viewer.js'\n\nfunction notFoundPage(): string {\n return `<!DOCTYPE html>\n<html><head><meta charset=\"UTF-8\"><title>Not Found - OpenACP</title>\n<style>body{background:#0d1117;color:#c9d1d9;font-family:sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0}\n.box{text-align:center;padding:40px}.code{font-size:72px;font-weight:bold;color:#484f58}p{margin-top:16px;color:#8b949e}</style>\n</head><body><div class=\"box\"><div class=\"code\">404</div><p>This viewer link has expired or does not exist.</p></div></body></html>`\n}\n\nexport function createTunnelServer(store: ViewerStore, authToken?: string): Hono {\n const app = new Hono()\n\n // Auth middleware\n if (authToken) {\n app.use('*', async (c, next) => {\n if (c.req.path === '/health') return next()\n const bearer = c.req.header('Authorization')?.replace('Bearer ', '')\n const query = c.req.query('token')\n if (bearer !== authToken && query !== authToken) {\n return c.text('Unauthorized', 401)\n }\n return next()\n })\n }\n\n app.get('/health', (c) => c.json({ status: 'ok' }))\n\n app.get('/view/:id', (c) => {\n const entry = store.get(c.req.param('id'))\n if (!entry || entry.type !== 'file') {\n return c.html(notFoundPage(), 404)\n }\n return c.html(renderFileViewer(entry))\n })\n\n app.get('/diff/:id', (c) => {\n const entry = store.get(c.req.param('id'))\n if (!entry || entry.type !== 'diff') {\n return c.html(notFoundPage(), 404)\n }\n return c.html(renderDiffViewer(entry))\n })\n\n app.get('/api/file/:id', (c) => {\n const entry = store.get(c.req.param('id'))\n if (!entry || entry.type !== 'file') {\n return c.json({ error: 'not found' }, 404)\n }\n return c.json({ filePath: entry.filePath, content: entry.content, language: entry.language })\n })\n\n app.get('/api/diff/:id', (c) => {\n const entry = store.get(c.req.param('id'))\n if (!entry || entry.type !== 'diff') {\n return c.json({ error: 'not found' }, 404)\n }\n return c.json({ filePath: entry.filePath, oldContent: entry.oldContent, newContent: entry.content, language: entry.language })\n })\n\n return app\n}\n","import type { ViewerEntry } from '../viewer-store.js'\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\n// Map our language IDs to Monaco language IDs\nconst MONACO_LANGUAGE: Record<string, string> = {\n typescript: 'typescript', javascript: 'javascript', python: 'python',\n rust: 'rust', go: 'go', java: 'java', kotlin: 'kotlin', ruby: 'ruby',\n php: 'php', c: 'c', cpp: 'cpp', csharp: 'csharp', swift: 'swift',\n bash: 'shell', json: 'json', yaml: 'yaml', toml: 'ini', xml: 'xml',\n html: 'html', css: 'css', scss: 'scss', sql: 'sql', markdown: 'markdown',\n dockerfile: 'dockerfile', hcl: 'hcl', plaintext: 'plaintext',\n}\n\nfunction getMonacoLang(lang?: string): string {\n if (!lang) return 'plaintext'\n return MONACO_LANGUAGE[lang] || 'plaintext'\n}\n\nexport function renderFileViewer(entry: ViewerEntry): string {\n const fileName = entry.filePath || 'untitled'\n const lang = getMonacoLang(entry.language)\n // Escape </script> inside content to prevent premature tag closure\n const safeContent = JSON.stringify(entry.content).replace(/<\\//g, '<\\\\/')\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${escapeHtml(fileName)} - OpenACP</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body { background: #1e1e1e; color: #d4d4d4; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; display: flex; flex-direction: column; height: 100vh; }\n .header { background: #252526; border-bottom: 1px solid #3c3c3c; padding: 8px 16px; display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; z-index: 10; }\n .file-info { display: flex; align-items: center; gap: 8px; font-size: 13px; min-width: 0; }\n .file-icon { font-size: 14px; flex-shrink: 0; }\n .file-path { color: #969696; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .file-name { color: #e0e0e0; font-weight: 500; flex-shrink: 0; }\n .actions { display: flex; gap: 6px; flex-shrink: 0; }\n .btn { background: #3c3c3c; color: #d4d4d4; border: 1px solid #505050; padding: 4px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; transition: background 0.15s; }\n .btn:hover { background: #505050; }\n .btn.active { background: #0e639c; border-color: #1177bb; }\n #editor-container { flex: 1; overflow: hidden; }\n .status-bar { background: #007acc; color: #fff; padding: 2px 16px; font-size: 12px; display: flex; justify-content: space-between; flex-shrink: 0; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <div class=\"file-info\">\n <span class=\"file-icon\">📄</span>\n ${formatBreadcrumb(fileName)}\n </div>\n <div class=\"actions\">\n ${lang === 'markdown' ? '<button class=\"btn\" onclick=\"togglePreview()\" id=\"btn-preview\">Preview</button>' : ''}\n <button class=\"btn\" onclick=\"toggleWordWrap()\" id=\"btn-wrap\">Wrap</button>\n <button class=\"btn\" onclick=\"toggleMinimap()\" id=\"btn-minimap\">Minimap</button>\n <button class=\"btn\" onclick=\"toggleTheme()\" id=\"btn-theme\">Light</button>\n <button class=\"btn\" onclick=\"copyCode()\">Copy</button>\n </div>\n </div>\n <div id=\"editor-container\"></div>\n <div id=\"preview-wrapper\" style=\"display:none; flex:1; overflow-y:auto;\">\n <div id=\"preview-container\" style=\"padding:24px 48px; max-width:900px; margin:0 auto; width:100%;\"></div>\n </div>\n <div class=\"status-bar\">\n <span>${escapeHtml(entry.language || 'plaintext')} | ${entry.content.split('\\n').length} lines</span>\n <span>OpenACP Viewer (read-only)</span>\n </div>\n\n ${lang === 'markdown' ? '<script src=\"https://cdn.jsdelivr.net/npm/marked@15.0.0/marked.min.js\"></script>' : ''}\n <script src=\"https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/loader.js\"></script>\n <script>\n const content = ${safeContent};\n const lang = ${JSON.stringify(lang)};\n let editor;\n let isDark = true;\n let wordWrap = false;\n let minimap = true;\n\n require.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs' } });\n require(['vs/editor/editor.main'], function () {\n editor = monaco.editor.create(document.getElementById('editor-container'), {\n value: content,\n language: lang,\n theme: 'vs-dark',\n readOnly: true,\n automaticLayout: true,\n minimap: { enabled: true },\n scrollBeyondLastLine: false,\n fontSize: 13,\n fontFamily: \"'SF Mono', SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace\",\n lineNumbers: 'on',\n renderLineHighlight: 'all',\n wordWrap: 'off',\n padding: { top: 8 },\n });\n\n // Handle line range from URL hash: #L42 or #L42-L55\n function highlightFromHash() {\n const hash = location.hash.slice(1);\n const match = hash.match(/^L(\\\\d+)(?:-L?(\\\\d+))?$/);\n if (!match) return;\n const startLine = parseInt(match[1], 10);\n const endLine = match[2] ? parseInt(match[2], 10) : startLine;\n editor.revealLineInCenter(startLine);\n editor.setSelection(new monaco.Selection(startLine, 1, endLine + 1, 1));\n }\n highlightFromHash();\n window.addEventListener('hashchange', highlightFromHash);\n });\n\n function toggleTheme() {\n isDark = !isDark;\n monaco.editor.setTheme(isDark ? 'vs-dark' : 'vs');\n document.body.style.background = isDark ? '#1e1e1e' : '#ffffff';\n document.querySelector('.header').style.background = isDark ? '#252526' : '#f3f3f3';\n document.querySelector('.header').style.borderColor = isDark ? '#3c3c3c' : '#e0e0e0';\n document.getElementById('btn-theme').textContent = isDark ? 'Light' : 'Dark';\n }\n\n function toggleWordWrap() {\n wordWrap = !wordWrap;\n editor.updateOptions({ wordWrap: wordWrap ? 'on' : 'off' });\n document.getElementById('btn-wrap').classList.toggle('active', wordWrap);\n }\n\n function toggleMinimap() {\n minimap = !minimap;\n editor.updateOptions({ minimap: { enabled: minimap } });\n document.getElementById('btn-minimap').classList.toggle('active', !minimap);\n }\n\n function copyCode() {\n navigator.clipboard.writeText(content).then(() => {\n const btn = event.target;\n btn.textContent = 'Copied!';\n setTimeout(() => btn.textContent = 'Copy', 2000);\n });\n }\n\n let previewMode = false;\n function togglePreview() {\n previewMode = !previewMode;\n const editorEl = document.getElementById('editor-container');\n const wrapperEl = document.getElementById('preview-wrapper');\n const previewEl = document.getElementById('preview-container');\n const btn = document.getElementById('btn-preview');\n if (previewMode) {\n editorEl.style.display = 'none';\n wrapperEl.style.display = 'block';\n previewEl.innerHTML = typeof marked !== 'undefined' ? marked.parse(content) : content.replace(/\\\\n/g, '<br>');\n previewEl.style.color = isDark ? '#d4d4d4' : '#1e1e1e';\n wrapperEl.style.background = isDark ? '#1e1e1e' : '#ffffff';\n btn.classList.add('active');\n btn.textContent = 'Editor';\n } else {\n editorEl.style.display = 'block';\n wrapperEl.style.display = 'none';\n btn.classList.remove('active');\n btn.textContent = 'Preview';\n }\n }\n </script>\n <style>\n #preview-container { font-size: 15px; line-height: 1.7; }\n #preview-container h1 { font-size: 2em; margin: 0.5em 0 0.3em; border-bottom: 1px solid #3c3c3c; padding-bottom: 0.3em; }\n #preview-container h2 { font-size: 1.5em; margin: 0.5em 0 0.3em; border-bottom: 1px solid #3c3c3c; padding-bottom: 0.2em; }\n #preview-container h3 { font-size: 1.25em; margin: 0.4em 0 0.2em; }\n #preview-container p { margin: 0.5em 0; }\n #preview-container code { background: rgba(128,128,128,0.2); padding: 2px 6px; border-radius: 3px; font-size: 0.9em; }\n #preview-container pre { background: rgba(0,0,0,0.3); padding: 16px; border-radius: 6px; overflow-x: auto; margin: 0.5em 0; }\n #preview-container pre code { background: none; padding: 0; }\n #preview-container blockquote { border-left: 3px solid #505050; padding-left: 16px; margin: 0.5em 0; color: #969696; }\n #preview-container ul, #preview-container ol { padding-left: 24px; margin: 0.5em 0; }\n #preview-container table { border-collapse: collapse; margin: 0.5em 0; width: 100%; }\n #preview-container th, #preview-container td { border: 1px solid #3c3c3c; padding: 6px 12px; text-align: left; }\n #preview-container th { background: rgba(128,128,128,0.15); }\n #preview-container a { color: #3794ff; }\n #preview-container img { max-width: 100%; }\n </style>\n</body>\n</html>`\n}\n\nfunction formatBreadcrumb(filePath: string): string {\n const parts = filePath.split('/')\n if (parts.length <= 1) return `<span class=\"file-name\">${escapeHtml(filePath)}</span>`\n const dir = parts.slice(0, -1).join(' / ')\n const name = parts[parts.length - 1]\n return `<span class=\"file-path\">${escapeHtml(dir)} /</span> <span class=\"file-name\">${escapeHtml(name)}</span>`\n}\n","import { createPatch } from 'diff'\nimport type { ViewerEntry } from '../viewer-store.js'\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nconst MONACO_LANGUAGE: Record<string, string> = {\n typescript: 'typescript', javascript: 'javascript', python: 'python',\n rust: 'rust', go: 'go', java: 'java', kotlin: 'kotlin', ruby: 'ruby',\n php: 'php', c: 'c', cpp: 'cpp', csharp: 'csharp', swift: 'swift',\n bash: 'shell', json: 'json', yaml: 'yaml', toml: 'ini', xml: 'xml',\n html: 'html', css: 'css', scss: 'scss', sql: 'sql', markdown: 'markdown',\n dockerfile: 'dockerfile', hcl: 'hcl', plaintext: 'plaintext',\n}\n\nfunction getMonacoLang(lang?: string): string {\n if (!lang) return 'plaintext'\n return MONACO_LANGUAGE[lang] || 'plaintext'\n}\n\nexport function renderDiffViewer(entry: ViewerEntry): string {\n const fileName = entry.filePath || 'untitled'\n const lang = getMonacoLang(entry.language)\n const oldContent = entry.oldContent || ''\n const newContent = entry.content\n\n // Count changes for stats\n const patch = createPatch(fileName, oldContent, newContent, 'before', 'after')\n const adds = (patch.match(/^\\+[^+]/gm) || []).length\n const dels = (patch.match(/^-[^-]/gm) || []).length\n\n // Escape </script> in content\n const safeOld = JSON.stringify(oldContent).replace(/<\\//g, '<\\\\/')\n const safeNew = JSON.stringify(newContent).replace(/<\\//g, '<\\\\/')\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${escapeHtml(fileName)} (diff) - OpenACP</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body { background: #1e1e1e; color: #d4d4d4; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; display: flex; flex-direction: column; height: 100vh; }\n .header { background: #252526; border-bottom: 1px solid #3c3c3c; padding: 8px 16px; display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; z-index: 10; }\n .file-info { display: flex; align-items: center; gap: 8px; font-size: 13px; }\n .file-icon { font-size: 14px; }\n .file-name { color: #e0e0e0; font-weight: 500; }\n .stats { font-size: 12px; margin-left: 12px; }\n .stats .add { color: #4ec9b0; }\n .stats .del { color: #f14c4c; }\n .actions { display: flex; gap: 6px; }\n .btn { background: #3c3c3c; color: #d4d4d4; border: 1px solid #505050; padding: 4px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; transition: background 0.15s; }\n .btn:hover { background: #505050; }\n .btn.active { background: #0e639c; border-color: #1177bb; }\n #editor-container { flex: 1; overflow: hidden; }\n .status-bar { background: #007acc; color: #fff; padding: 2px 16px; font-size: 12px; display: flex; justify-content: space-between; flex-shrink: 0; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <div class=\"file-info\">\n <span class=\"file-icon\">📝</span>\n <span class=\"file-name\">${escapeHtml(fileName)}</span>\n <span class=\"stats\"><span class=\"add\">+${adds}</span> / <span class=\"del\">-${dels}</span></span>\n </div>\n <div class=\"actions\">\n <button class=\"btn active\" id=\"btn-side\" onclick=\"setView('side')\">Side by Side</button>\n <button class=\"btn\" id=\"btn-inline\" onclick=\"setView('inline')\">Inline</button>\n <button class=\"btn\" onclick=\"toggleTheme()\" id=\"btn-theme\">Light</button>\n </div>\n </div>\n <div id=\"editor-container\"></div>\n <div class=\"status-bar\">\n <span>${escapeHtml(entry.language || 'plaintext')} | <span class=\"add\">+${adds}</span> <span class=\"del\">-${dels}</span></span>\n <span>OpenACP Diff Viewer</span>\n </div>\n\n <script src=\"https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/loader.js\"></script>\n <script>\n const oldContent = ${safeOld};\n const newContent = ${safeNew};\n const lang = ${JSON.stringify(lang)};\n let diffEditor;\n let isDark = true;\n let renderSideBySide = true;\n\n require.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs' } });\n require(['vs/editor/editor.main'], function () {\n const originalModel = monaco.editor.createModel(oldContent, lang);\n const modifiedModel = monaco.editor.createModel(newContent, lang);\n\n diffEditor = monaco.editor.createDiffEditor(document.getElementById('editor-container'), {\n theme: 'vs-dark',\n readOnly: true,\n automaticLayout: true,\n renderSideBySide: true,\n scrollBeyondLastLine: false,\n fontSize: 13,\n fontFamily: \"'SF Mono', SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace\",\n padding: { top: 8 },\n enableSplitViewResizing: true,\n renderOverviewRuler: true,\n });\n\n diffEditor.setModel({ original: originalModel, modified: modifiedModel });\n });\n\n function setView(mode) {\n renderSideBySide = mode === 'side';\n diffEditor.updateOptions({ renderSideBySide });\n document.getElementById('btn-side').classList.toggle('active', renderSideBySide);\n document.getElementById('btn-inline').classList.toggle('active', !renderSideBySide);\n }\n\n function toggleTheme() {\n isDark = !isDark;\n monaco.editor.setTheme(isDark ? 'vs-dark' : 'vs');\n document.body.style.background = isDark ? '#1e1e1e' : '#ffffff';\n document.querySelector('.header').style.background = isDark ? '#252526' : '#f3f3f3';\n document.querySelector('.header').style.borderColor = isDark ? '#3c3c3c' : '#e0e0e0';\n document.getElementById('btn-theme').textContent = isDark ? 'Light' : 'Dark';\n }\n </script>\n</body>\n</html>`\n}\n"],"mappings":"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","names":["fs","path","os","resolve","spawn","log","resolve","spawn","spawn","log","resolve","spawn","spawn","log","resolve","spawn","log","path","os","fs","path","log","escapeHtml","MONACO_LANGUAGE","getMonacoLang","log","resolve"]}