fix: fix bugs in core modules
- tty: fix isStdoutTTY to use fstat first, fall back to TERM heuristic - git: fix commit regex to handle root-commit output format - git: fix parseNameStatus to handle edge cases (empty lines, missing tabs) - ai: fix readStream to cancel reader instead of releaseLock - cli: remove dead code resolveFlagName function - clipboard: fix inconsistent indentation Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -123,7 +123,6 @@ async function readStream(body: ReadableStream<Uint8Array>, callbacks: StreamCal
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split("\n");
|
||||
// Keep the last potentially incomplete line
|
||||
buffer = lines.pop() ?? "";
|
||||
|
||||
for (const line of lines) {
|
||||
@@ -136,7 +135,12 @@ async function readStream(body: ReadableStream<Uint8Array>, callbacks: StreamCal
|
||||
try {
|
||||
const parsed = JSON.parse(data) as {
|
||||
choices?: Array<{ delta?: { content?: string }; finish_reason?: string }>;
|
||||
error?: { message?: string };
|
||||
};
|
||||
if (parsed.error) {
|
||||
callbacks.onError?.(new Error(`Stream error: ${parsed.error.message ?? "unknown"}`));
|
||||
continue;
|
||||
}
|
||||
const token = parsed.choices?.[0]?.delta?.content;
|
||||
if (token) {
|
||||
fullText += token;
|
||||
@@ -152,7 +156,8 @@ async function readStream(body: ReadableStream<Uint8Array>, callbacks: StreamCal
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
reader.releaseLock();
|
||||
try { await reader.cancel(); } catch {}
|
||||
// releaseLock is not needed after cancel
|
||||
}
|
||||
|
||||
callbacks.onDone?.(fullText);
|
||||
|
||||
+3
-1
@@ -19,7 +19,9 @@ export async function copyToClipboard(text: string): Promise<boolean> {
|
||||
proc.stdin.end();
|
||||
const exitCode = await proc.exited;
|
||||
if (exitCode === 0) return true;
|
||||
} catch {}
|
||||
} catch {
|
||||
// Try next command
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
+11
-6
@@ -37,12 +37,17 @@ function parseNameStatus(output: string): FileEntry[] {
|
||||
return output
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter(Boolean)
|
||||
.filter((line) => line.trim())
|
||||
.map((line) => {
|
||||
const [status, ...pathParts] = line.split("\t");
|
||||
const path = pathParts[pathParts.length - 1] ?? "";
|
||||
return { path, status: status!, label: statusToLabel(status!) };
|
||||
});
|
||||
const tabIdx = line.indexOf("\t");
|
||||
if (tabIdx === -1) return null;
|
||||
const status = line.slice(0, tabIdx);
|
||||
// Join path parts back (paths may contain escaped chars but not tabs)
|
||||
const path = line.slice(tabIdx + 1);
|
||||
if (!status || !path) return null;
|
||||
return { path, status, label: statusToLabel(status) };
|
||||
})
|
||||
.filter((entry): entry is FileEntry => entry !== null);
|
||||
}
|
||||
|
||||
export async function getStagedFiles(): Promise<FileEntry[]> {
|
||||
@@ -140,7 +145,7 @@ export async function commit(
|
||||
throw new Error(stderr.trim() || `git commit failed (exit code ${exitCode})`);
|
||||
}
|
||||
|
||||
const branchHashMatch = stdout.match(/\[(\S+)\s+([0-9a-f]{7,})/);
|
||||
const branchHashMatch = stdout.match(/\[(\S+)\s+(?:\(root-commit\)\s+)?([0-9a-f]{7,})/);
|
||||
const branch = branchHashMatch?.[1] ?? "";
|
||||
const hash = branchHashMatch?.[2] ?? "";
|
||||
|
||||
|
||||
+3
-4
@@ -23,14 +23,13 @@ export function isStdinTTY(): boolean {
|
||||
}
|
||||
|
||||
export function isStdoutTTY(): boolean {
|
||||
// Use a heuristic for stdout — check if we're in a terminal
|
||||
if (process.env.TERM || process.env.TERM_PROGRAM) return true;
|
||||
if (process.env.NO_COLOR) return false;
|
||||
// Try fstat on fd 1 (stdout)
|
||||
// Primary check: fstat on fd 1 (stdout) — most reliable
|
||||
try {
|
||||
const stat = fstatSync(1);
|
||||
return stat.isCharacterDevice();
|
||||
} catch {
|
||||
// Fall back to TERM heuristic only when fstat fails
|
||||
if (process.env.TERM || process.env.TERM_PROGRAM) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user