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.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error.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/page_client-reference-manifest.js +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/connect/page_client-reference-manifest.js +1 -1
- package/.next/server/app/demo/[scenario]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/new/page_client-reference-manifest.js +1 -1
- package/.next/server/app/new.html +1 -1
- package/.next/server/app/new.rsc +2 -2
- package/.next/server/app/new.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/.next/server/app/new.segments/new.segment.rsc +1 -1
- package/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
- package/.next/server/app/onboarding.html +1 -1
- package/.next/server/app/onboarding.rsc +2 -2
- package/.next/server/app/onboarding.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/personas/page_client-reference-manifest.js +1 -1
- package/.next/server/app/personas.html +1 -1
- package/.next/server/app/personas.rsc +2 -2
- package/.next/server/app/personas.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/.next/server/app/personas.segments/personas.segment.rsc +1 -1
- package/.next/server/app/runs/[runId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/runs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/permissions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings.html +1 -1
- package/.next/server/app/settings.rsc +2 -2
- package/.next/server/app/settings.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/templates/page_client-reference-manifest.js +1 -1
- package/.next/server/app/templates.html +1 -1
- package/.next/server/app/templates.rsc +2 -2
- package/.next/server/app/templates.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/.next/server/app/templates.segments/templates.segment.rsc +1 -1
- package/.next/server/chunks/189.js +1 -1
- package/.next/server/chunks/325.js +1 -1
- package/.next/server/chunks/681.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{245-e103518e1c6037c0.js → 245-203bd8285e6b0858.js} +1 -1
- package/.next/static/chunks/641-02dbc18bdc194ee1.js +1 -0
- package/.next/trace +20 -20
- package/.next/trace-build +1 -1
- package/README.md +22 -0
- package/bin/chorus.mjs +87 -5
- package/dist/cli/commands/diagnose.js +404 -0
- package/dist/cli/commands/diagnose.js.map +1 -0
- package/dist/cli/crash-hook.js +135 -0
- package/dist/cli/crash-hook.js.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/daemon/runner/fallback-registry.js +110 -0
- package/dist/daemon/runner/fallback-registry.js.map +1 -0
- package/dist/daemon/runner/reviewer-driver.js +68 -23
- package/dist/daemon/runner/reviewer-driver.js.map +1 -1
- package/dist/daemon/runner/template-fallback.js +22 -8
- package/dist/daemon/runner/template-fallback.js.map +1 -1
- package/package.json +1 -1
- package/.next/static/chunks/641-2908cb9553b8753a.js +0 -1
- /package/.next/static/{eOeXty5cBGWg7xnmtF6ST → NjUsrVtX8A7dE29z5nGfv}/_buildManifest.js +0 -0
- /package/.next/static/{eOeXty5cBGWg7xnmtF6ST → NjUsrVtX8A7dE29z5nGfv}/_ssgManifest.js +0 -0
package/.next/trace-build
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"name":"run-webpack","duration":
|
|
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 {
|
|
18
|
-
import {
|
|
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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"}
|