mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 18:30:39 +09:00
feat: polish issue thread markdown and references
This commit is contained in:
parent
548721248e
commit
958c11699e
16 changed files with 659 additions and 44 deletions
|
|
@ -3,6 +3,7 @@ import type { TranscriptEntry, StdoutLineParser, TranscriptParserSource } from "
|
|||
|
||||
export type RunLogChunk = { ts: string; stream: "stdout" | "stderr" | "system"; chunk: string };
|
||||
type TranscriptBuildOptions = { censorUsernameInLogs?: boolean };
|
||||
type RedactionOptions = { enabled: boolean };
|
||||
|
||||
function resolveStdoutParser(source: StdoutLineParser | TranscriptParserSource) {
|
||||
if (typeof source === "function") {
|
||||
|
|
@ -33,6 +34,66 @@ export function appendTranscriptEntries(entries: TranscriptEntry[], incoming: Tr
|
|||
}
|
||||
}
|
||||
|
||||
function truncateTranscriptLine(line: string, maxLength = 160) {
|
||||
if (line.length <= maxLength) return line;
|
||||
return `${line.slice(0, maxLength - 3)}...`;
|
||||
}
|
||||
|
||||
function formatTranscriptParserError(error: unknown) {
|
||||
if (error instanceof Error && error.message) return error.message;
|
||||
if (typeof error === "string" && error) return error;
|
||||
try {
|
||||
return JSON.stringify(error);
|
||||
} catch {
|
||||
return String(error);
|
||||
}
|
||||
}
|
||||
|
||||
function createTranscriptParseErrorEntry(
|
||||
line: string,
|
||||
ts: string,
|
||||
error: unknown,
|
||||
redactionOptions: RedactionOptions,
|
||||
): TranscriptEntry {
|
||||
const errorText = formatTranscriptParserError(error) || "unknown parser error";
|
||||
const preview = truncateTranscriptLine(line);
|
||||
return {
|
||||
kind: "result",
|
||||
ts,
|
||||
text: redactHomePathUserSegments(
|
||||
`Chat transcript error: ${errorText}. Falling back for line: ${preview}`,
|
||||
redactionOptions,
|
||||
),
|
||||
inputTokens: 0,
|
||||
outputTokens: 0,
|
||||
cachedTokens: 0,
|
||||
costUsd: 0,
|
||||
subtype: "transcript_parse_error",
|
||||
isError: true,
|
||||
errors: [],
|
||||
};
|
||||
}
|
||||
|
||||
function appendParsedTranscriptLine(args: {
|
||||
entries: TranscriptEntry[];
|
||||
line: string;
|
||||
ts: string;
|
||||
parseLine: (line: string, ts: string) => TranscriptEntry[];
|
||||
reset: (() => void) | null;
|
||||
redactionOptions: RedactionOptions;
|
||||
}) {
|
||||
const { entries, line, ts, parseLine, reset, redactionOptions } = args;
|
||||
try {
|
||||
appendTranscriptEntries(
|
||||
entries,
|
||||
parseLine(line, ts).map((entry) => redactTranscriptEntryPaths(entry, redactionOptions)),
|
||||
);
|
||||
} catch (error) {
|
||||
reset?.();
|
||||
appendTranscriptEntry(entries, createTranscriptParseErrorEntry(line, ts, error, redactionOptions));
|
||||
}
|
||||
}
|
||||
|
||||
export function buildTranscript(
|
||||
chunks: RunLogChunk[],
|
||||
parserSource: StdoutLineParser | TranscriptParserSource,
|
||||
|
|
@ -59,14 +120,28 @@ export function buildTranscript(
|
|||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed) continue;
|
||||
appendTranscriptEntries(entries, parseLine(trimmed, chunk.ts).map((entry) => redactTranscriptEntryPaths(entry, redactionOptions)));
|
||||
appendParsedTranscriptLine({
|
||||
entries,
|
||||
line: trimmed,
|
||||
ts: chunk.ts,
|
||||
parseLine,
|
||||
reset,
|
||||
redactionOptions,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const trailing = stdoutBuffer.trim();
|
||||
if (trailing) {
|
||||
const ts = chunks.length > 0 ? chunks[chunks.length - 1]!.ts : new Date().toISOString();
|
||||
appendTranscriptEntries(entries, parseLine(trailing, ts).map((entry) => redactTranscriptEntryPaths(entry, redactionOptions)));
|
||||
appendParsedTranscriptLine({
|
||||
entries,
|
||||
line: trailing,
|
||||
ts,
|
||||
parseLine,
|
||||
reset,
|
||||
redactionOptions,
|
||||
});
|
||||
}
|
||||
|
||||
reset?.();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue