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