Skip to content

Commit

Permalink
Handle component tree failure data
Browse files Browse the repository at this point in the history
  • Loading branch information
bhackett1024 committed Jan 22, 2025
1 parent 2cfbb63 commit 7ce6110
Showing 1 changed file with 48 additions and 20 deletions.
68 changes: 48 additions & 20 deletions app/lib/replay/SimulationPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,27 +78,37 @@ interface ExecutionDataPoint {

// Initial point for analysis that is an uncaught exception thrown
// from application code called by React, causing the app to unmount.
interface ExecutionDataInitialPointReactException {
interface RecordingFailureDataReactException {
kind: "ReactException";
errorText: string;
point: ProtocolExecutionPoint;

// Whether the exception was thrown by library code called at the point.
calleeFrame: boolean;
}

// Initial point for analysis that is an exception logged to the console.
interface ExecutionDataInitialPointConsoleError {
interface RecordingFailureDataConsoleError {
kind: "ConsoleError";
errorText: string;
point: ProtocolExecutionPoint;
}

type BaseExecutionDataInitialPoint =
| ExecutionDataInitialPointReactException
| ExecutionDataInitialPointConsoleError;
// Fallback failure data shows the React component tree at the end of the recording.
interface ReactComponentTree {
name: string;
children: ReactComponentTree[];
}

export type ExecutionDataInitialPoint = {
point: ProtocolExecutionPoint;
} & BaseExecutionDataInitialPoint;
interface RecordingFailureDataComponentTree {
kind: "ComponentTree";
componentTree: ReactComponentTree;
}

export type RecordingFailureData =
| RecordingFailureDataReactException
| RecordingFailureDataConsoleError
| RecordingFailureDataComponentTree;

export interface ExecutionDataAnalysisResult {
// Points which were described.
Expand All @@ -119,7 +129,7 @@ export interface ExecutionDataAnalysisResult {

// If no point or comment was available, describes the failure associated with the
// initial point of the analysis.
failureData?: ExecutionDataInitialPoint;
failureData?: RecordingFailureData;
}

function trimFileName(url: string): string {
Expand Down Expand Up @@ -164,13 +174,25 @@ async function annotateSource(repositoryContents: string, fileName: string, sour
return rv;
}

function describeComponentTree(componentTree: ReactComponentTree, indent: string): string {
let rv = "";
rv += `${indent}${componentTree.name}\n`;
for (const child of componentTree.children) {
rv += describeComponentTree(child, indent + " ");
}
return rv;
}

function codeBlock(text: string): string {
return "```\n" + text + (text.endsWith("\n") ? "" : "\n") + "```";
}

async function enhancePromptFromFailureData(
failurePoint: ExecutionDataPoint,
failureData: ExecutionDataInitialPoint,
points: ExecutionDataPoint[],
failureData: RecordingFailureData,
repositoryContents: string
): Promise<string> {
const pointText = failurePoint.location.source.trim();
const fileName = trimFileName(failurePoint.location.url);
const failurePoint = "point" in failureData ? points.find(p => p.point === failureData.point) : undefined;

let prompt = "";
let annotation;
Expand All @@ -188,14 +210,23 @@ async function enhancePromptFromFailureData(
prompt += "An exception was thrown and later logged to the console.\n";
annotation = `This line is throwing the exception "${failureData.errorText}"`;
break;
case "ComponentTree":
prompt += "The React component tree at the end of the recording:\n\n";
prompt += codeBlock(describeComponentTree(failureData.componentTree, ""));
break;
default:
throw new Error(`Unknown failure kind: ${(failureData as any).kind}`);
}

const annotatedSource = await annotateSource(repositoryContents, fileName, pointText, annotation);
if (failurePoint) {
assert(annotation);
const pointText = failurePoint.location.source.trim();
const fileName = trimFileName(failurePoint.location.url);
const annotatedSource = await annotateSource(repositoryContents, fileName, pointText, annotation);
prompt += `Here is the affected code, in ${fileName}:\n\n`;
prompt += codeBlock(annotatedSource);
}

prompt += `Here is the affected code, in ${fileName}:\n\n`;
prompt += "```\n" + annotatedSource + "```\n";
return prompt;
}

Expand All @@ -218,12 +249,9 @@ export async function getSimulationEnhancedPrompt(recordingId: string, repositor
const { points, failureData } = rval;
assert(failureData, "No failure data");

const failurePoint = points.find(p => p.point === failureData.point);
assert(failurePoint, "No failure point");

console.log("FailureData", JSON.stringify(failureData, null, 2));

const prompt = await enhancePromptFromFailureData(failurePoint, failureData, repositoryContents);
const prompt = await enhancePromptFromFailureData(points, failureData, repositoryContents);
console.log("Enhanced prompt", prompt);
return prompt;
} finally {
Expand Down

0 comments on commit 7ce6110

Please sign in to comment.