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
@@ -1,39 +1,266 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
2
  import { normalizeVibePulseConfig, readConfig, writeConfig } from '@/lib/opencodeConfig';
3
3
 
4
- // Allowed fields to expose in the API
5
- const ALLOWED_AGENT_FIELDS = ['model', 'temperature', 'top_p', 'variant', 'prompt_append'] as const;
4
+ const SECRET_FIELD_PATTERNS = [
5
+ 'api',
6
+ 'key',
7
+ 'token',
8
+ 'secret',
9
+ 'password',
10
+ 'auth',
11
+ 'credential',
12
+ 'private',
13
+ 'cert',
14
+ ];
15
+
16
+ const SAFE_TOKEN_FIELD_NAMES = new Set(['max_tokens', 'budget_tokens']);
17
+
18
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
19
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
20
+ }
6
21
 
7
- /**
8
- * Filters an agent config to only include allowed fields
9
- */
10
- function filterAgentConfig(agent: Record<string, unknown>): Record<string, unknown> {
11
- const filtered: Record<string, unknown> = {};
12
-
13
- for (const field of ALLOWED_AGENT_FIELDS) {
14
- if (agent[field] !== undefined) {
15
- filtered[field] = agent[field];
22
+ function isSecretLikeField(field: string): boolean {
23
+ const normalizedField = field
24
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
25
+ .toLowerCase();
26
+
27
+ const parts = normalizedField.split(/[^a-z0-9]+/);
28
+
29
+ // 1. Check for separated or camelCase fields (exact token matches)
30
+ if (parts.some((p) => p !== '' && SECRET_FIELD_PATTERNS.includes(p))) {
31
+ if (SAFE_TOKEN_FIELD_NAMES.has(normalizedField)) {
32
+ return false;
16
33
  }
34
+
35
+ return true;
36
+ }
37
+
38
+ // 2. Check for common concatenated sensitive fields (whole string matches)
39
+ // This satisfies the Codex check for "apikey", "accesstoken", "privatekey"
40
+ const concatenatedSecrets = [
41
+ 'apikey',
42
+ 'accesskey',
43
+ 'accesstoken',
44
+ 'authtoken',
45
+ 'privatekey',
46
+ 'secretkey',
47
+ 'passwordhash',
48
+ 'credential'
49
+ ];
50
+ if (concatenatedSecrets.includes(normalizedField)) {
51
+ return true;
52
+ }
53
+
54
+ return false;
55
+ }
56
+
57
+ function isAgentOrCategoryIdentifierPath(path: string): boolean {
58
+ return path === 'agents' || path === 'categories';
59
+ }
60
+
61
+ function collectSecretLikeFields(value: unknown, path = ''): string[] {
62
+ if (Array.isArray(value)) {
63
+ return value.flatMap((entry, index) => collectSecretLikeFields(entry, `${path}[${index}]`));
64
+ }
65
+
66
+ if (!isPlainObject(value)) {
67
+ return [];
68
+ }
69
+
70
+ const disallowedFields: string[] = [];
71
+
72
+ for (const [key, childValue] of Object.entries(value)) {
73
+ const fieldPath = path ? `${path}.${key}` : key;
74
+ const isMapIdentifier = isAgentOrCategoryIdentifierPath(path);
75
+
76
+ if (!isMapIdentifier && isSecretLikeField(key)) {
77
+ disallowedFields.push(fieldPath);
78
+ continue;
79
+ }
80
+
81
+ disallowedFields.push(...collectSecretLikeFields(childValue, fieldPath));
82
+ }
83
+
84
+ return disallowedFields;
85
+ }
86
+
87
+ function stripSecretLikeFields(value: unknown, path = ''): unknown {
88
+ if (Array.isArray(value)) {
89
+ return value.map((entry, index) => stripSecretLikeFields(entry, `${path}[${index}]`));
90
+ }
91
+
92
+ if (!isPlainObject(value)) {
93
+ return value;
94
+ }
95
+
96
+ const safeValue: Record<string, unknown> = {};
97
+
98
+ for (const [key, childValue] of Object.entries(value)) {
99
+ const fieldPath = path ? `${path}.${key}` : key;
100
+ const isMapIdentifier = isAgentOrCategoryIdentifierPath(path);
101
+
102
+ if (isMapIdentifier || !isSecretLikeField(key)) {
103
+ safeValue[key] = stripSecretLikeFields(childValue, fieldPath);
104
+ }
105
+ }
106
+
107
+ return safeValue;
108
+ }
109
+
110
+ function mergeUnknownConfigValue(currentValue: unknown, submittedValue: unknown): unknown {
111
+ if (!isPlainObject(currentValue) || !isPlainObject(submittedValue)) {
112
+ return submittedValue;
113
+ }
114
+
115
+ const mergedValue: Record<string, unknown> = { ...currentValue };
116
+
117
+ for (const [key, childValue] of Object.entries(submittedValue)) {
118
+ mergedValue[key] = mergeUnknownConfigValue(mergedValue[key], childValue);
119
+ }
120
+
121
+ return mergedValue;
122
+ }
123
+
124
+ function badRequest(error: string) {
125
+ return NextResponse.json({ error }, { status: 400 });
126
+ }
127
+
128
+ function forbidden(disallowedFields: string[]) {
129
+ return NextResponse.json(
130
+ { error: `Config contains disallowed fields: ${disallowedFields.join(', ')}` },
131
+ { status: 403 }
132
+ );
133
+ }
134
+
135
+ function validateStringField(section: string, field: string, value: unknown, options: { nonEmpty?: boolean } = {}) {
136
+ if (typeof value !== 'string' || (options.nonEmpty && value.trim() === '')) {
137
+ return badRequest(`${section}: ${field} must be ${options.nonEmpty ? 'a non-empty string' : 'a string'}`);
138
+ }
139
+
140
+ return null;
141
+ }
142
+
143
+ function validateFiniteNumber(section: string, field: string, value: unknown) {
144
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
145
+ return badRequest(`${section}: ${field} must be a finite number`);
146
+ }
147
+
148
+ return null;
149
+ }
150
+
151
+ function validateFallbackModelEntry(section: string, value: unknown) {
152
+ if (typeof value === 'string' || isPlainObject(value)) {
153
+ return null;
154
+ }
155
+
156
+ return badRequest(`${section}: fallback_models entries must be strings or objects`);
157
+ }
158
+
159
+ function validateAgentOrCategoryField(section: string, field: string, value: unknown) {
160
+ switch (field) {
161
+ case 'model':
162
+ return validateStringField(section, field, value, { nonEmpty: true });
163
+ case 'variant':
164
+ case 'prompt_append':
165
+ case 'description':
166
+ case 'category':
167
+ case 'system':
168
+ return validateStringField(section, field, value);
169
+ case 'reasoningEffort':
170
+ if (value === null) return null;
171
+ return validateStringField(section, field, value);
172
+ case 'temperature': {
173
+ const error = validateFiniteNumber(section, field, value);
174
+ if (error) return error;
175
+
176
+ const temperature = value as number;
177
+ if (temperature < 0 || temperature > 2) {
178
+ return badRequest(`${section}: temperature must be a number between 0 and 2`);
179
+ }
180
+
181
+ return null;
182
+ }
183
+ case 'top_p': {
184
+ const error = validateFiniteNumber(section, field, value);
185
+ if (error) return error;
186
+
187
+ const topP = value as number;
188
+ if (topP < 0 || topP > 1) {
189
+ return badRequest(`${section}: top_p must be a number between 0 and 1`);
190
+ }
191
+
192
+ return null;
193
+ }
194
+ case 'maxTokens':
195
+ case 'max_tokens': {
196
+ const error = validateFiniteNumber(section, field, value);
197
+ if (error) return error;
198
+
199
+ if ((value as number) <= 0) {
200
+ return badRequest(`${section}: ${field} must be greater than 0`);
201
+ }
202
+
203
+ return null;
204
+ }
205
+ case 'thinking':
206
+ if (typeof value !== 'boolean' && !isPlainObject(value)) {
207
+ return badRequest(`${section}: thinking must be a boolean or object`);
208
+ }
209
+
210
+ return null;
211
+ case 'fallback_models':
212
+ if (value === null) return null;
213
+ if (Array.isArray(value)) {
214
+ for (const entry of value) {
215
+ const error = validateFallbackModelEntry(section, entry);
216
+ if (error) return error;
217
+ }
218
+
219
+ return null;
220
+ }
221
+
222
+ return validateFallbackModelEntry(section, value);
223
+ default:
224
+ return null;
17
225
  }
18
-
19
- return filtered;
226
+ }
227
+
228
+ function validateVibePulseField(field: string, value: unknown) {
229
+ if (field === 'stickyBusyDelayMs' || field === 'sessionsRefreshIntervalMs') {
230
+ const error = validateFiniteNumber('Vibepulse', field, value);
231
+ if (error) return error;
232
+
233
+ if (field === 'stickyBusyDelayMs' && (value as number) < 0) {
234
+ return badRequest(`Vibepulse: '${field}' must be a non-negative number`);
235
+ }
236
+
237
+ if (field === 'sessionsRefreshIntervalMs' && (value as number) <= 0) {
238
+ return badRequest(`Vibepulse: '${field}' must be greater than 0`);
239
+ }
240
+ }
241
+
242
+ if (field === 'openEditorTargetMode' && value !== 'remote' && value !== 'hub') {
243
+ return badRequest(`Vibepulse: '${field}' must be either 'remote' or 'hub'`);
244
+ }
245
+
246
+ return null;
20
247
  }
21
248
 
22
249
  /**
23
250
  * GET /api/opencode-config
24
- * Returns filtered agent configuration
25
- * Only exposes: model, temperature, top_p
251
+ * Returns safe v4-compatible configuration
26
252
  * Filters out sensitive fields (apiKey, token, password, etc.)
27
253
  */
28
254
  export async function GET() {
29
255
  try {
30
256
  const config = await readConfig();
257
+ const safeConfig = stripSecretLikeFields(config) as Record<string, unknown>;
31
258
  const agents = config.agents || {};
32
259
  const filteredAgents: Record<string, Record<string, unknown>> = {};
33
260
 
34
261
  for (const [agentName, agentConfig] of Object.entries(agents)) {
35
- if (typeof agentConfig === 'object' && agentConfig !== null) {
36
- filteredAgents[agentName] = filterAgentConfig(agentConfig as Record<string, unknown>);
262
+ if (isPlainObject(agentConfig)) {
263
+ filteredAgents[agentName] = stripSecretLikeFields(agentConfig) as Record<string, unknown>;
37
264
  }
38
265
  }
39
266
 
@@ -41,16 +268,21 @@ export async function GET() {
41
268
  const filteredCategories: Record<string, Record<string, unknown>> = {};
42
269
 
43
270
  for (const [catName, catConfig] of Object.entries(categories)) {
44
- if (typeof catConfig === 'object' && catConfig !== null && !Array.isArray(catConfig)) {
45
- filteredCategories[catName] = filterAgentConfig(catConfig as Record<string, unknown>);
271
+ if (isPlainObject(catConfig)) {
272
+ filteredCategories[catName] = stripSecretLikeFields(catConfig) as Record<string, unknown>;
46
273
  }
47
274
  }
48
275
 
49
- const vibepulse = normalizeVibePulseConfig(config.vibepulse);
276
+ const vibepulse = stripSecretLikeFields(normalizeVibePulseConfig(config.vibepulse));
277
+ const teamMode = isPlainObject(config.team_mode)
278
+ ? stripSecretLikeFields(config.team_mode)
279
+ : config.team_mode;
50
280
 
51
- return NextResponse.json({
281
+ return NextResponse.json({
282
+ ...safeConfig,
52
283
  agents: filteredAgents,
53
284
  categories: filteredCategories,
285
+ team_mode: teamMode,
54
286
  vibepulse
55
287
  });
56
288
  } catch (error) {
@@ -65,7 +297,6 @@ export async function GET() {
65
297
  /**
66
298
  * POST /api/opencode-config
67
299
  * Updates agent configuration with validation
68
- * Only allows: model, temperature, top_p
69
300
  * Rejects sensitive fields (apiKey, token, password, secret, etc.)
70
301
  */
71
302
  export async function POST(request: NextRequest) {
@@ -73,19 +304,24 @@ export async function POST(request: NextRequest) {
73
304
  const body = await request.json();
74
305
 
75
306
  // Validate request structure
76
- if (!body || typeof body !== 'object') {
307
+ if (!body || typeof body !== 'object' || Array.isArray(body)) {
77
308
  return NextResponse.json(
78
309
  { error: 'Invalid request body' },
79
310
  { status: 400 }
80
311
  );
81
312
  }
82
313
 
83
- const { agents, categories, vibepulse } = body;
314
+ const disallowedFields = collectSecretLikeFields(body);
315
+ if (disallowedFields.length > 0) {
316
+ return forbidden(disallowedFields);
317
+ }
318
+
319
+ const { agents, categories, vibepulse, team_mode: teamMode } = body;
84
320
 
85
321
  // If neither agents, categories, nor vibepulse provided, nothing to update
86
- if (agents === undefined && categories === undefined && vibepulse === undefined) {
322
+ if (Object.keys(body).length === 0) {
87
323
  return NextResponse.json(
88
- { error: 'Missing agents, categories, or vibepulse field' },
324
+ { error: 'Missing config fields to update' },
89
325
  { status: 400 }
90
326
  );
91
327
  }
@@ -114,6 +350,24 @@ export async function POST(request: NextRequest) {
114
350
  );
115
351
  }
116
352
 
353
+ if (teamMode !== undefined && (typeof teamMode !== 'object' || teamMode === null || Array.isArray(teamMode))) {
354
+ return NextResponse.json(
355
+ { error: 'team_mode must be an object' },
356
+ { status: 400 }
357
+ );
358
+ }
359
+
360
+ if (
361
+ isPlainObject(teamMode) &&
362
+ Object.prototype.hasOwnProperty.call(teamMode, 'enabled') &&
363
+ typeof teamMode.enabled !== 'boolean'
364
+ ) {
365
+ return NextResponse.json(
366
+ { error: 'team_mode.enabled must be a boolean' },
367
+ { status: 400 }
368
+ );
369
+ }
370
+
117
371
  // Read current config
118
372
  const currentConfig = await readConfig();
119
373
  const currentAgents = currentConfig.agents || {};
@@ -129,7 +383,7 @@ export async function POST(request: NextRequest) {
129
383
 
130
384
  if (agents !== undefined) {
131
385
  for (const [agentName, agentConfig] of Object.entries(agents)) {
132
- if (typeof agentConfig !== 'object' || agentConfig === null || Array.isArray(agentConfig)) {
386
+ if (!isPlainObject(agentConfig)) {
133
387
  return NextResponse.json(
134
388
  { error: `Agent '${agentName}' config must be an object` },
135
389
  { status: 400 }
@@ -137,95 +391,27 @@ export async function POST(request: NextRequest) {
137
391
  }
138
392
 
139
393
  const config = agentConfig as Record<string, unknown>;
140
- const disallowedFields: string[] = [];
141
-
142
- for (const key of Object.keys(config)) {
143
- const lowerKey = key.toLowerCase();
144
- if (
145
- lowerKey.includes('api') ||
146
- lowerKey.includes('key') ||
147
- lowerKey.includes('token') ||
148
- lowerKey.includes('secret') ||
149
- lowerKey.includes('password') ||
150
- lowerKey.includes('auth') ||
151
- lowerKey.includes('credential') ||
152
- lowerKey.includes('private') ||
153
- lowerKey.includes('cert')
154
- ) {
155
- disallowedFields.push(key);
156
- }
157
- }
158
-
159
- if (disallowedFields.length > 0) {
160
- return NextResponse.json(
161
- {
162
- error: `Agent '${agentName}' contains disallowed fields: ${disallowedFields.join(', ')}`
163
- },
164
- { status: 403 }
165
- );
166
- }
167
394
 
168
395
  const validatedConfig: Record<string, unknown> = {};
169
396
 
170
397
  for (const [field, value] of Object.entries(config)) {
171
- const lowerField = field.toLowerCase();
172
-
173
- if (lowerField === 'model') {
174
- if (typeof value !== 'string' || value.trim() === '') {
175
- return NextResponse.json(
176
- { error: `Agent '${agentName}': model must be a non-empty string` },
177
- { status: 400 }
178
- );
179
- }
180
- validatedConfig[field] = value;
181
- } else if (lowerField === 'temperature') {
182
- const temp = Number(value);
183
- if (isNaN(temp) || temp < 0 || temp > 2) {
184
- return NextResponse.json(
185
- { error: `Agent '${agentName}': temperature must be a number between 0 and 2` },
186
- { status: 400 }
187
- );
188
- }
189
- validatedConfig[field] = temp;
190
- } else if (lowerField === 'top_p') {
191
- const topP = Number(value);
192
- if (isNaN(topP) || topP < 0 || topP > 1) {
193
- return NextResponse.json(
194
- { error: `Agent '${agentName}': top_p must be a number between 0 and 1` },
195
- { status: 400 }
196
- );
197
- }
198
- validatedConfig[field] = topP;
199
- } else if (lowerField === 'variant') {
200
- if (typeof value !== 'string') {
201
- return NextResponse.json(
202
- { error: `Agent '${agentName}': variant must be a string` },
203
- { status: 400 }
204
- );
205
- }
206
- validatedConfig[field] = value;
207
- } else if (lowerField === 'prompt_append') {
208
- if (typeof value !== 'string') {
209
- return NextResponse.json(
210
- { error: `Agent '${agentName}': prompt_append must be a string` },
211
- { status: 400 }
212
- );
213
- }
214
- validatedConfig[field] = value;
215
- } else {
216
- return NextResponse.json(
217
- {
218
- error: `Agent '${agentName}': unknown field '${field}'. Allowed fields: model, temperature, top_p, variant, prompt_append`
219
- },
220
- { status: 400 }
221
- );
222
- }
398
+ const error = validateAgentOrCategoryField(`Agent '${agentName}'`, field, value);
399
+ if (error) return error;
400
+
401
+ validatedConfig[field] = value;
223
402
  }
224
403
 
225
404
  updatedAgents[agentName] = {
226
405
  ...(currentAgents[agentName] as Record<string, unknown> || {}),
227
406
  ...validatedConfig
228
407
  };
408
+
409
+ if (validatedConfig.reasoningEffort === null) {
410
+ delete updatedAgents[agentName].reasoningEffort;
411
+ }
412
+ if (validatedConfig.fallback_models === null) {
413
+ delete updatedAgents[agentName].fallback_models;
414
+ }
229
415
  }
230
416
  }
231
417
 
@@ -241,7 +427,7 @@ export async function POST(request: NextRequest) {
241
427
 
242
428
  if (categories !== undefined) {
243
429
  for (const [categoryName, categoryConfig] of Object.entries(categories)) {
244
- if (typeof categoryConfig !== 'object' || categoryConfig === null || Array.isArray(categoryConfig)) {
430
+ if (!isPlainObject(categoryConfig)) {
245
431
  return NextResponse.json(
246
432
  { error: `Category '${categoryName}' config must be an object` },
247
433
  { status: 400 }
@@ -252,39 +438,23 @@ export async function POST(request: NextRequest) {
252
438
  const validatedCategoryConfig: Record<string, unknown> = {};
253
439
 
254
440
  for (const [field, value] of Object.entries(configObj)) {
255
- if (field === 'model' || field === 'variant' || field === 'prompt_append' || field === 'description') {
256
- if (value !== undefined && typeof value !== 'string') {
257
- return NextResponse.json(
258
- { error: `Category '${categoryName}': '${field}' must be a string` },
259
- { status: 400 }
260
- );
261
- }
262
- validatedCategoryConfig[field] = value;
263
- } else if (field === 'temperature' || field === 'top_p') {
264
- if (value !== undefined && typeof value !== 'number') {
265
- return NextResponse.json(
266
- { error: `Category '${categoryName}': '${field}' must be a number` },
267
- { status: 400 }
268
- );
269
- }
270
-
271
- const numValue = value as number;
272
- const temp = field === 'temperature' ? Math.max(0, Math.min(2, numValue)) : numValue;
273
- const topP = field === 'top_p' ? Math.max(0, Math.min(1, numValue)) : numValue;
274
-
275
- validatedCategoryConfig[field] = field === 'temperature' ? temp : topP;
276
- } else {
277
- return NextResponse.json(
278
- { error: `Category '${categoryName}': unknown field '${field}'` },
279
- { status: 400 }
280
- );
281
- }
441
+ const error = validateAgentOrCategoryField(`Category '${categoryName}'`, field, value);
442
+ if (error) return error;
443
+
444
+ validatedCategoryConfig[field] = value;
282
445
  }
283
446
 
284
447
  updatedCategories[categoryName] = {
285
448
  ...((currentCategories[categoryName] as Record<string, unknown>) || {}),
286
449
  ...validatedCategoryConfig
287
450
  };
451
+
452
+ if (validatedCategoryConfig.reasoningEffort === null) {
453
+ delete updatedCategories[categoryName].reasoningEffort;
454
+ }
455
+ if (validatedCategoryConfig.fallback_models === null) {
456
+ delete updatedCategories[categoryName].fallback_models;
457
+ }
288
458
  }
289
459
  }
290
460
 
@@ -298,72 +468,53 @@ export async function POST(request: NextRequest) {
298
468
  }
299
469
 
300
470
  for (const [field, value] of Object.entries(vibepulse as Record<string, unknown>)) {
301
- if (field === 'stickyBusyDelayMs' || field === 'sessionsRefreshIntervalMs') {
302
- if (value !== undefined && typeof value !== 'number') {
303
- return NextResponse.json(
304
- { error: `Vibepulse: '${field}' must be a number` },
305
- { status: 400 }
306
- );
307
- }
308
- if (typeof value === 'number') {
309
- if (!Number.isFinite(value)) {
310
- return NextResponse.json(
311
- { error: `Vibepulse: '${field}' must be a finite number` },
312
- { status: 400 }
313
- );
314
- }
315
-
316
- if (field === 'stickyBusyDelayMs' && value < 0) {
317
- return NextResponse.json(
318
- { error: `Vibepulse: '${field}' must be a non-negative number` },
319
- { status: 400 }
320
- );
321
- }
322
-
323
- if (field === 'sessionsRefreshIntervalMs' && value <= 0) {
324
- return NextResponse.json(
325
- { error: `Vibepulse: '${field}' must be greater than 0` },
326
- { status: 400 }
327
- );
328
- }
329
-
330
- updatedVibepulse[field] = value;
331
- }
332
- } else if (field === 'openEditorTargetMode') {
333
- if (value !== 'remote' && value !== 'hub') {
334
- return NextResponse.json(
335
- { error: `Vibepulse: '${field}' must be either 'remote' or 'hub'` },
336
- { status: 400 }
337
- );
338
- }
471
+ const error = validateVibePulseField(field, value);
472
+ if (error) return error;
339
473
 
340
- updatedVibepulse[field] = value;
341
- } else {
342
- return NextResponse.json(
343
- { error: `Vibepulse: unknown field '${field}'` },
344
- { status: 400 }
345
- );
346
- }
474
+ updatedVibepulse[field] = value;
347
475
  }
348
476
  }
349
477
 
350
478
  // Update config and save
351
479
  const newConfig = { ...currentConfig } as Record<string, unknown>;
480
+
481
+ for (const [field, value] of Object.entries(body)) {
482
+ if (field !== 'agents' && field !== 'categories' && field !== 'vibepulse' && field !== 'team_mode') {
483
+ newConfig[field] = mergeUnknownConfigValue(newConfig[field], value);
484
+ }
485
+ }
486
+
352
487
  if (agents !== undefined) newConfig.agents = updatedAgents;
353
488
  if (categories !== undefined) newConfig.categories = updatedCategories;
354
489
  if (vibepulse !== undefined) newConfig.vibepulse = updatedVibepulse;
490
+ if (teamMode !== undefined) {
491
+ newConfig.team_mode = {
492
+ ...(isPlainObject(currentConfig.team_mode) ? currentConfig.team_mode : {}),
493
+ ...(teamMode as Record<string, unknown>),
494
+ };
495
+ }
355
496
 
356
497
  // writeConfig type doesn't natively expose categories yet, safely bypassing
357
498
  await writeConfig(
358
499
  newConfig as {
359
- agents?: Record<string, Record<string, unknown>>;
360
- categories?: Record<string, Record<string, unknown>>;
361
- vibepulse?: Record<string, unknown>;
362
- }
363
- );
500
+ agents?: Record<string, Record<string, unknown>>;
501
+ categories?: Record<string, Record<string, unknown>>;
502
+ vibepulse?: Record<string, unknown>;
503
+ team_mode?: Record<string, unknown>;
504
+ }
505
+ );
506
+
507
+ const safeResponse = stripSecretLikeFields(newConfig) as Record<string, unknown>;
364
508
 
365
509
  return NextResponse.json(
366
- { success: true, agents: updatedAgents, categories: updatedCategories, vibepulse: updatedVibepulse },
510
+ {
511
+ ...safeResponse,
512
+ success: true,
513
+ agents: safeResponse.agents,
514
+ categories: safeResponse.categories,
515
+ team_mode: safeResponse.team_mode,
516
+ vibepulse: safeResponse.vibepulse,
517
+ },
367
518
  { status: 200 }
368
519
  );
369
520
  } catch (error) {