@@ -120,6 +120,7 @@ type RuntimeParityTranscriptRecord = {
|
120 | 120 | }; |
121 | 121 | |
122 | 122 | type RuntimeParityMockRequestSnapshot = { |
| 123 | +prompt?: string; |
123 | 124 | allInputText?: string; |
124 | 125 | plannedToolName?: string; |
125 | 126 | plannedToolArgs?: unknown; |
@@ -759,14 +760,22 @@ function resolveRuntimeParityToolCalls(params: {
|
759 | 760 | function filterMockRequestsForParentPrompt( |
760 | 761 | requests: RuntimeParityMockRequestSnapshot[], |
761 | 762 | parentPrompt: string, |
| 763 | +parentPrompts: readonly string[] = [parentPrompt], |
762 | 764 | ) { |
763 | | -const normalizedParentPrompt = normalizeTextForParity(parentPrompt); |
764 | | -if (!normalizedParentPrompt) { |
| 765 | +const normalizedParentPrompts = parentPrompts |
| 766 | +.map(normalizeTextForParity) |
| 767 | +.filter((prompt) => prompt.length > 0); |
| 768 | +if (normalizedParentPrompts.length === 0) { |
765 | 769 | return requests; |
766 | 770 | } |
767 | | -const matching = requests.filter((request) => |
768 | | -normalizeTextForParity(request.allInputText ?? "").includes(normalizedParentPrompt), |
769 | | -); |
| 771 | +const matching = requests.filter((request) => { |
| 772 | +const normalizedPrompt = normalizeTextForParity(request.prompt ?? ""); |
| 773 | +if (normalizedPrompt) { |
| 774 | +return normalizedParentPrompts.some((prompt) => normalizedPrompt.includes(prompt)); |
| 775 | +} |
| 776 | +const normalizedHistory = normalizeTextForParity(request.allInputText ?? ""); |
| 777 | +return normalizedParentPrompts.some((prompt) => normalizedHistory.includes(prompt)); |
| 778 | +}); |
770 | 779 | return matching.length > 0 ? matching : requests; |
771 | 780 | } |
772 | 781 | |
@@ -966,6 +975,7 @@ async function loadRuntimeParityTranscripts(params: {
|
966 | 975 | async function loadRuntimeParityMockToolCalls( |
967 | 976 | mockBaseUrl: string | undefined, |
968 | 977 | parentPrompt: string, |
| 978 | +parentPrompts: readonly string[] = [parentPrompt], |
969 | 979 | ): Promise<RuntimeParityToolCall[] | null> { |
970 | 980 | const normalizedBaseUrl = mockBaseUrl?.trim().replace(/\/+$/u, ""); |
971 | 981 | if (!normalizedBaseUrl) { |
@@ -991,14 +1001,15 @@ async function loadRuntimeParityMockToolCalls(
|
991 | 1001 | } |
992 | 1002 | const requests = payload.filter(isMessageRecord).map( |
993 | 1003 | (entry): RuntimeParityMockRequestSnapshot => ({ |
| 1004 | +prompt: readNonEmptyString(entry.prompt), |
994 | 1005 | allInputText: readNonEmptyString(entry.allInputText), |
995 | 1006 | plannedToolName: readNonEmptyString(entry.plannedToolName), |
996 | 1007 | plannedToolArgs: entry.plannedToolArgs ?? null, |
997 | 1008 | toolOutput: readNonEmptyString(entry.toolOutput) ?? "", |
998 | 1009 | }), |
999 | 1010 | ); |
1000 | 1011 | return resolveToolCallOrderFromMockRequests( |
1001 | | -filterMockRequestsForParentPrompt(requests, parentPrompt), |
| 1012 | +filterMockRequestsForParentPrompt(requests, parentPrompt, parentPrompts), |
1002 | 1013 | ); |
1003 | 1014 | } catch { |
1004 | 1015 | return null; |
@@ -1015,12 +1026,16 @@ export async function captureRuntimeParityCell(
|
1015 | 1026 | }); |
1016 | 1027 | const transcriptRecords = buildTranscriptRecords(transcriptBytes); |
1017 | 1028 | const transcriptToolCalls = resolveToolCallOrder(transcriptRecords); |
1018 | | -const parentPrompt = |
1019 | | -transcriptRecords |
1020 | | -.filter((record) => record.role === "user" && !isToolResultLikeMessage(record.message)) |
1021 | | -.map((record) => extractAssistantText(record.message)) |
1022 | | -.find(Boolean) ?? ""; |
1023 | | -const mockToolCalls = await loadRuntimeParityMockToolCalls(params.mockBaseUrl, parentPrompt); |
| 1029 | +const parentPrompts = transcriptRecords |
| 1030 | +.filter((record) => record.role === "user") |
| 1031 | +.map((record) => extractAssistantText(record.message)) |
| 1032 | +.filter((prompt) => prompt.length > 0); |
| 1033 | +const parentPrompt = parentPrompts[0] ?? ""; |
| 1034 | +const mockToolCalls = await loadRuntimeParityMockToolCalls( |
| 1035 | +params.mockBaseUrl, |
| 1036 | +parentPrompt, |
| 1037 | +parentPrompts, |
| 1038 | +); |
1024 | 1039 | const gatewayLogs = params.gateway.logs?.(); |
1025 | 1040 | const sentinelFindings = [ |
1026 | 1041 | ...scanGatewayLogSentinels(gatewayLogs), |
|