update
This commit is contained in:
1 parent
67c757f481
commit
b8dda3c8d0
77 files changed
+1577
-2808
No files matched your search
@@ -77,135 +77,6 @@ export function normalizeMessagesForPrompt(
|
||||
// Applied when session state is restored, not at every message send.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A transcript entry from adapter session state.
|
||||
* Adapters serialize their conversation as arrays of these blocks.
|
||||
*/
|
||||
export interface TranscriptBlock {
|
||||
role: "user" | "assistant" | "system";
|
||||
content: string | TranscriptContentBlock[];
|
||||
}
|
||||
|
||||
export interface TranscriptContentBlock {
|
||||
type: string;
|
||||
id?: string;
|
||||
tool_use_id?: string;
|
||||
name?: string;
|
||||
input?: unknown;
|
||||
content?: string;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Repair tool_use / tool_result pairing in a serialized transcript.
|
||||
* - Orphan tool_results (no matching tool_use) are removed.
|
||||
* - Unpaired tool_use blocks get a synthetic "[interrupted]" result appended.
|
||||
* - Duplicate tool_use IDs are deduplicated (keep first).
|
||||
*
|
||||
* Returns a repaired copy; does not mutate the input.
|
||||
*/
|
||||
export function repairToolPairing(transcript: TranscriptBlock[]): TranscriptBlock[] {
|
||||
const toolUseIds = new Set<string>();
|
||||
const toolResultIds = new Set<string>();
|
||||
|
||||
// Pass 1: collect all tool_use and tool_result IDs
|
||||
for (const block of transcript) {
|
||||
if (!Array.isArray(block.content)) continue;
|
||||
for (const part of block.content) {
|
||||
if (part.type === "tool_use" && part.id) {
|
||||
toolUseIds.add(part.id);
|
||||
}
|
||||
if (part.type === "tool_result" && part.tool_use_id) {
|
||||
toolResultIds.add(part.tool_use_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2: filter orphan tool_results and deduplicate tool_use IDs
|
||||
const seenToolUseIds = new Set<string>();
|
||||
const repaired: TranscriptBlock[] = [];
|
||||
|
||||
for (const block of transcript) {
|
||||
if (typeof block.content === "string") {
|
||||
repaired.push(block);
|
||||
continue;
|
||||
}
|
||||
|
||||
const filteredContent: TranscriptContentBlock[] = [];
|
||||
for (const part of block.content) {
|
||||
if (part.type === "tool_result" && part.tool_use_id && !toolUseIds.has(part.tool_use_id)) {
|
||||
continue; // orphan tool_result — remove
|
||||
}
|
||||
if (part.type === "tool_use" && part.id) {
|
||||
if (seenToolUseIds.has(part.id)) continue; // duplicate — remove
|
||||
seenToolUseIds.add(part.id);
|
||||
}
|
||||
filteredContent.push(part);
|
||||
}
|
||||
|
||||
if (filteredContent.length > 0) {
|
||||
repaired.push({ ...block, content: filteredContent });
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 3: add synthetic results for unpaired tool_use blocks
|
||||
const unpairedToolUseIds = [...toolUseIds].filter((id) => !toolResultIds.has(id));
|
||||
if (unpairedToolUseIds.length > 0) {
|
||||
const syntheticResults: TranscriptContentBlock[] = unpairedToolUseIds.map((id) => ({
|
||||
type: "tool_result",
|
||||
tool_use_id: id,
|
||||
content: "[interrupted — tool call did not complete before session ended]",
|
||||
}));
|
||||
repaired.push({
|
||||
role: "user",
|
||||
content: syntheticResults,
|
||||
});
|
||||
}
|
||||
|
||||
return repaired;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and return repair statistics for a transcript.
|
||||
* Use for logging/diagnostics without modifying the transcript.
|
||||
*/
|
||||
export function diagnoseTranscript(transcript: TranscriptBlock[]): {
|
||||
totalBlocks: number;
|
||||
toolUseCount: number;
|
||||
toolResultCount: number;
|
||||
orphanResultCount: number;
|
||||
unpairedUseCount: number;
|
||||
} {
|
||||
const toolUseIds = new Set<string>();
|
||||
const toolResultIds = new Set<string>();
|
||||
let toolUseCount = 0;
|
||||
let toolResultCount = 0;
|
||||
|
||||
for (const block of transcript) {
|
||||
if (!Array.isArray(block.content)) continue;
|
||||
for (const part of block.content) {
|
||||
if (part.type === "tool_use" && part.id) {
|
||||
toolUseIds.add(part.id);
|
||||
toolUseCount++;
|
||||
}
|
||||
if (part.type === "tool_result" && part.tool_use_id) {
|
||||
toolResultIds.add(part.tool_use_id);
|
||||
toolResultCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const orphanResultCount = [...toolResultIds].filter((id) => !toolUseIds.has(id)).length;
|
||||
const unpairedUseCount = [...toolUseIds].filter((id) => !toolResultIds.has(id)).length;
|
||||
|
||||
return {
|
||||
totalBlocks: transcript.length,
|
||||
toolUseCount,
|
||||
toolResultCount,
|
||||
orphanResultCount,
|
||||
unpairedUseCount,
|
||||
};
|
||||
}
|
||||
|
||||
export interface CommentRecord {
|
||||
taskId: string;
|
||||
|
||||
Reference in new issue
Block a user