@mercuryo-ai/agentbrowse 0.2.60 → 0.2.61
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/README.md +30 -5
- package/dist/browser-session-state.d.ts +39 -0
- package/dist/browser-session-state.d.ts.map +1 -1
- package/dist/browser-session-state.js +63 -1
- package/dist/commands/act.d.ts.map +1 -1
- package/dist/commands/act.js +539 -535
- package/dist/commands/attach.d.ts.map +1 -1
- package/dist/commands/attach.js +5 -10
- 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.map +1 -1
- package/dist/commands/browser-status.js +26 -30
- 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/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +11 -8
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +79 -73
- package/dist/commands/observe-inventory.d.ts +1 -0
- package/dist/commands/observe-inventory.d.ts.map +1 -1
- package/dist/commands/observe-inventory.js +15 -3
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +260 -272
- package/dist/commands/screenshot.d.ts.map +1 -1
- package/dist/commands/screenshot.js +50 -64
- package/dist/library.d.ts +2 -1
- package/dist/library.d.ts.map +1 -1
- package/dist/library.js +2 -1
- package/dist/protected-fill.d.ts.map +1 -1
- package/dist/protected-fill.js +46 -7
- 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/docs/configuration.md +36 -4
- package/docs/getting-started.md +28 -4
- package/docs/troubleshooting.md +42 -6
- package/package.json +1 -1
- 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,6 +21,8 @@ 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
27
|
import { annotateDomTargets, compressSemanticallyDuplicateTargets, orderBySurfaceCompetition, prioritizeGoalActionTargets, } from './observe-semantics.js';
|
|
26
28
|
import { buildGroupedObserveScopes, buildGoalProjectionScopeRefs, buildGoalObserveInventoryCandidates, compactFillableForms, compactSignals, expandWorkflowGraphTargets, projectPersistedTargetsForGoal, selectTargetsForGoalMatches, } from './observe-projection.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,250 @@ 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 = compressSemanticallyDuplicateTargets(orderBySurfaceCompetition(annotateDomTargets(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
|
+
return buildObserveSuccessResult(session, observeStep, {
|
|
261
|
+
success: true,
|
|
262
|
+
observationMode: 'deterministic_dom',
|
|
263
|
+
pageRef,
|
|
264
|
+
resolvedBy: 'dom',
|
|
265
|
+
...domRuntimeResolution(),
|
|
266
|
+
scopes: buildGroupedObserveScopes({
|
|
267
|
+
pageRef,
|
|
268
|
+
title,
|
|
269
|
+
scopes: selectScopesForOutput(observedScopes, targets),
|
|
270
|
+
targets,
|
|
271
|
+
}),
|
|
272
|
+
signals: compactSignals(pageSignals),
|
|
273
|
+
fillableForms: compactFillableForms(fillableForms),
|
|
274
|
+
metrics: session.runtime?.metrics,
|
|
275
|
+
message: targets.length === 0 ? 'This observe pass returned zero targets.' : undefined,
|
|
276
|
+
...buildObservePageMetadata({
|
|
277
|
+
url,
|
|
278
|
+
title,
|
|
279
|
+
protectedExposure,
|
|
280
|
+
}),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
if (!allowAssistive) {
|
|
284
|
+
return buildObserveSuccessResult(session, observeStep, {
|
|
285
|
+
success: true,
|
|
286
|
+
observationMode: 'deterministic_dom',
|
|
287
|
+
pageRef,
|
|
288
|
+
resolvedBy: 'dom',
|
|
289
|
+
...domRuntimeResolution(),
|
|
290
|
+
scopes: [],
|
|
291
|
+
signals: compactSignals(pageSignals),
|
|
292
|
+
fillableForms: [],
|
|
293
|
+
metrics: session.runtime?.metrics,
|
|
294
|
+
message: 'This observe pass returned zero targets.',
|
|
295
|
+
...buildObservePageMetadata({
|
|
296
|
+
url,
|
|
297
|
+
title,
|
|
298
|
+
protectedExposure,
|
|
299
|
+
}),
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
stagehandFallbackReason = 'deterministic-observe-empty';
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
domPassError = err instanceof Error ? err.message : String(err);
|
|
306
|
+
if (!allowAssistive) {
|
|
307
|
+
return buildObserveContractFailureResult(session, {
|
|
308
|
+
step: observeStep,
|
|
309
|
+
error: 'observe_failed',
|
|
310
|
+
outcomeType: 'blocked',
|
|
311
|
+
message: 'Observe failed.',
|
|
312
|
+
reason: domPassError,
|
|
313
|
+
pageRef,
|
|
314
|
+
runId: session.activeRunId,
|
|
315
|
+
stepId: observeStep?.stepId,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
stagehandFallbackReason = 'deterministic-observe-failed';
|
|
319
|
+
}
|
|
244
320
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
321
|
+
if (instruction) {
|
|
322
|
+
try {
|
|
323
|
+
const resolvedPage = await resolveCurrentPageContext(browser, session);
|
|
324
|
+
pageRef = resolvedPage.pageRef;
|
|
325
|
+
const page = resolvedPage.page;
|
|
326
|
+
const previousPageUrl = session.runtime?.pages?.[pageRef]?.url;
|
|
327
|
+
const { url, title } = await syncSessionPage(session, pageRef, page);
|
|
328
|
+
const protectedExposure = getProtectedExposure(session, pageRef);
|
|
329
|
+
if (protectedExposure) {
|
|
330
|
+
return buildObserveContractFailureResult(session, {
|
|
331
|
+
step: observeStep,
|
|
332
|
+
...buildProtectedObserveBlockedResult(protectedExposure, 'goal-rerank'),
|
|
333
|
+
pageRef,
|
|
334
|
+
runId: session.activeRunId,
|
|
335
|
+
stepId: observeStep?.stepId,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
bumpPageScopeEpoch(session, pageRef);
|
|
339
|
+
setCurrentPage(session, pageRef);
|
|
340
|
+
const collectedTargets = await collectDomTargets(page, {
|
|
341
|
+
includeActivationAffordances: true,
|
|
342
|
+
});
|
|
343
|
+
let observeAccessibilityStats;
|
|
344
|
+
const domTargets = compressSemanticallyDuplicateTargets(orderBySurfaceCompetition(annotateDomTargets(await enrichDomTargetsWithAccessibility(page, collectedTargets, {
|
|
345
|
+
onStats: (stats) => {
|
|
346
|
+
observeAccessibilityStats = stats;
|
|
347
|
+
},
|
|
348
|
+
}))));
|
|
349
|
+
if (observeAccessibilityStats) {
|
|
350
|
+
incrementMetric(session, 'observeAxAttempts', observeAccessibilityStats.axAttempts);
|
|
351
|
+
incrementMetric(session, 'observeAxHits', observeAccessibilityStats.axHits);
|
|
352
|
+
incrementMetric(session, 'observeFallbackUses', observeAccessibilityStats.fallbackUses);
|
|
353
|
+
}
|
|
354
|
+
const pageSignals = await collectPageSignals(page).catch(() => []);
|
|
355
|
+
const pageState = classifyObservePageState(pageSignals);
|
|
356
|
+
const surfaceInputs = collectSurfaceDescriptors(pageRef, domTargets);
|
|
357
|
+
if (domTargets.length > 0) {
|
|
358
|
+
const rerankedCandidates = await tracedStepOperation(() => rerankDomTargetsForGoal(instruction, buildGoalObserveInventoryCandidates(domTargets, surfaceInputs), { session }), {
|
|
359
|
+
spanName: 'agentbrowse.observe.rerank_goal_candidates',
|
|
360
|
+
attributes: {
|
|
361
|
+
...observePhaseAttributes,
|
|
362
|
+
'agentbrowse.observe.target_count': domTargets.length,
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
const { targets: goalMatchedTargets, selectedSurfaceIds } = selectTargetsForGoalMatches(domTargets, rerankedCandidates);
|
|
366
|
+
const selectedTargets = prioritizeGoalActionTargets(instruction, expandWorkflowGraphTargets(domTargets, goalMatchedTargets, {
|
|
367
|
+
selectedSurfaceIds,
|
|
368
|
+
}));
|
|
369
|
+
const persisted = persistObservedSurfacesForPage(session, pageRef, domTargets, {
|
|
370
|
+
allSurfaceInputs: surfaceInputs,
|
|
371
|
+
explicitSurfaceIds: selectedSurfaceIds,
|
|
372
|
+
});
|
|
373
|
+
observedScopes = persisted.observedScopes;
|
|
374
|
+
const surfaceRefMap = persisted.surfaceRefMap;
|
|
375
|
+
const targets = replaceTargetsForPage(session, pageRef, domTargets.map((target) => toDomDescriptor(pageRef, target, surfaceRefMap)));
|
|
376
|
+
reconcileObservedTargetsForPage(session, pageRef, targets);
|
|
377
|
+
attachObservedTargetOwners(domTargets, targets);
|
|
378
|
+
observedScopes = linkObservedSurfaceGraph(session, pageRef, domTargets, targets, observedScopes, surfaceRefMap);
|
|
379
|
+
const fillableForms = shouldSuppressFillableFormsForObserve(pageState)
|
|
380
|
+
? clearProtectedFillableFormsForPage(session, pageRef)
|
|
381
|
+
: await persistProtectedFillableFormsForPage(session, pageRef, url, targets, new Date().toISOString(), { previousPageUrl });
|
|
382
|
+
if (selectedTargets.length > 0 || selectedSurfaceIds.size > 0) {
|
|
383
|
+
const projectedTargets = projectPersistedTargetsForGoal(domTargets, targets, selectedTargets);
|
|
384
|
+
const explicitScopeRefs = buildGoalProjectionScopeRefs(projectedTargets, selectedSurfaceIds, surfaceRefMap);
|
|
385
|
+
return buildObserveSuccessResult(session, observeStep, {
|
|
386
|
+
success: true,
|
|
387
|
+
observationMode: canUseAssistiveLlm
|
|
388
|
+
? 'goal_assistive_rerank'
|
|
389
|
+
: 'goal_heuristic_shortlist',
|
|
390
|
+
pageRef,
|
|
391
|
+
resolvedBy: 'dom-rerank',
|
|
392
|
+
...domRuntimeResolution(),
|
|
393
|
+
scopes: buildGroupedObserveScopes({
|
|
394
|
+
pageRef,
|
|
395
|
+
title,
|
|
396
|
+
scopes: selectScopesForOutput(observedScopes, projectedTargets, explicitScopeRefs),
|
|
397
|
+
targets: projectedTargets,
|
|
398
|
+
}),
|
|
399
|
+
signals: compactSignals(pageSignals),
|
|
400
|
+
fillableForms: compactFillableForms(fillableForms),
|
|
401
|
+
metrics: session.runtime?.metrics,
|
|
402
|
+
url,
|
|
403
|
+
title,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
return buildObserveSuccessResult(session, observeStep, {
|
|
407
|
+
success: true,
|
|
408
|
+
observationMode: canUseAssistiveLlm
|
|
409
|
+
? 'goal_assistive_rerank'
|
|
410
|
+
: 'goal_heuristic_shortlist',
|
|
411
|
+
pageRef,
|
|
412
|
+
resolvedBy: 'dom-rerank',
|
|
413
|
+
...domRuntimeResolution(),
|
|
414
|
+
scopes: [],
|
|
415
|
+
signals: compactSignals(pageSignals),
|
|
416
|
+
fillableForms: compactFillableForms(fillableForms),
|
|
417
|
+
metrics: session.runtime?.metrics,
|
|
418
|
+
message: 'This goal-based observe pass returned zero matching targets.',
|
|
419
|
+
url,
|
|
420
|
+
title,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
stagehandFallbackReason = 'deterministic-observe-empty';
|
|
424
|
+
}
|
|
425
|
+
catch (err) {
|
|
426
|
+
domPassError = err instanceof Error ? err.message : String(err);
|
|
427
|
+
stagehandFallbackReason = 'deterministic-observe-failed';
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
const resolvedPage = await resolveCurrentPageContext(browser, session);
|
|
432
|
+
pageRef = resolvedPage.pageRef;
|
|
433
|
+
const page = resolvedPage.page;
|
|
434
|
+
const { url, title } = await syncSessionPage(session, pageRef, page);
|
|
435
|
+
const protectedExposure = getProtectedExposure(session, pageRef);
|
|
436
|
+
if (protectedExposure) {
|
|
437
|
+
return buildObserveContractFailureResult(session, {
|
|
438
|
+
step: observeStep,
|
|
439
|
+
...buildProtectedObserveBlockedResult(protectedExposure, 'stagehand-fallback'),
|
|
440
|
+
fallbackReason: stagehandFallbackReason ?? undefined,
|
|
441
|
+
deterministicObserveError: domPassError ?? undefined,
|
|
442
|
+
pageRef,
|
|
443
|
+
runId: session.activeRunId,
|
|
444
|
+
stepId: observeStep?.stepId,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
bumpPageScopeEpoch(session, pageRef);
|
|
448
|
+
setCurrentPage(session, pageRef);
|
|
449
|
+
const pageSignals = await collectPageSignals(page).catch(() => []);
|
|
450
|
+
const actions = await withStagehand(session, async (stagehand) => {
|
|
451
|
+
incrementMetric(session, 'stagehandCalls');
|
|
452
|
+
return instruction
|
|
453
|
+
? (await stagehand.observe(instruction, {
|
|
454
|
+
page,
|
|
455
|
+
}))
|
|
456
|
+
: (await stagehand.observe({ page }));
|
|
457
|
+
});
|
|
458
|
+
const targets = replaceTargetsForPage(session, pageRef, await Promise.all(actions.map((action) => toStagehandDescriptor(pageRef, action, page, normalizePageSignature(url)))));
|
|
459
|
+
const fillableForms = markProtectedFillableFormsUnknownForPage(session, pageRef);
|
|
260
460
|
return buildObserveSuccessResult(session, observeStep, {
|
|
261
461
|
success: true,
|
|
262
|
-
observationMode: '
|
|
462
|
+
observationMode: 'goal_assistive_stagehand',
|
|
263
463
|
pageRef,
|
|
264
|
-
resolvedBy: '
|
|
265
|
-
...
|
|
464
|
+
resolvedBy: 'stagehand-observe',
|
|
465
|
+
...stagehandRuntimeResolution(stagehandFallbackReason ?? 'deterministic-observe-failed'),
|
|
466
|
+
deterministicObserveError: domPassError ?? undefined,
|
|
266
467
|
scopes: buildGroupedObserveScopes({
|
|
267
468
|
pageRef,
|
|
268
469
|
title,
|
|
@@ -273,259 +474,46 @@ export async function observeBrowser(session, instruction) {
|
|
|
273
474
|
fillableForms: compactFillableForms(fillableForms),
|
|
274
475
|
metrics: session.runtime?.metrics,
|
|
275
476
|
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
|
-
}),
|
|
477
|
+
url,
|
|
478
|
+
title,
|
|
302
479
|
});
|
|
303
480
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
481
|
+
catch (err) {
|
|
482
|
+
const stagehandError = err instanceof Error ? err.message : String(err);
|
|
483
|
+
const details = domPassError
|
|
484
|
+
? `${stagehandError} (deterministic observe failed earlier: ${domPassError})`
|
|
485
|
+
: stagehandError;
|
|
309
486
|
return buildObserveContractFailureResult(session, {
|
|
310
487
|
step: observeStep,
|
|
311
488
|
error: 'observe_failed',
|
|
312
489
|
outcomeType: 'blocked',
|
|
313
490
|
message: 'Observe failed.',
|
|
314
|
-
reason:
|
|
491
|
+
reason: details,
|
|
315
492
|
pageRef,
|
|
316
493
|
runId: session.activeRunId,
|
|
317
494
|
stepId: observeStep?.stepId,
|
|
318
495
|
});
|
|
319
496
|
}
|
|
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
497
|
});
|
|
507
498
|
}
|
|
508
499
|
catch (err) {
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
500
|
+
const browserConnectionFailure = describeBrowserConnectionFailure(err, {
|
|
501
|
+
defaultMessage: instruction
|
|
502
|
+
? 'Observe could not start because AgentBrowse failed to connect to the browser.'
|
|
503
|
+
: 'Observe failed.',
|
|
504
|
+
unrecoverableSessionMessage: 'Observe could not start because the previous browser session is no longer reachable.',
|
|
505
|
+
});
|
|
513
506
|
return buildObserveContractFailureResult(session, {
|
|
514
507
|
step: observeStep,
|
|
515
|
-
error: 'observe_failed',
|
|
508
|
+
error: instruction ? 'browser_connection_failed' : 'observe_failed',
|
|
516
509
|
outcomeType: 'blocked',
|
|
517
|
-
message:
|
|
518
|
-
reason:
|
|
510
|
+
message: browserConnectionFailure.message,
|
|
511
|
+
reason: browserConnectionFailure.reason,
|
|
519
512
|
pageRef,
|
|
520
513
|
runId: session.activeRunId,
|
|
521
514
|
stepId: observeStep?.stepId,
|
|
522
515
|
});
|
|
523
516
|
}
|
|
524
|
-
finally {
|
|
525
|
-
if (browser) {
|
|
526
|
-
await disconnectPlaywright(browser);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
517
|
});
|
|
530
518
|
}
|
|
531
519
|
/** 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"}
|