vibepulse 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (420) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +4 -0
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/cache/.previewinfo +1 -1
  5. package/.next/cache/.rscinfo +1 -1
  6. package/.next/cache/.tsbuildinfo +1 -1
  7. package/.next/cache/config.json +3 -3
  8. package/.next/fallback-build-manifest.json +2 -2
  9. package/.next/prerender-manifest.json +3 -3
  10. package/.next/routes-manifest.json +32 -0
  11. package/.next/server/app/_global-error/page.js +1 -1
  12. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  13. package/.next/server/app/_global-error.html +2 -2
  14. package/.next/server/app/_global-error.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  16. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  17. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  18. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  19. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  20. package/.next/server/app/_not-found/page.js +1 -1
  21. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  22. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  23. package/.next/server/app/_not-found.html +1 -1
  24. package/.next/server/app/_not-found.rsc +2 -2
  25. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  26. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  27. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  28. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  29. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  30. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  31. package/.next/server/app/api/node/events/route.js +1 -1
  32. package/.next/server/app/api/node/events/route.js.nft.json +1 -1
  33. package/.next/server/app/api/node/health/route.js +1 -1
  34. package/.next/server/app/api/node/health/route.js.nft.json +1 -1
  35. package/.next/server/app/api/node/sessions/[id]/archive/route/app-paths-manifest.json +3 -0
  36. package/.next/server/app/api/node/sessions/[id]/archive/route/build-manifest.json +11 -0
  37. package/.next/server/app/api/node/sessions/[id]/archive/route/server-reference-manifest.json +4 -0
  38. package/.next/server/app/api/node/sessions/[id]/archive/route.js +6 -0
  39. package/.next/server/app/api/node/sessions/[id]/archive/route.js.map +5 -0
  40. package/.next/server/app/api/node/sessions/[id]/archive/route.js.nft.json +1 -0
  41. package/.next/server/app/api/node/sessions/[id]/archive/route_client-reference-manifest.js +2 -0
  42. package/.next/server/app/api/node/sessions/[id]/delete/route/app-paths-manifest.json +3 -0
  43. package/.next/server/app/api/node/sessions/[id]/delete/route/build-manifest.json +11 -0
  44. package/.next/server/app/api/node/sessions/[id]/delete/route/server-reference-manifest.json +4 -0
  45. package/.next/server/app/api/node/sessions/[id]/delete/route.js +7 -0
  46. package/.next/server/app/api/node/sessions/[id]/delete/route.js.map +5 -0
  47. package/.next/server/app/api/node/sessions/[id]/delete/route.js.nft.json +1 -0
  48. package/.next/server/app/api/node/sessions/[id]/delete/route_client-reference-manifest.js +2 -0
  49. package/.next/server/app/api/node/sessions/[id]/open-editor/route/app-paths-manifest.json +3 -0
  50. package/.next/server/app/api/node/sessions/[id]/open-editor/route/build-manifest.json +11 -0
  51. package/.next/server/app/api/node/sessions/[id]/open-editor/route/server-reference-manifest.json +4 -0
  52. package/.next/server/app/api/node/sessions/[id]/open-editor/route.js +7 -0
  53. package/.next/server/app/api/node/sessions/[id]/open-editor/route.js.map +5 -0
  54. package/.next/server/app/api/node/sessions/[id]/open-editor/route.js.nft.json +1 -0
  55. package/.next/server/app/api/node/sessions/[id]/open-editor/route_client-reference-manifest.js +2 -0
  56. package/.next/server/app/api/node/sessions/route.js +1 -1
  57. package/.next/server/app/api/node/sessions/route.js.nft.json +1 -1
  58. package/.next/server/app/api/opencode-events/route.js +1 -1
  59. package/.next/server/app/api/opencode-events/route.js.nft.json +1 -1
  60. package/.next/server/app/api/sessions/[id]/archive/route.js +2 -1
  61. package/.next/server/app/api/sessions/[id]/archive/route.js.nft.json +1 -1
  62. package/.next/server/app/api/sessions/[id]/delete/route.js +3 -2
  63. package/.next/server/app/api/sessions/[id]/delete/route.js.nft.json +1 -1
  64. package/.next/server/app/api/sessions/[id]/open-editor/route/app-paths-manifest.json +3 -0
  65. package/.next/server/app/api/sessions/[id]/open-editor/route/build-manifest.json +11 -0
  66. package/.next/server/app/api/sessions/[id]/open-editor/route/server-reference-manifest.json +4 -0
  67. package/.next/server/app/api/sessions/[id]/open-editor/route.js +7 -0
  68. package/.next/server/app/api/sessions/[id]/open-editor/route.js.map +5 -0
  69. package/.next/server/app/api/sessions/[id]/open-editor/route.js.nft.json +1 -0
  70. package/.next/server/app/api/sessions/[id]/open-editor/route_client-reference-manifest.js +2 -0
  71. package/.next/server/app/api/sessions/route.js +1 -1
  72. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  73. package/.next/server/app/index.html +1 -1
  74. package/.next/server/app/index.rsc +3 -3
  75. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  76. package/.next/server/app/index.segments/_full.segment.rsc +3 -3
  77. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  78. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  79. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  80. package/.next/server/app/page.js +1 -1
  81. package/.next/server/app/page.js.nft.json +1 -1
  82. package/.next/server/app/page_client-reference-manifest.js +1 -1
  83. package/.next/server/app-paths-manifest.json +4 -0
  84. package/.next/server/chunks/[root-of-the-server]__1211da38._.js +3 -0
  85. package/.next/server/chunks/[root-of-the-server]__1211da38._.js.map +1 -0
  86. package/.next/{standalone/.next/server/chunks/[root-of-the-server]__b698889b._.js → server/chunks/[root-of-the-server]__1b87ec42._.js} +2 -2
  87. package/.next/server/chunks/[root-of-the-server]__1b87ec42._.js.map +1 -0
  88. package/.next/server/chunks/[root-of-the-server]__2b526e7a._.js +3 -0
  89. package/.next/server/chunks/[root-of-the-server]__2b526e7a._.js.map +1 -0
  90. package/.next/server/chunks/[root-of-the-server]__2f981540._.js +3 -0
  91. package/.next/server/chunks/[root-of-the-server]__2f981540._.js.map +1 -0
  92. package/.next/server/chunks/[root-of-the-server]__3745b314._.js +3 -0
  93. package/.next/server/chunks/[root-of-the-server]__3745b314._.js.map +1 -0
  94. package/.next/server/chunks/[root-of-the-server]__56690af0._.js +1 -1
  95. package/.next/server/chunks/[root-of-the-server]__56690af0._.js.map +1 -1
  96. package/.next/server/chunks/[root-of-the-server]__56f5f249._.js +1 -1
  97. package/.next/server/chunks/[root-of-the-server]__56f5f249._.js.map +1 -1
  98. package/.next/server/chunks/[root-of-the-server]__59175de4._.js +1 -1
  99. package/.next/server/chunks/[root-of-the-server]__59175de4._.js.map +1 -1
  100. package/.next/server/chunks/[root-of-the-server]__64fffc02._.js +1 -1
  101. package/.next/server/chunks/[root-of-the-server]__64fffc02._.js.map +1 -1
  102. package/.next/server/chunks/[root-of-the-server]__6c428a24._.js +3 -0
  103. package/.next/server/chunks/[root-of-the-server]__6c428a24._.js.map +1 -0
  104. package/.next/server/chunks/[root-of-the-server]__73a00b88._.js +3 -0
  105. package/.next/server/chunks/[root-of-the-server]__73a00b88._.js.map +1 -0
  106. package/.next/server/chunks/[root-of-the-server]__89c5eeab._.js +1 -1
  107. package/.next/server/chunks/[root-of-the-server]__89c5eeab._.js.map +1 -1
  108. package/.next/server/chunks/[root-of-the-server]__8da6c5a8._.js +1 -1
  109. package/.next/server/chunks/[root-of-the-server]__8da6c5a8._.js.map +1 -1
  110. package/.next/server/chunks/[root-of-the-server]__b796d06c._.js +1 -1
  111. package/.next/server/chunks/[root-of-the-server]__b796d06c._.js.map +1 -1
  112. package/.next/server/chunks/[root-of-the-server]__c2ce5c0f._.js +1 -1
  113. package/.next/server/chunks/[root-of-the-server]__c2ce5c0f._.js.map +1 -1
  114. package/.next/server/chunks/[root-of-the-server]__d8e61048._.js +3 -0
  115. package/.next/server/chunks/[root-of-the-server]__d8e61048._.js.map +1 -0
  116. package/.next/server/chunks/[root-of-the-server]__db285678._.js +3 -0
  117. package/.next/server/chunks/[root-of-the-server]__db285678._.js.map +1 -0
  118. package/.next/{standalone/.next/server/chunks/[root-of-the-server]__16a9eb0a._.js → server/chunks/[root-of-the-server]__e00a9200._.js} +2 -2
  119. package/.next/server/chunks/{[root-of-the-server]__16a9eb0a._.js.map → [root-of-the-server]__e00a9200._.js.map} +1 -1
  120. package/.next/server/chunks/[root-of-the-server]__e5df5e5f._.js +3 -0
  121. package/.next/server/chunks/[root-of-the-server]__e5df5e5f._.js.map +1 -0
  122. package/.next/server/chunks/_next-internal_server_app_api_node_sessions_[id]_archive_route_actions_237255a5.js +3 -0
  123. package/.next/server/chunks/_next-internal_server_app_api_node_sessions_[id]_archive_route_actions_237255a5.js.map +1 -0
  124. package/.next/server/chunks/_next-internal_server_app_api_node_sessions_[id]_delete_route_actions_e5d426f6.js +3 -0
  125. package/.next/server/chunks/_next-internal_server_app_api_node_sessions_[id]_delete_route_actions_e5d426f6.js.map +1 -0
  126. package/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_open-editor_route_actions_eaebf476.js +3 -0
  127. package/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_open-editor_route_actions_eaebf476.js.map +1 -0
  128. package/.next/server/chunks/ce889_server_app_api_node_sessions_[id]_open-editor_route_actions_791cdf5b.js +3 -0
  129. package/.next/server/chunks/ce889_server_app_api_node_sessions_[id]_open-editor_route_actions_791cdf5b.js.map +1 -0
  130. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7e181e75.js +1 -1
  131. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7e181e75.js.map +1 -1
  132. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js +1 -1
  133. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js.map +1 -1
  134. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_fa835ac3.js +2 -2
  135. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_fa835ac3.js.map +1 -1
  136. package/.next/server/chunks/ssr/{[root-of-the-server]__efc52f08._.js → [root-of-the-server]__631e12d0._.js} +2 -2
  137. package/.next/server/chunks/ssr/[root-of-the-server]__a8cd3911._.js +3 -0
  138. package/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js +3 -3
  139. package/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js.map +1 -1
  140. package/.next/server/pages/404.html +1 -1
  141. package/.next/server/pages/500.html +2 -2
  142. package/.next/server/server-reference-manifest.js +1 -1
  143. package/.next/server/server-reference-manifest.json +1 -1
  144. package/.next/standalone/.next/BUILD_ID +1 -1
  145. package/.next/standalone/.next/app-path-routes-manifest.json +4 -0
  146. package/.next/standalone/.next/build-manifest.json +2 -2
  147. package/.next/standalone/.next/prerender-manifest.json +3 -3
  148. package/.next/standalone/.next/routes-manifest.json +32 -0
  149. package/.next/standalone/.next/server/app/_global-error/page.js +1 -1
  150. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  152. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  153. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  154. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  155. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  156. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  157. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  158. package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
  159. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  161. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  162. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  163. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  164. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  165. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  166. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  167. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  168. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  169. package/.next/standalone/.next/server/app/api/node/events/route.js +1 -1
  170. package/.next/standalone/.next/server/app/api/node/events/route.js.nft.json +1 -1
  171. package/.next/standalone/.next/server/app/api/node/health/route.js +1 -1
  172. package/.next/standalone/.next/server/app/api/node/health/route.js.nft.json +1 -1
  173. package/.next/standalone/.next/server/app/api/node/sessions/[id]/archive/route/app-paths-manifest.json +3 -0
  174. package/.next/standalone/.next/server/app/api/node/sessions/[id]/archive/route/build-manifest.json +11 -0
  175. package/.next/standalone/.next/server/app/api/node/sessions/[id]/archive/route/server-reference-manifest.json +4 -0
  176. package/.next/standalone/.next/server/app/api/node/sessions/[id]/archive/route.js +6 -0
  177. package/.next/standalone/.next/server/app/api/node/sessions/[id]/archive/route.js.map +5 -0
  178. package/.next/standalone/.next/server/app/api/node/sessions/[id]/archive/route.js.nft.json +1 -0
  179. package/.next/standalone/.next/server/app/api/node/sessions/[id]/archive/route_client-reference-manifest.js +2 -0
  180. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route/app-paths-manifest.json +3 -0
  181. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route/build-manifest.json +11 -0
  182. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route/server-reference-manifest.json +4 -0
  183. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route.js +7 -0
  184. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route.js.map +5 -0
  185. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route.js.nft.json +1 -0
  186. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route_client-reference-manifest.js +2 -0
  187. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route/app-paths-manifest.json +3 -0
  188. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route/build-manifest.json +11 -0
  189. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route/server-reference-manifest.json +4 -0
  190. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route.js +7 -0
  191. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route.js.map +5 -0
  192. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route.js.nft.json +1 -0
  193. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route_client-reference-manifest.js +2 -0
  194. package/.next/standalone/.next/server/app/api/node/sessions/route.js +1 -1
  195. package/.next/standalone/.next/server/app/api/node/sessions/route.js.nft.json +1 -1
  196. package/.next/standalone/.next/server/app/api/opencode-events/route.js +1 -1
  197. package/.next/standalone/.next/server/app/api/opencode-events/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/sessions/[id]/archive/route.js +2 -1
  199. package/.next/standalone/.next/server/app/api/sessions/[id]/archive/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/sessions/[id]/delete/route.js +3 -2
  201. package/.next/standalone/.next/server/app/api/sessions/[id]/delete/route.js.nft.json +1 -1
  202. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route/app-paths-manifest.json +3 -0
  203. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route/build-manifest.json +11 -0
  204. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route/server-reference-manifest.json +4 -0
  205. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route.js +7 -0
  206. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route.js.map +5 -0
  207. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route.js.nft.json +1 -0
  208. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route_client-reference-manifest.js +2 -0
  209. package/.next/standalone/.next/server/app/api/sessions/route.js +1 -1
  210. package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
  211. package/.next/standalone/.next/server/app/index.html +1 -1
  212. package/.next/standalone/.next/server/app/index.rsc +3 -3
  213. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  214. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
  215. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  216. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  217. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  218. package/.next/standalone/.next/server/app/page.js +1 -1
  219. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  220. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  221. package/.next/standalone/.next/server/app-paths-manifest.json +4 -0
  222. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1211da38._.js +3 -0
  223. package/.next/{server/chunks/[root-of-the-server]__b698889b._.js → standalone/.next/server/chunks/[root-of-the-server]__1b87ec42._.js} +2 -2
  224. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2b526e7a._.js +3 -0
  225. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2f981540._.js +3 -0
  226. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3745b314._.js +3 -0
  227. package/.next/standalone/.next/server/chunks/[root-of-the-server]__56690af0._.js +1 -1
  228. package/.next/standalone/.next/server/chunks/[root-of-the-server]__56f5f249._.js +1 -1
  229. package/.next/standalone/.next/server/chunks/[root-of-the-server]__59175de4._.js +1 -1
  230. package/.next/standalone/.next/server/chunks/[root-of-the-server]__64fffc02._.js +1 -1
  231. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c428a24._.js +3 -0
  232. package/.next/standalone/.next/server/chunks/[root-of-the-server]__73a00b88._.js +3 -0
  233. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89c5eeab._.js +1 -1
  234. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8da6c5a8._.js +1 -1
  235. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b796d06c._.js +1 -1
  236. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c2ce5c0f._.js +1 -1
  237. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d8e61048._.js +3 -0
  238. package/.next/standalone/.next/server/chunks/[root-of-the-server]__db285678._.js +3 -0
  239. package/.next/{server/chunks/[root-of-the-server]__16a9eb0a._.js → standalone/.next/server/chunks/[root-of-the-server]__e00a9200._.js} +2 -2
  240. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e5df5e5f._.js +3 -0
  241. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_node_sessions_[id]_archive_route_actions_237255a5.js +3 -0
  242. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_node_sessions_[id]_delete_route_actions_e5d426f6.js +3 -0
  243. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_open-editor_route_actions_eaebf476.js +3 -0
  244. package/.next/standalone/.next/server/chunks/ce889_server_app_api_node_sessions_[id]_open-editor_route_actions_791cdf5b.js +3 -0
  245. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7e181e75.js +1 -1
  246. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js +1 -1
  247. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_fa835ac3.js +2 -2
  248. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__efc52f08._.js → [root-of-the-server]__631e12d0._.js} +2 -2
  249. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__a8cd3911._.js +3 -0
  250. package/.next/standalone/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js +3 -3
  251. package/.next/standalone/.next/server/pages/404.html +1 -1
  252. package/.next/standalone/.next/server/pages/500.html +2 -2
  253. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  254. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  255. package/.next/standalone/.next/static/chunks/7ac19aaef01f4a03.js +13 -0
  256. package/.next/standalone/.next/static/chunks/f42202943f6742e5.css +3 -0
  257. package/.next/standalone/AGENTS.md +85 -0
  258. package/.next/standalone/README.md +76 -0
  259. package/.next/standalone/__mocks__/child_process.ts +4 -0
  260. package/.next/standalone/bin/dev-runtime.js +58 -0
  261. package/.next/standalone/bin/vibepulse.js +87 -0
  262. package/.next/standalone/check-hsql.mjs +71 -0
  263. package/.next/standalone/docs/session-status-detection.md +258 -0
  264. package/.next/standalone/eslint.config.mjs +31 -0
  265. package/.next/standalone/next.config.ts +8 -0
  266. package/.next/standalone/package-lock.json +10312 -0
  267. package/.next/standalone/package.json +1 -1
  268. package/.next/standalone/postcss.config.mjs +7 -0
  269. package/.next/standalone/src/AGENTS.md +41 -0
  270. package/.next/standalone/src/app/api/AGENTS.md +40 -0
  271. package/.next/standalone/src/app/api/node/events/route.test.ts +196 -0
  272. package/.next/standalone/src/app/api/node/events/route.ts +259 -0
  273. package/.next/standalone/src/app/api/node/health/route.test.ts +190 -0
  274. package/.next/standalone/src/app/api/node/health/route.ts +48 -0
  275. package/.next/standalone/src/app/api/node/sessions/[id]/archive/route.test.ts +128 -0
  276. package/.next/standalone/src/app/api/node/sessions/[id]/archive/route.ts +97 -0
  277. package/.next/standalone/src/app/api/node/sessions/[id]/delete/route.test.ts +113 -0
  278. package/.next/standalone/src/app/api/node/sessions/[id]/delete/route.ts +81 -0
  279. package/.next/standalone/src/app/api/node/sessions/[id]/open-editor/route.test.ts +206 -0
  280. package/.next/standalone/src/app/api/node/sessions/[id]/open-editor/route.ts +123 -0
  281. package/.next/standalone/src/app/api/node/sessions/route.test.ts +408 -0
  282. package/.next/standalone/src/app/api/node/sessions/route.ts +1094 -0
  283. package/.next/standalone/src/app/api/nodes/route.test.ts +237 -0
  284. package/.next/standalone/src/app/api/nodes/route.ts +176 -0
  285. package/.next/standalone/src/app/api/opencode-config/route.test.ts +86 -0
  286. package/.next/standalone/src/app/api/opencode-config/route.ts +376 -0
  287. package/.next/standalone/src/app/api/opencode-config/status/route.ts +31 -0
  288. package/.next/standalone/src/app/api/opencode-events/route.test.ts +624 -0
  289. package/.next/standalone/src/app/api/opencode-events/route.ts +508 -0
  290. package/.next/standalone/src/app/api/opencode-models/route.test.ts +167 -0
  291. package/.next/standalone/src/app/api/opencode-models/route.ts +76 -0
  292. package/.next/standalone/src/app/api/profiles/[id]/apply/route.ts +49 -0
  293. package/.next/standalone/src/app/api/profiles/[id]/export/route.ts +31 -0
  294. package/.next/standalone/src/app/api/profiles/[id]/route.ts +160 -0
  295. package/.next/standalone/src/app/api/profiles/import/route.test.js +107 -0
  296. package/.next/standalone/src/app/api/profiles/import/route.ts +65 -0
  297. package/.next/standalone/src/app/api/profiles/route.ts +107 -0
  298. package/.next/standalone/src/app/api/sessions/[id]/archive/route.test.ts +136 -0
  299. package/.next/standalone/src/app/api/sessions/[id]/archive/route.ts +170 -0
  300. package/.next/standalone/src/app/api/sessions/[id]/delete/route.test.ts +113 -0
  301. package/.next/standalone/src/app/api/sessions/[id]/delete/route.ts +137 -0
  302. package/.next/standalone/src/app/api/sessions/[id]/open-editor/route.test.ts +218 -0
  303. package/.next/standalone/src/app/api/sessions/[id]/open-editor/route.ts +85 -0
  304. package/.next/standalone/src/app/api/sessions/[id]/route.test.ts +531 -0
  305. package/.next/standalone/src/app/api/sessions/[id]/route.ts +75 -0
  306. package/.next/standalone/src/app/api/sessions/route.test.ts +1298 -0
  307. package/.next/standalone/src/app/api/sessions/route.ts +1695 -0
  308. package/.next/standalone/src/app/favicon.ico +0 -0
  309. package/.next/standalone/src/app/globals.css +66 -0
  310. package/.next/standalone/src/app/layout.tsx +37 -0
  311. package/.next/standalone/src/app/page.test.tsx +134 -0
  312. package/.next/standalone/src/app/page.tsx +358 -0
  313. package/.next/standalone/src/components/AGENTS.md +42 -0
  314. package/.next/standalone/src/components/ErrorBoundary.tsx +72 -0
  315. package/.next/standalone/src/components/KanbanBoard.test.tsx +704 -0
  316. package/.next/standalone/src/components/KanbanBoard.tsx +852 -0
  317. package/.next/standalone/src/components/LoadingState.tsx +37 -0
  318. package/.next/standalone/src/components/ProjectCard.test.tsx +773 -0
  319. package/.next/standalone/src/components/ProjectCard.tsx +595 -0
  320. package/.next/standalone/src/components/QueryProvider.tsx +25 -0
  321. package/.next/standalone/src/components/SessionCard.test.tsx +566 -0
  322. package/.next/standalone/src/components/SessionCard.tsx +434 -0
  323. package/.next/standalone/src/components/SessionList.tsx +60 -0
  324. package/.next/standalone/src/components/host-config/HostManagerDialog.test.tsx +252 -0
  325. package/.next/standalone/src/components/host-config/HostManagerDialog.tsx +476 -0
  326. package/.next/standalone/src/components/opencode-config/AgentConfigForm.test.tsx +72 -0
  327. package/.next/standalone/src/components/opencode-config/AgentConfigForm.tsx +483 -0
  328. package/.next/standalone/src/components/opencode-config/AgentModelSelector.tsx +284 -0
  329. package/.next/standalone/src/components/opencode-config/AgentsConfigPanel.tsx +162 -0
  330. package/.next/standalone/src/components/opencode-config/ConfigButton.tsx +43 -0
  331. package/.next/standalone/src/components/opencode-config/ConfigPanel.tsx +91 -0
  332. package/.next/standalone/src/components/opencode-config/FullscreenConfigPanel.tsx +435 -0
  333. package/.next/standalone/src/components/opencode-config/GeneralSettingsForm.test.tsx +91 -0
  334. package/.next/standalone/src/components/opencode-config/GeneralSettingsForm.tsx +288 -0
  335. package/.next/standalone/src/components/opencode-config/categories/CategoriesList.tsx +382 -0
  336. package/.next/standalone/src/components/opencode-config/categories/CategoriesManager.test.tsx +111 -0
  337. package/.next/standalone/src/components/opencode-config/categories/CategoriesManager.tsx +174 -0
  338. package/.next/standalone/src/components/opencode-config/categories/CategoryConfigForm.tsx +453 -0
  339. package/.next/standalone/src/components/opencode-config/profiles/ProfileCard.tsx +140 -0
  340. package/.next/standalone/src/components/opencode-config/profiles/ProfileEditor.tsx +446 -0
  341. package/.next/standalone/src/components/opencode-config/profiles/ProfileList.tsx +446 -0
  342. package/.next/standalone/src/components/opencode-config/profiles/ProfileManager.test.tsx +225 -0
  343. package/.next/standalone/src/components/opencode-config/profiles/ProfileManager.tsx +405 -0
  344. package/.next/standalone/src/components/ui/Tabs.tsx +59 -0
  345. package/.next/standalone/src/hooks/useHostSources.test.ts +509 -0
  346. package/.next/standalone/src/hooks/useHostSources.ts +299 -0
  347. package/.next/standalone/src/hooks/useOpencodeSync.test.ts +387 -0
  348. package/.next/standalone/src/hooks/useOpencodeSync.ts +571 -0
  349. package/.next/standalone/src/index.ts +2 -0
  350. package/.next/standalone/src/lib/editorLauncher.server.ts +36 -0
  351. package/.next/standalone/src/lib/editorLauncher.test.ts +35 -0
  352. package/.next/standalone/src/lib/editorLauncher.ts +25 -0
  353. package/.next/standalone/src/lib/hostAccent.test.ts +58 -0
  354. package/.next/standalone/src/lib/hostAccent.ts +46 -0
  355. package/.next/standalone/src/lib/hostIdentity.test.ts +187 -0
  356. package/.next/standalone/src/lib/hostIdentity.ts +122 -0
  357. package/.next/standalone/src/lib/hostSourcesStorage.test.ts +141 -0
  358. package/.next/standalone/src/lib/hostSourcesStorage.ts +72 -0
  359. package/.next/standalone/src/lib/nodeProtocol.test.ts +159 -0
  360. package/.next/standalone/src/lib/nodeProtocol.ts +142 -0
  361. package/.next/standalone/src/lib/nodeRegistry.test.ts +173 -0
  362. package/.next/standalone/src/lib/nodeRegistry.ts +398 -0
  363. package/.next/standalone/src/lib/notificationSound.ts +292 -0
  364. package/.next/standalone/src/lib/opencodeConfig.test.ts +100 -0
  365. package/.next/standalone/src/lib/opencodeConfig.ts +76 -0
  366. package/.next/standalone/src/lib/opencodeDiscovery.ts +275 -0
  367. package/.next/standalone/src/lib/profiles/share.test.ts +91 -0
  368. package/.next/standalone/src/lib/profiles/share.ts +93 -0
  369. package/.next/standalone/src/lib/profiles/storage.test.ts +108 -0
  370. package/.next/standalone/src/lib/profiles/storage.ts +370 -0
  371. package/.next/standalone/src/lib/runtimeMode.test.ts +29 -0
  372. package/.next/standalone/src/lib/runtimeMode.ts +29 -0
  373. package/.next/standalone/src/lib/sessionActionErrors.ts +37 -0
  374. package/.next/standalone/src/lib/sessionArchiveOverrides.test.ts +43 -0
  375. package/.next/standalone/src/lib/sessionArchiveOverrides.ts +116 -0
  376. package/.next/standalone/src/lib/transform.test.ts +121 -0
  377. package/.next/standalone/src/lib/transform.ts +193 -0
  378. package/.next/standalone/src/test/setup.ts +8 -0
  379. package/.next/standalone/src/types/index.ts +152 -0
  380. package/.next/standalone/src/types/opencodeConfig.ts +149 -0
  381. package/.next/standalone/tsconfig.json +34 -0
  382. package/.next/standalone/tsconfig.lib.json +17 -0
  383. package/.next/standalone/vitest.config.ts +16 -0
  384. package/.next/static/chunks/7ac19aaef01f4a03.js +13 -0
  385. package/.next/static/chunks/f42202943f6742e5.css +3 -0
  386. package/.next/trace +1 -1
  387. package/.next/trace-build +1 -1
  388. package/.next/types/routes.d.ts +5 -1
  389. package/.next/types/validator.ts +36 -0
  390. package/package.json +1 -1
  391. package/.next/server/chunks/[root-of-the-server]__0b017945._.js +0 -3
  392. package/.next/server/chunks/[root-of-the-server]__0b017945._.js.map +0 -1
  393. package/.next/server/chunks/[root-of-the-server]__1e118bd3._.js +0 -3
  394. package/.next/server/chunks/[root-of-the-server]__1e118bd3._.js.map +0 -1
  395. package/.next/server/chunks/[root-of-the-server]__6979e732._.js +0 -3
  396. package/.next/server/chunks/[root-of-the-server]__6979e732._.js.map +0 -1
  397. package/.next/server/chunks/[root-of-the-server]__a7b4d79d._.js +0 -3
  398. package/.next/server/chunks/[root-of-the-server]__a7b4d79d._.js.map +0 -1
  399. package/.next/server/chunks/[root-of-the-server]__b698889b._.js.map +0 -1
  400. package/.next/server/chunks/[root-of-the-server]__ddc251b7._.js +0 -3
  401. package/.next/server/chunks/[root-of-the-server]__ddc251b7._.js.map +0 -1
  402. package/.next/server/chunks/ssr/[root-of-the-server]__b0788643._.js +0 -3
  403. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b017945._.js +0 -3
  404. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1e118bd3._.js +0 -3
  405. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6979e732._.js +0 -3
  406. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a7b4d79d._.js +0 -3
  407. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ddc251b7._.js +0 -3
  408. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b0788643._.js +0 -3
  409. package/.next/standalone/.next/static/chunks/9f8c22002e7395e8.js +0 -13
  410. package/.next/standalone/.next/static/chunks/f1b55db60e7ed6f3.css +0 -3
  411. package/.next/static/chunks/9f8c22002e7395e8.js +0 -13
  412. package/.next/static/chunks/f1b55db60e7ed6f3.css +0 -3
  413. /package/.next/server/chunks/ssr/{[root-of-the-server]__efc52f08._.js.map → [root-of-the-server]__631e12d0._.js.map} +0 -0
  414. /package/.next/server/chunks/ssr/{[root-of-the-server]__b0788643._.js.map → [root-of-the-server]__a8cd3911._.js.map} +0 -0
  415. /package/.next/standalone/.next/static/{L_tmqf71LaeMzApO4SiU- → Fw2R3y-fHX4B2SWxNy_4X}/_buildManifest.js +0 -0
  416. /package/.next/standalone/.next/static/{L_tmqf71LaeMzApO4SiU- → Fw2R3y-fHX4B2SWxNy_4X}/_clientMiddlewareManifest.json +0 -0
  417. /package/.next/standalone/.next/static/{L_tmqf71LaeMzApO4SiU- → Fw2R3y-fHX4B2SWxNy_4X}/_ssgManifest.js +0 -0
  418. /package/.next/static/{L_tmqf71LaeMzApO4SiU- → Fw2R3y-fHX4B2SWxNy_4X}/_buildManifest.js +0 -0
  419. /package/.next/static/{L_tmqf71LaeMzApO4SiU- → Fw2R3y-fHX4B2SWxNy_4X}/_clientMiddlewareManifest.json +0 -0
  420. /package/.next/static/{L_tmqf71LaeMzApO4SiU- → Fw2R3y-fHX4B2SWxNy_4X}/_ssgManifest.js +0 -0
