@nuanu-ai/agentbrowse 0.2.47 → 0.2.49
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 +81 -10
- package/dist/agentpay-gateway.d.ts +9 -0
- package/dist/agentpay-gateway.d.ts.map +1 -1
- package/dist/agentpay-gateway.js +31 -1
- package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
- package/dist/agentpay-stagehand-llm.js +9 -1
- package/dist/command-api-tracing.d.ts +19 -0
- package/dist/command-api-tracing.d.ts.map +1 -0
- package/dist/command-api-tracing.js +137 -0
- package/dist/commands/act.d.ts.map +1 -1
- package/dist/commands/act.js +822 -670
- package/dist/commands/act.test-harness.d.ts +6 -0
- package/dist/commands/act.test-harness.d.ts.map +1 -1
- package/dist/commands/act.test-harness.js +44 -1
- package/dist/commands/action-acceptance.d.ts.map +1 -1
- package/dist/commands/action-acceptance.js +115 -0
- package/dist/commands/captcha-solve.d.ts.map +1 -1
- package/dist/commands/captcha-solve.js +83 -16
- package/dist/commands/click-action-executor.d.ts +0 -1
- package/dist/commands/click-action-executor.d.ts.map +1 -1
- package/dist/commands/click-action-executor.js +31 -77
- package/dist/commands/close.d.ts +3 -3
- package/dist/commands/close.d.ts.map +1 -1
- package/dist/commands/close.js +178 -0
- package/dist/commands/descriptor-validation.d.ts.map +1 -1
- package/dist/commands/descriptor-validation.js +75 -57
- package/dist/commands/end-session.d.ts +25 -0
- package/dist/commands/end-session.d.ts.map +1 -0
- package/dist/commands/end-session.js +161 -0
- package/dist/commands/extract-stagehand-executor.js +1 -1
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +339 -202
- package/dist/commands/fill-secret.d.ts +3 -3
- package/dist/commands/fill-secret.d.ts.map +1 -1
- package/dist/commands/fill-secret.js +419 -234
- package/dist/commands/get-secrets-catalog.d.ts.map +1 -1
- package/dist/commands/get-secrets-catalog.js +66 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +6 -3
- package/dist/commands/interaction-kernel.d.ts +46 -0
- package/dist/commands/interaction-kernel.d.ts.map +1 -0
- package/dist/commands/interaction-kernel.js +215 -0
- package/dist/commands/launch.d.ts +1 -3
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +115 -27
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +188 -45
- package/dist/commands/observe-accessibility.d.ts.map +1 -1
- package/dist/commands/observe-accessibility.js +46 -39
- package/dist/commands/observe-dom-label-contract.d.ts.map +1 -1
- package/dist/commands/observe-dom-label-contract.js +5 -0
- package/dist/commands/observe-inventory.d.ts +13 -0
- package/dist/commands/observe-inventory.d.ts.map +1 -1
- package/dist/commands/observe-inventory.js +320 -65
- package/dist/commands/observe-persistence.d.ts.map +1 -1
- package/dist/commands/observe-persistence.js +3 -0
- package/dist/commands/observe-projection.d.ts +1 -0
- package/dist/commands/observe-projection.d.ts.map +1 -1
- package/dist/commands/observe-projection.js +7 -2
- package/dist/commands/observe-protected.d.ts +1 -0
- package/dist/commands/observe-protected.d.ts.map +1 -1
- package/dist/commands/observe-protected.js +9 -4
- package/dist/commands/observe-semantics.d.ts.map +1 -1
- package/dist/commands/observe-semantics.js +5 -2
- package/dist/commands/observe-stagehand.d.ts +1 -0
- package/dist/commands/observe-stagehand.d.ts.map +1 -1
- package/dist/commands/observe-stagehand.js +2 -0
- package/dist/commands/observe.d.ts +2 -0
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +387 -203
- package/dist/commands/observe.test-harness.d.ts +8 -0
- package/dist/commands/observe.test-harness.d.ts.map +1 -1
- package/dist/commands/observe.test-harness.js +48 -1
- package/dist/commands/poll-secret.d.ts +6 -0
- package/dist/commands/poll-secret.d.ts.map +1 -0
- package/dist/commands/poll-secret.js +159 -0
- package/dist/commands/request-secret.d.ts +6 -0
- package/dist/commands/request-secret.d.ts.map +1 -0
- package/dist/commands/request-secret.js +284 -0
- package/dist/commands/screenshot.d.ts.map +1 -1
- package/dist/commands/screenshot.js +172 -7
- package/dist/commands/select-action-executor.d.ts.map +1 -1
- package/dist/commands/semantic-observe.d.ts +4 -0
- package/dist/commands/semantic-observe.d.ts.map +1 -1
- package/dist/commands/semantic-observe.js +388 -17
- package/dist/commands/start-session.d.ts +31 -0
- package/dist/commands/start-session.d.ts.map +1 -0
- package/dist/commands/start-session.js +347 -0
- package/dist/commands/status.d.ts +2 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +166 -144
- package/dist/control-semantics.d.ts +1 -0
- package/dist/control-semantics.d.ts.map +1 -1
- package/dist/control-semantics.js +51 -9
- package/dist/generated/build-config.d.ts +2 -0
- package/dist/generated/build-config.d.ts.map +1 -0
- package/dist/generated/build-config.js +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +163 -63
- package/dist/otel-exporter.d.ts +58 -0
- package/dist/otel-exporter.d.ts.map +1 -0
- package/dist/otel-exporter.js +263 -0
- package/dist/otel-projector.d.ts +75 -0
- package/dist/otel-projector.d.ts.map +1 -0
- package/dist/otel-projector.js +409 -0
- package/dist/owned-browser.d.ts +1 -1
- package/dist/owned-browser.d.ts.map +1 -1
- package/dist/owned-browser.js +13 -1
- package/dist/owned-process.d.ts +2 -0
- package/dist/owned-process.d.ts.map +1 -1
- package/dist/owned-process.js +7 -3
- package/dist/playwright-runtime.d.ts +1 -1
- package/dist/playwright-runtime.d.ts.map +1 -1
- package/dist/playwright-runtime.js +8 -8
- package/dist/run-observability.d.ts +25 -0
- package/dist/run-observability.d.ts.map +1 -0
- package/dist/run-observability.js +115 -0
- package/dist/run-store.d.ts +274 -0
- package/dist/run-store.d.ts.map +1 -0
- package/dist/run-store.js +631 -0
- package/dist/runtime-metrics.d.ts +27 -0
- package/dist/runtime-metrics.d.ts.map +1 -0
- package/dist/runtime-metrics.js +66 -0
- package/dist/runtime-page-state.d.ts +11 -0
- package/dist/runtime-page-state.d.ts.map +1 -0
- package/dist/runtime-page-state.js +62 -0
- package/dist/runtime-protected-state.d.ts +16 -0
- package/dist/runtime-protected-state.d.ts.map +1 -0
- package/dist/runtime-protected-state.js +157 -0
- package/dist/runtime-state.d.ts +10 -44
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +57 -222
- package/dist/secrets/backend.d.ts +65 -16
- package/dist/secrets/backend.d.ts.map +1 -1
- package/dist/secrets/backend.js +135 -95
- package/dist/secrets/catalog-sync.d.ts.map +1 -1
- package/dist/secrets/catalog-sync.js +4 -1
- package/dist/secrets/form-matcher.d.ts +5 -5
- package/dist/secrets/form-matcher.d.ts.map +1 -1
- package/dist/secrets/form-matcher.js +292 -164
- package/dist/secrets/intent-output.d.ts +6 -10
- package/dist/secrets/intent-output.d.ts.map +1 -1
- package/dist/secrets/intent-output.js +4 -58
- package/dist/secrets/mock-agentpay-cabinet.d.ts +38 -27
- package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -1
- package/dist/secrets/mock-agentpay-cabinet.js +177 -111
- package/dist/secrets/protected-artifact-guard.d.ts +2 -2
- package/dist/secrets/protected-artifact-guard.d.ts.map +1 -1
- package/dist/secrets/protected-artifact-guard.js +2 -2
- package/dist/secrets/protected-bindings.d.ts +1 -1
- package/dist/secrets/protected-bindings.d.ts.map +1 -1
- package/dist/secrets/protected-bindings.js +6 -0
- package/dist/secrets/protected-field-semantics.d.ts +9 -0
- package/dist/secrets/protected-field-semantics.d.ts.map +1 -0
- package/dist/secrets/protected-field-semantics.js +154 -0
- package/dist/secrets/protected-field-values.d.ts.map +1 -1
- package/dist/secrets/protected-field-values.js +3 -3
- package/dist/secrets/protected-fill.d.ts +1 -1
- package/dist/secrets/protected-fill.d.ts.map +1 -1
- package/dist/secrets/protected-fill.js +45 -149
- package/dist/secrets/protected-value-adapters.d.ts +2 -1
- package/dist/secrets/protected-value-adapters.d.ts.map +1 -1
- package/dist/secrets/protected-value-adapters.js +80 -1
- package/dist/secrets/request-output.d.ts +11 -0
- package/dist/secrets/request-output.d.ts.map +1 -0
- package/dist/secrets/request-output.js +75 -0
- package/dist/secrets/types.d.ts +15 -9
- package/dist/secrets/types.d.ts.map +1 -1
- package/dist/secrets/types.js +3 -0
- package/dist/session-event-exporter.d.ts +36 -0
- package/dist/session-event-exporter.d.ts.map +1 -0
- package/dist/session-event-exporter.js +428 -0
- package/dist/session.d.ts +16 -7
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +150 -23
- package/dist/sessions-backend.d.ts +354 -0
- package/dist/sessions-backend.d.ts.map +1 -0
- package/dist/sessions-backend.js +126 -0
- package/dist/solver/browser-launcher.d.ts +1 -1
- package/dist/solver/browser-launcher.d.ts.map +1 -1
- package/dist/solver/browser-launcher.js +39 -13
- package/dist/solver/captcha-solver.d.ts.map +1 -1
- package/dist/solver/captcha-solver.js +8 -1
- package/dist/solver/config.d.ts +0 -1
- package/dist/solver/config.d.ts.map +1 -1
- package/dist/solver/config.js +0 -22
- package/dist/solver/types.d.ts +1 -0
- package/dist/solver/types.d.ts.map +1 -1
- package/dist/workflow-session-completion.d.ts +33 -0
- package/dist/workflow-session-completion.d.ts.map +1 -0
- package/dist/workflow-session-completion.js +156 -0
- package/package.json +11 -1
- package/dist/commands/create-intent.d.ts +0 -6
- package/dist/commands/create-intent.d.ts.map +0 -1
- package/dist/commands/create-intent.js +0 -75
- package/dist/commands/poll-intent.d.ts +0 -6
- package/dist/commands/poll-intent.d.ts.map +0 -1
- package/dist/commands/poll-intent.js +0 -57
package/dist/commands/extract.js
CHANGED
|
@@ -4,9 +4,14 @@
|
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { AgentpayStructuredOutputTruncatedError } from '../agentpay-stagehand-llm.js';
|
|
6
6
|
import { saveSession } from '../session.js';
|
|
7
|
-
import {
|
|
7
|
+
import { getSurface, getTarget, markSurfaceLifecycle, markTargetLifecycle, } from '../runtime-state.js';
|
|
8
|
+
import { getPageScopeEpoch, setCurrentPage } from '../runtime-page-state.js';
|
|
8
9
|
import { outputContractFailure, outputJSON } from '../output.js';
|
|
9
10
|
import { connectPlaywright, disconnectPlaywright, resolveCurrentPageContext, resolvePageByRef as resolvePlaywrightPageByRef, syncSessionPage, } from '../playwright-runtime.js';
|
|
11
|
+
import { withApiTraceContext } from '../command-api-tracing.js';
|
|
12
|
+
import { finishRunStep, startRunStep } from '../run-store.js';
|
|
13
|
+
import { appendCommandLifecycleEventBestEffort, captureStepSnapshotBestEffort, } from '../run-observability.js';
|
|
14
|
+
import { exportRunStepToOtlpHttpJsonBestEffort } from '../otel-exporter.js';
|
|
10
15
|
import { normalizePageSignature } from './descriptor-validation.js';
|
|
11
16
|
import { readScopedDialogText } from './extract-scoped-dialog-text.js';
|
|
12
17
|
import { resolveScopedExtractContext } from './extract-scope-resolution.js';
|
|
@@ -177,230 +182,362 @@ function buildTruncationReason(error) {
|
|
|
177
182
|
function schemaRequestsScopedDialogText(schemaDescriptor) {
|
|
178
183
|
return schemaDescriptor.dialog_text === 'string';
|
|
179
184
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
schemaDescriptor = JSON.parse(schemaJson);
|
|
184
|
-
}
|
|
185
|
-
catch {
|
|
186
|
-
return outputContractFailure({
|
|
187
|
-
error: 'invalid_extract_schema',
|
|
188
|
-
outcomeType: 'blocked',
|
|
189
|
-
message: 'Extraction could not start because the schema JSON is invalid.',
|
|
190
|
-
reason: 'The provided schema argument is not valid JSON.',
|
|
191
|
-
});
|
|
185
|
+
function finalizeExtractStepBestEffort(runId, stepId, options) {
|
|
186
|
+
if (!runId || !stepId) {
|
|
187
|
+
return;
|
|
192
188
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
let pageRef = scopeTarget?.pageRef ?? session.runtime?.currentPageRef ?? 'p0';
|
|
199
|
-
if (scopeRef && !scopeTarget) {
|
|
200
|
-
return outputContractFailure({
|
|
201
|
-
error: 'unknown_scope_ref',
|
|
202
|
-
outcomeType: 'blocked',
|
|
203
|
-
message: 'Extraction could not start because the requested scopeRef is unknown.',
|
|
204
|
-
reason: `No live scope target matches scopeRef ${scopeRef}.`,
|
|
205
|
-
scopeRef,
|
|
189
|
+
try {
|
|
190
|
+
finishRunStep({
|
|
191
|
+
runId,
|
|
192
|
+
stepId,
|
|
193
|
+
...options,
|
|
206
194
|
});
|
|
207
195
|
}
|
|
208
|
-
|
|
209
|
-
return outputContractFailure({
|
|
210
|
-
error: 'stale_extract_scope',
|
|
211
|
-
outcomeType: 'binding_stale',
|
|
212
|
-
message: 'Extraction could not start because the requested scope is no longer live.',
|
|
213
|
-
reason: `Scope ${scopeRef} is ${scopeTarget.lifecycle}${scopeTarget.lifecycleReason ? ` because ${scopeTarget.lifecycleReason}` : ''}.`,
|
|
214
|
-
scopeRef,
|
|
215
|
-
});
|
|
196
|
+
catch {
|
|
216
197
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
198
|
+
}
|
|
199
|
+
async function emitExtractSuccess(session, runId, stepId, payload) {
|
|
200
|
+
const step = runId && stepId ? { runId, stepId, command: 'extract' } : null;
|
|
201
|
+
captureStepSnapshotBestEffort({
|
|
202
|
+
session,
|
|
203
|
+
step,
|
|
204
|
+
phase: 'after',
|
|
205
|
+
pageRef: typeof payload.pageRef === 'string' ? payload.pageRef : session.runtime?.currentPageRef,
|
|
206
|
+
url: typeof payload.url === 'string' ? payload.url : undefined,
|
|
207
|
+
title: typeof payload.title === 'string' ? payload.title : undefined,
|
|
208
|
+
});
|
|
209
|
+
appendCommandLifecycleEventBestEffort({
|
|
210
|
+
step,
|
|
211
|
+
phase: 'completed',
|
|
212
|
+
attributes: {
|
|
213
|
+
outcomeType: 'extraction_completed',
|
|
214
|
+
pageRef: typeof payload.pageRef === 'string' ? payload.pageRef : undefined,
|
|
215
|
+
scopeRef: typeof payload.scopeRef === 'string' ? payload.scopeRef : undefined,
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
finalizeExtractStepBestEffort(runId, stepId, {
|
|
219
|
+
success: true,
|
|
220
|
+
outcomeType: 'extraction_completed',
|
|
221
|
+
message: 'Extraction completed.',
|
|
222
|
+
});
|
|
223
|
+
await exportRunStepToOtlpHttpJsonBestEffort(runId, stepId);
|
|
224
|
+
return outputJSON(payload);
|
|
225
|
+
}
|
|
226
|
+
async function emitExtractContractFailure(session, params) {
|
|
227
|
+
const step = params.runId && params.stepId
|
|
228
|
+
? { runId: params.runId, stepId: params.stepId, command: 'extract' }
|
|
229
|
+
: null;
|
|
230
|
+
captureStepSnapshotBestEffort({
|
|
231
|
+
session,
|
|
232
|
+
step,
|
|
233
|
+
phase: 'point-in-time',
|
|
234
|
+
pageRef: typeof params.pageRef === 'string' ? params.pageRef : session.runtime?.currentPageRef,
|
|
235
|
+
});
|
|
236
|
+
appendCommandLifecycleEventBestEffort({
|
|
237
|
+
step,
|
|
238
|
+
phase: 'failed',
|
|
239
|
+
attributes: {
|
|
240
|
+
outcomeType: params.outcomeType,
|
|
241
|
+
pageRef: typeof params.pageRef === 'string' ? params.pageRef : undefined,
|
|
242
|
+
scopeRef: typeof params.scopeRef === 'string' ? params.scopeRef : undefined,
|
|
243
|
+
staleScope: params.staleScope === true,
|
|
244
|
+
reason: params.reason,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
finalizeExtractStepBestEffort(params.runId, params.stepId, {
|
|
248
|
+
success: false,
|
|
249
|
+
outcomeType: params.outcomeType,
|
|
250
|
+
message: params.message,
|
|
251
|
+
reason: params.reason,
|
|
252
|
+
});
|
|
253
|
+
await exportRunStepToOtlpHttpJsonBestEffort(params.runId, params.stepId);
|
|
254
|
+
const { runId: _runId, stepId: _stepId, ...result } = params;
|
|
255
|
+
return outputContractFailure(result);
|
|
256
|
+
}
|
|
257
|
+
export async function extract(session, schemaJson, scopeRef) {
|
|
258
|
+
const initialPageRef = session.runtime?.currentPageRef ?? 'p0';
|
|
259
|
+
const extractStep = session.activeRunId
|
|
260
|
+
? startRunStep({
|
|
261
|
+
runId: session.activeRunId,
|
|
262
|
+
command: 'extract',
|
|
263
|
+
input: {
|
|
264
|
+
schemaJson,
|
|
265
|
+
...(scopeRef ? { scopeRef } : {}),
|
|
266
|
+
},
|
|
267
|
+
refs: {
|
|
268
|
+
pageRef: initialPageRef,
|
|
269
|
+
},
|
|
270
|
+
})
|
|
271
|
+
: null;
|
|
272
|
+
const extractStepHandle = session.activeRunId && extractStep?.stepId
|
|
273
|
+
? {
|
|
274
|
+
runId: session.activeRunId,
|
|
275
|
+
stepId: extractStep.stepId,
|
|
276
|
+
command: 'extract',
|
|
277
|
+
}
|
|
278
|
+
: null;
|
|
279
|
+
captureStepSnapshotBestEffort({
|
|
280
|
+
session,
|
|
281
|
+
step: extractStepHandle,
|
|
282
|
+
phase: 'before',
|
|
283
|
+
pageRef: initialPageRef,
|
|
284
|
+
});
|
|
285
|
+
appendCommandLifecycleEventBestEffort({
|
|
286
|
+
step: extractStepHandle,
|
|
287
|
+
phase: 'started',
|
|
288
|
+
attributes: {
|
|
289
|
+
schemaJson,
|
|
290
|
+
pageRef: initialPageRef,
|
|
291
|
+
...(scopeRef ? { scopeRef } : {}),
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
return withApiTraceContext({
|
|
295
|
+
runId: session.activeRunId,
|
|
296
|
+
stepId: extractStep?.stepId,
|
|
297
|
+
command: 'extract',
|
|
298
|
+
}, async () => {
|
|
299
|
+
let schemaDescriptor;
|
|
300
|
+
try {
|
|
301
|
+
schemaDescriptor = JSON.parse(schemaJson);
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return emitExtractContractFailure(session, {
|
|
305
|
+
error: 'invalid_extract_schema',
|
|
306
|
+
outcomeType: 'blocked',
|
|
307
|
+
message: 'Extraction could not start because the schema JSON is invalid.',
|
|
308
|
+
reason: 'The provided schema argument is not valid JSON.',
|
|
309
|
+
runId: session.activeRunId,
|
|
310
|
+
stepId: extractStep?.stepId,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
const schema = buildSchema(schemaDescriptor);
|
|
314
|
+
const instruction = buildInstruction(schemaDescriptor, scopeRef);
|
|
315
|
+
const targetScope = scopeRef ? getTarget(session, scopeRef) : null;
|
|
316
|
+
const surfaceScope = !targetScope && scopeRef ? getSurface(session, scopeRef) : null;
|
|
317
|
+
const scopeTarget = targetScope ?? surfaceScope;
|
|
318
|
+
let pageRef = scopeTarget?.pageRef ?? session.runtime?.currentPageRef ?? 'p0';
|
|
319
|
+
if (scopeRef && !scopeTarget) {
|
|
320
|
+
return emitExtractContractFailure(session, {
|
|
321
|
+
error: 'unknown_scope_ref',
|
|
322
|
+
outcomeType: 'blocked',
|
|
323
|
+
message: 'Extraction could not start because the requested scopeRef is unknown.',
|
|
324
|
+
reason: `No live scope target matches scopeRef ${scopeRef}.`,
|
|
325
|
+
scopeRef,
|
|
326
|
+
runId: session.activeRunId,
|
|
327
|
+
stepId: extractStep?.stepId,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
if (scopeTarget && scopeTarget.lifecycle !== 'live') {
|
|
331
|
+
return emitExtractContractFailure(session, {
|
|
332
|
+
error: 'stale_extract_scope',
|
|
222
333
|
outcomeType: 'binding_stale',
|
|
223
|
-
message: 'Extraction could not start because the requested
|
|
224
|
-
reason:
|
|
334
|
+
message: 'Extraction could not start because the requested scope is no longer live.',
|
|
335
|
+
reason: `Scope ${scopeRef} is ${scopeTarget.lifecycle}${scopeTarget.lifecycleReason ? ` because ${scopeTarget.lifecycleReason}` : ''}.`,
|
|
225
336
|
scopeRef,
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
staleReason: 'snapshot-scope-expired',
|
|
337
|
+
runId: session.activeRunId,
|
|
338
|
+
stepId: extractStep?.stepId,
|
|
229
339
|
});
|
|
230
340
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
browser = await connectPlaywright(session.cdpUrl);
|
|
248
|
-
}
|
|
249
|
-
catch (err) {
|
|
250
|
-
return outputContractFailure({
|
|
251
|
-
error: 'browser_connection_failed',
|
|
252
|
-
outcomeType: 'blocked',
|
|
253
|
-
message: 'Extraction could not start because AgentBrowse failed to connect to the browser.',
|
|
254
|
-
reason: err instanceof Error ? err.message : String(err),
|
|
255
|
-
scopeRef,
|
|
256
|
-
pageRef,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
try {
|
|
260
|
-
let sourcePage;
|
|
261
|
-
if (scopeTarget) {
|
|
262
|
-
sourcePage = await resolvePlaywrightPageByRef(browser, session, pageRef);
|
|
341
|
+
if (surfaceScope) {
|
|
342
|
+
const snapshotScopeReason = snapshotScopeUnavailableReason(session, surfaceScope);
|
|
343
|
+
if (snapshotScopeReason) {
|
|
344
|
+
return emitExtractContractFailure(session, {
|
|
345
|
+
error: 'expired_extract_scope',
|
|
346
|
+
outcomeType: 'binding_stale',
|
|
347
|
+
message: 'Extraction could not start because the requested snapshot scope is no longer current.',
|
|
348
|
+
reason: snapshotScopeReason,
|
|
349
|
+
scopeRef,
|
|
350
|
+
pageRef,
|
|
351
|
+
staleScope: true,
|
|
352
|
+
staleReason: 'snapshot-scope-expired',
|
|
353
|
+
runId: session.activeRunId,
|
|
354
|
+
stepId: extractStep?.stepId,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
263
357
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
358
|
+
if (targetScope && !canUseTargetAsExtractScope(targetScope)) {
|
|
359
|
+
return emitExtractContractFailure(session, {
|
|
360
|
+
error: 'invalid_extract_scope',
|
|
361
|
+
outcomeType: 'unsupported',
|
|
362
|
+
message: 'Extraction cannot use the requested target as a scope.',
|
|
363
|
+
reason: `Target ${scopeRef} is a leaf control, not an extractable scope container.`,
|
|
364
|
+
scopeRef,
|
|
365
|
+
runId: session.activeRunId,
|
|
366
|
+
stepId: extractStep?.stepId,
|
|
367
|
+
});
|
|
268
368
|
}
|
|
269
|
-
let
|
|
270
|
-
let
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
369
|
+
let browser = null;
|
|
370
|
+
let failureMessage = null;
|
|
371
|
+
let cleanupScopedExtract = null;
|
|
372
|
+
let staleScope = false;
|
|
373
|
+
let staleReason = null;
|
|
374
|
+
try {
|
|
375
|
+
browser = await connectPlaywright(session.cdpUrl);
|
|
276
376
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
377
|
+
catch (err) {
|
|
378
|
+
return emitExtractContractFailure(session, {
|
|
379
|
+
error: 'browser_connection_failed',
|
|
380
|
+
outcomeType: 'blocked',
|
|
381
|
+
message: 'Extraction could not start because AgentBrowse failed to connect to the browser.',
|
|
382
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
383
|
+
scopeRef,
|
|
384
|
+
pageRef,
|
|
385
|
+
runId: session.activeRunId,
|
|
386
|
+
stepId: extractStep?.stepId,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
try {
|
|
390
|
+
let sourcePage;
|
|
391
|
+
if (scopeTarget) {
|
|
392
|
+
sourcePage = await resolvePlaywrightPageByRef(browser, session, pageRef);
|
|
288
393
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
394
|
+
else {
|
|
395
|
+
const resolvedPage = await resolveCurrentPageContext(browser, session);
|
|
396
|
+
pageRef = resolvedPage.pageRef;
|
|
397
|
+
sourcePage = resolvedPage.page;
|
|
398
|
+
}
|
|
399
|
+
let page = sourcePage;
|
|
400
|
+
let scopedResolution = null;
|
|
401
|
+
const { url, title } = await syncSessionPage(session, pageRef, sourcePage);
|
|
402
|
+
if (scopeTarget?.pageSignature && normalizePageSignature(url) !== scopeTarget.pageSignature) {
|
|
403
|
+
staleScope = true;
|
|
404
|
+
staleReason = 'page-signature-mismatch';
|
|
405
|
+
throw new Error('stale_scope_target_page_signature_changed');
|
|
406
|
+
}
|
|
407
|
+
let effectiveSelector;
|
|
408
|
+
if (scopeTarget) {
|
|
409
|
+
try {
|
|
410
|
+
scopedResolution = await resolveScopedExtractContext({
|
|
411
|
+
page: sourcePage,
|
|
412
|
+
scopeTarget,
|
|
413
|
+
validateDomSignature: Boolean(targetScope),
|
|
308
414
|
});
|
|
415
|
+
cleanupScopedExtract = scopedResolution.cleanup;
|
|
416
|
+
page = scopedResolution.page;
|
|
417
|
+
effectiveSelector = scopedResolution.selector;
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
if (error instanceof Error &&
|
|
421
|
+
error.message === 'stale_scope_target_dom_signature_changed') {
|
|
422
|
+
staleScope = true;
|
|
423
|
+
staleReason = 'dom-signature-mismatch';
|
|
424
|
+
}
|
|
425
|
+
else if (surfaceScope &&
|
|
426
|
+
surfaceExtractScopeLifetime(surfaceScope) === 'snapshot' &&
|
|
427
|
+
error instanceof Error &&
|
|
428
|
+
error.message === 'scope_target_unresolvable') {
|
|
429
|
+
return emitExtractContractFailure(session, {
|
|
430
|
+
error: 'expired_extract_scope',
|
|
431
|
+
outcomeType: 'binding_stale',
|
|
432
|
+
message: 'Extraction failed because the requested snapshot scope expired before it could be rebound.',
|
|
433
|
+
reason: `Snapshot scope ${scopeRef} is no longer present in the current visible page state.`,
|
|
434
|
+
scopeRef,
|
|
435
|
+
pageRef,
|
|
436
|
+
staleScope: true,
|
|
437
|
+
staleReason: 'snapshot-scope-expired',
|
|
438
|
+
runId: session.activeRunId,
|
|
439
|
+
stepId: extractStep?.stepId,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
throw error;
|
|
309
443
|
}
|
|
310
|
-
throw error;
|
|
311
444
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
445
|
+
setCurrentPage(session, pageRef);
|
|
446
|
+
const execution = await executeStagehandExtract({
|
|
447
|
+
session,
|
|
448
|
+
instruction,
|
|
449
|
+
schema,
|
|
450
|
+
page,
|
|
451
|
+
selector: effectiveSelector,
|
|
452
|
+
degradationReason: scopedResolution?.degraded
|
|
453
|
+
? scopedResolution.degradationReason
|
|
454
|
+
: undefined,
|
|
455
|
+
});
|
|
456
|
+
let data = execution.data;
|
|
457
|
+
if (scopeTarget &&
|
|
458
|
+
effectiveSelector &&
|
|
459
|
+
schemaRequestsScopedDialogText(schemaDescriptor) &&
|
|
460
|
+
data &&
|
|
461
|
+
typeof data === 'object' &&
|
|
462
|
+
!Array.isArray(data)) {
|
|
463
|
+
const dialogText = await readScopedDialogText(page, effectiveSelector);
|
|
464
|
+
if (typeof dialogText === 'string' && dialogText.trim().length > 0) {
|
|
465
|
+
data = {
|
|
466
|
+
...data,
|
|
467
|
+
dialog_text: dialogText,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
337
470
|
}
|
|
471
|
+
saveSession(session);
|
|
472
|
+
return emitExtractSuccess(session, session.activeRunId, extractStep?.stepId, {
|
|
473
|
+
success: true,
|
|
474
|
+
...execution,
|
|
475
|
+
data,
|
|
476
|
+
pageRef,
|
|
477
|
+
scopeRef,
|
|
478
|
+
metrics: session.runtime?.metrics,
|
|
479
|
+
url,
|
|
480
|
+
title,
|
|
481
|
+
});
|
|
338
482
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
title,
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
catch (err) {
|
|
352
|
-
if (staleScope && scopeRef) {
|
|
353
|
-
if (targetScope) {
|
|
354
|
-
markTargetLifecycle(session, scopeRef, 'stale', staleReason ?? 'unknown');
|
|
483
|
+
catch (err) {
|
|
484
|
+
if (staleScope && scopeRef) {
|
|
485
|
+
if (targetScope) {
|
|
486
|
+
markTargetLifecycle(session, scopeRef, 'stale', staleReason ?? 'unknown');
|
|
487
|
+
}
|
|
488
|
+
else if (surfaceScope) {
|
|
489
|
+
markSurfaceLifecycle(session, scopeRef, 'stale', staleReason ?? 'unknown');
|
|
490
|
+
}
|
|
491
|
+
saveSession(session);
|
|
355
492
|
}
|
|
356
|
-
|
|
357
|
-
|
|
493
|
+
if (err instanceof Error && err.message.startsWith('outputContractFailure:')) {
|
|
494
|
+
throw err;
|
|
358
495
|
}
|
|
359
|
-
|
|
496
|
+
if (!staleScope && err instanceof AgentpayStructuredOutputTruncatedError) {
|
|
497
|
+
return emitExtractContractFailure(session, {
|
|
498
|
+
error: 'extract_output_truncated',
|
|
499
|
+
outcomeType: 'blocked',
|
|
500
|
+
message: 'Extraction failed because the provider truncated structured output.',
|
|
501
|
+
reason: buildTruncationReason(err),
|
|
502
|
+
scopeRef,
|
|
503
|
+
pageRef,
|
|
504
|
+
staleScope: false,
|
|
505
|
+
provider: err.provider,
|
|
506
|
+
model: err.model,
|
|
507
|
+
finishReason: err.finishReason,
|
|
508
|
+
maxOutputTokens: err.maxOutputTokens,
|
|
509
|
+
completionTokens: err.completionTokens,
|
|
510
|
+
runId: session.activeRunId,
|
|
511
|
+
stepId: extractStep?.stepId,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
failureMessage = `Extract failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
360
515
|
}
|
|
361
|
-
|
|
362
|
-
|
|
516
|
+
finally {
|
|
517
|
+
if (cleanupScopedExtract) {
|
|
518
|
+
await cleanupScopedExtract().catch(() => undefined);
|
|
519
|
+
}
|
|
520
|
+
if (browser) {
|
|
521
|
+
await disconnectPlaywright(browser);
|
|
522
|
+
}
|
|
363
523
|
}
|
|
364
|
-
if (
|
|
365
|
-
|
|
366
|
-
error: '
|
|
367
|
-
outcomeType: 'blocked',
|
|
368
|
-
message:
|
|
369
|
-
|
|
524
|
+
if (failureMessage) {
|
|
525
|
+
return emitExtractContractFailure(session, {
|
|
526
|
+
error: staleScope ? 'stale_extract_scope' : 'extract_failed',
|
|
527
|
+
outcomeType: staleScope ? 'binding_stale' : 'blocked',
|
|
528
|
+
message: staleScope
|
|
529
|
+
? 'Extraction failed because the requested scope became stale.'
|
|
530
|
+
: 'Extraction failed.',
|
|
531
|
+
reason: staleScope && scopeRef
|
|
532
|
+
? `${failureMessage} (${scopeRef} marked stale: ${staleReason ?? 'stale'})`
|
|
533
|
+
: failureMessage.replace(/^Extract failed:\s*/, ''),
|
|
370
534
|
scopeRef,
|
|
371
535
|
pageRef,
|
|
372
|
-
staleScope
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
maxOutputTokens: err.maxOutputTokens,
|
|
377
|
-
completionTokens: err.completionTokens,
|
|
536
|
+
staleScope,
|
|
537
|
+
staleReason: staleReason ?? undefined,
|
|
538
|
+
runId: session.activeRunId,
|
|
539
|
+
stepId: extractStep?.stepId,
|
|
378
540
|
});
|
|
379
541
|
}
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
finally {
|
|
383
|
-
if (cleanupScopedExtract) {
|
|
384
|
-
await cleanupScopedExtract().catch(() => undefined);
|
|
385
|
-
}
|
|
386
|
-
if (browser) {
|
|
387
|
-
disconnectPlaywright(browser);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
if (failureMessage) {
|
|
391
|
-
outputContractFailure({
|
|
392
|
-
error: staleScope ? 'stale_extract_scope' : 'extract_failed',
|
|
393
|
-
outcomeType: staleScope ? 'binding_stale' : 'blocked',
|
|
394
|
-
message: staleScope
|
|
395
|
-
? 'Extraction failed because the requested scope became stale.'
|
|
396
|
-
: 'Extraction failed.',
|
|
397
|
-
reason: staleScope && scopeRef
|
|
398
|
-
? `${failureMessage} (${scopeRef} marked stale: ${staleReason ?? 'stale'})`
|
|
399
|
-
: failureMessage.replace(/^Extract failed:\s*/, ''),
|
|
400
|
-
scopeRef,
|
|
401
|
-
pageRef,
|
|
402
|
-
staleScope,
|
|
403
|
-
staleReason: staleReason ?? undefined,
|
|
404
|
-
});
|
|
405
|
-
}
|
|
542
|
+
});
|
|
406
543
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* browse fill-secret <fillRef> <
|
|
3
|
-
*
|
|
2
|
+
* browse fill-secret <fillRef> <requestId> — Claim an already approved secret request and fill
|
|
3
|
+
* protected fields using deterministic browser execution.
|
|
4
4
|
*/
|
|
5
5
|
import type { BrowseSession } from '../session.js';
|
|
6
|
-
export declare function fillSecret(session: BrowseSession, fillRef: string,
|
|
6
|
+
export declare function fillSecret(session: BrowseSession, fillRef: string, requestId: string): Promise<void>;
|
|
7
7
|
//# sourceMappingURL=fill-secret.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fill-secret.d.ts","sourceRoot":"","sources":["../../src/commands/fill-secret.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"fill-secret.d.ts","sourceRoot":"","sources":["../../src/commands/fill-secret.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAkRnD,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAggBf"}
|