@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
@@ -3,6 +3,7 @@ import { AgentpayStagehandLlmClient } from '../agentpay-stagehand-llm.js';
3
3
  import { tryResolveAgentpayGatewayConfig } from '../agentpay-gateway.js';
4
4
  import { IDENTITY_FIELD_KEYS, LOGIN_FIELD_KEYS, PAYMENT_CARD_FIELD_KEYS } from './types.js';
5
5
  import { normalizeProtectedBindingValueHint, protectedBindingKey, protectedBindingValueHintSchema, } from './protected-bindings.js';
6
+ import { inferProtectedFieldMeaningFromTarget } from './protected-field-semantics.js';
6
7
  const PROMPT_VALUE_MAX_CHARS = 180;
7
8
  const PROMPT_SIGNAL_MAX_CHARS = 220;
8
9
  const PROMPT_SIGNAL_MAX_VALUES = 8;
@@ -12,16 +13,23 @@ const PAYMENT_CARD_CORE_FIELD_KEYS = new Set([
12
13
  'exp_year',
13
14
  'cvv',
14
15
  ]);
15
- const PAYMENT_CARD_CORE_SIGNAL_RE = /\b(card number|card no|cc-number|cc number|expiration|expiry|exp(?:iry)? date|mm\s*\/\s*yy|security code|cvv|cvc)\b/i;
16
- const PAYMENT_CARD_NAME_SIGNAL_RE = /\b(cardholder|card holder|name on card|cardholder name|full name)\b/i;
16
+ const EXPLICIT_PAYMENT_CARD_CORE_FIELD_KEYS = new Set(['pan', 'cvv']);
17
+ const IDENTITY_ANCHOR_FIELD_KEYS = new Set([
18
+ 'document_number',
19
+ 'date_of_birth',
20
+ 'nationality',
21
+ 'issuing_country',
22
+ ]);
23
+ const IDENTITY_SUPPLEMENTAL_FIELD_KEYS = new Set([
24
+ 'issue_date',
25
+ 'expiry_date',
26
+ ]);
27
+ const IDENTITY_NAME_FIELD_KEYS = new Set(['full_name']);
17
28
  const EXPLICIT_PAYMENT_CARD_NAME_SIGNAL_RE = /\b(cardholder|card holder|name on card|cardholder name)\b/i;
18
29
  const PAYMENT_CARD_PAN_SIGNAL_RE = /\b(card number|card no|cc-number|cc number)\b/i;
19
- const PAYMENT_CARD_EXP_SIGNAL_RE = /\b(expiration|expiry|exp(?:iry)? date|exp date|mm\s*\/\s*yy|mmyy|mm\/yy)\b/i;
20
30
  const PAYMENT_CARD_CVV_SIGNAL_RE = /\b(security code|cvv|cvc)\b/i;
21
31
  const STRONG_PAYMENT_CARD_EXP_SIGNAL_RE = /\b(mm\s*\/\s*yy|mmyy|card exp(?:iry)?|card expiration|cc-exp)\b/i;
