@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.
Files changed (198) hide show
  1. package/README.md +81 -10
  2. package/dist/agentpay-gateway.d.ts +9 -0
  3. package/dist/agentpay-gateway.d.ts.map +1 -1
  4. package/dist/agentpay-gateway.js +31 -1
  5. package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
  6. package/dist/agentpay-stagehand-llm.js +9 -1
  7. package/dist/command-api-tracing.d.ts +19 -0
  8. package/dist/command-api-tracing.d.ts.map +1 -0
  9. package/dist/command-api-tracing.js +137 -0
  10. package/dist/commands/act.d.ts.map +1 -1
  11. package/dist/commands/act.js +822 -670
  12. package/dist/commands/act.test-harness.d.ts +6 -0
  13. package/dist/commands/act.test-harness.d.ts.map +1 -1
  14. package/dist/commands/act.test-harness.js +44 -1
  15. package/dist/commands/action-acceptance.d.ts.map +1 -1
  16. package/dist/commands/action-acceptance.js +115 -0
  17. package/dist/commands/captcha-solve.d.ts.map +1 -1
  18. package/dist/commands/captcha-solve.js +83 -16
  19. package/dist/commands/click-action-executor.d.ts +0 -1
  20. package/dist/commands/click-action-executor.d.ts.map +1 -1
  21. package/dist/commands/click-action-executor.js +31 -77
  22. package/dist/commands/close.d.ts +3 -3
  23. package/dist/commands/close.d.ts.map +1 -1
  24. package/dist/commands/close.js +178 -0
  25. package/dist/commands/descriptor-validation.d.ts.map +1 -1
  26. package/dist/commands/descriptor-validation.js +75 -57
  27. package/dist/commands/end-session.d.ts +25 -0
  28. package/dist/commands/end-session.d.ts.map +1 -0
  29. package/dist/commands/end-session.js +161 -0
  30. package/dist/commands/extract-stagehand-executor.js +1 -1
  31. package/dist/commands/extract.d.ts.map +1 -1
  32. package/dist/commands/extract.js +339 -202
  33. package/dist/commands/fill-secret.d.ts +3 -3
  34. package/dist/commands/fill-secret.d.ts.map +1 -1
  35. package/dist/commands/fill-secret.js +419 -234
  36. package/dist/commands/get-secrets-catalog.d.ts.map +1 -1
  37. package/dist/commands/get-secrets-catalog.js +66 -5
  38. package/dist/commands/init.d.ts.map +1 -1
  39. package/dist/commands/init.js +6 -3
  40. package/dist/commands/interaction-kernel.d.ts +46 -0
  41. package/dist/commands/interaction-kernel.d.ts.map +1 -0
  42. package/dist/commands/interaction-kernel.js +215 -0
  43. package/dist/commands/launch.d.ts +1 -3
  44. package/dist/commands/launch.d.ts.map +1 -1
  45. package/dist/commands/launch.js +115 -27
  46. package/dist/commands/navigate.d.ts.map +1 -1
  47. package/dist/commands/navigate.js +188 -45
  48. package/dist/commands/observe-accessibility.d.ts.map +1 -1
  49. package/dist/commands/observe-accessibility.js +46 -39
  50. package/dist/commands/observe-dom-label-contract.d.ts.map +1 -1
  51. package/dist/commands/observe-dom-label-contract.js +5 -0
  52. package/dist/commands/observe-inventory.d.ts +13 -0
  53. package/dist/commands/observe-inventory.d.ts.map +1 -1
  54. package/dist/commands/observe-inventory.js +320 -65
  55. package/dist/commands/observe-persistence.d.ts.map +1 -1
  56. package/dist/commands/observe-persistence.js +3 -0
  57. package/dist/commands/observe-projection.d.ts +1 -0
  58. package/dist/commands/observe-projection.d.ts.map +1 -1
  59. package/dist/commands/observe-projection.js +7 -2
  60. package/dist/commands/observe-protected.d.ts +1 -0
  61. package/dist/commands/observe-protected.d.ts.map +1 -1
  62. package/dist/commands/observe-protected.js +9 -4
  63. package/dist/commands/observe-semantics.d.ts.map +1 -1
  64. package/dist/commands/observe-semantics.js +5 -2
  65. package/dist/commands/observe-stagehand.d.ts +1 -0
  66. package/dist/commands/observe-stagehand.d.ts.map +1 -1
  67. package/dist/commands/observe-stagehand.js +2 -0
  68. package/dist/commands/observe.d.ts +2 -0
  69. package/dist/commands/observe.d.ts.map +1 -1
  70. package/dist/commands/observe.js +387 -203
  71. package/dist/commands/observe.test-harness.d.ts +8 -0
  72. package/dist/commands/observe.test-harness.d.ts.map +1 -1
  73. package/dist/commands/observe.test-harness.js +48 -1
  74. package/dist/commands/poll-secret.d.ts +6 -0
  75. package/dist/commands/poll-secret.d.ts.map +1 -0
  76. package/dist/commands/poll-secret.js +159 -0
  77. package/dist/commands/request-secret.d.ts +6 -0
  78. package/dist/commands/request-secret.d.ts.map +1 -0
  79. package/dist/commands/request-secret.js +284 -0
  80. package/dist/commands/screenshot.d.ts.map +1 -1
  81. package/dist/commands/screenshot.js +172 -7
  82. package/dist/commands/select-action-executor.d.ts.map +1 -1
  83. package/dist/commands/semantic-observe.d.ts +4 -0
  84. package/dist/commands/semantic-observe.d.ts.map +1 -1
  85. package/dist/commands/semantic-observe.js +388 -17
  86. package/dist/commands/start-session.d.ts +31 -0
  87. package/dist/commands/start-session.d.ts.map +1 -0
  88. package/dist/commands/start-session.js +347 -0
  89. package/dist/commands/status.d.ts +2 -1
  90. package/dist/commands/status.d.ts.map +1 -1
  91. package/dist/commands/status.js +166 -144
  92. package/dist/control-semantics.d.ts +1 -0
  93. package/dist/control-semantics.d.ts.map +1 -1
  94. package/dist/control-semantics.js +51 -9
  95. package/dist/generated/build-config.d.ts +2 -0
  96. package/dist/generated/build-config.d.ts.map +1 -0
  97. package/dist/generated/build-config.js +2 -0
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +163 -63
  100. package/dist/otel-exporter.d.ts +58 -0
  101. package/dist/otel-exporter.d.ts.map +1 -0
  102. package/dist/otel-exporter.js +263 -0
  103. package/dist/otel-projector.d.ts +75 -0
  104. package/dist/otel-projector.d.ts.map +1 -0
  105. package/dist/otel-projector.js +409 -0
  106. package/dist/owned-browser.d.ts +1 -1
  107. package/dist/owned-browser.d.ts.map +1 -1
  108. package/dist/owned-browser.js +13 -1
  109. package/dist/owned-process.d.ts +2 -0
  110. package/dist/owned-process.d.ts.map +1 -1
  111. package/dist/owned-process.js +7 -3
  112. package/dist/playwright-runtime.d.ts +1 -1
  113. package/dist/playwright-runtime.d.ts.map +1 -1
  114. package/dist/playwright-runtime.js +8 -8
  115. package/dist/run-observability.d.ts +25 -0
  116. package/dist/run-observability.d.ts.map +1 -0
  117. package/dist/run-observability.js +115 -0
  118. package/dist/run-store.d.ts +274 -0
  119. package/dist/run-store.d.ts.map +1 -0
  120. package/dist/run-store.js +631 -0
  121. package/dist/runtime-metrics.d.ts +27 -0
  122. package/dist/runtime-metrics.d.ts.map +1 -0
  123. package/dist/runtime-metrics.js +66 -0
  124. package/dist/runtime-page-state.d.ts +11 -0
  125. package/dist/runtime-page-state.d.ts.map +1 -0
  126. package/dist/runtime-page-state.js +62 -0
  127. package/dist/runtime-protected-state.d.ts +16 -0
  128. package/dist/runtime-protected-state.d.ts.map +1 -0
  129. package/dist/runtime-protected-state.js +157 -0
  130. package/dist/runtime-state.d.ts +10 -44
  131. package/dist/runtime-state.d.ts.map +1 -1
  132. package/dist/runtime-state.js +57 -222
  133. package/dist/secrets/backend.d.ts +65 -16
  134. package/dist/secrets/backend.d.ts.map +1 -1
  135. package/dist/secrets/backend.js +135 -95
  136. package/dist/secrets/catalog-sync.d.ts.map +1 -1
  137. package/dist/secrets/catalog-sync.js +4 -1
  138. package/dist/secrets/form-matcher.d.ts +5 -5
  139. package/dist/secrets/form-matcher.d.ts.map +1 -1
  140. package/dist/secrets/form-matcher.js +292 -164
  141. package/dist/secrets/intent-output.d.ts +6 -10
  142. package/dist/secrets/intent-output.d.ts.map +1 -1
  143. package/dist/secrets/intent-output.js +4 -58
  144. package/dist/secrets/mock-agentpay-cabinet.d.ts +38 -27
  145. package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -1
  146. package/dist/secrets/mock-agentpay-cabinet.js +177 -111
  147. package/dist/secrets/protected-artifact-guard.d.ts +2 -2
  148. package/dist/secrets/protected-artifact-guard.d.ts.map +1 -1
  149. package/dist/secrets/protected-artifact-guard.js +2 -2
  150. package/dist/secrets/protected-bindings.d.ts +1 -1
  151. package/dist/secrets/protected-bindings.d.ts.map +1 -1
  152. package/dist/secrets/protected-bindings.js +6 -0
  153. package/dist/secrets/protected-field-semantics.d.ts +9 -0
  154. package/dist/secrets/protected-field-semantics.d.ts.map +1 -0
  155. package/dist/secrets/protected-field-semantics.js +154 -0
  156. package/dist/secrets/protected-field-values.d.ts.map +1 -1
  157. package/dist/secrets/protected-field-values.js +3 -3
  158. package/dist/secrets/protected-fill.d.ts +1 -1
  159. package/dist/secrets/protected-fill.d.ts.map +1 -1
  160. package/dist/secrets/protected-fill.js +45 -149
  161. package/dist/secrets/protected-value-adapters.d.ts +2 -1
  162. package/dist/secrets/protected-value-adapters.d.ts.map +1 -1
  163. package/dist/secrets/protected-value-adapters.js +80 -1
  164. package/dist/secrets/request-output.d.ts +11 -0
  165. package/dist/secrets/request-output.d.ts.map +1 -0
  166. package/dist/secrets/request-output.js +75 -0
  167. package/dist/secrets/types.d.ts +15 -9
  168. package/dist/secrets/types.d.ts.map +1 -1
  169. package/dist/secrets/types.js +3 -0
  170. package/dist/session-event-exporter.d.ts +36 -0
  171. package/dist/session-event-exporter.d.ts.map +1 -0
  172. package/dist/session-event-exporter.js +428 -0
  173. package/dist/session.d.ts +16 -7
  174. package/dist/session.d.ts.map +1 -1
  175. package/dist/session.js +150 -23
  176. package/dist/sessions-backend.d.ts +354 -0
  177. package/dist/sessions-backend.d.ts.map +1 -0
  178. package/dist/sessions-backend.js +126 -0
  179. package/dist/solver/browser-launcher.d.ts +1 -1
  180. package/dist/solver/browser-launcher.d.ts.map +1 -1
  181. package/dist/solver/browser-launcher.js +39 -13
  182. package/dist/solver/captcha-solver.d.ts.map +1 -1
  183. package/dist/solver/captcha-solver.js +8 -1
  184. package/dist/solver/config.d.ts +0 -1
  185. package/dist/solver/config.d.ts.map +1 -1
  186. package/dist/solver/config.js +0 -22
  187. package/dist/solver/types.d.ts +1 -0
  188. package/dist/solver/types.d.ts.map +1 -1
  189. package/dist/workflow-session-completion.d.ts +33 -0
  190. package/dist/workflow-session-completion.d.ts.map +1 -0
  191. package/dist/workflow-session-completion.js +156 -0
  192. package/package.json +11 -1
  193. package/dist/commands/create-intent.d.ts +0 -6
  194. package/dist/commands/create-intent.d.ts.map +0 -1
  195. package/dist/commands/create-intent.js +0 -75
  196. package/dist/commands/poll-intent.d.ts +0 -6
  197. package/dist/commands/poll-intent.d.ts.map +0 -1
  198. package/dist/commands/poll-intent.js +0 -57
