chorus-codes 0.7.0 → 0.7.1

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 (291) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/cache/.previewinfo +1 -1
  4. package/.next/cache/.rscinfo +1 -1
  5. package/.next/fallback-build-manifest.json +3 -3
  6. package/.next/prerender-manifest.json +3 -3
  7. package/.next/server/app/_global-error.html +1 -1
  8. package/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/server/app/_not-found.html +1 -1
  15. package/.next/server/app/_not-found.rsc +1 -1
  16. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  22. package/.next/server/app/new.html +1 -1
  23. package/.next/server/app/new.rsc +1 -1
  24. package/.next/server/app/new.segments/_full.segment.rsc +1 -1
  25. package/.next/server/app/new.segments/_head.segment.rsc +1 -1
  26. package/.next/server/app/new.segments/_index.segment.rsc +1 -1
  27. package/.next/server/app/new.segments/_tree.segment.rsc +1 -1
  28. package/.next/server/app/new.segments/new/__PAGE__.segment.rsc +1 -1
  29. package/.next/server/app/new.segments/new.segment.rsc +1 -1
  30. package/.next/server/app/onboarding.html +1 -1
  31. package/.next/server/app/onboarding.rsc +1 -1
  32. package/.next/server/app/onboarding.segments/_full.segment.rsc +1 -1
  33. package/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
  34. package/.next/server/app/onboarding.segments/_index.segment.rsc +1 -1
  35. package/.next/server/app/onboarding.segments/_tree.segment.rsc +1 -1
  36. package/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
  37. package/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
  38. package/.next/server/app/personas.html +1 -1
  39. package/.next/server/app/personas.rsc +1 -1
  40. package/.next/server/app/personas.segments/_full.segment.rsc +1 -1
  41. package/.next/server/app/personas.segments/_head.segment.rsc +1 -1
  42. package/.next/server/app/personas.segments/_index.segment.rsc +1 -1
  43. package/.next/server/app/personas.segments/_tree.segment.rsc +1 -1
  44. package/.next/server/app/personas.segments/personas/__PAGE__.segment.rsc +1 -1
  45. package/.next/server/app/personas.segments/personas.segment.rsc +1 -1
  46. package/.next/server/app/settings.html +1 -1
  47. package/.next/server/app/settings.rsc +1 -1
  48. package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  49. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  50. package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  51. package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  52. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
  53. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  54. package/.next/server/app/templates.html +1 -1
  55. package/.next/server/app/templates.rsc +1 -1
  56. package/.next/server/app/templates.segments/_full.segment.rsc +1 -1
  57. package/.next/server/app/templates.segments/_head.segment.rsc +1 -1
  58. package/.next/server/app/templates.segments/_index.segment.rsc +1 -1
  59. package/.next/server/app/templates.segments/_tree.segment.rsc +1 -1
  60. package/.next/server/app/templates.segments/templates/__PAGE__.segment.rsc +1 -1
  61. package/.next/server/app/templates.segments/templates.segment.rsc +1 -1
  62. package/.next/server/middleware-build-manifest.js +3 -3
  63. package/.next/server/pages/404.html +1 -1
  64. package/.next/server/pages/500.html +1 -1
  65. package/.next/server/server-reference-manifest.js +1 -1
  66. package/.next/server/server-reference-manifest.json +1 -1
  67. package/.next/trace +1 -1
  68. package/.next/trace-build +1 -1
  69. package/dist/cli/commands/doctor.js +116 -0
  70. package/dist/cli/commands/doctor.js.map +1 -0
  71. package/dist/cli/commands/init.js +211 -0
  72. package/dist/cli/commands/init.js.map +1 -0
  73. package/dist/cli/commands/start.js +240 -0
  74. package/dist/cli/commands/start.js.map +1 -0
  75. package/dist/cli/commands/status.js +54 -0
  76. package/dist/cli/commands/status.js.map +1 -0
  77. package/dist/cli/commands/stop.js +97 -0
  78. package/dist/cli/commands/stop.js.map +1 -0
  79. package/dist/cli/connect.js +108 -0
  80. package/dist/cli/connect.js.map +1 -0
  81. package/dist/cli/index.js +99 -0
  82. package/dist/cli/index.js.map +1 -0
  83. package/dist/cli/port-utils.js +260 -0
  84. package/dist/cli/port-utils.js.map +1 -0
  85. package/dist/cli/runtime-env.js +60 -0
  86. package/dist/cli/runtime-env.js.map +1 -0
  87. package/dist/cli/shared.js +54 -0
  88. package/dist/cli/shared.js.map +1 -0
  89. package/dist/cli/ui.js +60 -0
  90. package/dist/cli/ui.js.map +1 -0
  91. package/dist/daemon/agents/claude.js +98 -0
  92. package/dist/daemon/agents/claude.js.map +1 -0
  93. package/dist/daemon/agents/codex.js +160 -0
  94. package/dist/daemon/agents/codex.js.map +1 -0
  95. package/dist/daemon/agents/gemini.js +111 -0
  96. package/dist/daemon/agents/gemini.js.map +1 -0
  97. package/dist/daemon/agents/index.js +59 -0
  98. package/dist/daemon/agents/index.js.map +1 -0
  99. package/dist/daemon/agents/kimi.js +206 -0
  100. package/dist/daemon/agents/kimi.js.map +1 -0
  101. package/dist/daemon/agents/opencode.js +228 -0
  102. package/dist/daemon/agents/opencode.js.map +1 -0
  103. package/dist/daemon/agents/openrouter.js +274 -0
  104. package/dist/daemon/agents/openrouter.js.map +1 -0
  105. package/dist/daemon/agents/parsers/claude.js +63 -0
  106. package/dist/daemon/agents/parsers/claude.js.map +1 -0
  107. package/dist/daemon/agents/parsers/codex.js +51 -0
  108. package/dist/daemon/agents/parsers/codex.js.map +1 -0
  109. package/dist/daemon/agents/parsers/gemini.js +144 -0
  110. package/dist/daemon/agents/parsers/gemini.js.map +1 -0
  111. package/dist/daemon/agents/parsers/index.js +31 -0
  112. package/dist/daemon/agents/parsers/index.js.map +1 -0
  113. package/dist/daemon/agents/parsers/kimi.js +8 -0
  114. package/dist/daemon/agents/parsers/kimi.js.map +1 -0
  115. package/dist/daemon/agents/parsers/opencode.js +105 -0
  116. package/dist/daemon/agents/parsers/opencode.js.map +1 -0
  117. package/dist/daemon/agents/parsers/openrouter.js +69 -0
  118. package/dist/daemon/agents/parsers/openrouter.js.map +1 -0
  119. package/dist/daemon/agents/parsers/shared.js +17 -0
  120. package/dist/daemon/agents/parsers/shared.js.map +1 -0
  121. package/dist/daemon/agents/preflight.js +83 -0
  122. package/dist/daemon/agents/preflight.js.map +1 -0
  123. package/dist/daemon/agents/quote.js +45 -0
  124. package/dist/daemon/agents/quote.js.map +1 -0
  125. package/dist/daemon/agents/sandbox-guard.js +69 -0
  126. package/dist/daemon/agents/sandbox-guard.js.map +1 -0
  127. package/dist/daemon/agents/types.js +6 -0
  128. package/dist/daemon/agents/types.js.map +1 -0
  129. package/dist/daemon/api-response.js +65 -0
  130. package/dist/daemon/api-response.js.map +1 -0
  131. package/dist/daemon/error-detector.js +329 -0
  132. package/dist/daemon/error-detector.js.map +1 -0
  133. package/dist/daemon/headless.js +533 -0
  134. package/dist/daemon/headless.js.map +1 -0
  135. package/dist/daemon/index.js +333 -0
  136. package/dist/daemon/index.js.map +1 -0
  137. package/dist/daemon/openrouter.js +192 -0
  138. package/dist/daemon/openrouter.js.map +1 -0
  139. package/dist/daemon/orchestrators/claude.js +163 -0
  140. package/dist/daemon/orchestrators/claude.js.map +1 -0
  141. package/dist/daemon/orchestrators/codex.js +101 -0
  142. package/dist/daemon/orchestrators/codex.js.map +1 -0
  143. package/dist/daemon/orchestrators/cursor-windsurf.js +118 -0
  144. package/dist/daemon/orchestrators/cursor-windsurf.js.map +1 -0
  145. package/dist/daemon/orchestrators/gemini.js +108 -0
  146. package/dist/daemon/orchestrators/gemini.js.map +1 -0
  147. package/dist/daemon/orchestrators/index.js +90 -0
  148. package/dist/daemon/orchestrators/index.js.map +1 -0
  149. package/dist/daemon/orchestrators/kimi.js +108 -0
  150. package/dist/daemon/orchestrators/kimi.js.map +1 -0
  151. package/dist/daemon/orchestrators/opencode.js +152 -0
  152. package/dist/daemon/orchestrators/opencode.js.map +1 -0
  153. package/dist/daemon/orchestrators/shared.js +60 -0
  154. package/dist/daemon/orchestrators/shared.js.map +1 -0
  155. package/dist/daemon/output-watcher.js +131 -0
  156. package/dist/daemon/output-watcher.js.map +1 -0
  157. package/dist/daemon/participant-aborts.js +123 -0
  158. package/dist/daemon/participant-aborts.js.map +1 -0
  159. package/dist/daemon/reaper.js +46 -0
  160. package/dist/daemon/reaper.js.map +1 -0
  161. package/dist/daemon/routes/chats-events.js +62 -0
  162. package/dist/daemon/routes/chats-events.js.map +1 -0
  163. package/dist/daemon/routes/chats-stream.js +241 -0
  164. package/dist/daemon/routes/chats-stream.js.map +1 -0
  165. package/dist/daemon/routes/chats-validation.js +13 -0
  166. package/dist/daemon/routes/chats-validation.js.map +1 -0
  167. package/dist/daemon/routes/chats.js +545 -0
  168. package/dist/daemon/routes/chats.js.map +1 -0
  169. package/dist/daemon/routes/openrouter.js +103 -0
  170. package/dist/daemon/routes/openrouter.js.map +1 -0
  171. package/dist/daemon/routes/settings.js +199 -0
  172. package/dist/daemon/routes/settings.js.map +1 -0
  173. package/dist/daemon/routes/stats.js +155 -0
  174. package/dist/daemon/routes/stats.js.map +1 -0
  175. package/dist/daemon/routes/system.js +208 -0
  176. package/dist/daemon/routes/system.js.map +1 -0
  177. package/dist/daemon/routes/templates-personas.js +254 -0
  178. package/dist/daemon/routes/templates-personas.js.map +1 -0
  179. package/dist/daemon/routes/voices.js +139 -0
  180. package/dist/daemon/routes/voices.js.map +1 -0
  181. package/dist/daemon/runner/doer-driver.js +346 -0
  182. package/dist/daemon/runner/doer-driver.js.map +1 -0
  183. package/dist/daemon/runner/doer.js +336 -0
  184. package/dist/daemon/runner/doer.js.map +1 -0
  185. package/dist/daemon/runner/prior-round.js +140 -0
  186. package/dist/daemon/runner/prior-round.js.map +1 -0
  187. package/dist/daemon/runner/prompt-builder.js +292 -0
  188. package/dist/daemon/runner/prompt-builder.js.map +1 -0
  189. package/dist/daemon/runner/review-only-phase.js +103 -0
  190. package/dist/daemon/runner/review-only-phase.js.map +1 -0
  191. package/dist/daemon/runner/reviewer-driver.js +410 -0
  192. package/dist/daemon/runner/reviewer-driver.js.map +1 -0
  193. package/dist/daemon/runner/reviewer.js +384 -0
  194. package/dist/daemon/runner/reviewer.js.map +1 -0
  195. package/dist/daemon/runner/run-with-fallback.js +56 -0
  196. package/dist/daemon/runner/run-with-fallback.js.map +1 -0
  197. package/dist/daemon/runner/sanitize-name.js +8 -0
  198. package/dist/daemon/runner/sanitize-name.js.map +1 -0
  199. package/dist/daemon/runner/stream-file-writer.js +116 -0
  200. package/dist/daemon/runner/stream-file-writer.js.map +1 -0
  201. package/dist/daemon/runner/swap-sidecar.js +102 -0
  202. package/dist/daemon/runner/swap-sidecar.js.map +1 -0
  203. package/dist/daemon/runner/template-fallback.js +119 -0
  204. package/dist/daemon/runner/template-fallback.js.map +1 -0
  205. package/dist/daemon/runner/types.js +3 -0
  206. package/dist/daemon/runner/types.js.map +1 -0
  207. package/dist/daemon/runner/verdict.js +51 -0
  208. package/dist/daemon/runner/verdict.js.map +1 -0
  209. package/dist/daemon/runner-multiplex.js +364 -0
  210. package/dist/daemon/runner-multiplex.js.map +1 -0
  211. package/dist/daemon/runner.js +427 -0
  212. package/dist/daemon/runner.js.map +1 -0
  213. package/dist/daemon/ship.js +340 -0
  214. package/dist/daemon/ship.js.map +1 -0
  215. package/dist/daemon/template-cache.js +37 -0
  216. package/dist/daemon/template-cache.js.map +1 -0
  217. package/dist/daemon/tmux-types.js +9 -0
  218. package/dist/daemon/tmux-types.js.map +1 -0
  219. package/dist/daemon/tmux.js +341 -0
  220. package/dist/daemon/tmux.js.map +1 -0
  221. package/dist/lib/atomic-write.js +55 -0
  222. package/dist/lib/atomic-write.js.map +1 -0
  223. package/dist/lib/chat-events-bus.js +27 -0
  224. package/dist/lib/chat-events-bus.js.map +1 -0
  225. package/dist/lib/chat-slug.js +105 -0
  226. package/dist/lib/chat-slug.js.map +1 -0
  227. package/dist/lib/cli-detect.js +388 -0
  228. package/dist/lib/cli-detect.js.map +1 -0
  229. package/dist/lib/cli-health.js +156 -0
  230. package/dist/lib/cli-health.js.map +1 -0
  231. package/dist/lib/cli-paths.js +113 -0
  232. package/dist/lib/cli-paths.js.map +1 -0
  233. package/dist/lib/cli-precheck.js +141 -0
  234. package/dist/lib/cli-precheck.js.map +1 -0
  235. package/dist/lib/db/chats.js +244 -0
  236. package/dist/lib/db/chats.js.map +1 -0
  237. package/dist/lib/db/connection.js +254 -0
  238. package/dist/lib/db/connection.js.map +1 -0
  239. package/dist/lib/db/index.js +34 -0
  240. package/dist/lib/db/index.js.map +1 -0
  241. package/dist/lib/db/personas.js +65 -0
  242. package/dist/lib/db/personas.js.map +1 -0
  243. package/dist/lib/db/phase-events.js +172 -0
  244. package/dist/lib/db/phase-events.js.map +1 -0
  245. package/dist/lib/db/secrets.js +53 -0
  246. package/dist/lib/db/secrets.js.map +1 -0
  247. package/dist/lib/db/settings.js +47 -0
  248. package/dist/lib/db/settings.js.map +1 -0
  249. package/dist/lib/db/templates.js +75 -0
  250. package/dist/lib/db/templates.js.map +1 -0
  251. package/dist/lib/db/voices.js +184 -0
  252. package/dist/lib/db/voices.js.map +1 -0
  253. package/dist/lib/lineage-maps.js +200 -0
  254. package/dist/lib/lineage-maps.js.map +1 -0
  255. package/dist/lib/logger.js +186 -0
  256. package/dist/lib/logger.js.map +1 -0
  257. package/dist/lib/personas.js +117 -0
  258. package/dist/lib/personas.js.map +1 -0
  259. package/dist/lib/runtime-path.js +222 -0
  260. package/dist/lib/runtime-path.js.map +1 -0
  261. package/dist/lib/settings/billing.js +58 -0
  262. package/dist/lib/settings/billing.js.map +1 -0
  263. package/dist/lib/settings/permissions.js +81 -0
  264. package/dist/lib/settings/permissions.js.map +1 -0
  265. package/dist/lib/settings/transport.js +113 -0
  266. package/dist/lib/settings/transport.js.map +1 -0
  267. package/dist/lib/telemetry.js +290 -0
  268. package/dist/lib/telemetry.js.map +1 -0
  269. package/dist/lib/template-schema.js +319 -0
  270. package/dist/lib/template-schema.js.map +1 -0
  271. package/dist/lib/template-validation.js +82 -0
  272. package/dist/lib/template-validation.js.map +1 -0
  273. package/dist/lib/voices.js +533 -0
  274. package/dist/lib/voices.js.map +1 -0
  275. package/dist/mcp/client.js +138 -0
  276. package/dist/mcp/client.js.map +1 -0
  277. package/dist/mcp/index.js +178 -0
  278. package/dist/mcp/index.js.map +1 -0
  279. package/dist/mcp/tools.js +355 -0
  280. package/dist/mcp/tools.js.map +1 -0
  281. package/package.json +2 -1
  282. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js +0 -6077
  283. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js.map +0 -69
  284. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js +0 -6318
  285. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js.map +0 -71
  286. package/.next/dev/types/cache-life.d.ts +0 -145
  287. package/.next/dev/types/routes.d.ts +0 -84
  288. package/.next/dev/types/validator.ts +0 -178
  289. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_buildManifest.js +0 -0
  290. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_clientMiddlewareManifest.js +0 -0
  291. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_ssgManifest.js +0 -0
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * SSE stream — `/chats/events`. Pushes chat-list mutations
4
+ * (created/updated/deleted) so the cockpit sidebar shows freshly-fired
5
+ * chats — including those created via MCP or external curl — without
6
+ * waiting for a poll cycle.
7
+ *
8
+ * The payload is intentionally minimal: `{ chatId, kind, ts }`. The
9
+ * client refetches the list on any event; we don't try to patch state
10
+ * incrementally because the list is short (12 most recent) and the
11
+ * round-trip is cheap.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.registerChatEventsRoute = registerChatEventsRoute;
15
+ const chat_events_bus_js_1 = require("../../lib/chat-events-bus.js");
16
+ const HEARTBEAT_INTERVAL_MS = 25_000;
17
+ function registerChatEventsRoute(fastify) {
18
+ fastify.get('/chats/events', async (_request, reply) => {
19
+ reply.hijack();
20
+ reply.raw.writeHead(200, {
21
+ 'Content-Type': 'text/event-stream',
22
+ 'Cache-Control': 'no-cache',
23
+ Connection: 'keep-alive',
24
+ });
25
+ // Initial hello so the client knows the channel is open. Some
26
+ // browsers (and proxies) buffer the first chunk until enough bytes
27
+ // arrive — sending a comment line forces the headers through.
28
+ reply.raw.write(': connected\n\n');
29
+ const onChange = (ev) => {
30
+ try {
31
+ reply.raw.write(`data: ${JSON.stringify(ev)}\n\n`);
32
+ }
33
+ catch {
34
+ /* connection closed mid-write */
35
+ }
36
+ };
37
+ chat_events_bus_js_1.chatEventsBus.on('change', onChange);
38
+ // Heartbeat keeps idle connections alive across NAT timeouts and
39
+ // makes EventSource's 'error' fire promptly when the daemon dies.
40
+ const heartbeat = setInterval(() => {
41
+ try {
42
+ reply.raw.write(': hb\n\n');
43
+ }
44
+ catch {
45
+ /* ignore */
46
+ }
47
+ }, HEARTBEAT_INTERVAL_MS);
48
+ const cleanup = () => {
49
+ clearInterval(heartbeat);
50
+ chat_events_bus_js_1.chatEventsBus.off('change', onChange);
51
+ try {
52
+ reply.raw.end();
53
+ }
54
+ catch {
55
+ /* already closed */
56
+ }
57
+ };
58
+ reply.raw.on('close', cleanup);
59
+ reply.raw.on('error', cleanup);
60
+ });
61
+ }
62
+ //# sourceMappingURL=chats-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chats-events.js","sourceRoot":"","sources":["../../../src/daemon/routes/chats-events.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAOH,0DAgDC;AApDD,qEAAmF;AAEnF,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAErC,SAAgB,uBAAuB,CAAC,OAAwB;IAC9D,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;QACrD,KAAK,CAAC,MAAM,EAAE,CAAC;QAEf,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACvB,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,UAAU,EAAE,YAAY;SACzB,CAAC,CAAC;QAEH,8DAA8D;QAC9D,mEAAmE;QACnE,8DAA8D;QAC9D,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAEnC,MAAM,QAAQ,GAAG,CAAC,EAAmB,EAAQ,EAAE;YAC7C,IAAI,CAAC;gBACH,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;YACrD,CAAC;YAAC,MAAM,CAAC;gBACP,iCAAiC;YACnC,CAAC;QACH,CAAC,CAAC;QAEF,kCAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAErC,iEAAiE;QACjE,kEAAkE;QAClE,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YACjC,IAAI,CAAC;gBACH,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC,EAAE,qBAAqB,CAAC,CAAC;QAE1B,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,aAAa,CAAC,SAAS,CAAC,CAAC;YACzB,kCAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACtC,IAAI,CAAC;gBACH,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YAClB,CAAC;YAAC,MAAM,CAAC;gBACP,oBAAoB;YACtB,CAAC;QACH,CAAC,CAAC;QAEF,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/B,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ /**
3
+ * SSE stream handler — `/api/v1/chats/:id/stream`. Multiplexes onto an
4
+ * active runChat via runner-multiplex; replays past phase_events from
5
+ * DB so a late-attach run page sees history immediately.
6
+ *
7
+ * ─────────────────────────────────────────────────────────────────────
8
+ * SSE event vocabulary — frozen v0.7. Adding a new event TYPE is
9
+ * non-breaking (consumers ignore unknown types). Adding a new payload
10
+ * KEY to an existing type is non-breaking. RENAMING a type or REMOVING
11
+ * a required key is a wire break — bump /api/v2 first.
12
+ *
13
+ * | type | required payload |
14
+ * |------------------|--------------------------------------------------|
15
+ * | phase_start | chatId, phaseIdx, ts |
16
+ * | phase_progress | chatId, phaseIdx, round, role, agent, elapsedMs |
17
+ * | phase_done | chatId, phaseIdx, ts |
18
+ * | participant_done | chatId, phaseIdx, round, role, agent |
19
+ * | text_delta | chatId, text, ts |
20
+ * | tool_call | chatId, tool, args, ts |
21
+ * | cli_error | chatId, error: { code, message, lineage? } |
22
+ * | error | chatId, error: { code, message, details? } |
23
+ * | chat_done | chatId, status, verdict, replay?, ts |
24
+ *
25
+ * All `error.code` values come from the canonical enum in
26
+ * src/daemon/api-response.ts. `ts` is unix ms (grandfathered — we
27
+ * intentionally did NOT convert to ISO 8601 in the v0.7 freeze; new
28
+ * fields shipped from v0.8 onward should use ISO 8601).
29
+ * ─────────────────────────────────────────────────────────────────────
30
+ */
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.registerChatStreamRoute = registerChatStreamRoute;
33
+ const index_js_1 = require("../../lib/db/index.js");
34
+ const logger_js_1 = require("../../lib/logger.js");
35
+ const api_response_js_1 = require("../api-response.js");
36
+ const runner_multiplex_js_1 = require("../runner-multiplex.js");
37
+ const template_cache_js_1 = require("../template-cache.js");
38
+ const chats_validation_js_1 = require("./chats-validation.js");
39
+ const TERMINAL_STATUSES = [
40
+ 'approved',
41
+ 'merged',
42
+ 'blocked',
43
+ 'cancelled',
44
+ 'failed',
45
+ 'no_review',
46
+ ];
47
+ function registerChatStreamRoute(fastify, { tmuxMgr, errorDetector }) {
48
+ fastify.get('/chats/:id/stream', async (request, reply) => {
49
+ const param = request.params.id;
50
+ if (!(0, chats_validation_js_1.isValidChatId)(param)) {
51
+ reply.code(400);
52
+ return (0, api_response_js_1.errorResponse)('validation', 'invalid chat id');
53
+ }
54
+ try {
55
+ const chat = await index_js_1.chats.getBySlugOrId(param);
56
+ if (!chat) {
57
+ reply.code(404);
58
+ return (0, api_response_js_1.errorResponse)('not_found', 'chat not found');
59
+ }
60
+ // From here on, `chatId` is the row's authoritative ULID — every
61
+ // downstream key (activeRuns, subscribers, runWithMultiplex) uses
62
+ // the ULID, never the slug.
63
+ const chatId = chat.id;
64
+ const tmplRow = await index_js_1.templates.getById(chat.template_id);
65
+ if (!tmplRow) {
66
+ reply.code(404);
67
+ return (0, api_response_js_1.errorResponse)('not_found', 'template not found');
68
+ }
69
+ // Cached by templateId + updated_at so SSE re-attaches don't
70
+ // re-parse on every browser refresh.
71
+ let template;
72
+ try {
73
+ template = (0, template_cache_js_1.getParsedTemplate)(tmplRow.id, tmplRow.yaml, tmplRow.updated_at);
74
+ }
75
+ catch (parseError) {
76
+ reply.code(400);
77
+ return (0, api_response_js_1.errorResponse)('validation', `Invalid template: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
78
+ }
79
+ // Take ownership of the underlying socket. Without `reply.hijack()`
80
+ // Fastify would auto-end the response when this async handler
81
+ // returns — the SSE would close immediately after the initial
82
+ // replay even though we still want to keep streaming live events.
83
+ reply.hijack();
84
+ // Set SSE headers.
85
+ //
86
+ // Do NOT add Content-Encoding: gzip here, and do not stick a
87
+ // buffering proxy in front of this route. SSE is line-delimited
88
+ // (`data: ...\n\n`); gzip's compression window batches bytes
89
+ // until flush, which collapses many small events into one frame
90
+ // and breaks the client's per-event parser.
91
+ reply.raw.writeHead(200, {
92
+ 'Content-Type': 'text/event-stream',
93
+ 'Cache-Control': 'no-cache',
94
+ Connection: 'keep-alive',
95
+ });
96
+ const subscriber = {
97
+ paused: false,
98
+ queue: [],
99
+ write: (line) => {
100
+ try {
101
+ return reply.raw.write(line);
102
+ }
103
+ catch {
104
+ /* connection closed mid-write */
105
+ return false;
106
+ }
107
+ },
108
+ close: () => {
109
+ reply.raw.end();
110
+ },
111
+ };
112
+ // Replay past phase_events from DB so a late-attach run page sees
113
+ // history immediately instead of a blank screen. Best-effort —
114
+ // DB doesn't capture phase_progress or cli_error, so live tail is
115
+ // still richer.
116
+ //
117
+ // Backpressure: when subscriber.write() returns false (kernel
118
+ // buffer full), every subsequent reconstructed event must go to
119
+ // subscriber.queue — NOT keep calling write() into a paused
120
+ // socket. The drain handler below flushes the queue once the
121
+ // kernel buffer recovers.
122
+ const pastEvents = await index_js_1.phaseEvents.list(chatId);
123
+ for (const ev of pastEvents) {
124
+ const reconstructed = (0, runner_multiplex_js_1.phaseEventToRunnerEvent)(chatId, ev);
125
+ if (!reconstructed)
126
+ continue;
127
+ const line = `data: ${JSON.stringify(reconstructed)}\n\n`;
128
+ if (subscriber.paused) {
129
+ subscriber.queue.push(line);
130
+ continue;
131
+ }
132
+ if (!subscriber.write(line)) {
133
+ subscriber.paused = true;
134
+ }
135
+ }
136
+ // If chat is already terminal, replay is enough — close after
137
+ // sending a synthetic chat_done so the client knows it's caught up.
138
+ if (TERMINAL_STATUSES.includes(chat.status)) {
139
+ const line = `data: ${JSON.stringify({
140
+ chatId,
141
+ type: 'chat_done',
142
+ payload: {
143
+ status: chat.status === 'approved' ? 'completed' : chat.status,
144
+ verdict: chat.status === 'approved' ? 'approved' : chat.status,
145
+ ...(chat.pr_url ? { prUrl: chat.pr_url } : {}),
146
+ ...(chat.ship_error ? { shipError: chat.ship_error } : {}),
147
+ replay: true,
148
+ },
149
+ ts: chat.finished_at ?? Date.now(),
150
+ })}\n\n`;
151
+ subscriber.write(line);
152
+ reply.raw.end();
153
+ return;
154
+ }
155
+ // CRITICAL: clear `paused` unconditionally on drain even if the
156
+ // queue is empty. A write that returns false with no queued
157
+ // follow-up at drain time would otherwise leave the subscriber
158
+ // permanently paused — every later event would funnel into the
159
+ // queue (because dispatch in onEvent only queues when paused),
160
+ // and no further drain ever fires (the kernel buffer is already
161
+ // empty). Order: unpause first, then flush whatever queued up.
162
+ const onDrain = () => {
163
+ if (!subscriber.paused)
164
+ return;
165
+ subscriber.paused = false;
166
+ while (subscriber.queue.length > 0) {
167
+ const queuedLine = subscriber.queue.shift();
168
+ const canContinue = subscriber.write(queuedLine);
169
+ if (!canContinue) {
170
+ subscriber.paused = true;
171
+ break;
172
+ }
173
+ }
174
+ };
175
+ reply.raw.on('drain', onDrain);
176
+ // Either attach to an in-flight runner or fire a fresh one. The
177
+ // singleton invariant — exactly one runChat per chatId at any
178
+ // time — is what fixes the load-spike bug.
179
+ const existing = (0, runner_multiplex_js_1.getActiveRun)(chatId);
180
+ if (existing) {
181
+ existing.subscribers.add(subscriber);
182
+ request.raw.on('close', () => {
183
+ existing.subscribers.delete(subscriber);
184
+ reply.raw.removeListener('drain', onDrain);
185
+ });
186
+ return;
187
+ }
188
+ // No active run — fire one and register. Persistence + status
189
+ // updates are part of the multiplexed onEvent so they happen
190
+ // exactly once even when multiple SSEs subscribe.
191
+ const run = (0, runner_multiplex_js_1.runWithMultiplex)({ chatId, template, chat, tmuxMgr, errorDetector });
192
+ // Chain `.catch` on the ActiveRun.promise so an async rejection
193
+ // from runChat doesn't escape as an unhandled rejection. Node
194
+ // >= 15 hard-exits the daemon on those — exactly the failure the
195
+ // launch-eve gemini review flagged on this stream-attached path.
196
+ run.promise.catch((err) => {
197
+ (0, logger_js_1.chatLogger)(chatId).error({ err: err instanceof Error ? err.message : String(err) }, 'stream-attached runner failed');
198
+ });
199
+ run.subscribers.add(subscriber);
200
+ request.raw.on('close', () => {
201
+ run.subscribers.delete(subscriber);
202
+ reply.raw.removeListener('drain', onDrain);
203
+ });
204
+ return;
205
+ }
206
+ catch (error) {
207
+ const message = error instanceof Error ? error.message : 'Unknown error';
208
+ request.log.error(error);
209
+ // Tell Fastify "I own this socket now" before writing on
210
+ // reply.raw, even on the error path — without this, when the
211
+ // throw happens BEFORE the success-path reply.hijack() (e.g. a
212
+ // DB error in chats.getBySlugOrId, or the YAML parse path
213
+ // failing), Fastify will try to auto-serialize the handler's
214
+ // return value AFTER we've already written headers + an error
215
+ // frame. That double-write throws ERR_HTTP_HEADERS_SENT. hijack()
216
+ // here is idempotent if already called.
217
+ try {
218
+ reply.hijack();
219
+ }
220
+ catch {
221
+ /* already hijacked */
222
+ }
223
+ if (!reply.raw.headersSent) {
224
+ reply.raw.writeHead(200, {
225
+ 'Content-Type': 'text/event-stream',
226
+ 'Cache-Control': 'no-cache',
227
+ Connection: 'keep-alive',
228
+ });
229
+ // SSE error event uses the canonical envelope shape so clients
230
+ // can rely on `error.code` + `error.message` regardless of
231
+ // whether the failure surfaced over REST or SSE.
232
+ reply.raw.write(`data: ${JSON.stringify({
233
+ type: 'error',
234
+ error: { code: 'internal', message },
235
+ })}\n\n`);
236
+ }
237
+ reply.raw.end();
238
+ }
239
+ });
240
+ }
241
+ //# sourceMappingURL=chats-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chats-stream.js","sourceRoot":"","sources":["../../../src/daemon/routes/chats-stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isValidChatId = isValidChatId;
4
+ // Permissive chatId validator — the runner uses ULIDs (26-char Base32)
5
+ // but we keep older fixtures + the MCP create_chat surface in mind, so
6
+ // allow any short alphanumeric/dash string. Belt-and-braces against
7
+ // unbounded user input becoming a filesystem path or log file name (DoS
8
+ // via 100 MB id).
9
+ const CHAT_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
10
+ function isValidChatId(value) {
11
+ return typeof value === 'string' && CHAT_ID_RE.test(value);
12
+ }
13
+ //# sourceMappingURL=chats-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chats-validation.js","sourceRoot":"","sources":["../../../src/daemon/routes/chats-validation.ts"],"names":[],"mappings":";;AAOA,sCAEC;AATD,uEAAuE;AACvE,uEAAuE;AACvE,oEAAoE;AACpE,wEAAwE;AACxE,kBAAkB;AAClB,MAAM,UAAU,GAAG,uBAAuB,CAAC;AAE3C,SAAgB,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC"}