chorus-codes 0.8.26 → 0.8.28

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 (101) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +2 -2
  3. package/.next/prerender-manifest.json +3 -3
  4. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  5. package/.next/server/app/_global-error.html +1 -1
  6. package/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/server/app/_not-found/page_client-reference-manifest.js +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/connect/page_client-reference-manifest.js +1 -1
  23. package/.next/server/app/demo/[scenario]/page_client-reference-manifest.js +1 -1
  24. package/.next/server/app/new/page_client-reference-manifest.js +1 -1
  25. package/.next/server/app/new.html +1 -1
  26. package/.next/server/app/new.rsc +2 -2
  27. package/.next/server/app/new.segments/_full.segment.rsc +2 -2
  28. package/.next/server/app/new.segments/_head.segment.rsc +1 -1
  29. package/.next/server/app/new.segments/_index.segment.rsc +1 -1
  30. package/.next/server/app/new.segments/_tree.segment.rsc +1 -1
  31. package/.next/server/app/new.segments/new/__PAGE__.segment.rsc +2 -2
  32. package/.next/server/app/new.segments/new.segment.rsc +1 -1
  33. package/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  34. package/.next/server/app/onboarding.html +1 -1
  35. package/.next/server/app/onboarding.rsc +2 -2
  36. package/.next/server/app/onboarding.segments/_full.segment.rsc +2 -2
  37. package/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
  38. package/.next/server/app/onboarding.segments/_index.segment.rsc +1 -1
  39. package/.next/server/app/onboarding.segments/_tree.segment.rsc +1 -1
  40. package/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +2 -2
  41. package/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
  42. package/.next/server/app/page_client-reference-manifest.js +1 -1
  43. package/.next/server/app/personas/page_client-reference-manifest.js +1 -1
  44. package/.next/server/app/personas.html +1 -1
  45. package/.next/server/app/personas.rsc +2 -2
  46. package/.next/server/app/personas.segments/_full.segment.rsc +2 -2
  47. package/.next/server/app/personas.segments/_head.segment.rsc +1 -1
  48. package/.next/server/app/personas.segments/_index.segment.rsc +1 -1
  49. package/.next/server/app/personas.segments/_tree.segment.rsc +1 -1
  50. package/.next/server/app/personas.segments/personas/__PAGE__.segment.rsc +2 -2
  51. package/.next/server/app/personas.segments/personas.segment.rsc +1 -1
  52. package/.next/server/app/runs/[runId]/page_client-reference-manifest.js +1 -1
  53. package/.next/server/app/runs/page_client-reference-manifest.js +1 -1
  54. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  55. package/.next/server/app/settings/permissions/page_client-reference-manifest.js +1 -1
  56. package/.next/server/app/settings.html +1 -1
  57. package/.next/server/app/settings.rsc +2 -2
  58. package/.next/server/app/settings.segments/_full.segment.rsc +2 -2
  59. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  60. package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  61. package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  62. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
  63. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  64. package/.next/server/app/templates/page_client-reference-manifest.js +1 -1
  65. package/.next/server/app/templates.html +1 -1
  66. package/.next/server/app/templates.rsc +2 -2
  67. package/.next/server/app/templates.segments/_full.segment.rsc +2 -2
  68. package/.next/server/app/templates.segments/_head.segment.rsc +1 -1
  69. package/.next/server/app/templates.segments/_index.segment.rsc +1 -1
  70. package/.next/server/app/templates.segments/_tree.segment.rsc +1 -1
  71. package/.next/server/app/templates.segments/templates/__PAGE__.segment.rsc +2 -2
  72. package/.next/server/app/templates.segments/templates.segment.rsc +1 -1
  73. package/.next/server/chunks/189.js +1 -1
  74. package/.next/server/chunks/325.js +1 -1
  75. package/.next/server/chunks/681.js +1 -1
  76. package/.next/server/middleware-build-manifest.js +1 -1
  77. package/.next/server/pages/404.html +1 -1
  78. package/.next/server/pages/500.html +1 -1
  79. package/.next/server/server-reference-manifest.json +1 -1
  80. package/.next/static/chunks/{245-e103518e1c6037c0.js → 245-203bd8285e6b0858.js} +1 -1
  81. package/.next/static/chunks/641-02dbc18bdc194ee1.js +1 -0
  82. package/.next/trace +20 -20
  83. package/.next/trace-build +1 -1
  84. package/README.md +22 -0
  85. package/bin/chorus.mjs +87 -5
  86. package/dist/cli/commands/diagnose.js +404 -0
  87. package/dist/cli/commands/diagnose.js.map +1 -0
  88. package/dist/cli/crash-hook.js +135 -0
  89. package/dist/cli/crash-hook.js.map +1 -0
  90. package/dist/cli/index.js +2 -0
  91. package/dist/cli/index.js.map +1 -1
  92. package/dist/daemon/runner/fallback-registry.js +110 -0
  93. package/dist/daemon/runner/fallback-registry.js.map +1 -0
  94. package/dist/daemon/runner/reviewer-driver.js +68 -23
  95. package/dist/daemon/runner/reviewer-driver.js.map +1 -1
  96. package/dist/daemon/runner/template-fallback.js +22 -8
  97. package/dist/daemon/runner/template-fallback.js.map +1 -1
  98. package/package.json +1 -1
  99. package/.next/static/chunks/641-2908cb9553b8753a.js +0 -1
  100. /package/.next/static/{eOeXty5cBGWg7xnmtF6ST → NjUsrVtX8A7dE29z5nGfv}/_buildManifest.js +0 -0
  101. /package/.next/static/{eOeXty5cBGWg7xnmtF6ST → NjUsrVtX8A7dE29z5nGfv}/_ssgManifest.js +0 -0
