@nuanu-ai/agentbrowse 0.2.46 → 0.2.48

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 (190) hide show
  1. package/README.md +69 -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 +30 -0
  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/interaction-kernel.d.ts +46 -0
  39. package/dist/commands/interaction-kernel.d.ts.map +1 -0
  40. package/dist/commands/interaction-kernel.js +215 -0
  41. package/dist/commands/launch.d.ts +0 -2
  42. package/dist/commands/launch.d.ts.map +1 -1
  43. package/dist/commands/launch.js +109 -17
  44. package/dist/commands/navigate.d.ts.map +1 -1
  45. package/dist/commands/navigate.js +188 -45
  46. package/dist/commands/observe-accessibility.d.ts.map +1 -1
  47. package/dist/commands/observe-accessibility.js +50 -39
  48. package/dist/commands/observe-dom-label-contract.d.ts.map +1 -1
  49. package/dist/commands/observe-dom-label-contract.js +5 -0
  50. package/dist/commands/observe-inventory.d.ts +13 -0
  51. package/dist/commands/observe-inventory.d.ts.map +1 -1
  52. package/dist/commands/observe-inventory.js +320 -65
  53. package/dist/commands/observe-persistence.d.ts.map +1 -1
  54. package/dist/commands/observe-persistence.js +3 -0
  55. package/dist/commands/observe-projection.d.ts +1 -0
  56. package/dist/commands/observe-projection.d.ts.map +1 -1
  57. package/dist/commands/observe-projection.js +7 -2
  58. package/dist/commands/observe-protected.d.ts +1 -0
  59. package/dist/commands/observe-protected.d.ts.map +1 -1
  60. package/dist/commands/observe-protected.js +9 -4
  61. package/dist/commands/observe-semantics.d.ts.map +1 -1
  62. package/dist/commands/observe-semantics.js +5 -2
  63. package/dist/commands/observe-stagehand.d.ts +1 -0
  64. package/dist/commands/observe-stagehand.d.ts.map +1 -1
  65. package/dist/commands/observe-stagehand.js +2 -0
  66. package/dist/commands/observe.d.ts +2 -0
  67. package/dist/commands/observe.d.ts.map +1 -1
  68. package/dist/commands/observe.js +387 -203
  69. package/dist/commands/observe.test-harness.d.ts +8 -0
  70. package/dist/commands/observe.test-harness.d.ts.map +1 -1
  71. package/dist/commands/observe.test-harness.js +48 -1
  72. package/dist/commands/poll-secret.d.ts +6 -0
  73. package/dist/commands/poll-secret.d.ts.map +1 -0
  74. package/dist/commands/poll-secret.js +159 -0
  75. package/dist/commands/request-secret.d.ts +6 -0
  76. package/dist/commands/request-secret.d.ts.map +1 -0
  77. package/dist/commands/request-secret.js +284 -0
  78. package/dist/commands/screenshot.d.ts.map +1 -1
  79. package/dist/commands/screenshot.js +172 -7
  80. package/dist/commands/select-action-executor.d.ts.map +1 -1
  81. package/dist/commands/semantic-observe.d.ts +4 -0
  82. package/dist/commands/semantic-observe.d.ts.map +1 -1
  83. package/dist/commands/semantic-observe.js +388 -17
  84. package/dist/commands/start-session.d.ts +31 -0
  85. package/dist/commands/start-session.d.ts.map +1 -0
  86. package/dist/commands/start-session.js +347 -0
  87. package/dist/commands/status.d.ts +2 -1
  88. package/dist/commands/status.d.ts.map +1 -1
  89. package/dist/commands/status.js +166 -144
  90. package/dist/control-semantics.d.ts +1 -0
  91. package/dist/control-semantics.d.ts.map +1 -1
  92. package/dist/control-semantics.js +51 -9
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +144 -45
  95. package/dist/otel-exporter.d.ts +58 -0
  96. package/dist/otel-exporter.d.ts.map +1 -0
  97. package/dist/otel-exporter.js +263 -0
  98. package/dist/otel-projector.d.ts +75 -0
  99. package/dist/otel-projector.d.ts.map +1 -0
  100. package/dist/otel-projector.js +409 -0
  101. package/dist/owned-browser.d.ts +1 -1
  102. package/dist/owned-browser.d.ts.map +1 -1
  103. package/dist/owned-browser.js +13 -1
  104. package/dist/owned-process.d.ts +2 -0
  105. package/dist/owned-process.d.ts.map +1 -1
  106. package/dist/owned-process.js +7 -3
  107. package/dist/playwright-runtime.d.ts +1 -1
  108. package/dist/playwright-runtime.d.ts.map +1 -1
  109. package/dist/playwright-runtime.js +8 -8
  110. package/dist/run-observability.d.ts +25 -0
  111. package/dist/run-observability.d.ts.map +1 -0
  112. package/dist/run-observability.js +115 -0
  113. package/dist/run-store.d.ts +274 -0
  114. package/dist/run-store.d.ts.map +1 -0
  115. package/dist/run-store.js +631 -0
  116. package/dist/runtime-metrics.d.ts +27 -0
  117. package/dist/runtime-metrics.d.ts.map +1 -0
  118. package/dist/runtime-metrics.js +66 -0
  119. package/dist/runtime-page-state.d.ts +11 -0
  120. package/dist/runtime-page-state.d.ts.map +1 -0
  121. package/dist/runtime-page-state.js +62 -0
  122. package/dist/runtime-protected-state.d.ts +16 -0
  123. package/dist/runtime-protected-state.d.ts.map +1 -0
  124. package/dist/runtime-protected-state.js +157 -0
  125. package/dist/runtime-state.d.ts +10 -44
  126. package/dist/runtime-state.d.ts.map +1 -1
  127. package/dist/runtime-state.js +57 -222
  128. package/dist/secrets/backend.d.ts +65 -16
  129. package/dist/secrets/backend.d.ts.map +1 -1
  130. package/dist/secrets/backend.js +135 -95
  131. package/dist/secrets/catalog-sync.d.ts.map +1 -1
  132. package/dist/secrets/catalog-sync.js +4 -1
  133. package/dist/secrets/form-matcher.d.ts +5 -5
  134. package/dist/secrets/form-matcher.d.ts.map +1 -1
  135. package/dist/secrets/form-matcher.js +292 -164
  136. package/dist/secrets/intent-output.d.ts +6 -10
  137. package/dist/secrets/intent-output.d.ts.map +1 -1
  138. package/dist/secrets/intent-output.js +4 -58
  139. package/dist/secrets/mock-agentpay-cabinet.d.ts +38 -27
  140. package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -1
  141. package/dist/secrets/mock-agentpay-cabinet.js +177 -111
  142. package/dist/secrets/protected-artifact-guard.d.ts +2 -2
  143. package/dist/secrets/protected-artifact-guard.d.ts.map +1 -1
  144. package/dist/secrets/protected-artifact-guard.js +2 -2
  145. package/dist/secrets/protected-bindings.d.ts +1 -1
  146. package/dist/secrets/protected-bindings.d.ts.map +1 -1
  147. package/dist/secrets/protected-bindings.js +6 -0
  148. package/dist/secrets/protected-field-semantics.d.ts +9 -0
  149. package/dist/secrets/protected-field-semantics.d.ts.map +1 -0
  150. package/dist/secrets/protected-field-semantics.js +154 -0
  151. package/dist/secrets/protected-field-values.d.ts.map +1 -1
  152. package/dist/secrets/protected-field-values.js +3 -3
  153. package/dist/secrets/protected-fill.d.ts +1 -1
  154. package/dist/secrets/protected-fill.d.ts.map +1 -1
  155. package/dist/secrets/protected-fill.js +45 -149
  156. package/dist/secrets/protected-value-adapters.d.ts +2 -1
  157. package/dist/secrets/protected-value-adapters.d.ts.map +1 -1
  158. package/dist/secrets/protected-value-adapters.js +80 -1
  159. package/dist/secrets/request-output.d.ts +11 -0
  160. package/dist/secrets/request-output.d.ts.map +1 -0
  161. package/dist/secrets/request-output.js +75 -0
  162. package/dist/secrets/types.d.ts +15 -9
  163. package/dist/secrets/types.d.ts.map +1 -1
  164. package/dist/secrets/types.js +3 -0
  165. package/dist/session-event-exporter.d.ts +36 -0
  166. package/dist/session-event-exporter.d.ts.map +1 -0
  167. package/dist/session-event-exporter.js +428 -0
  168. package/dist/session.d.ts +16 -7
  169. package/dist/session.d.ts.map +1 -1
  170. package/dist/session.js +150 -23
  171. package/dist/sessions-backend.d.ts +354 -0
  172. package/dist/sessions-backend.d.ts.map +1 -0
  173. package/dist/sessions-backend.js +126 -0
  174. package/dist/solver/browser-launcher.d.ts +1 -1
  175. package/dist/solver/browser-launcher.d.ts.map +1 -1
  176. package/dist/solver/browser-launcher.js +39 -13
  177. package/dist/solver/captcha-solver.d.ts.map +1 -1
  178. package/dist/solver/captcha-solver.js +8 -1
  179. package/dist/solver/types.d.ts +1 -0
  180. package/dist/solver/types.d.ts.map +1 -1
  181. package/dist/workflow-session-completion.d.ts +33 -0
  182. package/dist/workflow-session-completion.d.ts.map +1 -0
  183. package/dist/workflow-session-completion.js +156 -0
  184. package/package.json +9 -1
  185. package/dist/commands/create-intent.d.ts +0 -6
  186. package/dist/commands/create-intent.d.ts.map +0 -1
  187. package/dist/commands/create-intent.js +0 -75
  188. package/dist/commands/poll-intent.d.ts +0 -6
  189. package/dist/commands/poll-intent.d.ts.map +0 -1
  190. package/dist/commands/poll-intent.js +0 -57
