mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-17 07:10:12 +02:00
fix(global-discover): stop dropping sessions when header >8KB
extractCwdFromJsonl() reads the first 8KB of each JSONL session file and
runs JSON.parse on every newline-split line. When a session record
happens to straddle the 8KB cap, the last line ends in a truncated JSON
fragment, JSON.parse throws, the catch block 'continue's silently, and
if that was the only line carrying 'cwd' the whole project gets dropped
from the discovery output without a warning.
Two independent hardening steps:
1. Raise the read cap to 64KB. Session headers observed in Claude
Code / Codex / Gemini transcripts fit comfortably; this just moves
the cliff out of the normal range.
2. Drop the final segment after splitting on '\\n'. If the read hit
the cap mid-line, that segment is guaranteed incomplete; if the
file ended inside the buffer, the split produces an empty final
segment and dropping it is a no-op.
Together these make the parser robust regardless of how verbose the
leading records are.
This commit is contained in:
@@ -274,15 +274,22 @@ function resolveClaudeCodeCwd(
|
||||
}
|
||||
|
||||
function extractCwdFromJsonl(filePath: string): string | null {
|
||||
// Read a capped prefix so huge JSONL files don't blow up memory. 64KB
|
||||
// comfortably fits the largest observed session headers; the old 8KB cap
|
||||
// would sometimes fall inside a single long line and silently drop the
|
||||
// project (JSON.parse failure on the truncated tail).
|
||||
const MAX_BYTES = 64 * 1024;
|
||||
const MAX_LINES = 30;
|
||||
try {
|
||||
// Read only the first 8KB to avoid loading huge JSONL files into memory
|
||||
const fd = openSync(filePath, "r");
|
||||
const buf = Buffer.alloc(8192);
|
||||
const bytesRead = readSync(fd, buf, 0, 8192, 0);
|
||||
const buf = Buffer.alloc(MAX_BYTES);
|
||||
const bytesRead = readSync(fd, buf, 0, MAX_BYTES, 0);
|
||||
closeSync(fd);
|
||||
const text = buf.toString("utf-8", 0, bytesRead);
|
||||
const lines = text.split("\n").slice(0, 15);
|
||||
for (const line of lines) {
|
||||
// Drop the final segment — it may be an incomplete line at the cap boundary.
|
||||
const parts = text.split("\n");
|
||||
const completeLines = parts.length > 1 ? parts.slice(0, -1) : parts;
|
||||
for (const line of completeLines.slice(0, MAX_LINES)) {
|
||||
if (!line.trim()) continue;
|
||||
try {
|
||||
const obj = JSON.parse(line);
|
||||
|
||||
Reference in New Issue
Block a user