@chorus-aidlc/chorus 0.15.1 → 0.16.2

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 (444) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +394 -393
  3. package/.next/standalone/.next/app-path-routes-manifest.json +46 -46
  4. package/.next/standalone/.next/build-manifest.json +5 -5
  5. package/.next/standalone/.next/prerender-manifest.json +21 -21
  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 +2 -2
  10. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page.js +2 -2
  13. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page.js.nft.json +1 -1
  14. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js +2 -2
  16. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page.js +2 -2
  19. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page.js.nft.json +1 -1
  20. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page.js +2 -2
  22. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page_client-reference-manifest.js +1 -1
  24. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js +2 -2
  25. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js +2 -2
  28. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page_client-reference-manifest.js +1 -1
  30. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js +2 -2
  31. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page_client-reference-manifest.js +1 -1
  33. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page.js +2 -2
  34. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page_client-reference-manifest.js +1 -1
  36. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js +1 -1
  37. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js +1 -1
  40. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/(dashboard)/projects/page.js +1 -1
  43. package/.next/standalone/.next/server/app/(dashboard)/projects/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/(dashboard)/projects/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/(dashboard)/settings/page.js +2 -2
  46. package/.next/standalone/.next/server/app/(dashboard)/settings/page.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  50. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  51. package/.next/standalone/.next/server/app/admin/companies/[uuid]/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/admin/companies/new/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/admin/companies/new.html +2 -2
  54. package/.next/standalone/.next/server/app/admin/companies/new.rsc +2 -2
  55. package/.next/standalone/.next/server/app/admin/companies/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/admin/companies.html +2 -2
  57. package/.next/standalone/.next/server/app/admin/companies.rsc +2 -2
  58. package/.next/standalone/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  59. package/.next/standalone/.next/server/app/admin.html +2 -2
  60. package/.next/standalone/.next/server/app/admin.rsc +2 -2
  61. package/.next/standalone/.next/server/app/api/admin/companies/[uuid]/route_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/api/admin/companies/route_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/app/api/admin/login/route_client-reference-manifest.js +1 -1
  64. package/.next/standalone/.next/server/app/api/admin/session/route_client-reference-manifest.js +1 -1
  65. package/.next/standalone/.next/server/app/api/agent-connections/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/agent-connections/route_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/api/agents/[uuid]/route_client-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route.js +1 -1
  69. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route_client-reference-manifest.js +1 -1
  71. package/.next/standalone/.next/server/app/api/agents/route_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/api/api-keys/[uuid]/route_client-reference-manifest.js +1 -1
  73. package/.next/standalone/.next/server/app/api/api-keys/route_client-reference-manifest.js +1 -1
  74. package/.next/standalone/.next/server/app/api/auth/callback/route_client-reference-manifest.js +1 -1
  75. package/.next/standalone/.next/server/app/api/auth/check-default/route_client-reference-manifest.js +1 -1
  76. package/.next/standalone/.next/server/app/api/auth/company-oidc/route_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/api/auth/default-login/route_client-reference-manifest.js +1 -1
  78. package/.next/standalone/.next/server/app/api/auth/identify/route_client-reference-manifest.js +1 -1
  79. package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  80. package/.next/standalone/.next/server/app/api/auth/me/route_client-reference-manifest.js +1 -1
  81. package/.next/standalone/.next/server/app/api/auth/sync-token/route_client-reference-manifest.js +1 -1
  82. package/.next/standalone/.next/server/app/api/comments/route.js +1 -1
  83. package/.next/standalone/.next/server/app/api/comments/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/comments/route_client-reference-manifest.js +1 -1
  85. package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route_client-reference-manifest.js +1 -1
  87. package/.next/standalone/.next/server/app/api/daemon/control/route.js +1 -1
  88. package/.next/standalone/.next/server/app/api/daemon/control/route_client-reference-manifest.js +1 -1
  89. package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route_client-reference-manifest.js +1 -1
  91. package/.next/standalone/.next/server/app/api/daemon/execution-state/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/daemon/execution-state/route_client-reference-manifest.js +1 -1
  93. package/.next/standalone/.next/server/app/api/daemon/executions/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/daemon/executions/route_client-reference-manifest.js +1 -1
  95. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route.js +1 -1
  96. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route_client-reference-manifest.js +1 -1
  98. package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route.js +1 -1
  99. package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route.js.nft.json +1 -1
  100. package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route_client-reference-manifest.js +1 -1
  101. package/.next/standalone/.next/server/app/api/daemon/resume/route.js +1 -1
  102. package/.next/standalone/.next/server/app/api/daemon/resume/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/daemon/resume/route_client-reference-manifest.js +1 -1
  104. package/.next/standalone/.next/server/app/api/daemon/transcript/route.js +1 -1
  105. package/.next/standalone/.next/server/app/api/daemon/transcript/route.js.nft.json +1 -1
  106. package/.next/standalone/.next/server/app/api/daemon/transcript/route_client-reference-manifest.js +1 -1
  107. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js +1 -1
  108. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js.nft.json +1 -1
  109. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route_client-reference-manifest.js +1 -1
  110. package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route.js.nft.json +1 -1
  111. package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route_client-reference-manifest.js +1 -1
  112. package/.next/standalone/.next/server/app/api/daemon-directory-requests/route.js.nft.json +1 -1
  113. package/.next/standalone/.next/server/app/api/daemon-directory-requests/route_client-reference-manifest.js +1 -1
  114. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route.js +1 -1
  115. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route_client-reference-manifest.js +1 -1
  117. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route.js +1 -1
  118. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route.js.nft.json +1 -1
  119. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route_client-reference-manifest.js +1 -1
  120. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route.js +1 -1
  121. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route.js.nft.json +1 -1
  122. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route_client-reference-manifest.js +1 -1
  123. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route.js +1 -1
  124. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route_client-reference-manifest.js +1 -1
  126. package/.next/standalone/.next/server/app/api/daemon-sessions/route.js +1 -1
  127. package/.next/standalone/.next/server/app/api/daemon-sessions/route.js.nft.json +1 -1
  128. package/.next/standalone/.next/server/app/api/daemon-sessions/route_client-reference-manifest.js +1 -1
  129. package/.next/standalone/.next/server/app/api/documents/[uuid]/route_client-reference-manifest.js +1 -1
  130. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route.js +1 -1
  131. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route.js.nft.json +1 -1
  132. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route_client-reference-manifest.js +1 -1
  133. package/.next/standalone/.next/server/app/api/events/notifications/route.js +1 -1
  134. package/.next/standalone/.next/server/app/api/events/notifications/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/events/notifications/route_client-reference-manifest.js +1 -1
  136. package/.next/standalone/.next/server/app/api/events/route.js +1 -1
  137. package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
  138. package/.next/standalone/.next/server/app/api/events/route_client-reference-manifest.js +1 -1
  139. package/.next/standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  140. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route.js +1 -1
  141. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route_client-reference-manifest.js +1 -1
  143. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route.js +1 -1
  144. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route.js.nft.json +1 -1
  145. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route_client-reference-manifest.js +1 -1
  146. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route.js +1 -1
  147. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route_client-reference-manifest.js +1 -1
  149. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route.js +1 -1
  150. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route_client-reference-manifest.js +1 -1
  152. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route.js +1 -1
  153. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route_client-reference-manifest.js +1 -1
  155. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route.js +1 -1
  156. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route.js.nft.json +1 -1
  157. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route_client-reference-manifest.js +1 -1
  158. package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route.js.nft.json +1 -1
  159. package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route_client-reference-manifest.js +1 -1
  160. package/.next/standalone/.next/server/app/api/ideas/conversational/route.js +1 -1
  161. package/.next/standalone/.next/server/app/api/ideas/conversational/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/ideas/conversational/route_client-reference-manifest.js +1 -1
  163. package/.next/standalone/.next/server/app/api/mcp/route.js +2 -2
  164. package/.next/standalone/.next/server/app/api/mcp/route.js.nft.json +1 -1
  165. package/.next/standalone/.next/server/app/api/mcp/route_client-reference-manifest.js +1 -1
  166. package/.next/standalone/.next/server/app/api/me/assignments/route.js +1 -1
  167. package/.next/standalone/.next/server/app/api/me/assignments/route.js.nft.json +1 -1
  168. package/.next/standalone/.next/server/app/api/me/assignments/route_client-reference-manifest.js +1 -1
  169. package/.next/standalone/.next/server/app/api/mentionables/route.js +1 -1
  170. package/.next/standalone/.next/server/app/api/mentionables/route.js.nft.json +1 -1
  171. package/.next/standalone/.next/server/app/api/mentionables/route_client-reference-manifest.js +1 -1
  172. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route.js +1 -1
  173. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route_client-reference-manifest.js +1 -1
  175. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route.js +1 -1
  176. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route.js.nft.json +1 -1
  177. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route_client-reference-manifest.js +1 -1
  178. package/.next/standalone/.next/server/app/api/notifications/preferences/route.js +1 -1
  179. package/.next/standalone/.next/server/app/api/notifications/preferences/route.js.nft.json +1 -1
  180. package/.next/standalone/.next/server/app/api/notifications/preferences/route_client-reference-manifest.js +1 -1
  181. package/.next/standalone/.next/server/app/api/notifications/read-all/route.js +1 -1
  182. package/.next/standalone/.next/server/app/api/notifications/read-all/route.js.nft.json +1 -1
  183. package/.next/standalone/.next/server/app/api/notifications/read-all/route_client-reference-manifest.js +1 -1
  184. package/.next/standalone/.next/server/app/api/notifications/route.js +1 -1
  185. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  186. package/.next/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  187. package/.next/standalone/.next/server/app/api/notifications/unread-count/route.js +1 -1
  188. package/.next/standalone/.next/server/app/api/notifications/unread-count/route.js.nft.json +1 -1
  189. package/.next/standalone/.next/server/app/api/notifications/unread-count/route_client-reference-manifest.js +1 -1
  190. package/.next/standalone/.next/server/app/api/project-groups/[uuid]/dashboard/route_client-reference-manifest.js +1 -1
  191. package/.next/standalone/.next/server/app/api/project-groups/[uuid]/route_client-reference-manifest.js +1 -1
  192. package/.next/standalone/.next/server/app/api/project-groups/route_client-reference-manifest.js +1 -1
  193. package/.next/standalone/.next/server/app/api/project-visits/pin/route_client-reference-manifest.js +1 -1
  194. package/.next/standalone/.next/server/app/api/project-visits/route_client-reference-manifest.js +1 -1
  195. package/.next/standalone/.next/server/app/api/project-visits/visit/route_client-reference-manifest.js +1 -1
  196. package/.next/standalone/.next/server/app/api/projects/[uuid]/activity/route_client-reference-manifest.js +1 -1
  197. package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route_client-reference-manifest.js +1 -1
  199. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js +1 -1
  200. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js.nft.json +1 -1
  201. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route_client-reference-manifest.js +1 -1
  202. package/.next/standalone/.next/server/app/api/projects/[uuid]/documents/route_client-reference-manifest.js +1 -1
  203. package/.next/standalone/.next/server/app/api/projects/[uuid]/group/route_client-reference-manifest.js +1 -1
  204. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route.js +1 -1
  205. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route.js.nft.json +1 -1
  206. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route_client-reference-manifest.js +1 -1
  207. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route.js +1 -1
  208. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route.js.nft.json +1 -1
  209. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route_client-reference-manifest.js +1 -1
  210. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/[proposalUuid]/validate/route_client-reference-manifest.js +1 -1
  211. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/route_client-reference-manifest.js +1 -1
  212. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/summary/route_client-reference-manifest.js +1 -1
  213. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route.js +1 -1
  214. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route.js.nft.json +1 -1
  215. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route_client-reference-manifest.js +1 -1
  216. package/.next/standalone/.next/server/app/api/projects/[uuid]/route_client-reference-manifest.js +1 -1
  217. package/.next/standalone/.next/server/app/api/projects/[uuid]/stats/route_client-reference-manifest.js +1 -1
  218. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route.js +1 -1
  219. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route.js.nft.json +1 -1
  220. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route_client-reference-manifest.js +1 -1
  221. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route.js +1 -1
  222. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route.js.nft.json +1 -1
  223. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route_client-reference-manifest.js +1 -1
  224. package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route.js.nft.json +1 -1
  225. package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route_client-reference-manifest.js +1 -1
  226. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  227. package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  228. package/.next/standalone/.next/server/app/api/proposals/[uuid]/approve/route_client-reference-manifest.js +1 -1
  229. package/.next/standalone/.next/server/app/api/proposals/[uuid]/close/route_client-reference-manifest.js +1 -1
  230. package/.next/standalone/.next/server/app/api/proposals/[uuid]/reject/route_client-reference-manifest.js +1 -1
  231. package/.next/standalone/.next/server/app/api/proposals/[uuid]/revoke/route_client-reference-manifest.js +1 -1
  232. package/.next/standalone/.next/server/app/api/proposals/[uuid]/route_client-reference-manifest.js +1 -1
  233. package/.next/standalone/.next/server/app/api/references/[uuid]/route_client-reference-manifest.js +1 -1
  234. package/.next/standalone/.next/server/app/api/references/route_client-reference-manifest.js +1 -1
  235. package/.next/standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  236. package/.next/standalone/.next/server/app/api/session/route_client-reference-manifest.js +1 -1
  237. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route.js +1 -1
  238. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route.js.nft.json +1 -1
  239. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route_client-reference-manifest.js +1 -1
  240. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route.js +1 -1
  241. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route.js.nft.json +1 -1
  242. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route_client-reference-manifest.js +1 -1
  243. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route.js +1 -1
  244. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route.js.nft.json +1 -1
  245. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route_client-reference-manifest.js +1 -1
  246. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route.js +1 -1
  247. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route.js.nft.json +1 -1
  248. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route_client-reference-manifest.js +1 -1
  249. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route.js +1 -1
  250. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route.js.nft.json +1 -1
  251. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route_client-reference-manifest.js +1 -1
  252. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route.js +1 -1
  253. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route.js.nft.json +1 -1
  254. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route_client-reference-manifest.js +1 -1
  255. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route.js +1 -1
  256. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route.js.nft.json +1 -1
  257. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route_client-reference-manifest.js +1 -1
  258. package/.next/standalone/.next/server/app/index.html +2 -2
  259. package/.next/standalone/.next/server/app/index.rsc +2 -2
  260. package/.next/standalone/.next/server/app/login/admin/page_client-reference-manifest.js +1 -1
  261. package/.next/standalone/.next/server/app/login/admin.html +2 -2
  262. package/.next/standalone/.next/server/app/login/admin.rsc +2 -2
  263. package/.next/standalone/.next/server/app/login/callback/page_client-reference-manifest.js +1 -1
  264. package/.next/standalone/.next/server/app/login/callback.html +2 -2
  265. package/.next/standalone/.next/server/app/login/callback.rsc +2 -2
  266. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  267. package/.next/standalone/.next/server/app/login/pick-workspace/page_client-reference-manifest.js +1 -1
  268. package/.next/standalone/.next/server/app/login/pick-workspace.html +2 -2
  269. package/.next/standalone/.next/server/app/login/pick-workspace.rsc +2 -2
  270. package/.next/standalone/.next/server/app/login.html +2 -2
  271. package/.next/standalone/.next/server/app/login.rsc +2 -2
  272. package/.next/standalone/.next/server/app/onboarding/page.js +2 -2
  273. package/.next/standalone/.next/server/app/onboarding/page.js.nft.json +1 -1
  274. package/.next/standalone/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  275. package/.next/standalone/.next/server/app/onboarding.html +2 -2
  276. package/.next/standalone/.next/server/app/onboarding.rsc +3 -3
  277. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  278. package/.next/standalone/.next/server/app/projects.html +2 -2
  279. package/.next/standalone/.next/server/app/projects.rsc +3 -3
  280. package/.next/standalone/.next/server/app/settings.html +2 -2
  281. package/.next/standalone/.next/server/app/settings.rsc +4 -4
  282. package/.next/standalone/.next/server/app-paths-manifest.json +46 -46
  283. package/.next/standalone/.next/server/chunks/1318.js +1 -1
  284. package/.next/standalone/.next/server/chunks/1559.js +2 -2
  285. package/.next/standalone/.next/server/chunks/2570.js +2 -2
  286. package/.next/standalone/.next/server/chunks/2572.js +1 -1
  287. package/.next/standalone/.next/server/chunks/2618.js +1 -1
  288. package/.next/standalone/.next/server/chunks/2961.js +1 -1
  289. package/.next/standalone/.next/server/chunks/3594.js +1 -0
  290. package/.next/standalone/.next/server/chunks/{2547.js → 4011.js} +3 -3
  291. package/.next/standalone/.next/server/chunks/4394.js +1 -0
  292. package/.next/standalone/.next/server/chunks/4827.js +1 -1
  293. package/.next/standalone/.next/server/chunks/5205.js +1 -0
  294. package/.next/standalone/.next/server/chunks/5245.js +1 -1
  295. package/.next/standalone/.next/server/chunks/{2282.js → 5351.js} +3 -3
  296. package/.next/standalone/.next/server/chunks/6113.js +1 -1
  297. package/.next/standalone/.next/server/chunks/6207.js +1 -1
  298. package/.next/standalone/.next/server/chunks/6506.js +3 -3
  299. package/.next/standalone/.next/server/chunks/6667.js +1 -0
  300. package/.next/standalone/.next/server/chunks/679.js +1 -1
  301. package/.next/standalone/.next/server/chunks/6995.js +1 -0
  302. package/.next/standalone/.next/server/chunks/7364.js +1 -1
  303. package/.next/standalone/.next/server/chunks/7368.js +1 -1
  304. package/.next/standalone/.next/server/chunks/7530.js +1 -1
  305. package/.next/standalone/.next/server/chunks/920.js +1 -1
  306. package/.next/standalone/.next/server/chunks/9213.js +1 -1
  307. package/.next/standalone/.next/server/chunks/9378.js +1 -1
  308. package/.next/standalone/.next/server/chunks/9793.js +1 -0
  309. package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  310. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  311. package/.next/standalone/.next/server/pages/404.html +2 -2
  312. package/.next/standalone/.next/server/pages/500.html +1 -1
  313. package/.next/standalone/.next/server/pages-manifest.json +1 -1
  314. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  315. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  316. package/.next/standalone/.next/static/chunks/11595.b6f8ad33572b32fe.js +1 -0
  317. package/.next/standalone/.next/static/chunks/19887-9f459ee9e8d0855f.js +1 -0
  318. package/.next/standalone/.next/static/chunks/29108-b9b232255811ffa8.js +1 -0
  319. package/.next/standalone/.next/static/chunks/{31308-bb4a97b3f39c22dd.js → 31308-fda6febfb2882a28.js} +1 -1
  320. package/.next/standalone/.next/static/chunks/33456.e8550ad410031e29.js +1 -0
  321. package/.next/standalone/.next/static/chunks/35432-ee83da56c49ef6f8.js +1 -0
  322. package/.next/standalone/.next/static/chunks/4860.b405fc235b36271b.js +1 -0
  323. package/.next/standalone/.next/static/chunks/53073-5fd399cb25a11740.js +1 -0
  324. package/.next/standalone/.next/static/chunks/6603-07faab08560f7ecd.js +1 -0
  325. package/.next/standalone/.next/static/chunks/66980-652990fcf3212c94.js +10 -0
  326. package/.next/standalone/.next/static/chunks/78155-db70d9684a1e77a2.js +1 -0
  327. package/.next/standalone/.next/static/chunks/78917-7354d3b6908da7d1.js +1 -0
  328. package/.next/standalone/.next/static/chunks/82751-de255af4418d53e4.js +1 -0
  329. package/.next/standalone/.next/static/chunks/94643-6d31df78aa3074b5.js +1 -0
  330. package/.next/standalone/.next/static/chunks/96170-75da13decdb6f73f.js +1 -0
  331. package/.next/standalone/.next/static/chunks/99366-425e9ef22e60e3e2.js +1 -0
  332. package/.next/standalone/.next/static/chunks/99373.9dce8f30802824fc.js +1 -0
  333. package/.next/standalone/.next/static/chunks/app/(dashboard)/layout-cea0bb3e3a295bea.js +1 -0
  334. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/page-007278623926490f.js +1 -0
  335. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-b6ecaf52f6b81ec7.js +1 -0
  336. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/{page-2c9d3f4c6e0ff807.js → page-82404154708e48a9.js} +1 -1
  337. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/page-f5a351c544ed23d7.js +1 -0
  338. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-3cd46bec9383b191.js +1 -0
  339. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/page-d5b222f379b2e8ca.js +1 -0
  340. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/{page-ed9415921188b4d3.js → page-6abc7d1785e2b999.js} +1 -1
  341. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/{page-c70af8cac7bdc483.js → page-7f87113e5d8bcf6e.js} +1 -1
  342. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/{page-715b000c156a080c.js → page-30ab1573c4bd466f.js} +1 -1
  343. package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-b21d4184d9ca0b25.js +1 -0
  344. package/.next/standalone/.next/static/chunks/app/onboarding/page-3b6c54f887108635.js +1 -0
  345. package/.next/standalone/.next/static/chunks/{webpack-e181cbbb1e041891.js → webpack-b54e0c78eded76be.js} +1 -1
  346. package/.next/standalone/.next/static/css/893d99a21153c9b0.css +1 -0
  347. package/.next/standalone/package.json +1 -1
  348. package/.next/standalone/public/chorus-plugin/.claude-plugin/plugin.json +1 -1
  349. package/.next/standalone/public/chorus-plugin/agents/code-reviewer.md +1 -1
  350. package/.next/standalone/public/chorus-plugin/agents/proposal-reviewer.md +1 -0
  351. package/.next/standalone/public/chorus-plugin/agents/task-reviewer.md +2 -0
  352. package/.next/standalone/public/chorus-plugin/skills/brainstorm/SKILL.md +1 -1
  353. package/.next/standalone/public/chorus-plugin/skills/chorus/SKILL.md +4 -3
  354. package/.next/standalone/public/chorus-plugin/skills/develop/SKILL.md +1 -1
  355. package/.next/standalone/public/chorus-plugin/skills/docs/SKILL.md +68 -0
  356. package/.next/standalone/public/chorus-plugin/skills/idea/SKILL.md +1 -1
  357. package/.next/standalone/public/chorus-plugin/skills/openspec-aware/SKILL.md +1 -1
  358. package/.next/standalone/public/chorus-plugin/skills/proposal/SKILL.md +1 -1
  359. package/.next/standalone/public/chorus-plugin/skills/quick-dev/SKILL.md +1 -1
  360. package/.next/standalone/public/chorus-plugin/skills/review/SKILL.md +1 -1
  361. package/.next/standalone/public/chorus-plugin/skills/yolo/SKILL.md +1 -1
  362. package/.next/standalone/public/install-kiro.sh +10 -7
  363. package/.next/standalone/public/kiro-plugin/.kiro/agents/chorus-code-reviewer.json +1 -1
  364. package/.next/standalone/public/kiro-plugin/.kiro/agents/chorus-proposal-reviewer.json +1 -1
  365. package/.next/standalone/public/kiro-plugin/.kiro/agents/chorus-task-reviewer.json +1 -1
  366. package/.next/standalone/public/kiro-plugin/.kiro/agents/chorus.json +1 -0
  367. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-brainstorm/SKILL.md +1 -1
  368. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-develop/SKILL.md +1 -1
  369. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-docs/SKILL.md +68 -0
  370. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-idea/SKILL.md +1 -1
  371. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-openspec-aware/SKILL.md +1 -1
  372. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-proposal/SKILL.md +1 -1
  373. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-quick-dev/SKILL.md +1 -1
  374. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-review/SKILL.md +1 -1
  375. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-yolo/SKILL.md +1 -1
  376. package/.next/standalone/public/kiro-plugin/.kiro/steering/chorus.md +3 -2
  377. package/.next/standalone/public/kiro-plugin/bin/chorus-api.sh +1 -1
  378. package/.next/standalone/public/skill/brainstorm-chorus/SKILL.md +1 -1
  379. package/.next/standalone/public/skill/chorus/SKILL.md +4 -3
  380. package/.next/standalone/public/skill/code-reviewer-chorus/SKILL.md +2 -2
  381. package/.next/standalone/public/skill/develop-chorus/SKILL.md +1 -1
  382. package/.next/standalone/public/skill/docs-chorus/SKILL.md +70 -0
  383. package/.next/standalone/public/skill/idea-chorus/SKILL.md +1 -1
  384. package/.next/standalone/public/skill/package.json +9 -5
  385. package/.next/standalone/public/skill/proposal-chorus/SKILL.md +1 -1
  386. package/.next/standalone/public/skill/proposal-reviewer-chorus/SKILL.md +2 -1
  387. package/.next/standalone/public/skill/quick-dev-chorus/SKILL.md +1 -1
  388. package/.next/standalone/public/skill/review-chorus/SKILL.md +1 -1
  389. package/.next/standalone/public/skill/task-reviewer-chorus/SKILL.md +2 -1
  390. package/.next/standalone/public/skill/yolo-chorus/SKILL.md +1 -1
  391. package/README.ja.md +31 -359
  392. package/README.ko.md +33 -360
  393. package/README.md +39 -367
  394. package/README.zh.md +36 -341
  395. package/cli/claude-spawner.mjs +15 -6
  396. package/cli/client-args.mjs +8 -0
  397. package/cli/codex-spawner.mjs +7 -3
  398. package/cli/control-handler.mjs +13 -3
  399. package/cli/credentials.mjs +41 -0
  400. package/cli/daemon-config.mjs +202 -1
  401. package/cli/daemon-install-config.mjs +38 -1
  402. package/cli/daemon-rest-client.mjs +11 -3
  403. package/cli/daemon.mjs +274 -11
  404. package/cli/event-router.mjs +17 -5
  405. package/cli/login.mjs +90 -2
  406. package/cli/prompts.mjs +116 -1
  407. package/cli/turn-reporter.mjs +5 -1
  408. package/cli/wake-queue.mjs +57 -35
  409. package/cli/waker.mjs +125 -36
  410. package/package.json +1 -1
  411. package/prisma/migrations/20260814101500_add_typed_assignment_provenance/migration.sql +2 -0
  412. package/prisma/schema.prisma +4 -2
  413. package/.next/standalone/.next/server/chunks/1114.js +0 -1
  414. package/.next/standalone/.next/server/chunks/1524.js +0 -1
  415. package/.next/standalone/.next/server/chunks/330.js +0 -1
  416. package/.next/standalone/.next/server/chunks/3525.js +0 -1
  417. package/.next/standalone/.next/server/chunks/4070.js +0 -1
  418. package/.next/standalone/.next/server/chunks/8540.js +0 -1
  419. package/.next/standalone/.next/static/chunks/11595.69e774e65ffda45f.js +0 -1
  420. package/.next/standalone/.next/static/chunks/18351-12dc856208d79e10.js +0 -1
  421. package/.next/standalone/.next/static/chunks/33456.48112aa459fd9c68.js +0 -1
  422. package/.next/standalone/.next/static/chunks/37938-0b9a2b891c04b166.js +0 -1
  423. package/.next/standalone/.next/static/chunks/4340-a33120fb742af57e.js +0 -1
  424. package/.next/standalone/.next/static/chunks/4860.496d21fc6db9e153.js +0 -1
  425. package/.next/standalone/.next/static/chunks/68326-61feeb2f6cddd338.js +0 -1
  426. package/.next/standalone/.next/static/chunks/72974-7e63b565a9ef443b.js +0 -1
  427. package/.next/standalone/.next/static/chunks/78917-f91904c6c2d12dab.js +0 -1
  428. package/.next/standalone/.next/static/chunks/80748-e971c5a5d6ef967d.js +0 -1
  429. package/.next/standalone/.next/static/chunks/80904-973284d1fe916c38.js +0 -1
  430. package/.next/standalone/.next/static/chunks/94426-39b6da238425f9b7.js +0 -10
  431. package/.next/standalone/.next/static/chunks/94470-cae3b3ad4e51d2ff.js +0 -1
  432. package/.next/standalone/.next/static/chunks/94643-ba1ebff5769d2b50.js +0 -1
  433. package/.next/standalone/.next/static/chunks/99373.5ac319a55a8f99a1.js +0 -1
  434. package/.next/standalone/.next/static/chunks/app/(dashboard)/layout-177a3fa88be94b4a.js +0 -1
  435. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/page-ae7c9d32fa1c2532.js +0 -1
  436. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-4a8ac49308a4e23b.js +0 -1
  437. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/page-03408be00dc4822b.js +0 -1
  438. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-dd5a0d1e50226c78.js +0 -1
  439. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/page-596d97796dd55e2f.js +0 -1
  440. package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-e786a59c24eb5bda.js +0 -1
  441. package/.next/standalone/.next/static/chunks/app/onboarding/page-df7c97cefb508201.js +0 -1
  442. package/.next/standalone/.next/static/css/ef995b001437e3ef.css +0 -1
  443. /package/.next/standalone/.next/static/{8kqUZqMF8xgdDXm_I4XdF → YTZwWTfE0BsJnjCDYCEHi}/_buildManifest.js +0 -0
  444. /package/.next/standalone/.next/static/{8kqUZqMF8xgdDXm_I4XdF → YTZwWTfE0BsJnjCDYCEHi}/_ssgManifest.js +0 -0
