fix(protocol): align Trace v2/v3 classification and hover steps

Require Trace v3 version const 3, reject mixed pages/states payloads, and
align TypeScript selection optionality with the generated schema. Trace v2
on main already records hover steps, so the frozen v2 schema must accept
them instead of dropping them during reduction.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
“haonan”
2026-08-23 21:26:39 +08:00
committed by GitHub
co-authored by Cursor
parent f98198949a
commit 524516cb56
9 changed files with 234 additions and 31 deletions
@@ -151,7 +151,7 @@ describe("reduceTraceSteps", () => {
});
});
it("drops hover steps unsupported by historical v2 clients", () => {
it("keeps hover steps before menu clicks", () => {
const { steps } = reduceTraceSteps(
[
{
@@ -167,11 +167,11 @@ describe("reduceTraceSteps", () => {
],
"https://example.com/app",
);
expect(steps.map((s) => s.op)).toEqual(["click"]);
expect(steps.map((s) => s.op)).toEqual(["hover", "click"]);
expect(steps[0]).toMatchObject({
op: "click",
op: "hover",
page: "p1",
target: { name: "Profile" },
target: { name: "Account" },
});
});
+6 -2
View File
@@ -18,7 +18,6 @@ export function shouldRecordPress(
}
function shouldIncludeDraft(step: DraftTraceStep): boolean {
if (step.op === "hover") return false;
if (step.op === "press" && !shouldRecordPress(step.key, step.modifiers)) return false;
return true;
}
@@ -140,7 +139,12 @@ function toV2Step(
effectForNavigation(step.navigated_to, urlToId),
);
case "hover":
return null;
return {
op: "hover",
id,
page,
target: step.target,
};
case "fill":
return {
op: "fill",
+3 -2
View File
@@ -793,6 +793,7 @@ export type DraftTraceStep =
export type Step =
| ({ op: "navigate" } & StepCommon & { to: string })
| ({ op: "click" } & StepCommon & { target: TargetDescriptor })
| ({ op: "hover" } & StepCommon & { target: TargetDescriptor })
| ({ op: "fill" } & StepCommon & {
target: TargetDescriptor;
value: string;
@@ -834,7 +835,7 @@ export type StepV3 =
})
| ({ op: "select" } & StepCommonV3 & {
target: TargetDescriptorV3;
selection: SelectedOption[];
selection?: SelectedOption[];
})
| ({ op: "press" } & StepCommonV3 & {
key: string;
@@ -844,7 +845,7 @@ export type StepV3 =
| ({ op: "scroll" } & StepCommonV3);
export interface TraceV3 {
version: number;
version: 3;
recorded_at: string;
started_at?: string;
purpose?: string;