chorus-codes 0.7.0 → 0.7.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.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/cache/.previewinfo +1 -1
- package/.next/cache/.rscinfo +1 -1
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/new.html +1 -1
- package/.next/server/app/new.rsc +1 -1
- package/.next/server/app/new.segments/_full.segment.rsc +1 -1
- package/.next/server/app/new.segments/_head.segment.rsc +1 -1
- package/.next/server/app/new.segments/_index.segment.rsc +1 -1
- package/.next/server/app/new.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/new.segments/new/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/new.segments/new.segment.rsc +1 -1
- package/.next/server/app/onboarding.html +1 -1
- package/.next/server/app/onboarding.rsc +1 -1
- package/.next/server/app/onboarding.segments/_full.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_index.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
- package/.next/server/app/personas.html +1 -1
- package/.next/server/app/personas.rsc +1 -1
- package/.next/server/app/personas.segments/_full.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_head.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_index.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/personas.segments/personas/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/personas.segments/personas.segment.rsc +1 -1
- package/.next/server/app/settings.html +1 -1
- package/.next/server/app/settings.rsc +1 -1
- package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/templates.html +1 -1
- package/.next/server/app/templates.rsc +1 -1
- package/.next/server/app/templates.segments/_full.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_head.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_index.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/templates.segments/templates/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/templates.segments/templates.segment.rsc +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/trace +1 -1
- package/.next/trace-build +1 -1
- package/README.md +38 -15
- package/dist/cli/commands/doctor.js +116 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.js +211 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/start.js +298 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.js +54 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.js +97 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/connect.js +108 -0
- package/dist/cli/connect.js.map +1 -0
- package/dist/cli/index.js +99 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/port-utils.js +260 -0
- package/dist/cli/port-utils.js.map +1 -0
- package/dist/cli/runtime-env.js +60 -0
- package/dist/cli/runtime-env.js.map +1 -0
- package/dist/cli/shared.js +54 -0
- package/dist/cli/shared.js.map +1 -0
- package/dist/cli/ui.js +60 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/daemon/agents/claude.js +98 -0
- package/dist/daemon/agents/claude.js.map +1 -0
- package/dist/daemon/agents/codex.js +160 -0
- package/dist/daemon/agents/codex.js.map +1 -0
- package/dist/daemon/agents/gemini.js +111 -0
- package/dist/daemon/agents/gemini.js.map +1 -0
- package/dist/daemon/agents/index.js +59 -0
- package/dist/daemon/agents/index.js.map +1 -0
- package/dist/daemon/agents/kimi.js +206 -0
- package/dist/daemon/agents/kimi.js.map +1 -0
- package/dist/daemon/agents/opencode.js +228 -0
- package/dist/daemon/agents/opencode.js.map +1 -0
- package/dist/daemon/agents/openrouter.js +274 -0
- package/dist/daemon/agents/openrouter.js.map +1 -0
- package/dist/daemon/agents/parsers/claude.js +63 -0
- package/dist/daemon/agents/parsers/claude.js.map +1 -0
- package/dist/daemon/agents/parsers/codex.js +51 -0
- package/dist/daemon/agents/parsers/codex.js.map +1 -0
- package/dist/daemon/agents/parsers/gemini.js +144 -0
- package/dist/daemon/agents/parsers/gemini.js.map +1 -0
- package/dist/daemon/agents/parsers/index.js +31 -0
- package/dist/daemon/agents/parsers/index.js.map +1 -0
- package/dist/daemon/agents/parsers/kimi.js +8 -0
- package/dist/daemon/agents/parsers/kimi.js.map +1 -0
- package/dist/daemon/agents/parsers/opencode.js +105 -0
- package/dist/daemon/agents/parsers/opencode.js.map +1 -0
- package/dist/daemon/agents/parsers/openrouter.js +69 -0
- package/dist/daemon/agents/parsers/openrouter.js.map +1 -0
- package/dist/daemon/agents/parsers/shared.js +17 -0
- package/dist/daemon/agents/parsers/shared.js.map +1 -0
- package/dist/daemon/agents/preflight.js +83 -0
- package/dist/daemon/agents/preflight.js.map +1 -0
- package/dist/daemon/agents/quote.js +45 -0
- package/dist/daemon/agents/quote.js.map +1 -0
- package/dist/daemon/agents/sandbox-guard.js +69 -0
- package/dist/daemon/agents/sandbox-guard.js.map +1 -0
- package/dist/daemon/agents/types.js +6 -0
- package/dist/daemon/agents/types.js.map +1 -0
- package/dist/daemon/api-response.js +65 -0
- package/dist/daemon/api-response.js.map +1 -0
- package/dist/daemon/error-detector.js +329 -0
- package/dist/daemon/error-detector.js.map +1 -0
- package/dist/daemon/headless.js +533 -0
- package/dist/daemon/headless.js.map +1 -0
- package/dist/daemon/index.js +333 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/openrouter.js +192 -0
- package/dist/daemon/openrouter.js.map +1 -0
- package/dist/daemon/orchestrators/claude.js +163 -0
- package/dist/daemon/orchestrators/claude.js.map +1 -0
- package/dist/daemon/orchestrators/codex.js +101 -0
- package/dist/daemon/orchestrators/codex.js.map +1 -0
- package/dist/daemon/orchestrators/cursor-windsurf.js +118 -0
- package/dist/daemon/orchestrators/cursor-windsurf.js.map +1 -0
- package/dist/daemon/orchestrators/gemini.js +108 -0
- package/dist/daemon/orchestrators/gemini.js.map +1 -0
- package/dist/daemon/orchestrators/index.js +90 -0
- package/dist/daemon/orchestrators/index.js.map +1 -0
- package/dist/daemon/orchestrators/kimi.js +108 -0
- package/dist/daemon/orchestrators/kimi.js.map +1 -0
- package/dist/daemon/orchestrators/opencode.js +152 -0
- package/dist/daemon/orchestrators/opencode.js.map +1 -0
- package/dist/daemon/orchestrators/shared.js +60 -0
- package/dist/daemon/orchestrators/shared.js.map +1 -0
- package/dist/daemon/output-watcher.js +131 -0
- package/dist/daemon/output-watcher.js.map +1 -0
- package/dist/daemon/participant-aborts.js +123 -0
- package/dist/daemon/participant-aborts.js.map +1 -0
- package/dist/daemon/reaper.js +46 -0
- package/dist/daemon/reaper.js.map +1 -0
- package/dist/daemon/routes/chats-events.js +62 -0
- package/dist/daemon/routes/chats-events.js.map +1 -0
- package/dist/daemon/routes/chats-stream.js +241 -0
- package/dist/daemon/routes/chats-stream.js.map +1 -0
- package/dist/daemon/routes/chats-validation.js +13 -0
- package/dist/daemon/routes/chats-validation.js.map +1 -0
- package/dist/daemon/routes/chats.js +545 -0
- package/dist/daemon/routes/chats.js.map +1 -0
- package/dist/daemon/routes/openrouter.js +103 -0
- package/dist/daemon/routes/openrouter.js.map +1 -0
- package/dist/daemon/routes/settings.js +199 -0
- package/dist/daemon/routes/settings.js.map +1 -0
- package/dist/daemon/routes/stats.js +155 -0
- package/dist/daemon/routes/stats.js.map +1 -0
- package/dist/daemon/routes/system.js +208 -0
- package/dist/daemon/routes/system.js.map +1 -0
- package/dist/daemon/routes/templates-personas.js +254 -0
- package/dist/daemon/routes/templates-personas.js.map +1 -0
- package/dist/daemon/routes/voices.js +139 -0
- package/dist/daemon/routes/voices.js.map +1 -0
- package/dist/daemon/runner/doer-driver.js +346 -0
- package/dist/daemon/runner/doer-driver.js.map +1 -0
- package/dist/daemon/runner/doer.js +336 -0
- package/dist/daemon/runner/doer.js.map +1 -0
- package/dist/daemon/runner/prior-round.js +140 -0
- package/dist/daemon/runner/prior-round.js.map +1 -0
- package/dist/daemon/runner/prompt-builder.js +292 -0
- package/dist/daemon/runner/prompt-builder.js.map +1 -0
- package/dist/daemon/runner/review-only-phase.js +103 -0
- package/dist/daemon/runner/review-only-phase.js.map +1 -0
- package/dist/daemon/runner/reviewer-driver.js +410 -0
- package/dist/daemon/runner/reviewer-driver.js.map +1 -0
- package/dist/daemon/runner/reviewer.js +384 -0
- package/dist/daemon/runner/reviewer.js.map +1 -0
- package/dist/daemon/runner/run-with-fallback.js +56 -0
- package/dist/daemon/runner/run-with-fallback.js.map +1 -0
- package/dist/daemon/runner/sanitize-name.js +8 -0
- package/dist/daemon/runner/sanitize-name.js.map +1 -0
- package/dist/daemon/runner/stream-file-writer.js +116 -0
- package/dist/daemon/runner/stream-file-writer.js.map +1 -0
- package/dist/daemon/runner/swap-sidecar.js +102 -0
- package/dist/daemon/runner/swap-sidecar.js.map +1 -0
- package/dist/daemon/runner/template-fallback.js +119 -0
- package/dist/daemon/runner/template-fallback.js.map +1 -0
- package/dist/daemon/runner/types.js +3 -0
- package/dist/daemon/runner/types.js.map +1 -0
- package/dist/daemon/runner/verdict.js +51 -0
- package/dist/daemon/runner/verdict.js.map +1 -0
- package/dist/daemon/runner-multiplex.js +364 -0
- package/dist/daemon/runner-multiplex.js.map +1 -0
- package/dist/daemon/runner.js +427 -0
- package/dist/daemon/runner.js.map +1 -0
- package/dist/daemon/ship.js +340 -0
- package/dist/daemon/ship.js.map +1 -0
- package/dist/daemon/template-cache.js +37 -0
- package/dist/daemon/template-cache.js.map +1 -0
- package/dist/daemon/tmux-types.js +9 -0
- package/dist/daemon/tmux-types.js.map +1 -0
- package/dist/daemon/tmux.js +341 -0
- package/dist/daemon/tmux.js.map +1 -0
- package/dist/lib/atomic-write.js +55 -0
- package/dist/lib/atomic-write.js.map +1 -0
- package/dist/lib/chat-events-bus.js +27 -0
- package/dist/lib/chat-events-bus.js.map +1 -0
- package/dist/lib/chat-slug.js +105 -0
- package/dist/lib/chat-slug.js.map +1 -0
- package/dist/lib/cli-detect.js +388 -0
- package/dist/lib/cli-detect.js.map +1 -0
- package/dist/lib/cli-health.js +156 -0
- package/dist/lib/cli-health.js.map +1 -0
- package/dist/lib/cli-paths.js +113 -0
- package/dist/lib/cli-paths.js.map +1 -0
- package/dist/lib/cli-precheck.js +141 -0
- package/dist/lib/cli-precheck.js.map +1 -0
- package/dist/lib/db/chats.js +244 -0
- package/dist/lib/db/chats.js.map +1 -0
- package/dist/lib/db/connection.js +254 -0
- package/dist/lib/db/connection.js.map +1 -0
- package/dist/lib/db/index.js +34 -0
- package/dist/lib/db/index.js.map +1 -0
- package/dist/lib/db/personas.js +65 -0
- package/dist/lib/db/personas.js.map +1 -0
- package/dist/lib/db/phase-events.js +172 -0
- package/dist/lib/db/phase-events.js.map +1 -0
- package/dist/lib/db/secrets.js +53 -0
- package/dist/lib/db/secrets.js.map +1 -0
- package/dist/lib/db/settings.js +47 -0
- package/dist/lib/db/settings.js.map +1 -0
- package/dist/lib/db/templates.js +75 -0
- package/dist/lib/db/templates.js.map +1 -0
- package/dist/lib/db/voices.js +184 -0
- package/dist/lib/db/voices.js.map +1 -0
- package/dist/lib/lineage-maps.js +200 -0
- package/dist/lib/lineage-maps.js.map +1 -0
- package/dist/lib/logger.js +186 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/personas.js +117 -0
- package/dist/lib/personas.js.map +1 -0
- package/dist/lib/runtime-path.js +222 -0
- package/dist/lib/runtime-path.js.map +1 -0
- package/dist/lib/settings/billing.js +58 -0
- package/dist/lib/settings/billing.js.map +1 -0
- package/dist/lib/settings/permissions.js +81 -0
- package/dist/lib/settings/permissions.js.map +1 -0
- package/dist/lib/settings/transport.js +113 -0
- package/dist/lib/settings/transport.js.map +1 -0
- package/dist/lib/telemetry.js +290 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/template-schema.js +319 -0
- package/dist/lib/template-schema.js.map +1 -0
- package/dist/lib/template-validation.js +82 -0
- package/dist/lib/template-validation.js.map +1 -0
- package/dist/lib/voices.js +533 -0
- package/dist/lib/voices.js.map +1 -0
- package/dist/mcp/client.js +138 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/index.js +178 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/tools.js +355 -0
- package/dist/mcp/tools.js.map +1 -0
- package/package.json +2 -1
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js +0 -6077
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js.map +0 -69
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js +0 -6318
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js.map +0 -71
- package/.next/dev/types/cache-life.d.ts +0 -145
- package/.next/dev/types/routes.d.ts +0 -84
- package/.next/dev/types/validator.ts +0 -178
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_buildManifest.js +0 -0
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_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"}
|