package/cli/daemon.mjs CHANGED
@@ -8,6 +8,12 @@
8
8
  // so a human can `claude --resume <idea-uuid>`); new-vs-resume is decided by
9
9
  // probing the on-disk transcript — there is no persisted session-id map.
10
10
  //
11
+ // Wake coalescing (add-daemon-wake-coalescing): the WakeQueue is PER-CONNECTION
12
+ // and serializes per DIRECT idea (= per session). Wakes that pile up on the same
13
+ // key while a turn runs are drained together and delivered as ONE batch — a
14
+ // single runBatch → waker.wakeBatch → one `claude --resume` turn — so N
15
+ // same-session queued wakes coalesce into one turn, never N sequential turns.
16
+ //
11
17
  // Connection / session / transcript reporting to the server is intentionally
12
18
  // NOT done here — the no-op UploadHooks reserve those seams for the derived
13
19
  // observability idea.
@@ -47,7 +53,13 @@ import { createInterruptReporter } from "./interrupt-reporter.mjs";
47
53
  import { createTurnReporter } from "./turn-reporter.mjs";
48
54
  import { createDaemonRestClient } from "./daemon-rest-client.mjs";
49
55
  import { createControlHandler } from "./control-handler.mjs";
50
- import { resolveSigintTimeoutMs, resolveDaemonCwds, resolveBrowseRoots } from "./daemon-config.mjs";
56
+ import {
57
+ resolveSigintTimeoutMs,
58
+ resolveDaemonCwds,
59
+ resolveBrowseRoots,
60
+ resolveAgentConfigs,
61
+ hasConfiguredAgents,
62
+ } from "./daemon-config.mjs";
51
63
  import { discoverDirectories, validateDirectory } from "./directory-discovery.mjs";