22
- const IDENTITY_ANCHOR_SIGNAL_RE = /\b(passport|document(?: number| no)?|id(?: number| no)?|identity(?: number)?|nationality|citizenship|date of birth|birth date|dob|issuing country|country of issue|country\/region of issue|issuing state)\b/i;
23
- const IDENTITY_NAME_SIGNAL_RE = /\b(first name|last name|given name|family name|surname|full name|middle name|forename)\b/i;
24
- const IDENTITY_SUPPLEMENTAL_SIGNAL_RE = /\b(issue date|date of issue|expiry date|expiration date|date of expiry)\b/i;
32
+ const GENERIC_SHELL_SELECTOR_ROOTS = new Set(['#__next', '#root', '#app', '#app-root']);
25
33
  const protectedFormPlanSchema = z.object({
26
34
  confidence: z.enum(['high', 'medium', 'low']),
27
35
  bindings: z
@@ -66,6 +74,23 @@ function selectorSignalFragments(selector) {
66
74
  }
67
75
  return fragments;
68
76
  }
77
+ function selectorRootOf(target) {
78
+ const selectors = [
79
+ target.context?.item?.selector,
80
+ target.context?.container?.selector,
81
+ target.context?.landmark?.selector,
82
+ ].filter((value) => typeof value === 'string' && value.length > 0);
83
+ for (const selector of selectors) {
84
+ for (const match of selector.matchAll(/#[A-Za-z0-9_-]+/g)) {
85
+ const candidate = match[0]?.trim().toLowerCase();
86
+ if (!candidate || GENERIC_SHELL_SELECTOR_ROOTS.has(candidate)) {
87
+ continue;
88
+ }
89
+ return match[0];
90
+ }
91
+ }
92
+ return null;
93
+ }
69
94
  function signalValuesOf(target) {
70
95
  const values = new Set();
71
96
  const push = (value) => {
@@ -99,115 +124,43 @@ function signalValuesOf(target) {
99
124
  }
100
125
  return [...values];
101
126
  }
102
- function localSignalValuesOf(target) {
127
+ function directFieldSignalValuesOf(target) {
103
128
  const values = new Set();
104
129
  const push = (value) => {
105
130
  const normalized = normalizeText(value);
106
131
  if (normalized) {
107
- values.add(normalized.length > PROMPT_SIGNAL_MAX_CHARS
108
- ? `${normalized.slice(0, PROMPT_SIGNAL_MAX_CHARS - 1)}…`
109
- : normalized);
132
+ values.add(normalized);
110
133
  }
111
134
  };
112
135
  push(target.label);
113
136
  push(target.displayLabel);
114
- push(target.kind);
115
- push(target.semantics?.role);
116
- push(target.semantics?.name);
117
137
  push(target.placeholder);
118
138
  push(target.inputName);
119
139
  push(target.inputType);
120
140
  push(target.autocomplete);
121
- for (const candidate of target.locatorCandidates) {
122
- push(candidate.name);
123
- if (candidate.strategy === 'css' || candidate.strategy === 'xpath') {
124
- push(candidate.value);
125
- for (const fragment of selectorSignalFragments(candidate.value)) {
126
- push(fragment);
127
- }
128
- continue;
129
- }
130
- if (candidate.strategy === 'label' ||
131
- candidate.strategy === 'placeholder' ||
132
- candidate.strategy === 'title') {
133
- push(candidate.value);
134
- }
135
- }
141
+ push(target.semantics?.name);
136
142
  return [...values];
137
143
  }
144
+ function targetHasInferredProtectedMeaning(target, kind, fieldKeys) {
145
+ return inferProtectedFieldMeaningFromTarget(target).some((hint) => {
146
+ if (hint.kind !== kind) {
147
+ return false;
148
+ }
149
+ return !fieldKeys || fieldKeys.has(hint.fieldKey);
150
+ });
151
+ }
138
152
  function targetLooksLikePaymentCardCore(target) {
139
- const autocomplete = normalizeText(target.autocomplete);
140
- const inputName = normalizeText(target.inputName);
141
- const signals = localSignalValuesOf(target);
142
- if (autocomplete.includes('cc-number') ||
143
- autocomplete.includes('cc-exp') ||
144
- autocomplete.includes('cc-csc')) {
145
- return true;
146
- }
147
- if (signals.some((signal) => PAYMENT_CARD_CORE_SIGNAL_RE.test(signal))) {
148
- return true;
149
- }
150
- return /\b(card(number)?|expiry|exp|cvc|cvv)\b/.test(inputName);
153
+ return targetHasInferredProtectedMeaning(target, 'payment_card', PAYMENT_CARD_CORE_FIELD_KEYS);
151
154
  }
152
155
  function targetLooksRelevantToPaymentCard(target) {
153
- if (targetLooksLikePaymentCardCore(target)) {
154
- return true;
155
- }
156
- const autocomplete = normalizeText(target.autocomplete);
157
- const inputName = normalizeText(target.inputName);
158
- const signals = localSignalValuesOf(target);
159
- if (autocomplete.includes('cc-name')) {
160
- return true;
161
- }
162
- if (PAYMENT_CARD_NAME_SIGNAL_RE.test(normalizeText(target.label))) {
163
- return true;
164
- }
165
- if (signals.some((signal) => PAYMENT_CARD_NAME_SIGNAL_RE.test(signal))) {
166
- return true;
167
- }
168
- return /\b(cardholder|card-holder|cc-name)\b/.test(inputName);
156
+ return (targetLooksLikeExplicitPaymentCardTarget(target) ||
157
+ targetLooksLikePaymentCardCore(target) ||
158
+ targetHasInferredProtectedMeaning(target, 'payment_card'));
169
159
  }
170
160
  function deterministicPaymentCardFieldKeysForTarget(target) {
171
- const autocomplete = normalizeText(target.autocomplete);
172
- const inputName = normalizeText(target.inputName);
173
- const signals = localSignalValuesOf(target);
174
- if (autocomplete.includes('cc-number')) {
175
- return ['pan'];
176
- }
177
- if (autocomplete.includes('cc-exp')) {
178
- return ['exp_month', 'exp_year'];
179
- }
180
- if (autocomplete.includes('cc-csc')) {
181
- return ['cvv'];
182
- }
183
- if (autocomplete.includes('cc-name')) {
184
- return ['cardholder'];
185
- }
186
- if (signals.some((signal) => PAYMENT_CARD_PAN_SIGNAL_RE.test(signal))) {
187
- return ['pan'];
188
- }
189
- if (signals.some((signal) => PAYMENT_CARD_EXP_SIGNAL_RE.test(signal))) {
190
- return ['exp_month', 'exp_year'];
191
- }
192
- if (signals.some((signal) => PAYMENT_CARD_CVV_SIGNAL_RE.test(signal))) {
193
- return ['cvv'];
194
- }
195
- if (signals.some((signal) => PAYMENT_CARD_NAME_SIGNAL_RE.test(signal))) {
196
- return ['cardholder'];
197
- }
198
- if (/\b(card(number)?|cc-?number)\b/.test(inputName)) {
199
- return ['pan'];
200
- }
201
- if (/\b(exp|expiry|expiration)\b/.test(inputName)) {
202
- return ['exp_month', 'exp_year'];
203
- }
204
- if (/\b(cvv|cvc|security)\b/.test(inputName)) {
205
- return ['cvv'];
206
- }
207
- if (/\b(cardholder|card-holder|cc-name)\b/.test(inputName)) {
208
- return ['cardholder'];
209
- }
210
- return [];
161
+ return inferProtectedFieldMeaningFromTarget(target)
162
+ .filter((hint) => hint.kind === 'payment_card')
163
+ .map((hint) => hint.fieldKey);
211
164
  }
212
165
  function deterministicPaymentCardPlan(plannerGroup, fullGroup) {
213
166
  const fieldTargets = new Map();
@@ -266,30 +219,15 @@ function deterministicPaymentCardPlan(plannerGroup, fullGroup) {
266
219
  function targetLooksLikeExplicitPaymentCardTarget(target) {
267
220
  const autocomplete = normalizeText(target.autocomplete);
268
221
  const inputName = normalizeText(target.inputName);
269
- const signals = localSignalValuesOf(target);
222
+ const signals = directFieldSignalValuesOf(target);
270
223
  const frameKey = normalizeText(frameKeyOf(target) ?? undefined);
271
- if (autocomplete.includes('cc-number') ||
272
- autocomplete.includes('cc-exp') ||
273
- autocomplete.includes('cc-csc') ||
274
- autocomplete.includes('cc-name')) {
275
- return true;
276
- }
277
- if (signals.some((signal) => PAYMENT_CARD_PAN_SIGNAL_RE.test(signal))) {
278
- return true;
279
- }
280
- if (signals.some((signal) => PAYMENT_CARD_CVV_SIGNAL_RE.test(signal))) {
224
+ if (targetLooksLikeExplicitPaymentCardCoreTarget(target) || autocomplete.includes('cc-name')) {
281
225
  return true;
282
226
  }
283
227
  if (signals.some((signal) => EXPLICIT_PAYMENT_CARD_NAME_SIGNAL_RE.test(signal))) {
284
228
  return true;
285
229
  }
286
- if (signals.some((signal) => STRONG_PAYMENT_CARD_EXP_SIGNAL_RE.test(signal))) {
287
- return true;
288
- }
289
- if (/\b(card(number)?|cc-?number|cardholder|card-holder|cc-name|cvv|cvc|security)\b/.test(inputName)) {
290
- return true;
291
- }
292
- if (/\bcc[-_ ]?exp\b/.test(inputName)) {
230
+ if (/\b(cardholder|card-holder|cc-name)\b/.test(inputName)) {
293
231
  return true;
294
232
  }
295
233
  return /\bcard[-_ ]?(number|expiry|exp|cvc|cvv|security|holder)\b/.test(frameKey);
@@ -297,13 +235,16 @@ function targetLooksLikeExplicitPaymentCardTarget(target) {
297
235
  function targetLooksLikeExplicitPaymentCardCoreTarget(target) {
298
236
  const autocomplete = normalizeText(target.autocomplete);
299
237
  const inputName = normalizeText(target.inputName);
300
- const signals = localSignalValuesOf(target);
238
+ const signals = directFieldSignalValuesOf(target);
301
239
  const frameKey = normalizeText(frameKeyOf(target) ?? undefined);
302
240
  if (autocomplete.includes('cc-number') ||
303
241
  autocomplete.includes('cc-exp') ||
304
242
  autocomplete.includes('cc-csc')) {
305
243
  return true;
306
244
  }
245
+ if (targetHasInferredProtectedMeaning(target, 'payment_card', EXPLICIT_PAYMENT_CARD_CORE_FIELD_KEYS)) {
246
+ return true;
247
+ }
307
248
  if (signals.some((signal) => PAYMENT_CARD_PAN_SIGNAL_RE.test(signal))) {
308
249
  return true;
309
250
  }
@@ -322,38 +263,172 @@ function targetLooksLikeExplicitPaymentCardCoreTarget(target) {
322
263
  return /\bcard[-_ ]?(number|expiry|exp|cvc|cvv|security)\b/.test(frameKey);
323
264
  }
324
265
  function targetLooksLikeIdentityAnchorTarget(target) {
325
- const autocomplete = normalizeText(target.autocomplete);
326
- const inputName = normalizeText(target.inputName);
327
- const signals = localSignalValuesOf(target);
328
- if (autocomplete.includes('bday')) {
329
- return true;
266
+ return targetHasInferredProtectedMeaning(target, 'identity', IDENTITY_ANCHOR_FIELD_KEYS);
267
+ }
268
+ function targetLooksLikeIdentitySupplementalTarget(target) {
269
+ if (targetLooksLikeExplicitPaymentCardTarget(target)) {
270
+ return false;
330
271
  }
331
- if (/\b(passport|document|identity|nationality|citizenship|birth|dob|issuing)\b/.test(inputName)) {
332
- return true;
272
+ return targetHasInferredProtectedMeaning(target, 'identity', IDENTITY_SUPPLEMENTAL_FIELD_KEYS);
273
+ }
274
+ function targetLooksLikeIdentityNameTarget(target) {
275
+ if (targetLooksLikeExplicitPaymentCardTarget(target)) {
276
+ return false;
333
277
  }
334
- return signals.some((signal) => IDENTITY_ANCHOR_SIGNAL_RE.test(signal));
278
+ return targetHasInferredProtectedMeaning(target, 'identity', IDENTITY_NAME_FIELD_KEYS);
335
279
  }
336
- function targetLooksLikeIdentitySupplementalTarget(target) {
280
+ function targetLooksLikePotentialIdentityNameTarget(target) {
337
281
  if (targetLooksLikeExplicitPaymentCardTarget(target)) {
338
282
  return false;
339
283
  }
340
- const inputName = normalizeText(target.inputName);
341
- const signals = localSignalValuesOf(target);
342
- if (/\b(issue|expiry|expiration)(?:_?date)?\b/.test(inputName)) {
284
+ if (targetLooksLikeIdentityNameTarget(target)) {
343
285
  return true;
344
286
  }
345
- return signals.some((signal) => IDENTITY_SUPPLEMENTAL_SIGNAL_RE.test(signal));
287
+ const signals = directFieldSignalValuesOf(target);
288
+ return signals.some((signal) => /\b(full name|first name|given name|middle name|last name|family name|surname|forename)\b/.test(signal));
346
289
  }
347
- function targetLooksLikeIdentityNameTarget(target) {
290
+ function targetLooksLikePotentialIdentityDobPartTarget(target) {
348
291
  if (targetLooksLikeExplicitPaymentCardTarget(target)) {
349
292
  return false;
350
293
  }
351
- const inputName = normalizeText(target.inputName);
352
- const signals = localSignalValuesOf(target);
353
- if (/\b(first|last|given|family|surname|forename|middle|full)_?name\b/.test(inputName)) {
354
- return true;
294
+ if (!(target.controlFamily === 'select' ||
295
+ target.controlFamily === 'datepicker' ||
296
+ target.kind === 'select' ||
297
+ target.allowedActions.includes('select'))) {
298
+ return false;
299
+ }
300
+ const signals = directFieldSignalValuesOf(target);
301
+ return signals.some((signal) => /\b(day|month|year)\b/.test(signal));
302
+ }
303
+ function deterministicIdentityBindingsForTarget(target) {
304
+ return inferProtectedFieldMeaningFromTarget(target)
305
+ .filter((hint) => hint.kind === 'identity')
306
+ .map((hint) => ({
307
+ fieldKey: hint.fieldKey,
308
+ valueHint: hint.valueHint,
309
+ }));
310
+ }
311
+ function deterministicIdentityPlan(plannerGroup, fullGroup) {
312
+ const fieldTargets = new Map();
313
+ for (const target of plannerGroup.targets) {
314
+ for (const binding of deterministicIdentityBindingsForTarget(target)) {
315
+ const key = protectedBindingKey({
316
+ fieldKey: binding.fieldKey,
317
+ targetRef: target.ref,
318
+ valueHint: binding.valueHint ?? 'direct',
319
+ });
320
+ if (fieldTargets.has(key)) {
321
+ return null;
322
+ }
323
+ fieldTargets.set(key, {
324
+ fieldKey: binding.fieldKey,
325
+ targetRef: target.ref,
326
+ valueHint: normalizeProtectedBindingValueHint(binding.fieldKey, binding.valueHint),
327
+ });
328
+ }
329
+ }
330
+ if (fieldTargets.size === 0) {
331
+ return null;
332
+ }
333
+ const targetByRef = new Map(fullGroup.targets.map((target) => [target.ref, target]));
334
+ const fields = [];
335
+ for (const binding of fieldTargets.values()) {
336
+ const target = targetByRef.get(binding.targetRef);
337
+ fields.push({
338
+ fieldKey: binding.fieldKey,
339
+ targetRef: binding.targetRef,
340
+ label: target?.displayLabel ?? target?.label,
341
+ required: target?.validation?.required,
342
+ valueHint: binding.valueHint,
343
+ });
355
344
  }
356
- return signals.some((signal) => IDENTITY_NAME_SIGNAL_RE.test(signal));
345
+ const boundTargetRefs = new Set(fields.map((field) => field.targetRef));
346
+ const hasUnresolvedPlannerRelevantTargets = fullGroup.targets.some((target) => {
347
+ if (boundTargetRefs.has(target.ref)) {
348
+ return false;
349
+ }
350
+ return (targetLooksLikePotentialIdentityNameTarget(target) ||
351
+ targetLooksLikePotentialIdentityDobPartTarget(target) ||
352
+ targetLooksLikeIdentityAnchorTarget(target) ||
353
+ targetLooksLikeIdentitySupplementalTarget(target));
354
+ });
355
+ if (hasUnresolvedPlannerRelevantTargets) {
356
+ return null;
357
+ }
358
+ return {
359
+ confidence: 'high',
360
+ fields: fields.sort((left, right) => {
361
+ const leftPriority = canonicalFieldOrder('identity').indexOf(left.fieldKey);
362
+ const rightPriority = canonicalFieldOrder('identity').indexOf(right.fieldKey);
363
+ if (leftPriority !== rightPriority) {
364
+ return leftPriority - rightPriority;
365
+ }
366
+ return left.targetRef.localeCompare(right.targetRef);
367
+ }),
368
+ };
369
+ }
370
+ function targetLooksLikeLoginUsernameTarget(target) {
371
+ return inferProtectedFieldMeaningFromTarget(target).some((hint) => hint.kind === 'login' && hint.fieldKey === 'username');
372
+ }
373
+ function targetLooksLikeLoginPasswordTarget(target) {
374
+ return inferProtectedFieldMeaningFromTarget(target).some((hint) => hint.kind === 'login' && hint.fieldKey === 'password');
375
+ }
376
+ function deterministicLoginFieldKeysForTarget(target) {
377
+ return inferProtectedFieldMeaningFromTarget(target)
378
+ .filter((hint) => hint.kind === 'login')
379
+ .map((hint) => hint.fieldKey);
380
+ }
381
+ function deterministicLoginPlan(plannerGroup, fullGroup) {
382
+ const fieldTargets = new Map();
383
+ for (const target of plannerGroup.targets) {
384
+ for (const fieldKey of deterministicLoginFieldKeysForTarget(target)) {
385
+ const refs = fieldTargets.get(fieldKey) ?? new Set();
386
+ refs.add(target.ref);
387
+ fieldTargets.set(fieldKey, refs);
388
+ }
389
+ }
390
+ const usernameRefs = fieldTargets.get('username');
391
+ const passwordRefs = fieldTargets.get('password');
392
+ if (!usernameRefs || usernameRefs.size !== 1 || !passwordRefs || passwordRefs.size !== 1) {
393
+ return null;
394
+ }
395
+ const targetByRef = new Map(fullGroup.targets.map((target) => [target.ref, target]));
396
+ const fields = [
397
+ {
398
+ fieldKey: 'username',
399
+ targetRef: [...usernameRefs][0],
400
+ label: targetByRef.get([...usernameRefs][0])?.displayLabel ??
401
+ targetByRef.get([...usernameRefs][0])?.label,
402
+ required: targetByRef.get([...usernameRefs][0])?.validation?.required,
403
+ valueHint: 'direct',
404
+ },
405
+ {
406
+ fieldKey: 'password',
407
+ targetRef: [...passwordRefs][0],
408
+ label: targetByRef.get([...passwordRefs][0])?.displayLabel ??
409
+ targetByRef.get([...passwordRefs][0])?.label,
410
+ required: targetByRef.get([...passwordRefs][0])?.validation?.required,
411
+ valueHint: 'direct',
412
+ },
413
+ ];
414
+ return {
415
+ confidence: 'high',
416
+ fields,
417
+ };
418
+ }
419
+ function loginPlannerGroup(group) {
420
+ const relevantTargets = group.targets.filter((target) => targetLooksLikeLoginUsernameTarget(target) || targetLooksLikeLoginPasswordTarget(target));
421
+ if (relevantTargets.length === 0) {
422
+ return null;
423
+ }
424
+ const hasPasswordAnchor = relevantTargets.some((target) => targetLooksLikeLoginPasswordTarget(target));
425
+ if (!hasPasswordAnchor) {
426
+ return null;
427
+ }
428
+ return {
429
+ groupKey: group.groupKey,
430
+ targets: relevantTargets,
431
+ };
357
432
  }
358
433
  function identityPlannerGroup(group) {
359
434
  const identityAnchorTargets = group.targets.filter((target) => !targetLooksLikeExplicitPaymentCardTarget(target) &&
@@ -361,19 +436,19 @@ function identityPlannerGroup(group) {
361
436
  if (identityAnchorTargets.length === 0) {
362
437
  return null;
363
438
  }
364
- const nameTargets = group.targets.filter(targetLooksLikeIdentityNameTarget);
365
- const supplementalTargets = group.targets.filter(targetLooksLikeIdentitySupplementalTarget);
366
- const targetByRef = new Map();
367
- for (const target of [...nameTargets, ...identityAnchorTargets, ...supplementalTargets]) {
368
- targetByRef.set(target.ref, target);
439
+ const hasPotentialNameTarget = group.targets.some(targetLooksLikePotentialIdentityNameTarget);
440
+ if (!hasPotentialNameTarget) {
441
+ return null;
369
442
  }
370
443
  return {
371
444
  groupKey: group.groupKey,
372
- targets: [...targetByRef.values()],
445
+ targets: group.targets.filter((target) => !targetLooksLikeExplicitPaymentCardTarget(target)),
373
446
  };
374
447
  }
375
448
  function plannerGroupForKind(kind, group) {
376
449
  switch (kind) {
450
+ case 'login':
451
+ return loginPlannerGroup(group);
377
452
  case 'payment_card': {
378
453
  const relevantTargets = group.targets.filter((target) => targetLooksRelevantToPaymentCard(target));
379
454
  if (relevantTargets.length === 0) {
@@ -395,17 +470,27 @@ function plannerGroupForKind(kind, group) {
395
470
  }
396
471
  }
397
472
  function formGroupKeyOf(target) {
398
- for (const node of [
399
- target.context?.landmark,
400
- target.context?.container,
401
- target.context?.group,
402
- target.context?.item,
403
- ]) {
473
+ for (const node of [target.context?.group, target.context?.container, target.context?.item]) {
404
474
  if (normalizeText(node?.kind) !== 'form') {
405
475
  continue;
406
476
  }
407
477
  const label = normalizeText(node?.label ?? node?.text);
408
- return label ? `form:${label}` : `form:${target.pageRef}`;
478
+ if (label) {
479
+ return `form:${label}`;
480
+ }
481
+ }
482
+ if (normalizeText(target.context?.landmark?.kind) === 'form') {
483
+ const landmarkLabel = normalizeText(target.context?.landmark?.label);
484
+ if (landmarkLabel) {
485
+ return `form:${landmarkLabel}`;
486
+ }
487
+ }
488
+ const selectorRoot = selectorRootOf(target);
489
+ if (selectorRoot) {
490
+ return `selector-root:${selectorRoot}`;
491
+ }
492
+ if (target.surfaceRef) {
493
+ return `surface:${target.surfaceRef}`;
409
494
  }
410
495
  return `page:${target.pageRef}`;
411
496
  }
@@ -451,6 +536,10 @@ function purposePrompt(kind) {
451
536
  'full_name may be one direct full-name field or two split fields:',
452
537
  '- First/Given name -> fieldKey=full_name, valueHint=full_name.given',
453
538
  '- Last/Family/Surname -> fieldKey=full_name, valueHint=full_name.family',
539
+ 'date_of_birth may be one direct field or three split controls:',
540
+ '- Day control -> fieldKey=date_of_birth, valueHint=date_of_birth.day',
541
+ '- Month control -> fieldKey=date_of_birth, valueHint=date_of_birth.month',
542
+ '- Year control -> fieldKey=date_of_birth, valueHint=date_of_birth.year',
454
543
  'Do not confuse contact fields like email, phone, address, city, country/region with identity fields.',
455
544
  'Do not treat generic contact-only forms as identity forms.',
456
545
  ].join('\n');
@@ -555,8 +644,36 @@ function sanitizeBindings(kind, group, bindings) {
555
644
  return left.targetRef.localeCompare(right.targetRef);
556
645
  });
557
646
  }
558
- function isCredibleKindMatch(_kind, fieldBindings) {
559
- return fieldBindings.length > 0;
647
+ function isCredibleKindMatch(kind, fieldBindings) {
648
+ if (fieldBindings.length === 0) {
649
+ return false;
650
+ }
651
+ const fieldKeys = new Set(fieldBindings.map((field) => field.fieldKey));
652
+ switch (kind) {
653
+ case 'login':
654
+ return fieldKeys.has('username') && fieldKeys.has('password');
655
+ case 'payment_card':
656
+ return (fieldKeys.has('pan') &&
657
+ fieldKeys.has('exp_month') &&
658
+ fieldKeys.has('exp_year') &&
659
+ fieldKeys.has('cvv'));
660
+ case 'identity': {
661
+ const anchorKeys = new Set([
662
+ 'document_number',
663
+ 'date_of_birth',
664
+ 'nationality',
665
+ 'issue_date',
666
+ 'expiry_date',
667
+ 'issuing_country',
668
+ ]);
669
+ const hasAnchor = [...fieldKeys].some((fieldKey) => anchorKeys.has(fieldKey));
670
+ const hasDirectFullName = fieldBindings.some((field) => field.fieldKey === 'full_name' && (field.valueHint ?? 'direct') === 'direct');
671
+ const hasGivenName = fieldBindings.some((field) => field.fieldKey === 'full_name' && field.valueHint === 'full_name.given');
672
+ const hasFamilyName = fieldBindings.some((field) => field.fieldKey === 'full_name' && field.valueHint === 'full_name.family');
673
+ const hasCompleteName = hasDirectFullName || (hasGivenName && hasFamilyName);
674
+ return hasAnchor && hasCompleteName;
675
+ }
676
+ }
560
677
  }
561
678
  function frameKeyOf(target) {
562
679
  if (!target.framePath || target.framePath.length === 0) {
@@ -634,17 +751,35 @@ function buildStoredSecretCandidates(catalog, kind, confidence, matchedFieldKeys
634
751
  function hasApplicableStoredSecretKind(catalog, kind) {
635
752
  return catalog.storedSecrets.some((secret) => secret.kind === kind);
636
753
  }
754
+ const ORDERED_PROTECTED_KINDS = ['login', 'identity', 'payment_card'];
637
755
  function purposesByPriority(catalog) {
638
- const orderedKinds = ['login', 'identity', 'payment_card'];
639
- return orderedKinds.filter((kind) => hasApplicableStoredSecretKind(catalog, kind));
756
+ if (!catalog) {
757
+ return ORDERED_PROTECTED_KINDS;
758
+ }
759
+ return ORDERED_PROTECTED_KINDS.filter((kind) => hasApplicableStoredSecretKind(catalog, kind));
640
760
  }
641
761
  async function planBindingsForGroup(client, kind, plannerGroup, fullGroup) {
762
+ if (kind === 'login') {
763
+ const deterministicPlan = deterministicLoginPlan(plannerGroup, fullGroup);
764
+ if (deterministicPlan) {
765
+ return deterministicPlan;
766
+ }
767
+ }
642
768
  if (kind === 'payment_card') {
643
769
  const deterministicPlan = deterministicPaymentCardPlan(plannerGroup, fullGroup);
644
770
  if (deterministicPlan) {
645
771
  return deterministicPlan;
646
772
  }
647
773
  }
774
+ if (kind === 'identity') {
775
+ const deterministicPlan = deterministicIdentityPlan(plannerGroup, fullGroup);
776
+ if (deterministicPlan) {
777
+ return deterministicPlan;
778
+ }
779
+ }
780
+ if (!client) {
781
+ return null;
782
+ }
648
783
  const result = await client.createChatCompletion({
649
784
  logger: () => { },
650
785
  options: {
@@ -662,7 +797,7 @@ async function planBindingsForGroup(client, kind, plannerGroup, fullGroup) {
662
797
  : sanitizeBindings(kind, plannerGroup, result.data.bindings),
663
798
  };
664
799
  }
665
- function plannerGroupsForCatalog(group, catalog) {
800
+ function plannerGroupsForGroup(group, catalog) {
666
801
  const candidates = [];
667
802
  for (const kind of purposesByPriority(catalog)) {
668
803
  const plannerGroup = plannerGroupForKind(kind, group);
@@ -674,20 +809,14 @@ function plannerGroupsForCatalog(group, catalog) {
674
809
  return candidates;
675
810
  }
676
811
  export async function matchStoredSecretsToObservedTargets(pageRef, targets, catalog, options = {}) {
677
- if (!catalog) {
678
- return [];
679
- }
680
812
  const gateway = options.gatewayConfig === undefined ? tryResolveAgentpayGatewayConfig() : options.gatewayConfig;
681
- if (!gateway) {
682
- return [];
683
- }
684
- const client = new AgentpayStagehandLlmClient(gateway);
813
+ const client = catalog && gateway ? new AgentpayStagehandLlmClient(gateway) : null;
685
814
  const targetByRef = new Map(targets.map((target) => [target.ref, target]));
686
815
  const groups = groupTargetsByForm(targets);
687
816
  const nextObservedAt = options.observedAt ?? new Date().toISOString();
688
817
  const forms = [];
689
818
  for (const group of groups) {
690
- for (const { kind, plannerGroup } of plannerGroupsForCatalog(group, catalog)) {
819
+ for (const { kind, plannerGroup } of plannerGroupsForGroup(group, catalog)) {
691
820
  const planned = await planBindingsForGroup(client, kind, plannerGroup, group).catch(() => null);
692
821
  if (!planned || planned.confidence === 'low') {
693
822
  continue;
@@ -696,10 +825,9 @@ export async function matchStoredSecretsToObservedTargets(pageRef, targets, cata
696
825
  continue;
697
826
  }
698
827
  const matchedFieldKeys = new Set(planned.fields.map((field) => field.fieldKey));
699
- const storedSecretCandidates = buildStoredSecretCandidates(catalog, kind, planned.confidence, matchedFieldKeys);
700
- if (storedSecretCandidates.length === 0) {
701
- continue;
702
- }
828
+ const storedSecretCandidates = catalog
829
+ ? buildStoredSecretCandidates(catalog, kind, planned.confidence, matchedFieldKeys)
830
+ : [];
703
831
  forms.push({
704
832
  pageRef,
705
833
  scopeRef: formScopeRef(planned.fields, targetByRef),
@@ -1,11 +1,7 @@
1
- import type { SecretIntentSnapshot, SecretIntentStatus } from './types.js';
2
- export declare function serializeSecretIntent(snapshot: SecretIntentSnapshot): Record<string, unknown>;
3
- export declare function serializeSecretIntentContext(snapshot: SecretIntentSnapshot): Record<string, unknown>;
4
- export type SecretIntentStatusContract = {
5
- message: string;
6
- reason: string;
7
- nextAction?: string;
8
- outcomeType?: 'approval_pending' | 'approval_denied' | 'intent_expired';
9
- };
10
- export declare function describeSecretIntentStatus(status: SecretIntentStatus): SecretIntentStatusContract;
1
+ import { type SecretRequestStatusContract } from './request-output.js';
2
+ import type { SecretRequestSnapshot, SecretRequestStatus } from './types.js';
3
+ export declare function serializeSecretIntent(snapshot: SecretRequestSnapshot): Record<string, unknown>;
4
+ export declare function serializeSecretIntentContext(snapshot: SecretRequestSnapshot): Record<string, unknown>;
5
+ export type SecretIntentStatusContract = SecretRequestStatusContract;
6
+ export declare function describeSecretIntentStatus(status: SecretRequestStatus): SecretIntentStatusContract;
11
7
  //# sourceMappingURL=intent-output.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"intent-output.d.ts","sourceRoot":"","sources":["../../src/secrets/intent-output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE3E,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAY7F;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,oBAAoB,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;CACzE,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,0BAA0B,CA0CjG"}
1
+ {"version":3,"file":"intent-output.d.ts","sourceRoot":"","sources":["../../src/secrets/intent-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,2BAA2B,EACjC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE7E,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9F;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB;AAED,MAAM,MAAM,0BAA0B,GAAG,2BAA2B,CAAC;AAErE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,mBAAmB,GAAG,0BAA0B,CAElG"}