@@ -0,0 +1,595 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useMemo, useRef, useState } from 'react';
4
+ import { useQuery, useQueryClient } from '@tanstack/react-query';
5
+ import { KanbanCard } from '@/types';
6
+ import { buildEditorUri } from '@/lib/editorLauncher';
7
+ import { getHostAccentTextClass } from '@/lib/hostAccent';
8
+ import { mapSessionActionError } from '@/lib/sessionActionErrors';
9
+
10
+ interface ConfigResponse {
11
+ vibepulse?: {
12
+ openEditorTargetMode?: 'remote' | 'hub';
13
+ };
14
+ }
15
+
16
+ interface ProjectCardProps {
17
+ projectName: string;
18
+ branch?: string;
19
+ cards: KanbanCard[];
20
+ readOnly?: boolean;
21
+ hostLabel?: string;
22
+ multipleHostsEnabled?: boolean;
23
+ }
24
+
25
+ function formatRelativeTime(timestamp: number): string {
26
+ const diffMs = Date.now() - timestamp;
27
+ const diffMins = Math.floor(diffMs / (1000 * 60));
28
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
29
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
30
+
31
+ if (diffMins < 1) return '<1m';
32
+ if (diffHours < 1) return `${diffMins}m`;
33
+ if (diffDays < 1) return `${diffHours}h`;
34
+ return `${diffDays}d`;
35
+ }
36
+
37
+ function buildTooltipTitle(lines: string[], debugReason?: string): string {
38
+ return debugReason ? [...lines, `Reason: ${debugReason}`].join('\n') : lines.join('\n');
39
+ }
40
+
41
+ function StatusDot({ status, waitingForUser }: { status: string; waitingForUser: boolean }) {
42
+ if (waitingForUser) {
43
+ return (
44
+ <span className="relative flex h-2 w-2 flex-shrink-0" title="Waiting">
45
+ <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75"></span>
46
+ <span className="relative inline-flex rounded-full h-2 w-2 bg-amber-500"></span>
47
+ </span>
48
+ );
49
+ }
50
+ switch (status) {
51
+ case 'busy':
52
+ return (
53
+ <span className="relative flex h-2 w-2 flex-shrink-0" title="Running">
54
+ <span className="animate-pulse absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
55
+ <span className="relative inline-flex rounded-full h-2 w-2 bg-emerald-500"></span>
56
+ </span>
57
+ );
58
+ case 'retry':
59
+ return (
60
+ <span className="relative flex h-2 w-2 flex-shrink-0" title="Retrying">
61
+ <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-red-400 opacity-75"></span>
62
+ <span className="relative inline-flex rounded-full h-2 w-2 bg-red-500"></span>
63
+ </span>
64
+ );
65
+ default:
66
+ return <span className="inline-flex rounded-full h-2 w-2 bg-gray-400 flex-shrink-0" title="Idle"></span>;
67
+ }
68
+ }
69
+
70
+ function HeaderActionMenu({ cards, readOnly = false, isActionPending, onActionError, onPendingActionChange }: { cards: KanbanCard[]; readOnly?: boolean; isActionPending: boolean; onActionError: (message: string | null) => void; onPendingActionChange: (value: 'open' | 'archive' | 'delete' | null) => void }) {
71
+ const queryClient = useQueryClient();
72
+ const [open, setOpen] = useState(false);
73
+ const menuRef = useRef<HTMLDivElement>(null);
74
+
75
+ useEffect(() => {
76
+ if (!open) return;
77
+ const handler = (e: MouseEvent) => {
78
+ if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
79
+ setOpen(false);
80
+ }
81
+ };
82
+ document.addEventListener('mousedown', handler);
83
+ return () => document.removeEventListener('mousedown', handler);
84
+ }, [open]);
85
+
86
+ const hasUnarchived = cards.some(c => c.status !== 'done');
87
+ const hasMixedHosts = new Set(cards.map((card) => card.hostId ?? 'local')).size > 1;
88
+
89
+ const handleArchiveAll = async (e: React.MouseEvent) => {
90
+ e.stopPropagation();
91
+ if (isActionPending) return;
92
+ onActionError(null);
93
+ if (hasMixedHosts) {
94
+ onActionError('Mixed-host archive is not supported');
95
+ setOpen(false);
96
+ return;
97
+ }
98
+
99
+ const unarchivedCards = cards.filter(c => c.status !== 'done');
100
+ onPendingActionChange('archive');
101
+ try {
102
+ const responses = await Promise.all(unarchivedCards.map(card =>
103
+ fetch(`/api/sessions/${card.id}/archive`, { method: 'POST' })
104
+ ));
105
+ const failedResponse = responses.find((response) => !response.ok);
106
+ if (failedResponse) {
107
+ const errorBody = await failedResponse.json().catch(() => null);
108
+ onActionError(mapSessionActionError(errorBody, 'Failed to archive sessions'));
109
+ }
110
+ } catch {
111
+ onActionError('Remote node is offline or unreachable.');
112
+ } finally {
113
+ onPendingActionChange(null);
114
+ }
115
+ setOpen(false);
116
+ await queryClient.invalidateQueries({ queryKey: ['sessions'] });
117
+ };
118
+
119
+ const handleDeleteAll = async (e: React.MouseEvent) => {
120
+ e.stopPropagation();
121
+ if (isActionPending) return;
122
+ onActionError(null);
123
+ if (hasMixedHosts) {
124
+ onActionError('Mixed-host delete is not supported');
125
+ setOpen(false);
126
+ return;
127
+ }
128
+
129
+ if (!confirm(`Delete ${cards.length} session(s)? This cannot be undone.`)) return;
130
+ onPendingActionChange('delete');
131
+ try {
132
+ const responses = await Promise.all(cards.map(card =>
133
+ fetch(`/api/sessions/${card.id}/delete`, { method: 'POST' })
134
+ ));
135
+ const failedResponse = responses.find((response) => !response.ok);
136
+ if (failedResponse) {
137
+ const errorBody = await failedResponse.json().catch(() => null);
138
+ onActionError(mapSessionActionError(errorBody, 'Failed to delete sessions'));
139
+ }
140
+ } catch {
141
+ onActionError('Remote node is offline or unreachable.');
142
+ } finally {
143
+ onPendingActionChange(null);
144
+ }
145
+ setOpen(false);
146
+ await queryClient.invalidateQueries({ queryKey: ['sessions'] });
147
+ };
148
+
149
+ if (readOnly) return null;
150
+
151
+ return (
152
+ <div className="relative" ref={menuRef}>
153
+ <button
154
+ type="button"
155
+ className="w-5 h-5 flex items-center justify-center rounded-full text-gray-400 hover:text-gray-700 hover:bg-gray-200/80 dark:text-gray-400 dark:hover:text-gray-200 dark:hover:bg-zinc-600 transition-colors"
156
+ onClick={(e) => { e.stopPropagation(); if (!isActionPending) setOpen(!open); }}
157
+ title="Batch actions"
158
+ disabled={isActionPending}
159
+ >
160
+ <svg className="w-3.5 h-3.5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
161
+ <path d="M5 10a2 2 0 110 4 2 2 0 010-4zm7 0a2 2 0 110 4 2 2 0 010-4zm7 0a2 2 0 110 4 2 2 0 010-4z" />
162
+ </svg>
163
+ </button>
164
+ {open && (
165
+ <div className="absolute right-0 top-6 w-32 rounded-md border border-gray-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900 z-20">
166
+ {hasUnarchived && (
167
+ <button
168
+ type="button"
169
+ className="w-full text-left px-3 py-1.5 text-xs text-gray-700 hover:bg-gray-50 dark:text-gray-200 dark:hover:bg-zinc-800"
170
+ onClick={handleArchiveAll}
171
+ disabled={isActionPending}
172
+ >
173
+ Archive all
174
+ </button>
175
+ )}
176
+ <button
177
+ type="button"
178
+ className="w-full text-left px-3 py-1.5 text-xs text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
179
+ onClick={handleDeleteAll}
180
+ disabled={isActionPending}
181
+ >
182
+ Delete all
183
+ </button>
184
+ </div>
185
+ )}
186
+ </div>
187
+ );
188
+ }
189
+
190
+ // Hover-reveal action menu for each session row
191
+ function RowActionMenu({ cardId, archived, isActionPending, onActionError, onPendingActionChange }: { cardId: string; archived: boolean; isActionPending: boolean; onActionError: (message: string | null) => void; onPendingActionChange: (value: 'open' | 'archive' | 'delete' | null) => void }) {
192
+ const queryClient = useQueryClient();
193
+ const [open, setOpen] = useState(false);
194
+ const menuRef = useRef<HTMLDivElement>(null);
195
+
196
+ useEffect(() => {
197
+ if (!open) return;
198
+ const handler = (e: MouseEvent) => {
199
+ if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
200
+ setOpen(false);
201
+ }
202
+ };
203
+ document.addEventListener('mousedown', handler);
204
+ return () => document.removeEventListener('mousedown', handler);
205
+ }, [open]);
206
+
207
+ const handleArchive = async (e: React.MouseEvent) => {
208
+ e.stopPropagation();
209
+ if (isActionPending) return;
210
+ onActionError(null);
211
+ onPendingActionChange('archive');
212
+ try {
213
+ const response = await fetch(`/api/sessions/${cardId}/archive`, { method: 'POST' });
214
+ if (!response.ok) {
215
+ const errorBody = await response.json().catch(() => null);
216
+ onActionError(mapSessionActionError(errorBody, 'Failed to archive session'));
217
+ }
218
+ } catch {
219
+ onActionError('Remote node is offline or unreachable.');
220
+ } finally {
221
+ onPendingActionChange(null);
222
+ setOpen(false);
223
+ await queryClient.invalidateQueries({ queryKey: ['sessions'] });
224
+ }
225
+ };
226
+
227
+ const handleDelete = async (e: React.MouseEvent) => {
228
+ e.stopPropagation();
229
+ if (isActionPending) return;
230
+ onActionError(null);
231
+ onPendingActionChange('delete');
232
+ try {
233
+ const response = await fetch(`/api/sessions/${cardId}/delete`, { method: 'POST' });
234
+ if (!response.ok) {
235
+ const errorBody = await response.json().catch(() => null);
236
+ onActionError(mapSessionActionError(errorBody, 'Failed to delete session'));
237
+ }
238
+ } catch {
239
+ onActionError('Remote node is offline or unreachable.');
240
+ } finally {
241
+ onPendingActionChange(null);
242
+ setOpen(false);
243
+ await queryClient.invalidateQueries({ queryKey: ['sessions'] });
244
+ }
245
+ };
246
+
247
+ return (
248
+ <div className="relative flex-shrink-0" ref={menuRef}>
249
+ <button
250
+ type="button"
251
+ className="w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-gray-600 hover:bg-gray-200 dark:text-gray-500 dark:hover:text-gray-300 dark:hover:bg-zinc-600 transition-colors"
252
+ onClick={(e) => { e.stopPropagation(); if (!isActionPending) setOpen(!open); }}
253
+ title="Actions"
254
+ disabled={isActionPending}
255
+ >
256
+ <svg className="w-3.5 h-3.5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
257
+ <path d="M5 10a2 2 0 110 4 2 2 0 010-4zm7 0a2 2 0 110 4 2 2 0 010-4zm7 0a2 2 0 110 4 2 2 0 010-4z" />
258
+ </svg>
259
+ </button>
260
+ {open && (
261
+ <div className="absolute right-0 top-6 w-28 rounded-md border border-gray-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900 z-20">
262
+ {!archived ? (
263
+ <button
264
+ type="button"
265
+ className="w-full text-left px-3 py-1.5 text-xs text-gray-700 hover:bg-gray-50 dark:text-gray-200 dark:hover:bg-zinc-800"
266
+ onClick={handleArchive}
267
+ disabled={isActionPending}
268
+ >
269
+ Archive
270
+ </button>
271
+ ) : null}
272
+ <button
273
+ type="button"
274
+ className="w-full text-left px-3 py-1.5 text-xs text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
275
+ onClick={handleDelete}
276
+ disabled={isActionPending}
277
+ >
278
+ Delete
279
+ </button>
280
+ </div>
281
+ )}
282
+ </div>
283
+ );
284
+ }
285
+
286
+ // Session row with expandable subagent children
287
+ function SessionRow({ card, isLast, readOnly = false, isActionPending, onActionError, onPendingActionChange }: { card: KanbanCard; isLast: boolean; readOnly?: boolean; isActionPending: boolean; onActionError: (message: string | null) => void; onPendingActionChange: (value: 'open' | 'archive' | 'delete' | null) => void }) {
288
+ const [expanded, setExpanded] = useState(true);
289
+ const visibleChildren = (card.children || []).filter(
290
+ (child) => child.realTimeStatus !== 'idle' || child.waitingForUser
291
+ );
292
+ const hasChildren = visibleChildren.length > 0;
293
+ const rowTitle = buildTooltipTitle([
294
+ card.title || 'Untitled Session',
295
+ `Active ${formatRelativeTime(card.updatedAt)} ago`,
296
+ `Started ${formatRelativeTime(card.createdAt)} ago`,
297
+ ], card.debugReason);
298
+
299
+ return (
300
+ <div className={!isLast ? 'border-b border-gray-50 dark:border-zinc-700/30' : ''}>
301
+ <div
302
+ className="group/row flex items-center gap-2.5 px-3 py-2 hover:bg-gray-50 dark:hover:bg-zinc-700/30 transition-colors"
303
+ title={rowTitle}
304
+ >
305
+ {/* Expand toggle or spacer */}
306
+ {hasChildren && (
307
+ <button
308
+ type="button"
309
+ onClick={(e) => { e.stopPropagation(); setExpanded(!expanded); }}
310
+ className="w-3 h-3 flex items-center justify-center text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 flex-shrink-0 transition-transform"
311
+ title={expanded ? 'Collapse subagents' : 'Expand subagents'}
312
+ >
313
+ <svg
314
+ className={`w-2.5 h-2.5 transition-transform duration-150 ${expanded ? 'rotate-90' : ''}`}
315
+ viewBox="0 0 6 10" fill="currentColor"
316
+ aria-hidden="true"
317
+ >
318
+ <path d="M1 1l4 4-4 4" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" />
319
+ </svg>
320
+ </button>
321
+ )}
322
+ <StatusDot status={card.opencodeStatus} waitingForUser={card.waitingForUser} />
323
+ <span className="text-sm text-gray-700 dark:text-gray-300 truncate flex-1 min-w-0">
324
+ {card.title || 'Untitled Session'}
325
+ </span>
326
+ {/* Child count badge */}
327
+ {hasChildren && !expanded && (
328
+ <span className="text-[9px] font-medium text-gray-400 dark:text-gray-500 bg-gray-100 dark:bg-zinc-700 px-1 py-0.5 rounded flex-shrink-0">
329
+ {visibleChildren.length} sub
330
+ </span>
331
+ )}
332
+ {/* Time: visible by default, hidden on hover */}
333
+ <span className="text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0 tabular-nums group-hover/row:hidden">
334
+ {formatRelativeTime(card.updatedAt)}
335
+ </span>
336
+ {/* Action menu: hidden by default, visible on hover */}
337
+ {!readOnly ? (
338
+ <div className="hidden group-hover/row:flex flex-shrink-0">
339
+ <RowActionMenu cardId={card.id} archived={card.status === 'done'} isActionPending={isActionPending} onActionError={onActionError} onPendingActionChange={onPendingActionChange} />
340
+ </div>
341
+ ) : null}
342
+ </div>
343
+ {/* Subagent children */}
344
+ {hasChildren && expanded && (
345
+ <div className="bg-gray-50/50 dark:bg-zinc-800/30">
346
+ {visibleChildren.map((child, i) => (
347
+ <div
348
+ key={child.id}
349
+ className="flex items-center gap-2 pl-8 pr-3 py-1.5 hover:bg-gray-100/50 dark:hover:bg-zinc-700/20 transition-colors"
350
+ title={buildTooltipTitle([child.title || 'Subagent'], child.debugReason)}
351
+ >
352
+ {/* Tree connector */}
353
+ <span className="text-gray-300 dark:text-zinc-600 text-xs flex-shrink-0 font-mono leading-none">
354
+ {i === visibleChildren.length - 1 ? '└' : '├'}
355
+ </span>
356
+ <StatusDot status={child.realTimeStatus} waitingForUser={child.waitingForUser} />
357
+ <span className="text-xs text-gray-500 dark:text-gray-400 truncate flex-1 min-w-0">
358
+ {child.title || 'Subagent'}
359
+ </span>
360
+ </div>
361
+ ))}
362
+ </div>
363
+ )}
364
+ </div>
365
+ );
366
+ }
367
+
368
+ export function ProjectCard({ projectName, branch, cards, readOnly: _readOnly, hostLabel: _hostLabel, multipleHostsEnabled }: ProjectCardProps) {
369
+ const firstCard = cards[0];
370
+ const readOnly = _readOnly ?? firstCard?.readOnly ?? false;
371
+ const hostLabel = _hostLabel ?? firstCard?.hostLabel;
372
+ const hostId = firstCard?.hostId;
373
+ const showHostBadge = hostLabel && (multipleHostsEnabled || hostLabel !== 'Local');
374
+ const hostAccentClass = getHostAccentTextClass(hostId, hostLabel);
375
+ const [actionError, setActionError] = useState<string | null>(null);
376
+ const [pendingAction, setPendingAction] = useState<'open' | 'archive' | 'delete' | null>(null);
377
+ const [openTool, setOpenTool] = useState(() => {
378
+ if (typeof window === 'undefined') return 'vscode';
379
+ return window.localStorage.getItem('vibepulse:open-tool') || 'vscode';
380
+ });
381
+ const { data: config, isLoading: isConfigLoading, isError: isConfigError } = useQuery<ConfigResponse>({
382
+ queryKey: ['opencode-config'],
383
+ queryFn: async () => {
384
+ const response = await fetch('/api/opencode-config');
385
+ if (!response.ok) {
386
+ throw new Error('Failed to load config');
387
+ }
388
+
389
+ return response.json();
390
+ },
391
+ staleTime: 30_000,
392
+ });
393
+ const remoteSshHost = useMemo(() => {
394
+ if (typeof window === 'undefined') {
395
+ return '';
396
+ }
397
+
398
+ const storedHost = window.localStorage.getItem('vibepulse:ssh-host');
399
+ if (storedHost) {
400
+ return storedHost;
401
+ }
402
+
403
+ const firstRemoteBaseUrl = firstCard?.hostBaseUrl;
404
+ if (firstRemoteBaseUrl && firstCard?.hostId !== 'local') {
405
+ try {
406
+ return new URL(firstRemoteBaseUrl).hostname;
407
+ } catch {
408
+ }
409
+ }
410
+
411
+ const hostname = window.location.hostname;
412
+ if (hostname && hostname !== 'localhost' && hostname !== '127.0.0.1') {
413
+ return hostname;
414
+ }
415
+
416
+ return '';
417
+ }, [firstCard?.hostBaseUrl, firstCard?.hostId]);
418
+ const isActionPending = pendingAction !== null;
419
+ const pendingActionLabel = pendingAction === 'open'
420
+ ? 'Opening…'
421
+ : pendingAction === 'archive'
422
+ ? 'Archiving…'
423
+ : pendingAction === 'delete'
424
+ ? 'Deleting…'
425
+ : null;
426
+ const isRemoteProjectCard = !!firstCard && firstCard.hostId !== undefined && firstCard.hostId !== 'local';
427
+ const isConfigPendingForRemoteOpen = isRemoteProjectCard && isConfigLoading && !config;
428
+ const isConfigUnavailableForRemoteOpen = isRemoteProjectCard && !config && !isConfigLoading;
429
+
430
+ const handleOpenProject = () => {
431
+ if (isActionPending) {
432
+ return;
433
+ }
434
+
435
+ if (isConfigPendingForRemoteOpen) {
436
+ return;
437
+ }
438
+
439
+ if (isConfigUnavailableForRemoteOpen) {
440
+ setActionError('Failed to load open settings. Remote open is unavailable until configuration loads.');
441
+ return;
442
+ }
443
+
444
+ const directory = cards[0]?.directory;
445
+ if (!directory) return;
446
+ setActionError(null);
447
+ const firstProjectCard = cards[0];
448
+ const openEditorTargetMode = config?.vibepulse?.openEditorTargetMode === 'hub' ? 'hub' : 'remote';
449
+ const isRemoteProject = firstProjectCard?.hostId !== undefined && firstProjectCard.hostId !== 'local';
450
+
451
+ if (isRemoteProject && openEditorTargetMode === 'hub' && openTool === 'antigravity') {
452
+ setActionError('Antigravity does not support hub-mode remote opens. Use VS Code or switch target mode to Remote node.');
453
+ return;
454
+ }
455
+
456
+ const useRemoteSshTarget = isRemoteProject && openEditorTargetMode === 'hub' && openTool === 'vscode';
457
+ const target = buildEditorUri(openTool === 'antigravity' ? 'antigravity' : 'vscode', directory, {
458
+ remoteSshHost: useRemoteSshTarget ? remoteSshHost : null,
459
+ });
460
+
461
+ if (isRemoteProject && openEditorTargetMode === 'remote') {
462
+ void (async () => {
463
+ setPendingAction('open');
464
+ try {
465
+ const response = await fetch(`/api/sessions/${firstProjectCard.id}/open-editor`, {
466
+ method: 'POST',
467
+ headers: { 'Content-Type': 'application/json' },
468
+ body: JSON.stringify({ tool: openTool }),
469
+ });
470
+ if (!response.ok) {
471
+ const errorBody = await response.json().catch(() => null);
472
+ setActionError(mapSessionActionError(errorBody, 'Failed to open remote editor'));
473
+ }
474
+ } catch {
475
+ setActionError('Remote node is offline or unreachable.');
476
+ } finally {
477
+ setPendingAction(null);
478
+ }
479
+ })();
480
+ return;
481
+ }
482
+
483
+ window.location.assign(target);
484
+ };
485
+
486
+ return (
487
+ <article className="w-full bg-white dark:bg-zinc-800 rounded-xl shadow-sm border border-gray-200 dark:border-zinc-700 hover:shadow-lg hover:border-gray-300 dark:hover:border-zinc-600 transition-all duration-200 overflow-visible">
488
+ {/* Header */}
489
+ <div className="group/header flex items-center gap-2 px-3 py-2.5 hover:bg-gray-50 dark:hover:bg-zinc-700/30 transition-colors">
490
+ <div
491
+ className={`flex items-center justify-center flex-shrink-0 ${showHostBadge ? hostAccentClass : 'text-blue-500 dark:text-blue-400'}`}
492
+ title={showHostBadge ? `Source: ${hostLabel}` : undefined}
493
+ >
494
+ <svg
495
+ className="w-4 h-4"
496
+ fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"
497
+ >
498
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
499
+ </svg>
500
+ </div>
501
+ <span className="text-sm font-semibold text-gray-800 dark:text-gray-200 truncate flex-1 min-w-0">
502
+ {projectName}
503
+ </span>
504
+ {(cards.length > 1 || !readOnly) && (
505
+ <div className="flex items-center flex-shrink-0 bg-gray-100 dark:bg-zinc-700/50 rounded-full h-6 border border-gray-200/50 dark:border-zinc-700">
506
+ {cards.length > 1 && (
507
+ <span className={`text-[11px] font-medium text-gray-500 dark:text-gray-400 ${!readOnly ? 'pl-2.5 pr-1' : 'px-2.5'}`}>
508
+ {cards.length}
509
+ </span>
510
+ )}
511
+ {!readOnly && (
512
+ <div className={`${cards.length > 1 ? 'pr-0.5' : 'px-0.5'}`}>
513
+ <HeaderActionMenu cards={cards} readOnly={readOnly} isActionPending={isActionPending} onActionError={setActionError} onPendingActionChange={setPendingAction} />
514
+ </div>
515
+ )}
516
+ </div>
517
+ )}
518
+ </div>
519
+
520
+ {/* Session rows */}
521
+ <div className="border-t border-gray-100 dark:border-zinc-700/50">
522
+ {cards.map((card, index) => (
523
+ <SessionRow
524
+ key={card.id}
525
+ card={card}
526
+ isLast={index === cards.length - 1}
527
+ readOnly={readOnly}
528
+ isActionPending={isActionPending}
529
+ onActionError={setActionError}
530
+ onPendingActionChange={setPendingAction}
531
+ />
532
+ ))}
533
+ </div>
534
+
535
+ {/* Footer */}
536
+ {!readOnly && (
537
+ <div className="flex items-center justify-between gap-2 px-3 py-1.5 border-t border-gray-100 dark:border-zinc-700/50 bg-gray-50/50 dark:bg-zinc-800/50">
538
+ <div className="min-w-0 flex-1 text-[10px] text-gray-400 dark:text-gray-500 truncate">
539
+ {branch ? (
540
+ <span className="truncate" title={branch}>{branch}</span>
541
+ ) : null}
542
+ </div>
543
+ <div className="flex items-center justify-end gap-1.5 flex-shrink-0">
544
+ <select
545
+ className="text-[10px] rounded border border-gray-200 bg-white px-1 py-0.5 text-gray-500 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-gray-400 focus:outline-none"
546
+ value={openTool}
547
+ onClick={(e) => e.stopPropagation()}
548
+ onChange={(e) => {
549
+ setOpenTool(e.target.value);
550
+ window.localStorage.setItem('vibepulse:open-tool', e.target.value);
551
+ }}
552
+ title="Select open tool"
553
+ disabled={isActionPending || isConfigPendingForRemoteOpen || isConfigUnavailableForRemoteOpen}
554
+ >
555
+ <option value="vscode">VSCode</option>
556
+ <option value="antigravity">Antigravity</option>
557
+ </select>
558
+ <button
559
+ type="button"
560
+ onClick={handleOpenProject}
561
+ className="flex items-center gap-1 px-2 py-0.5 rounded-md text-[10px] font-medium text-gray-500 hover:text-blue-600 hover:bg-blue-50 disabled:cursor-not-allowed disabled:opacity-50 dark:text-gray-400 dark:hover:text-blue-400 dark:hover:bg-blue-900/20 transition-colors"
562
+ title="Open project"
563
+ disabled={isActionPending || isConfigPendingForRemoteOpen || isConfigUnavailableForRemoteOpen}
564
+ >
565
+ <svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
566
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
567
+ </svg>
568
+ Open
569
+ </button>
570
+ </div>
571
+ </div>
572
+ )}
573
+ {actionError ? (
574
+ <div className="border-t border-red-100 bg-red-50 px-3 py-2 text-xs text-red-700 dark:border-red-900/40 dark:bg-red-900/20 dark:text-red-300">
575
+ {actionError}
576
+ </div>
577
+ ) : null}
578
+ {isConfigError && isConfigUnavailableForRemoteOpen ? (
579
+ <div className="border-t border-red-100 bg-red-50 px-3 py-2 text-xs text-red-700 dark:border-red-900/40 dark:bg-red-900/20 dark:text-red-300">
580
+ Failed to load open settings. Remote open is unavailable until configuration loads.
581
+ </div>
582
+ ) : null}
583
+ {isConfigPendingForRemoteOpen ? (
584
+ <div className="border-t border-blue-100 bg-blue-50 px-3 py-2 text-xs text-blue-700 dark:border-blue-900/40 dark:bg-blue-900/20 dark:text-blue-300">
585
+ Loading open settings…
586
+ </div>
587
+ ) : null}
588
+ {pendingActionLabel ? (
589
+ <div className="border-t border-blue-100 bg-blue-50 px-3 py-2 text-xs text-blue-700 dark:border-blue-900/40 dark:bg-blue-900/20 dark:text-blue-300">
590
+ {pendingActionLabel}
591
+ </div>
592
+ ) : null}
593
+ </article>
594
+ );
595
+ }
@@ -0,0 +1,25 @@
1
+ 'use client';
2
+
3
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4
+ import { ReactNode } from 'react';
5
+
6
+ const queryClient = new QueryClient({
7
+ defaultOptions: {
8
+ queries: {
9
+ refetchOnWindowFocus: false,
10
+ staleTime: 0,
11
+ },
12
+ },
13
+ });
14
+
15
+ interface QueryProviderProps {
16
+ children: ReactNode;
17
+ }
18
+
19
+ export function QueryProvider({ children }: QueryProviderProps) {
20
+ return (
21
+ <QueryClientProvider client={queryClient}>
22
+ {children}
23
+ </QueryClientProvider>
24
+ );
25
+ }