@mercuryo-ai/agentbrowse 0.2.60 → 0.2.63
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.
- package/CHANGELOG.md +33 -1
- package/README.md +132 -14
- package/dist/browser-session-state.d.ts +40 -10
- package/dist/browser-session-state.d.ts.map +1 -1
- package/dist/browser-session-state.js +63 -5
- package/dist/commands/act.d.ts.map +1 -1
- package/dist/commands/act.js +548 -535
- package/dist/commands/attach.d.ts +1 -3
- package/dist/commands/attach.d.ts.map +1 -1
- package/dist/commands/attach.js +5 -12
- package/dist/commands/browser-connection-failure.d.ts +9 -0
- package/dist/commands/browser-connection-failure.d.ts.map +1 -0
- package/dist/commands/browser-connection-failure.js +15 -0
- package/dist/commands/browser-status.d.ts +0 -2
- package/dist/commands/browser-status.d.ts.map +1 -1
- package/dist/commands/browser-status.js +27 -37
- package/dist/commands/close.d.ts.map +1 -1
- package/dist/commands/close.js +5 -0
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +147 -144
- package/dist/commands/interaction-kernel.d.ts +1 -1
- package/dist/commands/interaction-kernel.d.ts.map +1 -1
- package/dist/commands/interaction-kernel.js +1 -1
- package/dist/commands/launch.d.ts +0 -1
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +11 -12
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +79 -73
- package/dist/commands/observe-accessibility.d.ts.map +1 -1
- package/dist/commands/observe-accessibility.js +36 -2
- package/dist/commands/observe-inventory.d.ts +50 -7
- package/dist/commands/observe-inventory.d.ts.map +1 -1
- package/dist/commands/observe-inventory.js +822 -99
- package/dist/commands/observe-persistence.d.ts.map +1 -1
- package/dist/commands/observe-persistence.js +49 -6
- package/dist/commands/observe-projection.d.ts +6 -2
- package/dist/commands/observe-projection.d.ts.map +1 -1
- package/dist/commands/observe-projection.js +251 -27
- package/dist/commands/observe-semantics.d.ts +1 -0
- package/dist/commands/observe-semantics.d.ts.map +1 -1
- package/dist/commands/observe-semantics.js +541 -135
- package/dist/commands/observe-signals.d.ts +4 -4
- package/dist/commands/observe-signals.d.ts.map +1 -1
- package/dist/commands/observe-signals.js +2 -2
- package/dist/commands/observe-surfaces.d.ts +2 -1
- package/dist/commands/observe-surfaces.d.ts.map +1 -1
- package/dist/commands/observe-surfaces.js +143 -45
- package/dist/commands/observe.d.ts +5 -1
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +266 -274
- package/dist/commands/screenshot.d.ts.map +1 -1
- package/dist/commands/screenshot.js +50 -64
- package/dist/commands/semantic-observe.d.ts.map +1 -1
- package/dist/commands/semantic-observe.js +43 -0
- package/dist/library.d.ts +3 -1
- package/dist/library.d.ts.map +1 -1
- package/dist/library.js +3 -1
- package/dist/match-resolve-fill.d.ts +196 -0
- package/dist/match-resolve-fill.d.ts.map +1 -0
- package/dist/match-resolve-fill.js +700 -0
- package/dist/match-resolve-fill.test-support.d.ts +34 -0
- package/dist/match-resolve-fill.test-support.d.ts.map +1 -0
- package/dist/match-resolve-fill.test-support.js +81 -0
- package/dist/protected-fill.d.ts.map +1 -1
- package/dist/protected-fill.js +46 -7
- package/dist/runtime-protected-state.d.ts.map +1 -1
- package/dist/runtime-protected-state.js +12 -0
- package/dist/runtime-state.d.ts +6 -0
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +6 -0
- package/dist/secrets/form-matcher.d.ts.map +1 -1
- package/dist/secrets/form-matcher.js +76 -27
- package/dist/secrets/protected-exact-value-redaction.d.ts.map +1 -1
- package/dist/secrets/protected-exact-value-redaction.js +6 -0
- package/dist/secrets/protected-fill.js +3 -3
- package/dist/session.d.ts +3 -3
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +2 -2
- package/dist/solver/browser-launcher.d.ts.map +1 -1
- package/dist/solver/browser-launcher.js +2 -1
- package/dist/sticky-owner-host-entry.d.ts +2 -0
- package/dist/sticky-owner-host-entry.d.ts.map +1 -0
- package/dist/sticky-owner-host-entry.js +97 -0
- package/dist/sticky-owner.d.ts +15 -0
- package/dist/sticky-owner.d.ts.map +1 -0
- package/dist/sticky-owner.js +431 -0
- package/dist/testing.d.ts +1 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +1 -0
- package/docs/README.md +28 -11
- package/docs/api-reference.md +311 -19
- package/docs/assistive-runtime.md +41 -16
- package/docs/configuration.md +36 -4
- package/docs/getting-started.md +73 -5
- package/docs/integration-checklist.md +32 -3
- package/docs/match-resolve-fill.md +699 -0
- package/docs/protected-fill.md +373 -91
- package/docs/testing.md +147 -15
- package/docs/troubleshooting.md +47 -6
- package/examples/README.md +7 -0
- package/examples/match-resolve-fill.ts +107 -0
- package/package.json +4 -2
- package/dist/protected-fill-browser.d.ts +0 -22
- package/dist/protected-fill-browser.d.ts.map +0 -1
- package/dist/protected-fill-browser.js +0 -52
package/dist/commands/observe.js
CHANGED
|
@@ -7,7 +7,7 @@ import { ensureRuntimeState, replaceTargetsForPage } from '../runtime-state.js';
|
|
|
7
7
|
import { incrementMetric } from '../runtime-metrics.js';
|
|
8
8
|
import { bumpPageScopeEpoch, setCurrentPage } from '../runtime-page-state.js';
|
|
9
9
|
import { getProtectedExposure } from '../runtime-protected-state.js';
|
|
10
|
-
import {
|
|
10
|
+
import { resolveCurrentPageContext, syncSessionPage } from '../playwright-runtime.js';
|
|
11
11
|
import { tracedStepOperation, withApiTraceContext } from '../command-api-tracing.js';
|
|
12
12
|
import { captureDiagnosticSnapshotBestEffort, finishDiagnosticStepBestEffort, recordCommandLifecycleEventBestEffort, startDiagnosticStep, } from '../diagnostics.js';
|
|
13
13
|
import { outputContractFailure, outputJSON, } from '../output.js';
|
|
@@ -21,9 +21,11 @@ import { enrichDomTargetsWithAccessibility } from './observe-accessibility.js';
|
|
|
21
21
|
import { collectPageSignals } from './observe-signals.js';
|
|
22
22
|
import { attachObservedTargetOwners, linkObservedSurfaceGraph, reconcileObservedTargetsForPage, persistObservedSurfacesForPage, toDomDescriptor, } from './observe-persistence.js';
|
|
23
23
|
import { clearProtectedFillableFormsForPage, markProtectedFillableFormsUnknownForPage, persistProtectedFillableFormsForPage, } from './observe-protected.js';
|
|
24
|
+
import { withStickyOwnerBrowser } from '../sticky-owner.js';
|
|
25
|
+
import { describeBrowserConnectionFailure } from './browser-connection-failure.js';
|
|
24
26
|
import { classifyObservePageState, shouldSuppressFillableFormsForObserve, } from './observe-page-state.js';
|
|
25
|
-
import {
|
|
26
|
-
import { buildGroupedObserveScopes, buildGoalProjectionScopeRefs, buildGoalObserveInventoryCandidates, compactFillableForms, compactSignals, expandWorkflowGraphTargets, projectPersistedTargetsForGoal, selectTargetsForGoalMatches, } from './observe-projection.js';
|
|
27
|
+
import { normalizePostEnrichmentDomTargets, prioritizeGoalActionTargets, } from './observe-semantics.js';
|
|
28
|
+
import { buildGroupedObserveScopes, buildGoalProjectionScopeRefs, buildGoalObserveInventoryCandidates, compactFillableForms, compactSignals, expandWorkflowGraphTargets, materializeObserveOutputTargets, projectPersistedTargetsForGoal, selectTargetsForGoalMatches, } from './observe-projection.js';
|
|
27
29
|
import { collectSurfaceDescriptors, selectScopesForOutput } from './observe-surfaces.js';
|
|
28
30
|
import { toStagehandDescriptor } from './observe-stagehand.js';
|
|
29
31
|
import { rerankDomTargetsForGoal } from './semantic-observe.js';
|
|
@@ -174,7 +176,6 @@ export async function observeBrowser(session, instruction) {
|
|
|
174
176
|
let pageRef = runtime.currentPageRef;
|
|
175
177
|
let domPassError = null;
|
|
176
178
|
let stagehandFallbackReason = null;
|
|
177
|
-
let browser = null;
|
|
178
179
|
let observedScopes = [];
|
|
179
180
|
const observeStep = startDiagnosticStep({
|
|
180
181
|
runId: session.activeRunId,
|
|
@@ -219,50 +220,254 @@ export async function observeBrowser(session, instruction) {
|
|
|
219
220
|
stepId: observeStep?.stepId,
|
|
220
221
|
});
|
|
221
222
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
223
|
+
try {
|
|
224
|
+
return await withStickyOwnerBrowser(session, async (browser) => {
|
|
225
|
+
if (!instruction) {
|
|
226
|
+
try {
|
|
227
|
+
const resolvedPage = await resolveCurrentPageContext(browser, session);
|
|
228
|
+
pageRef = resolvedPage.pageRef;
|
|
229
|
+
const page = resolvedPage.page;
|
|
230
|
+
const previousPageUrl = session.runtime?.pages?.[pageRef]?.url;
|
|
231
|
+
const { url, title } = await syncSessionPage(session, pageRef, page);
|
|
232
|
+
const protectedExposure = getProtectedExposure(session, pageRef);
|
|
233
|
+
bumpPageScopeEpoch(session, pageRef);
|
|
234
|
+
setCurrentPage(session, pageRef);
|
|
235
|
+
const collectedTargets = await collectDomTargets(page);
|
|
236
|
+
let observeAccessibilityStats;
|
|
237
|
+
const domTargets = normalizePostEnrichmentDomTargets(await enrichDomTargetsWithAccessibility(page, collectedTargets, {
|
|
238
|
+
onStats: (stats) => {
|
|
239
|
+
observeAccessibilityStats = stats;
|
|
240
|
+
},
|
|
241
|
+
}));
|
|
242
|
+
if (observeAccessibilityStats) {
|
|
243
|
+
incrementMetric(session, 'observeAxAttempts', observeAccessibilityStats.axAttempts);
|
|
244
|
+
incrementMetric(session, 'observeAxHits', observeAccessibilityStats.axHits);
|
|
245
|
+
incrementMetric(session, 'observeFallbackUses', observeAccessibilityStats.fallbackUses);
|
|
246
|
+
}
|
|
247
|
+
const pageSignals = await collectPageSignals(page).catch(() => []);
|
|
248
|
+
const pageState = classifyObservePageState(pageSignals);
|
|
249
|
+
const persisted = persistObservedSurfacesForPage(session, pageRef, domTargets);
|
|
250
|
+
observedScopes = persisted.observedScopes;
|
|
251
|
+
const surfaceRefMap = persisted.surfaceRefMap;
|
|
252
|
+
if (domTargets.length > 0) {
|
|
253
|
+
const targets = replaceTargetsForPage(session, pageRef, domTargets.map((target) => toDomDescriptor(pageRef, target, surfaceRefMap)));
|
|
254
|
+
reconcileObservedTargetsForPage(session, pageRef, targets);
|
|
255
|
+
attachObservedTargetOwners(domTargets, targets);
|
|
256
|
+
observedScopes = linkObservedSurfaceGraph(session, pageRef, domTargets, targets, observedScopes, surfaceRefMap);
|
|
257
|
+
const fillableForms = shouldSuppressFillableFormsForObserve(pageState)
|
|
258
|
+
? clearProtectedFillableFormsForPage(session, pageRef)
|
|
259
|
+
: await persistProtectedFillableFormsForPage(session, pageRef, url, targets, new Date().toISOString(), { previousPageUrl });
|
|
260
|
+
const outputTargets = materializeObserveOutputTargets(domTargets, targets);
|
|
261
|
+
return buildObserveSuccessResult(session, observeStep, {
|
|
262
|
+
success: true,
|
|
263
|
+
observationMode: 'deterministic_dom',
|
|
264
|
+
pageRef,
|
|
265
|
+
resolvedBy: 'dom',
|
|
266
|
+
...domRuntimeResolution(),
|
|
267
|
+
scopes: buildGroupedObserveScopes({
|
|
268
|
+
pageRef,
|
|
269
|
+
title,
|
|
270
|
+
scopes: selectScopesForOutput(observedScopes, targets),
|
|
271
|
+
targets: outputTargets,
|
|
272
|
+
}),
|
|
273
|
+
signals: compactSignals(pageSignals),
|
|
274
|
+
fillableForms: compactFillableForms(fillableForms),
|
|
275
|
+
metrics: session.runtime?.metrics,
|
|
276
|
+
message: targets.length === 0 ? 'This observe pass returned zero targets.' : undefined,
|
|
277
|
+
...buildObservePageMetadata({
|
|
278
|
+
url,
|
|
279
|
+
title,
|
|
280
|
+
protectedExposure,
|
|
281
|
+
}),
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
if (!allowAssistive) {
|
|
285
|
+
return buildObserveSuccessResult(session, observeStep, {
|
|
286
|
+
success: true,
|
|
287
|
+
observationMode: 'deterministic_dom',
|
|
288
|
+
pageRef,
|
|
289
|
+
resolvedBy: 'dom',
|
|
290
|
+
...domRuntimeResolution(),
|
|
291
|
+
scopes: [],
|
|
292
|
+
signals: compactSignals(pageSignals),
|
|
293
|
+
fillableForms: [],
|
|
294
|
+
metrics: session.runtime?.metrics,
|
|
295
|
+
message: 'This observe pass returned zero targets.',
|
|
296
|
+
...buildObservePageMetadata({
|
|
297
|
+
url,
|
|
298
|
+
title,
|
|
299
|
+
protectedExposure,
|
|
300
|
+
}),
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
stagehandFallbackReason = 'deterministic-observe-empty';
|
|
304
|
+
}
|
|
305
|
+
catch (err) {
|
|
306
|
+
domPassError = err instanceof Error ? err.message : String(err);
|
|
307
|
+
if (!allowAssistive) {
|
|
308
|
+
return buildObserveContractFailureResult(session, {
|
|
309
|
+
step: observeStep,
|
|
310
|
+
error: 'observe_failed',
|
|
311
|
+
outcomeType: 'blocked',
|
|
312
|
+
message: 'Observe failed.',
|
|
313
|
+
reason: domPassError,
|
|
314
|
+
pageRef,
|
|
315
|
+
runId: session.activeRunId,
|
|
316
|
+
stepId: observeStep?.stepId,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
stagehandFallbackReason = 'deterministic-observe-failed';
|
|
320
|
+
}
|
|
244
321
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
322
|
+
if (instruction) {
|
|
323
|
+
try {
|
|
324
|
+
const resolvedPage = await resolveCurrentPageContext(browser, session);
|
|
325
|
+
pageRef = resolvedPage.pageRef;
|
|
326
|
+
const page = resolvedPage.page;
|
|
327
|
+
const previousPageUrl = session.runtime?.pages?.[pageRef]?.url;
|
|
328
|
+
const { url, title } = await syncSessionPage(session, pageRef, page);
|
|
329
|
+
const protectedExposure = getProtectedExposure(session, pageRef);
|
|
330
|
+
if (protectedExposure) {
|
|
331
|
+
return buildObserveContractFailureResult(session, {
|
|
332
|
+
step: observeStep,
|
|
333
|
+
...buildProtectedObserveBlockedResult(protectedExposure, 'goal-rerank'),
|
|
334
|
+
pageRef,
|
|
335
|
+
runId: session.activeRunId,
|
|
336
|
+
stepId: observeStep?.stepId,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
bumpPageScopeEpoch(session, pageRef);
|
|
340
|
+
setCurrentPage(session, pageRef);
|
|
341
|
+
const collectedTargets = await collectDomTargets(page, {
|
|
342
|
+
includeActivationAffordances: true,
|
|
343
|
+
});
|
|
344
|
+
let observeAccessibilityStats;
|
|
345
|
+
const domTargets = normalizePostEnrichmentDomTargets(await enrichDomTargetsWithAccessibility(page, collectedTargets, {
|
|
346
|
+
onStats: (stats) => {
|
|
347
|
+
observeAccessibilityStats = stats;
|
|
348
|
+
},
|
|
349
|
+
}));
|
|
350
|
+
if (observeAccessibilityStats) {
|
|
351
|
+
incrementMetric(session, 'observeAxAttempts', observeAccessibilityStats.axAttempts);
|
|
352
|
+
incrementMetric(session, 'observeAxHits', observeAccessibilityStats.axHits);
|
|
353
|
+
incrementMetric(session, 'observeFallbackUses', observeAccessibilityStats.fallbackUses);
|
|
354
|
+
}
|
|
355
|
+
const pageSignals = await collectPageSignals(page).catch(() => []);
|
|
356
|
+
const pageState = classifyObservePageState(pageSignals);
|
|
357
|
+
const surfaceInputs = collectSurfaceDescriptors(pageRef, domTargets);
|
|
358
|
+
if (domTargets.length > 0) {
|
|
359
|
+
const rerankedCandidates = await tracedStepOperation(() => rerankDomTargetsForGoal(instruction, buildGoalObserveInventoryCandidates(domTargets, surfaceInputs), { session }), {
|
|
360
|
+
spanName: 'agentbrowse.observe.rerank_goal_candidates',
|
|
361
|
+
attributes: {
|
|
362
|
+
...observePhaseAttributes,
|
|
363
|
+
'agentbrowse.observe.target_count': domTargets.length,
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
const { targets: goalMatchedTargets, selectedSurfaceIds } = selectTargetsForGoalMatches(domTargets, rerankedCandidates);
|
|
367
|
+
const selectedTargets = prioritizeGoalActionTargets(instruction, expandWorkflowGraphTargets(domTargets, goalMatchedTargets, {
|
|
368
|
+
selectedSurfaceIds,
|
|
369
|
+
}));
|
|
370
|
+
const persisted = persistObservedSurfacesForPage(session, pageRef, domTargets, {
|
|
371
|
+
allSurfaceInputs: surfaceInputs,
|
|
372
|
+
explicitSurfaceIds: selectedSurfaceIds,
|
|
373
|
+
});
|
|
374
|
+
observedScopes = persisted.observedScopes;
|
|
375
|
+
const surfaceRefMap = persisted.surfaceRefMap;
|
|
376
|
+
const targets = replaceTargetsForPage(session, pageRef, domTargets.map((target) => toDomDescriptor(pageRef, target, surfaceRefMap)));
|
|
377
|
+
reconcileObservedTargetsForPage(session, pageRef, targets);
|
|
378
|
+
attachObservedTargetOwners(domTargets, targets);
|
|
379
|
+
observedScopes = linkObservedSurfaceGraph(session, pageRef, domTargets, targets, observedScopes, surfaceRefMap);
|
|
380
|
+
const fillableForms = shouldSuppressFillableFormsForObserve(pageState)
|
|
381
|
+
? clearProtectedFillableFormsForPage(session, pageRef)
|
|
382
|
+
: await persistProtectedFillableFormsForPage(session, pageRef, url, targets, new Date().toISOString(), { previousPageUrl });
|
|
383
|
+
if (selectedTargets.length > 0 || selectedSurfaceIds.size > 0) {
|
|
384
|
+
const projectedTargets = projectPersistedTargetsForGoal(domTargets, targets, selectedTargets);
|
|
385
|
+
const outputProjectedTargets = materializeObserveOutputTargets(domTargets, targets, projectedTargets);
|
|
386
|
+
const explicitScopeRefs = buildGoalProjectionScopeRefs(outputProjectedTargets, selectedSurfaceIds, surfaceRefMap);
|
|
387
|
+
return buildObserveSuccessResult(session, observeStep, {
|
|
388
|
+
success: true,
|
|
389
|
+
observationMode: canUseAssistiveLlm
|
|
390
|
+
? 'goal_assistive_rerank'
|
|
391
|
+
: 'goal_heuristic_shortlist',
|
|
392
|
+
pageRef,
|
|
393
|
+
resolvedBy: 'dom-rerank',
|
|
394
|
+
...domRuntimeResolution(),
|
|
395
|
+
scopes: buildGroupedObserveScopes({
|
|
396
|
+
pageRef,
|
|
397
|
+
title,
|
|
398
|
+
scopes: selectScopesForOutput(observedScopes, outputProjectedTargets, explicitScopeRefs),
|
|
399
|
+
targets: outputProjectedTargets,
|
|
400
|
+
}),
|
|
401
|
+
signals: compactSignals(pageSignals),
|
|
402
|
+
fillableForms: compactFillableForms(fillableForms),
|
|
403
|
+
metrics: session.runtime?.metrics,
|
|
404
|
+
url,
|
|
405
|
+
title,
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
return buildObserveSuccessResult(session, observeStep, {
|
|
409
|
+
success: true,
|
|
410
|
+
observationMode: canUseAssistiveLlm
|
|
411
|
+
? 'goal_assistive_rerank'
|
|
412
|
+
: 'goal_heuristic_shortlist',
|
|
413
|
+
pageRef,
|
|
414
|
+
resolvedBy: 'dom-rerank',
|
|
415
|
+
...domRuntimeResolution(),
|
|
416
|
+
scopes: [],
|
|
417
|
+
signals: compactSignals(pageSignals),
|
|
418
|
+
fillableForms: compactFillableForms(fillableForms),
|
|
419
|
+
metrics: session.runtime?.metrics,
|
|
420
|
+
message: 'This goal-based observe pass returned zero matching targets.',
|
|
421
|
+
url,
|
|
422
|
+
title,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
stagehandFallbackReason = 'deterministic-observe-empty';
|
|
426
|
+
}
|
|
427
|
+
catch (err) {
|
|
428
|
+
domPassError = err instanceof Error ? err.message : String(err);
|
|
429
|
+
stagehandFallbackReason = 'deterministic-observe-failed';
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
try {
|
|
433
|
+
const resolvedPage = await resolveCurrentPageContext(browser, session);
|
|
434
|
+
pageRef = resolvedPage.pageRef;
|
|
435
|
+
const page = resolvedPage.page;
|
|
436
|
+
const { url, title } = await syncSessionPage(session, pageRef, page);
|
|
437
|
+
const protectedExposure = getProtectedExposure(session, pageRef);
|
|
438
|
+
if (protectedExposure) {
|
|
439
|
+
return buildObserveContractFailureResult(session, {
|
|
440
|
+
step: observeStep,
|
|
441
|
+
...buildProtectedObserveBlockedResult(protectedExposure, 'stagehand-fallback'),
|
|
442
|
+
fallbackReason: stagehandFallbackReason ?? undefined,
|
|
443
|
+
deterministicObserveError: domPassError ?? undefined,
|
|
444
|
+
pageRef,
|
|
445
|
+
runId: session.activeRunId,
|
|
446
|
+
stepId: observeStep?.stepId,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
bumpPageScopeEpoch(session, pageRef);
|
|
450
|
+
setCurrentPage(session, pageRef);
|
|
451
|
+
const pageSignals = await collectPageSignals(page).catch(() => []);
|
|
452
|
+
const actions = await withStagehand(session, async (stagehand) => {
|
|
453
|
+
incrementMetric(session, 'stagehandCalls');
|
|
454
|
+
return instruction
|
|
455
|
+
? (await stagehand.observe(instruction, {
|
|
456
|
+
page,
|
|
457
|
+
}))
|
|
458
|
+
: (await stagehand.observe({
|
|
459
|
+
page,
|
|
460
|
+
}));
|
|
461
|
+
});
|
|
462
|
+
const targets = replaceTargetsForPage(session, pageRef, await Promise.all(actions.map((action) => toStagehandDescriptor(pageRef, action, page, normalizePageSignature(url)))));
|
|
463
|
+
const fillableForms = markProtectedFillableFormsUnknownForPage(session, pageRef);
|
|
260
464
|
return buildObserveSuccessResult(session, observeStep, {
|
|
261
465
|
success: true,
|
|
262
|
-
observationMode: '
|
|
466
|
+
observationMode: 'goal_assistive_stagehand',
|
|
263
467
|
pageRef,
|
|
264
|
-
resolvedBy: '
|
|
265
|
-
...
|
|
468
|
+
resolvedBy: 'stagehand-observe',
|
|
469
|
+
...stagehandRuntimeResolution(stagehandFallbackReason ?? 'deterministic-observe-failed'),
|
|
470
|
+
deterministicObserveError: domPassError ?? undefined,
|
|
266
471
|
scopes: buildGroupedObserveScopes({
|
|
267
472
|
pageRef,
|
|
268
473
|
title,
|
|
@@ -273,259 +478,46 @@ export async function observeBrowser(session, instruction) {
|
|
|
273
478
|
fillableForms: compactFillableForms(fillableForms),
|
|
274
479
|
metrics: session.runtime?.metrics,
|
|
275
480
|
message: targets.length === 0 ? 'This observe pass returned zero targets.' : undefined,
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
title,
|
|
279
|
-
protectedExposure,
|
|
280
|
-
}),
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
if (!allowAssistive) {
|
|
284
|
-
await disconnectPlaywright(browser);
|
|
285
|
-
browser = null;
|
|
286
|
-
return buildObserveSuccessResult(session, observeStep, {
|
|
287
|
-
success: true,
|
|
288
|
-
observationMode: 'deterministic_dom',
|
|
289
|
-
pageRef,
|
|
290
|
-
resolvedBy: 'dom',
|
|
291
|
-
...domRuntimeResolution(),
|
|
292
|
-
scopes: [],
|
|
293
|
-
signals: compactSignals(pageSignals),
|
|
294
|
-
fillableForms: [],
|
|
295
|
-
metrics: session.runtime?.metrics,
|
|
296
|
-
message: 'This observe pass returned zero targets.',
|
|
297
|
-
...buildObservePageMetadata({
|
|
298
|
-
url,
|
|
299
|
-
title,
|
|
300
|
-
protectedExposure,
|
|
301
|
-
}),
|
|
481
|
+
url,
|
|
482
|
+
title,
|
|
302
483
|
});
|
|
303
484
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
485
|
+
catch (err) {
|
|
486
|
+
const stagehandError = err instanceof Error ? err.message : String(err);
|
|
487
|
+
const details = domPassError
|
|
488
|
+
? `${stagehandError} (deterministic observe failed earlier: ${domPassError})`
|
|
489
|
+
: stagehandError;
|
|
309
490
|
return buildObserveContractFailureResult(session, {
|
|
310
491
|
step: observeStep,
|
|
311
492
|
error: 'observe_failed',
|
|
312
493
|
outcomeType: 'blocked',
|
|
313
494
|
message: 'Observe failed.',
|
|
314
|
-
reason:
|
|
495
|
+
reason: details,
|
|
315
496
|
pageRef,
|
|
316
497
|
runId: session.activeRunId,
|
|
317
498
|
stepId: observeStep?.stepId,
|
|
318
499
|
});
|
|
319
500
|
}
|
|
320
|
-
stagehandFallbackReason = 'deterministic-observe-failed';
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if (instruction) {
|
|
324
|
-
try {
|
|
325
|
-
if (!browser) {
|
|
326
|
-
browser = await connectPlaywright(session.cdpUrl);
|
|
327
|
-
}
|
|
328
|
-
const resolvedPage = await resolveCurrentPageContext(browser, session);
|
|
329
|
-
pageRef = resolvedPage.pageRef;
|
|
330
|
-
const page = resolvedPage.page;
|
|
331
|
-
const previousPageUrl = session.runtime?.pages?.[pageRef]?.url;
|
|
332
|
-
const { url, title } = await syncSessionPage(session, pageRef, page);
|
|
333
|
-
const protectedExposure = getProtectedExposure(session, pageRef);
|
|
334
|
-
if (protectedExposure) {
|
|
335
|
-
return buildObserveContractFailureResult(session, {
|
|
336
|
-
step: observeStep,
|
|
337
|
-
...buildProtectedObserveBlockedResult(protectedExposure, 'goal-rerank'),
|
|
338
|
-
pageRef,
|
|
339
|
-
runId: session.activeRunId,
|
|
340
|
-
stepId: observeStep?.stepId,
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
bumpPageScopeEpoch(session, pageRef);
|
|
344
|
-
setCurrentPage(session, pageRef);
|
|
345
|
-
const collectedTargets = await collectDomTargets(page, {
|
|
346
|
-
includeActivationAffordances: true,
|
|
347
|
-
});
|
|
348
|
-
let observeAccessibilityStats;
|
|
349
|
-
const domTargets = compressSemanticallyDuplicateTargets(orderBySurfaceCompetition(annotateDomTargets(await enrichDomTargetsWithAccessibility(page, collectedTargets, {
|
|
350
|
-
onStats: (stats) => {
|
|
351
|
-
observeAccessibilityStats = stats;
|
|
352
|
-
},
|
|
353
|
-
}))));
|
|
354
|
-
if (observeAccessibilityStats) {
|
|
355
|
-
incrementMetric(session, 'observeAxAttempts', observeAccessibilityStats.axAttempts);
|
|
356
|
-
incrementMetric(session, 'observeAxHits', observeAccessibilityStats.axHits);
|
|
357
|
-
incrementMetric(session, 'observeFallbackUses', observeAccessibilityStats.fallbackUses);
|
|
358
|
-
}
|
|
359
|
-
const pageSignals = await collectPageSignals(page).catch(() => []);
|
|
360
|
-
const pageState = classifyObservePageState(pageSignals);
|
|
361
|
-
const surfaceInputs = collectSurfaceDescriptors(pageRef, domTargets);
|
|
362
|
-
if (domTargets.length > 0) {
|
|
363
|
-
const rerankedCandidates = await tracedStepOperation(() => rerankDomTargetsForGoal(instruction, buildGoalObserveInventoryCandidates(domTargets, surfaceInputs), { session }), {
|
|
364
|
-
spanName: 'agentbrowse.observe.rerank_goal_candidates',
|
|
365
|
-
attributes: {
|
|
366
|
-
...observePhaseAttributes,
|
|
367
|
-
'agentbrowse.observe.target_count': domTargets.length,
|
|
368
|
-
},
|
|
369
|
-
});
|
|
370
|
-
const { targets: goalMatchedTargets, selectedSurfaceIds } = selectTargetsForGoalMatches(domTargets, rerankedCandidates);
|
|
371
|
-
const selectedTargets = prioritizeGoalActionTargets(instruction, expandWorkflowGraphTargets(domTargets, goalMatchedTargets, {
|
|
372
|
-
selectedSurfaceIds,
|
|
373
|
-
}));
|
|
374
|
-
const persisted = persistObservedSurfacesForPage(session, pageRef, domTargets, {
|
|
375
|
-
allSurfaceInputs: surfaceInputs,
|
|
376
|
-
explicitSurfaceIds: selectedSurfaceIds,
|
|
377
|
-
});
|
|
378
|
-
observedScopes = persisted.observedScopes;
|
|
379
|
-
const surfaceRefMap = persisted.surfaceRefMap;
|
|
380
|
-
const targets = replaceTargetsForPage(session, pageRef, domTargets.map((target) => toDomDescriptor(pageRef, target, surfaceRefMap)));
|
|
381
|
-
reconcileObservedTargetsForPage(session, pageRef, targets);
|
|
382
|
-
attachObservedTargetOwners(domTargets, targets);
|
|
383
|
-
observedScopes = linkObservedSurfaceGraph(session, pageRef, domTargets, targets, observedScopes, surfaceRefMap);
|
|
384
|
-
const fillableForms = shouldSuppressFillableFormsForObserve(pageState)
|
|
385
|
-
? clearProtectedFillableFormsForPage(session, pageRef)
|
|
386
|
-
: await persistProtectedFillableFormsForPage(session, pageRef, url, targets, new Date().toISOString(), { previousPageUrl });
|
|
387
|
-
if (selectedTargets.length > 0 || selectedSurfaceIds.size > 0) {
|
|
388
|
-
const projectedTargets = projectPersistedTargetsForGoal(domTargets, targets, selectedTargets);
|
|
389
|
-
const explicitScopeRefs = buildGoalProjectionScopeRefs(projectedTargets, selectedSurfaceIds, surfaceRefMap);
|
|
390
|
-
await disconnectPlaywright(browser);
|
|
391
|
-
browser = null;
|
|
392
|
-
return buildObserveSuccessResult(session, observeStep, {
|
|
393
|
-
success: true,
|
|
394
|
-
observationMode: canUseAssistiveLlm
|
|
395
|
-
? 'goal_assistive_rerank'
|
|
396
|
-
: 'goal_heuristic_shortlist',
|
|
397
|
-
pageRef,
|
|
398
|
-
resolvedBy: 'dom-rerank',
|
|
399
|
-
...domRuntimeResolution(),
|
|
400
|
-
scopes: buildGroupedObserveScopes({
|
|
401
|
-
pageRef,
|
|
402
|
-
title,
|
|
403
|
-
scopes: selectScopesForOutput(observedScopes, projectedTargets, explicitScopeRefs),
|
|
404
|
-
targets: projectedTargets,
|
|
405
|
-
}),
|
|
406
|
-
signals: compactSignals(pageSignals),
|
|
407
|
-
fillableForms: compactFillableForms(fillableForms),
|
|
408
|
-
metrics: session.runtime?.metrics,
|
|
409
|
-
url,
|
|
410
|
-
title,
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
await disconnectPlaywright(browser);
|
|
414
|
-
browser = null;
|
|
415
|
-
return buildObserveSuccessResult(session, observeStep, {
|
|
416
|
-
success: true,
|
|
417
|
-
observationMode: canUseAssistiveLlm
|
|
418
|
-
? 'goal_assistive_rerank'
|
|
419
|
-
: 'goal_heuristic_shortlist',
|
|
420
|
-
pageRef,
|
|
421
|
-
resolvedBy: 'dom-rerank',
|
|
422
|
-
...domRuntimeResolution(),
|
|
423
|
-
scopes: [],
|
|
424
|
-
signals: compactSignals(pageSignals),
|
|
425
|
-
fillableForms: compactFillableForms(fillableForms),
|
|
426
|
-
metrics: session.runtime?.metrics,
|
|
427
|
-
message: 'This goal-based observe pass returned zero matching targets.',
|
|
428
|
-
url,
|
|
429
|
-
title,
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
stagehandFallbackReason = 'deterministic-observe-empty';
|
|
433
|
-
}
|
|
434
|
-
catch (err) {
|
|
435
|
-
domPassError = err instanceof Error ? err.message : String(err);
|
|
436
|
-
stagehandFallbackReason = 'deterministic-observe-failed';
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
try {
|
|
440
|
-
if (!browser) {
|
|
441
|
-
browser = await connectPlaywright(session.cdpUrl);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
catch (err) {
|
|
445
|
-
const domFailure = domPassError && domPassError.length > 0 ? `; dom observe failed: ${domPassError}` : '';
|
|
446
|
-
return buildObserveContractFailureResult(session, {
|
|
447
|
-
step: observeStep,
|
|
448
|
-
error: 'browser_connection_failed',
|
|
449
|
-
outcomeType: 'blocked',
|
|
450
|
-
message: 'Observe could not start because AgentBrowse failed to connect to the browser.',
|
|
451
|
-
reason: `${err instanceof Error ? err.message : String(err)}${domFailure}`,
|
|
452
|
-
pageRef,
|
|
453
|
-
runId: session.activeRunId,
|
|
454
|
-
stepId: observeStep?.stepId,
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
try {
|
|
458
|
-
const resolvedPage = await resolveCurrentPageContext(browser, session);
|
|
459
|
-
pageRef = resolvedPage.pageRef;
|
|
460
|
-
const page = resolvedPage.page;
|
|
461
|
-
const { url, title } = await syncSessionPage(session, pageRef, page);
|
|
462
|
-
const protectedExposure = getProtectedExposure(session, pageRef);
|
|
463
|
-
if (protectedExposure) {
|
|
464
|
-
return buildObserveContractFailureResult(session, {
|
|
465
|
-
step: observeStep,
|
|
466
|
-
...buildProtectedObserveBlockedResult(protectedExposure, 'stagehand-fallback'),
|
|
467
|
-
fallbackReason: stagehandFallbackReason ?? undefined,
|
|
468
|
-
deterministicObserveError: domPassError ?? undefined,
|
|
469
|
-
pageRef,
|
|
470
|
-
runId: session.activeRunId,
|
|
471
|
-
stepId: observeStep?.stepId,
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
bumpPageScopeEpoch(session, pageRef);
|
|
475
|
-
setCurrentPage(session, pageRef);
|
|
476
|
-
const pageSignals = await collectPageSignals(page).catch(() => []);
|
|
477
|
-
const actions = await withStagehand(session, async (stagehand) => {
|
|
478
|
-
incrementMetric(session, 'stagehandCalls');
|
|
479
|
-
return instruction
|
|
480
|
-
? (await stagehand.observe(instruction, {
|
|
481
|
-
page,
|
|
482
|
-
}))
|
|
483
|
-
: (await stagehand.observe({ page }));
|
|
484
|
-
});
|
|
485
|
-
const targets = replaceTargetsForPage(session, pageRef, await Promise.all(actions.map((action) => toStagehandDescriptor(pageRef, action, page, normalizePageSignature(url)))));
|
|
486
|
-
const fillableForms = markProtectedFillableFormsUnknownForPage(session, pageRef);
|
|
487
|
-
return buildObserveSuccessResult(session, observeStep, {
|
|
488
|
-
success: true,
|
|
489
|
-
observationMode: 'goal_assistive_stagehand',
|
|
490
|
-
pageRef,
|
|
491
|
-
resolvedBy: 'stagehand-observe',
|
|
492
|
-
...stagehandRuntimeResolution(stagehandFallbackReason ?? 'deterministic-observe-failed'),
|
|
493
|
-
deterministicObserveError: domPassError ?? undefined,
|
|
494
|
-
scopes: buildGroupedObserveScopes({
|
|
495
|
-
pageRef,
|
|
496
|
-
title,
|
|
497
|
-
scopes: selectScopesForOutput(observedScopes, targets),
|
|
498
|
-
targets,
|
|
499
|
-
}),
|
|
500
|
-
signals: compactSignals(pageSignals),
|
|
501
|
-
fillableForms: compactFillableForms(fillableForms),
|
|
502
|
-
metrics: session.runtime?.metrics,
|
|
503
|
-
message: targets.length === 0 ? 'This observe pass returned zero targets.' : undefined,
|
|
504
|
-
url,
|
|
505
|
-
title,
|
|
506
501
|
});
|
|
507
502
|
}
|
|
508
503
|
catch (err) {
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
504
|
+
const browserConnectionFailure = describeBrowserConnectionFailure(err, {
|
|
505
|
+
defaultMessage: instruction
|
|
506
|
+
? 'Observe could not start because AgentBrowse failed to connect to the browser.'
|
|
507
|
+
: 'Observe failed.',
|
|
508
|
+
unrecoverableSessionMessage: 'Observe could not start because the previous browser session is no longer reachable.',
|
|
509
|
+
});
|
|
513
510
|
return buildObserveContractFailureResult(session, {
|
|
514
511
|
step: observeStep,
|
|
515
|
-
error: 'observe_failed',
|
|
512
|
+
error: instruction ? 'browser_connection_failed' : 'observe_failed',
|
|
516
513
|
outcomeType: 'blocked',
|
|
517
|
-
message:
|
|
518
|
-
reason:
|
|
514
|
+
message: browserConnectionFailure.message,
|
|
515
|
+
reason: browserConnectionFailure.reason,
|
|
519
516
|
pageRef,
|
|
520
517
|
runId: session.activeRunId,
|
|
521
518
|
stepId: observeStep?.stepId,
|
|
522
519
|
});
|
|
523
520
|
}
|
|
524
|
-
finally {
|
|
525
|
-
if (browser) {
|
|
526
|
-
await disconnectPlaywright(browser);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
521
|
});
|
|
530
522
|
}
|
|
531
523
|
/** CLI wrapper for `observeBrowser(...)` that persists the observed runtime state. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAkBzE,kEAAkE;AAClE,eAAO,MAAM,sBAAsB,6FAIzB,CAAC;AAEX,8DAA8D;AAC9D,eAAO,MAAM,wBAAwB,0EAI3B,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1E,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9E,4CAA4C;AAC5C,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wCAAwC;AACxC,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,mBAAmB,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC,qBAAqB,EAAE,SAAS,GAAG,2BAA2B,CAAC,CAAC;IACrF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,uBAAuB,GAAG,uBAAuB,CAAC;AAkJjF,0DAA0D;AAC1D,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,gBAAgB,CAAC,CA2G3B;AAED,qGAAqG;AACrG,wBAAsB,UAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBjG"}
|