@browserbasehq/orca 3.5.0-preview.0 → 3.5.0-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/cjs/lib/v3/agent/utils/captureAriaTreeProbe.d.ts +35 -0
  2. package/dist/cjs/lib/v3/agent/utils/captureAriaTreeProbe.js +38 -0
  3. package/dist/cjs/lib/v3/agent/utils/captureAriaTreeProbe.js.map +1 -0
  4. package/dist/cjs/lib/v3/agent/utils/postStepProbeEvidence.d.ts +19 -0
  5. package/dist/cjs/lib/v3/agent/utils/postStepProbeEvidence.js +54 -0
  6. package/dist/cjs/lib/v3/agent/utils/postStepProbeEvidence.js.map +1 -0
  7. package/dist/cjs/lib/v3/agent/utils/toolOutputEvidence.d.ts +2 -0
  8. package/dist/cjs/lib/v3/agent/utils/toolOutputEvidence.js +62 -0
  9. package/dist/cjs/lib/v3/agent/utils/toolOutputEvidence.js.map +1 -0
  10. package/dist/cjs/lib/v3/agent/utils/wrapEvidenceCallback.d.ts +3 -0
  11. package/dist/cjs/lib/v3/agent/utils/wrapEvidenceCallback.js +25 -0
  12. package/dist/cjs/lib/v3/agent/utils/wrapEvidenceCallback.js.map +1 -0
  13. package/dist/cjs/lib/v3/api.d.ts +7 -1
  14. package/dist/cjs/lib/v3/api.js +100 -29
  15. package/dist/cjs/lib/v3/api.js.map +1 -1
  16. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.d.ts +24 -0
  17. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js +31 -0
  18. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
  19. package/dist/cjs/lib/v3/handlers/v3AgentHandler.d.ts +1 -0
  20. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +83 -7
  21. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  22. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.d.ts +11 -0
  23. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +119 -5
  24. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  25. package/dist/cjs/lib/v3/index.d.ts +11 -0
  26. package/dist/cjs/lib/v3/index.js +19 -1
  27. package/dist/cjs/lib/v3/index.js.map +1 -1
  28. package/dist/cjs/lib/v3/llm/LLMProvider.d.ts +3 -0
  29. package/dist/cjs/lib/v3/llm/LLMProvider.js +28 -8
  30. package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
  31. package/dist/cjs/lib/v3/types/public/agent.d.ts +6 -0
  32. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  33. package/dist/cjs/lib/v3/types/public/agentEvidenceEvents.d.ts +85 -0
  34. package/dist/cjs/lib/v3/types/public/agentEvidenceEvents.js +15 -0
  35. package/dist/cjs/lib/v3/types/public/agentEvidenceEvents.js.map +1 -0
  36. package/dist/cjs/lib/v3/types/public/api.d.ts +414 -182
  37. package/dist/cjs/lib/v3/types/public/api.js +62 -20
  38. package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
  39. package/dist/cjs/lib/v3/types/public/index.d.ts +1 -0
  40. package/dist/cjs/lib/v3/types/public/index.js +1 -0
  41. package/dist/cjs/lib/v3/types/public/index.js.map +1 -1
  42. package/dist/cjs/lib/v3/types/public/model.d.ts +16 -7
  43. package/dist/cjs/lib/v3/types/public/model.js.map +1 -1
  44. package/dist/cjs/lib/v3/v3.d.ts +1 -0
  45. package/dist/cjs/lib/v3/v3.js +14 -0
  46. package/dist/cjs/lib/v3/v3.js.map +1 -1
  47. package/dist/cjs/lib/v3/verifier/evidenceNormalization.d.ts +7 -0
  48. package/dist/cjs/lib/v3/verifier/evidenceNormalization.js +100 -0
  49. package/dist/cjs/lib/v3/verifier/evidenceNormalization.js.map +1 -0
  50. package/dist/cjs/lib/v3/verifier/index.d.ts +6 -0
  51. package/dist/cjs/lib/v3/verifier/index.js +16 -0
  52. package/dist/cjs/lib/v3/verifier/index.js.map +1 -0
  53. package/dist/cjs/lib/v3/verifier/trajectory.d.ts +50 -0
  54. package/dist/cjs/lib/v3/verifier/trajectory.js +316 -0
  55. package/dist/cjs/lib/v3/verifier/trajectory.js.map +1 -0
  56. package/dist/cjs/lib/v3/verifier/types.d.ts +281 -0
  57. package/dist/cjs/lib/v3/verifier/types.js +10 -0
  58. package/dist/cjs/lib/v3/verifier/types.js.map +1 -0
  59. package/dist/cjs/lib/v3Evaluator.d.ts +9 -4
  60. package/dist/cjs/lib/v3Evaluator.js +148 -0
  61. package/dist/cjs/lib/v3Evaluator.js.map +1 -1
  62. package/dist/cjs/lib/v3LegacyEvaluator.js +5 -1
  63. package/dist/cjs/lib/v3LegacyEvaluator.js.map +1 -1
  64. package/dist/esm/lib/v3/agent/utils/captureAriaTreeProbe.d.ts +35 -0
  65. package/dist/esm/lib/v3/agent/utils/captureAriaTreeProbe.js +35 -0
  66. package/dist/esm/lib/v3/agent/utils/captureAriaTreeProbe.js.map +1 -0
  67. package/dist/esm/lib/v3/agent/utils/postStepProbeEvidence.d.ts +19 -0
  68. package/dist/esm/lib/v3/agent/utils/postStepProbeEvidence.js +50 -0
  69. package/dist/esm/lib/v3/agent/utils/postStepProbeEvidence.js.map +1 -0
  70. package/dist/esm/lib/v3/agent/utils/toolOutputEvidence.d.ts +2 -0
  71. package/dist/esm/lib/v3/agent/utils/toolOutputEvidence.js +59 -0
  72. package/dist/esm/lib/v3/agent/utils/toolOutputEvidence.js.map +1 -0
  73. package/dist/esm/lib/v3/agent/utils/wrapEvidenceCallback.d.ts +3 -0
  74. package/dist/esm/lib/v3/agent/utils/wrapEvidenceCallback.js +22 -0
  75. package/dist/esm/lib/v3/agent/utils/wrapEvidenceCallback.js.map +1 -0
  76. package/dist/esm/lib/v3/api.d.ts +7 -1
  77. package/dist/esm/lib/v3/api.js +100 -29
  78. package/dist/esm/lib/v3/api.js.map +1 -1
  79. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.d.ts +24 -0
  80. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js +28 -0
  81. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
  82. package/dist/esm/lib/v3/handlers/v3AgentHandler.d.ts +1 -0
  83. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +83 -7
  84. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  85. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.d.ts +11 -0
  86. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +119 -5
  87. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  88. package/dist/esm/lib/v3/index.d.ts +11 -0
  89. package/dist/esm/lib/v3/index.js +10 -0
  90. package/dist/esm/lib/v3/index.js.map +1 -1
  91. package/dist/esm/lib/v3/llm/LLMProvider.d.ts +3 -0
  92. package/dist/esm/lib/v3/llm/LLMProvider.js +28 -9
  93. package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
  94. package/dist/esm/lib/v3/types/public/agent.d.ts +6 -0
  95. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  96. package/dist/esm/lib/v3/types/public/agentEvidenceEvents.d.ts +85 -0
  97. package/dist/esm/lib/v3/types/public/agentEvidenceEvents.js +14 -0
  98. package/dist/esm/lib/v3/types/public/agentEvidenceEvents.js.map +1 -0
  99. package/dist/esm/lib/v3/types/public/api.d.ts +414 -182
  100. package/dist/esm/lib/v3/types/public/api.js +60 -18
  101. package/dist/esm/lib/v3/types/public/api.js.map +1 -1
  102. package/dist/esm/lib/v3/types/public/index.d.ts +1 -0
  103. package/dist/esm/lib/v3/types/public/index.js +1 -0
  104. package/dist/esm/lib/v3/types/public/index.js.map +1 -1
  105. package/dist/esm/lib/v3/types/public/model.d.ts +16 -7
  106. package/dist/esm/lib/v3/types/public/model.js.map +1 -1
  107. package/dist/esm/lib/v3/v3.d.ts +1 -0
  108. package/dist/esm/lib/v3/v3.js +14 -0
  109. package/dist/esm/lib/v3/v3.js.map +1 -1
  110. package/dist/esm/lib/v3/verifier/evidenceNormalization.d.ts +7 -0
  111. package/dist/esm/lib/v3/verifier/evidenceNormalization.js +93 -0
  112. package/dist/esm/lib/v3/verifier/evidenceNormalization.js.map +1 -0
  113. package/dist/esm/lib/v3/verifier/index.d.ts +6 -0
  114. package/dist/esm/lib/v3/verifier/index.js +3 -0
  115. package/dist/esm/lib/v3/verifier/index.js.map +1 -0
  116. package/dist/esm/lib/v3/verifier/trajectory.d.ts +50 -0
  117. package/dist/esm/lib/v3/verifier/trajectory.js +273 -0
  118. package/dist/esm/lib/v3/verifier/trajectory.js.map +1 -0
  119. package/dist/esm/lib/v3/verifier/types.d.ts +281 -0
  120. package/dist/esm/lib/v3/verifier/types.js +9 -0
  121. package/dist/esm/lib/v3/verifier/types.js.map +1 -0
  122. package/dist/esm/lib/v3Evaluator.d.ts +9 -4
  123. package/dist/esm/lib/v3Evaluator.js +148 -0
  124. package/dist/esm/lib/v3Evaluator.js.map +1 -1
  125. package/dist/esm/lib/v3LegacyEvaluator.js +5 -1
  126. package/dist/esm/lib/v3LegacyEvaluator.js.map +1 -1
  127. package/package.json +4 -4
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Shared verifier types for trajectories, rubrics, evidence, and results.
3
+ *
4
+ * The verifier consumes saved trajectories instead of a live browser. DOM and
5
+ * Hybrid runs preserve tool-return text/JSON evidence, while CUA runs preserve
6
+ * screenshots sent to the provider plus independent harness probes.
7
+ */
8
+ /** Token usage for one or more LLM calls. Matches AgentResult.usage shape. */
9
+ export interface TrajectoryUsage {
10
+ input_tokens: number;
11
+ output_tokens: number;
12
+ reasoning_tokens?: number;
13
+ cached_input_tokens?: number;
14
+ inference_time_ms?: number;
15
+ }
16
+ /** A single criterion in a Stagehand rubric. */
17
+ export interface RubricCriterion {
18
+ /** Short name of the criterion (e.g., "Add ground beef to cart"). */
19
+ criterion: string;
20
+ /** What to evaluate and how to award partial credit. */
21
+ description: string;
22
+ /** Maximum points for this criterion. */
23
+ maxPoints: number;
24
+ /**
25
+ * Applicability rule for situational criteria. When this condition is not
26
+ * met, the criterion is excluded from scoring rather than counted as failed.
27
+ */
28
+ condition?: string;
29
+ }
30
+ /** A rubric — list of criteria for a task. */
31
+ export interface Rubric {
32
+ items: RubricCriterion[];
33
+ }
34
+ /**
35
+ * Spec for a single task being verified. Carried both at runtime and into the
36
+ * verifier alongside the trajectory.
37
+ */
38
+ export interface TaskSpec {
39
+ /** Stable identifier (e.g., "united_13" for WebTailBench, task_id for Mind2Web). */
40
+ id: string;
41
+ /** Task instruction shown to the agent. */
42
+ instruction: string;
43
+ /** Starting URL, if any. */
44
+ initUrl?: string;
45
+ /** Rubric carried by the dataset or generated by a verifier backend. */
46
+ precomputedRubric?: Rubric;
47
+ /** Optional reference answer (set when dataset ships one). */
48
+ expectedAnswer?: string;
49
+ }
50
+ /**
51
+ * A single modality unit in tier-1 agent evidence. Mirrors the shape of
52
+ * ModelMessage content parts so we can reproduce what the LLM ingested.
53
+ */
54
+ export type AgentEvidenceModality = {
55
+ type: "text";
56
+ content: string;
57
+ } | {
58
+ type: "image";
59
+ bytes: Buffer;
60
+ mediaType: string;
61
+ } | {
62
+ type: "json";
63
+ content: unknown;
64
+ };
65
+ /**
66
+ * Tier 1 — exactly the bytes/strings/objects the agent's LLM ingested as the
67
+ * tool result for this step.
68
+ *
69
+ * Modes:
70
+ * - CUA: usually a single image modality (the screenshot sent to the provider).
71
+ * - Hybrid: tool result with optional screenshotBase64 → one image + one text.
72
+ * - DOM: tool returns (extract JSON, ariaTree text, etc.) → text/json modalities.
73
+ */
74
+ export interface AgentEvidence {
75
+ modalities: AgentEvidenceModality[];
76
+ }
77
+ /**
78
+ * Tier 2 — independent harness probes around this step.
79
+ *
80
+ * If a probe wasn't captured, the field is absent (not null).
81
+ */
82
+ export interface ProbeEvidence {
83
+ /** URL after the step's tool execution. */
84
+ url?: string;
85
+ /**
86
+ * Bus screenshot captured after the step. Path on disk is preferred once
87
+ * persisted; in-memory Buffer is used during a live run.
88
+ */
89
+ screenshot?: Buffer;
90
+ /** Reference to the persisted screenshot file under the trajectory dir. */
91
+ screenshotPath?: string;
92
+ /** Accessibility tree snapshot. */
93
+ ariaTree?: string;
94
+ /** Verifier-requested probes, keyed by criterion id. */
95
+ onDemand?: Record<string, unknown>;
96
+ }
97
+ /** Outcome of a single tool execution as seen by the harness. */
98
+ export interface ToolOutput {
99
+ ok: boolean;
100
+ /**
101
+ * The tool's return value. Same payload that flowed into agentEvidence
102
+ * modalities, but in its native shape (e.g., the extract result, the act
103
+ * describe-string) rather than serialized for the LLM.
104
+ */
105
+ result: unknown;
106
+ error?: string;
107
+ }
108
+ /** One step in a trajectory: action + reasoning + evidence + outcome. */
109
+ export interface TrajectoryStep {
110
+ actionName: string;
111
+ actionArgs: Record<string, unknown>;
112
+ /** From AgentAction.reasoning. May be empty for tools that don't surface reasoning. */
113
+ reasoning: string;
114
+ agentEvidence: AgentEvidence;
115
+ probeEvidence: ProbeEvidence;
116
+ toolOutput: ToolOutput;
117
+ }
118
+ /** Terminal status of the agent run. */
119
+ export type TrajectoryStatus = "complete" | "aborted" | "stalled" | "error";
120
+ /**
121
+ * Full trajectory for one task run.
122
+ *
123
+ * The on-disk layout is one directory per task:
124
+ *
125
+ * .trajectories/<run-id>/<task-id>/
126
+ * ├── task_data.json — TaskSpec + result metadata
127
+ * ├── trajectory.json — this object, with screenshotPath instead of bytes
128
+ * ├── screenshots/ — step probe/agent images plus final observation
129
+ * ├── scores/
130
+ * │ └── result.json — Result from V3Evaluator.verify()
131
+ * └── core.log — captured action log
132
+ */
133
+ export interface Trajectory {
134
+ task: TaskSpec;
135
+ steps: TrajectoryStep[];
136
+ finalAnswer?: string;
137
+ /** Terminal page observation captured after the agent finishes. */
138
+ finalObservation?: ProbeEvidence;
139
+ status: TrajectoryStatus;
140
+ usage: TrajectoryUsage;
141
+ }
142
+ /** Score for a single rubric criterion after evidence analysis + rescoring. */
143
+ export interface CriterionScore {
144
+ /** Matches RubricCriterion.criterion (the criterion's short name). */
145
+ criterion: string;
146
+ /** Maximum possible points for this criterion. */
147
+ maxPoints: number;
148
+ /**
149
+ * Points earned post-evidence-analysis (paper's post_image_earned_points).
150
+ * Null if the criterion was conditional and its condition wasn't met (excluded
151
+ * from both numerator and denominator in the process score).
152
+ */
153
+ earnedPoints: number | null;
154
+ /** Verifier's explanation for the score. */
155
+ explanation: string;
156
+ /**
157
+ * True if the criterion is conditional and its condition was determined to
158
+ * be met. Absent for non-conditional criteria.
159
+ */
160
+ conditionMet?: boolean;
161
+ /**
162
+ * Set when the verifier had no evidence to ground this criterion in either
163
+ * tier. Per paper §2, treated as uncontrollable failure → full credit, but
164
+ * surfaced here so dashboards can flag low-confidence results.
165
+ */
166
+ evidenceInsufficient?: boolean;
167
+ }
168
+ /**
169
+ * First-point-of-failure analysis (paper Step 9a). Identifies the earliest
170
+ * step where the agent's trajectory went off-track, using a structured error
171
+ * taxonomy (7 top-level categories, 1.1–7.4 sub-codes).
172
+ */
173
+ export interface FirstPointOfFailure {
174
+ stepIndex: number;
175
+ /** Sub-code from the error taxonomy (e.g., "2.3" for a specific hallucination type). */
176
+ errorCode: string;
177
+ /** Top-level category name (Selection, Hallucination, etc.). */
178
+ category: string;
179
+ /** Verifier's reasoning for selecting this point. */
180
+ description?: string;
181
+ }
182
+ /**
183
+ * Structured observation surfaced by the verifier that another agent or
184
+ * tooling could act on. Findings are emitted opportunistically by Step 8
185
+ * (outcome verification) when the verifier notices actionable patterns —
186
+ * repeated tool-call failures, ambiguous task specs, evidence gaps, etc.
187
+ *
188
+ * Not produced for every task: when nothing actionable surfaces, the
189
+ * `findings` array on the EvaluationResult is empty. Consumers should treat the
190
+ * field as advisory, not as part of the formal score.
191
+ */
192
+ export interface VerifierFinding {
193
+ /**
194
+ * Category of the observation. Open-ended enum — additional categories may
195
+ * be added as verifier backends surface new failure modes.
196
+ */
197
+ category: "agent_tool_usage" | "agent_strategy" | "rubric_quality" | "trajectory_capture" | "task_specification" | "verifier_uncertainty" | "other";
198
+ /** Impact: info (FYI), warning (worth investigating), blocking (broke the task). */
199
+ severity: "info" | "warning" | "blocking";
200
+ /** What the verifier noticed. Plain prose, grounded in evidence from the trajectory. */
201
+ description: string;
202
+ /**
203
+ * Optional concrete next action another agent could take. Should be
204
+ * specific enough that it can be acted on without further reasoning —
205
+ * e.g., "Try double_click instead of triple_click to clear placeholder
206
+ * text on this form field."
207
+ */
208
+ suggestedAction?: string;
209
+ /** Step indices in the trajectory where this pattern showed up. */
210
+ relatedSteps?: number[];
211
+ }
212
+ /** Stable debugging summary emitted by verifier backends. */
213
+ export interface VerifierRawSteps {
214
+ backend?: "legacy" | "verifier";
215
+ primaryIntent?: string;
216
+ reasoning?: string;
217
+ rubricSource?: "precomputed" | "generated" | "none";
218
+ approach?: "a" | "b";
219
+ optionalsMode?: "folded" | "separate" | "skip";
220
+ totalEarned?: number;
221
+ totalMax?: number;
222
+ evidenceImages?: number;
223
+ evidenceTexts?: number;
224
+ evidenceOriginalScreenshots?: number;
225
+ legacyEvaluation?: string;
226
+ screenshotCount?: number;
227
+ }
228
+ /** Task-validity classification (paper Step 10). */
229
+ export interface TaskValidity {
230
+ /** True if the task is underspecified / has multiple valid interpretations. */
231
+ isAmbiguous: boolean;
232
+ /** True if the task is impossible / illegal / NSFW / otherwise infeasible. */
233
+ isInvalid: boolean;
234
+ /** Optional sub-codes from the task-classification taxonomy. */
235
+ ambiguityCodes?: string[];
236
+ invalidTaskCodes?: string[];
237
+ }
238
+ /**
239
+ * Evaluator output. Legacy evaluation may only populate outcome fields; richer
240
+ * verifier backends can also populate process scoring and diagnostics.
241
+ *
242
+ * Process and outcome are deliberately independent when both are present:
243
+ * an agent can follow the right steps but get blocked (high process, low
244
+ * outcome), or succeed through an unexpected path (variable process, high
245
+ * outcome).
246
+ */
247
+ export interface EvaluationResult {
248
+ /** Did the agent accomplish the task from the user's perspective? */
249
+ outcomeSuccess: boolean;
250
+ /** Human-readable explanation for the outcome. */
251
+ explanation?: string;
252
+ /** Aggregated earned/max across applicable criteria, in [0, 1]. */
253
+ processScore?: number;
254
+ /** Per-criterion breakdown after rescoring. */
255
+ perCriterion?: CriterionScore[];
256
+ /** Step 9a — first step where the trajectory went off-track, if any. */
257
+ firstPointOfFailure?: FirstPointOfFailure;
258
+ /** Step 10 — task-itself ambiguity / validity. */
259
+ taskValidity?: TaskValidity;
260
+ /**
261
+ * Ids (RubricCriterion.criterion strings) of criteria where neither tier of
262
+ * evidence resolved the question. Treated as uncontrollable → full credit,
263
+ * but flagged here so consumers can decide whether to discount the score.
264
+ */
265
+ evidenceInsufficient?: string[];
266
+ /**
267
+ * Structured observations from the verifier that a downstream tool or
268
+ * follow-up agent could act on. Opportunistic — empty when the verifier
269
+ * doesn't notice anything actionable. Not part of the score; advisory.
270
+ */
271
+ findings?: VerifierFinding[];
272
+ /** Debugging summary from the active evaluator backend. */
273
+ rawSteps?: VerifierRawSteps;
274
+ }
275
+ /**
276
+ * Verifier interface. Implementations consume a Trajectory and return an
277
+ * EvaluationResult — they MUST NOT touch a live browser.
278
+ */
279
+ export interface Verifier {
280
+ verify(trajectory: Trajectory): Promise<EvaluationResult>;
281
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * Shared verifier types for trajectories, rubrics, evidence, and results.
4
+ *
5
+ * The verifier consumes saved trajectories instead of a live browser. DOM and
6
+ * Hybrid runs preserve tool-return text/JSON evidence, while CUA runs preserve
7
+ * screenshots sent to the provider plus independent harness probes.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../lib/v3/verifier/types.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG","sourcesContent":["/**\n * Shared verifier types for trajectories, rubrics, evidence, and results.\n *\n * The verifier consumes saved trajectories instead of a live browser. DOM and\n * Hybrid runs preserve tool-return text/JSON evidence, while CUA runs preserve\n * screenshots sent to the provider plus independent harness probes.\n */\n\n/** Token usage for one or more LLM calls. Matches AgentResult.usage shape. */\nexport interface TrajectoryUsage {\n input_tokens: number;\n output_tokens: number;\n reasoning_tokens?: number;\n cached_input_tokens?: number;\n inference_time_ms?: number;\n}\n\n/** A single criterion in a Stagehand rubric. */\nexport interface RubricCriterion {\n /** Short name of the criterion (e.g., \"Add ground beef to cart\"). */\n criterion: string;\n /** What to evaluate and how to award partial credit. */\n description: string;\n /** Maximum points for this criterion. */\n maxPoints: number;\n /**\n * Applicability rule for situational criteria. When this condition is not\n * met, the criterion is excluded from scoring rather than counted as failed.\n */\n condition?: string;\n}\n\n/** A rubric — list of criteria for a task. */\nexport interface Rubric {\n items: RubricCriterion[];\n}\n\n/**\n * Spec for a single task being verified. Carried both at runtime and into the\n * verifier alongside the trajectory.\n */\nexport interface TaskSpec {\n /** Stable identifier (e.g., \"united_13\" for WebTailBench, task_id for Mind2Web). */\n id: string;\n /** Task instruction shown to the agent. */\n instruction: string;\n /** Starting URL, if any. */\n initUrl?: string;\n /** Rubric carried by the dataset or generated by a verifier backend. */\n precomputedRubric?: Rubric;\n /** Optional reference answer (set when dataset ships one). */\n expectedAnswer?: string;\n}\n\n/**\n * A single modality unit in tier-1 agent evidence. Mirrors the shape of\n * ModelMessage content parts so we can reproduce what the LLM ingested.\n */\nexport type AgentEvidenceModality =\n | { type: \"text\"; content: string }\n | { type: \"image\"; bytes: Buffer; mediaType: string }\n | { type: \"json\"; content: unknown };\n\n/**\n * Tier 1 — exactly the bytes/strings/objects the agent's LLM ingested as the\n * tool result for this step.\n *\n * Modes:\n * - CUA: usually a single image modality (the screenshot sent to the provider).\n * - Hybrid: tool result with optional screenshotBase64 → one image + one text.\n * - DOM: tool returns (extract JSON, ariaTree text, etc.) → text/json modalities.\n */\nexport interface AgentEvidence {\n modalities: AgentEvidenceModality[];\n}\n\n/**\n * Tier 2 — independent harness probes around this step.\n *\n * If a probe wasn't captured, the field is absent (not null).\n */\nexport interface ProbeEvidence {\n /** URL after the step's tool execution. */\n url?: string;\n /**\n * Bus screenshot captured after the step. Path on disk is preferred once\n * persisted; in-memory Buffer is used during a live run.\n */\n screenshot?: Buffer;\n /** Reference to the persisted screenshot file under the trajectory dir. */\n screenshotPath?: string;\n /** Accessibility tree snapshot. */\n ariaTree?: string;\n /** Verifier-requested probes, keyed by criterion id. */\n onDemand?: Record<string, unknown>;\n}\n\n/** Outcome of a single tool execution as seen by the harness. */\nexport interface ToolOutput {\n ok: boolean;\n /**\n * The tool's return value. Same payload that flowed into agentEvidence\n * modalities, but in its native shape (e.g., the extract result, the act\n * describe-string) rather than serialized for the LLM.\n */\n result: unknown;\n error?: string;\n}\n\n/** One step in a trajectory: action + reasoning + evidence + outcome. */\nexport interface TrajectoryStep {\n actionName: string;\n actionArgs: Record<string, unknown>;\n /** From AgentAction.reasoning. May be empty for tools that don't surface reasoning. */\n reasoning: string;\n agentEvidence: AgentEvidence;\n probeEvidence: ProbeEvidence;\n toolOutput: ToolOutput;\n}\n\n/** Terminal status of the agent run. */\nexport type TrajectoryStatus = \"complete\" | \"aborted\" | \"stalled\" | \"error\";\n\n/**\n * Full trajectory for one task run.\n *\n * The on-disk layout is one directory per task:\n *\n * .trajectories/<run-id>/<task-id>/\n * ├── task_data.json — TaskSpec + result metadata\n * ├── trajectory.json — this object, with screenshotPath instead of bytes\n * ├── screenshots/ — step probe/agent images plus final observation\n * ├── scores/\n * │ └── result.json — Result from V3Evaluator.verify()\n * └── core.log — captured action log\n */\nexport interface Trajectory {\n task: TaskSpec;\n steps: TrajectoryStep[];\n finalAnswer?: string;\n /** Terminal page observation captured after the agent finishes. */\n finalObservation?: ProbeEvidence;\n status: TrajectoryStatus;\n usage: TrajectoryUsage;\n}\n\n/** Score for a single rubric criterion after evidence analysis + rescoring. */\nexport interface CriterionScore {\n /** Matches RubricCriterion.criterion (the criterion's short name). */\n criterion: string;\n /** Maximum possible points for this criterion. */\n maxPoints: number;\n /**\n * Points earned post-evidence-analysis (paper's post_image_earned_points).\n * Null if the criterion was conditional and its condition wasn't met (excluded\n * from both numerator and denominator in the process score).\n */\n earnedPoints: number | null;\n /** Verifier's explanation for the score. */\n explanation: string;\n /**\n * True if the criterion is conditional and its condition was determined to\n * be met. Absent for non-conditional criteria.\n */\n conditionMet?: boolean;\n /**\n * Set when the verifier had no evidence to ground this criterion in either\n * tier. Per paper §2, treated as uncontrollable failure → full credit, but\n * surfaced here so dashboards can flag low-confidence results.\n */\n evidenceInsufficient?: boolean;\n}\n\n/**\n * First-point-of-failure analysis (paper Step 9a). Identifies the earliest\n * step where the agent's trajectory went off-track, using a structured error\n * taxonomy (7 top-level categories, 1.1–7.4 sub-codes).\n */\nexport interface FirstPointOfFailure {\n stepIndex: number;\n /** Sub-code from the error taxonomy (e.g., \"2.3\" for a specific hallucination type). */\n errorCode: string;\n /** Top-level category name (Selection, Hallucination, etc.). */\n category: string;\n /** Verifier's reasoning for selecting this point. */\n description?: string;\n}\n\n/**\n * Structured observation surfaced by the verifier that another agent or\n * tooling could act on. Findings are emitted opportunistically by Step 8\n * (outcome verification) when the verifier notices actionable patterns —\n * repeated tool-call failures, ambiguous task specs, evidence gaps, etc.\n *\n * Not produced for every task: when nothing actionable surfaces, the\n * `findings` array on the EvaluationResult is empty. Consumers should treat the\n * field as advisory, not as part of the formal score.\n */\nexport interface VerifierFinding {\n /**\n * Category of the observation. Open-ended enum — additional categories may\n * be added as verifier backends surface new failure modes.\n */\n category:\n | \"agent_tool_usage\" // agent's tool calls had repeated issues (misclicks, wrong args, retries)\n | \"agent_strategy\" // higher-level planning / decision-making problems\n | \"rubric_quality\" // criteria were overly strict, ambiguous, or contradictory\n | \"trajectory_capture\" // gaps in evidence (missing screenshots, empty steps)\n | \"task_specification\" // task instruction was ambiguous / under- or over-specified\n | \"verifier_uncertainty\" // verifier itself couldn't confidently decide\n | \"other\";\n /** Impact: info (FYI), warning (worth investigating), blocking (broke the task). */\n severity: \"info\" | \"warning\" | \"blocking\";\n /** What the verifier noticed. Plain prose, grounded in evidence from the trajectory. */\n description: string;\n /**\n * Optional concrete next action another agent could take. Should be\n * specific enough that it can be acted on without further reasoning —\n * e.g., \"Try double_click instead of triple_click to clear placeholder\n * text on this form field.\"\n */\n suggestedAction?: string;\n /** Step indices in the trajectory where this pattern showed up. */\n relatedSteps?: number[];\n}\n\n/** Stable debugging summary emitted by verifier backends. */\nexport interface VerifierRawSteps {\n backend?: \"legacy\" | \"verifier\";\n primaryIntent?: string;\n reasoning?: string;\n rubricSource?: \"precomputed\" | \"generated\" | \"none\";\n approach?: \"a\" | \"b\";\n optionalsMode?: \"folded\" | \"separate\" | \"skip\";\n totalEarned?: number;\n totalMax?: number;\n evidenceImages?: number;\n evidenceTexts?: number;\n evidenceOriginalScreenshots?: number;\n legacyEvaluation?: string;\n screenshotCount?: number;\n}\n\n/** Task-validity classification (paper Step 10). */\nexport interface TaskValidity {\n /** True if the task is underspecified / has multiple valid interpretations. */\n isAmbiguous: boolean;\n /** True if the task is impossible / illegal / NSFW / otherwise infeasible. */\n isInvalid: boolean;\n /** Optional sub-codes from the task-classification taxonomy. */\n ambiguityCodes?: string[];\n invalidTaskCodes?: string[];\n}\n\n/**\n * Evaluator output. Legacy evaluation may only populate outcome fields; richer\n * verifier backends can also populate process scoring and diagnostics.\n *\n * Process and outcome are deliberately independent when both are present:\n * an agent can follow the right steps but get blocked (high process, low\n * outcome), or succeed through an unexpected path (variable process, high\n * outcome).\n */\nexport interface EvaluationResult {\n /** Did the agent accomplish the task from the user's perspective? */\n outcomeSuccess: boolean;\n /** Human-readable explanation for the outcome. */\n explanation?: string;\n /** Aggregated earned/max across applicable criteria, in [0, 1]. */\n processScore?: number;\n /** Per-criterion breakdown after rescoring. */\n perCriterion?: CriterionScore[];\n /** Step 9a — first step where the trajectory went off-track, if any. */\n firstPointOfFailure?: FirstPointOfFailure;\n /** Step 10 — task-itself ambiguity / validity. */\n taskValidity?: TaskValidity;\n /**\n * Ids (RubricCriterion.criterion strings) of criteria where neither tier of\n * evidence resolved the question. Treated as uncontrollable → full credit,\n * but flagged here so consumers can decide whether to discount the score.\n */\n evidenceInsufficient?: string[];\n /**\n * Structured observations from the verifier that a downstream tool or\n * follow-up agent could act on. Opportunistic — empty when the verifier\n * doesn't notice anything actionable. Not part of the score; advisory.\n */\n findings?: VerifierFinding[];\n /** Debugging summary from the active evaluator backend. */\n rawSteps?: VerifierRawSteps;\n}\n\n/**\n * Verifier interface. Implementations consume a Trajectory and return an\n * EvaluationResult — they MUST NOT touch a live browser.\n */\nexport interface Verifier {\n verify(trajectory: Trajectory): Promise<EvaluationResult>;\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import type { AvailableModel, ClientOptions } from "./v3/types/public/model.js";
2
- import type { EvaluateOptions, BatchAskOptions, EvaluationResult } from "./v3/types/private/evaluator.js";
2
+ import type { EvaluateOptions, BatchAskOptions, EvaluationResult as LegacyEvaluationResult } from "./v3/types/private/evaluator.js";
3
3
  import { V3 } from "./v3/v3.js";
4
+ import type { Trajectory, TaskSpec, EvaluationResult, Rubric, Verifier } from "./v3/verifier/index.js";
4
5
  export type V3EvaluatorBackend = "legacy" | "verifier";
5
6
  export type V3EvaluatorOptions = {
6
7
  /**
@@ -17,11 +18,15 @@ export type V3EvaluatorConstructorOptions = V3EvaluatorOptions & {
17
18
  modelName?: AvailableModel;
18
19
  modelClientOptions?: ClientOptions;
19
20
  };
20
- export declare class V3Evaluator {
21
+ export declare class V3Evaluator implements Verifier {
21
22
  private readonly backend;
22
23
  private readonly legacyEvaluator;
23
24
  constructor(v3: V3, modelNameOrOptions?: AvailableModel | V3EvaluatorConstructorOptions, modelClientOptions?: ClientOptions, options?: V3EvaluatorOptions);
24
- ask(options: EvaluateOptions): Promise<EvaluationResult>;
25
- batchAsk(options: BatchAskOptions): Promise<EvaluationResult[]>;
25
+ ask(options: EvaluateOptions): Promise<LegacyEvaluationResult>;
26
+ batchAsk(options: BatchAskOptions): Promise<LegacyEvaluationResult[]>;
27
+ verify(trajectory: Trajectory): Promise<EvaluationResult>;
28
+ generateRubric(taskSpec: TaskSpec): Promise<Rubric>;
26
29
  private getLegacyBackend;
30
+ private unavailableVerifierBackend;
31
+ private verifyTrajectoryWithLegacyEvaluator;
27
32
  }
@@ -19,12 +19,48 @@ class V3Evaluator {
19
19
  async batchAsk(options) {
20
20
  return this.getLegacyBackend("batchAsk").batchAsk(options);
21
21
  }
22
+ async verify(trajectory) {
23
+ const taskSpec = assertVerifierInput(trajectory);
24
+ if (this.backend === "legacy") {
25
+ return this.verifyTrajectoryWithLegacyEvaluator(trajectory, taskSpec);
26
+ }
27
+ return this.unavailableVerifierBackend("verify");
28
+ }
29
+ async generateRubric(taskSpec) {
30
+ if (!taskSpec?.id) {
31
+ throw new sdkErrors_js_1.StagehandInvalidArgumentError("TaskSpec.id is required for rubric generation");
32
+ }
33
+ if (this.backend === "verifier") {
34
+ return this.unavailableVerifierBackend("generateRubric");
35
+ }
36
+ return {
37
+ items: [legacyTaskCompletionCriterion(taskSpec)],
38
+ };
39
+ }
22
40
  getLegacyBackend(methodName) {
23
41
  if (this.backend === "legacy") {
24
42
  return this.legacyEvaluator;
25
43
  }
44
+ return this.unavailableVerifierBackend(methodName);
45
+ }
46
+ unavailableVerifierBackend(methodName) {
26
47
  throw new sdkErrors_js_1.StagehandInvalidArgumentError(`V3Evaluator.${methodName}() was configured with ${EVALUATOR_BACKEND_ENV}=verifier, but the verifier backend is not available in this build. Use "legacy" or install the verifier backend PR.`);
27
48
  }
49
+ async verifyTrajectoryWithLegacyEvaluator(trajectory, taskSpec) {
50
+ const screenshots = collectLegacyScreenshots(trajectory);
51
+ const agentReasoning = renderLegacyAgentReasoning(trajectory);
52
+ const answer = trajectory.finalAnswer;
53
+ if (!screenshots.length && !answer) {
54
+ return legacyInsufficientEvidenceResult("Legacy evaluator compatibility mode had no screenshots or final answer to evaluate.");
55
+ }
56
+ const result = await this.legacyEvaluator.ask({
57
+ question: taskSpec.instruction,
58
+ screenshot: screenshots.length ? screenshots : false,
59
+ answer,
60
+ agentReasoning,
61
+ });
62
+ return legacyEvaluationToResult(result, screenshots.length);
63
+ }
28
64
  }
29
65
  exports.V3Evaluator = V3Evaluator;
30
66
  function normalizeConstructorOptions(modelNameOrOptions, modelClientOptions, options) {
@@ -53,4 +89,116 @@ function resolveEvaluatorBackend(explicitBackend) {
53
89
  }
54
90
  throw new sdkErrors_js_1.StagehandInvalidArgumentError(`Invalid ${EVALUATOR_BACKEND_ENV}="${configuredBackend}". Expected "legacy" or "verifier".`);
55
91
  }
92
+ function assertVerifierInput(trajectory) {
93
+ if (!trajectory) {
94
+ throw new sdkErrors_js_1.StagehandInvalidArgumentError("Trajectory is required for verification");
95
+ }
96
+ if (!trajectory.task?.id) {
97
+ throw new sdkErrors_js_1.StagehandInvalidArgumentError("Trajectory.task.id is required for verification");
98
+ }
99
+ return trajectory.task;
100
+ }
101
+ function legacyTaskCompletionCriterion(taskSpec) {
102
+ return {
103
+ criterion: "legacy-task-completion",
104
+ description: `Evaluate whether the task was completed successfully: ${taskSpec.instruction}`,
105
+ maxPoints: 1,
106
+ };
107
+ }
108
+ function collectLegacyScreenshots(trajectory) {
109
+ const screenshots = [];
110
+ for (const step of trajectory.steps ?? []) {
111
+ if (Buffer.isBuffer(step.probeEvidence?.screenshot)) {
112
+ screenshots.push(step.probeEvidence.screenshot);
113
+ continue;
114
+ }
115
+ const agentImage = step.agentEvidence?.modalities?.find((modality) => modality.type === "image" && Buffer.isBuffer(modality.bytes));
116
+ if (agentImage) {
117
+ screenshots.push(agentImage.bytes);
118
+ }
119
+ }
120
+ if (Buffer.isBuffer(trajectory.finalObservation?.screenshot)) {
121
+ screenshots.push(trajectory.finalObservation.screenshot);
122
+ }
123
+ return screenshots;
124
+ }
125
+ function renderLegacyAgentReasoning(trajectory) {
126
+ const stepLines = (trajectory.steps ?? []).map((step, i) => {
127
+ const status = step.toolOutput?.ok === false ? "Tool status: failed" : "";
128
+ const output = step.toolOutput?.error
129
+ ? `Tool error: ${step.toolOutput.error}`
130
+ : `Tool output: ${stringifyForPrompt(step.toolOutput?.result)}`;
131
+ return [
132
+ `Step ${i}: ${step.actionName}`,
133
+ step.reasoning ? `Reasoning: ${step.reasoning}` : undefined,
134
+ status || undefined,
135
+ output,
136
+ ]
137
+ .filter(Boolean)
138
+ .join("\n");
139
+ });
140
+ if (!stepLines.length) {
141
+ return undefined;
142
+ }
143
+ return truncateForPrompt(`Agent trajectory:\n${stepLines.join("\n\n")}`, 16000);
144
+ }
145
+ function stringifyForPrompt(value) {
146
+ if (typeof value === "string") {
147
+ return value;
148
+ }
149
+ try {
150
+ const serialized = JSON.stringify(value);
151
+ return serialized ?? String(value);
152
+ }
153
+ catch {
154
+ return String(value);
155
+ }
156
+ }
157
+ function truncateForPrompt(value, maxLength) {
158
+ if (value.length <= maxLength) {
159
+ return value;
160
+ }
161
+ return `${value.slice(0, maxLength)}... [truncated]`;
162
+ }
163
+ function legacyEvaluationToResult(result, screenshotCount) {
164
+ const outcomeSuccess = result.evaluation === "YES";
165
+ const invalid = result.evaluation === "INVALID";
166
+ const findings = invalid
167
+ ? [
168
+ {
169
+ category: "verifier_uncertainty",
170
+ severity: "warning",
171
+ description: result.reasoning,
172
+ },
173
+ ]
174
+ : [];
175
+ return {
176
+ outcomeSuccess,
177
+ explanation: result.reasoning,
178
+ ...(findings.length ? { findings } : {}),
179
+ rawSteps: {
180
+ backend: "legacy",
181
+ legacyEvaluation: result.evaluation,
182
+ screenshotCount,
183
+ },
184
+ };
185
+ }
186
+ function legacyInsufficientEvidenceResult(reason) {
187
+ return {
188
+ outcomeSuccess: false,
189
+ explanation: reason,
190
+ findings: [
191
+ {
192
+ category: "trajectory_capture",
193
+ severity: "blocking",
194
+ description: reason,
195
+ },
196
+ ],
197
+ rawSteps: {
198
+ backend: "legacy",
199
+ legacyEvaluation: "INVALID",
200
+ screenshotCount: 0,
201
+ },
202
+ };
203
+ }
56
204
  //# sourceMappingURL=v3Evaluator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"v3Evaluator.js","sourceRoot":"","sources":["../../../lib/v3Evaluator.ts"],"names":[],"mappings":";;;AAOA,iEAA+E;AAC/E,iEAA2D;AAE3D,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AAC5D,MAAM,yBAAyB,GAAuB,QAAQ,CAAC;AA2B/D,MAAa,WAAW;IACL,OAAO,CAAqB;IAC5B,eAAe,CAAoB;IAEpD,YACE,EAAM,EACN,kBAAmE,EACnE,kBAAkC,EAClC,OAA4B;QAE5B,MAAM,iBAAiB,GAAG,2BAA2B,CACnD,kBAAkB,EAClB,kBAAkB,EAClB,OAAO,CACR,CAAC;QAEF,IAAI,CAAC,OAAO,GAAG,uBAAuB,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAClE,IAAI,CAAC,eAAe,GAAG,IAAI,wCAAiB,CAC1C,EAAE,EACF,iBAAiB,CAAC,SAAS,EAC3B,iBAAiB,CAAC,kBAAkB,CACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAwB;QAChC,OAAO,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAwB;QACrC,OAAO,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7D,CAAC;IAEO,gBAAgB,CAAC,UAAkB;QACzC,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,eAAe,CAAC;QAC9B,CAAC;QAED,MAAM,IAAI,4CAA6B,CACrC,eAAe,UAAU,0BAA0B,qBAAqB,sHAAsH,CAC/L,CAAC;IACJ,CAAC;CACF;AAzCD,kCAyCC;AAED,SAAS,2BAA2B,CAClC,kBAAmE,EACnE,kBAAkC,EAClC,OAA4B;IAE5B,IACE,kBAAkB;QAClB,OAAO,kBAAkB,KAAK,QAAQ;QACtC,CAAC,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAClC,CAAC;QACD,OAAO;YACL,SAAS,EAAE,kBAAkB,CAAC,SAAS;YACvC,kBAAkB,EAAE,kBAAkB,CAAC,kBAAkB;YACzD,OAAO,EAAE,kBAAkB,CAAC,OAAO,IAAI,OAAO,EAAE,OAAO;SACxD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,kBAAgD;QAC3D,kBAAkB;QAClB,OAAO,EAAE,OAAO,EAAE,OAAO;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,eAAoC;IAEpC,MAAM,iBAAiB,GACrB,eAAe;QACf,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QAClC,yBAAyB,CAAC;IAC5B,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEjE,IAAI,iBAAiB,KAAK,QAAQ,IAAI,iBAAiB,KAAK,UAAU,EAAE,CAAC;QACvE,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,MAAM,IAAI,4CAA6B,CACrC,WAAW,qBAAqB,KAAK,iBAAiB,qCAAqC,CAC5F,CAAC;AACJ,CAAC","sourcesContent":["import type { AvailableModel, ClientOptions } from \"./v3/types/public/model.js\";\nimport type {\n EvaluateOptions,\n BatchAskOptions,\n EvaluationResult,\n} from \"./v3/types/private/evaluator.js\";\nimport { V3 } from \"./v3/v3.js\";\nimport { StagehandInvalidArgumentError } from \"./v3/types/public/sdkErrors.js\";\nimport { LegacyV3Evaluator } from \"./v3LegacyEvaluator.js\";\n\nconst EVALUATOR_BACKEND_ENV = \"STAGEHAND_EVALUATOR_BACKEND\";\nconst DEFAULT_EVALUATOR_BACKEND: V3EvaluatorBackend = \"legacy\";\n\nexport type V3EvaluatorBackend = \"legacy\" | \"verifier\";\n\nexport type V3EvaluatorOptions = {\n /**\n * Selects the evaluator implementation.\n *\n * \"legacy\" preserves the existing screenshot/text YES/NO evaluator.\n * \"verifier\" is reserved for the rubric verifier backend.\n *\n * @default process.env.STAGEHAND_EVALUATOR_BACKEND || \"legacy\"\n */\n backend?: V3EvaluatorBackend;\n};\n\nexport type V3EvaluatorConstructorOptions = V3EvaluatorOptions & {\n modelName?: AvailableModel;\n modelClientOptions?: ClientOptions;\n};\n\ntype NormalizedConstructorOptions = {\n modelName?: AvailableModel;\n modelClientOptions?: ClientOptions;\n backend?: V3EvaluatorBackend;\n};\n\nexport class V3Evaluator {\n private readonly backend: V3EvaluatorBackend;\n private readonly legacyEvaluator: LegacyV3Evaluator;\n\n constructor(\n v3: V3,\n modelNameOrOptions?: AvailableModel | V3EvaluatorConstructorOptions,\n modelClientOptions?: ClientOptions,\n options?: V3EvaluatorOptions,\n ) {\n const normalizedOptions = normalizeConstructorOptions(\n modelNameOrOptions,\n modelClientOptions,\n options,\n );\n\n this.backend = resolveEvaluatorBackend(normalizedOptions.backend);\n this.legacyEvaluator = new LegacyV3Evaluator(\n v3,\n normalizedOptions.modelName,\n normalizedOptions.modelClientOptions,\n );\n }\n\n async ask(options: EvaluateOptions): Promise<EvaluationResult> {\n return this.getLegacyBackend(\"ask\").ask(options);\n }\n\n async batchAsk(options: BatchAskOptions): Promise<EvaluationResult[]> {\n return this.getLegacyBackend(\"batchAsk\").batchAsk(options);\n }\n\n private getLegacyBackend(methodName: string): LegacyV3Evaluator {\n if (this.backend === \"legacy\") {\n return this.legacyEvaluator;\n }\n\n throw new StagehandInvalidArgumentError(\n `V3Evaluator.${methodName}() was configured with ${EVALUATOR_BACKEND_ENV}=verifier, but the verifier backend is not available in this build. Use \"legacy\" or install the verifier backend PR.`,\n );\n }\n}\n\nfunction normalizeConstructorOptions(\n modelNameOrOptions?: AvailableModel | V3EvaluatorConstructorOptions,\n modelClientOptions?: ClientOptions,\n options?: V3EvaluatorOptions,\n): NormalizedConstructorOptions {\n if (\n modelNameOrOptions &&\n typeof modelNameOrOptions === \"object\" &&\n !Array.isArray(modelNameOrOptions)\n ) {\n return {\n modelName: modelNameOrOptions.modelName,\n modelClientOptions: modelNameOrOptions.modelClientOptions,\n backend: modelNameOrOptions.backend ?? options?.backend,\n };\n }\n\n return {\n modelName: modelNameOrOptions as AvailableModel | undefined,\n modelClientOptions,\n backend: options?.backend,\n };\n}\n\nfunction resolveEvaluatorBackend(\n explicitBackend?: V3EvaluatorBackend,\n): V3EvaluatorBackend {\n const configuredBackend =\n explicitBackend ??\n process.env[EVALUATOR_BACKEND_ENV] ??\n DEFAULT_EVALUATOR_BACKEND;\n const normalizedBackend = configuredBackend.trim().toLowerCase();\n\n if (normalizedBackend === \"legacy\" || normalizedBackend === \"verifier\") {\n return normalizedBackend;\n }\n\n throw new StagehandInvalidArgumentError(\n `Invalid ${EVALUATOR_BACKEND_ENV}=\"${configuredBackend}\". Expected \"legacy\" or \"verifier\".`,\n );\n}\n"]}
1
+ {"version":3,"file":"v3Evaluator.js","sourceRoot":"","sources":["../../../lib/v3Evaluator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AvailableModel, ClientOptions } from \"./v3/types/public/model.js\";\nimport type {\n EvaluateOptions,\n BatchAskOptions,\n EvaluationResult as LegacyEvaluationResult,\n} from \"./v3/types/private/evaluator.js\";\nimport { V3 } from \"./v3/v3.js\";\nimport { StagehandInvalidArgumentError } from \"./v3/types/public/sdkErrors.js\";\nimport { LegacyV3Evaluator } from \"./v3LegacyEvaluator.js\";\nimport type {\n Trajectory,\n TaskSpec,\n EvaluationResult,\n Rubric,\n Verifier,\n AgentEvidenceModality,\n VerifierFinding,\n} from \"./v3/verifier/index.js\";\n\nconst EVALUATOR_BACKEND_ENV = \"STAGEHAND_EVALUATOR_BACKEND\";\nconst DEFAULT_EVALUATOR_BACKEND: V3EvaluatorBackend = \"legacy\";\n\nexport type V3EvaluatorBackend = \"legacy\" | \"verifier\";\n\nexport type V3EvaluatorOptions = {\n /**\n * Selects the evaluator implementation.\n *\n * \"legacy\" preserves the existing screenshot/text YES/NO evaluator.\n * \"verifier\" is reserved for the rubric verifier backend.\n *\n * @default process.env.STAGEHAND_EVALUATOR_BACKEND || \"legacy\"\n */\n backend?: V3EvaluatorBackend;\n};\n\nexport type V3EvaluatorConstructorOptions = V3EvaluatorOptions & {\n modelName?: AvailableModel;\n modelClientOptions?: ClientOptions;\n};\n\ntype NormalizedConstructorOptions = {\n modelName?: AvailableModel;\n modelClientOptions?: ClientOptions;\n backend?: V3EvaluatorBackend;\n};\n\nexport class V3Evaluator implements Verifier {\n private readonly backend: V3EvaluatorBackend;\n private readonly legacyEvaluator: LegacyV3Evaluator;\n\n constructor(\n v3: V3,\n modelNameOrOptions?: AvailableModel | V3EvaluatorConstructorOptions,\n modelClientOptions?: ClientOptions,\n options?: V3EvaluatorOptions,\n ) {\n const normalizedOptions = normalizeConstructorOptions(\n modelNameOrOptions,\n modelClientOptions,\n options,\n );\n\n this.backend = resolveEvaluatorBackend(normalizedOptions.backend);\n this.legacyEvaluator = new LegacyV3Evaluator(\n v3,\n normalizedOptions.modelName,\n normalizedOptions.modelClientOptions,\n );\n }\n\n async ask(options: EvaluateOptions): Promise<LegacyEvaluationResult> {\n return this.getLegacyBackend(\"ask\").ask(options);\n }\n\n async batchAsk(options: BatchAskOptions): Promise<LegacyEvaluationResult[]> {\n return this.getLegacyBackend(\"batchAsk\").batchAsk(options);\n }\n\n async verify(trajectory: Trajectory): Promise<EvaluationResult> {\n const taskSpec = assertVerifierInput(trajectory);\n\n if (this.backend === \"legacy\") {\n return this.verifyTrajectoryWithLegacyEvaluator(trajectory, taskSpec);\n }\n\n return this.unavailableVerifierBackend(\"verify\");\n }\n\n async generateRubric(taskSpec: TaskSpec): Promise<Rubric> {\n if (!taskSpec?.id) {\n throw new StagehandInvalidArgumentError(\n \"TaskSpec.id is required for rubric generation\",\n );\n }\n\n if (this.backend === \"verifier\") {\n return this.unavailableVerifierBackend(\"generateRubric\");\n }\n\n return {\n items: [legacyTaskCompletionCriterion(taskSpec)],\n };\n }\n\n private getLegacyBackend(methodName: string): LegacyV3Evaluator {\n if (this.backend === \"legacy\") {\n return this.legacyEvaluator;\n }\n\n return this.unavailableVerifierBackend(methodName);\n }\n\n private unavailableVerifierBackend(methodName: string): never {\n throw new StagehandInvalidArgumentError(\n `V3Evaluator.${methodName}() was configured with ${EVALUATOR_BACKEND_ENV}=verifier, but the verifier backend is not available in this build. Use \"legacy\" or install the verifier backend PR.`,\n );\n }\n\n private async verifyTrajectoryWithLegacyEvaluator(\n trajectory: Trajectory,\n taskSpec: TaskSpec,\n ): Promise<EvaluationResult> {\n const screenshots = collectLegacyScreenshots(trajectory);\n const agentReasoning = renderLegacyAgentReasoning(trajectory);\n const answer = trajectory.finalAnswer;\n\n if (!screenshots.length && !answer) {\n return legacyInsufficientEvidenceResult(\n \"Legacy evaluator compatibility mode had no screenshots or final answer to evaluate.\",\n );\n }\n\n const result = await this.legacyEvaluator.ask({\n question: taskSpec.instruction,\n screenshot: screenshots.length ? screenshots : false,\n answer,\n agentReasoning,\n });\n\n return legacyEvaluationToResult(result, screenshots.length);\n }\n}\n\nfunction normalizeConstructorOptions(\n modelNameOrOptions?: AvailableModel | V3EvaluatorConstructorOptions,\n modelClientOptions?: ClientOptions,\n options?: V3EvaluatorOptions,\n): NormalizedConstructorOptions {\n if (\n modelNameOrOptions &&\n typeof modelNameOrOptions === \"object\" &&\n !Array.isArray(modelNameOrOptions)\n ) {\n return {\n modelName: modelNameOrOptions.modelName,\n modelClientOptions: modelNameOrOptions.modelClientOptions,\n backend: modelNameOrOptions.backend ?? options?.backend,\n };\n }\n\n return {\n modelName: modelNameOrOptions as AvailableModel | undefined,\n modelClientOptions,\n backend: options?.backend,\n };\n}\n\nfunction resolveEvaluatorBackend(\n explicitBackend?: V3EvaluatorBackend,\n): V3EvaluatorBackend {\n const configuredBackend =\n explicitBackend ??\n process.env[EVALUATOR_BACKEND_ENV] ??\n DEFAULT_EVALUATOR_BACKEND;\n const normalizedBackend = configuredBackend.trim().toLowerCase();\n\n if (normalizedBackend === \"legacy\" || normalizedBackend === \"verifier\") {\n return normalizedBackend;\n }\n\n throw new StagehandInvalidArgumentError(\n `Invalid ${EVALUATOR_BACKEND_ENV}=\"${configuredBackend}\". Expected \"legacy\" or \"verifier\".`,\n );\n}\n\nfunction assertVerifierInput(trajectory: Trajectory): TaskSpec {\n if (!trajectory) {\n throw new StagehandInvalidArgumentError(\n \"Trajectory is required for verification\",\n );\n }\n if (!trajectory.task?.id) {\n throw new StagehandInvalidArgumentError(\n \"Trajectory.task.id is required for verification\",\n );\n }\n return trajectory.task;\n}\n\nfunction legacyTaskCompletionCriterion(taskSpec: TaskSpec) {\n return {\n criterion: \"legacy-task-completion\",\n description: `Evaluate whether the task was completed successfully: ${taskSpec.instruction}`,\n maxPoints: 1,\n };\n}\n\nfunction collectLegacyScreenshots(trajectory: Trajectory): Buffer[] {\n const screenshots: Buffer[] = [];\n\n for (const step of trajectory.steps ?? []) {\n if (Buffer.isBuffer(step.probeEvidence?.screenshot)) {\n screenshots.push(step.probeEvidence.screenshot);\n continue;\n }\n\n const agentImage = step.agentEvidence?.modalities?.find(\n (\n modality,\n ): modality is Extract<AgentEvidenceModality, { type: \"image\" }> =>\n modality.type === \"image\" && Buffer.isBuffer(modality.bytes),\n );\n\n if (agentImage) {\n screenshots.push(agentImage.bytes);\n }\n }\n\n if (Buffer.isBuffer(trajectory.finalObservation?.screenshot)) {\n screenshots.push(trajectory.finalObservation.screenshot);\n }\n\n return screenshots;\n}\n\nfunction renderLegacyAgentReasoning(\n trajectory: Trajectory,\n): string | undefined {\n const stepLines = (trajectory.steps ?? []).map((step, i) => {\n const status = step.toolOutput?.ok === false ? \"Tool status: failed\" : \"\";\n const output = step.toolOutput?.error\n ? `Tool error: ${step.toolOutput.error}`\n : `Tool output: ${stringifyForPrompt(step.toolOutput?.result)}`;\n return [\n `Step ${i}: ${step.actionName}`,\n step.reasoning ? `Reasoning: ${step.reasoning}` : undefined,\n status || undefined,\n output,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n });\n\n if (!stepLines.length) {\n return undefined;\n }\n\n return truncateForPrompt(\n `Agent trajectory:\\n${stepLines.join(\"\\n\\n\")}`,\n 16000,\n );\n}\n\nfunction stringifyForPrompt(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n try {\n const serialized = JSON.stringify(value);\n return serialized ?? String(value);\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForPrompt(value: string, maxLength: number): string {\n if (value.length <= maxLength) {\n return value;\n }\n\n return `${value.slice(0, maxLength)}... [truncated]`;\n}\n\nfunction legacyEvaluationToResult(\n result: LegacyEvaluationResult,\n screenshotCount: number,\n): EvaluationResult {\n const outcomeSuccess = result.evaluation === \"YES\";\n const invalid = result.evaluation === \"INVALID\";\n const findings: VerifierFinding[] = invalid\n ? [\n {\n category: \"verifier_uncertainty\",\n severity: \"warning\",\n description: result.reasoning,\n },\n ]\n : [];\n\n return {\n outcomeSuccess,\n explanation: result.reasoning,\n ...(findings.length ? { findings } : {}),\n rawSteps: {\n backend: \"legacy\",\n legacyEvaluation: result.evaluation,\n screenshotCount,\n },\n };\n}\n\nfunction legacyInsufficientEvidenceResult(reason: string): EvaluationResult {\n return {\n outcomeSuccess: false,\n explanation: reason,\n findings: [\n {\n category: \"trajectory_capture\",\n severity: \"blocking\",\n description: reason,\n },\n ],\n rawSteps: {\n backend: \"legacy\",\n legacyEvaluation: \"INVALID\",\n screenshotCount: 0,\n },\n };\n}\n"]}
@@ -43,6 +43,7 @@ class LegacyV3Evaluator {
43
43
  if (Array.isArray(screenshot)) {
44
44
  return this._evaluateWithMultipleScreenshots({
45
45
  question,
46
+ answer,
46
47
  screenshots: screenshot,
47
48
  systemPrompt,
48
49
  agentReasoning,
@@ -162,7 +163,7 @@ class LegacyV3Evaluator {
162
163
  }
163
164
  }
164
165
  async _evaluateWithMultipleScreenshots(options) {
165
- const { question, screenshots, agentReasoning, systemPrompt = `You are an expert evaluator that confidently returns YES or NO given a question and multiple screenshots showing the progression of a task.
166
+ const { question, answer, screenshots, agentReasoning, systemPrompt = `You are an expert evaluator that confidently returns YES or NO given a question and multiple screenshots showing the progression of a task.
166
167
  ${agentReasoning ? "You also have access to the agent's detailed reasoning and thought process throughout the task." : ""}
167
168
  Analyze ALL screenshots to understand the complete journey. Look for evidence of task completion across all screenshots, not just the last one.
168
169
  Success criteria may appear at different points in the sequence (confirmation messages, intermediate states, etc).
@@ -191,6 +192,9 @@ class LegacyV3Evaluator {
191
192
  ? `Question: ${question}\n\nAgent's reasoning and actions throughout the task:\n${agentReasoning}\n\nI'm providing ${screenshots.length} screenshots showing the progression of the task. Please analyze both the agent's reasoning and all screenshots to determine if the task was completed successfully.`
192
193
  : `${question}\n\nI'm providing ${screenshots.length} screenshots showing the progression of the task. Please analyze all of them to determine if the task was completed successfully.`,
193
194
  },
195
+ ...(answer
196
+ ? [{ type: "text", text: `the answer is ${answer}` }]
197
+ : []),
194
198
  ...imageContents,
195
199
  ],
196
200
  },