@chorus-aidlc/chorus 0.16.4 → 0.17.0

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 (435) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +420 -420
  3. package/.next/standalone/.next/app-path-routes-manifest.json +53 -53
  4. package/.next/standalone/.next/build-manifest.json +5 -5
  5. package/.next/standalone/.next/prerender-manifest.json +45 -45
  6. package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page.js +1 -1
  7. package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page.js +1 -1
  10. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page.js +1 -1
  12. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js +2 -2
  14. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page.js +2 -2
  17. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page.js +2 -2
  19. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js +2 -2
  21. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js +2 -2
  24. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page_client-reference-manifest.js +1 -1
  26. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js +1 -1
  27. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page.js +2 -2
  30. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js +1 -1
  32. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js +1 -1
  35. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/(dashboard)/projects/page.js +1 -1
  38. package/.next/standalone/.next/server/app/(dashboard)/projects/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/(dashboard)/projects/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/(dashboard)/settings/page.js +2 -2
  41. package/.next/standalone/.next/server/app/(dashboard)/settings/page.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
  43. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  45. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  46. package/.next/standalone/.next/server/app/admin/companies/[uuid]/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/admin/companies/new/page_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/admin/companies/new.html +2 -2
  49. package/.next/standalone/.next/server/app/admin/companies/new.rsc +1 -1
  50. package/.next/standalone/.next/server/app/admin/companies/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/admin/companies.html +2 -2
  52. package/.next/standalone/.next/server/app/admin/companies.rsc +1 -1
  53. package/.next/standalone/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/admin.html +2 -2
  55. package/.next/standalone/.next/server/app/admin.rsc +1 -1
  56. package/.next/standalone/.next/server/app/api/admin/companies/[uuid]/route_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/api/admin/companies/route_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/api/admin/login/route_client-reference-manifest.js +1 -1
  59. package/.next/standalone/.next/server/app/api/admin/session/route_client-reference-manifest.js +1 -1
  60. package/.next/standalone/.next/server/app/api/agent-connections/route.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/api/agent-connections/route_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/api/agents/[uuid]/route_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route.js +1 -1
  64. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/api/agents/route_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/api/api-keys/[uuid]/route_client-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/app/api/api-keys/route_client-reference-manifest.js +1 -1
  69. package/.next/standalone/.next/server/app/api/auth/callback/route_client-reference-manifest.js +1 -1
  70. package/.next/standalone/.next/server/app/api/auth/check-default/route_client-reference-manifest.js +1 -1
  71. package/.next/standalone/.next/server/app/api/auth/company-oidc/route_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/api/auth/default-login/route_client-reference-manifest.js +1 -1
  73. package/.next/standalone/.next/server/app/api/auth/identify/route_client-reference-manifest.js +1 -1
  74. package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  75. package/.next/standalone/.next/server/app/api/auth/me/route_client-reference-manifest.js +1 -1
  76. package/.next/standalone/.next/server/app/api/auth/sync-token/route_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/api/comments/route.js +1 -1
  78. package/.next/standalone/.next/server/app/api/comments/route.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/api/comments/route_client-reference-manifest.js +1 -1
  80. package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route.js.nft.json +1 -1
  81. package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route_client-reference-manifest.js +1 -1
  82. package/.next/standalone/.next/server/app/api/daemon/control/route_client-reference-manifest.js +1 -1
  83. package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route_client-reference-manifest.js +1 -1
  85. package/.next/standalone/.next/server/app/api/daemon/execution-state/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/daemon/execution-state/route_client-reference-manifest.js +1 -1
  87. package/.next/standalone/.next/server/app/api/daemon/executions/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/daemon/executions/route_client-reference-manifest.js +1 -1
  89. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route.js +1 -1
  90. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route_client-reference-manifest.js +1 -1
  92. package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route_client-reference-manifest.js +1 -1
  94. package/.next/standalone/.next/server/app/api/daemon/resume/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/daemon/resume/route_client-reference-manifest.js +1 -1
  96. package/.next/standalone/.next/server/app/api/daemon/transcript/route.js +1 -1
  97. package/.next/standalone/.next/server/app/api/daemon/transcript/route.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/api/daemon/transcript/route_client-reference-manifest.js +1 -1
  99. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js +1 -1
  100. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route_client-reference-manifest.js +1 -1
  102. package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route_client-reference-manifest.js +1 -1
  104. package/.next/standalone/.next/server/app/api/daemon-directory-requests/route.js.nft.json +1 -1
  105. package/.next/standalone/.next/server/app/api/daemon-directory-requests/route_client-reference-manifest.js +1 -1
  106. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route.js +1 -1
  107. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route.js.nft.json +1 -1
  108. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route_client-reference-manifest.js +1 -1
  109. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route.js +1 -1
  110. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route.js.nft.json +1 -1
  111. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route_client-reference-manifest.js +1 -1
  112. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route.js +1 -1
  113. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route_client-reference-manifest.js +1 -1
  115. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route.js +1 -1
  116. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route.js.nft.json +1 -1
  117. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route_client-reference-manifest.js +1 -1
  118. package/.next/standalone/.next/server/app/api/daemon-sessions/route.js +1 -1
  119. package/.next/standalone/.next/server/app/api/daemon-sessions/route.js.nft.json +1 -1
  120. package/.next/standalone/.next/server/app/api/daemon-sessions/route_client-reference-manifest.js +1 -1
  121. package/.next/standalone/.next/server/app/api/documents/[uuid]/route_client-reference-manifest.js +1 -1
  122. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route.js +1 -1
  123. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route_client-reference-manifest.js +1 -1
  125. package/.next/standalone/.next/server/app/api/events/notifications/route.js +1 -1
  126. package/.next/standalone/.next/server/app/api/events/notifications/route.js.nft.json +1 -1
  127. package/.next/standalone/.next/server/app/api/events/notifications/route_client-reference-manifest.js +1 -1
  128. package/.next/standalone/.next/server/app/api/events/route.js +1 -1
  129. package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
  130. package/.next/standalone/.next/server/app/api/events/route_client-reference-manifest.js +1 -1
  131. package/.next/standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  132. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route.js +1 -1
  133. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route.js.nft.json +1 -1
  134. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route_client-reference-manifest.js +1 -1
  135. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route.js +1 -1
  136. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route_client-reference-manifest.js +1 -1
  138. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route.js +1 -1
  139. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route_client-reference-manifest.js +1 -1
  141. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route.js +1 -1
  142. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route_client-reference-manifest.js +1 -1
  144. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route.js +1 -1
  145. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route_client-reference-manifest.js +1 -1
  147. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route.js +1 -1
  148. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route.js.nft.json +1 -1
  149. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route_client-reference-manifest.js +1 -1
  150. package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route_client-reference-manifest.js +1 -1
  152. package/.next/standalone/.next/server/app/api/ideas/conversational/route.js +1 -1
  153. package/.next/standalone/.next/server/app/api/ideas/conversational/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/ideas/conversational/route_client-reference-manifest.js +1 -1
  155. package/.next/standalone/.next/server/app/api/mcp/route.js +4 -4
  156. package/.next/standalone/.next/server/app/api/mcp/route.js.nft.json +1 -1
  157. package/.next/standalone/.next/server/app/api/mcp/route_client-reference-manifest.js +1 -1
  158. package/.next/standalone/.next/server/app/api/me/assignments/route.js +1 -1
  159. package/.next/standalone/.next/server/app/api/me/assignments/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/me/assignments/route_client-reference-manifest.js +1 -1
  161. package/.next/standalone/.next/server/app/api/mentionables/route.js +1 -1
  162. package/.next/standalone/.next/server/app/api/mentionables/route.js.nft.json +1 -1
  163. package/.next/standalone/.next/server/app/api/mentionables/route_client-reference-manifest.js +1 -1
  164. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route.js +1 -1
  165. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route.js.nft.json +1 -1
  166. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route_client-reference-manifest.js +1 -1
  167. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route.js +1 -1
  168. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route.js.nft.json +1 -1
  169. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route_client-reference-manifest.js +1 -1
  170. package/.next/standalone/.next/server/app/api/notifications/preferences/route.js +1 -1
  171. package/.next/standalone/.next/server/app/api/notifications/preferences/route.js.nft.json +1 -1
  172. package/.next/standalone/.next/server/app/api/notifications/preferences/route_client-reference-manifest.js +1 -1
  173. package/.next/standalone/.next/server/app/api/notifications/read-all/route.js +1 -1
  174. package/.next/standalone/.next/server/app/api/notifications/read-all/route.js.nft.json +1 -1
  175. package/.next/standalone/.next/server/app/api/notifications/read-all/route_client-reference-manifest.js +1 -1
  176. package/.next/standalone/.next/server/app/api/notifications/route.js +1 -1
  177. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  178. package/.next/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  179. package/.next/standalone/.next/server/app/api/notifications/unread-count/route.js +1 -1
  180. package/.next/standalone/.next/server/app/api/notifications/unread-count/route.js.nft.json +1 -1
  181. package/.next/standalone/.next/server/app/api/notifications/unread-count/route_client-reference-manifest.js +1 -1
  182. package/.next/standalone/.next/server/app/api/project-groups/[uuid]/dashboard/route_client-reference-manifest.js +1 -1
  183. package/.next/standalone/.next/server/app/api/project-groups/[uuid]/route_client-reference-manifest.js +1 -1
  184. package/.next/standalone/.next/server/app/api/project-groups/route_client-reference-manifest.js +1 -1
  185. package/.next/standalone/.next/server/app/api/project-visits/pin/route_client-reference-manifest.js +1 -1
  186. package/.next/standalone/.next/server/app/api/project-visits/route_client-reference-manifest.js +1 -1
  187. package/.next/standalone/.next/server/app/api/project-visits/visit/route_client-reference-manifest.js +1 -1
  188. package/.next/standalone/.next/server/app/api/projects/[uuid]/activity/route_client-reference-manifest.js +1 -1
  189. package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route_client-reference-manifest.js +1 -1
  191. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js +1 -1
  192. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js.nft.json +1 -1
  193. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route_client-reference-manifest.js +1 -1
  194. package/.next/standalone/.next/server/app/api/projects/[uuid]/documents/route_client-reference-manifest.js +1 -1
  195. package/.next/standalone/.next/server/app/api/projects/[uuid]/group/route_client-reference-manifest.js +1 -1
  196. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route.js +1 -1
  197. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route_client-reference-manifest.js +1 -1
  199. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route.js +1 -1
  200. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route.js.nft.json +1 -1
  201. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route_client-reference-manifest.js +1 -1
  202. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/[proposalUuid]/validate/route_client-reference-manifest.js +1 -1
  203. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/route_client-reference-manifest.js +1 -1
  204. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/summary/route_client-reference-manifest.js +1 -1
  205. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route.js +1 -1
  206. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route.js.nft.json +1 -1
  207. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route_client-reference-manifest.js +1 -1
  208. package/.next/standalone/.next/server/app/api/projects/[uuid]/route_client-reference-manifest.js +1 -1
  209. package/.next/standalone/.next/server/app/api/projects/[uuid]/stats/route_client-reference-manifest.js +1 -1
  210. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route.js +1 -1
  211. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route.js.nft.json +1 -1
  212. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route_client-reference-manifest.js +1 -1
  213. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route.js +1 -1
  214. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route.js.nft.json +1 -1
  215. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route_client-reference-manifest.js +1 -1
  216. package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route.js.nft.json +1 -1
  217. package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route_client-reference-manifest.js +1 -1
  218. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  219. package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  220. package/.next/standalone/.next/server/app/api/proposals/[uuid]/approve/route_client-reference-manifest.js +1 -1
  221. package/.next/standalone/.next/server/app/api/proposals/[uuid]/close/route_client-reference-manifest.js +1 -1
  222. package/.next/standalone/.next/server/app/api/proposals/[uuid]/reject/route_client-reference-manifest.js +1 -1
  223. package/.next/standalone/.next/server/app/api/proposals/[uuid]/revoke/route_client-reference-manifest.js +1 -1
  224. package/.next/standalone/.next/server/app/api/proposals/[uuid]/route_client-reference-manifest.js +1 -1
  225. package/.next/standalone/.next/server/app/api/references/[uuid]/route_client-reference-manifest.js +1 -1
  226. package/.next/standalone/.next/server/app/api/references/route_client-reference-manifest.js +1 -1
  227. package/.next/standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  228. package/.next/standalone/.next/server/app/api/session/route_client-reference-manifest.js +1 -1
  229. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route.js +1 -1
  230. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route.js.nft.json +1 -1
  231. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route_client-reference-manifest.js +1 -1
  232. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route.js +1 -1
  233. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route.js.nft.json +1 -1
  234. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route_client-reference-manifest.js +1 -1
  235. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route.js +1 -1
  236. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route.js.nft.json +1 -1
  237. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route_client-reference-manifest.js +1 -1
  238. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route.js +1 -1
  239. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route.js.nft.json +1 -1
  240. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route_client-reference-manifest.js +1 -1
  241. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route.js +1 -1
  242. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route.js.nft.json +1 -1
  243. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route_client-reference-manifest.js +1 -1
  244. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route.js +1 -1
  245. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route.js.nft.json +1 -1
  246. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route_client-reference-manifest.js +1 -1
  247. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route.js +1 -1
  248. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route.js.nft.json +1 -1
  249. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route_client-reference-manifest.js +1 -1
  250. package/.next/standalone/.next/server/app/index.html +2 -2
  251. package/.next/standalone/.next/server/app/index.rsc +1 -1
  252. package/.next/standalone/.next/server/app/login/admin/page_client-reference-manifest.js +1 -1
  253. package/.next/standalone/.next/server/app/login/admin.html +2 -2
  254. package/.next/standalone/.next/server/app/login/admin.rsc +1 -1
  255. package/.next/standalone/.next/server/app/login/callback/page_client-reference-manifest.js +1 -1
  256. package/.next/standalone/.next/server/app/login/callback.html +2 -2
  257. package/.next/standalone/.next/server/app/login/callback.rsc +1 -1
  258. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  259. package/.next/standalone/.next/server/app/login/pick-workspace/page_client-reference-manifest.js +1 -1
  260. package/.next/standalone/.next/server/app/login/pick-workspace.html +2 -2
  261. package/.next/standalone/.next/server/app/login/pick-workspace.rsc +1 -1
  262. package/.next/standalone/.next/server/app/login.html +2 -2
  263. package/.next/standalone/.next/server/app/login.rsc +1 -1
  264. package/.next/standalone/.next/server/app/onboarding/page.js +2 -2
  265. package/.next/standalone/.next/server/app/onboarding/page.js.nft.json +1 -1
  266. package/.next/standalone/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  267. package/.next/standalone/.next/server/app/onboarding.html +2 -2
  268. package/.next/standalone/.next/server/app/onboarding.rsc +2 -2
  269. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  270. package/.next/standalone/.next/server/app/projects.html +2 -2
  271. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  272. package/.next/standalone/.next/server/app/settings.html +2 -2
  273. package/.next/standalone/.next/server/app/settings.rsc +3 -3
  274. package/.next/standalone/.next/server/app-paths-manifest.json +53 -53
  275. package/.next/standalone/.next/server/chunks/{5205.js → 1114.js} +1 -1
  276. package/.next/standalone/.next/server/chunks/1318.js +1 -1
  277. package/.next/standalone/.next/server/chunks/1437.js +1 -0
  278. package/.next/standalone/.next/server/chunks/1559.js +2 -2
  279. package/.next/standalone/.next/server/chunks/2572.js +1 -1
  280. package/.next/standalone/.next/server/chunks/2961.js +1 -1
  281. package/.next/standalone/.next/server/chunks/{9793.js → 3045.js} +1 -1
  282. package/.next/standalone/.next/server/chunks/3831.js +37 -0
  283. package/.next/standalone/.next/server/chunks/4827.js +1 -1
  284. package/.next/standalone/.next/server/chunks/5245.js +1 -1
  285. package/.next/standalone/.next/server/chunks/{4394.js → 5706.js} +1 -1
  286. package/.next/standalone/.next/server/chunks/6113.js +1 -1
  287. package/.next/standalone/.next/server/chunks/6207.js +1 -1
  288. package/.next/standalone/.next/server/chunks/6515.js +2 -2
  289. package/.next/standalone/.next/server/chunks/679.js +1 -1
  290. package/.next/standalone/.next/server/chunks/7368.js +1 -1
  291. package/.next/standalone/.next/server/chunks/7530.js +1 -1
  292. package/.next/standalone/.next/server/chunks/8454.js +1 -1
  293. package/.next/standalone/.next/server/chunks/920.js +1 -1
  294. package/.next/standalone/.next/server/chunks/9213.js +1 -1
  295. package/.next/standalone/.next/server/chunks/9378.js +1 -1
  296. package/.next/standalone/.next/server/chunks/9449.js +1 -0
  297. package/.next/standalone/.next/server/chunks/9458.js +1 -0
  298. package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  299. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  300. package/.next/standalone/.next/server/pages/404.html +2 -2
  301. package/.next/standalone/.next/server/pages/500.html +1 -1
  302. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  303. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  304. package/.next/standalone/.next/static/chunks/{11595.a6268c75ca8a2163.js → 11595.bbe40924d18958bf.js} +1 -1
  305. package/.next/standalone/.next/static/chunks/18139-e6ef4b5869593f8e.js +1 -0
  306. package/.next/standalone/.next/static/chunks/28856-ef2cb58fbd404ef9.js +1 -0
  307. package/.next/standalone/.next/static/chunks/{31308-fda6febfb2882a28.js → 31308-bb4a97b3f39c22dd.js} +1 -1
  308. package/.next/standalone/.next/static/chunks/{33456.16ff7edf00137539.js → 33456.5499eb8e892b110a.js} +1 -1
  309. package/.next/standalone/.next/static/chunks/{4860.9e06848eb531e667.js → 4860.be77046fb2b3a2bd.js} +1 -1
  310. package/.next/standalone/.next/static/chunks/66873-e3be53f41b3f2255.js +1 -0
  311. package/.next/standalone/.next/static/chunks/70303-aec3d52ad87602a3.js +1 -0
  312. package/.next/standalone/.next/static/chunks/76201-83b26515f85ce37c.js +1 -0
  313. package/.next/standalone/.next/static/chunks/78917-a8a8dff98857c045.js +1 -0
  314. package/.next/standalone/.next/static/chunks/97663-9c3ae4fd60b353db.js +1 -0
  315. package/.next/standalone/.next/static/chunks/{99373.81b79c91858f9099.js → 99373.111493dc260a2a04.js} +1 -1
  316. package/.next/standalone/.next/static/chunks/app/(dashboard)/{layout-b742c51c0a764daf.js → layout-40fe7d026c5a7c6d.js} +1 -1
  317. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/page-87d4d0fe90fca28c.js +1 -0
  318. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-1206abaee85dc915.js +1 -0
  319. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/{page-425acbe9ade5fa83.js → page-474e494097c8945f.js} +1 -1
  320. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/page-e902b19328092ccf.js +1 -0
  321. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-f273288c3530aa0f.js +1 -0
  322. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/page-6568a7b08bf9a54b.js +1 -0
  323. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/page-fbd3c27b68666234.js +1 -0
  324. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/{page-58b48aa0a11603c3.js → page-15bb6e1696668512.js} +1 -1
  325. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/{page-286faced32c6133f.js → page-2bea97214b1595cc.js} +1 -1
  326. package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-2bf7ceee62b574c7.js +1 -0
  327. package/.next/standalone/.next/static/chunks/app/onboarding/{page-5c82cf3abd856301.js → page-540da64d7ba16dc7.js} +1 -1
  328. package/.next/standalone/.next/static/chunks/{webpack-4d1cc14b13e247b6.js → webpack-7cbb3ba6792f1fb3.js} +1 -1
  329. package/.next/standalone/package.json +1 -1
  330. package/.next/standalone/public/chorus-plugin/.claude-plugin/plugin.json +1 -1
  331. package/.next/standalone/public/chorus-plugin/bin/chorus-api.sh +44 -1
  332. package/.next/standalone/public/chorus-plugin/bin/on-session-start.sh +4 -3
  333. package/.next/standalone/public/chorus-plugin/bin/tests/test-mcp-cli-delegation.sh +244 -0
  334. package/.next/standalone/public/chorus-plugin/skills/brainstorm/SKILL.md +1 -1
  335. package/.next/standalone/public/chorus-plugin/skills/chorus/SKILL.md +19 -1
  336. package/.next/standalone/public/chorus-plugin/skills/chorus-cli/SKILL.md +57 -0
  337. package/.next/standalone/public/chorus-plugin/skills/develop/SKILL.md +2 -2
  338. package/.next/standalone/public/chorus-plugin/skills/docs/SKILL.md +1 -1
  339. package/.next/standalone/public/chorus-plugin/skills/idea/SKILL.md +1 -1
  340. package/.next/standalone/public/chorus-plugin/skills/openspec-aware/SKILL.md +85 -42
  341. package/.next/standalone/public/chorus-plugin/skills/orchestrate/SKILL.md +1 -1
  342. package/.next/standalone/public/chorus-plugin/skills/proposal/SKILL.md +2 -2
  343. package/.next/standalone/public/chorus-plugin/skills/quick-dev/SKILL.md +1 -1
  344. package/.next/standalone/public/chorus-plugin/skills/review/SKILL.md +1 -1
  345. package/.next/standalone/public/chorus-plugin/skills/yolo/SKILL.md +3 -3
  346. package/.next/standalone/public/dsh-credentials.sh +20 -127
  347. package/.next/standalone/public/install-codex.sh +21 -406
  348. package/.next/standalone/public/install-kiro.sh +20 -344
  349. package/.next/standalone/public/install-opencode.sh +20 -275
  350. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-brainstorm/SKILL.md +1 -1
  351. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-cli/SKILL.md +57 -0
  352. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-develop/SKILL.md +2 -2
  353. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-docs/SKILL.md +1 -1
  354. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-idea/SKILL.md +1 -1
  355. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-openspec-aware/SKILL.md +85 -42
  356. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-orchestrate/SKILL.md +1 -1
  357. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-proposal/SKILL.md +2 -2
  358. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-quick-dev/SKILL.md +1 -1
  359. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-review/SKILL.md +1 -1
  360. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-yolo/SKILL.md +3 -3
  361. package/.next/standalone/public/kiro-plugin/bin/chorus-api.sh +44 -1
  362. package/.next/standalone/public/kiro-plugin/bin/on-agent-spawn.sh +6 -4
  363. package/.next/standalone/public/kiro-plugin/manifest.txt +41 -0
  364. package/.next/standalone/public/skill/brainstorm-chorus/SKILL.md +1 -1
  365. package/.next/standalone/public/skill/chorus/SKILL.md +19 -1
  366. package/.next/standalone/public/skill/code-reviewer-chorus/SKILL.md +1 -1
  367. package/.next/standalone/public/skill/develop-chorus/SKILL.md +1 -1
  368. package/.next/standalone/public/skill/docs-chorus/SKILL.md +1 -1
  369. package/.next/standalone/public/skill/idea-chorus/SKILL.md +1 -1
  370. package/.next/standalone/public/skill/orchestrate-chorus/SKILL.md +1 -1
  371. package/.next/standalone/public/skill/proposal-chorus/SKILL.md +1 -1
  372. package/.next/standalone/public/skill/proposal-reviewer-chorus/SKILL.md +1 -1
  373. package/.next/standalone/public/skill/quick-dev-chorus/SKILL.md +1 -1
  374. package/.next/standalone/public/skill/review-chorus/SKILL.md +1 -1
  375. package/.next/standalone/public/skill/task-reviewer-chorus/SKILL.md +1 -1
  376. package/.next/standalone/public/skill/yolo-chorus/SKILL.md +1 -1
  377. package/.next/standalone/public/test-dsh-credentials.sh +22 -38
  378. package/.next/standalone/public/test-install-codex.sh +31 -79
  379. package/README.ja.md +2 -2
  380. package/README.ko.md +2 -2
  381. package/README.md +2 -2
  382. package/README.zh.md +2 -2
  383. package/chorus.mjs +35 -1
  384. package/cli/agent-backend-prompt.mjs +3 -2
  385. package/cli/agents.mjs +329 -0
  386. package/cli/chorus-client.mjs +69 -0
  387. package/cli/claude-spawner.mjs +4 -0
  388. package/cli/codex-spawner.mjs +11 -6
  389. package/cli/credentials.mjs +185 -3
  390. package/cli/daemon-agent.mjs +26 -2
  391. package/cli/daemon-config.mjs +27 -2
  392. package/cli/daemon-service.mjs +120 -33
  393. package/cli/daemon.mjs +128 -22
  394. package/cli/dsh-spawner.mjs +7 -0
  395. package/cli/init/adapters.mjs +137 -0
  396. package/cli/init/agent-type-map.mjs +60 -0
  397. package/cli/init/chorus-plugin-consts.mjs +16 -0
  398. package/cli/init/codex-mcp-config.mjs +183 -0
  399. package/cli/init/contracts.mjs +120 -0
  400. package/cli/init/detect.mjs +97 -0
  401. package/cli/init/file-template.mjs +248 -0
  402. package/cli/init/install-methods.mjs +508 -0
  403. package/cli/init/registry.mjs +74 -0
  404. package/cli/init/run-command.mjs +30 -0
  405. package/cli/init/select.mjs +111 -0
  406. package/cli/init/steps/credential-seed.mjs +751 -0
  407. package/cli/init/steps/daemon-setup.mjs +246 -0
  408. package/cli/init/steps/plugin-install.mjs +37 -0
  409. package/cli/init-args.mjs +137 -0
  410. package/cli/init.mjs +198 -0
  411. package/cli/kiro-spawner.mjs +4 -0
  412. package/cli/mcp-args.mjs +280 -0
  413. package/cli/mcp.mjs +164 -0
  414. package/cli/spawner-select.mjs +45 -2
  415. package/package.json +1 -1
  416. package/.next/standalone/.next/server/chunks/3594.js +0 -1
  417. package/.next/standalone/.next/server/chunks/5351.js +0 -33
  418. package/.next/standalone/.next/server/chunks/6667.js +0 -1
  419. package/.next/standalone/.next/server/chunks/6995.js +0 -1
  420. package/.next/standalone/.next/static/chunks/19887-b805e1dcee8c367b.js +0 -1
  421. package/.next/standalone/.next/static/chunks/29108-5a11eea003f4cc11.js +0 -1
  422. package/.next/standalone/.next/static/chunks/53073-a7ed20af6538a178.js +0 -1
  423. package/.next/standalone/.next/static/chunks/6603-e70ddeab6ad09c50.js +0 -1
  424. package/.next/standalone/.next/static/chunks/78917-1b59cbb806b3ecfc.js +0 -1
  425. package/.next/standalone/.next/static/chunks/82751-3e161e1d8dbda3ac.js +0 -1
  426. package/.next/standalone/.next/static/chunks/99366-425e9ef22e60e3e2.js +0 -1
  427. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/page-f636e00c28f425ea.js +0 -1
  428. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-c004f1a194af7fa5.js +0 -1
  429. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/page-fdd617457730a116.js +0 -1
  430. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-b9eb4e0692996657.js +0 -1
  431. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/page-d5b222f379b2e8ca.js +0 -1
  432. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/page-0a6c2d0e1b68e0e4.js +0 -1
  433. package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-1507a761e67c2aa9.js +0 -1
  434. /package/.next/standalone/.next/static/{6sHDgeKioa0SJR1MAbcYG → 0spgxl3lP26Fl1otd1D7R}/_buildManifest.js +0 -0
  435. /package/.next/standalone/.next/static/{6sHDgeKioa0SJR1MAbcYG → 0spgxl3lP26Fl1otd1D7R}/_ssgManifest.js +0 -0