@@ -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 { getPageScopeEpoch, getSurface, getTarget, markSurfaceLifecycle, markTargetLifecycle, setCurrentPage, } from '../runtime-state.js';
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
- export async function extract(session, schemaJson, scopeRef) {
181
- let schemaDescriptor;
182
- try {
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
- const schema = buildSchema(schemaDescriptor);
194
- const instruction = buildInstruction(schemaDescriptor, scopeRef);
195
- const targetScope = scopeRef ? getTarget(session, scopeRef) : null;
196
- const surfaceScope = !targetScope && scopeRef ? getSurface(session, scopeRef) : null;
197
- const scopeTarget = targetScope ?? surfaceScope;
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
- if (scopeTarget && scopeTarget.lifecycle !== 'live') {
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
- if (surfaceScope) {
218
- const snapshotScopeReason = snapshotScopeUnavailableReason(session, surfaceScope);
219
- if (snapshotScopeReason) {
220
- return outputContractFailure({
221
- error: 'expired_extract_scope',
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 snapshot scope is no longer current.',
224
- reason: snapshotScopeReason,
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
- pageRef,
227
- staleScope: true,
228
- staleReason: 'snapshot-scope-expired',
337
+ runId: session.activeRunId,
338
+ stepId: extractStep?.stepId,
229
339
  });
230
340
  }
231
- }
232
- if (targetScope && !canUseTargetAsExtractScope(targetScope)) {
233
- return outputContractFailure({
234
- error: 'invalid_extract_scope',
235
- outcomeType: 'unsupported',
236
- message: 'Extraction cannot use the requested target as a scope.',
237
- reason: `Target ${scopeRef} is a leaf control, not an extractable scope container.`,
238
- scopeRef,
239
- });
240
- }
241
- let browser = null;
242
- let failureMessage = null;
243
- let cleanupScopedExtract = null;
244
- let staleScope = false;
245
- let staleReason = null;
246
- try {
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
- else {
265
- const resolvedPage = await resolveCurrentPageContext(browser, session);
266
- pageRef = resolvedPage.pageRef;
267
- sourcePage = resolvedPage.page;
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 page = sourcePage;
270
- let scopedResolution = null;
271
- const { url, title } = await syncSessionPage(session, pageRef, sourcePage);
272
- if (scopeTarget?.pageSignature && normalizePageSignature(url) !== scopeTarget.pageSignature) {
273
- staleScope = true;
274
- staleReason = 'page-signature-mismatch';
275
- throw new Error('stale_scope_target_page_signature_changed');
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
- let effectiveSelector;
278
- if (scopeTarget) {
279
- try {
280
- scopedResolution = await resolveScopedExtractContext({
281
- page: sourcePage,
282
- scopeTarget,
283
- validateDomSignature: Boolean(targetScope),
284
- });
285
- cleanupScopedExtract = scopedResolution.cleanup;
286
- page = scopedResolution.page;
287
- effectiveSelector = scopedResolution.selector;
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
- catch (error) {
290
- if (error instanceof Error &&
291
- error.message === 'stale_scope_target_dom_signature_changed') {
292
- staleScope = true;
293
- staleReason = 'dom-signature-mismatch';
294
- }
295
- else if (surfaceScope &&
296
- surfaceExtractScopeLifetime(surfaceScope) === 'snapshot' &&
297
- error instanceof Error &&
298
- error.message === 'scope_target_unresolvable') {
299
- outputContractFailure({
300
- error: 'expired_extract_scope',
301
- outcomeType: 'binding_stale',
302
- message: 'Extraction failed because the requested snapshot scope expired before it could be rebound.',
303
- reason: `Snapshot scope ${scopeRef} is no longer present in the current visible page state.`,
304
- scopeRef,
305
- pageRef,
306
- staleScope: true,
307
- staleReason: 'snapshot-scope-expired',
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
- setCurrentPage(session, pageRef);
314
- const execution = await executeStagehandExtract({
315
- session,
316
- instruction,
317
- schema,
318
- page,
319
- selector: effectiveSelector,
320
- degradationReason: scopedResolution?.degraded
321
- ? scopedResolution.degradationReason
322
- : undefined,
323
- });
324
- let data = execution.data;
325
- if (scopeTarget &&
326
- effectiveSelector &&
327
- schemaRequestsScopedDialogText(schemaDescriptor) &&
328
- data &&
329
- typeof data === 'object' &&
330
- !Array.isArray(data)) {
331
- const dialogText = await readScopedDialogText(page, effectiveSelector);
332
- if (typeof dialogText === 'string' && dialogText.trim().length > 0) {
333
- data = {
334
- ...data,
335
- dialog_text: dialogText,
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
- saveSession(session);
340
- outputJSON({
341
- success: true,
342
- ...execution,
343
- data,
344
- pageRef,
345
- scopeRef,
346
- metrics: session.runtime?.metrics,
347
- url,
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
- else if (surfaceScope) {
357
- markSurfaceLifecycle(session, scopeRef, 'stale', staleReason ?? 'unknown');
493
+ if (err instanceof Error && err.message.startsWith('outputContractFailure:')) {
494
+ throw err;
358
495
  }
359
- saveSession(session);
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
- if (err instanceof Error && err.message.startsWith('outputContractFailure:')) {
362
- throw err;
516
+ finally {
517
+ if (cleanupScopedExtract) {
518
+ await cleanupScopedExtract().catch(() => undefined);
519
+ }
520
+ if (browser) {
521
+ await disconnectPlaywright(browser);
522
+ }
363
523
  }
364
- if (!staleScope && err instanceof AgentpayStructuredOutputTruncatedError) {
365
- outputContractFailure({
366
- error: 'extract_output_truncated',
367
- outcomeType: 'blocked',
368
- message: 'Extraction failed because the provider truncated structured output.',
369
- reason: buildTruncationReason(err),
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: false,
373
- provider: err.provider,
374
- model: err.model,
375
- finishReason: err.finishReason,
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
- failureMessage = `Extract failed: ${err instanceof Error ? err.message : String(err)}`;
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> <intentId> — Fill protected fields from a cached one-time secret payload
3
- * using the persisted plan and deterministic browser execution.
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, intentId: string): Promise<void>;
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;AAUH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AA8InD,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAmUf"}
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"}