@made-by-moonlight/athene-web 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +448 -0
  3. package/.next/app-path-routes-manifest.json +47 -0
  4. package/.next/build-manifest.json +33 -0
  5. package/.next/export-marker.json +6 -0
  6. package/.next/images-manifest.json +58 -0
  7. package/.next/next-minimal-server.js.nft.json +1 -0
  8. package/.next/next-server.js.nft.json +1 -0
  9. package/.next/package.json +1 -0
  10. package/.next/prerender-manifest.json +172 -0
  11. package/.next/react-loadable-manifest.json +61 -0
  12. package/.next/required-server-files.json +335 -0
  13. package/.next/routes-manifest.json +234 -0
  14. package/.next/server/app/_not-found/page.js +2 -0
  15. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  16. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  17. package/.next/server/app/_not-found.html +1 -0
  18. package/.next/server/app/_not-found.meta +8 -0
  19. package/.next/server/app/_not-found.rsc +24 -0
  20. package/.next/server/app/api/backlog/route.js +1 -0
  21. package/.next/server/app/api/backlog/route.js.nft.json +1 -0
  22. package/.next/server/app/api/backlog/route_client-reference-manifest.js +1 -0
  23. package/.next/server/app/api/browse-directory/route.js +1 -0
  24. package/.next/server/app/api/browse-directory/route.js.nft.json +1 -0
  25. package/.next/server/app/api/browse-directory/route_client-reference-manifest.js +1 -0
  26. package/.next/server/app/api/filesystem/browse/route.js +1 -0
  27. package/.next/server/app/api/filesystem/browse/route.js.nft.json +1 -0
  28. package/.next/server/app/api/filesystem/browse/route_client-reference-manifest.js +1 -0
  29. package/.next/server/app/api/issues/route.js +1 -0
  30. package/.next/server/app/api/issues/route.js.nft.json +1 -0
  31. package/.next/server/app/api/issues/route_client-reference-manifest.js +1 -0
  32. package/.next/server/app/api/observability/route.js +1 -0
  33. package/.next/server/app/api/observability/route.js.nft.json +1 -0
  34. package/.next/server/app/api/observability/route_client-reference-manifest.js +1 -0
  35. package/.next/server/app/api/orchestrators/route.js +1 -0
  36. package/.next/server/app/api/orchestrators/route.js.nft.json +1 -0
  37. package/.next/server/app/api/orchestrators/route_client-reference-manifest.js +1 -0
  38. package/.next/server/app/api/projects/[id]/route.js +5 -0
  39. package/.next/server/app/api/projects/[id]/route.js.nft.json +1 -0
  40. package/.next/server/app/api/projects/[id]/route_client-reference-manifest.js +1 -0
  41. package/.next/server/app/api/projects/reload/route.js +1 -0
  42. package/.next/server/app/api/projects/reload/route.js.nft.json +1 -0
  43. package/.next/server/app/api/projects/reload/route_client-reference-manifest.js +1 -0
  44. package/.next/server/app/api/projects/route.js +1 -0
  45. package/.next/server/app/api/projects/route.js.nft.json +1 -0
  46. package/.next/server/app/api/projects/route_client-reference-manifest.js +1 -0
  47. package/.next/server/app/api/prs/[id]/merge/route.js +1 -0
  48. package/.next/server/app/api/prs/[id]/merge/route.js.nft.json +1 -0
  49. package/.next/server/app/api/prs/[id]/merge/route_client-reference-manifest.js +1 -0
  50. package/.next/server/app/api/reviews/execute/route.js +1 -0
  51. package/.next/server/app/api/reviews/execute/route.js.nft.json +1 -0
  52. package/.next/server/app/api/reviews/execute/route_client-reference-manifest.js +1 -0
  53. package/.next/server/app/api/reviews/findings/route.js +1 -0
  54. package/.next/server/app/api/reviews/findings/route.js.nft.json +1 -0
  55. package/.next/server/app/api/reviews/findings/route_client-reference-manifest.js +1 -0
  56. package/.next/server/app/api/reviews/route.js +1 -0
  57. package/.next/server/app/api/reviews/route.js.nft.json +1 -0
  58. package/.next/server/app/api/reviews/route_client-reference-manifest.js +1 -0
  59. package/.next/server/app/api/reviews/send/route.js +1 -0
  60. package/.next/server/app/api/reviews/send/route.js.nft.json +1 -0
  61. package/.next/server/app/api/reviews/send/route_client-reference-manifest.js +1 -0
  62. package/.next/server/app/api/runtime/terminal/route.js +1 -0
  63. package/.next/server/app/api/runtime/terminal/route.js.nft.json +1 -0
  64. package/.next/server/app/api/runtime/terminal/route_client-reference-manifest.js +1 -0
  65. package/.next/server/app/api/sessions/[id]/kill/route.js +1 -0
  66. package/.next/server/app/api/sessions/[id]/kill/route.js.nft.json +1 -0
  67. package/.next/server/app/api/sessions/[id]/kill/route_client-reference-manifest.js +1 -0
  68. package/.next/server/app/api/sessions/[id]/message/route.js +1 -0
  69. package/.next/server/app/api/sessions/[id]/message/route.js.nft.json +1 -0
  70. package/.next/server/app/api/sessions/[id]/message/route_client-reference-manifest.js +1 -0
  71. package/.next/server/app/api/sessions/[id]/remap/route.js +1 -0
  72. package/.next/server/app/api/sessions/[id]/remap/route.js.nft.json +1 -0
  73. package/.next/server/app/api/sessions/[id]/remap/route_client-reference-manifest.js +1 -0
  74. package/.next/server/app/api/sessions/[id]/restore/route.js +1 -0
  75. package/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -0
  76. package/.next/server/app/api/sessions/[id]/restore/route_client-reference-manifest.js +1 -0
  77. package/.next/server/app/api/sessions/[id]/route.js +1 -0
  78. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -0
  79. package/.next/server/app/api/sessions/[id]/route_client-reference-manifest.js +1 -0
  80. package/.next/server/app/api/sessions/[id]/send/route.js +1 -0
  81. package/.next/server/app/api/sessions/[id]/send/route.js.nft.json +1 -0
  82. package/.next/server/app/api/sessions/[id]/send/route_client-reference-manifest.js +1 -0
  83. package/.next/server/app/api/sessions/patches/route.js +1 -0
  84. package/.next/server/app/api/sessions/patches/route.js.nft.json +1 -0
  85. package/.next/server/app/api/sessions/patches/route_client-reference-manifest.js +1 -0
  86. package/.next/server/app/api/sessions/route.js +1 -0
  87. package/.next/server/app/api/sessions/route.js.nft.json +1 -0
  88. package/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -0
  89. package/.next/server/app/api/setup-labels/route.js +1 -0
  90. package/.next/server/app/api/setup-labels/route.js.nft.json +1 -0
  91. package/.next/server/app/api/setup-labels/route_client-reference-manifest.js +1 -0
  92. package/.next/server/app/api/spawn/route.js +1 -0
  93. package/.next/server/app/api/spawn/route.js.nft.json +1 -0
  94. package/.next/server/app/api/spawn/route_client-reference-manifest.js +1 -0
  95. package/.next/server/app/api/update/route.js +1 -0
  96. package/.next/server/app/api/update/route.js.nft.json +1 -0
  97. package/.next/server/app/api/update/route_client-reference-manifest.js +1 -0
  98. package/.next/server/app/api/verify/route.js +1 -0
  99. package/.next/server/app/api/verify/route.js.nft.json +1 -0
  100. package/.next/server/app/api/verify/route_client-reference-manifest.js +1 -0
  101. package/.next/server/app/api/version/route.js +1 -0
  102. package/.next/server/app/api/version/route.js.nft.json +1 -0
  103. package/.next/server/app/api/version/route_client-reference-manifest.js +1 -0
  104. package/.next/server/app/api/webhooks/[...slug]/route.js +1 -0
  105. package/.next/server/app/api/webhooks/[...slug]/route.js.nft.json +1 -0
  106. package/.next/server/app/api/webhooks/[...slug]/route_client-reference-manifest.js +1 -0
  107. package/.next/server/app/apple-icon/route.js +1 -0
  108. package/.next/server/app/apple-icon/route.js.nft.json +1 -0
  109. package/.next/server/app/apple-icon/route_client-reference-manifest.js +1 -0
  110. package/.next/server/app/apple-icon.body +0 -0
  111. package/.next/server/app/apple-icon.meta +1 -0
  112. package/.next/server/app/dev/terminal-test/page.js +15 -0
  113. package/.next/server/app/dev/terminal-test/page.js.nft.json +1 -0
  114. package/.next/server/app/dev/terminal-test/page_client-reference-manifest.js +1 -0
  115. package/.next/server/app/dev/terminal-test.html +1 -0
  116. package/.next/server/app/dev/terminal-test.meta +7 -0
  117. package/.next/server/app/dev/terminal-test.rsc +28 -0
  118. package/.next/server/app/icon/route.js +1 -0
  119. package/.next/server/app/icon/route.js.nft.json +1 -0
  120. package/.next/server/app/icon/route_client-reference-manifest.js +1 -0
  121. package/.next/server/app/icon-192/route.js +1 -0
  122. package/.next/server/app/icon-192/route.js.nft.json +1 -0
  123. package/.next/server/app/icon-192/route_client-reference-manifest.js +1 -0
  124. package/.next/server/app/icon-512/route.js +1 -0
  125. package/.next/server/app/icon-512/route.js.nft.json +1 -0
  126. package/.next/server/app/icon-512/route_client-reference-manifest.js +1 -0
  127. package/.next/server/app/icon.body +0 -0
  128. package/.next/server/app/icon.meta +1 -0
  129. package/.next/server/app/manifest.webmanifest/route.js +16 -0
  130. package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -0
  131. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -0
  132. package/.next/server/app/manifest.webmanifest.body +1 -0
  133. package/.next/server/app/manifest.webmanifest.meta +1 -0
  134. package/.next/server/app/page.js +2 -0
  135. package/.next/server/app/page.js.nft.json +1 -0
  136. package/.next/server/app/page_client-reference-manifest.js +1 -0
  137. package/.next/server/app/projects/[projectId]/page.js +2 -0
  138. package/.next/server/app/projects/[projectId]/page.js.nft.json +1 -0
  139. package/.next/server/app/projects/[projectId]/page_client-reference-manifest.js +1 -0
  140. package/.next/server/app/projects/[projectId]/sessions/[id]/page.js +2 -0
  141. package/.next/server/app/projects/[projectId]/sessions/[id]/page.js.nft.json +1 -0
  142. package/.next/server/app/projects/[projectId]/sessions/[id]/page_client-reference-manifest.js +1 -0
  143. package/.next/server/app/projects/[projectId]/settings/page.js +2 -0
  144. package/.next/server/app/projects/[projectId]/settings/page.js.nft.json +1 -0
  145. package/.next/server/app/projects/[projectId]/settings/page_client-reference-manifest.js +1 -0
  146. package/.next/server/app/prs/page.js +2 -0
  147. package/.next/server/app/prs/page.js.nft.json +1 -0
  148. package/.next/server/app/prs/page_client-reference-manifest.js +1 -0
  149. package/.next/server/app/review/page.js +2 -0
  150. package/.next/server/app/review/page.js.nft.json +1 -0
  151. package/.next/server/app/review/page_client-reference-manifest.js +1 -0
  152. package/.next/server/app/reviews/page.js +2 -0
  153. package/.next/server/app/reviews/page.js.nft.json +1 -0
  154. package/.next/server/app/reviews/page_client-reference-manifest.js +1 -0
  155. package/.next/server/app/sessions/[id]/page.js +2 -0
  156. package/.next/server/app/sessions/[id]/page.js.nft.json +1 -0
  157. package/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -0
  158. package/.next/server/app/test-direct/page.js +2 -0
  159. package/.next/server/app/test-direct/page.js.nft.json +1 -0
  160. package/.next/server/app/test-direct/page_client-reference-manifest.js +1 -0
  161. package/.next/server/app/test-direct.html +1 -0
  162. package/.next/server/app/test-direct.meta +7 -0
  163. package/.next/server/app/test-direct.rsc +28 -0
  164. package/.next/server/app-paths-manifest.json +47 -0
  165. package/.next/server/chunks/1215.js +1 -0
  166. package/.next/server/chunks/1271.js +1 -0
  167. package/.next/server/chunks/2106.js +1 -0
  168. package/.next/server/chunks/2347.js +3 -0
  169. package/.next/server/chunks/2899.js +1 -0
  170. package/.next/server/chunks/2914.js +1 -0
  171. package/.next/server/chunks/4033.js +1 -0
  172. package/.next/server/chunks/4148.js +942 -0
  173. package/.next/server/chunks/4422.js +32 -0
  174. package/.next/server/chunks/5053.js +1 -0
  175. package/.next/server/chunks/5689.js +1 -0
  176. package/.next/server/chunks/6148.js +9 -0
  177. package/.next/server/chunks/6582.js +25 -0
  178. package/.next/server/chunks/7002.js +1 -0
  179. package/.next/server/chunks/7486.js +9 -0
  180. package/.next/server/chunks/8803.js +6 -0
  181. package/.next/server/chunks/9472.js +847 -0
  182. package/.next/server/chunks/9493.js +1 -0
  183. package/.next/server/chunks/9561.js +22 -0
  184. package/.next/server/chunks/966.js +1 -0
  185. package/.next/server/functions-config-manifest.json +4 -0
  186. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  187. package/.next/server/middleware-build-manifest.js +1 -0
  188. package/.next/server/middleware-manifest.json +6 -0
  189. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  190. package/.next/server/next-font-manifest.js +1 -0
  191. package/.next/server/next-font-manifest.json +1 -0
  192. package/.next/server/pages/404.html +1 -0
  193. package/.next/server/pages/500.html +1 -0
  194. package/.next/server/pages/_app.js +1 -0
  195. package/.next/server/pages/_app.js.nft.json +1 -0
  196. package/.next/server/pages/_document.js +1 -0
  197. package/.next/server/pages/_document.js.nft.json +1 -0
  198. package/.next/server/pages/_error.js +19 -0
  199. package/.next/server/pages/_error.js.nft.json +1 -0
  200. package/.next/server/pages-manifest.json +6 -0
  201. package/.next/server/server-reference-manifest.js +1 -0
  202. package/.next/server/server-reference-manifest.json +1 -0
  203. package/.next/server/webpack-runtime.js +1 -0
  204. package/.next/static/chunks/0f200859.359176a445d2791f.js +10 -0
  205. package/.next/static/chunks/1089-c6d7995c7c19039a.js +1 -0
  206. package/.next/static/chunks/1461-af7c54935f21d56d.js +1 -0
  207. package/.next/static/chunks/2073-4192de0bb00cc993.js +1 -0
  208. package/.next/static/chunks/3764.4c736d9a181489a4.js +1 -0
  209. package/.next/static/chunks/4115-1a4fa80ec67a29d3.js +1 -0
  210. package/.next/static/chunks/4751.6c71bfc0c4520627.js +1 -0
  211. package/.next/static/chunks/503.f7ff284457dd9c40.js +1 -0
  212. package/.next/static/chunks/5204.7de7e266895bced7.js +1 -0
  213. package/.next/static/chunks/6835.7a29fa4b665b7c2f.js +1 -0
  214. package/.next/static/chunks/7008-0d9bee1bf4bfcbea.js +1 -0
  215. package/.next/static/chunks/7317.685aa5231218e8d3.js +1 -0
  216. package/.next/static/chunks/8204-7c7837ed694da99c.js +1 -0
  217. package/.next/static/chunks/8713-d3d663f55dc00e48.js +1 -0
  218. package/.next/static/chunks/8759-490573536f93f85c.js +1 -0
  219. package/.next/static/chunks/88a6fc35-f836b4b72df5eafa.js +1 -0
  220. package/.next/static/chunks/9531-a5175e55fa0db48d.js +1 -0
  221. package/.next/static/chunks/9876-de0c5a1a319b4e8e.js +1 -0
  222. package/.next/static/chunks/app/_not-found/page-6add9dacf1870b4b.js +1 -0
  223. package/.next/static/chunks/app/api/backlog/route-6add9dacf1870b4b.js +1 -0
  224. package/.next/static/chunks/app/api/browse-directory/route-6add9dacf1870b4b.js +1 -0
  225. package/.next/static/chunks/app/api/filesystem/browse/route-6add9dacf1870b4b.js +1 -0
  226. package/.next/static/chunks/app/api/issues/route-6add9dacf1870b4b.js +1 -0
  227. package/.next/static/chunks/app/api/observability/route-6add9dacf1870b4b.js +1 -0
  228. package/.next/static/chunks/app/api/orchestrators/route-6add9dacf1870b4b.js +1 -0
  229. package/.next/static/chunks/app/api/projects/[id]/route-6add9dacf1870b4b.js +1 -0
  230. package/.next/static/chunks/app/api/projects/reload/route-6add9dacf1870b4b.js +1 -0
  231. package/.next/static/chunks/app/api/projects/route-6add9dacf1870b4b.js +1 -0
  232. package/.next/static/chunks/app/api/prs/[id]/merge/route-6add9dacf1870b4b.js +1 -0
  233. package/.next/static/chunks/app/api/reviews/execute/route-6add9dacf1870b4b.js +1 -0
  234. package/.next/static/chunks/app/api/reviews/findings/route-6add9dacf1870b4b.js +1 -0
  235. package/.next/static/chunks/app/api/reviews/route-6add9dacf1870b4b.js +1 -0
  236. package/.next/static/chunks/app/api/reviews/send/route-6add9dacf1870b4b.js +1 -0
  237. package/.next/static/chunks/app/api/runtime/terminal/route-6add9dacf1870b4b.js +1 -0
  238. package/.next/static/chunks/app/api/sessions/[id]/kill/route-6add9dacf1870b4b.js +1 -0
  239. package/.next/static/chunks/app/api/sessions/[id]/message/route-6add9dacf1870b4b.js +1 -0
  240. package/.next/static/chunks/app/api/sessions/[id]/remap/route-6add9dacf1870b4b.js +1 -0
  241. package/.next/static/chunks/app/api/sessions/[id]/restore/route-6add9dacf1870b4b.js +1 -0
  242. package/.next/static/chunks/app/api/sessions/[id]/route-6add9dacf1870b4b.js +1 -0
  243. package/.next/static/chunks/app/api/sessions/[id]/send/route-6add9dacf1870b4b.js +1 -0
  244. package/.next/static/chunks/app/api/sessions/patches/route-6add9dacf1870b4b.js +1 -0
  245. package/.next/static/chunks/app/api/sessions/route-6add9dacf1870b4b.js +1 -0
  246. package/.next/static/chunks/app/api/setup-labels/route-6add9dacf1870b4b.js +1 -0
  247. package/.next/static/chunks/app/api/spawn/route-6add9dacf1870b4b.js +1 -0
  248. package/.next/static/chunks/app/api/update/route-6add9dacf1870b4b.js +1 -0
  249. package/.next/static/chunks/app/api/verify/route-6add9dacf1870b4b.js +1 -0
  250. package/.next/static/chunks/app/api/version/route-6add9dacf1870b4b.js +1 -0
  251. package/.next/static/chunks/app/api/webhooks/[...slug]/route-6add9dacf1870b4b.js +1 -0
  252. package/.next/static/chunks/app/apple-icon/route-6add9dacf1870b4b.js +1 -0
  253. package/.next/static/chunks/app/dev/terminal-test/page-d0132109f9d8524e.js +1 -0
  254. package/.next/static/chunks/app/error-d632d0714b987864.js +1 -0
  255. package/.next/static/chunks/app/global-error-f6bef179169bcdae.js +1 -0
  256. package/.next/static/chunks/app/icon/route-6add9dacf1870b4b.js +1 -0
  257. package/.next/static/chunks/app/icon-192/route-6add9dacf1870b4b.js +1 -0
  258. package/.next/static/chunks/app/icon-512/route-6add9dacf1870b4b.js +1 -0
  259. package/.next/static/chunks/app/layout-5cac6fe817194d7a.js +1 -0
  260. package/.next/static/chunks/app/loading-6add9dacf1870b4b.js +1 -0
  261. package/.next/static/chunks/app/manifest.webmanifest/route-6add9dacf1870b4b.js +1 -0
  262. package/.next/static/chunks/app/not-found-cba3f587e1f98dcb.js +1 -0
  263. package/.next/static/chunks/app/page-cf7bccb75990950d.js +1 -0
  264. package/.next/static/chunks/app/projects/[projectId]/layout-6add9dacf1870b4b.js +1 -0
  265. package/.next/static/chunks/app/projects/[projectId]/loading-6add9dacf1870b4b.js +1 -0
  266. package/.next/static/chunks/app/projects/[projectId]/page-039a93b16089ed57.js +1 -0
  267. package/.next/static/chunks/app/projects/[projectId]/sessions/[id]/page-043b525bedb8f0f7.js +1 -0
  268. package/.next/static/chunks/app/projects/[projectId]/settings/page-63572555892d7a61.js +1 -0
  269. package/.next/static/chunks/app/projects/layout-d43b2e38d46221bd.js +1 -0
  270. package/.next/static/chunks/app/prs/page-e447852fbe0c6ee4.js +1 -0
  271. package/.next/static/chunks/app/review/page-022b2d2c326ff413.js +1 -0
  272. package/.next/static/chunks/app/reviews/page-6add9dacf1870b4b.js +1 -0
  273. package/.next/static/chunks/app/sessions/[id]/error-67c0d27f977a1cc1.js +1 -0
  274. package/.next/static/chunks/app/sessions/[id]/loading-6add9dacf1870b4b.js +1 -0
  275. package/.next/static/chunks/app/sessions/[id]/not-found-cba3f587e1f98dcb.js +1 -0
  276. package/.next/static/chunks/app/sessions/[id]/page-863cf8dd2c76d06d.js +1 -0
  277. package/.next/static/chunks/app/test-direct/page-8b80ed180c0f2f42.js +1 -0
  278. package/.next/static/chunks/e12b4bb0.8742134e1ac0263f.js +58 -0
  279. package/.next/static/chunks/framework-7060e2ac4971c604.js +1 -0
  280. package/.next/static/chunks/main-app-162601c3f1c01b19.js +1 -0
  281. package/.next/static/chunks/main-ed1610689fbd6f0d.js +1 -0
  282. package/.next/static/chunks/pages/_app-f4baf4dbe88f6f54.js +1 -0
  283. package/.next/static/chunks/pages/_error-a7f6723f42093f29.js +1 -0
  284. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  285. package/.next/static/chunks/webpack-f9566aaa604a1b07.js +1 -0
  286. package/.next/static/css/0c9b7451c2ce7c02.css +1 -0
  287. package/.next/static/css/7ca4e3753c1c7833.css +1 -0
  288. package/.next/static/css/b4a15f23f468892a.css +1 -0
  289. package/.next/static/css/d06ee45019116677.css +1 -0
  290. package/.next/static/media/91601dd83defba07-s.p.woff2 +0 -0
  291. package/.next/static/media/aa8291c31d4e9e54-s.p.woff2 +0 -0
  292. package/.next/static/pROr0laPuZIdA4NYNygMD/_buildManifest.js +1 -0
  293. package/.next/static/pROr0laPuZIdA4NYNygMD/_ssgManifest.js +1 -0
  294. package/LICENSE +22 -0
  295. package/dist-server/direct-terminal-ws.js +109 -0
  296. package/dist-server/mux-websocket.js +1162 -0
  297. package/dist-server/single-port-server.js +305 -0
  298. package/dist-server/start-all.js +150 -0
  299. package/dist-server/terminal-observability.js +16 -0
  300. package/dist-server/tmux-utils.js +301 -0
  301. package/next.config.js +71 -0
  302. package/package.json +97 -0
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Shared tmux utilities for terminal servers.
3
+ *
4
+ * Extracted from direct-terminal-ws.ts and terminal-websocket.ts
5
+ * so the logic can be properly unit tested.
6
+ */
7
+ import { execFile, execFileSync } from "node:child_process";
8
+ import { readdirSync, existsSync, readFileSync } from "node:fs";
9
+ import { homedir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { promisify } from "node:util";
12
+ import { isWindows } from "@made-by-moonlight/athene-core";
13
+ const execFileAsync = promisify(execFile);
14
+ /** Session ID validation regex — alphanumeric, hyphens, underscores only */
15
+ export const SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
16
+ /** Hash prefix pattern — 12-char lowercase hex, as generated by generateConfigHash */
17
+ const HASH_PREFIX_PATTERN = /^[a-f0-9]{12}-/;
18
+ /**
19
+ * StorageKey pattern — either bare 12-hex hash or `{hash}-{projectName}`
20
+ * wrapped form. The wrapped suffix comes from `basename(projectPath)` on
21
+ * disk so it can contain any character a filesystem path component allows
22
+ * (spaces, unicode, etc.); we only require that something non-empty
23
+ * follows the `-` separator. Security: storageKey is passed to
24
+ * `execFileSync` which bypasses the shell, so arbitrary characters are
25
+ * safe in the argv.
26
+ */
27
+ const STORAGE_KEY_PATTERN = /^[a-f0-9]{12}(-.+)?$/;
28
+ const defaultFs = {
29
+ // Only return subdirectory names. `readdirSync` without withFileTypes
30
+ // includes plain files, so a stray file like `aabbccddeef0` would pass
31
+ // STORAGE_KEY_PATTERN and trigger an unnecessary existsSync probe.
32
+ readdir: (p) => readdirSync(p, { withFileTypes: true })
33
+ .filter((e) => e.isDirectory())
34
+ .map((e) => e.name),
35
+ exists: (p) => existsSync(p),
36
+ homedir,
37
+ };
38
+ /**
39
+ * Find every storageKey that owns a given sessionId by scanning the AO
40
+ * base directory for projects whose `sessions/{sessionId}` file exists.
41
+ *
42
+ * This is the authoritative disambiguation step: tmux names alone are
43
+ * ambiguous when storageKey can take either the bare-hash or wrapped
44
+ * `{hash}-{projectName}` form. The on-disk session record is unique per
45
+ * storageKey so it tells us exactly which tmux name to expect.
46
+ *
47
+ * Returns all candidates (not just the first). Multiple projects can
48
+ * share a sessionId like `app-1`, and the caller must probe each until
49
+ * it finds a live tmux session — otherwise a stale metadata dir from
50
+ * one project could shadow the live session of another.
51
+ */
52
+ function findStorageKeysForSession(sessionId, fs, projectId) {
53
+ const aoBase = join(fs.homedir(), ".agent-orchestrator");
54
+ let entries;
55
+ try {
56
+ entries = fs.readdir(aoBase);
57
+ }
58
+ catch {
59
+ return [];
60
+ }
61
+ const matches = [];
62
+ const projectMatches = [];
63
+ for (const entry of entries) {
64
+ if (!STORAGE_KEY_PATTERN.test(entry))
65
+ continue;
66
+ const sessionFile = join(aoBase, entry, "sessions", sessionId);
67
+ if (fs.exists(sessionFile)) {
68
+ const unwrappedProjectId = entry.slice(13); // Strip "{hash}-" prefix when present.
69
+ if (projectId && (entry === projectId || unwrappedProjectId === projectId)) {
70
+ projectMatches.push(entry);
71
+ }
72
+ else {
73
+ matches.push(entry);
74
+ }
75
+ }
76
+ }
77
+ return [...projectMatches, ...matches];
78
+ }
79
+ /**
80
+ * Validate a session ID format.
81
+ * Prevents path traversal, shell injection, and other attacks.
82
+ */
83
+ export function validateSessionId(sessionId) {
84
+ return SESSION_ID_PATTERN.test(sessionId);
85
+ }
86
+ /**
87
+ * Find full path to tmux binary.
88
+ *
89
+ * Checks common installation locations because node-pty's posix_spawnp
90
+ * doesn't reliably inherit PATH, and some Node.js environments (e.g.,
91
+ * launched from GUI apps) have minimal PATH.
92
+ *
93
+ * @param execFn - Injectable execFileSync for testing. Defaults to child_process.execFileSync.
94
+ */
95
+ export function findTmux(execFn = execFileSync) {
96
+ if (isWindows())
97
+ return null;
98
+ const candidates = [
99
+ "/opt/homebrew/bin/tmux", // macOS ARM (Homebrew)
100
+ "/usr/local/bin/tmux", // macOS Intel (Homebrew)
101
+ "/usr/bin/tmux", // Linux
102
+ ];
103
+ for (const p of candidates) {
104
+ try {
105
+ execFn(p, ["-V"], { timeout: 5000 });
106
+ return p;
107
+ }
108
+ catch {
109
+ continue;
110
+ }
111
+ }
112
+ return "tmux"; // Fall back to bare name
113
+ }
114
+ /**
115
+ * Check whether a tmux session with the given name exists.
116
+ *
117
+ * Uses `=` exact-match prefix so the lookup never falls back to tmux's
118
+ * default prefix matching (where "ao-1" would match "ao-15"). The caller
119
+ * must already have the canonical tmux session name (typically the value
120
+ * returned by `resolveTmuxSession`).
121
+ *
122
+ * Async: this runs from inside node-pty's `onExit` callback on every agent
123
+ * exit, and the WebSocket server is single-threaded. A synchronous
124
+ * `execFileSync` here would block the event loop — and every WebSocket
125
+ * connection, HTTP request, and in-flight terminal — for up to the 5 s
126
+ * subprocess timeout when tmux is slow to respond. Use the promisified
127
+ * `execFile` form instead.
128
+ *
129
+ * @returns true if the session exists, false otherwise (including tmux
130
+ * not running, no sessions, or any unexpected error)
131
+ */
132
+ export async function tmuxHasSession(tmuxPath, tmuxSessionName, execFn = execFileAsync) {
133
+ if (!tmuxPath)
134
+ return false;
135
+ try {
136
+ await execFn(tmuxPath, ["has-session", "-t", `=${tmuxSessionName}`], { timeout: 5000 });
137
+ return true;
138
+ }
139
+ catch {
140
+ return false;
141
+ }
142
+ }
143
+ /**
144
+ * Resolve a user-facing session ID to its actual tmux session name.
145
+ *
146
+ * ao-core names tmux sessions as `{storageKey}-{sessionId}`, where
147
+ * storageKey is either `{12-hex}` (bare hash) or `{12-hex}-{projectName}`
148
+ * (legacy wrapped format). This function:
149
+ *
150
+ * 1. Tries exact match using tmux's `=` prefix syntax to prevent
151
+ * prefix matching (where "ao-1" would incorrectly match "ao-15").
152
+ * 2. Looks up the storageKey owning this sessionId on disk (under
153
+ * `~/.agent-orchestrator/{storageKey}/sessions/{sessionId}`) and asks
154
+ * tmux whether the exact `{storageKey}-{sessionId}` session exists.
155
+ * The on-disk check is authoritative — it avoids ambiguous suffix
156
+ * matches where a bare session like `{hash}-my-app-1` could be
157
+ * mistaken for a lookup of `app-1`.
158
+ * 3. Falls back to listing sessions and matching a hash-prefixed name
159
+ * whose remainder equals the sessionId (bare-hash only), so behavior
160
+ * stays correct even if the on-disk session record is absent.
161
+ *
162
+ * @param sessionId - User-facing session ID (e.g., "ao-15")
163
+ * @param tmuxPath - Full path to tmux binary
164
+ * @param execFn - Injectable execFileSync for testing. Defaults to child_process.execFileSync.
165
+ * @param fs - Injectable filesystem adapter for testing.
166
+ * @returns The actual tmux session name, or null if not found
167
+ */
168
+ export function resolveTmuxSession(sessionId, tmuxPath, execFn = execFileSync, fs = defaultFs, projectId) {
169
+ if (!tmuxPath)
170
+ return null;
171
+ // Try exact match first using = prefix for exact matching (e.g., "ao-orchestrator")
172
+ // Without =, tmux uses prefix matching: "ao-1" would match "ao-15"
173
+ try {
174
+ execFn(tmuxPath, ["has-session", "-t", `=${sessionId}`], { timeout: 5000 });
175
+ return sessionId;
176
+ }
177
+ catch {
178
+ // Not an exact match
179
+ }
180
+ // Authoritative path: find candidate storageKeys on disk, then verify
181
+ // each exact tmux session name with has-session. This is unambiguous
182
+ // even when the storageKey is wrapped (`{hash}-{projectName}`). Walk
183
+ // every candidate so a stale metadata dir in one project can't shadow
184
+ // the live session of another project with the same sessionId.
185
+ for (const storageKey of findStorageKeysForSession(sessionId, fs, projectId)) {
186
+ const tmuxName = `${storageKey}-${sessionId}`;
187
+ try {
188
+ execFn(tmuxPath, ["has-session", "-t", `=${tmuxName}`], { timeout: 5000 });
189
+ return tmuxName;
190
+ }
191
+ catch {
192
+ // Session dir exists but tmux session doesn't — try next candidate
193
+ }
194
+ }
195
+ // Fallback: list sessions and match the bare-hash form only. We
196
+ // intentionally do NOT match by trailing suffix here — that would cause
197
+ // `app-1` to falsely resolve a distinct session `{hash}-my-app-1`. If a
198
+ // wrapped-storageKey session isn't findable on disk above, it's safer
199
+ // to return null than to guess.
200
+ try {
201
+ const output = execFn(tmuxPath, ["list-sessions", "-F", "#{session_name}"], {
202
+ timeout: 5000,
203
+ encoding: "utf8",
204
+ });
205
+ const sessions = output.split("\n").filter(Boolean);
206
+ const match = sessions.find((s) => HASH_PREFIX_PATTERN.test(s) && s.substring(13) === sessionId);
207
+ if (match) {
208
+ return match;
209
+ }
210
+ }
211
+ catch {
212
+ // tmux not running or no sessions
213
+ }
214
+ return null;
215
+ }
216
+ /**
217
+ * Resolve a user-facing session ID to its Windows named pipe path.
218
+ *
219
+ * V2 layout (current): JSON metadata at
220
+ * `~/.agent-orchestrator/projects/{projectId}/sessions/{sessionId}.json`
221
+ * with `runtimeHandle.data.pipePath` as a top-level field.
222
+ *
223
+ * V1 layout (legacy fallback): line-delimited key=value at
224
+ * `~/.agent-orchestrator/{storageKey}/sessions/{sessionId}` where
225
+ * storageKey is bare 12-hex or `{hash}-{projectName}`. Kept so users
226
+ * who haven't run `athene migrate-storage` still see live sessions.
227
+ *
228
+ * When `projectId` is provided, only that project's metadata file is read.
229
+ * Without it (legacy callers), walks all projects and returns the first
230
+ * matching pipePath — which can collide when two projects share a sessionId.
231
+ *
232
+ * @returns Full pipe path (e.g., "\\\\.\\pipe\\ao-pty-win1-orchestrator"), or null
233
+ */
234
+ export function resolvePipePath(sessionId, projectId, fs = defaultFs) {
235
+ if (!isWindows())
236
+ return null;
237
+ const readFile = fs.readFile ?? ((p) => readFileSync(p, "utf8"));
238
+ const aoBase = join(fs.homedir(), ".agent-orchestrator");
239
+ const readPipeFromV2 = (project) => {
240
+ const sessionFile = join(aoBase, "projects", project, "sessions", `${sessionId}.json`);
241
+ if (!fs.exists(sessionFile))
242
+ return null;
243
+ try {
244
+ const meta = JSON.parse(readFile(sessionFile));
245
+ const pipePath = meta.runtimeHandle?.data?.pipePath;
246
+ return typeof pipePath === "string" && pipePath.length > 0 ? pipePath : null;
247
+ }
248
+ catch {
249
+ return null;
250
+ }
251
+ };
252
+ // V2: prefer the caller's projectId when provided; otherwise walk all projects
253
+ const projectsDir = join(aoBase, "projects");
254
+ if (projectId) {
255
+ const pipe = readPipeFromV2(projectId);
256
+ if (pipe)
257
+ return pipe;
258
+ }
259
+ else if (fs.exists(projectsDir)) {
260
+ let projects;
261
+ try {
262
+ projects = fs.readdir(projectsDir);
263
+ }
264
+ catch {
265
+ projects = [];
266
+ }
267
+ for (const project of projects) {
268
+ const pipe = readPipeFromV2(project);
269
+ if (pipe)
270
+ return pipe;
271
+ }
272
+ }
273
+ // V1 fallback: line-delimited key=value under {storageKey}/sessions/{sessionId}
274
+ for (const storageKey of findStorageKeysForSession(sessionId, {
275
+ readdir: fs.readdir,
276
+ exists: fs.exists,
277
+ homedir: fs.homedir,
278
+ })) {
279
+ const sessionFile = join(aoBase, storageKey, "sessions", sessionId);
280
+ let content;
281
+ try {
282
+ content = readFile(sessionFile);
283
+ }
284
+ catch {
285
+ continue;
286
+ }
287
+ const match = content.match(/^runtimeHandle=(.+)$/m);
288
+ if (!match)
289
+ continue;
290
+ try {
291
+ const handle = JSON.parse(match[1]);
292
+ const pipePath = handle.data?.pipePath;
293
+ if (pipePath && pipePath.length > 0)
294
+ return pipePath;
295
+ }
296
+ catch {
297
+ continue;
298
+ }
299
+ }
300
+ return null;
301
+ }
package/next.config.js ADDED
@@ -0,0 +1,71 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ /** @type {import('next').NextConfig} */
8
+ const homeDir = os.homedir().replace(/\\/g, "/");
9
+ const nextConfig = {
10
+ outputFileTracingRoot: path.join(__dirname, "../.."),
11
+ transpilePackages: [
12
+ "@made-by-moonlight/athene-plugin-agent-claude-code",
13
+ "@made-by-moonlight/athene-plugin-agent-codex",
14
+ "@made-by-moonlight/athene-plugin-agent-opencode",
15
+ "@made-by-moonlight/athene-plugin-runtime-tmux",
16
+ "@made-by-moonlight/athene-plugin-scm-github",
17
+ "@made-by-moonlight/athene-plugin-tracker-github",
18
+ "@made-by-moonlight/athene-plugin-tracker-linear",
19
+ "@made-by-moonlight/athene-plugin-workspace-worktree",
20
+ ],
21
+ serverExternalPackages: [
22
+ "yaml",
23
+ "zod",
24
+ "@made-by-moonlight/athene-core",
25
+ "better-sqlite3",
26
+ ],
27
+ webpack: (config, { isServer }) => {
28
+ if (process.platform === "win32") {
29
+ config.snapshot = {
30
+ ...config.snapshot,
31
+ managedPaths: [/^(.+?[\\/]node_modules[\\/])/],
32
+ };
33
+ // Prevent nft from globbing the home directory during server file tracing.
34
+ // ao-core resolves paths like ~/.agent-orchestrator at runtime; nft tries to
35
+ // scan them at build time and hits EPERM on Windows junction points
36
+ // (e.g. C:\Users\<user>\Application Data).
37
+ if (isServer) {
38
+ const tracePlugin = config.plugins.find(
39
+ (p) => p.constructor?.name === "TraceEntryPointsPlugin"
40
+ );
41
+ if (tracePlugin) {
42
+ tracePlugin.traceIgnores = [
43
+ ...(tracePlugin.traceIgnores ?? []),
44
+ `${homeDir}/**`,
45
+ ];
46
+ }
47
+ }
48
+ }
49
+ return config;
50
+ },
51
+ async headers() {
52
+ return [
53
+ {
54
+ source: "/sw.js",
55
+ headers: [
56
+ { key: "Cache-Control", value: "no-cache, no-store, must-revalidate" },
57
+ { key: "Service-Worker-Allowed", value: "/" },
58
+ ],
59
+ },
60
+ ];
61
+ },
62
+ };
63
+
64
+ // Only load bundle analyzer when ANALYZE=true (dev-only dependency)
65
+ let config = nextConfig;
66
+ if (process.env.ANALYZE === "true") {
67
+ const { default: bundleAnalyzer } = await import("@next/bundle-analyzer");
68
+ config = bundleAnalyzer({ enabled: true })(nextConfig);
69
+ }
70
+
71
+ export default config;
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "@made-by-moonlight/athene-web",
3
+ "version": "0.9.2",
4
+ "description": "Web dashboard for Athene",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/slievr/Athene.git",
10
+ "directory": "packages/web"
11
+ },
12
+ "homepage": "https://github.com/slievr/Athene",
13
+ "bugs": {
14
+ "url": "https://github.com/slievr/Athene/issues"
15
+ },
16
+ "engines": {
17
+ "node": ">=20.18.3"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "files": [
23
+ ".next/server",
24
+ ".next/static",
25
+ ".next/*.json",
26
+ ".next/BUILD_ID",
27
+ "dist-server",
28
+ "next.config.js"
29
+ ],
30
+ "dependencies": {
31
+ "@xterm/addon-fit": "0.12.0-beta.256",
32
+ "@xterm/addon-unicode11": "0.10.0-beta.256",
33
+ "@xterm/addon-web-links": "0.13.0-beta.256",
34
+ "@xterm/addon-webgl": "0.20.0-beta.255",
35
+ "@xterm/xterm": "6.1.0-beta.256",
36
+ "next": "^15.1.0",
37
+ "next-themes": "^0.4.6",
38
+ "react": "^19.0.0",
39
+ "react-dom": "^19.0.0",
40
+ "server-only": "^0.0.1",
41
+ "ws": "^8.19.0",
42
+ "@made-by-moonlight/athene-core": "0.9.1",
43
+ "@made-by-moonlight/athene-plugin-agent-claude-code": "0.9.1",
44
+ "@made-by-moonlight/athene-plugin-agent-codex": "0.9.1",
45
+ "@made-by-moonlight/athene-plugin-agent-grok": "0.1.3",
46
+ "@made-by-moonlight/athene-plugin-agent-cursor": "0.9.1",
47
+ "@made-by-moonlight/athene-plugin-agent-kimicode": "0.9.1",
48
+ "@made-by-moonlight/athene-plugin-agent-opencode": "0.9.1",
49
+ "@made-by-moonlight/athene-plugin-runtime-tmux": "0.9.1",
50
+ "@made-by-moonlight/athene-plugin-scm-github": "0.9.1",
51
+ "@made-by-moonlight/athene-plugin-tracker-linear": "0.9.1",
52
+ "@made-by-moonlight/athene-plugin-workspace-worktree": "0.9.1",
53
+ "@made-by-moonlight/athene-plugin-tracker-github": "0.9.1",
54
+ "@made-by-moonlight/athene-plugin-runtime-process": "0.9.1"
55
+ },
56
+ "optionalDependencies": {
57
+ "node-pty": "^1.1.0"
58
+ },
59
+ "devDependencies": {
60
+ "@next/bundle-analyzer": "^15.1.0",
61
+ "@tailwindcss/postcss": "^4.0.0",
62
+ "@testing-library/jest-dom": "^6.9.1",
63
+ "@testing-library/react": "^16.1.0",
64
+ "@types/react": "^19.0.0",
65
+ "@types/react-dom": "^19.0.0",
66
+ "@types/ws": "^8.18.1",
67
+ "@vitejs/plugin-react": "^4.3.0",
68
+ "@vitest/coverage-v8": "^3.2.4",
69
+ "concurrently": "^9.2.1",
70
+ "jsdom": "^25.0.0",
71
+ "node-gyp": "^12.2.0",
72
+ "playwright": "^1.49.0",
73
+ "rimraf": "^6.0.0",
74
+ "tailwindcss": "^4.0.0",
75
+ "tsx": "^4.19.0",
76
+ "typescript": "^5.7.0",
77
+ "vite": "^6.4.2",
78
+ "vitest": "^3.2.4"
79
+ },
80
+ "scripts": {
81
+ "dev": "concurrently \"npm:dev:next\" \"npm:dev:direct-terminal\"",
82
+ "dev:next": "next dev -p ${PORT:-3000}",
83
+ "dev:direct-terminal": "node scripts/dev-direct-terminal.mjs",
84
+ "prebuild": "node scripts/guard-production-artifact-clean.mjs && rimraf .next dist-server",
85
+ "build": "next build && tsc -p tsconfig.server.json && node scripts/stamp-version.js",
86
+ "start": "next start",
87
+ "start:all": "node dist-server/start-all.js",
88
+ "dev:optimized": "rimraf .next dist-server && next build && tsc -p tsconfig.server.json && node dist-server/start-all.js",
89
+ "typecheck": "tsc --noEmit",
90
+ "test": "vitest run",
91
+ "test:e2e:review": "tsx e2e/review-board.e2e.ts",
92
+ "test:watch": "vitest",
93
+ "clean": "node scripts/guard-production-artifact-clean.mjs && rimraf .next dist-server",
94
+ "screenshot": "tsx e2e/screenshot.ts",
95
+ "screenshot:install": "npx playwright install chromium"
96
+ }
97
+ }