package/cli/agents.mjs ADDED
@@ -0,0 +1,329 @@
1
+ // cli/agents.mjs
2
+ // `chorus agents` — manage this machine's configured agents (the ~/.chorus/daemon.json
3
+ // agents[]): `list` (default), `add` (detect + install plugin + seed creds — the flow
4
+ // formerly reached via `chorus init`, delegated to runInit), and `remove <name|uuid>`.
5
+ // Listing lets a user/agent discover the valid `CHORUS_AGENT_PROFILE` /
6
+ // `chorus mcp --agent <name|uuid>` values without hand-reading the JSON. The `cho_`
7
+ // API key is NEVER emitted by list/remove — not masked, omitted entirely.
8
+ //
9
+ // Peer of the other `chorus` subcommands (login / daemon / mcp); dispatched from
10
+ // chorus.mjs before the server boot path, so every `chorus agents …` help/list/remove
11
+ // path never starts the embedded PostgreSQL.
12
+
13
+ import { readFileSync } from "node:fs";
14
+ import { loginFilePath } from "./credentials.mjs";
15
+ import { updateDaemonConfig } from "./login.mjs";
16
+
17
+ /** Read + parse a JSON file, returning null on any error (missing/malformed). */
18
+ function readJsonSafe(path) {
19
+ try {
20
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
21
+ return parsed && typeof parsed === "object" ? parsed : null;
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+
27
+ /** A non-empty trimmed string, or undefined. */
28
+ function nonEmpty(value) {
29
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
30
+ }
31
+
32
+ /** Compact host for the table (host[:port] only — never userinfo); never throws. */
33
+ function hostOf(url) {
34
+ if (!url) return "";
35
+ try {
36
+ return new URL(url).host;
37
+ } catch {
38
+ return "";
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Safe url for machine (--json) output: the origin only (scheme://host[:port]).
44
+ * Strips any userinfo / path / query so an accidental credential embedded in the
45
+ * url can never surface. Returns null when absent or unparseable (never echoes
46
+ * the raw string). Defense-in-depth — the stored API key lives in a separate
47
+ * `apiKey` field this command never reads.
48
+ */
49
+ function originOf(url) {
50
+ if (!url) return null;
51
+ try {
52
+ return new URL(url).origin;
53
+ } catch {
54
+ return null;
55
+ }
56
+ }
57
+
58
+ /** Group help for `chorus agents` (list / add / remove). */
59
+ export function agentsHelpText(version = "") {
60
+ const v = version ? ` v${version}` : "";
61
+ return `\
62
+ Chorus${v} — manage this machine's configured agents
63
+
64
+ USAGE
65
+ chorus agents [list] List configured agents (name, UUID, backend)
66
+ chorus agents --json Machine-readable list (API keys never included)
67
+ chorus agents add [flags] Configure agent(s): detect, install plugin, seed
68
+ credentials (formerly \`chorus init\`; same flags —
69
+ see \`chorus agents add --help\`)
70
+ chorus agents remove <name|uuid> Remove a configured agent from ~/.chorus/daemon.json
71
+
72
+ Each listed UUID or name is a valid value for \`chorus mcp --agent <name|uuid>\` or the
73
+ CHORUS_AGENT_PROFILE environment variable. The API key is never printed.
74
+ `;
75
+ }
76
+
77
+ /**
78
+ * Build the redacted agent rows from a parsed daemon.json object.
79
+ * @param {Record<string, unknown>|null} file
80
+ * @returns {Array<{index:number, name?:string, uuid?:string, agentType?:string, url?:string, daemonWake?:unknown, flat?:boolean}>}
81
+ */
82
+ export function collectAgents(file) {
83
+ if (!file) return [];
84
+ const rows = [];
85
+ if (Array.isArray(file.agents)) {
86
+ file.agents.forEach((a, i) => {
87
+ if (a && typeof a === "object") {
88
+ rows.push({
89
+ index: i,
90
+ name: nonEmpty(a.agentName) ?? nonEmpty(a.name) ?? nonEmpty(a.label),
91
+ uuid: nonEmpty(a.agentUuid),
92
+ agentType: nonEmpty(a.agentType),
93
+ url: nonEmpty(a.url) ?? nonEmpty(file.url),
94
+ daemonWake: a.daemonWake,
95
+ });
96
+ }
97
+ });
98
+ }
99
+ // Flat single-agent config (no agents[]): synthesize one row from the
100
+ // deprecated top-level fields so it still shows up.
101
+ if (rows.length === 0 && (nonEmpty(file.apiKey) || nonEmpty(file.agentUuid))) {
102
+ rows.push({
103
+ index: 0,
104
+ name: nonEmpty(file.agentName),
105
+ uuid: nonEmpty(file.agentUuid),
106
+ agentType: nonEmpty(file.agent),
107
+ url: nonEmpty(file.url),
108
+ flat: true,
109
+ });
110
+ }
111
+ return rows;
112
+ }
113
+
114
+ /**
115
+ * List configured agents (the `chorus agents` / `chorus agents list` body).
116
+ * Returns an exit code (never calls process.exit).
117
+ * @param {string[]} argv flags after the (optional) `list` sub-verb.
118
+ * @param {object} [opts]
119
+ * @returns {number}
120
+ */
121
+ function listAgents(argv = [], opts = {}) {
122
+ const out = opts.stdout ?? process.stdout;
123
+ const err = opts.stderr ?? process.stderr;
124
+ const env = opts.env ?? process.env;
125
+ const readJson = opts.readJson ?? readJsonSafe;
126
+ const loginPath = opts.loginPath ?? loginFilePath();
127
+ const version = opts.version ?? "";
128
+
129
+ let json = false;
130
+ for (const tok of argv) {
131
+ if (tok === "--help" || tok === "-h") {
132
+ out.write(agentsHelpText(version));
133
+ return 0;
134
+ }
135
+ if (tok === "--json") {
136
+ json = true;
137
+ continue;
138
+ }
139
+ err.write(`error: unknown flag: ${tok}\n\n${agentsHelpText(version)}`);
140
+ return 2;
141
+ }
142
+
143
+ const rows = collectAgents(readJson(loginPath));
144
+ const active = nonEmpty(env.CHORUS_AGENT_PROFILE);
145
+ const isActive = (r) => active !== undefined && (r.uuid === active || r.name === active);
146
+
147
+ if (json) {
148
+ // Redacted objects — the apiKey is intentionally never included.
149
+ const payload = rows.map((r) => ({
150
+ index: r.index,
151
+ name: r.name ?? null,
152
+ uuid: r.uuid ?? null,
153
+ agentType: r.agentType ?? null,
154
+ url: originOf(r.url),
155
+ daemonWake: r.daemonWake ?? null,
156
+ active: isActive(r),
157
+ }));
158
+ out.write(`${JSON.stringify(payload, null, 2)}\n`);
159
+ return 0;
160
+ }
161
+
162
+ if (rows.length === 0) {
163
+ out.write(
164
+ `No agents configured in ${loginPath}.\n` +
165
+ "Run `chorus agents add` (or `chorus login`) to add one.\n",
166
+ );
167
+ return 0;
168
+ }
169
+
170
+ out.write(`Agents in ${loginPath}:\n`);
171
+ for (const r of rows) {
172
+ const mark = isActive(r) ? "* " : " ";
173
+ const name = r.name ?? "(unnamed)";
174
+ const uuid = r.uuid ?? "(no uuid)";
175
+ const bits = [r.agentType ?? "?"];
176
+ if (r.daemonWake === false) bits.push("wake:off");
177
+ const host = hostOf(r.url);
178
+ if (host) bits.push(host);
179
+ out.write(`${mark}[${r.index}] ${name} ${uuid} (${bits.join(", ")})\n`);
180
+ }
181
+ if (active) {
182
+ out.write(
183
+ rows.some(isActive)
184
+ ? `\n* = active (CHORUS_AGENT_PROFILE="${active}")\n`
185
+ : `\n(note: CHORUS_AGENT_PROFILE="${active}" is set but matches no agent above)\n`,
186
+ );
187
+ }
188
+ out.write(
189
+ "\nPass a UUID or name to `chorus mcp --agent <name|uuid>` or set CHORUS_AGENT_PROFILE.\n" +
190
+ "API keys are never shown.\n",
191
+ );
192
+ return 0;
193
+ }
194
+
195
+ /** Usage for `chorus agents remove`. */
196
+ function removeHelpText() {
197
+ return "USAGE\n chorus agents remove <name|uuid> Remove a configured agent from ~/.chorus/daemon.json\n";
198
+ }
199
+
200
+ /**
201
+ * `chorus agents remove <name|uuid>` — drop the matching `agents[]` entry.
202
+ * Merge-safe: rewrites daemon.json replacing `agents[]` with the filtered array,
203
+ * preserving every other agent and all top-level fields. The API key is NEVER
204
+ * printed. dependency-injected (readJson/writeConfig/loginPath) for tests.
205
+ * @param {string[]} argv args after the `remove` word (argv[0] = target).
206
+ * @param {object} [opts]
207
+ * @returns {number}
208
+ */
209
+ export function removeAgent(argv = [], opts = {}) {
210
+ const out = opts.stdout ?? process.stdout;
211
+ const err = opts.stderr ?? process.stderr;
212
+ const readJson = opts.readJson ?? readJsonSafe;
213
+ const loginPath = opts.loginPath ?? loginFilePath();
214
+ const writeConfig = opts.writeConfig ?? ((partial) => updateDaemonConfig(partial, { path: loginPath }));
215
+
216
+ const first = argv[0];
217
+ if (first === "--help" || first === "-h") {
218
+ out.write(removeHelpText());
219
+ return 0;
220
+ }
221
+ const target = nonEmpty(first);
222
+ if (!target) {
223
+ err.write("error: `chorus agents remove` requires an agent name or UUID.\n" + removeHelpText());
224
+ return 2;
225
+ }
226
+
227
+ const file = readJson(loginPath);
228
+ const agents = file && Array.isArray(file.agents) ? file.agents.filter((a) => a && typeof a === "object") : [];
229
+ const keysOf = (a) => [a.agentUuid, a.agentName, a.label, a.name].map(nonEmpty).filter((k) => k !== undefined);
230
+ const matches = [];
231
+ agents.forEach((a, i) => {
232
+ if (keysOf(a).includes(target)) matches.push(i);
233
+ });
234
+
235
+ if (matches.length === 0) {
236
+ err.write(`error: no configured agent matches "${target}" in ${loginPath}.\n`);
237
+ if (agents.length) {
238
+ err.write("Configured agents:\n");
239
+ agents.forEach((a, i) =>
240
+ err.write(` [${i}] ${nonEmpty(a.agentName) ?? "(unnamed)"} ${nonEmpty(a.agentUuid) ?? "(no uuid)"}\n`),
241
+ );
242
+ } else {
243
+ err.write("(none configured)\n");
244
+ }
245
+ return 1;
246
+ }
247
+ if (matches.length > 1) {
248
+ err.write(
249
+ `error: "${target}" is ambiguous — it matches ${matches.length} agents. Use the agent UUID to disambiguate.\n`,
250
+ );
251
+ return 2;
252
+ }
253
+
254
+ const idx = matches[0];
255
+ const removed = agents[idx];
256
+ const remaining = agents.filter((_, i) => i !== idx);
257
+ // Replace agents[] wholesale (updateDaemonConfig shallow-merges the patch, so a
258
+ // new `agents` array overwrites the old one) — preserves every top-level field.
259
+ writeConfig({ agents: remaining });
260
+
261
+ out.write(
262
+ `Removed agent ${nonEmpty(removed.agentName) ?? "(unnamed)"} (${nonEmpty(removed.agentUuid) ?? "no uuid"}) ` +
263
+ `from ${loginPath}. ${remaining.length} agent(s) remain.\n`,
264
+ );
265
+ // dsh: $DSH_HOME/.env holds a single shared url+key (not per-agent) and is left
266
+ // untouched. dsh maps to the "offline" daemon agentType bucket — surface the note there.
267
+ if (nonEmpty(removed.agentType) === "offline") {
268
+ out.write(
269
+ "Note: any dsh $DSH_HOME/.env credentials were left untouched (a single shared file) — clear them manually if needed.\n",
270
+ );
271
+ }
272
+ // Claude Code: `chorus agents add` may have written CHORUS_* into the user-global
273
+ // ~/.claude/settings.json env block. Reverse cleanup is out of scope — leave it in place
274
+ // (a later re-add overwrites it idempotently) but tell the operator, mirroring the dsh note.
275
+ if (nonEmpty(removed.agentType) === "claude-code") {
276
+ out.write(
277
+ "Note: any CHORUS_* keys written into ~/.claude/settings.json were left untouched — clear them manually if needed.\n",
278
+ );
279
+ }
280
+ // Codex: `chorus agents add` may have written CHORUS_* into ~/.codex/.env (and a keyless
281
+ // [mcp_servers.chorus] block that references CHORUS_API_KEY via bearer_token_env_var in
282
+ // ~/.codex/config.toml — no literal key). Reverse cleanup is out of scope — leave it, tell the operator.
283
+ if (nonEmpty(removed.agentType) === "codex") {
284
+ out.write(
285
+ "Note: any CHORUS_* env written into ~/.codex/.env " +
286
+ "(and the keyless [mcp_servers.chorus] block in ~/.codex/config.toml, which references the key via bearer_token_env_var) were left untouched — clear them manually if needed.\n",
287
+ );
288
+ }
289
+ return 0;
290
+ }
291
+
292
+ /**
293
+ * Run `chorus agents [list|add|remove] …`. Dispatches the sub-verb:
294
+ * (none) / `list` → list configured agents
295
+ * `add [flags]` → runInit (the flow formerly reached via `chorus init`)
296
+ * `remove <n|uuid>` → removeAgent
297
+ * A group-level `--help`/`-h` prints the group usage. Never boots the server.
298
+ * Returns an exit code (or a Promise thereof for `add`).
299
+ * @param {string[]} argv argv AFTER the `agents` word.
300
+ * @param {object} [opts]
301
+ * @returns {number | Promise<number>}
302
+ */
303
+ export function runAgents(argv = [], opts = {}) {
304
+ const out = opts.stdout ?? process.stdout;
305
+ const err = opts.stderr ?? process.stderr;
306
+ const version = opts.version ?? "";
307
+ const first = argv[0];
308
+
309
+ if (first === "--help" || first === "-h") {
310
+ out.write(agentsHelpText(version));
311
+ return 0;
312
+ }
313
+ if (first === "add") {
314
+ // Delegate to the existing init flow (renamed entry). Dynamic import keeps the
315
+ // list/remove paths from loading the heavier init subsystem.
316
+ const runInit = opts.runInit ?? (async (a, o) => (await import("./init.mjs")).runInit(a, o));
317
+ return runInit(argv.slice(1), { version });
318
+ }
319
+ if (first === "remove") {
320
+ return removeAgent(argv.slice(1), opts);
321
+ }
322
+ // An unknown positional sub-verb (not `list`, not a flag) is a usage error.
323
+ if (first !== undefined && first !== "list" && !first.startsWith("-")) {
324
+ err.write(`error: unknown \`chorus agents\` subcommand: ${first}\n\n${agentsHelpText(version)}`);
325
+ return 2;
326
+ }
327
+ // Bare `chorus agents`, explicit `list`, or list flags (--json/--help handled inside).
328
+ return listAgents(first === "list" ? argv.slice(1) : argv, opts);
329
+ }
@@ -76,6 +76,56 @@ export class ChorusClient {
76
76
  }
77
77
  }
78
78
 
79
+ /**
80
+ * Like {@link callTool} but returns the tool result's text content VERBATIM,
81
+ * never JSON-parsed — the byte-faithful form the `chorus mcp call` CLI prints
82
+ * to stay a drop-in for `chorus-api.sh mcp-tool` (which emits
83
+ * `.result.content[].text`). `text` is the newline-join of every `content[]`
84
+ * block whose `type` is `text`. Lazy-connects; retries once on a stateless
85
+ * 404 / session-expired error, mirroring {@link callTool}.
86
+ * @param {string} name
87
+ * @param {Record<string, unknown>} [args]
88
+ * @returns {Promise<{ isError: boolean, text: string }>}
89
+ */
90
+ async callToolRaw(name, args = {}) {
91
+ if (!this.client || this.status !== "connected") await this.connect();
92
+ try {
93
+ return await this.#doCallToolRaw(name, args);
94
+ } catch (err) {
95
+ if (this.#isSessionExpired(err)) {
96
+ this.logger.warn("MCP session expired, reconnecting...");
97
+ this.status = "reconnecting";
98
+ this.client = null;
99
+ this.transport = null;
100
+ await this.connect();
101
+ return await this.#doCallToolRaw(name, args);
102
+ }
103
+ throw err;
104
+ }
105
+ }
106
+
107
+ /**
108
+ * List the tools this connection's API key is permitted to see. Lazy-connects;
109
+ * retries once on a stateless 404 / session-expired error.
110
+ * @returns {Promise<Array<{ name: string, description: string }>>}
111
+ */
112
+ async listTools() {
113
+ if (!this.client || this.status !== "connected") await this.connect();
114
+ try {
115
+ return await this.#doListTools();
116
+ } catch (err) {
117
+ if (this.#isSessionExpired(err)) {
118
+ this.logger.warn("MCP session expired, reconnecting...");
119
+ this.status = "reconnecting";
120
+ this.client = null;
121
+ this.transport = null;
122
+ await this.connect();
123
+ return await this.#doListTools();
124
+ }
125
+ throw err;
126
+ }
127
+ }
128
+
79
129
  async disconnect() {
80
130
  if (this.client) {
81
131
  try {
@@ -89,6 +139,25 @@ export class ChorusClient {
89
139
  this.status = "disconnected";
90
140
  }
91
141
 
142
+ /** @param {string} name @param {Record<string, unknown>} args */
143
+ async #doCallToolRaw(name, args) {
144
+ if (!this.client) throw new Error("MCP client not connected");
145
+ const result = await this.client.callTool({ name, arguments: args });
146
+ const blocks = /** @type {Array<{type:string,text?:string}>} */ (result.content ?? []);
147
+ const text = blocks
148
+ .filter((c) => c.type === "text")
149
+ .map((c) => c.text ?? "")
150
+ .join("\n");
151
+ return { isError: Boolean(result.isError), text };
152
+ }
153
+
154
+ async #doListTools() {
155
+ if (!this.client) throw new Error("MCP client not connected");
156
+ const result = await this.client.listTools();
157
+ const tools = /** @type {Array<{name:string,description?:string}>} */ (result.tools ?? []);
158
+ return tools.map((t) => ({ name: t.name, description: t.description ?? "" }));
159
+ }
160
+
92
161
  /** @param {string} name @param {Record<string, unknown>} args */
93
162
  async #doCallTool(name, args) {
94
163
  if (!this.client) throw new Error("MCP client not connected");
@@ -329,6 +329,10 @@ export class ClaudeSpawner {
329
329
  if (this.creds) {
330
330
  if (this.creds.url) childEnv.CHORUS_URL = this.creds.url;
331
331
  if (this.creds.apiKey) childEnv.CHORUS_API_KEY = this.creds.apiKey;
332
+ // Identity profile for the woken session — its hooks/skills pass this to
333
+ // `chorus mcp --agent`, which resolves the key from ~/.chorus/daemon.json.
334
+ if (this.creds.agentUuid || this.creds.agentName)
335
+ childEnv.CHORUS_AGENT_PROFILE = this.creds.agentUuid || this.creds.agentName;
332
336
  }
333
337
 
334
338
  return new Promise((resolve) => {
@@ -14,12 +14,13 @@
14
14
  // `resume <thread_id>`. (serde: ThreadEvent tag="type", rename="thread.started";
15
15
  // ThreadStartedEvent.thread_id: String — codex-rs/exec/src/exec_events.rs.)
16
16
  // • No `--mcp-config`: Codex reads MCP servers from the user's ~/.codex/config.toml.
17
- // The Chorus MCP key there is USER-MANAGED: the installer writes a LITERAL Bearer
18
- // header and Codex does NOT expand ${VAR} inside http_headers, so the CHORUS_API_KEY
19
- // the daemon exports does NOT reach Codex's MCP auth. The daemon still exports
20
- // CHORUS_URL / CHORUS_API_KEY into the child env but only for the plugin's shell
21
- // tooling (chorus-api.sh / SessionStart hooks), never argv and never Codex MCP.
22
- // (Multi-agent: two Codex agents with different keys each need their own CODEX_HOME.)
17
+ // `chorus agents add` writes [mcp_servers.chorus] with bearer_token_env_var =
18
+ // "CHORUS_API_KEY" a KEYLESS reference (no literal key in config.toml), and Codex
19
+ // resolves that env var into `Authorization: Bearer <key>` at connect. So the
20
+ // CHORUS_API_KEY the daemon exports into the child env below DOES reach Codex's MCP
21
+ // auth (as well as the plugin's shell tooling chorus-api.sh / SessionStart hooks);
22
+ // never argv. (Multi-agent: two Codex agents with different keys each need their own
23
+ // CODEX_HOME so their config.toml + ~/.codex/.env don't collide.)
23
24
  // • Permission is a SANDBOX mode, not a tool allowlist.
24
25
  //
25
26
  // Reuses claude-spawner's platform-neutral helpers: parseNdjsonChunk (NDJSON
@@ -276,6 +277,10 @@ export class CodexSpawner {
276
277
  if (this.creds) {
277
278
  if (this.creds.url) childEnv.CHORUS_URL = this.creds.url;
278
279
  if (this.creds.apiKey) childEnv.CHORUS_API_KEY = this.creds.apiKey;
280
+ // Identity profile for the woken session — its hooks/skills pass this to
281
+ // `chorus mcp --agent`, which resolves the key from ~/.chorus/daemon.json.
282
+ if (this.creds.agentUuid || this.creds.agentName)
283
+ childEnv.CHORUS_AGENT_PROFILE = this.creds.agentUuid || this.creds.agentName;
279
284
  }
280
285
 
281
286
  return new Promise((resolve) => {
@@ -159,13 +159,26 @@ export function resolveCredentials(flags = {}, deps = {}) {
159
159
  if (url && apiKey) return { url, apiKey, source: "env" };
160
160
  }
161
161
 
162
- // 3. Login file (~/.chorus/daemon.json)
162
+ // 3. Login file (~/.chorus/daemon.json): the flat top-level url/apiKey, else the
163
+ // first agents[] entry. The flat top-level agent config is DEPRECATED — `chorus
164
+ // init` now writes credentials only into agents[] — so fall back to agents[0]
165
+ // so this single-credential resolver (install/daemon-setup gate, legacy flat
166
+ // daemon) still resolves from an agents[]-only daemon.json.
163
167
  tried.push(`login file (${loginPath}, run \`chorus login\`)`);
164
168
  {
165
169
  const file = readJson(loginPath);
166
170
  if (file) {
167
- const url = nonEmpty(file.url);
168
- const apiKey = nonEmpty(file.apiKey);
171
+ let url = nonEmpty(file.url);
172
+ let apiKey = nonEmpty(file.apiKey);
173
+ if (!(url && apiKey) && Array.isArray(file.agents)) {
174
+ const a0 = file.agents.find(
175
+ (a) => a && typeof a === "object" && nonEmpty(a.url) && nonEmpty(a.apiKey),
176
+ );
177
+ if (a0) {
178
+ url = nonEmpty(a0.url);
179
+ apiKey = nonEmpty(a0.apiKey);
180
+ }
181
+ }
169
182
  if (url && apiKey) return { url, apiKey, source: "login-file" };
170
183
  }
171
184
  }
@@ -194,3 +207,172 @@ export function resolveCredentials(flags = {}, deps = {}) {
194
207
  " • login: chorus login (persists to ~/.chorus/daemon.json)\n"
195
208
  );
196
209
  }
210
+
211
+ /**
212
+ * @typedef {Object} McpCredentials
213
+ * @property {string} url
214
+ * @property {string} apiKey
215
+ * @property {string} label Diagnostic label for the acting identity ("flag" /
216
+ * "env" / a `~/.chorus/daemon.json` agent name/label / the flat-resolution source).
217
+ */
218
+
219
+ /**
220
+ * Resolve the url + `cho_` API key AND the acting agent identity for the
221
+ * `chorus mcp` command group. Unlike `resolveCredentials`, this understands the
222
+ * multi-agent `agents[]` model and refuses to guess which agent to act as.
223
+ *
224
+ * PROFILE identity (AWS-CLI style): a caller can name WHICH agent to act as by
225
+ * `--agent <name|uuid>` (explicit flag) or the `CHORUS_AGENT_PROFILE` env var,
226
+ * and this resolves that agent's key from `~/.chorus/daemon.json` — the secret
227
+ * never has to be threaded through the caller's environment. A profile matches
228
+ * an `agents[]` entry by its `agentUuid`, `agentName`, or the back-compat
229
+ * `label`/`name` aliases (exact). Ambiguous (matches >1 entry) → hard error.
230
+ *
231
+ * Precedence (owner decision: PREFER profile, fall back to url+key mode when no
232
+ * profile resolves — the key stays written in daemon.json, url+key is the
233
+ * fallback so the CLI-absent curl path still works):
234
+ * 1. Explicit `--agent <name|uuid>` flag → deliberate profile selection from
235
+ * `agents[]`, PREFERRED over an explicit url+key pair (no match → hard error
236
+ * listing agents). With NO `agents[]` it rides along an explicit `--url/--api-key`
237
+ * pair (else the env pair) as the label, else it is a usage error.
238
+ * 2. Explicit `--url` + `--api-key` flags (no `--agent`) → used directly
239
+ * (identity is explicit); a `CHORUS_AGENT_PROFILE` name rides along as the label.
240
+ * 3. `CHORUS_AGENT_PROFILE` env → ambient profile selection from `agents[]`.
241
+ * A match wins over the url+key env pair; NO match falls through (the
242
+ * profile "doesn't exist" → url-mode fallback), an ambiguous match throws.
243
+ * 4. `CHORUS_URL` + `CHORUS_API_KEY` env pair → used directly (url-mode
244
+ * fallback / legacy plugin-hook path); a profile name rides as the label.
245
+ * 5. Exactly one agent in `agents[]` + nothing specified → that agent.
246
+ * 6. More than one agent + nothing specified → hard error (never pick
247
+ * silently), listing the available agents.
248
+ * 7. No `agents[]` → flat resolution via `resolveCredentials`.
249
+ *
250
+ * Each selected agent's `url`/`apiKey` merges over the top-level per-field
251
+ * defaults (`resolveCredentialDefaults`), so an agent that omits a field
252
+ * inherits it.
253
+ *
254
+ * This never imports `cli/daemon-config.mjs` (which imports THIS module) — it
255
+ * reads `agents[]` directly to stay cycle-free; only url/apiKey/label matter for
256
+ * MCP, so per-agent agentType/permissionMode validation is intentionally skipped.
257
+ *
258
+ * @param {{ url?: string, apiKey?: string, agent?: string }} flags
259
+ * @param {ResolveDeps} [deps]
260
+ * @returns {McpCredentials}
261
+ * @throws {Error} on ambiguity, a missing `--agent` label, or nothing resolvable.
262
+ */
263
+ export function resolveMcpCredentials(flags = {}, deps = {}) {
264
+ const env = deps.env ?? process.env;
265
+ const readJson = deps.readJson ?? readJsonSafe;
266
+ const loginPath = deps.loginPath ?? loginFilePath();
267
+ const flagAgent = nonEmpty(flags.agent);
268
+ const envProfile = nonEmpty(env.CHORUS_AGENT_PROFILE);
269
+ // The profile name a caller asked for, whatever its source — used as the
270
+ // diagnostic label when creds ultimately come from explicit flags / the env pair.
271
+ const wanted = flagAgent ?? envProfile;
272
+
273
+ const envPair = () => {
274
+ const url = nonEmpty(env.CHORUS_URL);
275
+ const apiKey = nonEmpty(env.CHORUS_API_KEY);
276
+ return url && apiKey ? { url, apiKey } : null;
277
+ };
278
+ const flagPair = () => {
279
+ const url = nonEmpty(flags.url);
280
+ const apiKey = nonEmpty(flags.apiKey);
281
+ return url && apiKey ? { url, apiKey } : null;
282
+ };
283
+
284
+ // Read agents[] once and pre-resolve every entry (label, its match keys, and
285
+ // its effective url/apiKey merged over the top-level per-field defaults).
286
+ const file = readJson(loginPath);
287
+ const agentEntries =
288
+ file && Array.isArray(file.agents)
289
+ ? file.agents.filter((a) => a && typeof a === "object")
290
+ : [];
291
+ const hasAgents = agentEntries.length > 0;
292
+ const defaults = hasAgents ? resolveCredentialDefaults(flags, deps) : { url: undefined, apiKey: undefined };
293
+ const labelOf = (entry, i) =>
294
+ nonEmpty(entry.agentName) ?? nonEmpty(entry.label) ?? nonEmpty(entry.name) ?? `agents[${i}]`;
295
+ const resolved = agentEntries.map((entry, i) => ({
296
+ label: labelOf(entry, i),
297
+ // A profile may name an entry by its uuid, its display name, or the
298
+ // back-compat label/name aliases.
299
+ keys: [entry.agentUuid, entry.agentName, entry.label, entry.name]
300
+ .map((k) => nonEmpty(k))
301
+ .filter((k) => k !== undefined),
302
+ url: nonEmpty(entry.url) ?? defaults.url,
303
+ apiKey: nonEmpty(entry.apiKey) ?? defaults.apiKey,
304
+ }));
305
+ const labels = resolved.map((a) => a.label).join(", ");
306
+ const pick = (a) => {
307
+ if (!a.url || !a.apiKey) {
308
+ throw new Error(
309
+ `Agent "${a.label}" in ${loginPath} is missing a url or apiKey (and no top-level default supplies it).`,
310
+ );
311
+ }
312
+ return { url: a.url, apiKey: a.apiKey, label: a.label };
313
+ };
314
+ const matchesFor = (name) => resolved.filter((a) => a.keys.includes(name));
315
+ const selectOrThrow = (name, source) => {
316
+ const matches = matchesFor(name);
317
+ if (matches.length === 1) return pick(matches[0]);
318
+ if (matches.length > 1) {
319
+ throw new Error(
320
+ `${source} "${name}" is ambiguous in ${loginPath} — it matches ${matches.length} agents ` +
321
+ `(${matches.map((m) => m.label).join(", ")}). Use the agent UUID to disambiguate.`,
322
+ );
323
+ }
324
+ return null; // no match
325
+ };
326
+
327
+ // 1. Explicit --agent flag: a deliberate profile selection — PREFERRED over an
328
+ // explicit url+key flag pair (owner: "prefer profile"). With NO agents[] to
329
+ // match, it rides an explicit flag pair (else the env pair), using the name
330
+ // as the diagnostic label; with neither it is a usage error.
331
+ if (flagAgent) {
332
+ if (hasAgents) {
333
+ const hit = selectOrThrow(flagAgent, "--agent");
334
+ if (hit) return hit;
335
+ throw new Error(`--agent "${flagAgent}" not found in ${loginPath} agents[]. Available: ${labels}.`);
336
+ }
337
+ const pair = flagPair() ?? envPair();
338
+ if (pair) return { url: pair.url, apiKey: pair.apiKey, label: flagAgent };
339
+ throw new Error(
340
+ `--agent "${flagAgent}" was given but ${loginPath} declares no agents[]. ` +
341
+ `Remove --agent, or configure an agents[] list.`,
342
+ );
343
+ }
344
+
345
+ // 2. Explicit url+key flag pair (no --agent) — identity is explicit.
346
+ {
347
+ const pair = flagPair();
348
+ if (pair) return { url: pair.url, apiKey: pair.apiKey, label: wanted ?? "flag" };
349
+ }
350
+
351
+ // 3. CHORUS_AGENT_PROFILE env: ambient profile selection. A match wins over the
352
+ // url+key env pair; a no-match falls through to url-mode (profile "doesn't
353
+ // exist"); an ambiguous match throws.
354
+ if (envProfile && hasAgents) {
355
+ const hit = selectOrThrow(envProfile, "CHORUS_AGENT_PROFILE");
356
+ if (hit) return hit;
357
+ // no match → fall through to the url-mode fallback below
358
+ }
359
+
360
+ // 4. Env pair (url-mode fallback). Carry the profile name as the label if set.
361
+ {
362
+ const pair = envPair();
363
+ if (pair) return { url: pair.url, apiKey: pair.apiKey, label: wanted ?? "env" };
364
+ }
365
+
366
+ // 5/6. agents[] with nothing specified: auto-single, else hard error.
367
+ if (hasAgents) {
368
+ if (resolved.length === 1) return pick(resolved[0]);
369
+ throw new Error(
370
+ `Multiple agents are configured in ${loginPath} (${labels}). ` +
371
+ `Specify which one to act as with --agent <name|uuid> or CHORUS_AGENT_PROFILE.`,
372
+ );
373
+ }
374
+
375
+ // 7. No agents[] → flat resolution (throws the detailed "could not resolve" error).
376
+ const flat = resolveCredentials(flags, deps);
377
+ return { url: flat.url, apiKey: flat.apiKey, label: flat.source };
378
+ }