vibepulse 0.2.2 → 0.3.1-beta

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 (424) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +1 -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 +8 -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 +2 -2
  32. package/.next/server/app/api/node/events/route.js.nft.json +1 -1
  33. package/.next/server/app/api/node/sessions/[id]/delete/route.js +2 -2
  34. package/.next/server/app/api/node/sessions/[id]/delete/route.js.nft.json +1 -1
  35. package/.next/server/app/api/node/sessions/[id]/open-editor/route.js +2 -2
  36. package/.next/server/app/api/node/sessions/[id]/open-editor/route.js.nft.json +1 -1
  37. package/.next/server/app/api/node/sessions/route.js +6 -4
  38. package/.next/server/app/api/node/sessions/route.js.nft.json +1 -1
  39. package/.next/server/app/api/nodes/route.js +2 -2
  40. package/.next/server/app/api/nodes/route.js.nft.json +1 -1
  41. package/.next/server/app/api/opencode-config/route.js +2 -2
  42. package/.next/server/app/api/opencode-config/route.js.nft.json +1 -1
  43. package/.next/server/app/api/opencode-config/status/route.js +2 -2
  44. package/.next/server/app/api/opencode-config/status/route.js.nft.json +1 -1
  45. package/.next/server/app/api/opencode-events/route.js +3 -3
  46. package/.next/server/app/api/opencode-events/route.js.nft.json +1 -1
  47. package/.next/server/app/api/profiles/[id]/apply/route.js +2 -2
  48. package/.next/server/app/api/profiles/[id]/apply/route.js.nft.json +1 -1
  49. package/.next/server/app/api/profiles/[id]/export/route.js +2 -2
  50. package/.next/server/app/api/profiles/[id]/export/route.js.nft.json +1 -1
  51. package/.next/server/app/api/profiles/[id]/route.js +2 -2
  52. package/.next/server/app/api/profiles/[id]/route.js.nft.json +1 -1
  53. package/.next/server/app/api/profiles/import/route.js +2 -2
  54. package/.next/server/app/api/profiles/import/route.js.nft.json +1 -1
  55. package/.next/server/app/api/profiles/route.js +2 -2
  56. package/.next/server/app/api/profiles/route.js.nft.json +1 -1
  57. package/.next/server/app/api/sessions/[id]/archive/route.js +3 -2
  58. package/.next/server/app/api/sessions/[id]/archive/route.js.nft.json +1 -1
  59. package/.next/server/app/api/sessions/[id]/delete/route.js +4 -3
  60. package/.next/server/app/api/sessions/[id]/delete/route.js.nft.json +1 -1
  61. package/.next/server/app/api/sessions/[id]/open-editor/route.js +2 -2
  62. package/.next/server/app/api/sessions/[id]/open-editor/route.js.nft.json +1 -1
  63. package/.next/server/app/api/sessions/[id]/restore/route/app-paths-manifest.json +3 -0
  64. package/.next/server/app/api/sessions/[id]/restore/route/build-manifest.json +11 -0
  65. package/.next/server/app/api/sessions/[id]/restore/route/server-reference-manifest.json +4 -0
  66. package/.next/server/app/api/sessions/[id]/restore/route.js +8 -0
  67. package/.next/server/app/api/sessions/[id]/restore/route.js.map +5 -0
  68. package/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -0
  69. package/.next/server/app/api/sessions/[id]/restore/route_client-reference-manifest.js +2 -0
  70. package/.next/server/app/api/sessions/[id]/route.js +2 -2
  71. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  72. package/.next/server/app/api/sessions/route.js +5 -3
  73. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  74. package/.next/server/app/index.html +1 -1
  75. package/.next/server/app/index.rsc +3 -3
  76. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  77. package/.next/server/app/index.segments/_full.segment.rsc +3 -3
  78. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  79. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  80. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  81. package/.next/server/app/page_client-reference-manifest.js +1 -1
  82. package/.next/server/app-paths-manifest.json +1 -0
  83. package/.next/server/chunks/[root-of-the-server]__005eb0c5._.js +3 -0
  84. package/.next/server/chunks/[root-of-the-server]__005eb0c5._.js.map +1 -0
  85. package/.next/server/chunks/[root-of-the-server]__09e90d57._.js +3 -0
  86. package/.next/server/chunks/[root-of-the-server]__09e90d57._.js.map +1 -0
  87. package/.next/server/chunks/[root-of-the-server]__18dd0ce9._.js +3 -0
  88. package/.next/server/chunks/[root-of-the-server]__18dd0ce9._.js.map +1 -0
  89. package/.next/server/chunks/[root-of-the-server]__19468536._.js +3 -0
  90. package/.next/server/chunks/[root-of-the-server]__19468536._.js.map +1 -0
  91. package/.next/server/chunks/[root-of-the-server]__1b87ec42._.js +1 -1
  92. package/.next/server/chunks/[root-of-the-server]__1b87ec42._.js.map +1 -1
  93. package/.next/server/chunks/[root-of-the-server]__2b912935._.js +3 -0
  94. package/.next/server/chunks/[root-of-the-server]__2b912935._.js.map +1 -0
  95. package/.next/server/chunks/[root-of-the-server]__303d3bac._.js +3 -0
  96. package/.next/server/chunks/[root-of-the-server]__303d3bac._.js.map +1 -0
  97. package/.next/server/chunks/[root-of-the-server]__3fac2b91._.js +5 -0
  98. package/.next/server/chunks/[root-of-the-server]__3fac2b91._.js.map +1 -0
  99. package/.next/server/chunks/[root-of-the-server]__43440b8d._.js +3 -0
  100. package/.next/server/chunks/[root-of-the-server]__43440b8d._.js.map +1 -0
  101. package/.next/server/chunks/[root-of-the-server]__438f8bbe._.js +3 -0
  102. package/.next/server/chunks/[root-of-the-server]__438f8bbe._.js.map +1 -0
  103. package/.next/server/chunks/[root-of-the-server]__4a0bfb55._.js +3 -0
  104. package/.next/server/chunks/[root-of-the-server]__4a0bfb55._.js.map +1 -0
  105. package/.next/server/chunks/[root-of-the-server]__534c3949._.js +3 -0
  106. package/.next/server/chunks/[root-of-the-server]__534c3949._.js.map +1 -0
  107. package/.next/server/chunks/[root-of-the-server]__59160266._.js +1 -1
  108. package/.next/server/chunks/[root-of-the-server]__59160266._.js.map +1 -1
  109. package/.next/server/chunks/[root-of-the-server]__6f812da0._.js +3 -0
  110. package/.next/server/chunks/[root-of-the-server]__6f812da0._.js.map +1 -0
  111. package/.next/server/chunks/[root-of-the-server]__71aac504._.js +3 -0
  112. package/.next/server/chunks/[root-of-the-server]__71aac504._.js.map +1 -0
  113. package/.next/server/chunks/[root-of-the-server]__907a8bf2._.js +3 -0
  114. package/.next/server/chunks/[root-of-the-server]__907a8bf2._.js.map +1 -0
  115. package/.next/server/chunks/[root-of-the-server]__92089220._.js +3 -0
  116. package/.next/server/chunks/[root-of-the-server]__92089220._.js.map +1 -0
  117. package/.next/server/chunks/[root-of-the-server]__9b7bc2d0._.js +3 -0
  118. package/.next/server/chunks/[root-of-the-server]__9b7bc2d0._.js.map +1 -0
  119. package/.next/server/chunks/[root-of-the-server]__b2640944._.js +3 -0
  120. package/.next/server/chunks/[root-of-the-server]__b2640944._.js.map +1 -0
  121. package/.next/server/chunks/[root-of-the-server]__c2267cf1._.js +3 -0
  122. package/.next/server/chunks/[root-of-the-server]__c2267cf1._.js.map +1 -0
  123. package/.next/server/chunks/[root-of-the-server]__d7f7e6dd._.js +3 -0
  124. package/.next/server/chunks/{[root-of-the-server]__6924c09d._.js.map → [root-of-the-server]__d7f7e6dd._.js.map} +1 -1
  125. package/.next/server/chunks/[root-of-the-server]__d8e61048._.js +1 -1
  126. package/.next/server/chunks/[root-of-the-server]__d8e61048._.js.map +1 -1
  127. package/.next/server/chunks/[root-of-the-server]__f6d0d488._.js +3 -0
  128. package/.next/server/chunks/{[root-of-the-server]__192ed2f4._.js.map → [root-of-the-server]__f6d0d488._.js.map} +1 -1
  129. package/.next/server/chunks/[root-of-the-server]__fa559e1e._.js +3 -0
  130. package/.next/server/chunks/[root-of-the-server]__fa559e1e._.js.map +1 -0
  131. package/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_restore_route_actions_af7d6b6c.js +3 -0
  132. package/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_restore_route_actions_af7d6b6c.js.map +1 -0
  133. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7e181e75.js +1 -1
  134. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7e181e75.js.map +1 -1
  135. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_aca45402.js +1 -1
  136. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_aca45402.js.map +1 -1
  137. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js +1 -1
  138. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js.map +1 -1
  139. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_fa835ac3.js +2 -2
  140. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_fa835ac3.js.map +1 -1
  141. package/.next/server/chunks/src_lib_opencodeConfig_ts_8e209941._.js +3 -0
  142. package/.next/server/chunks/src_lib_opencodeConfig_ts_8e209941._.js.map +1 -0
  143. package/.next/server/chunks/src_lib_session-providers_claudeCode_ts_0f9590ed._.js +3 -0
  144. package/.next/server/chunks/src_lib_session-providers_claudeCode_ts_0f9590ed._.js.map +1 -0
  145. package/.next/server/chunks/ssr/{[root-of-the-server]__631e12d0._.js → [root-of-the-server]__c91a8380._.js} +2 -2
  146. package/.next/server/chunks/ssr/{[root-of-the-server]__631e12d0._.js.map → [root-of-the-server]__c91a8380._.js.map} +1 -1
  147. package/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js +3 -3
  148. package/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js.map +1 -1
  149. package/.next/server/pages/404.html +1 -1
  150. package/.next/server/pages/500.html +2 -2
  151. package/.next/server/server-reference-manifest.js +1 -1
  152. package/.next/server/server-reference-manifest.json +1 -1
  153. package/.next/standalone/.next/BUILD_ID +1 -1
  154. package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
  155. package/.next/standalone/.next/build-manifest.json +2 -2
  156. package/.next/standalone/.next/prerender-manifest.json +3 -3
  157. package/.next/standalone/.next/routes-manifest.json +8 -0
  158. package/.next/standalone/.next/server/app/_global-error/page.js +1 -1
  159. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  161. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  162. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  163. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  164. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  165. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  166. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  167. package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
  168. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  169. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  170. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  171. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  172. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  173. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  174. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  175. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  176. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  177. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  178. package/.next/standalone/.next/server/app/api/node/events/route.js +2 -2
  179. package/.next/standalone/.next/server/app/api/node/events/route.js.nft.json +1 -1
  180. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route.js +2 -2
  181. package/.next/standalone/.next/server/app/api/node/sessions/[id]/delete/route.js.nft.json +1 -1
  182. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route.js +2 -2
  183. package/.next/standalone/.next/server/app/api/node/sessions/[id]/open-editor/route.js.nft.json +1 -1
  184. package/.next/standalone/.next/server/app/api/node/sessions/route.js +6 -4
  185. package/.next/standalone/.next/server/app/api/node/sessions/route.js.nft.json +1 -1
  186. package/.next/standalone/.next/server/app/api/nodes/route.js +2 -2
  187. package/.next/standalone/.next/server/app/api/nodes/route.js.nft.json +1 -1
  188. package/.next/standalone/.next/server/app/api/opencode-config/route.js +2 -2
  189. package/.next/standalone/.next/server/app/api/opencode-config/route.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/api/opencode-config/status/route.js +2 -2
  191. package/.next/standalone/.next/server/app/api/opencode-config/status/route.js.nft.json +1 -1
  192. package/.next/standalone/.next/server/app/api/opencode-events/route.js +3 -3
  193. package/.next/standalone/.next/server/app/api/opencode-events/route.js.nft.json +1 -1
  194. package/.next/standalone/.next/server/app/api/profiles/[id]/apply/route.js +2 -2
  195. package/.next/standalone/.next/server/app/api/profiles/[id]/apply/route.js.nft.json +1 -1
  196. package/.next/standalone/.next/server/app/api/profiles/[id]/export/route.js +2 -2
  197. package/.next/standalone/.next/server/app/api/profiles/[id]/export/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/profiles/[id]/route.js +2 -2
  199. package/.next/standalone/.next/server/app/api/profiles/[id]/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/profiles/import/route.js +2 -2
  201. package/.next/standalone/.next/server/app/api/profiles/import/route.js.nft.json +1 -1
  202. package/.next/standalone/.next/server/app/api/profiles/route.js +2 -2
  203. package/.next/standalone/.next/server/app/api/profiles/route.js.nft.json +1 -1
  204. package/.next/standalone/.next/server/app/api/sessions/[id]/archive/route.js +3 -2
  205. package/.next/standalone/.next/server/app/api/sessions/[id]/archive/route.js.nft.json +1 -1
  206. package/.next/standalone/.next/server/app/api/sessions/[id]/delete/route.js +4 -3
  207. package/.next/standalone/.next/server/app/api/sessions/[id]/delete/route.js.nft.json +1 -1
  208. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route.js +2 -2
  209. package/.next/standalone/.next/server/app/api/sessions/[id]/open-editor/route.js.nft.json +1 -1
  210. package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route/app-paths-manifest.json +3 -0
  211. package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route/build-manifest.json +11 -0
  212. package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route/server-reference-manifest.json +4 -0
  213. package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route.js +8 -0
  214. package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route.js.map +5 -0
  215. package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -0
  216. package/.next/standalone/.next/server/app/api/sessions/[id]/restore/route_client-reference-manifest.js +2 -0
  217. package/.next/standalone/.next/server/app/api/sessions/[id]/route.js +2 -2
  218. package/.next/standalone/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  219. package/.next/standalone/.next/server/app/api/sessions/route.js +5 -3
  220. package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
  221. package/.next/standalone/.next/server/app/index.html +1 -1
  222. package/.next/standalone/.next/server/app/index.rsc +3 -3
  223. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  224. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
  225. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  226. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  227. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  228. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  229. package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
  230. package/.next/standalone/.next/server/chunks/[root-of-the-server]__005eb0c5._.js +3 -0
  231. package/.next/standalone/.next/server/chunks/[root-of-the-server]__09e90d57._.js +3 -0
  232. package/.next/standalone/.next/server/chunks/[root-of-the-server]__18dd0ce9._.js +3 -0
  233. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19468536._.js +3 -0
  234. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1b87ec42._.js +1 -1
  235. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2b912935._.js +3 -0
  236. package/.next/standalone/.next/server/chunks/[root-of-the-server]__303d3bac._.js +3 -0
  237. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3fac2b91._.js +5 -0
  238. package/.next/standalone/.next/server/chunks/[root-of-the-server]__43440b8d._.js +3 -0
  239. package/.next/standalone/.next/server/chunks/[root-of-the-server]__438f8bbe._.js +3 -0
  240. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4a0bfb55._.js +3 -0
  241. package/.next/standalone/.next/server/chunks/[root-of-the-server]__534c3949._.js +3 -0
  242. package/.next/standalone/.next/server/chunks/[root-of-the-server]__59160266._.js +1 -1
  243. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6f812da0._.js +3 -0
  244. package/.next/standalone/.next/server/chunks/[root-of-the-server]__71aac504._.js +3 -0
  245. package/.next/standalone/.next/server/chunks/[root-of-the-server]__907a8bf2._.js +3 -0
  246. package/.next/standalone/.next/server/chunks/[root-of-the-server]__92089220._.js +3 -0
  247. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9b7bc2d0._.js +3 -0
  248. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b2640944._.js +3 -0
  249. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c2267cf1._.js +3 -0
  250. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d7f7e6dd._.js +3 -0
  251. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d8e61048._.js +1 -1
  252. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f6d0d488._.js +3 -0
  253. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fa559e1e._.js +3 -0
  254. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_restore_route_actions_af7d6b6c.js +3 -0
  255. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7e181e75.js +1 -1
  256. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_aca45402.js +1 -1
  257. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_b054aff3.js +1 -1
  258. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_fa835ac3.js +2 -2
  259. package/.next/standalone/.next/server/chunks/src_lib_opencodeConfig_ts_8e209941._.js +3 -0
  260. package/.next/standalone/.next/server/chunks/src_lib_session-providers_claudeCode_ts_0f9590ed._.js +3 -0
  261. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__631e12d0._.js → [root-of-the-server]__c91a8380._.js} +2 -2
  262. package/.next/standalone/.next/server/chunks/ssr/src_app_page_tsx_a7111f3e._.js +3 -3
  263. package/.next/standalone/.next/server/pages/404.html +1 -1
  264. package/.next/standalone/.next/server/pages/500.html +2 -2
  265. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  266. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  267. package/.next/standalone/.next/static/chunks/9e790b67c80f853c.js +13 -0
  268. package/.next/standalone/.next/static/chunks/c3dc8cd80979c971.css +3 -0
  269. package/.next/standalone/AGENTS.md +4 -0
  270. package/.next/standalone/README.md +54 -5
  271. package/.next/standalone/check-hsql.mjs +1 -1
  272. package/.next/standalone/docs/session-status-detection.md +36 -0
  273. package/.next/standalone/docs/superpowers/specs/2026-04-09-claude-capability-alignment-design.md +39 -0
  274. package/.next/standalone/eslint.config.mjs +1 -0
  275. package/.next/standalone/package-lock.json +74 -13
  276. package/.next/standalone/package.json +2 -2
  277. package/.next/standalone/src/app/api/node/events/route.ts +3 -3
  278. package/.next/standalone/src/app/api/node/sessions/[id]/archive/route.test.ts +60 -1
  279. package/.next/standalone/src/app/api/node/sessions/[id]/archive/route.ts +77 -22
  280. package/.next/standalone/src/app/api/node/sessions/[id]/delete/route.ts +6 -5
  281. package/.next/standalone/src/app/api/node/sessions/[id]/open-editor/route.ts +6 -5
  282. package/.next/standalone/src/app/api/node/sessions/route.test.ts +282 -0
  283. package/.next/standalone/src/app/api/node/sessions/route.ts +156 -30
  284. package/.next/standalone/src/app/api/opencode-config/route.test.ts +613 -0
  285. package/.next/standalone/src/app/api/opencode-config/route.ts +336 -185
  286. package/.next/standalone/src/app/api/opencode-events/route.test.ts +77 -1
  287. package/.next/standalone/src/app/api/opencode-events/route.ts +3 -3
  288. package/.next/standalone/src/app/api/opencode-models/route.test.ts +19 -0
  289. package/.next/standalone/src/app/api/opencode-models/route.ts +4 -1
  290. package/.next/standalone/src/app/api/profiles/[id]/apply/route.test.ts +227 -0
  291. package/.next/standalone/src/app/api/profiles/[id]/apply/route.ts +13 -9
  292. package/.next/standalone/src/app/api/sessions/[id]/archive/route.test.ts +126 -0
  293. package/.next/standalone/src/app/api/sessions/[id]/archive/route.ts +47 -12
  294. package/.next/standalone/src/app/api/sessions/[id]/delete/route.test.ts +140 -0
  295. package/.next/standalone/src/app/api/sessions/[id]/delete/route.ts +51 -16
  296. package/.next/standalone/src/app/api/sessions/[id]/open-editor/route.test.ts +74 -0
  297. package/.next/standalone/src/app/api/sessions/[id]/open-editor/route.ts +22 -2
  298. package/.next/standalone/src/app/api/sessions/[id]/restore/route.test.ts +186 -0
  299. package/.next/standalone/src/app/api/sessions/[id]/restore/route.ts +184 -0
  300. package/.next/standalone/src/app/api/sessions/[id]/route.ts +3 -3
  301. package/.next/standalone/src/app/api/sessions/route.test.ts +1955 -100
  302. package/.next/standalone/src/app/api/sessions/route.ts +361 -986
  303. package/.next/standalone/src/components/KanbanBoard.test.tsx +307 -1
  304. package/.next/standalone/src/components/KanbanBoard.tsx +106 -19
  305. package/.next/standalone/src/components/ProjectCard.test.tsx +420 -6
  306. package/.next/standalone/src/components/ProjectCard.tsx +238 -86
  307. package/.next/standalone/src/components/SessionCard.test.tsx +259 -8
  308. package/.next/standalone/src/components/SessionCard.tsx +182 -76
  309. package/.next/standalone/src/components/opencode-config/AgentConfigForm.test.tsx +141 -1
  310. package/.next/standalone/src/components/opencode-config/AgentConfigForm.tsx +99 -7
  311. package/.next/standalone/src/components/opencode-config/GeneralSettingsForm.test.tsx +11 -0
  312. package/.next/standalone/src/components/opencode-config/GeneralSettingsForm.tsx +41 -2
  313. package/.next/standalone/src/components/opencode-config/categories/CategoriesManager.tsx +3 -1
  314. package/.next/standalone/src/components/opencode-config/categories/CategoryConfigForm.test.tsx +106 -8
  315. package/.next/standalone/src/components/opencode-config/categories/CategoryConfigForm.tsx +82 -5
  316. package/.next/standalone/src/hooks/useHostSources.test.ts +0 -41
  317. package/.next/standalone/src/hooks/useOpencodeSync.test.ts +321 -1
  318. package/.next/standalone/src/hooks/useOpencodeSync.ts +16 -12
  319. package/.next/standalone/src/lib/claudeSessionOverrides.test.ts +75 -0
  320. package/.next/standalone/src/lib/claudeSessionOverrides.ts +169 -0
  321. package/.next/standalone/src/lib/fixtures/opencode-config/oh-my-openagent.v4.jsonc +70 -0
  322. package/.next/standalone/src/lib/fixtures/opencode-config/oh-my-openagent.v4.secret-like.jsonc +21 -0
  323. package/.next/standalone/src/lib/fixtures/opencode-config/oh-my-opencode.v3.jsonc +17 -0
  324. package/.next/standalone/src/lib/opencodeConfig.test.ts +430 -3
  325. package/.next/standalone/src/lib/opencodeConfig.ts +157 -4
  326. package/.next/standalone/src/lib/opencodeDiscovery.test.ts +241 -0
  327. package/.next/standalone/src/lib/opencodeDiscovery.ts +164 -9
  328. package/.next/standalone/src/lib/profiles/share.test.ts +92 -0
  329. package/.next/standalone/src/lib/profiles/share.ts +1 -0
  330. package/.next/standalone/src/lib/profiles/storage.test.ts +77 -1
  331. package/.next/standalone/src/lib/profiles/storage.ts +10 -9
  332. package/.next/standalone/src/lib/session-providers/claudeCode.test.ts +2288 -0
  333. package/.next/standalone/src/lib/session-providers/claudeCode.ts +1083 -0
  334. package/.next/standalone/src/lib/session-providers/localAggregator.test.ts +322 -0
  335. package/.next/standalone/src/lib/session-providers/localAggregator.ts +302 -0
  336. package/.next/standalone/src/lib/session-providers/opencodeProvider.test.ts +170 -0
  337. package/.next/standalone/src/lib/session-providers/opencodeProvider.ts +721 -0
  338. package/.next/standalone/src/lib/session-providers/opencodeSdkCompat.ts +92 -0
  339. package/.next/standalone/src/lib/session-providers/providerIds.test.ts +337 -0
  340. package/.next/standalone/src/lib/session-providers/providerIds.ts +176 -0
  341. package/.next/standalone/src/lib/session-providers/types.ts +131 -0
  342. package/.next/standalone/src/lib/transform.test.ts +253 -0
  343. package/.next/standalone/src/lib/transform.ts +96 -37
  344. package/.next/standalone/src/types/index.ts +23 -17
  345. package/.next/standalone/src/types/opencodeConfig.ts +55 -0
  346. package/.next/static/chunks/9e790b67c80f853c.js +13 -0
  347. package/.next/static/chunks/c3dc8cd80979c971.css +3 -0
  348. package/.next/trace +1 -1
  349. package/.next/trace-build +1 -1
  350. package/.next/types/routes.d.ts +2 -1
  351. package/.next/types/validator.ts +9 -0
  352. package/README.md +54 -5
  353. package/package.json +2 -2
  354. package/.next/server/chunks/[root-of-the-server]__1211da38._.js +0 -3
  355. package/.next/server/chunks/[root-of-the-server]__1211da38._.js.map +0 -1
  356. package/.next/server/chunks/[root-of-the-server]__192ed2f4._.js +0 -3
  357. package/.next/server/chunks/[root-of-the-server]__2b526e7a._.js +0 -3
  358. package/.next/server/chunks/[root-of-the-server]__2b526e7a._.js.map +0 -1
  359. package/.next/server/chunks/[root-of-the-server]__2f981540._.js +0 -3
  360. package/.next/server/chunks/[root-of-the-server]__2f981540._.js.map +0 -1
  361. package/.next/server/chunks/[root-of-the-server]__3745b314._.js +0 -3
  362. package/.next/server/chunks/[root-of-the-server]__3745b314._.js.map +0 -1
  363. package/.next/server/chunks/[root-of-the-server]__56690af0._.js +0 -3
  364. package/.next/server/chunks/[root-of-the-server]__56690af0._.js.map +0 -1
  365. package/.next/server/chunks/[root-of-the-server]__56f5f249._.js +0 -3
  366. package/.next/server/chunks/[root-of-the-server]__56f5f249._.js.map +0 -1
  367. package/.next/server/chunks/[root-of-the-server]__59175de4._.js +0 -3
  368. package/.next/server/chunks/[root-of-the-server]__59175de4._.js.map +0 -1
  369. package/.next/server/chunks/[root-of-the-server]__64fffc02._.js +0 -3
  370. package/.next/server/chunks/[root-of-the-server]__64fffc02._.js.map +0 -1
  371. package/.next/server/chunks/[root-of-the-server]__6924c09d._.js +0 -3
  372. package/.next/server/chunks/[root-of-the-server]__6c428a24._.js +0 -3
  373. package/.next/server/chunks/[root-of-the-server]__6c428a24._.js.map +0 -1
  374. package/.next/server/chunks/[root-of-the-server]__73a00b88._.js +0 -3
  375. package/.next/server/chunks/[root-of-the-server]__73a00b88._.js.map +0 -1
  376. package/.next/server/chunks/[root-of-the-server]__7e757f50._.js +0 -3
  377. package/.next/server/chunks/[root-of-the-server]__7e757f50._.js.map +0 -1
  378. package/.next/server/chunks/[root-of-the-server]__89c5eeab._.js +0 -3
  379. package/.next/server/chunks/[root-of-the-server]__89c5eeab._.js.map +0 -1
  380. package/.next/server/chunks/[root-of-the-server]__8da6c5a8._.js +0 -3
  381. package/.next/server/chunks/[root-of-the-server]__8da6c5a8._.js.map +0 -1
  382. package/.next/server/chunks/[root-of-the-server]__b796d06c._.js +0 -3
  383. package/.next/server/chunks/[root-of-the-server]__b796d06c._.js.map +0 -1
  384. package/.next/server/chunks/[root-of-the-server]__c2ce5c0f._.js +0 -3
  385. package/.next/server/chunks/[root-of-the-server]__c2ce5c0f._.js.map +0 -1
  386. package/.next/server/chunks/[root-of-the-server]__db285678._.js +0 -3
  387. package/.next/server/chunks/[root-of-the-server]__db285678._.js.map +0 -1
  388. package/.next/server/chunks/[root-of-the-server]__e00a9200._.js +0 -5
  389. package/.next/server/chunks/[root-of-the-server]__e00a9200._.js.map +0 -1
  390. package/.next/server/chunks/[root-of-the-server]__e5df5e5f._.js +0 -3
  391. package/.next/server/chunks/[root-of-the-server]__e5df5e5f._.js.map +0 -1
  392. package/.next/server/chunks/[root-of-the-server]__edbc8d9e._.js +0 -3
  393. package/.next/server/chunks/[root-of-the-server]__edbc8d9e._.js.map +0 -1
  394. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1211da38._.js +0 -3
  395. package/.next/standalone/.next/server/chunks/[root-of-the-server]__192ed2f4._.js +0 -3
  396. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2b526e7a._.js +0 -3
  397. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2f981540._.js +0 -3
  398. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3745b314._.js +0 -3
  399. package/.next/standalone/.next/server/chunks/[root-of-the-server]__56690af0._.js +0 -3
  400. package/.next/standalone/.next/server/chunks/[root-of-the-server]__56f5f249._.js +0 -3
  401. package/.next/standalone/.next/server/chunks/[root-of-the-server]__59175de4._.js +0 -3
  402. package/.next/standalone/.next/server/chunks/[root-of-the-server]__64fffc02._.js +0 -3
  403. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6924c09d._.js +0 -3
  404. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c428a24._.js +0 -3
  405. package/.next/standalone/.next/server/chunks/[root-of-the-server]__73a00b88._.js +0 -3
  406. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7e757f50._.js +0 -3
  407. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89c5eeab._.js +0 -3
  408. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8da6c5a8._.js +0 -3
  409. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b796d06c._.js +0 -3
  410. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c2ce5c0f._.js +0 -3
  411. package/.next/standalone/.next/server/chunks/[root-of-the-server]__db285678._.js +0 -3
  412. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e00a9200._.js +0 -5
  413. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e5df5e5f._.js +0 -3
  414. package/.next/standalone/.next/server/chunks/[root-of-the-server]__edbc8d9e._.js +0 -3
  415. package/.next/standalone/.next/static/chunks/65d5354ba0add961.js +0 -13
  416. package/.next/standalone/.next/static/chunks/f42202943f6742e5.css +0 -3
  417. package/.next/static/chunks/65d5354ba0add961.js +0 -13
  418. package/.next/static/chunks/f42202943f6742e5.css +0 -3
  419. /package/.next/standalone/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → 0WaQ6UjiNBgvh531pJVh0}/_buildManifest.js +0 -0
  420. /package/.next/standalone/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → 0WaQ6UjiNBgvh531pJVh0}/_clientMiddlewareManifest.json +0 -0
  421. /package/.next/standalone/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → 0WaQ6UjiNBgvh531pJVh0}/_ssgManifest.js +0 -0
  422. /package/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → 0WaQ6UjiNBgvh531pJVh0}/_buildManifest.js +0 -0
  423. /package/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → 0WaQ6UjiNBgvh531pJVh0}/_clientMiddlewareManifest.json +0 -0
  424. /package/.next/static/{5kq9DtuBFVxu4jsgmL5Q- → 0WaQ6UjiNBgvh531pJVh0}/_ssgManifest.js +0 -0