package/.next/trace-build CHANGED
@@ -1 +1 @@
1
- [{"name":"run-webpack","duration":10796114,"timestamp":6766667988726,"id":14,"parentId":1,"tags":{},"startTime":1778158038415,"traceId":"96ba550fd6eb03e5"},{"name":"run-typescript","duration":5584072,"timestamp":6766678787710,"id":2118,"parentId":1,"tags":{},"startTime":1778158049214,"traceId":"96ba550fd6eb03e5"},{"name":"static-check","duration":391682,"timestamp":6766684429367,"id":2121,"parentId":1,"tags":{},"startTime":1778158054855,"traceId":"96ba550fd6eb03e5"},{"name":"static-generation","duration":897815,"timestamp":6766685736633,"id":2161,"parentId":1,"tags":{},"startTime":1778158056163,"traceId":"96ba550fd6eb03e5"},{"name":"collect-build-traces","duration":6311220,"timestamp":6766684821443,"id":2158,"parentId":1,"tags":{},"startTime":1778158055247,"traceId":"96ba550fd6eb03e5"},{"name":"telemetry-flush","duration":35,"timestamp":6766691134339,"id":2170,"parentId":1,"tags":{},"startTime":1778158061560,"traceId":"96ba550fd6eb03e5"},{"name":"next-build","duration":23236409,"timestamp":6766667897975,"id":1,"tags":{"buildMode":"default","version":"16.2.4","bundler":"webpack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1778158038324,"traceId":"96ba550fd6eb03e5"}]
1
+ [{"name":"run-webpack","duration":11102656,"timestamp":6838567862179,"id":14,"parentId":1,"tags":{},"startTime":1778229938288,"traceId":"5cf28171087389e4"},{"name":"run-typescript","duration":5758387,"timestamp":6838578968058,"id":2118,"parentId":1,"tags":{},"startTime":1778229949394,"traceId":"5cf28171087389e4"},{"name":"static-check","duration":445357,"timestamp":6838584777547,"id":2121,"parentId":1,"tags":{},"startTime":1778229955204,"traceId":"5cf28171087389e4"},{"name":"static-generation","duration":1411537,"timestamp":6838585518579,"id":2161,"parentId":1,"tags":{},"startTime":1778229955945,"traceId":"5cf28171087389e4"},{"name":"collect-build-traces","duration":6426440,"timestamp":6838585223302,"id":2158,"parentId":1,"tags":{},"startTime":1778229955649,"traceId":"5cf28171087389e4"},{"name":"telemetry-flush","duration":31,"timestamp":6838591651453,"id":2170,"parentId":1,"tags":{},"startTime":1778229962077,"traceId":"5cf28171087389e4"},{"name":"next-build","duration":23887132,"timestamp":6838567764361,"id":1,"tags":{"buildMode":"default","version":"16.2.4","bundler":"webpack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1778229938190,"traceId":"5cf28171087389e4"}]
package/README.md CHANGED
@@ -328,10 +328,32 @@ chorus start --ui # boot + open browser
328
328
  chorus stop # shut it down
329
329
  chorus status # is it running?
330
330
  chorus doctor # diagnose AI tool detection / sandbox issues
331
+ chorus diagnose # print a redacted diagnostic bundle for bug reports
331
332
  ```
332
333
 
333
334
  ---
334
335
 
336
+ ## Reporting bugs
337
+
338
+ When something goes wrong, run:
339
+
340
+ ```bash
341
+ chorus diagnose
342
+ ```
343
+
344
+ It prints a fenced markdown block with: chorus version, running daemon
345
+ version (and a **VERSION MISMATCH** flag if the CLI was upgraded but the
346
+ daemon hasn't been restarted), node + OS + arch, daemon health, DB
347
+ counts, CLI detection, the latest crash dump if any, and the last 50
348
+ lines of `daemon.log`. Paste the block into a new issue at
349
+ <https://github.com/chorus-codes/chorus/issues/new>.
350
+
351
+ If chorus crashes hard (uncaught exception during boot — common on
352
+ older Node + Windows combos), a self-contained crash log is written to
353
+ `~/.chorus/crashes/<timestamp>.log`. Attach it to the issue.
354
+
355
+ ---
356
+
335
357
  ## Telemetry
336
358
 
337
359
  Chorus pings home once on startup and once every 24h. The payload is fixed:
package/bin/chorus.mjs CHANGED
@@ -13,18 +13,100 @@ if (nodeMajor < 20) {
13
13
  process.exit(1);
14
14
  }
15
15
 
16
- import { existsSync } from "node:fs";
17
- import { fileURLToPath } from "node:url";
18
- import { dirname, resolve } from "node:path";
16
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
+ import { homedir } from "node:os";
18
+ import { fileURLToPath, pathToFileURL } from "node:url";
19
+ import { dirname, join, resolve } from "node:path";
20
+
21
+ // Crash hook — installed BEFORE any other import so it captures early
22
+ // startup failures. The src/cli/crash-hook.ts version is the testable
23
+ // canonical source; this is its zero-dependency twin, kept inline so it
24
+ // works even if `await import(distEntry)` itself throws (e.g. the Node
25
+ // 25 + Windows ESM URL scheme bug that motivated this work).
26
+ //
27
+ // Field set must stay in sync with src/cli/crash-hook.ts buildCrashLog
28
+ // (timestamp, source, chorus, node, platform, argv, cwd, uptime_ms).
29
+ // Drift means the maintainer has to read two formats. The package
30
+ // version is read from package.json beside this file rather than
31
+ // importing pkg from src — that import would itself need to load via
32
+ // dist/src and could fail in the very situations this hook exists for.
33
+ const ISSUE_URL = "https://github.com/chorus-codes/chorus/issues/new";
34
+
35
+ function readChorusVersion() {
36
+ try {
37
+ const __dn = dirname(fileURLToPath(import.meta.url));
38
+ const raw = readFileSync(resolve(__dn, "..", "package.json"), "utf-8");
39
+ const parsed = JSON.parse(raw);
40
+ return typeof parsed.version === "string" ? parsed.version : "(unknown)";
41
+ } catch {
42
+ return "(unknown)";
43
+ }
44
+ }
45
+
46
+ function installCrashHook() {
47
+ const crashDir = join(homedir(), ".chorus", "crashes");
48
+ const version = readChorusVersion();
49
+ const handle = (err, source) => {
50
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
51
+ const stack =
52
+ err instanceof Error
53
+ ? `${err.name}: ${err.message}\n${err.stack ?? "(no stack)"}`
54
+ : String(err);
55
+ const body = [
56
+ "# Chorus crash report",
57
+ "",
58
+ `timestamp: ${new Date().toISOString()}`,
59
+ `source: ${source}`,
60
+ `chorus: ${version}`,
61
+ `node: ${process.versions.node}`,
62
+ `platform: ${process.platform} ${process.arch}`,
63
+ `argv: ${process.argv.slice(1).join(" ")}`,
64
+ `cwd: ${process.cwd()}`,
65
+ `uptime_ms: ${Math.round(process.uptime() * 1000)}`,
66
+ "",
67
+ "## Error",
68
+ "",
69
+ stack,
70
+ "",
71
+ ].join("\n");
72
+ let written = null;
73
+ try {
74
+ mkdirSync(crashDir, { recursive: true });
75
+ written = join(crashDir, `${ts}.log`);
76
+ writeFileSync(written, body, "utf-8");
77
+ } catch {
78
+ written = null;
79
+ }
80
+ const headline =
81
+ err instanceof Error ? `${err.name}: ${err.message}` : String(err);
82
+ process.stderr.write(`\n✗ Chorus crashed (${source}): ${headline}\n`);
83
+ if (written) {
84
+ process.stderr.write(` Crash log saved to: ${written}\n`);
85
+ process.stderr.write(` Please attach it to a new issue: ${ISSUE_URL}\n`);
86
+ process.stderr.write(` Or run: chorus diagnose\n\n`);
87
+ } else {
88
+ process.stderr.write(` (could not write log to ${crashDir})\n`);
89
+ process.stderr.write(` Please file an issue at ${ISSUE_URL} with:\n`);
90
+ process.stderr.write(body + "\n\n");
91
+ }
92
+ process.exit(1);
93
+ };
94
+ process.on("uncaughtException", (err) => handle(err, "uncaughtException"));
95
+ process.on("unhandledRejection", (err) => handle(err, "unhandledRejection"));
96
+ }
97
+ installCrashHook();
19
98
 
20
99
  const __dirname = dirname(fileURLToPath(import.meta.url));
21
100
  const distEntry = resolve(__dirname, "../dist/cli/index.js");
22
101
 
102
+ // Use pathToFileURL so dynamic import works on Windows where absolute
103
+ // paths look like `C:\...` and Node 25 rejects them as bare URLs with
104
+ // ERR_UNSUPPORTED_ESM_URL_SCHEME (Reddit user `SelectSouth2582` 2026-05-08).
23
105
  if (existsSync(distEntry)) {
24
- await import(distEntry);
106
+ await import(pathToFileURL(distEntry).href);
25
107
  } else {
26
108
  // Dev / unpublished install — register tsx and run from src.
27
109
  const tsx = await import("tsx/esm/api");
28
110
  tsx.register();
29
- await import(resolve(__dirname, "../src/cli/index.ts"));
111
+ await import(pathToFileURL(resolve(__dirname, "../src/cli/index.ts")).href);
30
112
  }
@@ -0,0 +1,404 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports._testing = void 0;
7
+ exports.formatReport = formatReport;
8
+ exports.registerDiagnoseCommand = registerDiagnoseCommand;
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const os_1 = __importDefault(require("os"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const daemon_discovery_js_1 = require("../../lib/daemon-discovery.js");
13
+ const shared_js_1 = require("../shared.js");
14
+ const ISSUE_URL = 'https://github.com/chorus-codes/chorus/issues/new';
15
+ function abbreviateHome(p) {
16
+ const home = os_1.default.homedir();
17
+ return p.startsWith(home) ? '~' + p.slice(home.length) : p;
18
+ }
19
+ /**
20
+ * Resolve the bin path through any symlinks before classifying. A
21
+ * `sudo npm install -g chorus-codes` plants a symlink at
22
+ * `/usr/bin/chorus` (or `/usr/local/bin/chorus`) pointing into
23
+ * `/usr/lib/node_modules/chorus-codes/bin/chorus.mjs`. Node's
24
+ * `process.argv[1]` returns the SYMLINK path on Linux, not the
25
+ * resolved target — so the raw path matches none of the
26
+ * `node_modules` / `dist` / `.ts` substrings and `detectInstallMode`
27
+ * returns `'unknown'`.
28
+ *
29
+ * realpath fixes that. Wrapped in try/catch because a broken symlink
30
+ * (or a path we can't stat) shouldn't abort the diagnostic — we fall
31
+ * back to the original path so the report still tells you SOMETHING.
32
+ */
33
+ function resolveBinPath(rawBinPath) {
34
+ try {
35
+ return fs_1.default.realpathSync(rawBinPath);
36
+ }
37
+ catch {
38
+ return rawBinPath;
39
+ }
40
+ }
41
+ function detectInstallMode(binPath) {
42
+ if (binPath.includes('node_modules'))
43
+ return 'global-npm';
44
+ if (binPath.endsWith('.ts'))
45
+ return 'dev-tsx';
46
+ if (binPath.includes('/dist/') || binPath.includes('\\dist\\'))
47
+ return 'local-dist';
48
+ return 'unknown';
49
+ }
50
+ /**
51
+ * Drop log lines that are known-benign — they make a bug-report block
52
+ * look scarier than it is, and they're not actionable. Currently just
53
+ * Next.js 16's "failed to pipe response" trace which fires whenever an
54
+ * SSE client (browser tab) closes mid-stream — expected behaviour, not
55
+ * an error worth surfacing.
56
+ *
57
+ * Conservative: only filters specific known patterns. New noise types
58
+ * earn their entry by being explicitly added — we don't want to hide
59
+ * an actual bug because its message vaguely matches a regex.
60
+ */
61
+ function filterBenignNoise(text) {
62
+ if (!text || text.startsWith('('))
63
+ return { kept: text, filteredCount: 0 };
64
+ // The Next.js 16 SSE pipe-close trace spans ~15 lines starting from
65
+ // `⨯ Error: failed to pipe response` and ending after the inner
66
+ // `UND_ERR_SOCKET` block. We split on a `}` line that follows a
67
+ // `code: 'UND_ERR_SOCKET'` to find the end of the trace.
68
+ //
69
+ // Two cases to handle:
70
+ // 1. Full trace within the window — match opening line, drop until
71
+ // brace depth returns to <= 0.
72
+ // 2. Trace tail orphaned at start of window (the trace's opening
73
+ // line was BEFORE our raw-tail window). The orphan opens with
74
+ // stack/cause fragments like `at async ...{` or `[cause]: ...`
75
+ // with no preceding error line; keep dropping until we hit the
76
+ // end-of-trace `}` cluster. We detect this by looking back from
77
+ // a `code: 'UND_ERR_SOCKET'` line — if found in the first N
78
+ // lines without a preceding `failed to pipe response`, the
79
+ // window is starting mid-trace and we drop everything before
80
+ // and including the trace closer.
81
+ const lines = text.split('\n');
82
+ // Pass 1: find an orphan trace tail (UND_ERR_SOCKET without a
83
+ // preceding `failed to pipe response`) and trim everything before
84
+ // its closer.
85
+ const orphanIdx = lines.findIndex((l) => l.includes("code: 'UND_ERR_SOCKET'"));
86
+ let startIdx = 0;
87
+ let orphanCount = 0;
88
+ if (orphanIdx >= 0) {
89
+ let sawOpener = false;
90
+ for (let i = 0; i <= orphanIdx; i++) {
91
+ if (lines[i].includes('failed to pipe response')) {
92
+ sawOpener = true;
93
+ break;
94
+ }
95
+ }
96
+ if (!sawOpener) {
97
+ // Walk forward from orphanIdx to find the trace closer (a line
98
+ // that's just `}` or ` }` after which the next line either ends
99
+ // the cluster or starts new content).
100
+ let braceDepth = 0;
101
+ let closeIdx = orphanIdx;
102
+ for (let i = 0; i <= orphanIdx; i++) {
103
+ for (const ch of lines[i]) {
104
+ if (ch === '{')
105
+ braceDepth++;
106
+ else if (ch === '}')
107
+ braceDepth--;
108
+ }
109
+ }
110
+ for (let i = orphanIdx + 1; i < lines.length; i++) {
111
+ for (const ch of lines[i]) {
112
+ if (ch === '{')
113
+ braceDepth++;
114
+ else if (ch === '}')
115
+ braceDepth--;
116
+ }
117
+ if (braceDepth <= 0 && lines[i].trim().endsWith('}')) {
118
+ closeIdx = i;
119
+ break;
120
+ }
121
+ }
122
+ startIdx = closeIdx + 1;
123
+ orphanCount = 1;
124
+ }
125
+ }
126
+ // Pass 2: walk the rest of the window dropping full traces.
127
+ const out = [];
128
+ let dropping = false;
129
+ let braceDepth = 0;
130
+ let filteredCount = orphanCount;
131
+ for (let i = startIdx; i < lines.length; i++) {
132
+ const line = lines[i];
133
+ if (!dropping && line.includes('failed to pipe response')) {
134
+ dropping = true;
135
+ braceDepth = 0;
136
+ filteredCount++;
137
+ continue;
138
+ }
139
+ if (dropping) {
140
+ for (const ch of line) {
141
+ if (ch === '{')
142
+ braceDepth++;
143
+ else if (ch === '}')
144
+ braceDepth--;
145
+ }
146
+ if (braceDepth <= 0 && line.trim().endsWith('}')) {
147
+ dropping = false;
148
+ }
149
+ continue;
150
+ }
151
+ out.push(line);
152
+ }
153
+ return { kept: out.join('\n'), filteredCount };
154
+ }
155
+ function tailFile(p, lines) {
156
+ try {
157
+ if (!fs_1.default.existsSync(p))
158
+ return '(file not present)';
159
+ const content = fs_1.default.readFileSync(p, 'utf-8');
160
+ const all = content.split('\n');
161
+ return all.slice(-lines).join('\n').trim();
162
+ }
163
+ catch (err) {
164
+ return `(read failed: ${err instanceof Error ? err.message : String(err)})`;
165
+ }
166
+ }
167
+ async function gather() {
168
+ const chorusDir = path_1.default.join(os_1.default.homedir(), '.chorus');
169
+ const cliVersion = shared_js_1.pkg.version;
170
+ // Daemon state — look up daemon.json and probe /health for the
171
+ // currently-running version. Mismatch flag fires when CLI has been
172
+ // upgraded but the running daemon is still on the old version
173
+ // (the case the user hit after `npm install -g` without restart).
174
+ let runningDaemonVersion = null;
175
+ let healthyOnPort = null;
176
+ let daemonPidAlive = null;
177
+ let daemonJsonRaw = '(missing)';
178
+ try {
179
+ const info = (0, daemon_discovery_js_1.readDaemonInfo)();
180
+ if (info) {
181
+ daemonJsonRaw = JSON.stringify(info, null, 2);
182
+ try {
183
+ process.kill(info.daemonPid, 0);
184
+ daemonPidAlive = true;
185
+ }
186
+ catch (err) {
187
+ // ESRCH — process truly dead. EPERM — process exists but we
188
+ // don't own it (sudo'd daemon, container UID mismatch). Treat
189
+ // EPERM as alive — the daemon is there, we just can't signal
190
+ // it. Distinguishing matters: a sudo-started daemon with a
191
+ // user-mode CLI looks "dead" without this check, leading to
192
+ // wrong remediation advice in the bug report.
193
+ const code = err.code;
194
+ daemonPidAlive = code === 'EPERM';
195
+ }
196
+ const healthy = await (0, daemon_discovery_js_1.isDaemonHealthy)(info.daemonPort, 800);
197
+ if (healthy) {
198
+ healthyOnPort = info.daemonPort;
199
+ try {
200
+ // Mirror the 800ms cap from isDaemonHealthy. Without this,
201
+ // a daemon that passes the first health probe but stalls on
202
+ // the second response will hang `chorus diagnose` forever —
203
+ // the very state we're trying to capture in a bug report.
204
+ const ac = new AbortController();
205
+ const timer = setTimeout(() => ac.abort(), 800);
206
+ try {
207
+ const res = await fetch(`http://127.0.0.1:${info.daemonPort}/api/v1/health`, { signal: ac.signal });
208
+ const env = (await res.json());
209
+ if (env.data?.version)
210
+ runningDaemonVersion = env.data.version;
211
+ }
212
+ finally {
213
+ clearTimeout(timer);
214
+ }
215
+ }
216
+ catch {
217
+ /* health passed but version read failed/timed out — leave null */
218
+ }
219
+ }
220
+ }
221
+ }
222
+ catch {
223
+ /* daemon.json absent or malformed — leave defaults */
224
+ }
225
+ const mismatch = runningDaemonVersion !== null && runningDaemonVersion !== cliVersion;
226
+ // DB counts — best-effort. If the daemon is on an old version with
227
+ // a schema we can't read, we want to say "(unavailable)" not crash.
228
+ let chatsCount = '(unavailable)';
229
+ let voicesCount = '(unavailable)';
230
+ try {
231
+ const { getDb } = await import('../../lib/db/connection.js');
232
+ const db = await getDb();
233
+ const cr = await db.execute('SELECT COUNT(*) AS n FROM chats');
234
+ const vr = await db.execute('SELECT COUNT(*) AS n FROM voices');
235
+ chatsCount = Number(cr.rows[0].n);
236
+ voicesCount = Number(vr.rows[0].n);
237
+ }
238
+ catch (err) {
239
+ chatsCount = `(error: ${err instanceof Error ? err.message.slice(0, 80) : 'unknown'})`;
240
+ }
241
+ // Crashes — list crashes/ dir, surface the most recent file and a
242
+ // 20-line preview. The crash hook writes here; if diagnose finds
243
+ // entries, the user almost certainly wants to attach them.
244
+ let crashCount = 0;
245
+ let latestCrash = null;
246
+ try {
247
+ const crashDir = path_1.default.join(chorusDir, 'crashes');
248
+ if (fs_1.default.existsSync(crashDir)) {
249
+ const entries = fs_1.default
250
+ .readdirSync(crashDir)
251
+ .filter((n) => n.endsWith('.log'))
252
+ .map((n) => ({ name: n, full: path_1.default.join(crashDir, n) }))
253
+ .sort((a, b) => (a.name < b.name ? 1 : -1));
254
+ crashCount = entries.length;
255
+ if (entries.length > 0) {
256
+ const head = entries[0];
257
+ latestCrash = {
258
+ file: abbreviateHome(head.full),
259
+ preview: tailFile(head.full, 20),
260
+ };
261
+ }
262
+ }
263
+ }
264
+ catch {
265
+ /* crashes dir unreadable — leave defaults */
266
+ }
267
+ // CLI detection — reuse the same module doctor uses, but emit a
268
+ // compact summary (no PATH visibility section; that's doctor's job).
269
+ let clis = [];
270
+ try {
271
+ const { detectAllClis } = await import('../../lib/cli-detect.js');
272
+ const found = detectAllClis(true);
273
+ clis = found.map((d) => ({
274
+ id: d.id,
275
+ found: d.found,
276
+ path: d.path ? abbreviateHome(d.path) : undefined,
277
+ reason: d.reason,
278
+ }));
279
+ }
280
+ catch {
281
+ /* detection module load failed — leave empty */
282
+ }
283
+ return {
284
+ chorus: { cliVersion, runningDaemonVersion, mismatch },
285
+ runtime: {
286
+ node: process.versions.node,
287
+ platform: process.platform,
288
+ arch: process.arch,
289
+ release: os_1.default.release(),
290
+ },
291
+ install: {
292
+ // realpath the bin path so symlinks (e.g. /usr/bin/chorus →
293
+ // /usr/lib/node_modules/chorus-codes/bin/chorus.mjs from a
294
+ // global npm install) resolve before classification.
295
+ binPath: abbreviateHome(resolveBinPath(process.argv[1] ?? '(unknown)')),
296
+ mode: detectInstallMode(resolveBinPath(process.argv[1] ?? '')),
297
+ },
298
+ daemon: { daemonJson: daemonJsonRaw, daemonPidAlive, healthyOnPort },
299
+ db: { chats: chatsCount, voices: voicesCount },
300
+ logs: {
301
+ daemonTail: tailFile(path_1.default.join(chorusDir, 'logs', 'daemon.log'), 50),
302
+ // Strip Next.js 16's SSE pipe-close noise so the bug report
303
+ // doesn't look scary for what's actually a benign client
304
+ // disconnect. Read 300 raw lines (each trace ~15 lines, so this
305
+ // captures up to ~20 traces fully) then surface 20 post-filter
306
+ // so real errors aren't pushed out by noise.
307
+ webTail: (() => {
308
+ const raw = tailFile(path_1.default.join(chorusDir, 'logs', 'web.log'), 300);
309
+ const { kept, filteredCount } = filterBenignNoise(raw);
310
+ const trimmed = kept.split('\n').slice(-20).join('\n').trim();
311
+ return filteredCount > 0
312
+ ? `${trimmed}\n (${filteredCount} benign SSE-disconnect trace${filteredCount === 1 ? '' : 's'} filtered)`
313
+ : trimmed;
314
+ })(),
315
+ },
316
+ crashes: { count: crashCount, latest: latestCrash },
317
+ clis,
318
+ };
319
+ }
320
+ function formatReport(s) {
321
+ const lines = [];
322
+ lines.push('```');
323
+ lines.push('# Chorus diagnose');
324
+ lines.push('');
325
+ lines.push(`chorus CLI: ${s.chorus.cliVersion}`);
326
+ lines.push(`running daemon: ${s.chorus.runningDaemonVersion ?? '(not reachable)'}` +
327
+ (s.chorus.mismatch ? ' ⚠ VERSION MISMATCH — run `chorus stop && chorus start`' : ''));
328
+ lines.push(`node: ${s.runtime.node}`);
329
+ lines.push(`platform: ${s.runtime.platform} (${s.runtime.arch}, ${s.runtime.release})`);
330
+ lines.push(`install mode: ${s.install.mode}`);
331
+ lines.push(`bin path: ${s.install.binPath}`);
332
+ lines.push('');
333
+ lines.push('## Daemon state');
334
+ lines.push(`pid alive: ${s.daemon.daemonPidAlive ?? '(no daemon.json)'}`);
335
+ lines.push(`health probe: ${s.daemon.healthyOnPort !== null ? `OK on :${s.daemon.healthyOnPort}` : 'no response'}`);
336
+ lines.push('daemon.json:');
337
+ for (const ln of s.daemon.daemonJson.split('\n'))
338
+ lines.push(` ${ln}`);
339
+ lines.push('');
340
+ lines.push('## DB');
341
+ lines.push(`chats: ${s.db.chats}`);
342
+ lines.push(`voices: ${s.db.voices}`);
343
+ lines.push('');
344
+ lines.push('## CLI detection');
345
+ if (s.clis.length === 0) {
346
+ lines.push('(detection module failed to load)');
347
+ }
348
+ else {
349
+ for (const c of s.clis) {
350
+ lines.push(c.found
351
+ ? ` ✓ ${c.id.padEnd(14)} ${c.path ?? ''}`
352
+ : ` ✗ ${c.id.padEnd(14)} not found${c.reason ? ` — ${c.reason}` : ''}`);
353
+ }
354
+ }
355
+ lines.push('');
356
+ lines.push('## Crashes');
357
+ lines.push(`count: ${s.crashes.count}`);
358
+ if (s.crashes.latest) {
359
+ lines.push(`latest: ${s.crashes.latest.file}`);
360
+ lines.push('preview:');
361
+ for (const ln of s.crashes.latest.preview.split('\n'))
362
+ lines.push(` ${ln}`);
363
+ }
364
+ lines.push('');
365
+ lines.push('## Recent daemon.log (last 50 lines)');
366
+ for (const ln of s.logs.daemonTail.split('\n'))
367
+ lines.push(` ${ln}`);
368
+ lines.push('');
369
+ lines.push('## Recent web.log (last 20 lines)');
370
+ for (const ln of s.logs.webTail.split('\n'))
371
+ lines.push(` ${ln}`);
372
+ lines.push('```');
373
+ return lines.join('\n');
374
+ }
375
+ function registerDiagnoseCommand(program) {
376
+ program
377
+ .command('diagnose')
378
+ .description('Print a redacted diagnostic bundle to paste into a bug report')
379
+ .action(async () => {
380
+ try {
381
+ const snap = await gather();
382
+ const report = formatReport(snap);
383
+ console.log('');
384
+ console.log(report);
385
+ console.log('');
386
+ console.log(`Copy the block above into a new issue: ${ISSUE_URL}`);
387
+ console.log('');
388
+ }
389
+ catch (err) {
390
+ console.error('diagnose failed:', err instanceof Error ? err.message : err);
391
+ process.exit(1);
392
+ }
393
+ });
394
+ }
395
+ // Exported for tests — pure function over a snapshot is easy to assert.
396
+ exports._testing = {
397
+ gather,
398
+ formatReport,
399
+ detectInstallMode,
400
+ abbreviateHome,
401
+ resolveBinPath,
402
+ filterBenignNoise,
403
+ };
404
+ //# sourceMappingURL=diagnose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../../src/cli/commands/diagnose.ts"],"names":[],"mappings":"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"}