chorus-codes 0.7.2 → 0.7.4

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 (518) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +7 -7
  3. package/.next/build-manifest.json +13 -14
  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/webpack/client-production/0.pack +0 -0
  8. package/.next/cache/webpack/client-production/index.pack +0 -0
  9. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  10. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  11. package/.next/cache/webpack/server-production/0.pack +0 -0
  12. package/.next/cache/webpack/server-production/index.pack +0 -0
  13. package/.next/next-minimal-server.js.nft.json +1 -1
  14. package/.next/next-server.js.nft.json +1 -1
  15. package/.next/prerender-manifest.json +3 -3
  16. package/.next/react-loadable-manifest.json +6 -0
  17. package/.next/required-server-files.js +2 -0
  18. package/.next/required-server-files.json +2 -0
  19. package/.next/server/app/_global-error/page.js +32 -10
  20. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  21. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -3
  22. package/.next/server/app/_global-error.html +1 -1
  23. package/.next/server/app/_global-error.meta +2 -1
  24. package/.next/server/app/_global-error.rsc +8 -9
  25. package/.next/server/app/_global-error.segments/_full.segment.rsc +8 -9
  26. package/.next/server/app/_global-error.segments/{__PAGE__.segment.rsc → _global-error/__PAGE__.segment.rsc} +2 -2
  27. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +5 -0
  28. package/.next/server/app/_global-error.segments/_head.segment.rsc +3 -4
  29. package/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  30. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  31. package/.next/server/app/_not-found/page.js +2 -13
  32. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  33. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -3
  34. package/.next/server/app/_not-found.html +1 -1
  35. package/.next/server/app/_not-found.rsc +12 -10
  36. package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -10
  37. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  38. package/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  39. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  40. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  41. package/.next/server/app/_not-found.segments/_tree.segment.rsc +4 -2
  42. package/.next/server/app/api/daemon/[...path]/route.js +1 -7
  43. package/.next/server/app/api/daemon/[...path]/route.js.nft.json +1 -1
  44. package/.next/server/app/api/daemon/[...path]/route_client-reference-manifest.js +1 -3
  45. package/.next/server/app/api/run-artifacts/[chatId]/route.js +1 -6
  46. package/.next/server/app/api/run-artifacts/[chatId]/route.js.nft.json +1 -1
  47. package/.next/server/app/api/run-artifacts/[chatId]/route_client-reference-manifest.js +1 -3
  48. package/.next/server/app/connect/page.js +2 -15
  49. package/.next/server/app/connect/page.js.nft.json +1 -1
  50. package/.next/server/app/connect/page_client-reference-manifest.js +1 -3
  51. package/.next/server/app/favicon.ico/route.js +1 -8
  52. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  53. package/.next/server/app/icon.svg/route.js +1 -7
  54. package/.next/server/app/icon.svg/route.js.nft.json +1 -1
  55. package/.next/server/app/new/page.js +2 -14
  56. package/.next/server/app/new/page.js.nft.json +1 -1
  57. package/.next/server/app/new/page_client-reference-manifest.js +1 -3
  58. package/.next/server/app/new.html +1 -1
  59. package/.next/server/app/new.rsc +14 -14
  60. package/.next/server/app/new.segments/_full.segment.rsc +14 -14
  61. package/.next/server/app/new.segments/_head.segment.rsc +4 -4
  62. package/.next/server/app/new.segments/_index.segment.rsc +4 -4
  63. package/.next/server/app/new.segments/_tree.segment.rsc +4 -4
  64. package/.next/server/app/new.segments/new/__PAGE__.segment.rsc +4 -4
  65. package/.next/server/app/new.segments/new.segment.rsc +3 -3
  66. package/.next/server/app/onboarding/page.js +2 -14
  67. package/.next/server/app/onboarding/page.js.nft.json +1 -1
  68. package/.next/server/app/onboarding/page_client-reference-manifest.js +1 -3
  69. package/.next/server/app/onboarding.html +1 -1
  70. package/.next/server/app/onboarding.rsc +14 -14
  71. package/.next/server/app/onboarding.segments/_full.segment.rsc +14 -14
  72. package/.next/server/app/onboarding.segments/_head.segment.rsc +4 -4
  73. package/.next/server/app/onboarding.segments/_index.segment.rsc +4 -4
  74. package/.next/server/app/onboarding.segments/_tree.segment.rsc +4 -4
  75. package/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +4 -4
  76. package/.next/server/app/onboarding.segments/onboarding.segment.rsc +3 -3
  77. package/.next/server/app/page.js +2 -17
  78. package/.next/server/app/page.js.nft.json +1 -1
  79. package/.next/server/app/page_client-reference-manifest.js +1 -3
  80. package/.next/server/app/personas/page.js +2 -14
  81. package/.next/server/app/personas/page.js.nft.json +1 -1
  82. package/.next/server/app/personas/page_client-reference-manifest.js +1 -3
  83. package/.next/server/app/personas.html +1 -1
  84. package/.next/server/app/personas.rsc +14 -14
  85. package/.next/server/app/personas.segments/_full.segment.rsc +14 -14
  86. package/.next/server/app/personas.segments/_head.segment.rsc +4 -4
  87. package/.next/server/app/personas.segments/_index.segment.rsc +4 -4
  88. package/.next/server/app/personas.segments/_tree.segment.rsc +4 -4
  89. package/.next/server/app/personas.segments/personas/__PAGE__.segment.rsc +4 -4
  90. package/.next/server/app/personas.segments/personas.segment.rsc +3 -3
  91. package/.next/server/app/runs/[runId]/page.js +2 -16
  92. package/.next/server/app/runs/[runId]/page.js.nft.json +1 -1
  93. package/.next/server/app/runs/[runId]/page_client-reference-manifest.js +1 -3
  94. package/.next/server/app/runs/page.js +2 -15
  95. package/.next/server/app/runs/page.js.nft.json +1 -1
  96. package/.next/server/app/runs/page_client-reference-manifest.js +1 -3
  97. package/.next/server/app/settings/page.js +26 -14
  98. package/.next/server/app/settings/page.js.nft.json +1 -1
  99. package/.next/server/app/settings/page_client-reference-manifest.js +1 -3
  100. package/.next/server/app/settings/permissions/page.js +2 -14
  101. package/.next/server/app/settings/permissions/page.js.nft.json +1 -1
  102. package/.next/server/app/settings/permissions/page_client-reference-manifest.js +1 -3
  103. package/.next/server/app/settings.html +1 -1
  104. package/.next/server/app/settings.rsc +14 -14
  105. package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
  106. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  107. package/.next/server/app/settings.segments/_index.segment.rsc +4 -4
  108. package/.next/server/app/settings.segments/_tree.segment.rsc +4 -4
  109. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  110. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  111. package/.next/server/app/templates/page.js +2 -14
  112. package/.next/server/app/templates/page.js.nft.json +1 -1
  113. package/.next/server/app/templates/page_client-reference-manifest.js +1 -3
  114. package/.next/server/app/templates.html +1 -1
  115. package/.next/server/app/templates.rsc +14 -14
  116. package/.next/server/app/templates.segments/_full.segment.rsc +14 -14
  117. package/.next/server/app/templates.segments/_head.segment.rsc +4 -4
  118. package/.next/server/app/templates.segments/_index.segment.rsc +4 -4
  119. package/.next/server/app/templates.segments/_tree.segment.rsc +4 -4
  120. package/.next/server/app/templates.segments/templates/__PAGE__.segment.rsc +4 -4
  121. package/.next/server/app/templates.segments/templates.segment.rsc +3 -3
  122. package/.next/server/app-paths-manifest.json +7 -7
  123. package/.next/server/chunks/144.js +25 -0
  124. package/.next/server/chunks/332.js +18 -0
  125. package/.next/server/chunks/418.js +1 -0
  126. package/.next/server/chunks/429.js +1 -0
  127. package/.next/server/chunks/451.js +45 -0
  128. package/.next/server/chunks/498.js +1 -0
  129. package/.next/server/chunks/504.js +1 -0
  130. package/.next/server/chunks/557.js +5 -0
  131. package/.next/server/chunks/668.js +25 -0
  132. package/.next/server/chunks/681.js +1 -0
  133. package/.next/server/chunks/946.js +1 -0
  134. package/.next/server/chunks/95.js +1 -0
  135. package/.next/server/middleware-build-manifest.js +1 -21
  136. package/.next/server/middleware-manifest.json +2 -2
  137. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  138. package/.next/server/next-font-manifest.js +1 -1
  139. package/.next/server/next-font-manifest.json +1 -51
  140. package/.next/server/pages/404.html +1 -1
  141. package/.next/server/pages/500.html +1 -1
  142. package/.next/server/server-reference-manifest.js +1 -1
  143. package/.next/server/server-reference-manifest.json +1 -5
  144. package/.next/server/webpack-runtime.js +1 -0
  145. package/.next/static/chunks/116-0372d11bc2a9ac4d.js +25 -0
  146. package/.next/static/chunks/128-a5d059bf5b2e5090.js +32 -0
  147. package/.next/static/chunks/15-d438a2b057302bed.js +1 -0
  148. package/.next/static/chunks/344-1f06059a92faa936.js +1 -0
  149. package/.next/static/chunks/720-9732eeb760e004e3.js +5 -0
  150. package/.next/static/chunks/744-2b89d96d64610581.js +1 -0
  151. package/.next/static/chunks/app/_global-error/page-c01ad9f9473ce080.js +1 -0
  152. package/.next/static/chunks/app/_not-found/page-715bac6dc7f3427d.js +1 -0
  153. package/.next/static/chunks/app/api/daemon/[...path]/route-c01ad9f9473ce080.js +1 -0
  154. package/.next/static/chunks/app/api/run-artifacts/[chatId]/route-c01ad9f9473ce080.js +1 -0
  155. package/.next/static/chunks/app/connect/page-c09d9fb410c468b7.js +1 -0
  156. package/.next/static/chunks/app/layout-df8acd5bd06cbe45.js +1 -0
  157. package/.next/static/chunks/app/new/page-e4923b87c7a7b6ae.js +1 -0
  158. package/.next/static/chunks/app/onboarding/page-4c87427335371aaa.js +1 -0
  159. package/.next/static/chunks/app/page-3c0d23c063b036eb.js +1 -0
  160. package/.next/static/chunks/app/personas/page-a130cd11d8cbd832.js +1 -0
  161. package/.next/static/chunks/app/runs/[runId]/page-aa118bfeb6508779.js +1 -0
  162. package/.next/static/chunks/app/runs/page-503439d57f433574.js +1 -0
  163. package/.next/static/chunks/app/settings/page-64d7d48d2413a18b.js +25 -0
  164. package/.next/static/chunks/app/settings/permissions/page-18bf0e6d84be8fad.js +1 -0
  165. package/.next/static/chunks/app/templates/page-db5165c6311bf6e1.js +1 -0
  166. package/.next/static/chunks/ed64ccb0-b7d2b5246d18ca7e.js +1 -0
  167. package/.next/static/chunks/framework-dc9b726cfb42e402.js +1 -0
  168. package/.next/static/chunks/main-2088f7ac0f762d6a.js +5 -0
  169. package/.next/static/chunks/main-app-e9f7985e32dc8a63.js +1 -0
  170. package/.next/static/chunks/next/dist/client/components/builtin/app-error-c01ad9f9473ce080.js +1 -0
  171. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-c01ad9f9473ce080.js +1 -0
  172. package/.next/static/chunks/next/dist/client/components/builtin/global-error-538b25894f1d36d8.js +1 -0
  173. package/.next/static/chunks/next/dist/client/components/builtin/not-found-c01ad9f9473ce080.js +1 -0
  174. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c01ad9f9473ce080.js +1 -0
  175. package/.next/static/chunks/webpack-87142ab87b87c8fb.js +1 -0
  176. package/.next/static/css/a552ff3997000a18.css +3 -0
  177. package/.next/static/fRcji-LCH-qqfsUepgR1t/_buildManifest.js +1 -0
  178. package/.next/trace +19 -1
  179. package/.next/trace-build +1 -1
  180. package/.next/types/app/api/daemon/[...path]/route.ts +351 -0
  181. package/.next/types/app/api/run-artifacts/[chatId]/route.ts +351 -0
  182. package/.next/types/app/connect/page.ts +87 -0
  183. package/.next/types/app/layout.ts +87 -0
  184. package/.next/types/app/new/page.ts +87 -0
  185. package/.next/types/app/onboarding/page.ts +87 -0
  186. package/.next/types/app/page.ts +87 -0
  187. package/.next/types/app/personas/page.ts +87 -0
  188. package/.next/types/app/runs/[runId]/page.ts +87 -0
  189. package/.next/types/app/runs/page.ts +87 -0
  190. package/.next/types/app/settings/page.ts +87 -0
  191. package/.next/types/app/settings/permissions/page.ts +87 -0
  192. package/.next/types/app/templates/page.ts +87 -0
  193. package/.next/types/package.json +1 -0
  194. package/dist/cli/commands/start.js +38 -4
  195. package/dist/cli/commands/start.js.map +1 -1
  196. package/dist/cli/port-utils.js +143 -7
  197. package/dist/cli/port-utils.js.map +1 -1
  198. package/dist/daemon/index.js +1 -1
  199. package/dist/mcp/index.js +1 -1
  200. package/package.json +2 -2
  201. package/.next/build/chunks/[root-of-the-server]__0d-m0h0._.js +0 -206
  202. package/.next/build/chunks/[root-of-the-server]__0d-m0h0._.js.map +0 -8
  203. package/.next/build/chunks/[root-of-the-server]__0ubbtyl._.js +0 -500
  204. package/.next/build/chunks/[root-of-the-server]__0ubbtyl._.js.map +0 -11
  205. package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_06e.r3r._.js +0 -13
  206. package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_06e.r3r._.js.map +0 -5
  207. package/.next/build/chunks/[turbopack]_runtime.js +0 -890
  208. package/.next/build/chunks/[turbopack]_runtime.js.map +0 -11
  209. package/.next/build/chunks/node_modules__pnpm_0e-dfa2._.js +0 -6681
  210. package/.next/build/chunks/node_modules__pnpm_0e-dfa2._.js.map +0 -47
  211. package/.next/build/package.json +0 -1
  212. package/.next/build/postcss.js +0 -6
  213. package/.next/build/postcss.js.map +0 -5
  214. package/.next/diagnostics/route-bundle-stats.json +0 -176
  215. package/.next/fallback-build-manifest.json +0 -13
  216. package/.next/server/app/_global-error/page/app-paths-manifest.json +0 -3
  217. package/.next/server/app/_global-error/page/build-manifest.json +0 -17
  218. package/.next/server/app/_global-error/page/next-font-manifest.json +0 -6
  219. package/.next/server/app/_global-error/page/react-loadable-manifest.json +0 -1
  220. package/.next/server/app/_global-error/page/server-reference-manifest.json +0 -4
  221. package/.next/server/app/_global-error/page.js.map +0 -5
  222. package/.next/server/app/_not-found/page/app-paths-manifest.json +0 -3
  223. package/.next/server/app/_not-found/page/build-manifest.json +0 -17
  224. package/.next/server/app/_not-found/page/next-font-manifest.json +0 -11
  225. package/.next/server/app/_not-found/page/react-loadable-manifest.json +0 -1
  226. package/.next/server/app/_not-found/page/server-reference-manifest.json +0 -4
  227. package/.next/server/app/_not-found/page.js.map +0 -5
  228. package/.next/server/app/api/daemon/[...path]/route/app-paths-manifest.json +0 -3
  229. package/.next/server/app/api/daemon/[...path]/route/build-manifest.json +0 -9
  230. package/.next/server/app/api/daemon/[...path]/route/server-reference-manifest.json +0 -4
  231. package/.next/server/app/api/daemon/[...path]/route.js.map +0 -5
  232. package/.next/server/app/api/run-artifacts/[chatId]/route/app-paths-manifest.json +0 -3
  233. package/.next/server/app/api/run-artifacts/[chatId]/route/build-manifest.json +0 -9
  234. package/.next/server/app/api/run-artifacts/[chatId]/route/server-reference-manifest.json +0 -4
  235. package/.next/server/app/api/run-artifacts/[chatId]/route.js.map +0 -5
  236. package/.next/server/app/connect/page/app-paths-manifest.json +0 -3
  237. package/.next/server/app/connect/page/build-manifest.json +0 -17
  238. package/.next/server/app/connect/page/next-font-manifest.json +0 -11
  239. package/.next/server/app/connect/page/react-loadable-manifest.json +0 -1
  240. package/.next/server/app/connect/page/server-reference-manifest.json +0 -4
  241. package/.next/server/app/connect/page.js.map +0 -5
  242. package/.next/server/app/favicon.ico/route/app-paths-manifest.json +0 -3
  243. package/.next/server/app/favicon.ico/route/build-manifest.json +0 -9
  244. package/.next/server/app/favicon.ico/route.js.map +0 -5
  245. package/.next/server/app/icon.svg/route/app-paths-manifest.json +0 -3
  246. package/.next/server/app/icon.svg/route/build-manifest.json +0 -9
  247. package/.next/server/app/icon.svg/route.js.map +0 -5
  248. package/.next/server/app/new/page/app-paths-manifest.json +0 -3
  249. package/.next/server/app/new/page/build-manifest.json +0 -17
  250. package/.next/server/app/new/page/next-font-manifest.json +0 -11
  251. package/.next/server/app/new/page/react-loadable-manifest.json +0 -1
  252. package/.next/server/app/new/page/server-reference-manifest.json +0 -4
  253. package/.next/server/app/new/page.js.map +0 -5
  254. package/.next/server/app/onboarding/page/app-paths-manifest.json +0 -3
  255. package/.next/server/app/onboarding/page/build-manifest.json +0 -17
  256. package/.next/server/app/onboarding/page/next-font-manifest.json +0 -11
  257. package/.next/server/app/onboarding/page/react-loadable-manifest.json +0 -1
  258. package/.next/server/app/onboarding/page/server-reference-manifest.json +0 -4
  259. package/.next/server/app/onboarding/page.js.map +0 -5
  260. package/.next/server/app/page/app-paths-manifest.json +0 -3
  261. package/.next/server/app/page/build-manifest.json +0 -17
  262. package/.next/server/app/page/next-font-manifest.json +0 -11
  263. package/.next/server/app/page/react-loadable-manifest.json +0 -1
  264. package/.next/server/app/page/server-reference-manifest.json +0 -4
  265. package/.next/server/app/page.js.map +0 -5
  266. package/.next/server/app/personas/page/app-paths-manifest.json +0 -3
  267. package/.next/server/app/personas/page/build-manifest.json +0 -17
  268. package/.next/server/app/personas/page/next-font-manifest.json +0 -11
  269. package/.next/server/app/personas/page/react-loadable-manifest.json +0 -1
  270. package/.next/server/app/personas/page/server-reference-manifest.json +0 -4
  271. package/.next/server/app/personas/page.js.map +0 -5
  272. package/.next/server/app/runs/[runId]/page/app-paths-manifest.json +0 -3
  273. package/.next/server/app/runs/[runId]/page/build-manifest.json +0 -17
  274. package/.next/server/app/runs/[runId]/page/next-font-manifest.json +0 -11
  275. package/.next/server/app/runs/[runId]/page/react-loadable-manifest.json +0 -1
  276. package/.next/server/app/runs/[runId]/page/server-reference-manifest.json +0 -4
  277. package/.next/server/app/runs/[runId]/page.js.map +0 -5
  278. package/.next/server/app/runs/page/app-paths-manifest.json +0 -3
  279. package/.next/server/app/runs/page/build-manifest.json +0 -17
  280. package/.next/server/app/runs/page/next-font-manifest.json +0 -11
  281. package/.next/server/app/runs/page/react-loadable-manifest.json +0 -1
  282. package/.next/server/app/runs/page/server-reference-manifest.json +0 -4
  283. package/.next/server/app/runs/page.js.map +0 -5
  284. package/.next/server/app/settings/page/app-paths-manifest.json +0 -3
  285. package/.next/server/app/settings/page/build-manifest.json +0 -17
  286. package/.next/server/app/settings/page/next-font-manifest.json +0 -11
  287. package/.next/server/app/settings/page/react-loadable-manifest.json +0 -1
  288. package/.next/server/app/settings/page/server-reference-manifest.json +0 -4
  289. package/.next/server/app/settings/page.js.map +0 -5
  290. package/.next/server/app/settings/permissions/page/app-paths-manifest.json +0 -3
  291. package/.next/server/app/settings/permissions/page/build-manifest.json +0 -17
  292. package/.next/server/app/settings/permissions/page/next-font-manifest.json +0 -11
  293. package/.next/server/app/settings/permissions/page/react-loadable-manifest.json +0 -1
  294. package/.next/server/app/settings/permissions/page/server-reference-manifest.json +0 -4
  295. package/.next/server/app/settings/permissions/page.js.map +0 -5
  296. package/.next/server/app/templates/page/app-paths-manifest.json +0 -3
  297. package/.next/server/app/templates/page/build-manifest.json +0 -17
  298. package/.next/server/app/templates/page/next-font-manifest.json +0 -11
  299. package/.next/server/app/templates/page/react-loadable-manifest.json +0 -1
  300. package/.next/server/app/templates/page/server-reference-manifest.json +0 -4
  301. package/.next/server/app/templates/page.js.map +0 -5
  302. package/.next/server/chunks/05w9_next_0xdex7s._.js +0 -13
  303. package/.next/server/chunks/05w9_next_0xdex7s._.js.map +0 -1
  304. package/.next/server/chunks/05w9_next_dist_esm_build_templates_app-route_0.73kst.js +0 -3
  305. package/.next/server/chunks/05w9_next_dist_esm_build_templates_app-route_0.73kst.js.map +0 -1
  306. package/.next/server/chunks/[externals]_next_dist_0arv.vj._.js +0 -3
  307. package/.next/server/chunks/[externals]_next_dist_0arv.vj._.js.map +0 -1
  308. package/.next/server/chunks/[root-of-the-server]__02xvj_h._.js +0 -3
  309. package/.next/server/chunks/[root-of-the-server]__02xvj_h._.js.map +0 -1
  310. package/.next/server/chunks/[root-of-the-server]__0i7ddmr._.js +0 -3
  311. package/.next/server/chunks/[root-of-the-server]__0i7ddmr._.js.map +0 -1
  312. package/.next/server/chunks/[root-of-the-server]__0sxhm1i._.js +0 -3
  313. package/.next/server/chunks/[root-of-the-server]__0sxhm1i._.js.map +0 -1
  314. package/.next/server/chunks/[root-of-the-server]__12xxby8._.js +0 -3
  315. package/.next/server/chunks/[root-of-the-server]__12xxby8._.js.map +0 -1
  316. package/.next/server/chunks/[turbopack]_runtime.js +0 -903
  317. package/.next/server/chunks/[turbopack]_runtime.js.map +0 -11
  318. package/.next/server/chunks/_next-internal_server_app_api_daemon_[___path]_route_actions_0a5g-ar.js +0 -3
  319. package/.next/server/chunks/_next-internal_server_app_api_daemon_[___path]_route_actions_0a5g-ar.js.map +0 -1
  320. package/.next/server/chunks/_next-internal_server_app_api_run-artifacts_[chatId]_route_actions_07e2ul1.js +0 -3
  321. package/.next/server/chunks/_next-internal_server_app_api_run-artifacts_[chatId]_route_actions_07e2ul1.js.map +0 -1
  322. package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_095lj93.js +0 -3
  323. package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_095lj93.js.map +0 -1
  324. package/.next/server/chunks/_next-internal_server_app_icon_svg_route_actions_0-0ehc~.js +0 -3
  325. package/.next/server/chunks/_next-internal_server_app_icon_svg_route_actions_0-0ehc~.js.map +0 -1
  326. package/.next/server/chunks/ssr/05w9_next_dist_0q4woef._.js +0 -3
  327. package/.next/server/chunks/ssr/05w9_next_dist_0q4woef._.js.map +0 -1
  328. package/.next/server/chunks/ssr/05w9_next_dist_0ybpwn1._.js +0 -6
  329. package/.next/server/chunks/ssr/05w9_next_dist_0ybpwn1._.js.map +0 -1
  330. package/.next/server/chunks/ssr/05w9_next_dist_0~859ji._.js +0 -6
  331. package/.next/server/chunks/ssr/05w9_next_dist_0~859ji._.js.map +0 -1
  332. package/.next/server/chunks/ssr/05w9_next_dist_client_components_12u3mib._.js +0 -3
  333. package/.next/server/chunks/ssr/05w9_next_dist_client_components_12u3mib._.js.map +0 -1
  334. package/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_forbidden_04fbe_..js +0 -3
  335. package/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_forbidden_04fbe_..js.map +0 -1
  336. package/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_global-error_0brpl_..js +0 -3
  337. package/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_global-error_0brpl_..js.map +0 -1
  338. package/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_unauthorized_0~2g66g.js +0 -3
  339. package/.next/server/chunks/ssr/05w9_next_dist_client_components_builtin_unauthorized_0~2g66g.js.map +0 -1
  340. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0-f~6r1.js +0 -4
  341. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0-f~6r1.js.map +0 -1
  342. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_00czn99.js +0 -4
  343. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_00czn99.js.map +0 -1
  344. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_01nm1_6.js +0 -4
  345. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_01nm1_6.js.map +0 -1
  346. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0jcydv7.js +0 -4
  347. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0jcydv7.js.map +0 -1
  348. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0km.hvi.js +0 -4
  349. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0km.hvi.js.map +0 -1
  350. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0ln8_qt.js +0 -4
  351. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0ln8_qt.js.map +0 -1
  352. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0n3h-j1.js +0 -4
  353. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0n3h-j1.js.map +0 -1
  354. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0nc~v.o.js +0 -4
  355. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0nc~v.o.js.map +0 -1
  356. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0o6nct3.js +0 -4
  357. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0o6nct3.js.map +0 -1
  358. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0veve6-.js +0 -4
  359. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0veve6-.js.map +0 -1
  360. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0wh5tpo.js +0 -4
  361. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_0wh5tpo.js.map +0 -1
  362. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_10~fsfu.js +0 -4
  363. package/.next/server/chunks/ssr/05w9_next_dist_esm_build_templates_app-page_10~fsfu.js.map +0 -1
  364. package/.next/server/chunks/ssr/[root-of-the-server]__0-7oo8o._.js +0 -3
  365. package/.next/server/chunks/ssr/[root-of-the-server]__0-7oo8o._.js.map +0 -1
  366. package/.next/server/chunks/ssr/[root-of-the-server]__01t9qm2._.js +0 -3
  367. package/.next/server/chunks/ssr/[root-of-the-server]__01t9qm2._.js.map +0 -1
  368. package/.next/server/chunks/ssr/[root-of-the-server]__076~t6~._.js +0 -3
  369. package/.next/server/chunks/ssr/[root-of-the-server]__076~t6~._.js.map +0 -1
  370. package/.next/server/chunks/ssr/[root-of-the-server]__0_tow-j._.js +0 -3
  371. package/.next/server/chunks/ssr/[root-of-the-server]__0_tow-j._.js.map +0 -1
  372. package/.next/server/chunks/ssr/[root-of-the-server]__0bsym8v._.js +0 -3
  373. package/.next/server/chunks/ssr/[root-of-the-server]__0bsym8v._.js.map +0 -1
  374. package/.next/server/chunks/ssr/[root-of-the-server]__0bwjwxi._.js +0 -3
  375. package/.next/server/chunks/ssr/[root-of-the-server]__0bwjwxi._.js.map +0 -1
  376. package/.next/server/chunks/ssr/[root-of-the-server]__0c2e5js._.js +0 -3
  377. package/.next/server/chunks/ssr/[root-of-the-server]__0c2e5js._.js.map +0 -1
  378. package/.next/server/chunks/ssr/[root-of-the-server]__0d_59pi._.js +0 -3
  379. package/.next/server/chunks/ssr/[root-of-the-server]__0d_59pi._.js.map +0 -1
  380. package/.next/server/chunks/ssr/[root-of-the-server]__0dxp2sg._.js +0 -3
  381. package/.next/server/chunks/ssr/[root-of-the-server]__0dxp2sg._.js.map +0 -1
  382. package/.next/server/chunks/ssr/[root-of-the-server]__0e58.k_._.js +0 -3
  383. package/.next/server/chunks/ssr/[root-of-the-server]__0e58.k_._.js.map +0 -1
  384. package/.next/server/chunks/ssr/[root-of-the-server]__0ek20dj._.js +0 -3
  385. package/.next/server/chunks/ssr/[root-of-the-server]__0ek20dj._.js.map +0 -1
  386. package/.next/server/chunks/ssr/[root-of-the-server]__0h2o43u._.js +0 -3
  387. package/.next/server/chunks/ssr/[root-of-the-server]__0h2o43u._.js.map +0 -1
  388. package/.next/server/chunks/ssr/[root-of-the-server]__0hn95cc._.js +0 -33
  389. package/.next/server/chunks/ssr/[root-of-the-server]__0hn95cc._.js.map +0 -1
  390. package/.next/server/chunks/ssr/[root-of-the-server]__0ic.~tw._.js +0 -3
  391. package/.next/server/chunks/ssr/[root-of-the-server]__0ic.~tw._.js.map +0 -1
  392. package/.next/server/chunks/ssr/[root-of-the-server]__0jltd-t._.js +0 -3
  393. package/.next/server/chunks/ssr/[root-of-the-server]__0jltd-t._.js.map +0 -1
  394. package/.next/server/chunks/ssr/[root-of-the-server]__0k_96yx._.js +0 -3
  395. package/.next/server/chunks/ssr/[root-of-the-server]__0k_96yx._.js.map +0 -1
  396. package/.next/server/chunks/ssr/[root-of-the-server]__0l5ko41._.js +0 -19
  397. package/.next/server/chunks/ssr/[root-of-the-server]__0l5ko41._.js.map +0 -1
  398. package/.next/server/chunks/ssr/[root-of-the-server]__0p~21w8._.js +0 -3
  399. package/.next/server/chunks/ssr/[root-of-the-server]__0p~21w8._.js.map +0 -1
  400. package/.next/server/chunks/ssr/[root-of-the-server]__0tc4gl8._.js +0 -3
  401. package/.next/server/chunks/ssr/[root-of-the-server]__0tc4gl8._.js.map +0 -1
  402. package/.next/server/chunks/ssr/[root-of-the-server]__0v73tbn._.js +0 -3
  403. package/.next/server/chunks/ssr/[root-of-the-server]__0v73tbn._.js.map +0 -1
  404. package/.next/server/chunks/ssr/[root-of-the-server]__0we1ana._.js +0 -3
  405. package/.next/server/chunks/ssr/[root-of-the-server]__0we1ana._.js.map +0 -1
  406. package/.next/server/chunks/ssr/[root-of-the-server]__0xlzjhk._.js +0 -3
  407. package/.next/server/chunks/ssr/[root-of-the-server]__0xlzjhk._.js.map +0 -1
  408. package/.next/server/chunks/ssr/[root-of-the-server]__0ygksjc._.js +0 -33
  409. package/.next/server/chunks/ssr/[root-of-the-server]__0ygksjc._.js.map +0 -1
  410. package/.next/server/chunks/ssr/[root-of-the-server]__0yhjl35._.js +0 -3
  411. package/.next/server/chunks/ssr/[root-of-the-server]__0yhjl35._.js.map +0 -1
  412. package/.next/server/chunks/ssr/[root-of-the-server]__0~cqs-9._.js +0 -3
  413. package/.next/server/chunks/ssr/[root-of-the-server]__0~cqs-9._.js.map +0 -1
  414. package/.next/server/chunks/ssr/[root-of-the-server]__109.1j0._.js +0 -3
  415. package/.next/server/chunks/ssr/[root-of-the-server]__109.1j0._.js.map +0 -1
  416. package/.next/server/chunks/ssr/[root-of-the-server]__10gepjv._.js +0 -3
  417. package/.next/server/chunks/ssr/[root-of-the-server]__10gepjv._.js.map +0 -1
  418. package/.next/server/chunks/ssr/[turbopack]_runtime.js +0 -903
  419. package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +0 -11
  420. package/.next/server/chunks/ssr/_01t~nag._.js +0 -30
  421. package/.next/server/chunks/ssr/_01t~nag._.js.map +0 -1
  422. package/.next/server/chunks/ssr/_097xk3e._.js +0 -3
  423. package/.next/server/chunks/ssr/_097xk3e._.js.map +0 -1
  424. package/.next/server/chunks/ssr/_0bxoss0._.js +0 -30
  425. package/.next/server/chunks/ssr/_0bxoss0._.js.map +0 -1
  426. package/.next/server/chunks/ssr/_0ck1n8_._.js +0 -7
  427. package/.next/server/chunks/ssr/_0ck1n8_._.js.map +0 -1
  428. package/.next/server/chunks/ssr/_0d-304b._.js +0 -30
  429. package/.next/server/chunks/ssr/_0d-304b._.js.map +0 -1
  430. package/.next/server/chunks/ssr/_0p-_ahq._.js +0 -30
  431. package/.next/server/chunks/ssr/_0p-_ahq._.js.map +0 -1
  432. package/.next/server/chunks/ssr/_0qlx_85._.js +0 -7
  433. package/.next/server/chunks/ssr/_0qlx_85._.js.map +0 -1
  434. package/.next/server/chunks/ssr/_0y43gyn._.js +0 -27
  435. package/.next/server/chunks/ssr/_0y43gyn._.js.map +0 -1
  436. package/.next/server/chunks/ssr/_11i54x9._.js +0 -30
  437. package/.next/server/chunks/ssr/_11i54x9._.js.map +0 -1
  438. package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0k77kol.js +0 -3
  439. package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0k77kol.js.map +0 -1
  440. package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0eq97pa.js +0 -3
  441. package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0eq97pa.js.map +0 -1
  442. package/.next/server/chunks/ssr/_next-internal_server_app_connect_page_actions_0vb8s6u.js +0 -3
  443. package/.next/server/chunks/ssr/_next-internal_server_app_connect_page_actions_0vb8s6u.js.map +0 -1
  444. package/.next/server/chunks/ssr/_next-internal_server_app_new_page_actions_08q6mx5.js +0 -3
  445. package/.next/server/chunks/ssr/_next-internal_server_app_new_page_actions_08q6mx5.js.map +0 -1
  446. package/.next/server/chunks/ssr/_next-internal_server_app_onboarding_page_actions_0qdby58.js +0 -3
  447. package/.next/server/chunks/ssr/_next-internal_server_app_onboarding_page_actions_0qdby58.js.map +0 -1
  448. package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js +0 -3
  449. package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js.map +0 -1
  450. package/.next/server/chunks/ssr/_next-internal_server_app_personas_page_actions_08fq21v.js +0 -3
  451. package/.next/server/chunks/ssr/_next-internal_server_app_personas_page_actions_08fq21v.js.map +0 -1
  452. package/.next/server/chunks/ssr/_next-internal_server_app_runs_[runId]_page_actions_0z6r2tz.js +0 -3
  453. package/.next/server/chunks/ssr/_next-internal_server_app_runs_[runId]_page_actions_0z6r2tz.js.map +0 -1
  454. package/.next/server/chunks/ssr/_next-internal_server_app_runs_page_actions_04_e1xr.js +0 -3
  455. package/.next/server/chunks/ssr/_next-internal_server_app_runs_page_actions_04_e1xr.js.map +0 -1
  456. package/.next/server/chunks/ssr/_next-internal_server_app_settings_page_actions_0mr68ai.js +0 -3
  457. package/.next/server/chunks/ssr/_next-internal_server_app_settings_page_actions_0mr68ai.js.map +0 -1
  458. package/.next/server/chunks/ssr/_next-internal_server_app_settings_permissions_page_actions_0cr.qtc.js +0 -3
  459. package/.next/server/chunks/ssr/_next-internal_server_app_settings_permissions_page_actions_0cr.qtc.js.map +0 -1
  460. package/.next/server/chunks/ssr/_next-internal_server_app_templates_page_actions_0n8gow3.js +0 -3
  461. package/.next/server/chunks/ssr/_next-internal_server_app_templates_page_actions_0n8gow3.js.map +0 -1
  462. package/.next/server/chunks/ssr/node_modules__pnpm_0~j0k.e._.js +0 -33
  463. package/.next/server/chunks/ssr/node_modules__pnpm_0~j0k.e._.js.map +0 -1
  464. package/.next/server/chunks/ssr/src_app_new_page_tsx_0av4n2k._.js +0 -3
  465. package/.next/server/chunks/ssr/src_app_new_page_tsx_0av4n2k._.js.map +0 -1
  466. package/.next/server/chunks/ssr/src_app_onboarding_page_tsx_0xf7hpz._.js +0 -3
  467. package/.next/server/chunks/ssr/src_app_onboarding_page_tsx_0xf7hpz._.js.map +0 -1
  468. package/.next/server/chunks/ssr/src_app_personas_page_tsx_0jx9vyh._.js +0 -3
  469. package/.next/server/chunks/ssr/src_app_personas_page_tsx_0jx9vyh._.js.map +0 -1
  470. package/.next/server/chunks/ssr/src_app_settings_page_tsx_0h9v7dr._.js +0 -27
  471. package/.next/server/chunks/ssr/src_app_settings_page_tsx_0h9v7dr._.js.map +0 -1
  472. package/.next/server/chunks/ssr/src_app_templates_page_tsx_0tml2wg._.js +0 -3
  473. package/.next/server/chunks/ssr/src_app_templates_page_tsx_0tml2wg._.js.map +0 -1
  474. package/.next/server/chunks/ssr/src_components_0j77o23._.js +0 -3
  475. package/.next/server/chunks/ssr/src_components_0j77o23._.js.map +0 -1
  476. package/.next/server/chunks/ssr/src_components_0lc2g58._.js +0 -3
  477. package/.next/server/chunks/ssr/src_components_0lc2g58._.js.map +0 -1
  478. package/.next/server/chunks/ssr/src_components_live-run-real_index_tsx_0zzsdt9._.js +0 -3
  479. package/.next/server/chunks/ssr/src_components_live-run-real_index_tsx_0zzsdt9._.js.map +0 -1
  480. package/.next/static/9cD3yIOGe_Aqr17uJHTQS/_buildManifest.js +0 -11
  481. package/.next/static/9cD3yIOGe_Aqr17uJHTQS/_clientMiddlewareManifest.js +0 -1
  482. package/.next/static/chunks/0-xxtuzaqzyzy.css +0 -3
  483. package/.next/static/chunks/0.dctgbd3j_xg.js +0 -2
  484. package/.next/static/chunks/0.~gqf.-9g-fh.js +0 -1
  485. package/.next/static/chunks/01as9r5n5k.xo.js +0 -1
  486. package/.next/static/chunks/034b~pjm7y20e.js +0 -1
  487. package/.next/static/chunks/05o4oa_9xfaun.js +0 -1
  488. package/.next/static/chunks/08dnw-0gzytmy.js +0 -5
  489. package/.next/static/chunks/08f2b7tuf53ep.js +0 -1
  490. package/.next/static/chunks/0a_u3vdu6tc~f.js +0 -1
  491. package/.next/static/chunks/0am72irwq2bx0.js +0 -5
  492. package/.next/static/chunks/0c-d1bhb8byrx.js +0 -1
  493. package/.next/static/chunks/0s4~w2~is76y1.js +0 -1
  494. package/.next/static/chunks/0ue4qcctkv016.js +0 -4
  495. package/.next/static/chunks/0uok5~eqi6zku.js +0 -1
  496. package/.next/static/chunks/0v3lyuj75aq50.js +0 -1
  497. package/.next/static/chunks/0whnu9t5k-ij7.js +0 -1
  498. package/.next/static/chunks/0x00t3du13-u4.js +0 -25
  499. package/.next/static/chunks/0xs3ktzdh4rw4.js +0 -1
  500. package/.next/static/chunks/0~8r6nhrrl~f9.js +0 -1
  501. package/.next/static/chunks/10jdu00ksgu69.js +0 -1
  502. package/.next/static/chunks/10ld26~0f71ye.js +0 -25
  503. package/.next/static/chunks/11k2wbc04r__f.js +0 -25
  504. package/.next/static/chunks/13-.xgv2t5u6m.js +0 -31
  505. package/.next/static/chunks/152ec.u3_e~ya.js +0 -25
  506. package/.next/static/chunks/172tpttbumwi1.js +0 -25
  507. package/.next/static/chunks/turbopack-0-al833jv3to~.js +0 -1
  508. package/.next/static/media/favicon.0i~66t__91s97.ico +0 -0
  509. package/.next/static/media/icon.15.86wme~cdlv.svg +0 -6
  510. package/.next/turbopack +0 -0
  511. /package/.next/static/chunks/{03~yq9q893hmn.js → polyfills-42372ed130431b0a.js} +0 -0
  512. /package/.next/static/{9cD3yIOGe_Aqr17uJHTQS → fRcji-LCH-qqfsUepgR1t}/_ssgManifest.js +0 -0
  513. /package/.next/static/media/{caa3a2e1cccd8315-s.p.16t1db8_9y2o~.woff2 → 4cf2300e9c8272f7-s.p.woff2} +0 -0
  514. /package/.next/static/media/{bbc41e54d2fcbd21-s.0gw~uztddq1df.woff2 → 747892c23ea88013-s.woff2} +0 -0
  515. /package/.next/static/media/{8a480f0b521d4e75-s.06d3mdzz5bre_.woff2 → 8d697b304b401681-s.woff2} +0 -0
  516. /package/.next/static/media/{797e433ab948586e-s.p.0.q-h669a_dqa.woff2 → 93f479601ee12b01-s.p.woff2} +0 -0
  517. /package/.next/static/media/{4fa387ec64143e14-s.0q3udbd2bu5yp.woff2 → 9610d9e46709d722-s.woff2} +0 -0
  518. /package/.next/static/media/{7178b3e590c64307-s.11.cyxs5p-0z~.woff2 → ba015fad6dcf6784-s.woff2} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/app/onboarding/page.tsx","../../../../src/app/onboarding/api-keys-section.tsx","../../../../src/components/ui/input.tsx","../../../../src/app/onboarding/cli-section.tsx","../../../../src/app/onboarding/helpers.ts","../../../../src/app/onboarding/permissions-section.tsx","../../../../src/app/onboarding/submit.ts"],"sourcesContent":["\"use client\";\n\nimport { ArrowRight, Loader2 } from \"lucide-react\";\nimport { useRouter } from \"next/navigation\";\nimport { useEffect, useState, useTransition } from \"react\";\nimport { TriadLogo } from \"@/components/triad-logo\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n detectInstalledClis,\n saveCliPath,\n validateCliPath,\n type CliDetection,\n type DetectableCliId,\n type SandboxProfile,\n} from \"@/lib/api/settings\";\nimport {\n listOpencodeModels,\n type OpencodeModelsResult,\n} from \"@/lib/api/orchestrators\";\nimport { listVoices, updateVoice, type Voice } from \"@/lib/api/voices\";\nimport { ApiKeysSection } from \"./api-keys-section\";\nimport { CliSection } from \"./cli-section\";\nimport { PermissionsSection } from \"./permissions-section\";\nimport { describeError, submitOnboarding } from \"./submit\";\n\nexport default function OnboardingPage() {\n const router = useRouter();\n const [isPending, startTransition] = useTransition();\n const [error, setError] = useState<string | null>(null);\n\n const [selectedClis, setSelectedClis] = useState<Set<string>>(new Set());\n const [cliVoices, setCliVoices] = useState<Voice[]>([]);\n // Set rather than scalar so concurrent toggles don't fight over the\n // single \"in-flight\" id — mashing 5 toggles used to clear the lock the\n // moment the first request finished, briefly re-enabling the other 4\n // buttons while their requests were still pending.\n const [savingVoiceIds, setSavingVoiceIds] = useState<Set<string>>(new Set());\n const [voiceSaveError, setVoiceSaveError] = useState<string | null>(null);\n const [apiKeys, setApiKeys] = useState<Record<string, string>>({});\n const [sandboxProfile, setSandboxProfile] =\n useState<SandboxProfile>(\"workspace\");\n const [autoApprovePrompts, setAutoApprovePrompts] = useState<boolean>(true);\n const [networkAccess, setNetworkAccess] = useState<boolean>(false);\n const [detection, setDetection] = useState<Record<string, CliDetection>>({});\n // Tracks the initial detect-clis call so the UI can show \"Searching…\"\n // instead of falsely rendering every CLI as \"Not found\" before the\n // probe completes. Flips false on both success + failure paths.\n const [detecting, setDetecting] = useState(true);\n const [manualOpen, setManualOpen] = useState<Set<string>>(new Set());\n const [manualPath, setManualPath] = useState<Record<string, string>>({});\n const [manualError, setManualError] = useState<Record<string, string>>({});\n const [manualBusy, setManualBusy] = useState<Set<string>>(new Set());\n\n // OpenCode model picker: lazily fetched the first time the user ticks\n // OpenCode AND the binary is installed. The user picks which\n // subscription models chorus should expose as voices; persisted in\n // submit.ts.\n const [opencodeModels, setOpencodeModels] = useState<OpencodeModelsResult | null>(\n null,\n );\n const [opencodeModelsError, setOpencodeModelsError] = useState<string | null>(null);\n const [opencodeModelsLoading, setOpencodeModelsLoading] = useState(false);\n const [selectedOpencodeModels, setSelectedOpencodeModels] = useState<Set<string>>(\n new Set(),\n );\n\n useEffect(() => {\n // `cancelled` guards every setter against unmount-during-fetch\n // (StrictMode double-mount + nav-away mid-flight). Without it,\n // React logs warnings + we can land stale data on a dead component.\n let cancelled = false;\n detectInstalledClis()\n .then((rows) => {\n if (cancelled) return;\n const map: Record<string, CliDetection> = {};\n const preTick = new Set<string>();\n for (const row of rows) {\n map[row.id] = row;\n if (row.found) preTick.add(row.id);\n }\n setDetection(map);\n if (preTick.size > 0) setSelectedClis(preTick);\n })\n .catch(() => {\n // Detection is best-effort; if the daemon probe fails the user\n // can still tick boxes manually. No need to surface an error.\n })\n .finally(() => {\n if (!cancelled) setDetecting(false);\n });\n // Voices are seeded server-side on daemon boot — fetch the current\n // state so each CLI card can render its actual model list with\n // toggles, not just \"default model auto-enabled.\"\n listVoices({ source: \"cli\" })\n .then((v) => {\n if (!cancelled) setCliVoices(v);\n })\n .catch(() => {\n /* best-effort — seeding may not have completed yet */\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n const toggleVoice = async (v: Voice) => {\n setSavingVoiceIds((prev) => new Set(prev).add(v.id));\n setVoiceSaveError(null);\n try {\n const next = await updateVoice(v.id, { enabled: !v.enabled });\n setCliVoices((prev) => prev.map((p) => (p.id === next.id ? next : p)));\n } catch (err) {\n setVoiceSaveError(\n err instanceof Error ? err.message : \"Couldn't save voice toggle.\",\n );\n } finally {\n setSavingVoiceIds((prev) => {\n const next = new Set(prev);\n next.delete(v.id);\n return next;\n });\n }\n };\n\n const toggleCli = (id: string) => {\n setSelectedClis((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n };\n\n // Lazy-fetch the OpenCode model list the first time the user ticks\n // OpenCode AND the binary is installed. Runs `opencode models` on the\n // daemon side and groups by gateway prefix.\n useEffect(() => {\n if (!selectedClis.has(\"opencode-cli\")) return;\n if (!detection[\"opencode-cli\"]?.found) return;\n // Skip when we already succeeded, are mid-flight, OR previously\n // errored. Without the error check, finally() flipping loading=false\n // re-runs this effect (loading is in deps), which retries forever.\n if (opencodeModels || opencodeModelsLoading || opencodeModelsError) return;\n setOpencodeModelsLoading(true);\n setOpencodeModelsError(null);\n listOpencodeModels()\n .then((res) => {\n setOpencodeModels(res);\n // Pre-select the fleet defaults (kimi + deepseek when present).\n setSelectedOpencodeModels((prev) => {\n if (prev.size > 0) return prev;\n return new Set(res.defaultPicks);\n });\n })\n .catch((err) => {\n setOpencodeModelsError(\n err instanceof Error\n ? err.message\n : \"Couldn't list OpenCode models. Is the CLI authed (run `opencode auth login`)?\",\n );\n })\n .finally(() => setOpencodeModelsLoading(false));\n }, [\n selectedClis,\n detection,\n opencodeModels,\n opencodeModelsLoading,\n opencodeModelsError,\n ]);\n\n const toggleOpencodeModel = (m: string) => {\n setSelectedOpencodeModels((prev) => {\n const next = new Set(prev);\n if (next.has(m)) next.delete(m);\n else next.add(m);\n return next;\n });\n };\n\n const toggleManual = (id: string) => {\n setManualOpen((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n setManualError((prev) => ({ ...prev, [id]: \"\" }));\n };\n\n const submitManualPath = async (id: DetectableCliId) => {\n const value = (manualPath[id] || \"\").trim();\n if (!value) {\n setManualError((prev) => ({\n ...prev,\n [id]:\n \"Enter the full path to the CLI program (e.g. /usr/local/bin/claude).\",\n }));\n return;\n }\n setManualBusy((prev) => new Set(prev).add(id));\n setManualError((prev) => ({ ...prev, [id]: \"\" }));\n try {\n const result = await validateCliPath(id, value);\n if (result.found) {\n // Persist server-side BEFORE flipping UI state. If the save call\n // fails, surface the error and don't pretend the CLI is wired —\n // pre-fix this whole save step was missing, which is what made\n // the path forgotten across daemon restarts.\n try {\n await saveCliPath(id, result.path ?? value);\n } catch (err) {\n setManualError((prev) => ({\n ...prev,\n [id]: `Validation passed but save failed: ${\n err instanceof Error ? err.message : \"unknown error\"\n }. Try again, or paste the path again.`,\n }));\n return;\n }\n setDetection((prev) => ({ ...prev, [id]: result }));\n setSelectedClis((prev) => new Set(prev).add(id));\n // Refresh voices so the model list populates for the just-validated CLI.\n listVoices({ source: \"cli\" })\n .then(setCliVoices)\n .catch(() => {\n /* best-effort */\n });\n setManualOpen((prev) => {\n const next = new Set(prev);\n next.delete(id);\n return next;\n });\n } else {\n // Daemon now returns `reason` on validation failures — surface it.\n // Falls back to the generic message for older daemons.\n const reason = result.reason ?? \"couldn't run that path\";\n setManualError((prev) => ({\n ...prev,\n [id]: `Validation failed: ${reason}.`,\n }));\n }\n } catch {\n setManualError((prev) => ({\n ...prev,\n [id]: \"Validation failed. Is the daemon running?\",\n }));\n } finally {\n setManualBusy((prev) => {\n const next = new Set(prev);\n next.delete(id);\n return next;\n });\n }\n };\n\n const updateApiKey = (provider: string, value: string) => {\n setApiKeys((prev) => ({ ...prev, [provider]: value }));\n };\n\n const filledCount =\n selectedClis.size +\n Object.values(apiKeys).filter((v) => v.trim().length > 0).length;\n\n const handleSubmit = () => {\n setError(null);\n if (filledCount === 0) {\n setError(\"Pick at least one CLI or paste at least one API key to continue.\");\n return;\n }\n startTransition(async () => {\n try {\n await submitOnboarding({\n selectedClis,\n apiKeys,\n sandboxProfile,\n autoApprovePrompts,\n networkAccess,\n opencodeModels,\n selectedOpencodeModels,\n });\n router.push(\"/\");\n router.refresh();\n } catch (err) {\n setError(describeError(err));\n }\n });\n };\n\n return (\n <main className=\"min-h-screen bg-background text-foreground\">\n <div className=\"mx-auto w-full max-w-5xl px-4 py-10 sm:px-6 sm:py-14\">\n <div className=\"mb-8 flex items-center gap-3\">\n <div className=\"grid h-10 w-10 place-items-center rounded-md bg-primary/15 text-primary\">\n <TriadLogo className=\"h-6 w-6\" />\n </div>\n <div>\n <p className=\"text-xs uppercase tracking-wider text-muted-foreground\">\n Welcome to Chorus\n </p>\n <h1 className=\"text-2xl font-semibold tracking-tight\">\n Connect at least one model to begin\n </h1>\n </div>\n </div>\n\n <p className=\"mb-8 text-sm leading-relaxed text-muted-foreground\">\n Chorus runs your prompt past 2–4 LLMs of different lineages and\n synthesises consensus. Pick the CLI subscriptions you already have,\n or paste API keys. You can change these later in Settings.\n </p>\n\n <CliSection\n selectedClis={selectedClis}\n toggleCli={toggleCli}\n detection={detection}\n detecting={detecting}\n cliVoices={cliVoices}\n savingVoiceIds={savingVoiceIds}\n voiceSaveError={voiceSaveError}\n toggleVoice={toggleVoice}\n manualOpen={manualOpen}\n toggleManual={toggleManual}\n manualPath={manualPath}\n setManualPath={setManualPath}\n manualError={manualError}\n manualBusy={manualBusy}\n submitManualPath={submitManualPath}\n opencodeModels={opencodeModels}\n opencodeModelsError={opencodeModelsError}\n opencodeModelsLoading={opencodeModelsLoading}\n selectedOpencodeModels={selectedOpencodeModels}\n toggleOpencodeModel={toggleOpencodeModel}\n />\n\n <ApiKeysSection apiKeys={apiKeys} updateApiKey={updateApiKey} />\n\n <PermissionsSection\n sandboxProfile={sandboxProfile}\n setSandboxProfile={setSandboxProfile}\n autoApprovePrompts={autoApprovePrompts}\n setAutoApprovePrompts={setAutoApprovePrompts}\n networkAccess={networkAccess}\n setNetworkAccess={setNetworkAccess}\n />\n\n {error && (\n <div className=\"mb-6 rounded-md border border-destructive/50 bg-destructive/10 px-4 py-3 text-sm text-destructive\">\n {error}\n </div>\n )}\n\n <div className=\"flex flex-col-reverse gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <p className=\"text-xs text-muted-foreground\">\n {filledCount === 0\n ? \"Pick at least one to continue.\"\n : `${filledCount} ${filledCount === 1 ? \"credential\" : \"credentials\"} ready to save.`}\n </p>\n <Button\n onClick={handleSubmit}\n disabled={isPending || filledCount === 0}\n className=\"w-full sm:w-auto\"\n >\n {isPending ? (\n <>\n <Loader2 className=\"mr-1 h-4 w-4 animate-spin\" />\n Saving…\n </>\n ) : (\n <>\n Get started\n <ArrowRight className=\"ml-1 h-4 w-4\" />\n </>\n )}\n </Button>\n </div>\n </div>\n </main>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { Card } from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n AlertTriangle,\n Check,\n ExternalLink,\n Loader2,\n} from \"lucide-react\";\nimport {\n addOpenRouterVoices,\n listOpenRouterModels,\n saveOpenRouterKey,\n type OpenRouterModel,\n} from \"@/lib/api/openrouter\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * API-key entry during onboarding. v0.7 ships only the OpenRouter slot —\n * other providers' direct API paths aren't wired yet, so showing their\n * inputs would persist a key that does nothing.\n *\n * Flow when the user saves an OpenRouter key:\n * 1. POST /openrouter/save-key — daemon validates against the\n * catalog endpoint, returns { valid, error? }.\n * 2. On valid → fetch the catalog (GET /openrouter/models) and reveal\n * a small picker so the user can add a couple of voices before\n * finishing onboarding. Saves a second-trip to /connect just to\n * enable a model.\n * 3. On invalid → inline error, key is NOT persisted.\n */\n\n// Curated starter set — surfaced first in the picker so a user who\n// just wants \"any 2 voices to try chorus\" doesn't have to scroll.\n// Prefixed `openrouter:` form is what voices.id stores; the picker\n// reconciles against the bare model_id.\nconst STARTER_PICKS = [\n \"anthropic/claude-sonnet-4.5\",\n \"openai/gpt-5\",\n \"google/gemini-2.5-pro\",\n \"deepseek/deepseek-chat-v3.1\",\n \"moonshotai/kimi-k2\",\n];\n\ntype SaveState =\n | { kind: \"idle\" }\n | { kind: \"saving\" }\n | { kind: \"invalid\"; message: string }\n // Key validated + persisted, but the catalog fetch failed. User can\n // retry just the catalog without re-saving the key (which would be a\n // wasted round-trip).\n | { kind: \"catalog_failed\"; message: string }\n | { kind: \"loading_catalog\" }\n | { kind: \"valid\"; modelCount: number };\n\ninterface ApiKeysSectionProps {\n apiKeys: Record<string, string>;\n updateApiKey: (provider: string, value: string) => void;\n}\n\nexport function ApiKeysSection({ apiKeys, updateApiKey }: ApiKeysSectionProps) {\n const apiKey = apiKeys[\"openrouter\"] ?? \"\";\n const [saveState, setSaveState] = useState<SaveState>({ kind: \"idle\" });\n const [catalog, setCatalog] = useState<OpenRouterModel[] | null>(null);\n const [picked, setPicked] = useState<Set<string>>(new Set(STARTER_PICKS));\n const [adding, setAdding] = useState(false);\n const [addedMsg, setAddedMsg] = useState<string | null>(null);\n\n async function onSaveKey() {\n if (apiKey.trim().length === 0 || saveState.kind === \"saving\") return;\n setSaveState({ kind: \"saving\" });\n try {\n const v = await saveOpenRouterKey(apiKey.trim());\n if (!v.valid) {\n setSaveState({\n kind: \"invalid\",\n message: v.error ?? \"OpenRouter rejected this key.\",\n });\n return;\n }\n // Key is now persisted server-side. From this point a catalog\n // failure transitions to `catalog_failed` (recoverable via the\n // Reload button), not back to `invalid` (which would imply the\n // key itself was bad).\n await loadCatalog();\n } catch (err) {\n setSaveState({\n kind: \"invalid\",\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n async function loadCatalog() {\n setSaveState({ kind: \"loading_catalog\" });\n try {\n const { models } = await listOpenRouterModels();\n models.sort((a, b) => a.id.localeCompare(b.id));\n setCatalog(models);\n setSaveState({ kind: \"valid\", modelCount: models.length });\n } catch (err) {\n setSaveState({\n kind: \"catalog_failed\",\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n async function onAddVoices() {\n if (picked.size === 0 || adding) return;\n setAdding(true);\n setAddedMsg(null);\n try {\n const r = await addOpenRouterVoices(Array.from(picked));\n const added = r.added.length;\n const skipped = r.skipped.length;\n setAddedMsg(\n `Added ${added} voice${added === 1 ? \"\" : \"s\"}` +\n (skipped > 0 ? ` · skipped ${skipped} (unknown id)` : \"\"),\n );\n } catch (err) {\n setAddedMsg(\n `Couldn't add voices: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n setAdding(false);\n }\n }\n\n return (\n <section className=\"mb-8\">\n <h2 className=\"mb-3 flex flex-wrap items-baseline gap-x-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n <span>API access</span>\n <span className=\"font-normal normal-case text-muted-foreground/70\">\n optional — gives you any model on OpenRouter as a chorus voice\n </span>\n </h2>\n <Card className=\"space-y-3 bg-card p-4\">\n <div className=\"flex items-center justify-between\">\n <label\n htmlFor=\"apikey-openrouter\"\n className=\"text-sm font-medium\"\n >\n OpenRouter API key\n </label>\n <a\n href=\"https://openrouter.ai/keys\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground\"\n >\n Get a key <ExternalLink className=\"h-2.5 w-2.5\" />\n </a>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Input\n id=\"apikey-openrouter\"\n type=\"password\"\n autoComplete=\"off\"\n spellCheck={false}\n placeholder=\"sk-or-v1-…\"\n value={apiKey}\n onChange={(e) => {\n updateApiKey(\"openrouter\", e.target.value);\n if (saveState.kind !== \"idle\") setSaveState({ kind: \"idle\" });\n setCatalog(null);\n }}\n className=\"flex-1 font-mono text-xs\"\n disabled={\n saveState.kind === \"saving\" || saveState.kind === \"loading_catalog\"\n }\n />\n <button\n type=\"button\"\n onClick={onSaveKey}\n disabled={\n apiKey.trim().length === 0 ||\n saveState.kind === \"saving\" ||\n saveState.kind === \"loading_catalog\" ||\n saveState.kind === \"valid\"\n }\n className={cn(\n \"inline-flex h-9 items-center gap-1.5 rounded-md border px-3 text-[11px] font-medium transition disabled:cursor-not-allowed disabled:opacity-50\",\n saveState.kind === \"valid\"\n ? \"border-emerald-500/40 bg-emerald-500/10 text-emerald-300\"\n : \"border-primary/40 bg-primary/10 text-primary hover:bg-primary/20\",\n )}\n >\n {(saveState.kind === \"saving\" ||\n saveState.kind === \"loading_catalog\") && (\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n )}\n {saveState.kind === \"valid\" && <Check className=\"h-3 w-3\" />}\n {saveState.kind === \"saving\"\n ? \"Validating…\"\n : saveState.kind === \"loading_catalog\"\n ? \"Loading models…\"\n : saveState.kind === \"valid\"\n ? \"Validated\"\n : \"Validate & save\"}\n </button>\n </div>\n\n {saveState.kind === \"invalid\" && (\n <p className=\"flex items-center gap-1.5 text-xs text-destructive\">\n <AlertTriangle className=\"h-3 w-3\" />\n {saveState.message}\n </p>\n )}\n\n {saveState.kind === \"catalog_failed\" && (\n <div className=\"flex items-start justify-between gap-3 rounded-md border border-amber-500/40 bg-amber-500/5 px-3 py-2\">\n <p className=\"flex items-start gap-1.5 text-xs text-amber-100\">\n <AlertTriangle className=\"mt-0.5 h-3 w-3 shrink-0\" />\n <span>\n Key saved, but couldn&apos;t load the model catalog:{\" \"}\n {saveState.message}\n </span>\n </p>\n <button\n type=\"button\"\n onClick={loadCatalog}\n className=\"shrink-0 rounded-md border border-amber-500/40 bg-amber-500/10 px-2.5 py-1 text-[11px] font-medium text-amber-100 hover:bg-amber-500/20\"\n >\n Reload models\n </button>\n </div>\n )}\n\n {saveState.kind === \"valid\" && catalog && (\n <div className=\"space-y-2 rounded-md border border-emerald-500/20 bg-emerald-500/5 p-3\">\n <p className=\"text-[11px] text-emerald-300\">\n ✓ Key valid · {saveState.modelCount} models available. Pick a\n starter set now or browse the full catalog on the Connect page\n later.\n </p>\n <div className=\"grid grid-cols-1 gap-1 sm:grid-cols-2\">\n {STARTER_PICKS.filter((id) => catalog.some((m) => m.id === id)).map(\n (id) => {\n const sel = picked.has(id);\n const m = catalog.find((c) => c.id === id);\n return (\n <label\n key={id}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded border px-2 py-1.5 text-[11px] transition\",\n sel\n ? \"border-primary/50 bg-primary/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:border-muted-foreground/30\",\n )}\n >\n <input\n type=\"checkbox\"\n checked={sel}\n onChange={(e) => {\n setPicked((prev) => {\n const next = new Set(prev);\n if (e.target.checked) next.add(id);\n else next.delete(id);\n return next;\n });\n }}\n className=\"h-3 w-3 shrink-0\"\n />\n <span className=\"truncate font-mono\">{m?.id ?? id}</span>\n </label>\n );\n },\n )}\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={onAddVoices}\n disabled={picked.size === 0 || adding}\n className=\"inline-flex h-7 items-center gap-1.5 rounded-md border border-primary/40 bg-primary/10 px-2.5 text-[11px] font-medium text-primary transition hover:bg-primary/20 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {adding ? <Loader2 className=\"h-3 w-3 animate-spin\" /> : null}\n Add {picked.size > 0 ? picked.size : \"\"} voice\n {picked.size === 1 ? \"\" : \"s\"}\n </button>\n {addedMsg && (\n <p className=\"text-[11px] text-emerald-300\">{addedMsg}</p>\n )}\n </div>\n </div>\n )}\n\n <p className=\"text-[11px] leading-relaxed text-muted-foreground/80\">\n Stored locally in <code>~/.chorus/chorus.db</code>. Used only to\n call OpenRouter on your behalf. Direct API support for other\n providers (Anthropic, OpenAI, Google, xAI) is on the roadmap —\n today, route those models via OpenRouter.\n </p>\n </Card>\n </section>\n );\n}\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30\",\n \"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n \"aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","\"use client\";\n\nimport { Check, Loader2 } from \"lucide-react\";\nimport type { Dispatch, SetStateAction } from \"react\";\nimport type {\n CliDetection,\n DetectableCliId,\n} from \"@/lib/api/settings\";\nimport type { OpencodeModelsResult } from \"@/lib/api/orchestrators\";\nimport type { Voice } from \"@/lib/api/voices\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { UI_LINEAGE_BRAND, type UILineage } from \"@/lib/lineage-maps\";\nimport { cn } from \"@/lib/utils\";\nimport { CLIS, manualBinaryName } from \"./helpers\";\n\n/**\n * CLI subscription cards on the onboarding page. Mirrors /connect's\n * gradient-card aesthetic so the two pages feel like the same product.\n *\n * Layout rules:\n * - 2-column grid on lg+; single column below.\n * - Each card is a fixed h-72 slot — keeps row alignment when one\n * card has a model picker and another doesn't.\n * - Only the 5 CLI subscriptions show here. Cursor + Windsurf are\n * IDEs (no voices) and live on /connect.\n * - Detected CLIs render in their lineage's brand colour, expanded\n * with model picker inline. Not-detected CLIs render in muted grey\n * with the \"Set path manually\" link only.\n */\n\nconst CLI_TO_UI_LINEAGE: Record<string, UILineage> = {\n \"claude-code\": \"claude\",\n \"codex-cli\": \"codex\",\n \"gemini-cli\": \"gemini\",\n \"opencode-cli\": \"opencode\",\n \"kimi-cli\": \"kimi\",\n};\n\n// `voices.provider` mirrors the CLI id 1:1 for the single-model CLIs.\n// Kept as a Record for symmetry with CLI_TO_UI_LINEAGE.\nconst CLI_TO_PROVIDER: Record<string, string> = {\n \"claude-code\": \"claude-code\",\n \"codex-cli\": \"codex-cli\",\n \"gemini-cli\": \"gemini-cli\",\n \"opencode-cli\": \"opencode-cli\",\n \"kimi-cli\": \"kimi-cli\",\n};\n\nconst NEUTRAL_BRAND = {\n dot: \"bg-muted-foreground/40\",\n gradient: \"bg-gradient-to-br from-muted/30 via-card to-card\",\n} as const;\n\ninterface CliSectionProps {\n selectedClis: Set<string>;\n toggleCli: (id: string) => void;\n detection: Record<string, CliDetection>;\n /** True while the initial detect-clis probe is in flight. Cards\n * render in a \"searching…\" placeholder state — without this every\n * CLI looks \"not found\" for ~200-500ms on first paint. */\n detecting: boolean;\n /** All CLI-source voices, fetched on the page. The card filters by\n * provider locally so its model list reflects the live DB state. */\n cliVoices: Voice[];\n savingVoiceIds: Set<string>;\n voiceSaveError: string | null;\n toggleVoice: (v: Voice) => void;\n manualOpen: Set<string>;\n toggleManual: (id: string) => void;\n manualPath: Record<string, string>;\n setManualPath: Dispatch<SetStateAction<Record<string, string>>>;\n manualError: Record<string, string>;\n manualBusy: Set<string>;\n submitManualPath: (id: DetectableCliId) => void;\n\n opencodeModels: OpencodeModelsResult | null;\n opencodeModelsError: string | null;\n opencodeModelsLoading: boolean;\n selectedOpencodeModels: Set<string>;\n toggleOpencodeModel: (m: string) => void;\n}\n\n// Onboarding only lists actual CLI subscriptions. IDEs (Cursor/Windsurf)\n// belong on /connect — they invoke chorus but don't act as voices.\nconst ONBOARDING_CLIS = CLIS.filter(\n (c) => c.id !== \"cursor\" && c.id !== \"windsurf\",\n);\n\nexport function CliSection(props: CliSectionProps) {\n return (\n <section className=\"mb-8\">\n <h2 className=\"mb-3 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n CLI subscriptions\n </h2>\n <div className=\"grid grid-cols-1 items-start gap-2 lg:grid-cols-2\">\n {ONBOARDING_CLIS.map((cli) => {\n const checked = props.selectedClis.has(cli.id);\n const probe = props.detection[cli.id];\n const found = probe?.found === true;\n // While the initial probe is in flight we don't yet know if\n // this CLI is installed — render a neutral \"searching\" state\n // instead of falsely declaring \"Not found\".\n const searching = props.detecting && !probe;\n const showManual = !found && !searching && props.manualOpen.has(cli.id);\n const isBusy = props.manualBusy.has(cli.id);\n const brand = found\n ? (UI_LINEAGE_BRAND[CLI_TO_UI_LINEAGE[cli.id]] ?? NEUTRAL_BRAND)\n : NEUTRAL_BRAND;\n\n return (\n <div\n key={cli.id}\n className={cn(\n \"flex h-72 flex-col rounded-lg border transition\",\n found\n ? \"border-border\"\n : \"border-border/60 opacity-70\",\n brand.gradient,\n )}\n >\n {/* Header — checkbox + label + status badge */}\n <button\n type=\"button\"\n onClick={() => found && props.toggleCli(cli.id)}\n disabled={!found}\n className={cn(\n \"flex shrink-0 items-center gap-3 px-4 py-3 text-left transition\",\n found\n ? \"hover:bg-card/30\"\n : \"cursor-not-allowed\",\n )}\n >\n <div\n className={cn(\n \"grid h-5 w-5 shrink-0 place-items-center rounded border transition\",\n !found && \"opacity-50\",\n checked\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border\",\n )}\n >\n {checked && <Check className=\"h-3 w-3\" />}\n </div>\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n <span\n className={cn(\"h-2 w-2 shrink-0 rounded-full\", brand.dot)}\n />\n <h3 className=\"whitespace-nowrap text-sm font-semibold\">\n {cli.label}\n </h3>\n {found ? (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-emerald-500/10 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider text-emerald-300\">\n <Check className=\"h-3 w-3\" /> Installed\n </span>\n ) : searching ? (\n <span className=\"inline-flex items-center gap-1 rounded-full border border-border bg-card px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n <Loader2 className=\"h-3 w-3 animate-spin\" /> Searching…\n </span>\n ) : (\n <span className=\"inline-flex items-center rounded-full border border-border bg-card px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n Not found\n </span>\n )}\n </div>\n </button>\n\n {/* Body — fills the rest of the card */}\n <div className=\"flex flex-1 flex-col gap-2 overflow-y-auto border-t border-border bg-card/30 p-4\">\n <p className=\"text-[11px] leading-relaxed text-muted-foreground\">\n {found && probe.path ? (\n <code className=\"rounded bg-muted/60 px-1.5 py-0.5 font-mono\">\n {probe.path}\n </code>\n ) : searching ? (\n <span className=\"inline-flex items-center gap-1.5 text-muted-foreground\">\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n Probing PATH and known install dirs…\n </span>\n ) : (\n cli.hint\n )}\n </p>\n\n {!found && !searching && (\n <div className=\"space-y-2\">\n <button\n type=\"button\"\n onClick={() => props.toggleManual(cli.id)}\n className=\"text-[11px] text-muted-foreground transition hover:text-foreground\"\n >\n {showManual\n ? \"Cancel\"\n : \"Don't see it? Set path manually →\"}\n </button>\n {showManual && (\n <ManualPath\n cliId={cli.id}\n value={props.manualPath[cli.id] ?? \"\"}\n onChange={(v) =>\n props.setManualPath((prev) => ({\n ...prev,\n [cli.id]: v,\n }))\n }\n error={props.manualError[cli.id]}\n busy={isBusy}\n onSubmit={() =>\n props.submitManualPath(cli.id as DetectableCliId)\n }\n />\n )}\n </div>\n )}\n\n {found && cli.id === \"opencode-cli\" && checked && (\n <OpencodeInline\n loading={props.opencodeModelsLoading}\n error={props.opencodeModelsError}\n models={props.opencodeModels}\n selected={props.selectedOpencodeModels}\n onToggle={props.toggleOpencodeModel}\n />\n )}\n\n {found && cli.id !== \"opencode-cli\" && checked && (\n <SingleCliVoiceList\n cliId={cli.id}\n voices={props.cliVoices}\n savingVoiceIds={props.savingVoiceIds}\n saveError={props.voiceSaveError}\n onToggle={props.toggleVoice}\n />\n )}\n </div>\n </div>\n );\n })}\n </div>\n <p className=\"mt-3 text-[11px] text-muted-foreground\">\n Cursor and Windsurf are IDEs that invoke chorus, not voices —\n wire them up on the Connect page after onboarding.\n </p>\n </section>\n );\n}\n\n/**\n * Model toggle list for single-model CLIs (claude/codex/gemini/kimi).\n * Mirrors the OpenCode picker shape so all five cards feel consistent.\n * Each row is a real voices.upsert toggle — clicking saves immediately.\n */\ninterface SingleCliVoiceListProps {\n cliId: string;\n voices: Voice[];\n /** Set of voice ids currently mid-save. Concurrent toggles each\n * push their id in and remove it on settle, so two in-flight saves\n * keep both buttons disabled until each one finishes — earlier\n * scalar version cleared the lock on the first settle, leaking\n * enabled state to the still-pending button. */\n savingVoiceIds: Set<string>;\n saveError: string | null;\n onToggle: (v: Voice) => void;\n}\n\nfunction SingleCliVoiceList({\n cliId,\n voices,\n savingVoiceIds,\n saveError,\n onToggle,\n}: SingleCliVoiceListProps) {\n const provider = CLI_TO_PROVIDER[cliId];\n // Filter to this CLI's voices and stable-sort: immutable provider row\n // first (current model), versioned variants alphabetically after.\n const ours = voices\n .filter((v) => v.provider === provider)\n .slice()\n .sort((a, b) => {\n if (a.id === provider) return -1;\n if (b.id === provider) return 1;\n return a.model_id.localeCompare(b.model_id);\n });\n\n if (ours.length === 0) {\n return (\n <p className=\"text-[11px] italic text-muted-foreground/70\">\n Models will populate after the daemon finishes seeding (refresh\n in a few seconds).\n </p>\n );\n }\n\n const enabledCount = ours.filter((v) => v.enabled).length;\n\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <p className=\"text-[11px] font-medium uppercase tracking-wider text-muted-foreground\">\n Models\n </p>\n <p className=\"text-[11px] text-muted-foreground/70\">\n {enabledCount}/{ours.length} enabled\n </p>\n </div>\n {saveError && (\n <p className=\"text-[11px] text-destructive\">{saveError}</p>\n )}\n <div className=\"grid grid-cols-1 gap-1\">\n {ours.map((v) => {\n const sel = v.enabled;\n const isCurrent = v.id === provider;\n return (\n <button\n key={v.id}\n type=\"button\"\n disabled={savingVoiceIds.has(v.id)}\n onClick={() => onToggle(v)}\n title={v.model_id}\n className={cn(\n \"flex items-center gap-2 rounded border px-2 py-1.5 text-left text-[11px] transition disabled:opacity-60\",\n sel\n ? \"border-primary/50 bg-primary/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:border-muted-foreground/30\",\n )}\n >\n <div\n className={cn(\n \"grid h-3 w-3 shrink-0 place-items-center rounded-sm border transition\",\n sel\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border\",\n )}\n >\n {sel && <Check className=\"h-2 w-2\" />}\n </div>\n <span className=\"truncate font-mono\">{v.model_id}</span>\n {isCurrent && (\n <span className=\"shrink-0 rounded-full bg-emerald-500/10 px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider text-emerald-300\">\n current\n </span>\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n\n/**\n * Inline OpenCode model picker. Lives inside the card body (no extra\n * outer container) so widths align with the parent card.\n */\ninterface OpencodeInlineProps {\n loading: boolean;\n error: string | null;\n models: OpencodeModelsResult | null;\n selected: Set<string>;\n onToggle: (m: string) => void;\n}\n\nfunction OpencodeInline({\n loading,\n error,\n models,\n selected,\n onToggle,\n}: OpencodeInlineProps) {\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <p className=\"text-[11px] font-medium uppercase tracking-wider text-muted-foreground\">\n Pick models to enable\n </p>\n <p className=\"text-[11px] text-muted-foreground/70\">\n {selected.size} selected\n </p>\n </div>\n\n {loading && (\n <p className=\"flex items-center gap-2 text-[11px] text-muted-foreground\">\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n Listing models from{\" \"}\n <code className=\"rounded bg-muted px-1\">opencode models</code>…\n </p>\n )}\n\n {error && <p className=\"text-[11px] text-destructive\">{error}</p>}\n\n {models && (\n <div className=\"space-y-2\">\n {Object.entries(models.gateways)\n .filter(([gw]) => gw.startsWith(\"opencode\"))\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([gateway, list]) => (\n <div key={gateway} className=\"space-y-1\">\n <p className=\"text-[10px] font-mono text-muted-foreground/80\">\n {gateway}/\n </p>\n <div className=\"grid grid-cols-1 gap-1\">\n {list.map((m) => {\n const sel = selected.has(m);\n return (\n <button\n key={m}\n type=\"button\"\n onClick={() => onToggle(m)}\n title={m}\n className={cn(\n \"flex items-center gap-2 rounded border px-2 py-1.5 text-left text-[11px] transition\",\n sel\n ? \"border-primary/50 bg-primary/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:border-muted-foreground/30\",\n )}\n >\n <div\n className={cn(\n \"grid h-3 w-3 shrink-0 place-items-center rounded-sm border transition\",\n sel\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border\",\n )}\n >\n {sel && <Check className=\"h-2 w-2\" />}\n </div>\n <span className=\"truncate font-mono\">\n {m.slice(gateway.length + 1)}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n ))}\n <p className=\"text-[11px] leading-relaxed text-muted-foreground/70\">\n Pre-selected: {models.defaultPicks.join(\", \") || \"none\"}. Change\n anytime in <code className=\"rounded bg-muted px-1\">Settings</code>.\n </p>\n </div>\n )}\n </div>\n );\n}\n\nfunction ManualPath({\n cliId,\n value,\n onChange,\n error,\n busy,\n onSubmit,\n}: {\n cliId: string;\n value: string;\n onChange: (v: string) => void;\n error: string | undefined;\n busy: boolean;\n onSubmit: () => void;\n}) {\n const bin = manualBinaryName(cliId);\n return (\n <div className=\"space-y-2 rounded-md border border-border bg-card/50 p-3\">\n <p className=\"text-[11px] leading-relaxed text-muted-foreground\">\n Paste the full path to the{\" \"}\n <code className=\"rounded bg-muted px-1\">{bin}</code> binary. Run{\" \"}\n <code className=\"rounded bg-muted px-1\">which {bin}</code> (macOS /\n Linux) or <code className=\"rounded bg-muted px-1\">where {bin}</code>{\" \"}\n (Windows) to find it. The daemon will run{\" \"}\n <code className=\"rounded bg-muted px-1\">{bin} --version</code> with\n a 2s timeout to confirm the binary works and identifies as the{\" \"}\n {bin} CLI.\n </p>\n <div className=\"flex gap-2\">\n <Input\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={`/full/path/to/${bin}`}\n className=\"flex-1 font-mono text-xs\"\n spellCheck={false}\n autoComplete=\"off\"\n />\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={busy}\n onClick={onSubmit}\n >\n {busy ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : \"Verify\"}\n </Button>\n </div>\n {error && <p className=\"text-[11px] text-destructive\">{error}</p>}\n </div>\n );\n}\n","export interface CliRow {\n id: string;\n provider: string;\n label: string;\n hint: string;\n}\n\nexport interface ApiKeyRow {\n provider: string;\n label: string;\n placeholder: string;\n}\n\nexport const CLIS: CliRow[] = [\n {\n id: \"claude-code\",\n provider: \"anthropic\",\n label: \"Claude Code\",\n hint: \"Anthropic — uses your existing Claude login\",\n },\n {\n id: \"codex-cli\",\n provider: \"openai\",\n label: \"Codex CLI\",\n hint: \"OpenAI — ChatGPT Plus/Pro subscription\",\n },\n {\n id: \"gemini-cli\",\n provider: \"google\",\n label: \"Gemini CLI\",\n hint: \"Google — uses your gcloud auth\",\n },\n {\n id: \"opencode-cli\",\n provider: \"opencode\",\n label: \"OpenCode\",\n hint: \"OpenCode Go — routes Kimi, DeepSeek, Grok\",\n },\n {\n id: \"kimi-cli\",\n provider: \"moonshot\",\n label: \"Kimi CLI\",\n hint: \"MoonshotAI — kimi-k2 plan\",\n },\n {\n id: \"cursor\",\n provider: \"cursor\",\n label: \"Cursor\",\n hint: \"Cursor IDE — invoke chorus from inside it\",\n },\n {\n id: \"windsurf\",\n provider: \"windsurf\",\n label: \"Windsurf\",\n hint: \"Windsurf IDE — invoke chorus from inside it\",\n },\n];\n\nexport const API_KEYS: ApiKeyRow[] = [\n { provider: \"openrouter\", label: \"OpenRouter\", placeholder: \"sk-or-v1-...\" },\n];\n\n/** Best-effort lineage classifier — mirrors the daemon's\n * classifyOpencodeModel logic without importing it client-side. For\n * uncovered models the lineage falls back to \"opencode\". */\nexport function classifyOpencodeClient(qualified: string): {\n lineage: \"anthropic\" | \"openai\" | \"google\" | \"opencode\" | \"moonshot\";\n vendor_family: string | null;\n} {\n const slash = qualified.indexOf(\"/\");\n const tail = (slash >= 0 ? qualified.slice(slash + 1) : qualified).toLowerCase();\n if (tail.includes(\"kimi\")) return { lineage: \"moonshot\", vendor_family: null };\n if (tail.includes(\"claude\")) return { lineage: \"anthropic\", vendor_family: null };\n if (tail.includes(\"gpt\") || /(?:^|[^a-z])o[1-9](?:$|[^a-z0-9])/.test(tail))\n return { lineage: \"openai\", vendor_family: null };\n if (tail.includes(\"gemini\")) return { lineage: \"google\", vendor_family: null };\n if (tail.includes(\"deepseek\")) return { lineage: \"opencode\", vendor_family: \"deepseek\" };\n if (tail.includes(\"llama\") || tail.includes(\"meta\"))\n return { lineage: \"opencode\", vendor_family: \"meta\" };\n if (tail.includes(\"mistral\") || tail.includes(\"mixtral\"))\n return { lineage: \"opencode\", vendor_family: \"mistral\" };\n if (tail.includes(\"grok\") || tail.includes(\"xai\"))\n return { lineage: \"opencode\", vendor_family: \"xai\" };\n return { lineage: \"opencode\", vendor_family: null };\n}\n\nexport function manualBinaryName(cliId: string): string {\n switch (cliId) {\n case \"claude-code\":\n return \"claude\";\n case \"codex-cli\":\n return \"codex\";\n case \"gemini-cli\":\n return \"gemini\";\n case \"opencode-cli\":\n return \"opencode\";\n default:\n return \"kimi\";\n }\n}\n","\"use client\";\n\nimport { Check } from \"lucide-react\";\nimport type { SandboxProfile } from \"@/lib/api/settings\";\nimport { cn } from \"@/lib/utils\";\n\nconst PROFILES = [\n {\n id: \"strict\",\n label: \"Strict\",\n hint: \"Read-only. Reviewers can inspect code but can't write files, exec shell, or hit the network.\",\n },\n {\n id: \"workspace\",\n label: \"Workspace (recommended)\",\n hint: \"Read+write inside the chat dir, scoped shell, no network. Default for most teams.\",\n },\n {\n id: \"full\",\n label: \"Full access\",\n hint: \"No sandbox at all. Only on a personal machine you fully trust.\",\n },\n] as const;\n\ninterface PermissionsSectionProps {\n sandboxProfile: SandboxProfile;\n setSandboxProfile: (p: SandboxProfile) => void;\n autoApprovePrompts: boolean;\n setAutoApprovePrompts: (v: boolean) => void;\n networkAccess: boolean;\n setNetworkAccess: (v: boolean) => void;\n}\n\nexport function PermissionsSection({\n sandboxProfile,\n setSandboxProfile,\n autoApprovePrompts,\n setAutoApprovePrompts,\n networkAccess,\n setNetworkAccess,\n}: PermissionsSectionProps) {\n return (\n <section className=\"mb-8\">\n <h2 className=\"mb-3 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n Permissions &amp; sandbox\n </h2>\n <p className=\"mb-4 text-xs leading-relaxed text-muted-foreground\">\n Controls what reviewers can do on your machine. You can change this\n anytime in Settings &rarr; Permissions.\n </p>\n\n <div className=\"space-y-2\">\n {PROFILES.map((p) => {\n const checked = sandboxProfile === p.id;\n return (\n <button\n key={p.id}\n type=\"button\"\n onClick={() => setSandboxProfile(p.id)}\n className={cn(\n \"flex w-full items-start gap-3 rounded-lg border p-4 text-left transition\",\n checked\n ? \"border-primary/50 bg-primary/10\"\n : \"border-border bg-card hover:border-muted-foreground/30\",\n )}\n >\n <div\n className={cn(\n \"mt-0.5 grid h-5 w-5 shrink-0 place-items-center rounded-full border transition\",\n checked\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border\",\n )}\n >\n {checked && <Check className=\"h-3 w-3\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-medium\">{p.label}</div>\n <div className=\"mt-1 text-xs leading-relaxed text-muted-foreground\">\n {p.hint}\n </div>\n </div>\n </button>\n );\n })}\n </div>\n\n <div className=\"mt-3 space-y-2\">\n <label className=\"flex cursor-pointer items-start gap-3 rounded-lg border border-border bg-card p-3\">\n <input\n type=\"checkbox\"\n checked={autoApprovePrompts}\n onChange={(e) => setAutoApprovePrompts(e.target.checked)}\n className=\"mt-1 h-4 w-4 cursor-pointer accent-primary\"\n />\n <div className=\"min-w-0 flex-1 text-xs leading-relaxed\">\n <div className=\"text-sm font-medium\">\n Skip in-CLI permission prompts\n </div>\n <div className=\"mt-0.5 text-muted-foreground\">\n Passes <code className=\"rounded bg-muted px-1\">--afk</code> /{\" \"}\n <code className=\"rounded bg-muted px-1\">auto_edit</code> to\n spawned reviewers so they don&apos;t hang on per-tool prompts. Off\n = every action requires explicit consent in the CLI&apos;s TUI.\n </div>\n </div>\n </label>\n\n <label className=\"flex cursor-pointer items-start gap-3 rounded-lg border border-border bg-card p-3\">\n <input\n type=\"checkbox\"\n checked={networkAccess}\n onChange={(e) => setNetworkAccess(e.target.checked)}\n className=\"mt-1 h-4 w-4 cursor-pointer accent-primary\"\n />\n <div className=\"min-w-0 flex-1 text-xs leading-relaxed\">\n <div className=\"text-sm font-medium\">\n Allow outbound network from reviewers\n </div>\n <div className=\"mt-0.5 text-muted-foreground\">\n Off by default. Templates that explicitly need network override\n per phase.\n </div>\n </div>\n </label>\n </div>\n </section>\n );\n}\n","import {\n DaemonError,\n updateSettings,\n upsertSecret,\n} from \"@/lib/api\";\nimport type { OpencodeModelsResult } from \"@/lib/api/orchestrators\";\nimport {\n updatePermissions,\n type SandboxProfile,\n} from \"@/lib/api/settings\";\nimport { CLIS, classifyOpencodeClient } from \"./helpers\";\n\nexport interface OnboardingSubmitArgs {\n selectedClis: Set<string>;\n apiKeys: Record<string, string>;\n sandboxProfile: SandboxProfile;\n autoApprovePrompts: boolean;\n networkAccess: boolean;\n opencodeModels: OpencodeModelsResult | null;\n selectedOpencodeModels: Set<string>;\n}\n\n/**\n * Persist the onboarding form. Throws DaemonError when the daemon\n * rejects a write; the caller surfaces the message and keeps the form.\n */\nexport async function submitOnboarding(args: OnboardingSubmitArgs): Promise<void> {\n for (const cliId of args.selectedClis) {\n const cli = CLIS.find((c) => c.id === cliId);\n if (!cli) continue;\n await upsertSecret(cli.provider, {\n kind: \"cli_subscription\",\n value: cli.id,\n updatedAt: Date.now(),\n });\n }\n\n for (const [provider, value] of Object.entries(args.apiKeys)) {\n const trimmed = value.trim();\n if (!trimmed) continue;\n await upsertSecret(provider, {\n kind: \"api_key\",\n value: trimmed,\n updatedAt: Date.now(),\n });\n }\n\n await updatePermissions({\n sandboxProfile: args.sandboxProfile,\n autoApprovePrompts: args.autoApprovePrompts,\n networkAccess: args.networkAccess,\n });\n\n // Persist OpenCode model picks (if any) by upserting voice rows. We\n // can't assume the daemon's Phase 2 background seed has completed —\n // three round-1 reviewers caught this race: PUT-only would silently\n // drop the user's selection if the row didn't exist yet. List current\n // voices, PUT existing rows, POST missing ones.\n if (args.selectedClis.has(\"opencode-cli\") && args.opencodeModels) {\n await persistOpencodePicks(args);\n }\n\n await updateSettings({ onboarded: true });\n}\n\nasync function persistOpencodePicks(args: OnboardingSubmitArgs): Promise<void> {\n const { listVoices, updateVoice, createVoice } = await import(\n \"@/lib/api/voices\"\n );\n const existing = new Map(\n (await listVoices({ provider: \"opencode-cli\" }).catch(() => [])).map(\n (v) => [v.id, v] as const,\n ),\n );\n\n const models = args.opencodeModels;\n if (!models) return;\n\n await Promise.all(\n models.flat.map(async (m) => {\n const id = `opencode-cli:${m}`;\n const wantEnabled = args.selectedOpencodeModels.has(m);\n const row = existing.get(id);\n try {\n if (row) {\n if (row.enabled !== wantEnabled) {\n await updateVoice(id, { enabled: wantEnabled });\n }\n } else {\n // Row doesn't exist yet (Phase 2 seed missed it) — create\n // directly.\n const { lineage, vendor_family } = classifyOpencodeClient(m);\n await createVoice({\n provider: \"opencode-cli\",\n model_id: m,\n label: m,\n source: \"cli\",\n lineage,\n vendor_family,\n enabled: wantEnabled,\n });\n }\n } catch {\n // Best-effort: a single failed write shouldn't block onboarding.\n }\n }),\n );\n}\n\nexport function describeError(err: unknown): string {\n return err instanceof DaemonError\n ? err.message\n : \"Could not save. Is the Chorus daemon running?\";\n}\n"],"names":["Input","className","type","props"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- module.exports=[57926,a=>{"use strict";var b=a.i(81673),c=a.i(76015);let d=(0,a.i(91870).default)("copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);var e=a.i(3438),f=a.i(66985),g=a.i(58858),h=a.i(83862),i=a.i(91119),j=a.i(86304),k=a.i(34829),l=a.i(63690),m=a.i(32592),n=a.i(23202),o=a.i(63845),p=a.i(14574);a.i(30005);var q=a.i(92415),r=a.i(37035),s=a.i(64837),t=a.i(68114),u=a.i(88923);let v=/^[a-z0-9][a-z0-9-]{1,63}$/,w=[{value:"",label:"No preference"},{value:"anthropic",label:u.LINEAGE_LABEL.anthropic},{value:"openai",label:u.LINEAGE_LABEL.openai},{value:"google",label:u.LINEAGE_LABEL.google},{value:"opencode",label:u.LINEAGE_LABEL.opencode},{value:"moonshot",label:u.LINEAGE_LABEL.moonshot}],x={id:"",label:"",one_liner:"",recommended_lineage:"",system_prompt:"# Worldview\n\nDescribe the lens this persona uses to read code and findings.\n\n# What you look for\n\n- ...\n- ...\n\n# Tone\n\nHow the persona writes — terse, exhaustive, contrarian, etc.\n"};function y(a){return a.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}function z({label:a,hint:c,issue:d,span2:e,children:f}){return(0,b.jsxs)("label",{className:(0,t.cn)("flex flex-col gap-1",e&&"sm:col-span-2"),children:[(0,b.jsxs)("span",{className:"flex items-baseline justify-between gap-2",children:[(0,b.jsx)("span",{className:"text-[11px] font-medium uppercase tracking-wide text-muted-foreground",children:a}),c&&(0,b.jsx)("span",{className:"text-[10px] text-muted-foreground/70",children:c})]}),f,d&&(0,b.jsx)("span",{className:"text-[10px] text-destructive",children:d.message})]})}function A({form:a,setField:c,setIdDirty:d,isEdit:e,isBuiltin:f,issues:g}){return(0,b.jsxs)("div",{className:"min-h-0 flex-1 overflow-y-auto px-6 py-5",children:[e&&f&&(0,b.jsx)("div",{className:"mb-4 rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-[11px] text-amber-200",children:(0,b.jsxs)("div",{className:"flex items-start gap-2",children:[(0,b.jsx)(s.AlertTriangle,{className:"mt-0.5 h-3.5 w-3.5 shrink-0"}),(0,b.jsx)("div",{children:"Built-in persona. Saving demotes it to a user copy so the boot-time seed leaves it alone — you'll no longer receive upstream updates for this id."})]})}),(0,b.jsxs)("div",{className:"grid grid-cols-1 gap-4 sm:grid-cols-2",children:[(0,b.jsx)(z,{label:"Label",hint:"Human-friendly name shown in the picker",issue:g.find(a=>"label"===a.field),children:(0,b.jsx)("input",{type:"text",value:a.label,onChange:a=>c("label",a.target.value),placeholder:"Security Skeptic",className:"h-9 w-full rounded-md border border-border bg-background px-3 text-sm outline-none transition focus:border-primary/60"})}),(0,b.jsx)(z,{label:"ID",hint:e?"Locked once created":"Lowercase, dashes — auto-derived from label",issue:g.find(a=>"id"===a.field),children:(0,b.jsx)("input",{type:"text",value:a.id,disabled:e,onChange:a=>{d(!0),c("id",a.target.value)},placeholder:"security-skeptic",className:(0,t.cn)("h-9 w-full rounded-md border border-border bg-background px-3 font-mono text-sm outline-none transition focus:border-primary/60",e&&"cursor-not-allowed opacity-60")})}),(0,b.jsx)(z,{label:"One-liner",hint:"Shown under the label in the persona list",issue:g.find(a=>"one_liner"===a.field),span2:!0,children:(0,b.jsx)("input",{type:"text",value:a.one_liner,onChange:a=>c("one_liner",a.target.value),placeholder:"Reads every diff like an attacker.",className:"h-9 w-full rounded-md border border-border bg-background px-3 text-sm outline-none transition focus:border-primary/60"})}),(0,b.jsx)(z,{label:"Recommended lineage",hint:"Optional — pickers can default to this CLI",span2:!0,children:(0,b.jsx)("select",{value:a.recommended_lineage,onChange:a=>c("recommended_lineage",a.target.value),className:"h-9 w-full rounded-md border border-border bg-background px-3 text-sm outline-none transition focus:border-primary/60",children:w.map(a=>(0,b.jsx)("option",{value:a.value,children:a.label},a.value))})})]}),(0,b.jsx)("div",{className:"mt-5",children:(0,b.jsx)(z,{label:"System prompt",hint:"Prepended to the doer / reviewer ask at run time. Markdown.",issue:g.find(a=>"system_prompt"===a.field),children:(0,b.jsx)("textarea",{value:a.system_prompt,onChange:a=>c("system_prompt",a.target.value),spellCheck:!1,className:"min-h-[280px] w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-[12px] leading-relaxed outline-none transition focus:border-primary/60"})})})]})}var B=a.i(68103);function C({saveError:a,issues:c,valid:d,saving:f,deleting:h,confirmingDelete:i,canSave:j,isEdit:k,isBuiltin:l,onCancel:m,onSave:n,onDelete:o}){return(0,b.jsxs)("div",{className:"flex flex-col gap-2 border-t border-border bg-card/40 px-6 py-3",children:[a&&(0,b.jsx)("div",{className:"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[11px] text-destructive",children:(0,b.jsxs)("div",{className:"flex items-start gap-1.5",children:[(0,b.jsx)(s.AlertTriangle,{className:"mt-0.5 h-3 w-3 shrink-0"}),(0,b.jsx)("div",{className:"flex-1 leading-snug",children:a})]})}),(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsx)("div",{className:"flex items-center gap-1.5 text-[11px] text-muted-foreground",children:d?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(B.CheckCircle2,{className:"h-3 w-3 text-emerald-400"}),(0,b.jsx)("span",{children:"Ready to save"})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(s.AlertTriangle,{className:"h-3 w-3 text-destructive/80"}),(0,b.jsxs)("span",{children:[c.length," ",1===c.length?"issue":"issues"," to resolve"]})]})}),(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[k&&!l&&(0,b.jsxs)("button",{type:"button",onClick:o,disabled:h||f,className:(0,t.cn)("inline-flex h-9 items-center gap-1.5 rounded-md border px-3 text-sm font-medium transition",i?"border-destructive bg-destructive/15 text-destructive hover:bg-destructive/25":"border-border bg-card text-muted-foreground hover:border-destructive/50 hover:text-destructive"),children:[h?(0,b.jsx)(e.Loader2,{className:"h-3.5 w-3.5 animate-spin"}):(0,b.jsx)(g.Trash2,{className:"h-3.5 w-3.5"}),h?"Deleting…":i?"Click again to confirm":"Delete"]}),(0,b.jsx)("button",{type:"button",onClick:m,className:"h-9 rounded-md border border-border bg-card px-4 text-sm font-medium text-muted-foreground transition hover:border-muted-foreground/30 hover:text-foreground",children:"Cancel"}),(0,b.jsxs)("button",{type:"button",disabled:!j,onClick:n,className:(0,t.cn)("inline-flex h-9 items-center gap-1.5 rounded-md px-4 text-sm font-medium shadow-sm transition",j?"bg-primary text-primary-foreground hover:bg-primary/90":"cursor-not-allowed bg-muted text-muted-foreground/60 shadow-none"),children:[f&&(0,b.jsx)(e.Loader2,{className:"h-3.5 w-3.5 animate-spin"}),f?"Saving…":k?"Save changes":"Save persona"]})]})]})]})}function D({editing:a,trigger:d,onSaved:e,onDeleted:g,defaultOpen:h}){let[i,j]=(0,c.useState)(!!h),k=!!a,l=!!a?.builtin,s=(0,c.useMemo)(()=>a?{id:a.id,label:a.label,one_liner:a.one_liner,recommended_lineage:a.recommended_lineage??"",system_prompt:a.system_prompt??""}:x,[a?.id,a?.updated_at]),[t,u]=(0,c.useState)(s),[w,z]=(0,c.useState)(!1),[B,E]=(0,c.useState)(!1),[F,G]=(0,c.useState)(!1),[H,I]=(0,c.useState)(null),[J,K]=(0,c.useState)(k);(0,c.useEffect)(()=>{u(s),I(null),G(!1),K(k)},[s,k]);let L=(0,c.useRef)(s);(0,c.useEffect)(()=>{L.current=s});let M=(0,c.useMemo)(()=>{let a,b;return a=[],(b=k?t.id:t.id||y(t.label))?v.test(b)||a.push({field:"id",message:"id must be lowercase letters, numbers, dashes (2–64 chars)"}):a.push({field:"id",message:"id is required"}),t.label.trim()||a.push({field:"label",message:"label is required"}),t.one_liner.trim()||a.push({field:"one_liner",message:"one-liner is required"}),t.system_prompt.trim()||a.push({field:"system_prompt",message:"system prompt is required"}),a},[t,k]),N=0===M.length;function O(){u(L.current),z(!1),E(!1),I(null),G(!1),K(k)}function P(a){j(a),a||setTimeout(O,200)}async function Q(){if(!N||w)return;let b=k?a.id:t.id||y(t.label);z(!0),I(null);try{let a=await (0,r.savePersona)({id:b,label:t.label.trim(),one_liner:t.one_liner.trim(),system_prompt:t.system_prompt,recommended_lineage:t.recommended_lineage||null});e?.(a.id),P(!1)}catch(a){I(a instanceof q.DaemonError||a instanceof Error?a.message:"Save failed (unknown error)")}finally{z(!1)}}async function R(){if(a&&!l&&!B){if(!F){G(!0),setTimeout(()=>G(a=>!a&&a),8e3);return}E(!0),I(null);try{await (0,r.deletePersona)(a.id),g?.(a.id),P(!1)}catch(a){I(a instanceof q.DaemonError||a instanceof Error?a.message:"Delete failed (unknown error)"),G(!1)}finally{E(!1)}}}let S=N&&!w&&!B,T=d??(k?(0,b.jsx)("button",{type:"button","aria-label":`Edit persona ${a.label}`,className:"grid h-7 w-7 place-items-center rounded-md border border-border bg-card text-muted-foreground transition hover:border-muted-foreground/40 hover:bg-accent/60 hover:text-foreground",children:(0,b.jsx)(f.Pencil,{className:"h-3.5 w-3.5"})}):(0,b.jsxs)("button",{type:"button","aria-label":"New persona",className:"inline-flex shrink-0 items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground shadow-sm transition hover:bg-primary/90",children:[(0,b.jsx)(m.Plus,{className:"h-4 w-4"}),(0,b.jsx)("span",{className:"hidden sm:inline",children:"New persona"})]})),U=k?`Edit persona — ${a.label}`:"New persona",V=k?l?"Saving promotes this built-in to a user-owned row at the same id so your edits survive daemon restarts.":"Edit the worldview, recommended lineage, and system prompt.":"Personas are reusable worldviews that prepend to a doer or reviewer's prompt.";return(0,b.jsxs)(p.Dialog,{open:i,onOpenChange:P,children:[(0,b.jsx)(p.DialogTrigger,{asChild:!0,children:T}),(0,b.jsxs)(p.DialogContent,{showCloseButton:!1,className:"flex max-h-[85vh] w-[min(96vw,720px)] flex-col gap-0 overflow-hidden border-border bg-card p-0 shadow-2xl sm:max-w-none",children:[(0,b.jsxs)("div",{className:"flex items-center gap-3 border-b border-border px-6 py-4",children:[(0,b.jsx)("div",{className:"grid h-9 w-9 shrink-0 place-items-center rounded-md bg-primary/15 text-primary ring-1 ring-primary/20",children:(0,b.jsx)(n.Sparkles,{className:"h-4 w-4"})}),(0,b.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,b.jsx)(p.DialogTitle,{className:"text-[15px] font-semibold leading-tight tracking-tight",children:U}),(0,b.jsx)(p.DialogDescription,{className:"mt-0.5 text-xs text-muted-foreground",children:V})]}),(0,b.jsx)("button",{type:"button",onClick:()=>P(!1),className:"grid h-7 w-7 place-items-center rounded-md text-muted-foreground transition hover:bg-accent hover:text-foreground","aria-label":"Close",children:(0,b.jsx)(o.X,{className:"h-4 w-4"})})]}),(0,b.jsx)(A,{form:t,setField:function(a,b){u(c=>{let d={...c,[a]:b};return"label"!==a||J||k||(d.id=y(String(b))),d})},setIdDirty:K,isEdit:k,isBuiltin:l,issues:M}),(0,b.jsx)(C,{saveError:H,issues:M,valid:N,saving:w,deleting:B,confirmingDelete:F,canSave:S,isEdit:k,isBuiltin:l,onCancel:()=>P(!1),onSave:Q,onDelete:R})]})]})}a.s(["default",0,function(){let[a,m]=(0,c.useState)([]),[n,o]=(0,c.useState)(null),[p,s]=(0,c.useState)(""),[t,v]=(0,c.useState)(null),[w,x]=(0,c.useState)(!1),[y,z]=(0,c.useState)(0),[A,B]=(0,c.useState)(null),[C,E]=(0,c.useState)(null),[F,G]=(0,c.useState)(null),[H,I]=(0,c.useState)(null),[J,K]=(0,c.useState)(null),[L,M]=(0,c.useState)(null),N=(0,c.useCallback)(async a=>{try{let b=[...await (0,r.listPersonas)()].sort((a,b)=>a.builtin!==b.builtin?a.builtin?-1:1:a.label.localeCompare(b.label));m(b),a&&b.find(b=>b.id===a)?s(a):b.length>0?s(a=>b.find(b=>b.id===a)?a:b[0].id):s(""),z(a=>a+1)}catch(a){o(a instanceof q.DaemonError?a.message:"Failed to load personas")}},[]);async function O(a){if(!J&&!a.builtin){if(H!==a.id){I(a.id),M(null),setTimeout(()=>{I(b=>b===a.id?null:b)},8e3);return}K(a.id),M(null);try{await (0,r.deletePersona)(a.id),I(null),await N()}catch(a){M(a instanceof q.DaemonError||a instanceof Error?a.message:"Delete failed (unknown error)"),I(null)}finally{K(null)}}}async function P(b){if(!C){E(b.id),G(null);try{let c=b.system_prompt&&b.system_prompt.length>0?b:await (0,r.getPersona)(b.id),d=new Set(a.map(a=>a.id)),e=function({sourceId:a,taken:b,maxAttempts:c=100,uniqueSuffix:d=Date.now}){let e=`${a}-copy`;if(!b.has(e))return e;for(let a=2;a<c;a++){let c=`${e}-${a}`;if(!b.has(c))return c}return`${e}-${d()}`}({sourceId:b.id,taken:d}),f=await (0,r.savePersona)({id:e,label:`${c.label} (copy)`,one_liner:c.one_liner,system_prompt:c.system_prompt??"",recommended_lineage:c.recommended_lineage??null,forked_from:c.forked_from??c.id});B(f.id),await N(f.id)}catch(a){G(a instanceof q.DaemonError||a instanceof Error?a.message:"Duplicate failed (unknown error)")}finally{E(null)}}}return((0,c.useEffect)(()=>{N()},[N]),(0,c.useEffect)(()=>{if(!p)return void v(null);let a=!1;return x(!0),(0,r.getPersona)(p).then(b=>{a||v(b)}).catch(()=>{a||v(null)}).finally(()=>{a||x(!1)}),()=>{a=!0}},[p,y]),n)?(0,b.jsx)(h.AppShell,{children:(0,b.jsx)("div",{className:"mx-auto w-full max-w-6xl px-4 py-6 sm:px-6 sm:py-8 md:px-8 md:py-10",children:(0,b.jsxs)("div",{className:"rounded-lg border border-destructive/50 bg-destructive/10 p-4",children:[(0,b.jsx)("p",{className:"text-sm text-destructive",children:"Error loading personas"}),(0,b.jsx)("p",{className:"mt-1 text-xs text-muted-foreground",children:n})]})})}):(0,b.jsx)(h.AppShell,{children:(0,b.jsxs)("div",{className:"mx-auto w-full max-w-6xl px-4 py-6 sm:px-6 sm:py-8 md:px-8 md:py-10",children:[(0,b.jsx)(k.PageHeader,{eyebrow:"Personas",title:"Reviewer worldviews",subtitle:(0,b.jsxs)(b.Fragment,{children:["Each persona is a set of instructions that teaches the same model to look for different things. Same Claude or Codex, different worldview, wildly different findings. Use any of them via the"," ",(0,b.jsx)("code",{className:"font-mono text-foreground/80",children:"invoke_persona"})," MCP tool from inside Claude Code, Cursor, Codex, or any editor with chorus wired up."]}),action:(0,b.jsx)(D,{onSaved:a=>N(a)})}),F&&(0,b.jsxs)("div",{className:"mb-4 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:["Duplicate failed: ",F]}),L&&(0,b.jsxs)("div",{className:"mb-4 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:["Delete failed: ",L]}),(0,b.jsxs)("div",{className:"grid grid-cols-1 gap-4 lg:grid-cols-[1fr_1.2fr]",children:[(0,b.jsxs)("div",{className:"flex min-w-0 flex-col gap-2",children:[a.map(a=>{let c=a.id===p;return(0,b.jsxs)("div",{role:"button",tabIndex:0,onClick:()=>s(a.id),onKeyDown:b=>{("Enter"===b.key||" "===b.key)&&(b.preventDefault(),s(a.id))},className:`group relative cursor-pointer rounded-xl text-left transition focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/60 ${c?"ring-2 ring-primary/60 ring-offset-2 ring-offset-background":""}`,children:[(0,b.jsx)(i.Card,{className:"bg-card p-4 transition group-hover:border-muted-foreground/30",children:(0,b.jsx)("div",{className:"flex items-start justify-between gap-3",children:(0,b.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,b.jsx)("span",{className:"text-sm font-semibold",children:a.label}),a.builtin?(0,b.jsx)(j.Badge,{variant:"outline",className:"border-border text-[10px]",children:"built-in"}):(0,b.jsx)(j.Badge,{className:"bg-primary/15 text-[10px] text-primary",children:"user"}),a.recommended_lineage&&(0,b.jsxs)("span",{className:"flex items-center gap-1 text-[10px] text-muted-foreground",children:[(0,b.jsx)("span",{className:`h-1.5 w-1.5 rounded-full ${(0,u.lineageDot)(a.recommended_lineage)}`}),(0,u.lineageLabel)(a.recommended_lineage)]})]}),(0,b.jsx)("p",{className:"mt-1 text-xs text-muted-foreground line-clamp-2",children:a.one_liner}),(0,b.jsxs)("p",{className:"mt-1 font-mono text-[10px] text-muted-foreground/70",children:["id: ",a.id]})]})})}),(0,b.jsxs)("div",{className:`absolute bottom-3 right-3 flex items-center gap-1.5 transition ${c?"opacity-100":"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100"}`,onClick:b=>{b.stopPropagation(),s(a.id)},onKeyDown:a=>a.stopPropagation(),children:[(0,b.jsx)("button",{type:"button","aria-label":`Duplicate persona ${a.label}`,title:"Duplicate",disabled:C===a.id,onClick:()=>P(a),className:"grid h-7 w-7 place-items-center rounded-md border border-border bg-card text-muted-foreground transition hover:border-muted-foreground/40 hover:bg-accent/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",children:C===a.id?(0,b.jsx)(e.Loader2,{className:"h-3.5 w-3.5 animate-spin"}):(0,b.jsx)(d,{className:"h-3.5 w-3.5"})}),!a.builtin&&(0,b.jsx)("button",{type:"button","aria-label":H===a.id?`Confirm delete persona ${a.label}`:`Delete persona ${a.label}`,title:H===a.id?"Click again to confirm":"Delete",disabled:J===a.id,onClick:()=>O(a),className:`grid h-7 w-7 place-items-center rounded-md border transition disabled:cursor-not-allowed disabled:opacity-50 ${H===a.id?"border-destructive bg-destructive/15 text-destructive":"border-border bg-card text-muted-foreground hover:border-destructive/50 hover:text-destructive"}`,children:J===a.id?(0,b.jsx)(e.Loader2,{className:"h-3.5 w-3.5 animate-spin"}):(0,b.jsx)(g.Trash2,{className:"h-3.5 w-3.5"})}),t&&t.id===a.id?(0,b.jsx)(D,{editing:t,defaultOpen:A===a.id,onSaved:b=>{A===a.id&&B(null),N(b)},onDeleted:()=>{A===a.id&&B(null),N()}},`${a.id}:${A===a.id?"auto":"manual"}`):(0,b.jsx)("button",{type:"button","aria-label":`Edit persona ${a.label}`,title:"Edit",onClick:()=>{s(a.id),B(a.id)},className:"grid h-7 w-7 place-items-center rounded-md border border-border bg-card text-muted-foreground transition hover:border-muted-foreground/40 hover:bg-accent/60 hover:text-foreground",children:(0,b.jsx)(f.Pencil,{className:"h-3.5 w-3.5"})})]})]},a.id)}),0===a.length&&(0,b.jsx)(i.Card,{className:"bg-card p-4 text-center text-sm text-muted-foreground",children:"No personas yet. Daemon may still be seeding — refresh in a second."})]}),t?(0,b.jsx)(l.CodeBlock,{filename:`${t.id}.md`,charCount:t.system_prompt?.length??0,footer:(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("span",{children:["Invoke via"," ",(0,b.jsxs)("code",{className:"rounded bg-muted/40 px-1 font-mono text-[10px] text-foreground/80",children:["invoke_persona(",`{ personaId: "${t.id}" }`,")"]})]}),t.builtin&&(0,b.jsxs)("span",{children:["edit at"," ",(0,b.jsxs)("code",{className:"font-mono text-[10px]",children:["prompts/personas/",t.id,".md"]})]})]}),children:t.system_prompt??""}):w?(0,b.jsx)(i.Card,{className:"bg-card p-4 text-center text-muted-foreground",children:(0,b.jsx)("p",{className:"text-sm",children:"Loading persona…"})}):(0,b.jsx)(i.Card,{className:"bg-card p-4 text-center text-muted-foreground",children:(0,b.jsx)("p",{className:"text-sm",children:"Select a persona to view its prompt."})})]})]})})}],57926)}];
2
-
3
- //# sourceMappingURL=src_app_personas_page_tsx_0jx9vyh._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/components/persona-dialog/helpers.tsx","../../../../src/components/persona-dialog/form-body.tsx","../../../../src/components/persona-dialog/footer.tsx","../../../../src/components/persona-dialog/index.tsx","../../../../src/app/personas/page.tsx","../../../../node_modules/.pnpm/lucide-react%401.12.0_react%4019.2.4/node_modules/lucide-react/src/icons/copy.ts","../../../../src/lib/persona-duplicate-id.ts"],"sourcesContent":["\"use client\";\n\nimport { LINEAGE_LABEL, type DaemonLineage } from \"@/lib/lineage-maps\";\nimport { cn } from \"@/lib/utils\";\n\nconst PERSONA_ID_RE = /^[a-z0-9][a-z0-9-]{1,63}$/;\n\nexport const LINEAGE_OPTIONS: Array<{ value: DaemonLineage | \"\"; label: string }> = [\n { value: \"\", label: \"No preference\" },\n { value: \"anthropic\", label: LINEAGE_LABEL.anthropic },\n { value: \"openai\", label: LINEAGE_LABEL.openai },\n { value: \"google\", label: LINEAGE_LABEL.google },\n { value: \"opencode\", label: LINEAGE_LABEL.opencode },\n { value: \"moonshot\", label: LINEAGE_LABEL.moonshot },\n];\n\nexport interface FormState {\n id: string;\n label: string;\n one_liner: string;\n recommended_lineage: string;\n system_prompt: string;\n}\n\nexport const DEFAULT_FORM: FormState = {\n id: \"\",\n label: \"\",\n one_liner: \"\",\n recommended_lineage: \"\",\n system_prompt:\n \"# Worldview\\n\\nDescribe the lens this persona uses to read code and findings.\\n\\n# What you look for\\n\\n- ...\\n- ...\\n\\n# Tone\\n\\nHow the persona writes — terse, exhaustive, contrarian, etc.\\n\",\n};\n\nexport function slugify(input: string): string {\n return input\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 64);\n}\n\nexport interface ValidationIssue {\n field: keyof FormState;\n message: string;\n}\n\nexport function validate(form: FormState, isEdit: boolean): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const id = isEdit ? form.id : form.id || slugify(form.label);\n if (!id) issues.push({ field: \"id\", message: \"id is required\" });\n else if (!PERSONA_ID_RE.test(id))\n issues.push({\n field: \"id\",\n message: \"id must be lowercase letters, numbers, dashes (2–64 chars)\",\n });\n if (!form.label.trim()) issues.push({ field: \"label\", message: \"label is required\" });\n if (!form.one_liner.trim())\n issues.push({ field: \"one_liner\", message: \"one-liner is required\" });\n if (!form.system_prompt.trim())\n issues.push({ field: \"system_prompt\", message: \"system prompt is required\" });\n return issues;\n}\n\nexport function Field({\n label,\n hint,\n issue,\n span2,\n children,\n}: {\n label: string;\n hint?: string;\n issue?: ValidationIssue;\n span2?: boolean;\n children: React.ReactNode;\n}) {\n return (\n <label className={cn(\"flex flex-col gap-1\", span2 && \"sm:col-span-2\")}>\n <span className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {label}\n </span>\n {hint && (\n <span className=\"text-[10px] text-muted-foreground/70\">{hint}</span>\n )}\n </span>\n {children}\n {issue && (\n <span className=\"text-[10px] text-destructive\">{issue.message}</span>\n )}\n </label>\n );\n}\n","\"use client\";\n\nimport { AlertTriangle } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Field,\n LINEAGE_OPTIONS,\n type FormState,\n type ValidationIssue,\n} from \"./helpers\";\n\ninterface FormBodyProps {\n form: FormState;\n setField: <K extends keyof FormState>(k: K, v: FormState[K]) => void;\n setIdDirty: (dirty: boolean) => void;\n isEdit: boolean;\n isBuiltin: boolean;\n issues: ValidationIssue[];\n}\n\nexport function FormBody({\n form,\n setField,\n setIdDirty,\n isEdit,\n isBuiltin,\n issues,\n}: FormBodyProps) {\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-5\">\n {isEdit && isBuiltin && (\n <div className=\"mb-4 rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-[11px] text-amber-200\">\n <div className=\"flex items-start gap-2\">\n <AlertTriangle className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" />\n <div>\n Built-in persona. Saving demotes it to a user copy so the\n boot-time seed leaves it alone — you&apos;ll no longer\n receive upstream updates for this id.\n </div>\n </div>\n </div>\n )}\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <Field\n label=\"Label\"\n hint=\"Human-friendly name shown in the picker\"\n issue={issues.find((i) => i.field === \"label\")}\n >\n <input\n type=\"text\"\n value={form.label}\n onChange={(e) => setField(\"label\", e.target.value)}\n placeholder=\"Security Skeptic\"\n className=\"h-9 w-full rounded-md border border-border bg-background px-3 text-sm outline-none transition focus:border-primary/60\"\n />\n </Field>\n\n <Field\n label=\"ID\"\n hint={isEdit ? \"Locked once created\" : \"Lowercase, dashes — auto-derived from label\"}\n issue={issues.find((i) => i.field === \"id\")}\n >\n <input\n type=\"text\"\n value={form.id}\n disabled={isEdit}\n onChange={(e) => {\n setIdDirty(true);\n setField(\"id\", e.target.value);\n }}\n placeholder=\"security-skeptic\"\n className={cn(\n \"h-9 w-full rounded-md border border-border bg-background px-3 font-mono text-sm outline-none transition focus:border-primary/60\",\n isEdit && \"cursor-not-allowed opacity-60\",\n )}\n />\n </Field>\n\n <Field\n label=\"One-liner\"\n hint=\"Shown under the label in the persona list\"\n issue={issues.find((i) => i.field === \"one_liner\")}\n span2\n >\n <input\n type=\"text\"\n value={form.one_liner}\n onChange={(e) => setField(\"one_liner\", e.target.value)}\n placeholder=\"Reads every diff like an attacker.\"\n className=\"h-9 w-full rounded-md border border-border bg-background px-3 text-sm outline-none transition focus:border-primary/60\"\n />\n </Field>\n\n <Field\n label=\"Recommended lineage\"\n hint=\"Optional — pickers can default to this CLI\"\n span2\n >\n <select\n value={form.recommended_lineage}\n onChange={(e) => setField(\"recommended_lineage\", e.target.value)}\n className=\"h-9 w-full rounded-md border border-border bg-background px-3 text-sm outline-none transition focus:border-primary/60\"\n >\n {LINEAGE_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </Field>\n </div>\n\n <div className=\"mt-5\">\n <Field\n label=\"System prompt\"\n hint=\"Prepended to the doer / reviewer ask at run time. Markdown.\"\n issue={issues.find((i) => i.field === \"system_prompt\")}\n >\n <textarea\n value={form.system_prompt}\n onChange={(e) => setField(\"system_prompt\", e.target.value)}\n spellCheck={false}\n className=\"min-h-[280px] w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-[12px] leading-relaxed outline-none transition focus:border-primary/60\"\n />\n </Field>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { AlertTriangle, CheckCircle2, Loader2, Trash2 } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport type { ValidationIssue } from \"./helpers\";\n\ninterface FooterProps {\n saveError: string | null;\n issues: ValidationIssue[];\n valid: boolean;\n saving: boolean;\n deleting: boolean;\n confirmingDelete: boolean;\n canSave: boolean;\n isEdit: boolean;\n isBuiltin: boolean;\n onCancel: () => void;\n onSave: () => void;\n onDelete: () => void;\n}\n\nexport function Footer({\n saveError,\n issues,\n valid,\n saving,\n deleting,\n confirmingDelete,\n canSave,\n isEdit,\n isBuiltin,\n onCancel,\n onSave,\n onDelete,\n}: FooterProps) {\n return (\n <div className=\"flex flex-col gap-2 border-t border-border bg-card/40 px-6 py-3\">\n {saveError && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[11px] text-destructive\">\n <div className=\"flex items-start gap-1.5\">\n <AlertTriangle className=\"mt-0.5 h-3 w-3 shrink-0\" />\n <div className=\"flex-1 leading-snug\">{saveError}</div>\n </div>\n </div>\n )}\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-1.5 text-[11px] text-muted-foreground\">\n {valid ? (\n <>\n <CheckCircle2 className=\"h-3 w-3 text-emerald-400\" />\n <span>Ready to save</span>\n </>\n ) : (\n <>\n <AlertTriangle className=\"h-3 w-3 text-destructive/80\" />\n <span>\n {issues.length} {issues.length === 1 ? \"issue\" : \"issues\"} to\n resolve\n </span>\n </>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {isEdit && !isBuiltin && (\n <button\n type=\"button\"\n onClick={onDelete}\n disabled={deleting || saving}\n className={cn(\n \"inline-flex h-9 items-center gap-1.5 rounded-md border px-3 text-sm font-medium transition\",\n confirmingDelete\n ? \"border-destructive bg-destructive/15 text-destructive hover:bg-destructive/25\"\n : \"border-border bg-card text-muted-foreground hover:border-destructive/50 hover:text-destructive\",\n )}\n >\n {deleting ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Trash2 className=\"h-3.5 w-3.5\" />\n )}\n {deleting\n ? \"Deleting…\"\n : confirmingDelete\n ? \"Click again to confirm\"\n : \"Delete\"}\n </button>\n )}\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"h-9 rounded-md border border-border bg-card px-4 text-sm font-medium text-muted-foreground transition hover:border-muted-foreground/30 hover:text-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n disabled={!canSave}\n onClick={onSave}\n className={cn(\n \"inline-flex h-9 items-center gap-1.5 rounded-md px-4 text-sm font-medium shadow-sm transition\",\n canSave\n ? \"bg-primary text-primary-foreground hover:bg-primary/90\"\n : \"cursor-not-allowed bg-muted text-muted-foreground/60 shadow-none\",\n )}\n >\n {saving && <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />}\n {saving ? \"Saving…\" : isEdit ? \"Save changes\" : \"Save persona\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","\"use client\";\n\n/**\n * PersonaDialog — single dialog for both NEW and EDIT.\n *\n * Personas are flat (no YAML/Form duality like templates), so this is a\n * single form panel. The system prompt is the bulk of the content — a\n * Markdown body that gets prepended to the doer/reviewer's ask at run\n * time, so the textarea stretches to fill the dialog.\n *\n * Built-in source semantics mirror templates:\n * - Save on a builtin row → server demotes it to user-owned so the\n * boot-time seed leaves it alone.\n * - Delete is hidden for builtins because the seed would recreate them.\n * Users can clone-and-rename instead via the \"Fork\" trigger.\n */\n\nimport { Pencil, Plus, Sparkles, X } from \"lucide-react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogTitle,\n DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { DaemonError, deletePersona, savePersona } from \"@/lib/api\";\nimport type { Persona } from \"@/lib/api/personas\";\nimport { FormBody } from \"./form-body\";\nimport { Footer } from \"./footer\";\nimport { DEFAULT_FORM, slugify, validate, type FormState } from \"./helpers\";\n\nexport interface PersonaDialogProps {\n /** When set, dialog opens in EDIT mode populated from this persona.\n * Built-ins are edited in place — the server demotes them to\n * user-owned on save and the boot seed skips user rows. The\n * Duplicate per-row affordance covers \"I want a renamed copy\". */\n editing?: Persona;\n /** Renders the trigger. New mode wraps with a \"+ New persona\" button by default. */\n trigger?: React.ReactNode;\n /** Called after a successful save. Parent should refresh its list. */\n onSaved?: (savedId: string) => void;\n /** Called after a successful delete. Parent should refresh its list. */\n onDeleted?: (deletedId: string) => void;\n /** When provided, opens the dialog automatically on mount. Used by the\n * page after a Duplicate so the user lands directly in the new row's\n * edit form. The parent should clear this once consumed (typically\n * via remounting the dialog with a different React key). */\n defaultOpen?: boolean;\n}\n\nexport function PersonaDialog({\n editing,\n trigger,\n onSaved,\n onDeleted,\n defaultOpen,\n}: PersonaDialogProps) {\n const [open, setOpen] = useState(Boolean(defaultOpen));\n const isEdit = Boolean(editing);\n const isBuiltin = Boolean(editing?.builtin);\n\n // Depend on the *content* (id + updated_at) rather than the object\n // reference so a parent re-render with a fresh Persona pointing at the\n // same row doesn't wipe in-flight edits.\n const initial = useMemo<FormState>(() => {\n if (!editing) return DEFAULT_FORM;\n return {\n id: editing.id,\n label: editing.label,\n one_liner: editing.one_liner,\n recommended_lineage: editing.recommended_lineage ?? \"\",\n system_prompt: editing.system_prompt ?? \"\",\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editing?.id, editing?.updated_at]);\n\n const [form, setForm] = useState<FormState>(initial);\n const [saving, setSaving] = useState(false);\n const [deleting, setDeleting] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n // Tracks whether the user manually edited the id field; once they do,\n // typing in the label stops auto-syncing the slug.\n const [idDirty, setIdDirty] = useState(isEdit);\n\n // Reset internal form state when the parent passes a different\n // persona (id+updated_at change). The \"right\" pattern per React\n // Compiler is to remount via parent's `key` prop, but this dialog\n // also owns its own open/close state — a key change mid-edit would\n // close the dialog and discard pending edits. Keeping the\n // controlled-reset pattern; migration to lifted open state is v0.8.\n useEffect(() => {\n /* eslint-disable react-hooks/set-state-in-effect */\n setForm(initial);\n setSaveError(null);\n setConfirmingDelete(false);\n setIdDirty(isEdit);\n /* eslint-enable react-hooks/set-state-in-effect */\n }, [initial, isEdit]);\n\n // Hold the latest `initial` in a ref so the setTimeout-based reset\n // (`reset()` 200ms after dialog close) always reads the freshest value\n // — without it, save → close → 200ms-later reset captured the OLD\n // initial via closure. Assignment moved into useEffect so the React\n // Compiler purity check passes; the timing change is safe because the\n // only reader is `reset()`, which runs from setTimeout 200ms after\n // the close, well after this effect has committed.\n const initialRef = useRef(initial);\n useEffect(() => {\n initialRef.current = initial;\n });\n\n const issues = useMemo(() => validate(form, isEdit), [form, isEdit]);\n const valid = issues.length === 0;\n\n function setField<K extends keyof FormState>(k: K, v: FormState[K]) {\n setForm((prev) => {\n const next = { ...prev, [k]: v };\n if (k === \"label\" && !idDirty && !isEdit) {\n next.id = slugify(String(v));\n }\n return next;\n });\n }\n\n function reset() {\n setForm(initialRef.current);\n setSaving(false);\n setDeleting(false);\n setSaveError(null);\n setConfirmingDelete(false);\n setIdDirty(isEdit);\n }\n\n function handleClose(o: boolean) {\n setOpen(o);\n if (!o) setTimeout(reset, 200);\n }\n\n async function handleSave() {\n if (!valid || saving) return;\n const idToSave = isEdit ? editing!.id : form.id || slugify(form.label);\n setSaving(true);\n setSaveError(null);\n try {\n const saved = await savePersona({\n id: idToSave,\n label: form.label.trim(),\n one_liner: form.one_liner.trim(),\n system_prompt: form.system_prompt,\n recommended_lineage: form.recommended_lineage || null,\n });\n onSaved?.(saved.id);\n handleClose(false);\n } catch (err) {\n setSaveError(\n err instanceof DaemonError\n ? err.message\n : err instanceof Error\n ? err.message\n : \"Save failed (unknown error)\",\n );\n } finally {\n setSaving(false);\n }\n }\n\n async function handleDelete() {\n if (!editing || isBuiltin || deleting) return;\n if (!confirmingDelete) {\n setConfirmingDelete(true);\n // Auto-disarm after 8s so an abandoned arming doesn't fire on a\n // much later stray click. 4s was too tight in real-user testing —\n // anyone double-checking the row label blew the window.\n setTimeout(() => setConfirmingDelete((cur) => (cur ? false : cur)), 8000);\n return;\n }\n setDeleting(true);\n setSaveError(null);\n try {\n await deletePersona(editing.id);\n onDeleted?.(editing.id);\n handleClose(false);\n } catch (err) {\n setSaveError(\n err instanceof DaemonError\n ? err.message\n : err instanceof Error\n ? err.message\n : \"Delete failed (unknown error)\",\n );\n setConfirmingDelete(false);\n } finally {\n setDeleting(false);\n }\n }\n\n const canSave = valid && !saving && !deleting;\n\n const triggerEl =\n trigger ??\n (isEdit ? (\n <button\n type=\"button\"\n aria-label={`Edit persona ${editing!.label}`}\n className=\"grid h-7 w-7 place-items-center rounded-md border border-border bg-card text-muted-foreground transition hover:border-muted-foreground/40 hover:bg-accent/60 hover:text-foreground\"\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </button>\n ) : (\n <button\n type=\"button\"\n aria-label=\"New persona\"\n className=\"inline-flex shrink-0 items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground shadow-sm transition hover:bg-primary/90\"\n >\n <Plus className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">New persona</span>\n </button>\n ));\n\n const titleText = isEdit ? `Edit persona — ${editing!.label}` : \"New persona\";\n const descText = isEdit\n ? isBuiltin\n ? \"Saving promotes this built-in to a user-owned row at the same id so your edits survive daemon restarts.\"\n : \"Edit the worldview, recommended lineage, and system prompt.\"\n : \"Personas are reusable worldviews that prepend to a doer or reviewer's prompt.\";\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogTrigger asChild>{triggerEl}</DialogTrigger>\n\n <DialogContent\n showCloseButton={false}\n className=\"flex max-h-[85vh] w-[min(96vw,720px)] flex-col gap-0 overflow-hidden border-border bg-card p-0 shadow-2xl sm:max-w-none\"\n >\n <div className=\"flex items-center gap-3 border-b border-border px-6 py-4\">\n <div className=\"grid h-9 w-9 shrink-0 place-items-center rounded-md bg-primary/15 text-primary ring-1 ring-primary/20\">\n <Sparkles className=\"h-4 w-4\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <DialogTitle className=\"text-[15px] font-semibold leading-tight tracking-tight\">\n {titleText}\n </DialogTitle>\n <DialogDescription className=\"mt-0.5 text-xs text-muted-foreground\">\n {descText}\n </DialogDescription>\n </div>\n <button\n type=\"button\"\n onClick={() => handleClose(false)}\n className=\"grid h-7 w-7 place-items-center rounded-md text-muted-foreground transition hover:bg-accent hover:text-foreground\"\n aria-label=\"Close\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <FormBody\n form={form}\n setField={setField}\n setIdDirty={setIdDirty}\n isEdit={isEdit}\n isBuiltin={isBuiltin}\n issues={issues}\n />\n\n <Footer\n saveError={saveError}\n issues={issues}\n valid={valid}\n saving={saving}\n deleting={deleting}\n confirmingDelete={confirmingDelete}\n canSave={canSave}\n isEdit={isEdit}\n isBuiltin={isBuiltin}\n onCancel={() => handleClose(false)}\n onSave={handleSave}\n onDelete={handleDelete}\n />\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\";\n\n/**\n * Personas page — browse the worldview prompts that drive `invoke_persona`.\n * Built-in library lives in `prompts/personas/*.md` and is seeded into the\n * `personas` table on every daemon boot. User-cloned rows are never\n * overwritten. The cockpit fetches both via GET /personas; full system_prompt\n * is loaded on demand when a persona is selected (GET /personas/:id).\n */\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { Copy, Loader2, Pencil, Trash2 } from \"lucide-react\";\nimport { AppShell } from \"@/components/app-shell\";\nimport { Card } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { PageHeader } from \"@/components/page-header\";\nimport { CodeBlock } from \"@/components/code-block\";\nimport { PersonaDialog } from \"@/components/persona-dialog\";\nimport {\n listPersonas,\n getPersona,\n savePersona,\n deletePersona,\n DaemonError,\n} from \"@/lib/api\";\nimport type { Persona } from \"@/lib/api/personas\";\nimport { nextDuplicateId } from \"@/lib/persona-duplicate-id\";\nimport { lineageDot, lineageLabel } from \"@/lib/lineage-maps\";\n\nexport default function PersonasPage() {\n const [personas, setPersonas] = useState<Persona[]>([]);\n const [loadError, setLoadError] = useState<string | null>(null);\n const [selectedId, setSelectedId] = useState<string>(\"\");\n const [selectedFull, setSelectedFull] = useState<Persona | null>(null);\n const [loadingFull, setLoadingFull] = useState(false);\n // Bumped after every save/delete so the right-pane effect refetches the\n // updated_at-stamped row even when the selected id didn't change.\n const [reloadTick, setReloadTick] = useState(0);\n // When set, the per-row PersonaDialog mounted for this id opens\n // automatically and the trigger is consumed. Used by the Duplicate\n // affordance so the user lands directly in the new copy's edit form\n // without an extra click.\n const [autoOpenId, setAutoOpenId] = useState<string | null>(null);\n // Per-row \"duplicate in flight\" so we can show a spinner on the right\n // icon while the POST resolves; without it a slow daemon makes the\n // duplicate icon feel dead and tempts a second click.\n const [duplicatingId, setDuplicatingId] = useState<string | null>(null);\n const [duplicateError, setDuplicateError] = useState<string | null>(null);\n // Delete confirms inline rather than via a modal so the toolbar stays\n // light. First click = arms (id stored here), second click within the\n // arming window fires. Auto-disarms after 4s so a forgotten arm doesn't\n // delete on a much-later stray click.\n const [confirmingDeleteId, setConfirmingDeleteId] = useState<string | null>(null);\n const [deletingId, setDeletingId] = useState<string | null>(null);\n const [deleteError, setDeleteError] = useState<string | null>(null);\n\n const refresh = useCallback(async (preserveId?: string) => {\n try {\n const rows = await listPersonas();\n const sorted = [...rows].sort((a, b) => {\n if (a.builtin !== b.builtin) return a.builtin ? -1 : 1;\n return a.label.localeCompare(b.label);\n });\n setPersonas(sorted);\n if (preserveId && sorted.find((p) => p.id === preserveId)) {\n setSelectedId(preserveId);\n } else if (sorted.length > 0) {\n // Fall through to the first row when the preserved id no longer\n // exists (e.g. just-deleted) — without this the right pane would\n // strand on a stale id and render the empty state forever.\n setSelectedId((cur) => (sorted.find((p) => p.id === cur) ? cur : sorted[0].id));\n } else {\n setSelectedId(\"\");\n }\n setReloadTick((n) => n + 1);\n } catch (err) {\n setLoadError(err instanceof DaemonError ? err.message : \"Failed to load personas\");\n }\n }, []);\n\n // Mount-only data load. `refresh()` is async + uses setState\n // internally; React Compiler's set-state-in-effect rule flags this\n // because it can't track through the closure. The pattern is\n // intentional and equivalent to the canonical \"fetch on mount\"\n // recipe — switching to a Suspense-based loader is a v0.8 cockpit\n // refactor, not a v0.7 launch fix.\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n refresh();\n }, [refresh]);\n\n async function handleDeleteRow(target: Persona) {\n if (deletingId || target.builtin) return;\n if (confirmingDeleteId !== target.id) {\n setConfirmingDeleteId(target.id);\n setDeleteError(null);\n // Auto-disarm to avoid a long-lived primed Delete eating a later\n // accidental click; bumped from 4s to 8s after a real-user test\n // showed the original window timed out before the user could\n // re-confirm a long row. Matches the dialog's window.\n setTimeout(() => {\n setConfirmingDeleteId((cur) => (cur === target.id ? null : cur));\n }, 8000);\n return;\n }\n setDeletingId(target.id);\n setDeleteError(null);\n try {\n await deletePersona(target.id);\n setConfirmingDeleteId(null);\n await refresh();\n } catch (err) {\n setDeleteError(\n err instanceof DaemonError\n ? err.message\n : err instanceof Error\n ? err.message\n : \"Delete failed (unknown error)\",\n );\n setConfirmingDeleteId(null);\n } finally {\n setDeletingId(null);\n }\n }\n\n async function handleDuplicate(source: Persona) {\n if (duplicatingId) return;\n setDuplicatingId(source.id);\n setDuplicateError(null);\n try {\n // Need the full persona including system_prompt. List rows are\n // typically full (the daemon's listPersonas returns all columns)\n // but be defensive and refetch if the body is missing.\n const full =\n source.system_prompt && source.system_prompt.length > 0\n ? source\n : await getPersona(source.id);\n const taken = new Set(personas.map((p) => p.id));\n const newId = nextDuplicateId({ sourceId: source.id, taken });\n const saved = await savePersona({\n id: newId,\n label: `${full.label} (copy)`,\n one_liner: full.one_liner,\n system_prompt: full.system_prompt ?? \"\",\n recommended_lineage: full.recommended_lineage ?? null,\n // Record provenance so future tooling can trace which built-in or\n // user persona this copy was derived from. Past chats that\n // reference the source id continue to resolve there unchanged.\n // Flatten to the root: duplicating an already-duplicated row\n // points at the original ancestor, not the intermediate copy, so\n // the lineage chart stays one hop deep.\n forked_from: full.forked_from ?? full.id,\n });\n // Open the duplicate in edit mode immediately so the user can rename\n // or tweak before walking away. autoOpenId is consumed by the\n // per-row dialog's `key` + defaultOpen wiring (cleared after mount).\n setAutoOpenId(saved.id);\n await refresh(saved.id);\n } catch (err) {\n setDuplicateError(\n err instanceof DaemonError\n ? err.message\n : err instanceof Error\n ? err.message\n : \"Duplicate failed (unknown error)\",\n );\n } finally {\n setDuplicatingId(null);\n }\n }\n\n // Fetch the full persona (with system_prompt) when selection changes.\n // The two synchronous setStates inside this effect (clearing on empty\n // selection + flipping the loading flag) trip React Compiler's\n // set-state-in-effect rule. Migrating to Suspense + use(promise) is\n // a v0.8 cockpit refactor; the canonical async-fetch pattern is\n // intentional here.\n useEffect(() => {\n if (!selectedId) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setSelectedFull(null);\n return;\n }\n let cancelled = false;\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setLoadingFull(true);\n getPersona(selectedId)\n .then((p) => {\n if (cancelled) return;\n setSelectedFull(p);\n })\n .catch(() => {\n if (cancelled) return;\n setSelectedFull(null);\n })\n .finally(() => {\n if (cancelled) return;\n setLoadingFull(false);\n });\n return () => {\n cancelled = true;\n };\n }, [selectedId, reloadTick]);\n\n if (loadError) {\n return (\n <AppShell>\n <div className=\"mx-auto w-full max-w-6xl px-4 py-6 sm:px-6 sm:py-8 md:px-8 md:py-10\">\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-4\">\n <p className=\"text-sm text-destructive\">Error loading personas</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">{loadError}</p>\n </div>\n </div>\n </AppShell>\n );\n }\n\n return (\n <AppShell>\n <div className=\"mx-auto w-full max-w-6xl px-4 py-6 sm:px-6 sm:py-8 md:px-8 md:py-10\">\n <PageHeader\n eyebrow=\"Personas\"\n title=\"Reviewer worldviews\"\n subtitle={\n <>\n Each persona is a set of instructions that teaches the same model\n to look for different things. Same Claude or Codex, different\n worldview, wildly different findings. Use any of them via the{\" \"}\n <code className=\"font-mono text-foreground/80\">invoke_persona</code> MCP\n tool from inside Claude Code, Cursor, Codex, or any editor with\n chorus wired up.\n </>\n }\n action={<PersonaDialog onSaved={(id) => refresh(id)} />}\n />\n\n {duplicateError && (\n <div className=\"mb-4 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive\">\n Duplicate failed: {duplicateError}\n </div>\n )}\n {deleteError && (\n <div className=\"mb-4 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive\">\n Delete failed: {deleteError}\n </div>\n )}\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-[1fr_1.2fr]\">\n {/* Persona list */}\n <div className=\"flex min-w-0 flex-col gap-2\">\n {personas.map((p) => {\n const isSelected = p.id === selectedId;\n return (\n <div\n key={p.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => setSelectedId(p.id)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setSelectedId(p.id);\n }\n }}\n className={`group relative cursor-pointer rounded-xl text-left transition focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/60 ${\n isSelected\n ? \"ring-2 ring-primary/60 ring-offset-2 ring-offset-background\"\n : \"\"\n }`}\n >\n <Card className=\"bg-card p-4 transition group-hover:border-muted-foreground/30\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold\">{p.label}</span>\n {p.builtin ? (\n <Badge\n variant=\"outline\"\n className=\"border-border text-[10px]\"\n >\n built-in\n </Badge>\n ) : (\n <Badge className=\"bg-primary/15 text-[10px] text-primary\">\n user\n </Badge>\n )}\n {p.recommended_lineage && (\n <span className=\"flex items-center gap-1 text-[10px] text-muted-foreground\">\n <span\n className={`h-1.5 w-1.5 rounded-full ${lineageDot(p.recommended_lineage)}`}\n />\n {lineageLabel(p.recommended_lineage)}\n </span>\n )}\n </div>\n <p className=\"mt-1 text-xs text-muted-foreground line-clamp-2\">\n {p.one_liner}\n </p>\n <p className=\"mt-1 font-mono text-[10px] text-muted-foreground/70\">\n id: {p.id}\n </p>\n </div>\n </div>\n </Card>\n {/* Edit + Duplicate per-row affordances. Visible on hover\n or while selected. stopPropagation prevents the card's\n onClick from firing and snapping focus mid-edit. The\n Edit pencil needs the *full* persona (with\n system_prompt) so it's gated on the right-pane fetch\n having completed for this id; opening the dialog before\n selectedFull lands would prefill an empty body.\n Duplicate doesn't need that gate — the handler refetches\n the source if its body is missing. The PersonaDialog's\n `key` ties to autoOpenId so the duplicate's\n defaultOpen=true takes effect on a fresh mount. */}\n <div\n className={`absolute bottom-3 right-3 flex items-center gap-1.5 transition ${\n isSelected\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100\"\n }`}\n onClick={(e) => {\n e.stopPropagation();\n setSelectedId(p.id);\n }}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n aria-label={`Duplicate persona ${p.label}`}\n title=\"Duplicate\"\n disabled={duplicatingId === p.id}\n onClick={() => handleDuplicate(p)}\n className=\"grid h-7 w-7 place-items-center rounded-md border border-border bg-card text-muted-foreground transition hover:border-muted-foreground/40 hover:bg-accent/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {duplicatingId === p.id ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Copy className=\"h-3.5 w-3.5\" />\n )}\n </button>\n {!p.builtin && (\n <button\n type=\"button\"\n aria-label={\n confirmingDeleteId === p.id\n ? `Confirm delete persona ${p.label}`\n : `Delete persona ${p.label}`\n }\n title={\n confirmingDeleteId === p.id\n ? \"Click again to confirm\"\n : \"Delete\"\n }\n disabled={deletingId === p.id}\n onClick={() => handleDeleteRow(p)}\n className={`grid h-7 w-7 place-items-center rounded-md border transition disabled:cursor-not-allowed disabled:opacity-50 ${\n confirmingDeleteId === p.id\n ? \"border-destructive bg-destructive/15 text-destructive\"\n : \"border-border bg-card text-muted-foreground hover:border-destructive/50 hover:text-destructive\"\n }`}\n >\n {deletingId === p.id ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Trash2 className=\"h-3.5 w-3.5\" />\n )}\n </button>\n )}\n {selectedFull && selectedFull.id === p.id ? (\n <PersonaDialog\n key={`${p.id}:${autoOpenId === p.id ? \"auto\" : \"manual\"}`}\n editing={selectedFull}\n defaultOpen={autoOpenId === p.id}\n onSaved={(id) => {\n if (autoOpenId === p.id) setAutoOpenId(null);\n refresh(id);\n }}\n onDeleted={() => {\n if (autoOpenId === p.id) setAutoOpenId(null);\n refresh();\n }}\n />\n ) : (\n // Placeholder pencil for unselected rows. The real\n // PersonaDialog only mounts once selectedFull lands\n // for this id, so on hover we show a stand-in that\n // selects the card and queues auto-open. Once the\n // right-pane fetch resolves the dialog re-renders\n // above with defaultOpen=true.\n <button\n type=\"button\"\n aria-label={`Edit persona ${p.label}`}\n title=\"Edit\"\n onClick={() => {\n setSelectedId(p.id);\n setAutoOpenId(p.id);\n }}\n className=\"grid h-7 w-7 place-items-center rounded-md border border-border bg-card text-muted-foreground transition hover:border-muted-foreground/40 hover:bg-accent/60 hover:text-foreground\"\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n </div>\n );\n })}\n {personas.length === 0 && (\n <Card className=\"bg-card p-4 text-center text-sm text-muted-foreground\">\n No personas yet. Daemon may still be seeding — refresh in a\n second.\n </Card>\n )}\n </div>\n\n {/* System prompt preview */}\n {selectedFull ? (\n <CodeBlock\n filename={`${selectedFull.id}.md`}\n charCount={selectedFull.system_prompt?.length ?? 0}\n footer={\n <>\n <span>\n Invoke via{\" \"}\n <code className=\"rounded bg-muted/40 px-1 font-mono text-[10px] text-foreground/80\">\n invoke_persona({`{ personaId: \"${selectedFull.id}\" }`})\n </code>\n </span>\n {selectedFull.builtin && (\n <span>\n edit at{\" \"}\n <code className=\"font-mono text-[10px]\">\n prompts/personas/{selectedFull.id}.md\n </code>\n </span>\n )}\n </>\n }\n >\n {selectedFull.system_prompt ?? \"\"}\n </CodeBlock>\n ) : loadingFull ? (\n <Card className=\"bg-card p-4 text-center text-muted-foreground\">\n <p className=\"text-sm\">Loading persona…</p>\n </Card>\n ) : (\n <Card className=\"bg-card p-4 text-center text-muted-foreground\">\n <p className=\"text-sm\">Select a persona to view its prompt.</p>\n </Card>\n )}\n </div>\n </div>\n </AppShell>\n );\n}\n","import createLucideIcon from '../createLucideIcon';\nimport { IconNode } from '../types';\n\nexport const __iconNode: IconNode = [\n ['rect', { width: '14', height: '14', x: '8', y: '8', rx: '2', ry: '2', key: '17jyea' }],\n ['path', { d: 'M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2', key: 'zix9uf' }],\n];\n\n/**\n * @component @name Copy\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cmVjdCB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHg9IjgiIHk9IjgiIHJ4PSIyIiByeT0iMiIgLz4KICA8cGF0aCBkPSJNNCAxNmMtMS4xIDAtMi0uOS0yLTJWNGMwLTEuMS45LTIgMi0yaDEwYzEuMSAwIDIgLjkgMiAyIiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/copy\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Copy = createLucideIcon('copy', __iconNode);\n\nexport default Copy;\n","/**\n * Pick the next free ID for a duplicated persona row.\n *\n * Walks `<sourceId>-copy`, `<sourceId>-copy-2`, ... up to a sanity cap;\n * if that's exhausted (the user is duplicating an absurd number of\n * times) falls back to a unique-suffixed ID.\n *\n * Extracted to a pure helper so we can unit-test the slot-walking\n * logic AND so the React Compiler purity rule stops flagging the inline\n * `Date.now()` use as an in-render impurity. The unique-suffix source\n * is a parameter — caller passes `Date.now` in production, tests pass\n * a deterministic counter.\n */\nexport interface NextDuplicateIdInput {\n sourceId: string;\n taken: Set<string>;\n /** Sanity cap on `-copy-N` walks. Default 100 — user almost certainly\n * isn't intentionally duplicating the same row 100+ times. */\n maxAttempts?: number;\n /** Injectable time source. Production passes `Date.now`; tests pass\n * a deterministic stub. */\n uniqueSuffix?: () => number | string;\n}\n\nexport function nextDuplicateId({\n sourceId,\n taken,\n maxAttempts = 100,\n uniqueSuffix = Date.now,\n}: NextDuplicateIdInput): string {\n const base = `${sourceId}-copy`;\n if (!taken.has(base)) return base;\n for (let i = 2; i < maxAttempts; i++) {\n const candidate = `${base}-${i}`;\n if (!taken.has(candidate)) return candidate;\n }\n return `${base}-${uniqueSuffix()}`;\n}\n"],"names":["width","key","d"],"mappings":"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","ignoreList":[5]}
@@ -1,27 +0,0 @@
1
- module.exports=[20788,a=>{"use strict";var b=a.i(81673),c=a.i(76015),d=a.i(9106),e=a.i(91870);let f=(0,e.default)("wrench",[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]]);var g=a.i(83862),h=a.i(34829),i=a.i(14342);let j=(0,e.default)("shield",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]]),k=(0,e.default)("credit-card",[["rect",{width:"20",height:"14",x:"2",y:"5",rx:"2",key:"ynyp8z"}],["line",{x1:"2",x2:"22",y1:"10",y2:"10",key:"1b3vmo"}]]);var l=a.i(26442),m=a.i(86304),n=a.i(91119),o=a.i(84623),p=a.i(34823);let q=[{id:"read",name:"Read files",description:"cat, less, head, file open"},{id:"list",name:"List & search",description:"ls, grep, find, ripgrep"},{id:"write",name:"Write files",description:"Edit, Write inside allowed dirs"},{id:"exec",name:"Run commands",description:"Bash, npm, pnpm, python, go"},{id:"net",name:"Network access",description:"curl, fetch, package install"},{id:"outside-cwd",name:"Writes outside working dir",description:"Anything outside the allowed paths below"}],r={read:"auto",list:"auto",write:"ask",exec:"ask",net:"ask","outside-cwd":"block"},s={read:"auto",list:"auto",write:"block",exec:"ask",net:"ask","outside-cwd":"block"},t={auto:"bg-emerald-500/15 text-emerald-300 border-emerald-500/30",ask:"bg-amber-500/15 text-amber-300 border-amber-500/30",block:"bg-rose-500/15 text-rose-300 border-rose-500/30"};function u(a){return"auto"===a?"ask":"ask"===a?"block":"auto"}function v({id:a,icon:c,title:d,subtitle:e,children:f}){return(0,b.jsxs)(n.Card,{id:a,className:"mt-6 scroll-mt-20 bg-card p-5",children:[(0,b.jsxs)("div",{className:"mb-4 flex items-start gap-3",children:[(0,b.jsx)("span",{className:"rounded-md border border-border bg-card/60 p-1.5 text-foreground/70",children:c}),(0,b.jsxs)("div",{className:"flex-1",children:[(0,b.jsx)("h2",{className:"text-sm font-medium text-foreground",children:d}),(0,b.jsx)("p",{className:"mt-0.5 text-xs text-muted-foreground",children:e})]})]}),f]})}function w({label:a,children:c}){return(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1.5 block text-[11px] font-medium uppercase tracking-wider text-muted-foreground",children:a}),c]})}function x({policy:a,onCycle:c,role:d}){return(0,b.jsx)("button",{type:"button",onClick:c,className:`justify-self-end rounded-md border px-2.5 py-1 font-mono text-[10px] uppercase tracking-wider transition hover:scale-105 ${t[a]}`,title:`${d}: cycle policy`,children:a})}function y({kind:a,current:c,onSelect:d,icon:e,title:f,tagline:g,features:h,tradeoff:i}){let j=a===c;return(0,b.jsxs)("button",{type:"button",onClick:d,className:`flex w-full items-start gap-3 rounded-lg border p-3.5 text-left transition ${j?"border-primary/40 bg-primary/5 ring-2 ring-primary/30 ring-offset-2 ring-offset-background":"border-border bg-card/40 hover:border-foreground/30"}`,children:[(0,b.jsx)("span",{className:`mt-0.5 grid h-7 w-7 shrink-0 place-items-center rounded-md ${j?"bg-primary/20 text-primary":"bg-card text-muted-foreground"}`,children:e}),(0,b.jsxs)("div",{className:"flex-1",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)("span",{className:"text-sm font-semibold text-foreground",children:f}),(0,b.jsx)(m.Badge,{variant:"outline",className:"border-border font-mono text-[10px]",children:g})]}),(0,b.jsx)("ul",{className:"mt-1.5 space-y-0.5 text-[11px] text-muted-foreground",children:h.map(a=>(0,b.jsxs)("li",{className:"flex items-start gap-1.5",children:[(0,b.jsx)(o.Check,{className:"mt-0.5 h-3 w-3 shrink-0 text-emerald-400/60"}),(0,b.jsx)("span",{children:a})]},a))}),(0,b.jsxs)("div",{className:"mt-2 flex items-start gap-1.5 text-[10px] text-muted-foreground",children:[(0,b.jsx)(p.Info,{className:"mt-0.5 h-3 w-3 shrink-0 text-muted-foreground/60"}),(0,b.jsxs)("span",{children:[(0,b.jsx)("span",{className:"font-medium text-foreground/80",children:"Trade-off:"})," ",i]})]})]}),j&&(0,b.jsx)(o.Check,{className:"mt-1 h-4 w-4 shrink-0 text-primary"})]})}function z(){let[a,d]=(0,c.useState)(null),[e,f]=(0,c.useState)(void 0),[g,h]=(0,c.useState)(null),[i,j]=(0,c.useState)(null);return(0,c.useEffect)(()=>{let a=!1;return(0,l.getBillingMode)().then(b=>{a||(d(b.mode),f(b.descriptions))}).catch(b=>{a||j(b instanceof Error?b.message:"Could not load billing mode.")}),()=>{a=!0}},[]),(0,b.jsxs)(v,{icon:(0,b.jsx)(k,{className:"h-4 w-4"}),title:"Billing mode",subtitle:"How you pay for the AI CLIs chorus drives. Affects what the cost preview shows on the new-chat page — defaults to API rates so the number stays honest until you tell us otherwise.",children:[i&&(0,b.jsx)("div",{className:"mb-3 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive",children:i}),(0,b.jsx)("div",{className:"grid gap-2",children:["api","subscription","mixed"].map(c=>{let f=a===c,i=g===c,k=e?.[c];return(0,b.jsxs)("button",{type:"button",onClick:()=>{a===c||g||(h(c),j(null),(0,l.updateBillingMode)({mode:c}).then(a=>d(a.mode)).catch(a=>{j(a instanceof Error?a.message:"Save failed.")}).finally(()=>h(null)))},disabled:null!==g||null===a,className:`flex flex-col gap-1 rounded-lg border p-3 text-left transition ${f?"border-primary/50 bg-primary/10":"border-border bg-card hover:border-muted-foreground/30"} ${null!==g?"opacity-60":""}`,children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-sm font-medium",children:k?.label??c}),f&&(0,b.jsx)("span",{className:"rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-primary",children:i?"saving…":"active"})]}),(0,b.jsx)("p",{className:"text-xs leading-relaxed text-muted-foreground",children:k?.description??""})]},c)})})]})}let A=(0,e.default)("activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]);var B=a.i(64837);let C=(0,e.default)("cloud",[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z",key:"p7xjir"}]]);var D=a.i(92632),E=a.i(3438);let F=(0,e.default)("monitor",[["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2",key:"48i651"}],["line",{x1:"8",x2:"16",y1:"21",y2:"21",key:"1svkeh"}],["line",{x1:"12",x2:"12",y1:"17",y2:"21",key:"vw1qmm"}]]);var G=a.i(32592);let H=(0,e.default)("send",[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",key:"1ffxy3"}],["path",{d:"m21.854 2.147-10.94 10.939",key:"12cjpa"}]]),I=(0,e.default)("server",[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2",key:"ngkwjq"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2",key:"iecqi9"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6",key:"16zg32"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18",key:"nzw8ys"}]]);var J=a.i(51996);let K=(0,e.default)("webhook",[["path",{d:"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2",key:"q3hayz"}],["path",{d:"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06",key:"1go1hn"}],["path",{d:"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8",key:"qlwsc0"}]]),L=(0,e.default)("workflow",[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2",key:"by2w9f"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4",key:"xkn7yn"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2",key:"1cgmvn"}]]);var M=a.i(63845);function N(a){return(0,b.jsxs)("div",{className:"mt-2 select-none opacity-60 [&_*]:pointer-events-none","aria-disabled":"true",children:[(0,b.jsxs)(v,{icon:(0,b.jsx)(A,{className:"h-4 w-4"}),title:"Concurrency",subtitle:"How many chats Chorus runs in parallel. Overflow waits in a queue.",children:[(0,b.jsxs)("div",{className:"flex items-center gap-6",children:[(0,b.jsxs)("div",{className:"flex-1",children:[(0,b.jsx)("input",{type:"range",min:1,max:10,step:1,value:a.maxConcurrent,onChange:b=>a.setMaxConcurrent(parseInt(b.target.value,10)),disabled:!0,className:"w-full accent-primary"}),(0,b.jsxs)("div",{className:"mt-1.5 flex justify-between text-[10px] font-mono text-muted-foreground",children:[(0,b.jsx)("span",{children:"1"}),(0,b.jsx)("span",{children:"5"}),(0,b.jsx)("span",{children:"10"})]})]}),(0,b.jsxs)("div",{className:"rounded-md border border-border bg-card px-4 py-2 font-mono text-sm",children:[a.maxConcurrent," concurrent"]})]}),(0,b.jsxs)("p",{className:"mt-3 text-xs text-muted-foreground",children:["Each chat reserves one tmux session + ",3*a.maxConcurrent," reviewer panes. Above this limit new chats land in a FIFO queue."]})]}),(0,b.jsxs)(v,{icon:(0,b.jsx)(D.FolderLock,{className:"h-4 w-4"}),title:"Per-tool auto-approve",subtitle:"Drivers write code; reviewers don't. Defaults reflect that. Click any chip to cycle auto / ask / block.",children:[(0,b.jsxs)("div",{className:"grid grid-cols-[1fr_120px_120px] gap-3 border-b border-border pb-2 text-[10px] font-medium uppercase tracking-wider text-muted-foreground",children:[(0,b.jsx)("span",{children:"Tool"}),(0,b.jsxs)("span",{className:"flex items-center justify-end gap-1.5",children:[(0,b.jsx)("span",{className:"h-1.5 w-1.5 rounded-full bg-amber-400"}),"Driver"]}),(0,b.jsxs)("span",{className:"flex items-center justify-end gap-1.5",children:[(0,b.jsx)("span",{className:"h-1.5 w-1.5 rounded-full bg-blue-400"}),"Reviewer"]})]}),(0,b.jsx)("div",{className:"mt-1 divide-y divide-border opacity-70",children:q.map(c=>(0,b.jsxs)("div",{className:"grid grid-cols-[1fr_120px_120px] items-center gap-3 py-2.5",children:[(0,b.jsxs)("div",{className:"flex flex-col",children:[(0,b.jsx)("span",{className:"text-sm text-foreground",children:c.name}),(0,b.jsx)("span",{className:"text-[11px] text-muted-foreground",children:c.description})]}),(0,b.jsx)(x,{policy:a.driverPolicies[c.id],onCycle:()=>a.cyclePolicy("driver",c.id),role:"driver"}),(0,b.jsx)(x,{policy:a.reviewerPolicies[c.id],onCycle:()=>a.cyclePolicy("reviewer",c.id),role:"reviewer"})]},c.id))}),(0,b.jsxs)("p",{className:"mt-3 flex items-start gap-2 rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-100",children:[(0,b.jsx)(B.AlertTriangle,{className:"mt-0.5 h-3.5 w-3.5 shrink-0 text-amber-400"}),(0,b.jsxs)("span",{children:[(0,b.jsx)("span",{className:"font-semibold",children:"When wired:"})," ",(0,b.jsx)("code",{className:"rounded bg-amber-400/10 px-1 font-mono text-amber-200",children:"ask"})," ","prompts will appear as cards in the chat — you click"," ",(0,b.jsx)("span",{className:"font-semibold",children:"Approve"})," /"," ",(0,b.jsx)("span",{className:"font-semibold",children:"Deny"})," instead of the agent stalling."]})]})]}),(0,b.jsxs)(v,{icon:(0,b.jsx)(D.FolderLock,{className:"h-4 w-4"}),title:"Working directories",subtitle:"Each tmux session is started inside one of these paths. Writes outside are blocked.",children:[(0,b.jsx)("div",{className:"flex flex-wrap gap-2",children:a.allowedDirs.map(c=>(0,b.jsxs)("span",{className:"group inline-flex items-center gap-1.5 rounded-md border border-border bg-card px-2.5 py-1 font-mono text-[11px] text-foreground",children:[c,(0,b.jsx)("button",{type:"button",onClick:()=>a.setAllowedDirs(a.allowedDirs.filter(a=>a!==c)),className:"text-muted-foreground/50 transition hover:text-rose-400","aria-label":`Remove ${c}`,children:(0,b.jsx)(M.X,{className:"h-3 w-3"})})]},c))}),(0,b.jsxs)("div",{className:"mt-3 flex gap-2",children:[(0,b.jsx)("input",{type:"text",value:a.newDir,onChange:b=>a.setNewDir(b.target.value),onKeyDown:b=>"Enter"===b.key&&a.addDir(),placeholder:"~/code/another-project",className:"flex-1 rounded-md border border-border bg-card px-3 py-1.5 font-mono text-xs text-foreground placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:outline-none"}),(0,b.jsxs)("button",{type:"button",onClick:a.addDir,className:"flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition hover:bg-primary/90",children:[(0,b.jsx)(G.Plus,{className:"h-3.5 w-3.5"}),"Add path"]})]})]}),(0,b.jsx)(v,{icon:(0,b.jsx)(J.Sliders,{className:"h-4 w-4"}),title:"Template defaults",subtitle:"Applied to new templates and one-off chats. Per-template values override these.",children:(0,b.jsxs)("div",{className:"grid gap-4 sm:grid-cols-2",children:[(0,b.jsx)(w,{label:"Default driver",children:(0,b.jsxs)("select",{value:a.defaultDriver,onChange:b=>a.setDefaultDriver(b.target.value),className:"w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-foreground/30 focus:outline-none",children:[(0,b.jsx)("option",{value:"claude-code",children:"claude-code"}),(0,b.jsx)("option",{value:"cursor",children:"cursor"}),(0,b.jsx)("option",{value:"codex-cli",children:"codex-cli"}),(0,b.jsx)("option",{value:"windsurf",children:"windsurf"}),(0,b.jsx)("option",{value:"external",children:"external (ask each run)"})]})}),(0,b.jsx)(w,{label:"Default agreement threshold",children:(0,b.jsxs)("select",{value:a.defaultThreshold,onChange:b=>a.setDefaultThreshold(b.target.value),className:"w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-foreground/30 focus:outline-none",children:[(0,b.jsx)("option",{value:"unanimous",children:"unanimous"}),(0,b.jsx)("option",{value:"majority",children:"majority"}),(0,b.jsx)("option",{value:"any",children:"any"})]})}),(0,b.jsx)(w,{label:"Default cost cap (USD per chat)",children:(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)("span",{className:"font-mono text-sm text-muted-foreground",children:"$"}),(0,b.jsx)("input",{type:"number",step:"0.10",min:0,value:a.defaultCostCap,onChange:b=>a.setDefaultCostCap(b.target.value),className:"w-full rounded-md border border-border bg-card px-3 py-2 font-mono text-sm text-foreground focus:border-foreground/30 focus:outline-none"})]})}),(0,b.jsx)(w,{label:"On model error",children:(0,b.jsxs)("select",{defaultValue:"fallback",className:"w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-foreground/30 focus:outline-none",children:[(0,b.jsx)("option",{value:"fallback",children:"try next fallback model"}),(0,b.jsx)("option",{value:"fail",children:"mark chat failed"}),(0,b.jsx)("option",{value:"ask-user",children:"surface to me"})]})})]})}),(0,b.jsx)(v,{icon:(0,b.jsx)(j,{className:"h-4 w-4"}),title:"Privacy & data path",subtitle:"How prompts and code reach each LLM. Affects what leaves your machine.",children:(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsx)(y,{current:a.privacyTier,kind:"local",onSelect:()=>a.setPrivacyTier("local"),icon:(0,b.jsx)(F,{className:"h-4 w-4"}),title:"Local-only (BYO CLIs)",tagline:"Strictest",features:["Daemon runs on your machine; CLIs run on your machine.","Prompts go directly from your machine to each provider.","Chorus sees nothing — not even chat IDs."],tradeoff:"No cloud dashboard, no team sharing, no fallback when a CLI is down."}),(0,b.jsx)(y,{current:a.privacyTier,kind:"proxied",onSelect:()=>a.setPrivacyTier("proxied"),icon:(0,b.jsx)(I,{className:"h-4 w-4"}),title:"Proxied credits",tagline:"Recommended for credits",features:["Stateless edge proxy: prompts transit, never persist.","Stripe-pattern: same payload-handling discipline.","Used only when you spend credits to try a model you don't have."],tradeoff:"One extra hop between you and the provider."}),(0,b.jsx)(y,{current:a.privacyTier,kind:"cloud",onSelect:()=>a.setPrivacyTier("cloud"),icon:(0,b.jsx)(C,{className:"h-4 w-4"}),title:"Cloud workspace",tagline:"Team / multi-machine",features:["Code is cloned into Chorus's cloud workspace.","Transcripts + verdicts kept for audit & retro.","Encrypted at rest; SOC 2 in progress."],tradeoff:"Your code lives on our infra. Read the privacy whitepaper before flipping this on."})]})}),(0,b.jsx)(v,{icon:(0,b.jsx)(K,{className:"h-4 w-4"}),title:"Notifications & MCP",subtitle:"How outer orchestrators (your main Claude / Cursor session) get pinged when a chat finishes or blocks.",children:(0,b.jsxs)("div",{className:"space-y-4",children:[(0,b.jsxs)("button",{type:"button",onClick:()=>a.setMcpEnabled(!a.mcpEnabled),className:"flex w-full items-center justify-between rounded-md border border-border bg-card/50 px-3 py-3 text-left transition hover:border-foreground/20",children:[(0,b.jsxs)("div",{className:"flex items-start gap-3",children:[(0,b.jsx)(L,{className:"mt-0.5 h-4 w-4 text-primary"}),(0,b.jsxs)("div",{className:"flex flex-col",children:[(0,b.jsx)("span",{className:"text-sm text-foreground",children:"Chorus MCP server"}),(0,b.jsxs)("span",{className:"text-[11px] text-muted-foreground",children:["Exposes ",(0,b.jsx)("span",{className:"font-mono",children:"mm.create_chat"}),","," ",(0,b.jsx)("span",{className:"font-mono",children:"mm.update_settings"}),","," ",(0,b.jsx)("span",{className:"font-mono",children:"mm.create_template"})," and 9 other tools. Outer Claude / Cursor / Codex can configure Chorus for you."]})]})]}),(0,b.jsx)("span",{className:`flex h-5 w-9 items-center rounded-full border p-0.5 transition ${a.mcpEnabled?"border-emerald-500/40 bg-emerald-500/20":"border-border bg-card"}`,children:(0,b.jsx)("span",{className:`h-3.5 w-3.5 rounded-full transition-transform ${a.mcpEnabled?"translate-x-4 bg-emerald-400":"bg-muted-foreground/50"}`})})]}),(0,b.jsxs)(w,{label:"Webhook URL (optional)",children:[(0,b.jsxs)("div",{className:"flex gap-2",children:[(0,b.jsx)("input",{type:"url",value:a.webhookUrl,onChange:b=>a.setWebhookUrl(b.target.value),placeholder:"https://hooks.example.com/chorus",className:"flex-1 rounded-md border border-border bg-card px-3 py-2 font-mono text-xs text-foreground placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:outline-none"}),(0,b.jsxs)("button",{type:"button",onClick:a.testWebhook,disabled:!a.webhookUrl||"running"===a.webhookTestState,className:`flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs font-medium transition ${"ok"===a.webhookTestState?"border-emerald-500/30 bg-emerald-500/10 text-emerald-300":"fail"===a.webhookTestState?"border-rose-500/30 bg-rose-500/10 text-rose-300":"border-border bg-card text-muted-foreground hover:text-foreground"} disabled:cursor-not-allowed disabled:opacity-50`,children:["running"===a.webhookTestState?(0,b.jsx)(E.Loader2,{className:"h-3.5 w-3.5 animate-spin"}):"ok"===a.webhookTestState?(0,b.jsx)(o.Check,{className:"h-3.5 w-3.5"}):"fail"===a.webhookTestState?(0,b.jsx)(B.AlertTriangle,{className:"h-3.5 w-3.5"}):(0,b.jsx)(H,{className:"h-3.5 w-3.5"}),"ok"===a.webhookTestState?"204 OK":"fail"===a.webhookTestState?"Failed":"running"===a.webhookTestState?"Posting…":"Test"]})]}),(0,b.jsx)("p",{className:"mt-1.5 text-[11px] text-muted-foreground",children:"Posted on chat finished / blocked / errored. Payload includes chat_id, status, synthesis."})]})]})})]})}var O=a.i(97535);function P(){let[a,d]=(0,c.useState)(null),[e,f]=(0,c.useState)(!1),[g,h]=(0,c.useState)(null);(0,c.useEffect)(()=>{let a=!1;return(0,l.getTelemetryStatus)().then(b=>{a||d(b)}).catch(b=>{a||h(b instanceof Error?b.message:"Could not load telemetry status.")}),()=>{a=!0}},[]);let i=a?.envOverride||a?.fileOverride;return(0,b.jsxs)(v,{icon:(0,b.jsx)(O.Eye,{className:"h-4 w-4"}),title:"Anonymous telemetry",subtitle:"A small heartbeat sent to chorus.codes once per boot + every 24h. Helps us see what versions / OSes are in the wild. No code, no prompts, no chat content.",children:[g&&(0,b.jsx)("div",{className:"mb-3 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive",children:g}),(0,b.jsx)("div",{className:"rounded-lg border border-border bg-card p-3",children:(0,b.jsxs)("label",{className:"flex items-start gap-3",children:[(0,b.jsx)("input",{type:"checkbox",checked:a?.enabled??!1,onChange:b=>{var c;return c=b.target.checked,void(!e&&a&&!i&&(f(!0),h(null),(0,l.updateTelemetryEnabled)(c).then(d).catch(a=>{h(a instanceof Error?a.message:"Save failed.")}).finally(()=>f(!1))))},disabled:e||!a||i,className:"mt-1 h-4 w-4 cursor-pointer accent-primary disabled:cursor-not-allowed"}),(0,b.jsxs)("span",{className:"flex-1",children:[(0,b.jsxs)("span",{className:"block text-sm font-medium",children:["Send anonymous heartbeat",e&&(0,b.jsx)("span",{className:"ml-2 rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-primary",children:"saving…"})]}),(0,b.jsx)("span",{className:"mt-1 block text-xs leading-relaxed text-muted-foreground",children:"Sends: install UUID, chorus version, OS, arch, node major, daemon uptime, count of chats in the last 24h. That's it."})]})]})}),i&&(0,b.jsxs)("div",{className:"mt-3 rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-xs text-amber-100",children:["Telemetry is currently disabled by"," ",a?.envOverride&&(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"CHORUS_TELEMETRY"}),a?.envOverride&&a?.fileOverride&&" and ",a?.fileOverride&&(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"~/.chorus/no-telemetry"}),". The toggle above won't take effect until you remove the override."]}),(0,b.jsxs)("details",{className:"mt-3 text-xs text-muted-foreground",children:[(0,b.jsx)("summary",{className:"cursor-pointer hover:text-foreground",children:"Other ways to opt out"}),(0,b.jsxs)("ul",{className:"mt-2 list-inside list-disc space-y-1 leading-relaxed",children:[(0,b.jsxs)("li",{children:["Set ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"CHORUS_TELEMETRY=0"})," ","in your shell — also accepts ",(0,b.jsx)("code",{children:"false"}),", ",(0,b.jsx)("code",{children:"no"}),","," ",(0,b.jsx)("code",{children:"off"}),"."]}),(0,b.jsxs)("li",{children:[(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"touch ~/.chorus/no-telemetry"})," ","(cargo / brew convention)."]}),(0,b.jsxs)("li",{children:["Reset your install ID:"," ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"rm ~/.chorus/install-id"})," ","— a fresh UUID is minted on the next heartbeat."]})]}),a?.endpoint&&(0,b.jsxs)("p",{className:"mt-2 leading-relaxed",children:["Endpoint: ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:a.endpoint})]})]})]})}let Q=(0,e.default)("terminal",[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]]);function R(){let[a,d]=(0,c.useState)(null),[e,f]=(0,c.useState)(void 0),[g,h]=(0,c.useState)(!0),[i,j]=(0,c.useState)(null),[k,m]=(0,c.useState)(null);return(0,c.useEffect)(()=>{let a=!1;return(0,l.getTransport)().then(b=>{a||(d(b.transport),f(b.descriptions),h(!1!==b.tmuxAvailable))}).catch(b=>{a||m(b instanceof Error?b.message:"Could not load transport setting.")}),()=>{a=!0}},[]),(0,b.jsxs)(v,{id:"transport",icon:(0,b.jsx)(Q,{className:"h-4 w-4"}),title:"Run mode (headless / tmux)",subtitle:"How chorus runs each CLI. Default is headless (faster, lower RAM). Switch to tmux if you want to attach to a live voice and take over mid-run (debug + handoff).",children:[k&&(0,b.jsx)("div",{className:"mb-3 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive",children:k}),(0,b.jsx)("div",{className:"grid gap-2 sm:grid-cols-2",children:["headless","tmux"].map(c=>{let f=a===c,h=i===c,k=e?.[c],n="tmux"===c&&!g;return(0,b.jsxs)("button",{type:"button",onClick:()=>{a===c||i||(j(c),m(null),(0,l.updateTransport)({transport:c}).then(a=>{d(a.transport)}).catch(a=>{m(a instanceof Error?a.message:"Save failed.")}).finally(()=>j(null)))},disabled:null!==i||null===a||n,title:n?"tmux is not installed on this host. Install it (brew/apt/dnf) then restart the daemon.":void 0,className:`flex flex-col gap-1 rounded-lg border p-3 text-left transition ${f?"border-primary/50 bg-primary/10":"border-border bg-card hover:border-muted-foreground/30"} ${null!==i||n?"opacity-60 cursor-not-allowed":""}`,children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-sm font-medium",children:k?.label??("headless"===c?"Headless":"Tmux")}),f?(0,b.jsx)("span",{className:"rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-primary",children:h?"saving…":"active"}):n?(0,b.jsx)("span",{className:"rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-muted-foreground",children:"not installed"}):null]}),(0,b.jsx)("p",{className:"text-xs leading-relaxed text-muted-foreground",children:k?.description??("headless"===c?"Subprocess per call. Lower RAM, faster cold start, no permission dialogs.":"Persistent terminal sessions you can attach to for visual debug.")}),n&&(0,b.jsxs)("p",{className:"mt-1 text-[10px] leading-relaxed text-amber-300/80",children:["Install: macOS ",(0,b.jsx)("code",{children:"brew install tmux"})," · Ubuntu ",(0,b.jsx)("code",{children:"apt install tmux"})," · Fedora ",(0,b.jsx)("code",{children:"dnf install tmux"}),". Restart the daemon afterwards."]})]},c)})}),(0,b.jsxs)("p",{className:"mt-3 text-[11px] text-muted-foreground",children:["Tip: set ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"CHORUS_TRANSPORT=tmux"})," in your environment to override per-shell without changing this setting."]})]})}function S(a){return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(v,{icon:(0,b.jsx)(j,{className:"h-4 w-4"}),title:"Sandbox & first-call permissions",subtitle:"What can chorus-spawned reviewers do on this machine? Pick a profile, toggle prompt auto-approval, choose whether to allow outbound network.",children:(0,b.jsxs)("a",{href:"/settings/permissions",className:"inline-flex items-center gap-2 rounded-md border border-primary/40 bg-primary/5 px-3 py-2 text-sm font-medium text-primary transition hover:bg-primary/10",children:["Open Permissions page",(0,b.jsx)("span",{"aria-hidden":!0,children:"→"})]})}),(0,b.jsx)(R,{}),(0,b.jsx)(z,{}),(0,b.jsx)(P,{}),(0,b.jsxs)("div",{className:"mt-12 flex items-start gap-2 rounded-lg border border-amber-500/40 bg-amber-500/10 px-4 py-3 text-sm text-amber-100",role:"note",children:[(0,b.jsx)(i.Clock,{className:"mt-0.5 h-4 w-4 shrink-0 text-amber-400"}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-semibold",children:"Coming in v0.8 — preview only"}),(0,b.jsx)("p",{className:"mt-1 text-xs leading-relaxed text-amber-100/80",children:"The sections below show planned controls. They're not wired to the daemon yet — interaction is disabled. The YAML toggle at the top of the page already exposes the schema if you're curious."})]})]}),(0,b.jsx)(N,{...a})]})}function T({yaml:a}){return(0,b.jsxs)(n.Card,{className:"overflow-hidden bg-card p-0",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between border-b border-border px-4 py-2.5",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)(d.Code2,{className:"h-3.5 w-3.5 text-primary"}),(0,b.jsx)("span",{className:"text-[11px] font-medium uppercase tracking-wider text-foreground",children:"settings.yaml"}),(0,b.jsx)(m.Badge,{variant:"outline",className:"border-border font-mono text-[10px]",children:"~/.chorus/settings.yaml"})]}),(0,b.jsxs)("div",{className:"flex items-center gap-2 text-[10px] text-muted-foreground",children:[(0,b.jsx)(O.Eye,{className:"h-3 w-3"}),"live-rendered from form state"]})]}),(0,b.jsx)("textarea",{value:a,readOnly:!0,spellCheck:!1,className:"block min-h-[520px] w-full resize-none border-0 bg-background px-5 py-4 font-mono text-[12px] leading-relaxed text-foreground/90 focus:outline-none"}),(0,b.jsxs)("div",{className:"flex items-center justify-between border-t border-border px-4 py-2.5 text-[11px] text-muted-foreground",children:[(0,b.jsxs)("span",{children:["Same shape that"," ",(0,b.jsx)("span",{className:"font-mono text-foreground/80",children:"mm.update_settings"})," ","accepts as a patch."]}),(0,b.jsx)("button",{type:"button",className:"rounded-md border border-border bg-card px-2 py-1 text-[10px] text-muted-foreground transition hover:text-foreground",children:"Copy"})]})]})}a.s(["default",0,function(){let[a,e]=(0,c.useState)("form"),[i,j]=(0,c.useState)(3),[k,l]=(0,c.useState)(r),[m,n]=(0,c.useState)(s),[o,p]=(0,c.useState)(["~/dev","~/work","/tmp/chorus-sandbox"]),[t,v]=(0,c.useState)(""),[w,x]=(0,c.useState)("claude-code"),[y,z]=(0,c.useState)("2.00"),[A,B]=(0,c.useState)("unanimous"),[C,D]=(0,c.useState)(""),[E,F]=(0,c.useState)(!0),[G,H]=(0,c.useState)("local"),[I,J]=(0,c.useState)("idle"),K=(0,c.useMemo)(()=>{var a;let b,c,d;return b=(a={maxConcurrent:i,driverPolicies:k,reviewerPolicies:m,allowedDirs:o,defaultDriver:w,defaultCostCap:y,defaultThreshold:A,mcpEnabled:E,webhookUrl:C}).allowedDirs.map(a=>` - ${a}`).join("\n"),c=q.map(b=>` ${b.id.replace("-","_")}: ${a.driverPolicies[b.id]}`).join("\n"),d=q.map(b=>` ${b.id.replace("-","_")}: ${a.reviewerPolicies[b.id]}`).join("\n"),`# Chorus workspace settings
2
- # Edit here, or via the Form tab, or via mm.update_settings from any MCP client.
3
-
4
- concurrency:
5
- max_concurrent_chats: ${a.maxConcurrent}
6
-
7
- permissions:
8
- driver:
9
- ${c}
10
- reviewer:
11
- ${d}
12
-
13
- allowed_directories:
14
- ${b}
15
-
16
- defaults:
17
- driver: ${a.defaultDriver}
18
- agreement_threshold: ${a.defaultThreshold}
19
- cost_cap_usd: ${a.defaultCostCap}
20
- on_error: fallback
21
-
22
- notifications:
23
- mcp_enabled: ${a.mcpEnabled}
24
- webhook_url: ${a.webhookUrl?`"${a.webhookUrl}"`:'""'}
25
- `},[i,k,m,o,w,y,A,E,C]);return(0,b.jsx)(g.AppShell,{children:(0,b.jsxs)("div",{className:"mx-auto w-full max-w-6xl px-4 py-6 sm:px-6 sm:py-8 md:px-8 md:py-10",children:[(0,b.jsx)(h.PageHeader,{eyebrow:"Settings",title:"Workspace",subtitle:"Defaults applied to every chat. Templates can override these per-run. The MCP server can read & patch this config — your main Claude can configure Chorus for you.",action:(0,b.jsxs)("div",{className:"flex rounded-md border border-border bg-card p-0.5",children:[(0,b.jsxs)("button",{type:"button",onClick:()=>e("form"),className:`flex items-center gap-1.5 rounded-sm px-3 py-1.5 text-xs font-medium transition ${"form"===a?"bg-primary/15 text-foreground":"text-muted-foreground hover:text-foreground"}`,children:[(0,b.jsx)(f,{className:"h-3.5 w-3.5"}),"Form"]}),(0,b.jsxs)("button",{type:"button",onClick:()=>e("yaml"),className:`flex items-center gap-1.5 rounded-sm px-3 py-1.5 text-xs font-medium transition ${"yaml"===a?"bg-primary/15 text-foreground":"text-muted-foreground hover:text-foreground"}`,children:[(0,b.jsx)(d.Code2,{className:"h-3.5 w-3.5"}),"YAML"]})]})}),"yaml"===a?(0,b.jsx)(T,{yaml:K}):(0,b.jsx)(S,{maxConcurrent:i,setMaxConcurrent:j,driverPolicies:k,reviewerPolicies:m,cyclePolicy:function(a,b){"driver"===a?l(a=>({...a,[b]:u(a[b])})):n(a=>({...a,[b]:u(a[b])}))},allowedDirs:o,setAllowedDirs:p,newDir:t,setNewDir:v,addDir:function(){let a=t.trim();!a||o.includes(a)||(p(b=>[...b,a]),v(""))},defaultDriver:w,setDefaultDriver:x,defaultCostCap:y,setDefaultCostCap:z,defaultThreshold:A,setDefaultThreshold:B,webhookUrl:C,setWebhookUrl:D,mcpEnabled:E,setMcpEnabled:F,privacyTier:G,setPrivacyTier:H,webhookTestState:I,testWebhook:function(){"running"!==I&&(J("running"),setTimeout(()=>{J(C.startsWith("https://")?"ok":"fail"),setTimeout(()=>J("idle"),2200)},1100))}})]})})}],20788)}];
26
-
27
- //# sourceMappingURL=src_app_settings_page_tsx_0h9v7dr._.js.map