@@ -251,6 +251,59 @@ describe('/api/opencode-events', () => {
251
251
  await reader!.cancel();
252
252
  });
253
253
 
254
+ it('streams from the next discovered OpenCode port when the first local port preflight fails', async () => {
255
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
256
+ mockDiscoverPortsWithMeta.mockReturnValue({ ports: [7777, 7778], timedOut: false });
257
+
258
+ mockCreateOpencodeClient.mockImplementation(({ baseUrl }: { baseUrl: string }) => ({
259
+ global: {
260
+ event: vi.fn(async () => {
261
+ if (baseUrl === 'http://localhost:7777') {
262
+ throw new Error('port 7777 offline');
263
+ }
264
+
265
+ return {
266
+ stream: createAsyncIterable([
267
+ {
268
+ type: 'session.status',
269
+ properties: {
270
+ sessionID: 'surviving-port-session',
271
+ status: { type: 'busy' },
272
+ },
273
+ timestamp: 400,
274
+ },
275
+ ]),
276
+ };
277
+ }),
278
+ },
279
+ }) as never);
280
+
281
+ const response = await GET(new Request('http://localhost/api/opencode-events'));
282
+
283
+ expect(response.status).toBe(200);
284
+ expect(mockCreateOpencodeClient.mock.calls).toEqual(expect.arrayContaining([
285
+ [{ baseUrl: 'http://localhost:7777' }],
286
+ [{ baseUrl: 'http://localhost:7778' }],
287
+ ]));
288
+ expect(mockCreateOpencodeClient.mock.calls.length).toBeGreaterThanOrEqual(2);
289
+
290
+ const reader = response.body?.getReader();
291
+ expect(reader).toBeTruthy();
292
+
293
+ const first = await readPayload(reader!);
294
+ expect(first).toEqual({
295
+ type: 'session.status',
296
+ properties: {
297
+ sessionID: 'surviving-port-session',
298
+ status: { type: 'busy' },
299
+ },
300
+ timestamp: 400,
301
+ });
302
+
303
+ await reader!.cancel();
304
+ warnSpy.mockRestore();
305
+ });
306
+
254
307
  it('keeps the shared stream alive when one remote node stream fails', async () => {
255
308
  mockGlobalEvent.mockResolvedValue({
256
309
  stream: createAsyncIterable([
@@ -493,7 +546,7 @@ describe('/api/opencode-events', () => {
493
546
  const reader = response.body?.getReader();
494
547
  expect(reader).toBeTruthy();
495
548
 
496
- const first = await readPayload(reader!);
549
+ const first = (await readPayload(reader!)) as any;
497
550
  expect(first).toEqual({
498
551
  type: 'session.status',
499
552
  properties: {
@@ -502,6 +555,8 @@ describe('/api/opencode-events', () => {
502
555
  },
503
556
  timestamp: 100,
504
557
  });
558
+ expect(first.source).toBeUndefined();
559
+ expect(first.event).toBeUndefined();
505
560
 
506
561
  await reader!.cancel();
507
562
  });
@@ -621,4 +676,25 @@ describe('/api/opencode-events', () => {
621
676
 
622
677
  warnSpy.mockRestore();
623
678
  });
679
+
680
+ it('returns a graceful unavailable response when latest root SDK event preflight rejects with BadRequest shape', async () => {
681
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
682
+ mockGlobalEvent.mockRejectedValue({
683
+ name: 'BadRequestError',
684
+ status: 400,
685
+ body: { message: 'event stream unavailable' },
686
+ });
687
+
688
+ const response = await GET(new Request('http://localhost/api/opencode-events'));
689
+ const data = await response.json();
690
+
691
+ expect(response.status).toBe(503);
692
+ expect(data).toEqual({
693
+ error: 'Failed to connect to OpenCode event streams',
694
+ hint: 'Detected local and/or remote node event sources, but every streaming handshake failed. Ensure the hub can reach each source and retry.',
695
+ });
696
+ expect(mockGlobalEvent).toHaveBeenCalledWith({ signal: expect.any(AbortSignal) });
697
+
698
+ warnSpy.mockRestore();
699
+ });
624
700
  });
@@ -1,8 +1,8 @@
1
- import { createOpencodeClient } from '@opencode-ai/sdk';
2
1
  import { discoverOpencodePortsWithMeta } from '@/lib/opencodeDiscovery';
3
2
  import { NODE_PROTOCOL_VERSION, createNodeRequestHeaders } from '@/lib/nodeProtocol';
4
3
  import { listNodeRecords, type StoredNodeRecord } from '@/lib/nodeRegistry';
5
4
  import { RUNTIME_ROLE_ENV_VAR } from '@/lib/runtimeMode';
5
+ import { createVibePulseOpencodeClient, streamOpencodeGlobalEvents } from '@/lib/session-providers/opencodeSdkCompat';
6
6
 
7
7
  const DEFAULT_EVENTS_PREFLIGHT_TIMEOUT_MS = 2500;
8
8
 
@@ -106,7 +106,7 @@ async function connectLocalEventStreamWithTimeout(
106
106
  controller?: AbortController
107
107
  ): Promise<ConnectedStream> {
108
108
  const connectionController = controller ?? new AbortController();
109
- const client = createOpencodeClient({ baseUrl: `http://localhost:${port}` });
109
+ const client = createVibePulseOpencodeClient(`http://localhost:${port}`);
110
110
 
111
111
  let timerId: ReturnType<typeof setTimeout> | null = null;
112
112
  const timeoutPromise = new Promise<never>((_, reject) => {
@@ -118,7 +118,7 @@ async function connectLocalEventStreamWithTimeout(
118
118
 
119
119
  try {
120
120
  const connection = await Promise.race([
121
- client.global.event({ signal: connectionController.signal }),
121
+ streamOpencodeGlobalEvents(client, connectionController.signal),
122
122
  timeoutPromise,
123
123
  ]);
124
124
 
@@ -53,6 +53,25 @@ describe('/api/opencode-models', () => {
53
53
  expect(result.source).toBe('opencode');
54
54
  expect(result.models).toContain('anthropic/claude');
55
55
  });
56
+
57
+ it('should trim models and ignore provider headers, whitespace, and stderr noise', () => {
58
+ const result = handleExecResult(
59
+ null,
60
+ '\nAnthropic\n anthropic/claude-3.5-sonnet \n\nOpenAI\n\topenai/gpt-4o\t\nLoaded 2 providers\n',
61
+ 'debug: provider cache refreshed\nwarning: extra stderr noise'
62
+ );
63
+
64
+ expect(result.source).toBe('opencode');
65
+ expect(result.models).toEqual(['anthropic/claude-3.5-sonnet', 'openai/gpt-4o']);
66
+ });
67
+
68
+ it('should reject non-slash CLI output as an error', () => {
69
+ const result = handleExecResult(null, 'Anthropic\nOpenAI\nNo models configured\n', '');
70
+
71
+ expect(result.source).toBe('error');
72
+ expect(result.models).toEqual([]);
73
+ expect(result.error).toContain('No models found');
74
+ });
56
75
  });
57
76
 
58
77
  describe('GET API Integration Tests', () => {
@@ -41,7 +41,10 @@ export function handleExecResult(
41
41
  }
42
42
 
43
43
  try {
44
- const models = stdout.trim().split('\n').filter(line => line.includes('/'));
44
+ const models = stdout
45
+ .split('\n')
46
+ .map((line) => line.trim())
47
+ .filter((line) => line.includes('/'));
45
48
  if (models.length === 0) {
46
49
  return { models: [], source: 'error', error: 'No models found. Please check your OpenCode installation.' };
47
50
  }
@@ -0,0 +1,227 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ vi.mock('@/lib/profiles/storage', () => ({
4
+ readProfileConfig: vi.fn(),
5
+ getProfileById: vi.fn(),
6
+ setActiveProfileId: vi.fn(),
7
+ }));
8
+
9
+ vi.mock('@/lib/opencodeConfig', async () => {
10
+ const actual = await vi.importActual<typeof import('@/lib/opencodeConfig')>('@/lib/opencodeConfig');
11
+ return {
12
+ ...actual,
13
+ readConfig: vi.fn(),
14
+ writeConfig: vi.fn(),
15
+ };
16
+ });
17
+
18
+ import {
19
+ getProfileById,
20
+ readProfileConfig,
21
+ setActiveProfileId,
22
+ } from '@/lib/profiles/storage';
23
+ import { readConfig, writeConfig } from '@/lib/opencodeConfig';
24
+ import { createExportedProfileFile, parseImportedProfileFile } from '@/lib/profiles/share';
25
+ import { POST } from './route';
26
+
27
+ const mockReadProfileConfig = vi.mocked(readProfileConfig);
28
+ const mockGetProfileById = vi.mocked(getProfileById);
29
+ const mockSetActiveProfileId = vi.mocked(setActiveProfileId);
30
+ const mockReadConfig = vi.mocked(readConfig);
31
+ const mockWriteConfig = vi.mocked(writeConfig);
32
+ let consoleErrorSpy: ReturnType<typeof vi.spyOn>;
33
+
34
+ describe('/api/profiles/[id]/apply', () => {
35
+ beforeEach(() => {
36
+ vi.clearAllMocks();
37
+ consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
38
+ });
39
+
40
+ afterEach(() => {
41
+ consoleErrorSpy.mockRestore();
42
+ });
43
+
44
+ it('applies a profile as a v4 overlay without deleting absent config keys', async () => {
45
+ const exportedProfile = createExportedProfileFile(
46
+ {
47
+ id: 'v4-overlay',
48
+ name: 'V4 Overlay',
49
+ emoji: '🧩',
50
+ createdAt: '2026-05-11T00:00:00.000Z',
51
+ updatedAt: '2026-05-11T00:00:00.000Z',
52
+ },
53
+ {
54
+ agents: {
55
+ sisyphus: {
56
+ fallback_models: [
57
+ 'anthropic/claude-opus-4-6',
58
+ {
59
+ model: 'google/gemini-3.1-pro',
60
+ variant: 'high',
61
+ reasoningEffort: 'max',
62
+ maxTokens: 32000,
63
+ thinking: { enabled: true },
64
+ futureFallbackField: 'preserve-me',
65
+ },
66
+ ],
67
+ reasoningEffort: 'max',
68
+ maxTokens: 64000,
69
+ thinking: { type: 'enabled', budget_tokens: 12000 },
70
+ future_agent_knob: { mode: 'experimental' },
71
+ },
72
+ },
73
+ categories: {
74
+ ultrabrain: {
75
+ reasoningEffort: 'max',
76
+ fallback_models: [
77
+ 'openai/gpt-5.4',
78
+ { model: 'anthropic/claude-opus-4-6', reasoningEffort: 'max' },
79
+ ],
80
+ future_category_knob: 'keep-me',
81
+ },
82
+ },
83
+ team_mode: {
84
+ enabled: true,
85
+ strategy: 'pairing',
86
+ },
87
+ metadata: {
88
+ owner: 'platform',
89
+ },
90
+ }
91
+ );
92
+ const importedProfile = parseImportedProfileFile(exportedProfile);
93
+
94
+ mockGetProfileById.mockResolvedValue({
95
+ ...importedProfile.profile,
96
+ createdAt: '2026-05-11T00:00:00.000Z',
97
+ updatedAt: '2026-05-11T00:00:00.000Z',
98
+ });
99
+ mockReadProfileConfig.mockResolvedValue(importedProfile.config);
100
+ mockReadConfig.mockResolvedValue({
101
+ agents: {
102
+ sisyphus: {
103
+ model: 'openai/gpt-5.4',
104
+ fallback_models: ['anthropic/claude-opus-4-6'],
105
+ system: 'Keep this system prompt',
106
+ },
107
+ oracle: {
108
+ model: 'openai/gpt-5.4',
109
+ },
110
+ },
111
+ categories: {
112
+ deep: {
113
+ model: 'openai/gpt-5.4',
114
+ variant: 'medium',
115
+ },
116
+ },
117
+ tools: {
118
+ shell: { enabled: true },
119
+ },
120
+ });
121
+ mockWriteConfig.mockResolvedValue();
122
+ mockSetActiveProfileId.mockResolvedValue();
123
+
124
+ const response = await POST(new Request('http://localhost/api/profiles/v4-overlay/apply') as never, {
125
+ params: Promise.resolve({ id: 'v4-overlay' }),
126
+ });
127
+
128
+ expect(response.status).toBe(200);
129
+ expect(mockWriteConfig).toHaveBeenCalledWith({
130
+ agents: {
131
+ sisyphus: {
132
+ model: 'openai/gpt-5.4',
133
+ fallback_models: [
134
+ 'anthropic/claude-opus-4-6',
135
+ {
136
+ model: 'google/gemini-3.1-pro',
137
+ variant: 'high',
138
+ reasoningEffort: 'max',
139
+ maxTokens: 32000,
140
+ thinking: { enabled: true },
141
+ futureFallbackField: 'preserve-me',
142
+ },
143
+ ],
144
+ reasoningEffort: 'max',
145
+ maxTokens: 64000,
146
+ thinking: { type: 'enabled', budget_tokens: 12000 },
147
+ future_agent_knob: { mode: 'experimental' },
148
+ system: 'Keep this system prompt',
149
+ },
150
+ oracle: {
151
+ model: 'openai/gpt-5.4',
152
+ },
153
+ },
154
+ categories: {
155
+ deep: {
156
+ model: 'openai/gpt-5.4',
157
+ variant: 'medium',
158
+ },
159
+ ultrabrain: {
160
+ reasoningEffort: 'max',
161
+ fallback_models: [
162
+ 'openai/gpt-5.4',
163
+ { model: 'anthropic/claude-opus-4-6', reasoningEffort: 'max' },
164
+ ],
165
+ future_category_knob: 'keep-me',
166
+ },
167
+ },
168
+ team_mode: {
169
+ enabled: true,
170
+ strategy: 'pairing',
171
+ },
172
+ metadata: {
173
+ owner: 'platform',
174
+ },
175
+ tools: {
176
+ shell: { enabled: true },
177
+ },
178
+ });
179
+ expect(mockSetActiveProfileId).toHaveBeenCalledWith('v4-overlay');
180
+ });
181
+
182
+ it('rolls config back when setting the active profile fails', async () => {
183
+ const currentConfig = {
184
+ agents: {
185
+ oracle: { model: 'openai/gpt-5.4' },
186
+ },
187
+ team_mode: {
188
+ enabled: false,
189
+ },
190
+ };
191
+
192
+ mockGetProfileById.mockResolvedValue({
193
+ id: 'v4-overlay',
194
+ name: 'V4 Overlay',
195
+ emoji: '🧩',
196
+ createdAt: '2026-05-11T00:00:00.000Z',
197
+ updatedAt: '2026-05-11T00:00:00.000Z',
198
+ });
199
+ mockReadProfileConfig.mockResolvedValue({
200
+ agents: {
201
+ oracle: { model: 'anthropic/claude-opus-4-6' },
202
+ },
203
+ team_mode: {
204
+ enabled: true,
205
+ },
206
+ });
207
+ mockReadConfig.mockResolvedValue(currentConfig);
208
+ mockWriteConfig.mockResolvedValue();
209
+ mockSetActiveProfileId.mockRejectedValue(new Error('index write failed'));
210
+
211
+ const response = await POST(new Request('http://localhost/api/profiles/v4-overlay/apply') as never, {
212
+ params: Promise.resolve({ id: 'v4-overlay' }),
213
+ });
214
+
215
+ expect(response.status).toBe(500);
216
+ expect(mockWriteConfig).toHaveBeenNthCalledWith(1, {
217
+ agents: {
218
+ oracle: { model: 'anthropic/claude-opus-4-6' },
219
+ },
220
+ team_mode: {
221
+ enabled: true,
222
+ },
223
+ });
224
+ expect(mockWriteConfig).toHaveBeenNthCalledWith(2, currentConfig);
225
+ expect(mockSetActiveProfileId).toHaveBeenCalledTimes(1);
226
+ });
227
+ });
@@ -4,7 +4,7 @@ import {
4
4
  getProfileById,
5
5
  setActiveProfileId,
6
6
  } from '@/lib/profiles/storage';
7
- import { readConfig, writeConfig } from '@/lib/opencodeConfig';
7
+ import { mergeConfig, readConfig, writeConfig } from '@/lib/opencodeConfig';
8
8
 
9
9
  interface RouteParams {
10
10
  params: Promise<{ id: string }>;
@@ -24,15 +24,19 @@ export async function POST(_request: NextRequest, { params }: RouteParams) {
24
24
 
25
25
  const profileConfig = await readProfileConfig(id);
26
26
  const currentConfig = await readConfig();
27
+ const mergedConfig = mergeConfig(currentConfig, profileConfig);
28
+ let configWasWritten = false;
27
29
 
28
- const mergedConfig = {
29
- ...currentConfig,
30
- agents: profileConfig.agents,
31
- categories: profileConfig.categories,
32
- };
33
-
34
- await writeConfig(mergedConfig);
35
- await setActiveProfileId(id);
30
+ try {
31
+ await writeConfig(mergedConfig);
32
+ configWasWritten = true;
33
+ await setActiveProfileId(id);
34
+ } catch (error) {
35
+ if (configWasWritten) {
36
+ await writeConfig(currentConfig);
37
+ }
38
+ throw error;
39
+ }
36
40
 
37
41
  return NextResponse.json({
38
42
  message: 'Profile applied successfully',
@@ -13,13 +13,19 @@ vi.mock('@/lib/sessionArchiveOverrides', () => ({
13
13
  markSessionStickyStatusBlocked: vi.fn(),
14
14
  }));
15
15
 
16
+ vi.mock('@/lib/claudeSessionOverrides', () => ({
17
+ markClaudeSessionArchived: vi.fn(),
18
+ }));
19
+
16
20
  import { discoverOpencodePortsWithMeta } from '@/lib/opencodeDiscovery';
17
21
  import { listNodeRecords } from '@/lib/nodeRegistry';
22
+ import { markClaudeSessionArchived } from '@/lib/claudeSessionOverrides';
18
23
 
19
24
  import { POST } from './route';
20
25
 
21
26
  const mockDiscoverPortsWithMeta: any = discoverOpencodePortsWithMeta;
22
27
  const mockListNodeRecords: any = listNodeRecords;
28
+ const mockMarkClaudeSessionArchived: any = markClaudeSessionArchived;
23
29
 
24
30
  describe('/api/sessions/[id]/archive', () => {
25
31
  beforeEach(() => {
@@ -40,6 +46,48 @@ describe('/api/sessions/[id]/archive', () => {
40
46
  expect(mockFetch).toHaveBeenCalledWith('http://localhost:7777/session/abc', expect.objectContaining({ method: 'PATCH' }));
41
47
  });
42
48
 
49
+ it('archives on the next discovered OpenCode port when the first port fails', async () => {
50
+ mockDiscoverPortsWithMeta.mockReturnValue({ ports: [7777, 7778], timedOut: false });
51
+ const mockFetch = vi.fn(async (input: RequestInfo | URL) => {
52
+ const url = typeof input === 'string' ? input : input.toString();
53
+ if (url === 'http://localhost:7777/session/abc') {
54
+ throw new Error('port 7777 offline');
55
+ }
56
+
57
+ if (url === 'http://localhost:7778/session/abc') {
58
+ return new Response('', { status: 200 });
59
+ }
60
+
61
+ throw new Error(`Unexpected archive URL: ${url}`);
62
+ });
63
+ vi.stubGlobal('fetch', mockFetch);
64
+
65
+ const response = await POST(new Request('http://localhost/api/sessions/local:abc/archive', { method: 'POST' }), {
66
+ params: Promise.resolve({ id: 'local:abc' }),
67
+ });
68
+
69
+ expect(response.status).toBe(200);
70
+ expect(mockFetch).toHaveBeenCalledWith('http://localhost:7777/session/abc', expect.objectContaining({ method: 'PATCH' }));
71
+ expect(mockFetch).toHaveBeenCalledWith('http://localhost:7778/session/abc', expect.objectContaining({ method: 'PATCH' }));
72
+ });
73
+
74
+ it('treats UUID-like local ids without claude namespace as opencode sessions', async () => {
75
+ const opencodeUuid = '550e8400-e29b-41d4-a716-446655440000';
76
+ const mockFetch = vi.fn(async () => new Response(JSON.stringify({ error: 'missing' }), { status: 404 }));
77
+ vi.stubGlobal('fetch', mockFetch);
78
+
79
+ const response = await POST(new Request(`http://localhost/api/sessions/local:${opencodeUuid}/archive`, { method: 'POST' }), {
80
+ params: Promise.resolve({ id: `local:${opencodeUuid}` }),
81
+ });
82
+ const data = await response.json();
83
+
84
+ expect(response.status).toBe(404);
85
+ expect(data).toEqual({ error: 'Session not found', reason: 'session_not_found' });
86
+ expect(mockMarkClaudeSessionArchived).not.toHaveBeenCalled();
87
+ expect(mockDiscoverPortsWithMeta).toHaveBeenCalled();
88
+ expect(mockFetch).toHaveBeenCalledWith(`http://localhost:7777/session/${opencodeUuid}`, expect.objectContaining({ method: 'PATCH' }));
89
+ });
90
+
43
91
  it('forwards remote archive ids to the matching node endpoint', async () => {
44
92
  mockListNodeRecords.mockResolvedValue([
45
93
  {
@@ -98,6 +146,84 @@ describe('/api/sessions/[id]/archive', () => {
98
146
  expect(data).toEqual({ error: 'Session not found', reason: 'session_not_found' });
99
147
  });
100
148
 
149
+ it('archives Claude sessions through local override storage before any OpenCode execution', async () => {
150
+ const mockFetch = vi.fn();
151
+ vi.stubGlobal('fetch', mockFetch);
152
+
153
+ const response = await POST(new Request('http://localhost/api/sessions/local:claude~550e8400-e29b-41d4-a716-446655440000/archive', { method: 'POST' }), {
154
+ params: Promise.resolve({ id: 'local:claude~550e8400-e29b-41d4-a716-446655440000' }),
155
+ });
156
+ const data = await response.json();
157
+
158
+ expect(response.status).toBe(200);
159
+ expect(data).toEqual({ success: true });
160
+ expect(mockMarkClaudeSessionArchived).toHaveBeenCalledWith('550e8400-e29b-41d4-a716-446655440000');
161
+ expect(mockDiscoverPortsWithMeta).not.toHaveBeenCalled();
162
+ expect(mockFetch).not.toHaveBeenCalled();
163
+ });
164
+
165
+ it('archives scoped Claude sidechain sessions through local override storage', async () => {
166
+ const scopedSessionId = '550e8400-e29b-41d4-a716-446655440000__agent-a123';
167
+ const mockFetch = vi.fn();
168
+ vi.stubGlobal('fetch', mockFetch);
169
+
170
+ const response = await POST(new Request(`http://localhost/api/sessions/local:${scopedSessionId}/archive`, { method: 'POST' }), {
171
+ params: Promise.resolve({ id: `local:${scopedSessionId}` }),
172
+ });
173
+ const data = await response.json();
174
+
175
+ expect(response.status).toBe(200);
176
+ expect(data).toEqual({ success: true });
177
+ expect(mockMarkClaudeSessionArchived).toHaveBeenCalledWith(scopedSessionId);
178
+ expect(mockDiscoverPortsWithMeta).not.toHaveBeenCalled();
179
+ expect(mockFetch).not.toHaveBeenCalled();
180
+ });
181
+
182
+ it('rejects remote Claude archive requests before local override or node execution', async () => {
183
+ const mockFetch = vi.fn();
184
+ vi.stubGlobal('fetch', mockFetch);
185
+
186
+ const response = await POST(new Request('http://localhost/api/sessions/node-1:claude~550e8400-e29b-41d4-a716-446655440000/archive', { method: 'POST' }), {
187
+ params: Promise.resolve({ id: 'node-1:claude~550e8400-e29b-41d4-a716-446655440000' }),
188
+ });
189
+ const data = await response.json();
190
+
191
+ expect(response.status).toBe(403);
192
+ expect(data).toEqual({
193
+ error: 'Session action not supported by provider',
194
+ reason: 'provider_capability_unsupported',
195
+ provider: 'claude-code',
196
+ capability: 'archive',
197
+ });
198
+ expect(mockMarkClaudeSessionArchived).not.toHaveBeenCalled();
199
+ expect(mockListNodeRecords).not.toHaveBeenCalled();
200
+ expect(mockDiscoverPortsWithMeta).not.toHaveBeenCalled();
201
+ expect(mockFetch).not.toHaveBeenCalled();
202
+ });
203
+
204
+ it('rejects remote scoped Claude sidechain archive requests before node execution', async () => {
205
+ const scopedSessionId = '550e8400-e29b-41d4-a716-446655440000__agent-a123';
206
+ const mockFetch = vi.fn();
207
+ vi.stubGlobal('fetch', mockFetch);
208
+
209
+ const response = await POST(new Request(`http://localhost/api/sessions/node-1:${scopedSessionId}/archive`, { method: 'POST' }), {
210
+ params: Promise.resolve({ id: `node-1:${scopedSessionId}` }),
211
+ });
212
+ const data = await response.json();
213
+
214
+ expect(response.status).toBe(403);
215
+ expect(data).toEqual({
216
+ error: 'Session action not supported by provider',
217
+ reason: 'provider_capability_unsupported',
218
+ provider: 'claude-code',
219
+ capability: 'archive',
220
+ });
221
+ expect(mockMarkClaudeSessionArchived).not.toHaveBeenCalled();
222
+ expect(mockListNodeRecords).not.toHaveBeenCalled();
223
+ expect(mockDiscoverPortsWithMeta).not.toHaveBeenCalled();
224
+ expect(mockFetch).not.toHaveBeenCalled();
225
+ });
226
+
101
227
  it('does not misclassify non-404 local archive failures as session_not_found', async () => {
102
228
  const mockFetch = vi.fn(async () => new Response(JSON.stringify({ error: 'boom' }), { status: 500 }));
103
229
  vi.stubGlobal('fetch', mockFetch);
@@ -1,11 +1,13 @@
1
1
  import { discoverOpencodePortsWithMeta } from '@/lib/opencodeDiscovery';
2
- import { parseActionSessionReference, resolveLocalActionSessionId } from '@/lib/hostIdentity';
2
+ import { ActionSessionReference, parseActionSessionReference, resolveLocalActionSessionId } from '@/lib/hostIdentity';
3
3
  import { listNodeRecords } from '@/lib/nodeRegistry';
4
4
  import { createNodeRequestHeaders } from '@/lib/nodeProtocol';
5
+ import { detectProviderFromRawId, extractProviderRawId, getDefaultProviderContext } from '@/lib/session-providers/providerIds';
5
6
  import {
6
- clearSessionForceUnarchived,
7
- markSessionStickyStatusBlocked,
7
+ clearSessionForceUnarchived,
8
+ markSessionStickyStatusBlocked,
8
9
  } from '@/lib/sessionArchiveOverrides';
10
+ import { markClaudeSessionArchived } from '@/lib/claudeSessionOverrides';
9
11
 
10
12
  const REMOTE_NODE_ACTION_TIMEOUT_MS = 5_000;
11
13
 
@@ -23,6 +25,20 @@ function createSessionNotFoundResponse() {
23
25
  );
24
26
  }
25
27
 
28
+ function createUnsupportedCapabilityResponse(capability: 'archive', sessionId: string) {
29
+ const provider = detectProviderFromRawId(sessionId);
30
+
31
+ return Response.json(
32
+ {
33
+ error: 'Session action not supported by provider',
34
+ reason: 'provider_capability_unsupported',
35
+ provider,
36
+ capability,
37
+ },
38
+ { status: 403 }
39
+ );
40
+ }
41
+
26
42
  function createArchiveFailureResponse(
27
43
  status: number,
28
44
  message?: string,
@@ -87,17 +103,36 @@ async function forwardRemoteArchive(hostId: string, sessionId: string): Promise<
87
103
 
88
104
  export async function POST(_: Request, { params }: { params: Promise<{ id: string }> }) {
89
105
  const { id } = await params;
90
- const sessionId = resolveLocalActionSessionId(id);
106
+ let actionTarget: ActionSessionReference;
91
107
 
92
- if (!sessionId) {
93
- try {
94
- const actionTarget = parseActionSessionReference(id);
95
- if (actionTarget.isRemote) {
96
- return forwardRemoteArchive(actionTarget.hostId, actionTarget.sessionId);
97
- }
98
- } catch {
99
- return createInvalidActionSessionIdResponse();
108
+ try {
109
+ actionTarget = parseActionSessionReference(id);
110
+ } catch {
111
+ return createInvalidActionSessionIdResponse();
112
+ }
113
+
114
+ const provider = detectProviderFromRawId(actionTarget.sessionId);
115
+ if (!getDefaultProviderContext(provider).capabilities.archive) {
116
+ return createUnsupportedCapabilityResponse('archive', actionTarget.sessionId);
117
+ }
118
+
119
+ if (provider === 'claude-code' && actionTarget.isRemote) {
120
+ return createUnsupportedCapabilityResponse('archive', actionTarget.sessionId);
121
+ }
122
+
123
+ if (provider === 'claude-code') {
124
+ await markClaudeSessionArchived(extractProviderRawId(actionTarget.sessionId));
125
+ const localSessionId = resolveLocalActionSessionId(id);
126
+ if (localSessionId) {
127
+ clearSessionForceUnarchived(localSessionId);
128
+ markSessionStickyStatusBlocked(localSessionId);
100
129
  }
130
+ return Response.json({ success: true });
131
+ }
132
+
133
+ const sessionId = resolveLocalActionSessionId(id);
134
+ if (!sessionId && actionTarget.isRemote) {
135
+ return forwardRemoteArchive(actionTarget.hostId, actionTarget.sessionId);
101
136
  }
102
137
 
103
138
  if (!sessionId) {