@@ -3,12 +3,18 @@ import type { BrowseSession } from '../session.js';
3
3
  type ViMock = ReturnType<typeof vi.fn>;
4
4
  export declare const connectOverCDPMock: ViMock;
5
5
  export declare const connectStagehandMock: ViMock;
6
+ export declare const appendCommandLifecycleEventBestEffortMock: ViMock;
7
+ export declare const appendStepChildSpanMock: ViMock;
8
+ export declare const captureStepSnapshotBestEffortMock: ViMock;
9
+ export declare const exportRunStepToOtlpHttpJsonBestEffortMock: ViMock;
10
+ export declare const finishRunStepMock: ViMock;
6
11
  export declare const outputContractFailureMock: ViMock;
7
12
  export declare const outputErrorMock: ViMock;
8
13
  export declare const outputFailureMock: ViMock;
9
14
  export declare const outputJSONMock: ViMock;
10
15
  export declare const rerankDomTargetsForGoalMock: ViMock;
11
16
  export declare const saveSessionMock: ViMock;
17
+ export declare const startRunStepMock: ViMock;
12
18
  export declare const outputJSONRawPayloads: unknown[];
13
19
  export declare const observe: typeof import("./observe.js").observe, __testDomTargetCollection: {
14
20
  collectDomTargetsFromDocument: (context: {
@@ -30,6 +36,7 @@ export declare const observe: typeof import("./observe.js").observe, __testDomTa
30
36
  inputName?: string;
31
37
  inputType?: string;
32
38
  autocomplete?: string;
39
+ ariaAutocomplete?: string;
33
40
  value?: string;
34
41
  text?: string;
35
42
  currentValue?: string;
@@ -42,6 +49,7 @@ export declare const observe: typeof import("./observe.js").observe, __testDomTa
42
49
  inputName?: string;
43
50
  inputType?: string;
44
51
  autocomplete?: string;
52
+ ariaAutocomplete?: string;
45
53
  value?: string;
46
54
  text?: string;
47
55
  currentValue?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"observe.test-harness.d.ts","sourceRoot":"","sources":["../../src/commands/observe.test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,EAAE,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AA0EvC,eAAO,MAAM,kBAAkB,EAAE,MAAiC,CAAC;AACnE,eAAO,MAAM,oBAAoB,EAAE,MAAmC,CAAC;AACvE,eAAO,MAAM,yBAAyB,EAAE,MAAwC,CAAC;AACjF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,EAAE,MAAgC,CAAC;AACjE,eAAO,MAAM,cAAc,EAAE,MAA6B,CAAC;AAC3D,eAAO,MAAM,2BAA2B,EAAE,MAA0C,CAAC;AACrF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,qBAAqB,EAAE,OAAO,EAAgC,CAAC;AA+B5E,eAAO,MAAQ,OAAO,yCAAE,yBAAyB;;;;iBAqE6vX,CAAC;gBAAwB,CAAC;;;;;GArErxX,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAE3E,CAAC;AACF,eAAO,MAAQ,0BAA0B;;;;;CAA+C,CAAC;AAMzF,wBAAgB,WAAW,IAAI,aAAa,CAW3C;AAYD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,IAAI,EAAE,CAAC,EACP,YAAY,SAAkC,GAC7C,CAAC,GAAG;IAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;CAAE,CAM3C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAyB9C"}
1
+ {"version":3,"file":"observe.test-harness.d.ts","sourceRoot":"","sources":["../../src/commands/observe.test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,EAAE,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AAuFvC,eAAO,MAAM,kBAAkB,EAAE,MAAiC,CAAC;AACnE,eAAO,MAAM,oBAAoB,EAAE,MAAmC,CAAC;AACvE,eAAO,MAAM,yCAAyC,EAAE,MACP,CAAC;AAClD,eAAO,MAAM,uBAAuB,EAAE,MAAsC,CAAC;AAC7E,eAAO,MAAM,iCAAiC,EAAE,MAAgD,CAAC;AACjG,eAAO,MAAM,yCAAyC,EAAE,MACP,CAAC;AAClD,eAAO,MAAM,iBAAiB,EAAE,MAAgC,CAAC;AACjE,eAAO,MAAM,yBAAyB,EAAE,MAAwC,CAAC;AACjF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,EAAE,MAAgC,CAAC;AACjE,eAAO,MAAM,cAAc,EAAE,MAA6B,CAAC;AAC3D,eAAO,MAAM,2BAA2B,EAAE,MAA0C,CAAC;AACrF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,gBAAgB,EAAE,MAA+B,CAAC;AAC/D,eAAO,MAAM,qBAAqB,EAAE,OAAO,EAAgC,CAAC;AA8C5E,eAAO,MAAQ,OAAO,yCAAE,yBAAyB;;;;iBAqFoga,CAAC;gBAAwB,CAAC;;;;;GArF5ha,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAE3E,CAAC;AACF,eAAO,MAAQ,0BAA0B;;;;;CAA+C,CAAC;AAMzF,wBAAgB,WAAW,IAAI,aAAa,CAY3C;AAYD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,IAAI,EAAE,CAAC,EACP,YAAY,SAAkC,GAC7C,CAAC,GAAG;IAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;CAAE,CAM3C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAwC9C"}
@@ -1,5 +1,5 @@
1
1
  import { afterEach, beforeEach, vi } from 'vitest';
2
- import { registerPage } from '../runtime-state.js';
2
+ import { registerPage } from '../runtime-page-state.js';
3
3
  function flattenObservedTargetsForTests(payload) {
4
4
  return payload.scopes?.flatMap((scope) => scope.targets ?? []) ?? [];
5
5
  }
@@ -22,8 +22,16 @@ function normalizeObservedOutputForTests(payload) {
22
22
  const mocks = vi.hoisted(() => {
23
23
  const outputJSONRawPayloads = [];
24
24
  return {
25
+ appendCommandLifecycleEventBestEffortMock: vi.fn(),
26
+ appendStepChildSpanMock: vi.fn(),
27
+ captureStepSnapshotBestEffortMock: vi.fn(),
25
28
  connectOverCDPMock: vi.fn(),
26
29
  connectStagehandMock: vi.fn(),
30
+ exportRunStepToOtlpHttpJsonBestEffortMock: vi.fn(async () => ({
31
+ attempted: false,
32
+ reason: 'config_missing',
33
+ })),
34
+ finishRunStepMock: vi.fn(),
27
35
  outputContractFailureMock: vi.fn((payload) => {
28
36
  throw new Error(`outputContractFailure:${JSON.stringify(payload)}`);
29
37
  }),
@@ -49,16 +57,27 @@ const mocks = vi.hoisted(() => {
49
57
  }),
50
58
  rerankDomTargetsForGoalMock: vi.fn(async (..._args) => []),
51
59
  saveSessionMock: vi.fn(),
60
+ startRunStepMock: vi.fn((input) => ({
61
+ stepId: 'step_observe_1',
62
+ runId: input?.runId ?? 'run_123',
63
+ command: (input?.command ?? 'observe'),
64
+ })),
52
65
  };
53
66
  });
54
67
  export const connectOverCDPMock = mocks.connectOverCDPMock;
55
68
  export const connectStagehandMock = mocks.connectStagehandMock;
69
+ export const appendCommandLifecycleEventBestEffortMock = mocks.appendCommandLifecycleEventBestEffortMock;
70
+ export const appendStepChildSpanMock = mocks.appendStepChildSpanMock;
71
+ export const captureStepSnapshotBestEffortMock = mocks.captureStepSnapshotBestEffortMock;
72
+ export const exportRunStepToOtlpHttpJsonBestEffortMock = mocks.exportRunStepToOtlpHttpJsonBestEffortMock;
73
+ export const finishRunStepMock = mocks.finishRunStepMock;
56
74
  export const outputContractFailureMock = mocks.outputContractFailureMock;
57
75
  export const outputErrorMock = mocks.outputErrorMock;
58
76
  export const outputFailureMock = mocks.outputFailureMock;
59
77
  export const outputJSONMock = mocks.outputJSONMock;
60
78
  export const rerankDomTargetsForGoalMock = mocks.rerankDomTargetsForGoalMock;
61
79
  export const saveSessionMock = mocks.saveSessionMock;
80
+ export const startRunStepMock = mocks.startRunStepMock;
62
81
  export const outputJSONRawPayloads = mocks.outputJSONRawPayloads;
63
82
  vi.mock('playwright-core', () => ({
64
83
  chromium: {
@@ -77,6 +96,18 @@ vi.mock('../output.js', () => ({
77
96
  vi.mock('./semantic-observe.js', () => ({
78
97
  rerankDomTargetsForGoal: rerankDomTargetsForGoalMock,
79
98
  }));
99
+ vi.mock('../run-store.js', () => ({
100
+ appendStepChildSpan: appendStepChildSpanMock,
101
+ finishRunStep: finishRunStepMock,
102
+ startRunStep: startRunStepMock,
103
+ }));
104
+ vi.mock('../run-observability.js', () => ({
105
+ appendCommandLifecycleEventBestEffort: appendCommandLifecycleEventBestEffortMock,
106
+ captureStepSnapshotBestEffort: captureStepSnapshotBestEffortMock,
107
+ }));
108
+ vi.mock('../otel-exporter.js', () => ({
109
+ exportRunStepToOtlpHttpJsonBestEffort: exportRunStepToOtlpHttpJsonBestEffortMock,
110
+ }));
80
111
  vi.mock('../session.js', async () => {
81
112
  const actual = await vi.importActual('../session.js');
82
113
  return {
@@ -93,6 +124,7 @@ export function makeSession() {
93
124
  const session = {
94
125
  cdpUrl: 'ws://localhost:9222/devtools/browser/test',
95
126
  pid: 1,
127
+ activeRunId: 'run_123',
96
128
  launchedAt: new Date(0).toISOString(),
97
129
  };
98
130
  registerPage(session, {
@@ -119,8 +151,17 @@ export function withStagehandLocator(page, domSignature = 'button|button|Observe
119
151
  }
120
152
  export function installObserveTestHooks() {
121
153
  beforeEach(() => {
154
+ appendCommandLifecycleEventBestEffortMock.mockReset();
155
+ appendStepChildSpanMock.mockReset();
156
+ captureStepSnapshotBestEffortMock.mockReset();
122
157
  connectOverCDPMock.mockReset();
123
158
  connectStagehandMock.mockReset();
159
+ exportRunStepToOtlpHttpJsonBestEffortMock.mockReset();
160
+ exportRunStepToOtlpHttpJsonBestEffortMock.mockResolvedValue({
161
+ attempted: false,
162
+ reason: 'config_missing',
163
+ });
164
+ finishRunStepMock.mockReset();
124
165
  outputContractFailureMock.mockReset();
125
166
  outputContractFailureMock.mockImplementation((payload) => {
126
167
  throw new Error(`outputContractFailure:${JSON.stringify(payload)}`);
@@ -135,6 +176,12 @@ export function installObserveTestHooks() {
135
176
  rerankDomTargetsForGoalMock.mockReset();
136
177
  rerankDomTargetsForGoalMock.mockResolvedValue([]);
137
178
  saveSessionMock.mockReset();
179
+ startRunStepMock.mockReset();
180
+ startRunStepMock.mockImplementation((input) => ({
181
+ stepId: 'step_observe_1',
182
+ runId: input?.runId ?? 'run_123',
183
+ command: (input?.command ?? 'observe'),
184
+ }));
138
185
  });
139
186
  afterEach(() => {
140
187
  globalThis.fetch = originalFetch;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * browse poll-secret <requestId> — Poll one secret request state without blocking or claiming values.
3
+ */
4
+ import type { BrowseSession } from '../session.js';
5
+ export declare function pollSecret(session: BrowseSession, requestId: string): Promise<void>;
6
+ //# sourceMappingURL=poll-secret.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poll-secret.d.ts","sourceRoot":"","sources":["../../src/commands/poll-secret.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AA6GnD,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6GzF"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * browse poll-secret <requestId> — Poll one secret request state without blocking or claiming values.
3
+ */
4
+ import { outputFailure, outputJSON } from '../output.js';
5
+ import { withApiTraceContext } from '../command-api-tracing.js';
6
+ import { finishRunStep, startRunStep } from '../run-store.js';
7
+ import { exportRunStepToOtlpHttpJsonBestEffort } from '../otel-exporter.js';
8
+ import { appendCommandLifecycleEventBestEffort, captureStepSnapshotBestEffort, } from '../run-observability.js';
9
+ import { saveSecretRequestSnapshot } from '../runtime-protected-state.js';
10
+ import { saveSession } from '../session.js';
11
+ import { describeSecretRequestStatus, serializeSecretRequest, } from '../secrets/request-output.js';
12
+ import { getSecretBackend } from '../secrets/backend.js';
13
+ function finalizePollSecretStepBestEffort(runId, stepId, options) {
14
+ if (!runId || !stepId) {
15
+ return;
16
+ }
17
+ try {
18
+ finishRunStep({
19
+ runId,
20
+ stepId,
21
+ ...options,
22
+ });
23
+ }
24
+ catch {
25
+ }
26
+ }
27
+ async function emitPollSecretFailure(session, runId, stepId, payload, options = {}) {
28
+ const step = runId && stepId ? { runId, stepId, command: 'poll-secret' } : null;
29
+ captureStepSnapshotBestEffort({
30
+ session,
31
+ step,
32
+ phase: 'point-in-time',
33
+ pageRef: options.pageRef ?? session.runtime?.currentPageRef,
34
+ });
35
+ appendCommandLifecycleEventBestEffort({
36
+ step,
37
+ phase: 'failed',
38
+ attributes: {
39
+ outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : payload.error,
40
+ pageRef: options.pageRef,
41
+ requestId: options.requestId,
42
+ reason: typeof payload.reason === 'string' ? payload.reason : payload.error,
43
+ },
44
+ });
45
+ finalizePollSecretStepBestEffort(runId, stepId, {
46
+ success: false,
47
+ outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : payload.error,
48
+ message: typeof payload.message === 'string' ? payload.message : payload.error,
49
+ reason: typeof payload.reason === 'string' ? payload.reason : payload.error,
50
+ });
51
+ await exportRunStepToOtlpHttpJsonBestEffort(runId, stepId);
52
+ return outputFailure(payload);
53
+ }
54
+ async function emitPollSecretSuccess(session, runId, stepId, payload, defaultOutcomeType, options = {}) {
55
+ const step = runId && stepId ? { runId, stepId, command: 'poll-secret' } : null;
56
+ captureStepSnapshotBestEffort({
57
+ session,
58
+ step,
59
+ phase: 'after',
60
+ pageRef: options.pageRef ?? session.runtime?.currentPageRef,
61
+ });
62
+ appendCommandLifecycleEventBestEffort({
63
+ step,
64
+ phase: 'completed',
65
+ attributes: {
66
+ outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : defaultOutcomeType,
67
+ pageRef: options.pageRef,
68
+ requestId: options.requestId,
69
+ },
70
+ });
71
+ finalizePollSecretStepBestEffort(runId, stepId, {
72
+ success: true,
73
+ outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : defaultOutcomeType,
74
+ message: typeof payload.message === 'string' ? payload.message : 'Protected secret request polled.',
75
+ reason: typeof payload.reason === 'string' ? payload.reason : undefined,
76
+ });
77
+ await exportRunStepToOtlpHttpJsonBestEffort(runId, stepId);
78
+ return outputJSON(payload);
79
+ }
80
+ export async function pollSecret(session, requestId) {
81
+ const pollSecretStep = session.activeRunId
82
+ ? startRunStep({
83
+ runId: session.activeRunId,
84
+ command: 'poll-secret',
85
+ refs: {
86
+ requestId,
87
+ },
88
+ protectedStep: true,
89
+ })
90
+ : null;
91
+ const pollSecretStepHandle = session.activeRunId && pollSecretStep?.stepId
92
+ ? {
93
+ runId: session.activeRunId,
94
+ stepId: pollSecretStep.stepId,
95
+ command: 'poll-secret',
96
+ }
97
+ : null;
98
+ captureStepSnapshotBestEffort({
99
+ session,
100
+ step: pollSecretStepHandle,
101
+ phase: 'before',
102
+ pageRef: session.runtime?.currentPageRef,
103
+ });
104
+ appendCommandLifecycleEventBestEffort({
105
+ step: pollSecretStepHandle,
106
+ phase: 'started',
107
+ attributes: {
108
+ requestId,
109
+ pageRef: session.runtime?.currentPageRef,
110
+ },
111
+ });
112
+ return withApiTraceContext({
113
+ runId: session.activeRunId,
114
+ stepId: pollSecretStep?.stepId,
115
+ command: 'poll-secret',
116
+ }, async () => {
117
+ if (!session.intentSessionId) {
118
+ return emitPollSecretFailure(session, session.activeRunId, pollSecretStep?.stepId, {
119
+ error: 'workflow_session_unavailable',
120
+ outcomeType: 'blocked',
121
+ message: 'Protected secret request polling failed because no active workflow session is bound to this browser.',
122
+ reason: 'Run start-session first so AgentBrowse has a workflow session for secret requests.',
123
+ requestId,
124
+ }, {
125
+ requestId,
126
+ });
127
+ }
128
+ const result = await getSecretBackend().getSecretRequest(session.intentSessionId, requestId);
129
+ if (!result) {
130
+ return emitPollSecretFailure(session, session.activeRunId, pollSecretStep?.stepId, {
131
+ error: 'secret_request_not_found',
132
+ message: 'Protected secret request lookup failed because the requested request does not exist.',
133
+ outcomeType: 'blocked',
134
+ reason: 'The provided requestId was not found in AgentPay.',
135
+ requestId,
136
+ }, {
137
+ requestId,
138
+ });
139
+ }
140
+ const snapshot = saveSecretRequestSnapshot(session, result.snapshot);
141
+ session.intentSessionId = result.session.sessionId;
142
+ session.currentRequestId = result.session.currentRequestId ?? undefined;
143
+ session.lastKnownStatus = result.session.status;
144
+ session.lastEventSeq = result.session.lastEventSeq;
145
+ saveSession(session);
146
+ const statusContract = describeSecretRequestStatus(snapshot.status, snapshot.requestType);
147
+ return emitPollSecretSuccess(session, session.activeRunId, pollSecretStep?.stepId, {
148
+ success: true,
149
+ ...serializeSecretRequest(snapshot),
150
+ ...(statusContract.outcomeType ? { outcomeType: statusContract.outcomeType } : {}),
151
+ message: statusContract.message,
152
+ reason: statusContract.reason,
153
+ ...(statusContract.nextAction ? { nextAction: statusContract.nextAction } : {}),
154
+ }, snapshot.status === 'fulfilled' ? 'secret_request_ready_to_fill' : 'secret_request_polled', {
155
+ pageRef: snapshot.pageRef,
156
+ requestId,
157
+ });
158
+ });
159
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * browse request-secret <fillRef> <storedSecretRef> — Create or reuse a session-bound secret request.
3
+ */
4
+ import type { BrowseSession } from '../session.js';
5
+ export declare function requestSecret(session: BrowseSession, fillRef: string, storedSecretRef: string, merchantName: string): Promise<void>;
6
+ //# sourceMappingURL=request-secret.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-secret.d.ts","sourceRoot":"","sources":["../../src/commands/request-secret.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AA+KnD,wBAAsB,aAAa,CACjC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAwNf"}
@@ -0,0 +1,284 @@
1
+ /**
2
+ * browse request-secret <fillRef> <storedSecretRef> — Create or reuse a session-bound secret request.
3
+ */
4
+ import { outputFailure, outputJSON } from '../output.js';
5
+ import { withApiTraceContext } from '../command-api-tracing.js';
6
+ import { finishRunStep, startRunStep } from '../run-store.js';
7
+ import { exportRunStepToOtlpHttpJsonBestEffort } from '../otel-exporter.js';
8
+ import { appendCommandLifecycleEventBestEffort, captureStepSnapshotBestEffort, } from '../run-observability.js';
9
+ import { getFillableForm, saveSecretRequestSnapshot } from '../runtime-protected-state.js';
10
+ import { saveSession } from '../session.js';
11
+ import { tryResolveCatalogHost } from '../secrets/catalog-sync.js';
12
+ import { describeSecretRequestStatus, serializeSecretRequest, } from '../secrets/request-output.js';
13
+ import { getSecretBackend } from '../secrets/backend.js';
14
+ function fillableFormPresencePayload(fillableForm) {
15
+ return {
16
+ fillableFormPresence: fillableForm.presence ?? 'present',
17
+ };
18
+ }
19
+ function finalizeRequestSecretStepBestEffort(runId, stepId, options) {
20
+ if (!runId || !stepId) {
21
+ return;
22
+ }
23
+ try {
24
+ finishRunStep({
25
+ runId,
26
+ stepId,
27
+ ...options,
28
+ });
29
+ }
30
+ catch {
31
+ }
32
+ }
33
+ async function emitRequestSecretFailure(session, runId, stepId, payload, options = {}) {
34
+ const step = runId && stepId ? { runId, stepId, command: 'request-secret' } : null;
35
+ captureStepSnapshotBestEffort({
36
+ session,
37
+ step,
38
+ phase: 'point-in-time',
39
+ pageRef: options.pageRef ?? session.runtime?.currentPageRef,
40
+ });
41
+ appendCommandLifecycleEventBestEffort({
42
+ step,
43
+ phase: 'failed',
44
+ attributes: {
45
+ outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : payload.error,
46
+ pageRef: options.pageRef,
47
+ fillRef: options.fillRef,
48
+ storedSecretRef: options.storedSecretRef,
49
+ reason: typeof payload.reason === 'string' ? payload.reason : payload.error,
50
+ },
51
+ });
52
+ finalizeRequestSecretStepBestEffort(runId, stepId, {
53
+ success: false,
54
+ outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : payload.error,
55
+ message: typeof payload.message === 'string'
56
+ ? payload.message
57
+ : 'Protected secret request failed.',
58
+ reason: typeof payload.reason === 'string' ? payload.reason : payload.error,
59
+ });
60
+ await exportRunStepToOtlpHttpJsonBestEffort(runId, stepId);
61
+ return outputFailure(payload);
62
+ }
63
+ async function emitRequestSecretSuccess(session, runId, stepId, payload, options = {}) {
64
+ const step = runId && stepId ? { runId, stepId, command: 'request-secret' } : null;
65
+ captureStepSnapshotBestEffort({
66
+ session,
67
+ step,
68
+ phase: 'after',
69
+ pageRef: options.pageRef ?? session.runtime?.currentPageRef,
70
+ });
71
+ appendCommandLifecycleEventBestEffort({
72
+ step,
73
+ phase: 'completed',
74
+ attributes: {
75
+ outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : 'secret_request_created',
76
+ pageRef: options.pageRef,
77
+ fillRef: options.fillRef,
78
+ storedSecretRef: options.storedSecretRef,
79
+ requestId: options.requestId,
80
+ },
81
+ });
82
+ finalizeRequestSecretStepBestEffort(runId, stepId, {
83
+ success: true,
84
+ outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : 'secret_request_created',
85
+ message: typeof payload.message === 'string' ? payload.message : 'Protected secret request created.',
86
+ reason: typeof payload.reason === 'string' ? payload.reason : undefined,
87
+ });
88
+ await exportRunStepToOtlpHttpJsonBestEffort(runId, stepId);
89
+ return outputJSON(payload);
90
+ }
91
+ function secretFieldType(fieldKey) {
92
+ if (fieldKey === 'password' || fieldKey === 'cvv') {
93
+ return 'secret';
94
+ }
95
+ if (fieldKey === 'date_of_birth' || fieldKey === 'issue_date' || fieldKey === 'expiry_date') {
96
+ return 'date';
97
+ }
98
+ if (fieldKey === 'exp_month' || fieldKey === 'exp_year') {
99
+ return 'number';
100
+ }
101
+ return 'text';
102
+ }
103
+ function buildSecretHintFields(fillableForm, storedSecret) {
104
+ const allowedFieldKeys = storedSecret.fieldKeys && storedSecret.fieldKeys.length > 0
105
+ ? new Set(storedSecret.fieldKeys)
106
+ : null;
107
+ return fillableForm.fields
108
+ .filter((field) => !allowedFieldKeys || allowedFieldKeys.has(field.fieldKey))
109
+ .map((field) => ({
110
+ key: field.fieldKey,
111
+ ...(field.label ? { label: field.label } : {}),
112
+ ...(secretFieldType(field.fieldKey) ? { type: secretFieldType(field.fieldKey) } : {}),
113
+ required: field.required !== false,
114
+ }));
115
+ }
116
+ function persistSecretRequestState(session, result) {
117
+ const snapshot = saveSecretRequestSnapshot(session, result.snapshot);
118
+ session.intentSessionId = result.session.sessionId;
119
+ session.currentRequestId = result.session.currentRequestId ?? undefined;
120
+ session.lastKnownStatus = result.session.status;
121
+ session.lastEventSeq = result.session.lastEventSeq;
122
+ saveSession(session);
123
+ return snapshot;
124
+ }
125
+ export async function requestSecret(session, fillRef, storedSecretRef, merchantName) {
126
+ const requestSecretStep = session.activeRunId
127
+ ? startRunStep({
128
+ runId: session.activeRunId,
129
+ command: 'request-secret',
130
+ input: {
131
+ storedSecretRef,
132
+ merchantName,
133
+ },
134
+ refs: {
135
+ fillRef,
136
+ },
137
+ protectedStep: true,
138
+ })
139
+ : null;
140
+ const requestSecretStepHandle = session.activeRunId && requestSecretStep?.stepId
141
+ ? {
142
+ runId: session.activeRunId,
143
+ stepId: requestSecretStep.stepId,
144
+ command: 'request-secret',
145
+ }
146
+ : null;
147
+ captureStepSnapshotBestEffort({
148
+ session,
149
+ step: requestSecretStepHandle,
150
+ phase: 'before',
151
+ pageRef: session.runtime?.currentPageRef,
152
+ });
153
+ appendCommandLifecycleEventBestEffort({
154
+ step: requestSecretStepHandle,
155
+ phase: 'started',
156
+ attributes: {
157
+ fillRef,
158
+ storedSecretRef,
159
+ pageRef: session.runtime?.currentPageRef,
160
+ },
161
+ });
162
+ return withApiTraceContext({
163
+ runId: session.activeRunId,
164
+ stepId: requestSecretStep?.stepId,
165
+ command: 'request-secret',
166
+ }, async () => {
167
+ if (!session.intentSessionId) {
168
+ return emitRequestSecretFailure(session, session.activeRunId, requestSecretStep?.stepId, {
169
+ error: 'workflow_session_unavailable',
170
+ outcomeType: 'blocked',
171
+ message: 'Protected secret request was not created because no active workflow session is bound to this browser.',
172
+ reason: 'Run start-session first so AgentBrowse has a workflow session for secret requests.',
173
+ fillRef,
174
+ storedSecretRef,
175
+ }, {
176
+ fillRef,
177
+ storedSecretRef,
178
+ });
179
+ }
180
+ const fillableForm = getFillableForm(session, fillRef);
181
+ if (!fillableForm) {
182
+ return emitRequestSecretFailure(session, session.activeRunId, requestSecretStep?.stepId, {
183
+ error: 'unknown_fill_ref',
184
+ outcomeType: 'blocked',
185
+ message: 'Protected secret request was not created because the requested fill reference is unknown.',
186
+ reason: 'The provided fillRef does not match any currently observed protected fill target.',
187
+ fillRef,
188
+ }, {
189
+ fillRef,
190
+ storedSecretRef,
191
+ });
192
+ }
193
+ if (fillableForm.presence === 'absent') {
194
+ return emitRequestSecretFailure(session, session.activeRunId, requestSecretStep?.stepId, {
195
+ error: 'fillable_form_absent',
196
+ outcomeType: 'blocked',
197
+ message: 'Protected secret request was not created because the requested fill target is no longer present on the page.',
198
+ reason: 'AgentBrowse already observed this protected fill target as absent, so a new observe pass is required before requesting a secret.',
199
+ fillRef,
200
+ storedSecretRef,
201
+ ...fillableFormPresencePayload(fillableForm),
202
+ }, {
203
+ pageRef: fillableForm.pageRef,
204
+ fillRef,
205
+ storedSecretRef,
206
+ });
207
+ }
208
+ const storedSecret = fillableForm.storedSecretCandidates.find((candidate) => candidate.storedSecretRef === storedSecretRef);
209
+ if (!storedSecret) {
210
+ return emitRequestSecretFailure(session, session.activeRunId, requestSecretStep?.stepId, {
211
+ error: 'stored_secret_not_available_for_fill_ref',
212
+ outcomeType: 'blocked',
213
+ message: 'Protected secret request was not created because this stored secret is not available for the requested fill target.',
214
+ reason: 'The provided storedSecretRef is not a candidate for the requested protected fill target.',
215
+ fillRef,
216
+ storedSecretRef,
217
+ ...fillableFormPresencePayload(fillableForm),
218
+ }, {
219
+ pageRef: fillableForm.pageRef,
220
+ fillRef,
221
+ storedSecretRef,
222
+ });
223
+ }
224
+ const pageState = session.runtime?.pages?.[fillableForm.pageRef];
225
+ const pageUrl = pageState?.url;
226
+ const host = tryResolveCatalogHost(pageUrl);
227
+ if (!host) {
228
+ return emitRequestSecretFailure(session, session.activeRunId, requestSecretStep?.stepId, {
229
+ error: 'secret_request_host_resolution_failed',
230
+ outcomeType: 'blocked',
231
+ message: 'Protected secret request was not created because AgentBrowse could not determine the current site host.',
232
+ reason: 'The current page URL did not resolve to a usable host for secret request creation.',
233
+ fillRef,
234
+ storedSecretRef,
235
+ ...fillableFormPresencePayload(fillableForm),
236
+ }, {
237
+ pageRef: fillableForm.pageRef,
238
+ fillRef,
239
+ storedSecretRef,
240
+ });
241
+ }
242
+ const result = await getSecretBackend().createOrReuseSecretRequest({
243
+ sessionId: session.intentSessionId,
244
+ clientRequestId: requestSecretStep?.stepId ?? `request-secret-${Date.now()}`,
245
+ fillRef,
246
+ purpose: fillableForm.purpose,
247
+ merchantName,
248
+ page: {
249
+ ref: fillableForm.pageRef,
250
+ ...(pageState?.url ? { url: pageState.url } : {}),
251
+ ...(pageState?.title ? { title: pageState.title } : {}),
252
+ },
253
+ secretHint: {
254
+ storedSecretRef,
255
+ credentialName: storedSecret.displayName,
256
+ kind: storedSecret.kind,
257
+ host,
258
+ ...(fillableForm.scopeRef ? { scopeRef: fillableForm.scopeRef } : {}),
259
+ fields: buildSecretHintFields(fillableForm, storedSecret),
260
+ },
261
+ });
262
+ const snapshot = persistSecretRequestState(session, result);
263
+ const statusContract = describeSecretRequestStatus(snapshot.status, snapshot.requestType);
264
+ const reasonPrefix = result.reused
265
+ ? 'AgentBrowse reused an existing secret request for this fill target.'
266
+ : 'AgentBrowse created a new secret request for this fill target.';
267
+ return emitRequestSecretSuccess(session, session.activeRunId, requestSecretStep?.stepId, {
268
+ success: true,
269
+ ...fillableFormPresencePayload(fillableForm),
270
+ ...serializeSecretRequest(snapshot),
271
+ reused: result.reused,
272
+ ...(result.duplicate ? { duplicate: true } : {}),
273
+ ...(statusContract.outcomeType ? { outcomeType: statusContract.outcomeType } : {}),
274
+ message: statusContract.message,
275
+ reason: `${reasonPrefix} ${statusContract.reason}`,
276
+ ...(statusContract.nextAction ? { nextAction: statusContract.nextAction } : {}),
277
+ }, {
278
+ pageRef: fillableForm.pageRef,
279
+ fillRef,
280
+ storedSecretRef,
281
+ requestId: snapshot.requestId,
282
+ });
283
+ });
284
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAWnD,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEzF"}
1
+ {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAoKnD,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0HzF"}