52
64
  import {
53
65
  startBackground,
@@ -141,10 +153,7 @@ export function buildDaemon(creds, deps = {}) {
141
153
  // passed through so the Codex backend can export the daemon key into the woken
142
154
  // process env (the Claude backend ignores creds — it gets its key via --mcp-config).
143
155
  const spawner = deps.spawner ?? selectSpawner(agentType, { logger, permissionMode, creds });
144
- // The WakeQueue serializes per DIRECT idea (keyFor's key). It is shared across all
145
- // path-connections: serialization-per-idea still holds, and maxConcurrency caps the
146
- // whole process's in-flight wakes rather than per-cwd — the right global budget.
147
- const queue = new WakeQueue({ maxConcurrency: deps.maxConcurrency ?? 4, logger });
156
+ const maxConcurrency = deps.maxConcurrency ?? 4;
148
157
 
149
158
  // ===== Multi-path: the SET of cwds this daemon serves (T3 — FR-5) =====
150
159
  // Each declared path becomes one INDEPENDENT connection (own SSE self-report + own
@@ -332,6 +341,11 @@ export function buildDaemon(creds, deps = {}) {
332
341
  selectWaker(notification).markQueued(notification, key, attribution),
333
342
  wake: (notification, key, attribution) =>
334
343
  selectWaker(notification).wake(notification, key, attribution),
344
+ // Coalesced batch (add-daemon-wake-coalescing): every item shares the key → the same
345
+ // session → the same cwd (a session's cwd is pinned), so route the whole batch to the
346
+ // waker selected by the first item's runtimeCwd.
347
+ wakeBatch: (notifications, key, attribution) =>
348
+ selectWaker(notifications[0]).wakeBatch(notifications, key, attribution),
335
349
  markInterrupting(entityType, entityUuid) {
336
350
  for (const candidate of runtimeWakers.values()) {
337
351
  if (candidate.executions.has(`${entityType}:${entityUuid}`)) {
@@ -345,6 +359,19 @@ export function buildDaemon(creds, deps = {}) {
345
359
  buildExecutionSnapshot: () =>
346
360
  [...runtimeWakers.values()].flatMap((candidate) => candidate.buildExecutionSnapshot()),
347
361
  };
362
+ // The WakeQueue serializes per DIRECT idea (keyFor's key) and coalesces same-key pending
363
+ // wakes into one batch (add-daemon-wake-coalescing §C1/§C4). It is PER-CONNECTION so the
364
+ // batch runs on THIS connection's own waker facade — the runBatch drains the per-key data
365
+ // items { notification, attribution } and hands the whole batch to waker.wakeBatch (all
366
+ // items on one key share the session anchor, so items[0].attribution is the batch
367
+ // attribution). maxConcurrency caps this connection's in-flight batches.
368
+ const queue = new WakeQueue({
369
+ maxConcurrency,
370
+ logger,
371
+ runBatch: (key, items) =>
372
+ waker.wakeBatch(items.map((i) => i.notification), key, items[0].attribution),
373
+ });
374
+
348
375
  // The router reads THIS connection's own uuid lazily (same source the control handler
349
376
  // uses) to suppress a DIRECTED (pinned) wake stamped for a different connection
350
377
  // (fix-pinned-wake-directed-delivery, T2). Null until the SSE handshake assigns it — a
@@ -364,8 +391,20 @@ export function buildDaemon(creds, deps = {}) {
364
391
  // all scoped to THIS connection's uuid/router/backfill (see the original wiring
365
392
  // comments retained on the shared helpers). The control handler verifies a control
366
393
  // event against this connection's own connectionUuid before acting.
367
- const redispatchResume = (entityType, entityUuid, resumeReason, runtimeCwd) => {
368
- router.dispatchResume?.({ entityType, entityUuid, resumeReason, runtimeCwd });
394
+ const redispatchResume = (
395
+ entityType,
396
+ entityUuid,
397
+ resumeReason,
398
+ runtimeCwd,
399
+ orchestrator,
400
+ ) => {
401
+ router.dispatchResume?.({
402
+ entityType,
403
+ entityUuid,
404
+ resumeReason,
405
+ runtimeCwd,
406
+ orchestrator,
407
+ });
369
408
  };
370
409
  const deliverTurn = (turnUuid) => backfill?.pendingTurnsOnly?.(turnUuid);
371
410
  const onControl = createControlHandler({
@@ -477,6 +516,7 @@ export function buildDaemon(creds, deps = {}) {
477
516
  connectionState,
478
517
  waker,
479
518
  runtimeWakers,
519
+ queue,
480
520
  router,
481
521
  backfill,
482
522
  sseListener,
@@ -495,9 +535,11 @@ export function buildDaemon(creds, deps = {}) {
495
535
  mcpClient,
496
536
  lineage,
497
537
  spawner,
498
- queue,
499
538
  // Back-compat single-connection aliases (the common single-path case). The full
500
- // set is exposed as `connections` for multi-path inspection/tests.
539
+ // set is exposed as `connections` for multi-path inspection/tests. The WakeQueue is
540
+ // now per-connection (add-daemon-wake-coalescing) so its runBatch can run on the right
541
+ // connection's waker facade; the primary connection's queue is aliased here.
542
+ queue: primary.queue,
501
543
  waker: primary.waker,
502
544
  router: primary.router,
503
545
  sseListener: primary.sseListener,
@@ -520,8 +562,10 @@ export function buildDaemon(creds, deps = {}) {
520
562
  // and latch the queue (queued-but-unstarted wakes never spawn).
521
563
  for (const c of connections) {
522
564
  c.sseListener.disconnect?.();
565
+ // Latch each connection's OWN queue (queues are per-connection now — add-daemon-
566
+ // wake-coalescing) so queued-but-unstarted wakes never spawn.
567
+ c.queue?.stop?.();
523
568
  }
524
- queue.stop();
525
569
  // 2. Interrupt every in-flight wake subprocess via the shared kill escalation.
526
570
  // Each wake's exit path — seeing shuttingDown — reports its turn
527
571
  // interrupted(shutdown) and suppresses the execution crash report.
@@ -532,7 +576,11 @@ export function buildDaemon(creds, deps = {}) {
532
576
  // the kill escalation window plus a hard 5s cap for the exit path's REST
533
577
  // reports. A wake that outlives this does NOT hang the shutdown — its
534
578
  // orphaned turn is the server-side offline reconcile's job (the backstop).
535
- const drained = await queue.drain(sigintTimeoutMs + 5_000);
579
+ // Drain every connection's queue in parallel; `drained` is true only if all did.
580
+ const drainResults = await Promise.all(
581
+ connections.map((c) => c.queue?.drain?.(sigintTimeoutMs + 5_000) ?? true),
582
+ );
583
+ const drained = drainResults.every(Boolean);
536
584
  if (!drained) {
537
585
  logger.warn(
538
586
  "[Chorus] shutdown: in-flight wake(s) did not finish within the bound — exiting anyway (server reconcile will finalize their turns)",
@@ -544,6 +592,122 @@ export function buildDaemon(creds, deps = {}) {
544
592
  };
545
593
  }
546
594
 
595
+ /**
596
+ * Fan-out builder: compose ONE `buildDaemon` runtime per agent config, so a single
597
+ * daemon process serves N fully-independent agents — each with its own creds,
598
+ * ChorusClient, LineageResolver, spawner (by its `agentType`), WakeQueue (its own
599
+ * `maxConcurrency`), and connections over its OWN cwds. For N=1 this is behaviorally
600
+ * identical to `buildDaemon({url,apiKey}, deps)`.
601
+ *
602
+ * Each agent's runtime is isolated: a build/start failure in one agent is logged and
603
+ * skipped, and the others keep serving. The aggregate `allConflict` settles only when
604
+ * EVERY agent's paths are all already served (nothing left to do at all).
605
+ *
606
+ * Injectable seams mirror `buildDaemon`; array-valued deps (`spawner`, `mcpClient`,
607
+ * `lineage`, `sseListener`, `makeSseListener`) are indexed PER agent for tests.
608
+ *
609
+ * @param {import("./daemon-config.mjs").AgentConfig[]} agentConfigs
610
+ * @param {object} [deps]
611
+ * @returns {{ agents: Array<{cfg: any, daemon: any}>, connections: any[],
612
+ * waker: any, router: any, sseListener: any, allConflict: Promise<void>,
613
+ * start: () => Promise<void>, stop: () => Promise<void> }}
614
+ */
615
+ export function buildMultiAgentDaemon(agentConfigs, deps = {}) {
616
+ const logger = deps.logger ?? defaultLogger();
617
+ if (!Array.isArray(agentConfigs) || agentConfigs.length === 0) {
618
+ throw new Error("buildMultiAgentDaemon: at least one agent config is required");
619
+ }
620
+ const build = deps.build ?? buildDaemon;
621
+ const perAgent = (key, i) => {
622
+ const v = deps[key];
623
+ return Array.isArray(v) ? v[i] : i === 0 ? v : undefined;
624
+ };
625
+
626
+ const agents = agentConfigs
627
+ .map((cfg, i) => {
628
+ // Per-agent deps: cfg fields drive the per-agent runtime; injectable fakes are
629
+ // indexed per agent. `cwd` (singular) is cleared so a caller's single value can
630
+ // never leak across agents — each agent's `cwds` is authoritative.
631
+ const agentDeps = {
632
+ ...deps,
633
+ logger,
634
+ permissionMode: cfg.permissionMode,
635
+ agentType: cfg.agentType,
636
+ cwds: cfg.cwds,
637
+ cwd: undefined,
638
+ maxConcurrency: cfg.maxConcurrency,
639
+ sigintTimeoutMs: cfg.sigintTimeoutMs,
640
+ browseRoots: cfg.browseRoots,
641
+ mcpClient: perAgent("mcpClient", i),
642
+ lineage: perAgent("lineage", i),
643
+ spawner: perAgent("spawner", i),
644
+ sseListener: perAgent("sseListener", i),
645
+ makeSseListener: Array.isArray(deps.makeSseListener)
646
+ ? deps.makeSseListener[i]
647
+ : deps.makeSseListener,
648
+ };
649
+ try {
650
+ return { cfg, daemon: build({ url: cfg.url, apiKey: cfg.apiKey }, agentDeps) };
651
+ } catch (err) {
652
+ logger.error?.(
653
+ `[Chorus] agent ${cfg.label}: failed to build runtime — skipping ` +
654
+ `(${err instanceof Error ? err.message : String(err)})`,
655
+ );
656
+ return null;
657
+ }
658
+ })
659
+ .filter(Boolean);
660
+
661
+ if (agents.length === 0) {
662
+ throw new Error("buildMultiAgentDaemon: all agent runtimes failed to build");
663
+ }
664
+
665
+ const connections = agents.flatMap((a) => a.daemon.connections ?? []);
666
+ const primary = agents[0].daemon;
667
+ // Aggregate all-conflict: settles only when EVERY agent's paths are all already
668
+ // served by a live daemon (each agent's allConflict settles only in that case, and
669
+ // never otherwise). A single serving agent keeps the whole daemon alive.
670
+ const allConflict = Promise.all(
671
+ agents.map((a) => a.daemon.allConflict ?? new Promise(() => {})),
672
+ ).then(() => {});
673
+
674
+ return {
675
+ agents,
676
+ connections,
677
+ // Back-compat single aliases (first agent's primary connection) for inspection.
678
+ waker: primary.waker,
679
+ router: primary.router,
680
+ sseListener: primary.sseListener,
681
+ allConflict,
682
+ async start() {
683
+ // Start each agent independently; one agent's start failure is logged and
684
+ // isolated so the others still serve.
685
+ for (const a of agents) {
686
+ try {
687
+ await a.daemon.start();
688
+ } catch (err) {
689
+ logger.error?.(
690
+ `[Chorus] agent ${a.cfg.label}: start failed — ` +
691
+ `${err instanceof Error ? err.message : String(err)} (other agents continue)`,
692
+ );
693
+ }
694
+ }
695
+ },
696
+ async stop() {
697
+ for (const a of agents) {
698
+ try {
699
+ await a.daemon.stop();
700
+ } catch (err) {
701
+ logger.warn?.(
702
+ `[Chorus] agent ${a.cfg.label}: stop error — ` +
703
+ `${err instanceof Error ? err.message : String(err)}`,
704
+ );
705
+ }
706
+ }
707
+ },
708
+ };
709
+ }
710
+
547
711
  /**
548
712
  * Entry point for `chorus daemon`. Resolves credentials, validates them
549
713
  * (echoing the agent identity), and runs the daemon until terminated.
@@ -650,6 +814,105 @@ export async function runDaemon(flags = {}, deps = {}) {
650
814
  const cwds = resolveDaemonCwds({ cwd: flags.cwd }, { env });
651
815
  const browseRoots = resolveBrowseRoots({ browseRoot: flags.browseRoot }, { env });
652
816
 
817
+ // ===== Multi-agent mode (daemon-multi-agent) =====
818
+ // When daemon.json declares a non-empty agents[], run N fully-independent agents in
819
+ // one process. Each agent carries its OWN creds, so this bypasses the flat single-
820
+ // credential preflight (interactive credential completion is a single-agent
821
+ // affordance). Each agent authenticates on its own key; a failure is isolated
822
+ // (logged + that agent skipped) so the rest still serve.
823
+ if (hasConfiguredAgents({ readJson: deps.readJson, loginPath: deps.loginPath })) {
824
+ const buildMulti = deps.buildMulti ?? buildMultiAgentDaemon;
825
+ let agentConfigs;
826
+ try {
827
+ agentConfigs = resolveAgentConfigs(
828
+ {
829
+ url: flags.url,
830
+ apiKey: flags.apiKey,
831
+ agent: flags.agent,
832
+ cwd: flags.cwd,
833
+ browseRoot: flags.browseRoot,
834
+ sigintTimeout: flags.sigintTimeout,
835
+ chorusOnly: flags.chorusOnly,
836
+ yolo: flags.yolo,
837
+ },
838
+ { env, readJson: deps.readJson, loginPath: deps.loginPath },
839
+ );
840
+ } catch (err) {
841
+ errLog(`[Chorus] ${err instanceof Error ? err.message : String(err)}`);
842
+ return 1;
843
+ }
844
+
845
+ // Validate each agent independently. A validation failure logs + skips that agent
846
+ // (isolation) — the daemon still serves the agents that authenticated.
847
+ const okConfigs = [];
848
+ for (const cfg of agentConfigs) {
849
+ try {
850
+ const id = await validate({ url: cfg.url, apiKey: cfg.apiKey });
851
+ okConfigs.push(cfg);
852
+ log(
853
+ `[Chorus] agent ${cfg.label}: ${id.name} (${id.uuid}) — ${cfg.agentType}, ` +
854
+ `${cfg.permissionMode}, ${cfg.cwds.length} path(s), maxConcurrency=${cfg.maxConcurrency}`,
855
+ );
856
+ if (cfg.permissionMode === "yolo") errLog(`[Chorus] agent ${cfg.label}: ${yoloWarningLine()}`);
857
+ } catch (err) {
858
+ errLog(
859
+ `[Chorus] agent ${cfg.label}: credential validation failed — ` +
860
+ `${err instanceof Error ? err.message : String(err)} (skipping this agent)`,
861
+ );
862
+ }
863
+ }
864
+ if (okConfigs.length === 0) {
865
+ errLog(
866
+ `[Chorus] no agents authenticated — nothing to serve. Check the apiKeys in ${loginFilePath()}.`,
867
+ );
868
+ return 1;
869
+ }
870
+
871
+ const totalPaths = okConfigs.reduce((n, c) => n + c.cwds.length, 0);
872
+ log(
873
+ `[Chorus] multi-agent daemon starting — ${okConfigs.length} agent(s), ` +
874
+ `${totalPaths} connection(s), subscribing to ${okConfigs[0].url}/api/events/notifications`,
875
+ );
876
+ const multiDaemon = buildMulti(okConfigs, {
877
+ logger: { info: log, warn: errLog, error: errLog },
878
+ verbose,
879
+ fetchImpl: deps.fetchImpl,
880
+ killer: deps.killer,
881
+ sseListener: deps.sseListener,
882
+ makeSseListener: deps.makeSseListener,
883
+ spawner: deps.spawner,
884
+ mcpClient: deps.mcpClient,
885
+ lineage: deps.lineage,
886
+ build: deps.build,
887
+ });
888
+
889
+ const shutdownMulti = () => {
890
+ log("[Chorus] shutting down daemon...");
891
+ Promise.resolve(multiDaemon.stop()).finally(() => process.exit(0));
892
+ };
893
+ process.on("SIGINT", shutdownMulti);
894
+ process.on("SIGTERM", shutdownMulti);
895
+ await multiDaemon.start();
896
+ log("[Chorus] multi-agent daemon running. Waiting for task dispatches (Ctrl+C to stop).");
897
+
898
+ const ALL_CONFLICT_M = Symbol("all-conflict");
899
+ const waitForeverM = deps.waitForever ?? (() => new Promise(() => {}));
900
+ const allConflictSignalM = multiDaemon.allConflict ?? new Promise(() => {});
901
+ const outcomeM = await Promise.race([
902
+ waitForeverM().then(() => 0),
903
+ allConflictSignalM.then(() => ALL_CONFLICT_M),
904
+ ]);
905
+ if (outcomeM === ALL_CONFLICT_M) {
906
+ errLog(
907
+ `[Chorus] every declared path for every agent is already served by a live daemon — ` +
908
+ `nothing to do. Stop the other daemon(s) or remove the conflicting path(s), then restart.`,
909
+ );
910
+ await multiDaemon.stop();
911
+ return 1;
912
+ }
913
+ return 0;
914
+ }
915
+
653
916
  // Foreground preflight: resolve/complete credentials + resolve the permission
654
917
  // posture (confirming yolo on a TTY). Reuses the same pfDeps bundle the detach
655
918
  // path uses. Returns a numeric exit code on failure, or
@@ -37,8 +37,8 @@ export class EventRouter {
37
37
  /**
38
38
  * @param {{
39
39
  * mcpClient: { callTool: (name: string, args?: Record<string, unknown>) => Promise<any> },
40
- * waker: { keyFor: (n: any) => Promise<{ key: string, rootIdeaUuid: string|null, directIdeaUuid: string|null }>, wake: (n: any, key: string, attribution?: any) => Promise<void>, markQueued?: (n: any, key: string, attribution?: any) => void },
41
- * queue: { enqueue: (key: string, task: () => Promise<void>) => void },
40
+ * waker: { keyFor: (n: any) => Promise<{ key: string, rootIdeaUuid: string|null, directIdeaUuid: string|null }>, wakeBatch: (ns: any[], key: string, attribution?: any) => Promise<void>, markQueued?: (n: any, key: string, attribution?: any) => void },
41
+ * queue: { enqueue: (key: string, item: { notification: any, attribution: any }) => void },
42
42
  * wakeActions: Set<string>,
43
43
  * getConnectionUuid?: () => (string|null), This daemon's registered connection uuid
44
44
  * (null until the SSE handshake reports it).
@@ -228,7 +228,8 @@ export class EventRouter {
228
228
  * reason ("user" | "crash") threaded from the control event; it is stamped on the
229
229
  * synthetic notification as `resumedFrom` so the prompt builder can state a crash
230
230
  * explicitly. Absent/unknown → not stamped → the user-resume prompt.
231
- * @param {{ entityType?: string, entityUuid?: string, resumeReason?: string }} target
231
+ * @param {{ entityType?: string, entityUuid?: string, resumeReason?: string,
232
+ * orchestrator?: { type?: string, uuid?: string, name?: string } | null }} target
232
233
  */
233
234
  dispatchResume(target) {
234
235
  const entityType = target?.entityType;
@@ -247,6 +248,11 @@ export class EventRouter {
247
248
  entityUuid,
248
249
  ...(resumedFrom ? { resumedFrom } : {}),
249
250
  ...(typeof target?.runtimeCwd === "string" ? { runtimeCwd: target.runtimeCwd } : {}),
251
+ ...(target?.orchestrator?.type === "agent" &&
252
+ typeof target.orchestrator.uuid === "string" &&
253
+ typeof target.orchestrator.name === "string"
254
+ ? { orchestrator: target.orchestrator }
255
+ : {}),
250
256
  };
251
257
  this.#resolveAndEnqueue(n, `resume:${entityType}:${entityUuid}`).catch((err) => {
252
258
  this.logger.error(`[Chorus] failed to dispatch resume for ${entityType}:${entityUuid}: ${err}`);
@@ -383,7 +389,10 @@ export class EventRouter {
383
389
  } catch (err) {
384
390
  this.logger.warn(`[Chorus] markQueued failed for pending turn ${turnUuid}: ${err}`);
385
391
  }
386
- this.queue.enqueue(key, () => this.waker.wake(n, key, attribution));
392
+ // Enqueue an opaque DATA payload (add-daemon-wake-coalescing §C4), NOT a thunk: the
393
+ // queue coalesces all same-key pending items and hands the whole batch to its runBatch
394
+ // (wired to waker.wakeBatch in daemon.mjs). markQueued was already called per-item above.
395
+ this.queue.enqueue(key, { notification: n, attribution });
387
396
  }
388
397
 
389
398
  /**
@@ -531,6 +540,9 @@ export class EventRouter {
531
540
  } catch (err) {
532
541
  this.logger.warn(`[Chorus] markQueued failed for ${label}: ${err}`);
533
542
  }
534
- this.queue.enqueue(key, () => this.waker.wake(n, key, attribution));
543
+ // Enqueue an opaque DATA payload (add-daemon-wake-coalescing §C4), NOT a thunk: the
544
+ // queue coalesces all same-key pending items and hands the whole batch to its runBatch
545
+ // (wired to waker.wakeBatch in daemon.mjs). markQueued was already called per-item above.
546
+ this.queue.enqueue(key, { notification: n, attribution });
535
547
  }
536
548
  }
package/cli/login.mjs CHANGED
@@ -144,15 +144,86 @@ export function recordYoloAck(yoloAckAt, deps = {}) {
144
144
  return updateDaemonConfig({ yoloAckAt }, deps);
145
145
  }
146
146
 
147
+ /** A non-empty trimmed string, or undefined. */
148
+ function nonEmpty(value) {
149
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
150
+ }
151
+
152
+ /**
153
+ * Append a new agent to `~/.chorus/daemon.json`'s `agents[]` (daemon-multi-agent),
154
+ * via the same field-merge writer, WITHOUT overwriting any existing agent.
155
+ *
156
+ * Migration rule: if the file is still a flat single-agent config (top-level
157
+ * `apiKey`, no `agents[]`), the flat fields are first folded into `agents[0]` so
158
+ * the newly added key becomes `agents[1]` — the result is unambiguous (once
159
+ * `agents[]` exists, the flat top-level fields serve only as defaults, never as a
160
+ * standalone agent). Duplicate protection: if the new `apiKey` already matches an
161
+ * existing agent (or the pre-migration flat key), nothing is written.
162
+ *
163
+ * @param {{ url?: string, apiKey: string, agentType?: string, agentUuid?: string, agentName?: string }} agentObj
164
+ * @param {{ path?: string, read?: (p: string) => string, write?: (p: string, c: string, o: object) => void, mkdir?: (p: string, o: object) => void, rename?: (from: string, to: string) => void }} [deps]
165
+ * @returns {{ ok: true, path: string, agents: object[], index: number } | { ok: false, reason: "duplicate" }}
166
+ */
167
+ export function appendAgentConfig(agentObj, deps = {}) {
168
+ const path = deps.path ?? loginFilePath();
169
+ const read = deps.read ?? ((p) => readFileSync(p, "utf8"));
170
+
171
+ let current = {};
172
+ try {
173
+ const parsed = JSON.parse(read(path));
174
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) current = parsed;
175
+ } catch {
176
+ // treat as empty
177
+ }
178
+
179
+ const existingAgents =
180
+ Array.isArray(current.agents) ? current.agents.filter((a) => a && typeof a === "object") : [];
181
+
182
+ /** @type {object[]} */
183
+ let agents;
184
+ if (existingAgents.length > 0) {
185
+ agents = existingAgents.slice();
186
+ } else if (nonEmpty(current.apiKey)) {
187
+ // Migrate the flat single-agent config into agents[0] so the new key is agents[1].
188
+ const flat = { apiKey: current.apiKey };
189
+ if (nonEmpty(current.url)) flat.url = current.url;
190
+ if (nonEmpty(current.agent)) flat.agentType = current.agent;
191
+ if (Array.isArray(current.cwds)) flat.cwds = current.cwds;
192
+ if (nonEmpty(current.agentName)) flat.agentName = current.agentName;
193
+ if (nonEmpty(current.agentUuid)) flat.agentUuid = current.agentUuid;
194
+ agents = [flat];
195
+ } else {
196
+ agents = [];
197
+ }
198
+
199
+ // Never add a duplicate: refuse if this apiKey already backs an agent (checking
200
+ // both the agents[] entries and any pre-migration flat top-level key).
201
+ const existingKeys = new Set(agents.map((a) => a.apiKey).filter(Boolean));
202
+ if (nonEmpty(current.apiKey)) existingKeys.add(current.apiKey);
203
+ if (existingKeys.has(agentObj.apiKey)) {
204
+ return { ok: false, reason: "duplicate" };
205
+ }
206
+
207
+ agents.push(agentObj);
208
+ const writtenPath = updateDaemonConfig({ agents }, deps);
209
+ return { ok: true, path: writtenPath, agents, index: agents.length - 1 };
210
+ }
211
+
147
212
  /**
148
213
  * Run the login flow: collect url + key (flags or interactive), validate
149
214
  * against the server, and on success persist + echo identity. Returns an exit
150
215
  * code (0 success, non-zero failure). Never throws.
151
216
  *
152
- * @param {{ url?: string, apiKey?: string }} flags
217
+ * With `flags.add`, the validated key is APPENDED as an additional agent
218
+ * (daemon-multi-agent) via {@link appendAgentConfig} instead of overwriting the
219
+ * single flat credential — so one daemon can serve several agents. On an invalid
220
+ * key, or a duplicate, nothing is written.
221
+ *
222
+ * @param {{ url?: string, apiKey?: string, agent?: string, add?: boolean }} flags
153
223
  * @param {{
154
224
  * validate?: typeof validateAndFetchIdentity,
155
225
  * write?: typeof writeLoginFile,
226
+ * appendAgent?: typeof appendAgentConfig,
156
227
  * prompt?: typeof prompt,
157
228
  * log?: (m: string) => void,
158
229
  * errLog?: (m: string) => void,
@@ -162,6 +233,7 @@ export function recordYoloAck(yoloAckAt, deps = {}) {
162
233
  export async function runLogin(flags = {}, deps = {}) {
163
234
  const validate = deps.validate ?? validateAndFetchIdentity;
164
235
  const write = deps.write ?? writeLoginFile;
236
+ const appendAgent = deps.appendAgent ?? appendAgentConfig;
165
237
  const ask = deps.prompt ?? prompt;
166
238
  const log = deps.log ?? ((m) => process.stdout.write(m + "\n"));
167
239
  const errLog = deps.errLog ?? ((m) => process.stderr.write(m + "\n"));
@@ -183,10 +255,26 @@ export async function runLogin(flags = {}, deps = {}) {
183
255
  } catch (err) {
184
256
  const msg = err instanceof Error ? err.message : String(err);
185
257
  errLog(`Login failed: ${msg}`);
186
- errLog("Credentials were NOT saved.");
258
+ errLog(flags.add ? "No agent was added." : "Credentials were NOT saved.");
187
259
  return 1;
188
260
  }
189
261
 
262
+ // --add: append as an additional agent (multi-agent) instead of overwriting.
263
+ if (flags.add) {
264
+ const agentObj = { url, apiKey, agentUuid: identity.uuid, agentName: identity.name };
265
+ if (nonEmpty(flags.agent)) agentObj.agentType = nonEmpty(flags.agent);
266
+ const res = appendAgent(agentObj);
267
+ if (!res.ok) {
268
+ errLog(
269
+ `Agent ${identity.name} (${identity.uuid}) is already configured (same API key) — nothing changed.`,
270
+ );
271
+ return 1;
272
+ }
273
+ log(`Added agent ${identity.name} (${identity.uuid}) as agents[${res.index}] in ${res.path}.`);
274
+ log(`This daemon now serves ${res.agents.length} agent(s).`);
275
+ return 0;
276
+ }
277
+
190
278
  const path = write({ url, apiKey, agentUuid: identity.uuid, agentName: identity.name });
191
279
  log(`Logged in as ${identity.name} (${identity.uuid}).`);
192
280
  log(`Credentials saved to ${path}.`);