@nuanu-ai/agentbrowse 0.2.7 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -8
- package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
- package/dist/agentpay-stagehand-llm.js +5 -1
- package/dist/commands/act.d.ts +6 -2
- package/dist/commands/act.d.ts.map +1 -1
- package/dist/commands/act.js +840 -55
- package/dist/commands/act.test-harness.d.ts +19 -0
- package/dist/commands/act.test-harness.d.ts.map +1 -0
- package/dist/commands/act.test-harness.js +245 -0
- package/dist/commands/action-acceptance.d.ts +90 -0
- package/dist/commands/action-acceptance.d.ts.map +1 -0
- package/dist/commands/action-acceptance.js +1411 -0
- package/dist/commands/action-artifacts.d.ts +33 -0
- package/dist/commands/action-artifacts.d.ts.map +1 -0
- package/dist/commands/action-artifacts.js +104 -0
- package/dist/commands/action-execution-guards.d.ts +5 -0
- package/dist/commands/action-execution-guards.d.ts.map +1 -0
- package/dist/commands/action-execution-guards.js +3 -0
- package/dist/commands/action-executor-helpers.d.ts +21 -0
- package/dist/commands/action-executor-helpers.d.ts.map +1 -0
- package/dist/commands/action-executor-helpers.js +242 -0
- package/dist/commands/action-executor.d.ts +12 -0
- package/dist/commands/action-executor.d.ts.map +1 -0
- package/dist/commands/action-executor.js +45 -0
- package/dist/commands/action-fallbacks.d.ts +6 -0
- package/dist/commands/action-fallbacks.d.ts.map +1 -0
- package/dist/commands/action-fallbacks.js +43 -0
- package/dist/commands/action-value-projection.d.ts +32 -0
- package/dist/commands/action-value-projection.d.ts.map +1 -0
- package/dist/commands/action-value-projection.js +151 -0
- package/dist/commands/browse-actions.d.ts +4 -0
- package/dist/commands/browse-actions.d.ts.map +1 -0
- package/dist/commands/browse-actions.js +4 -0
- package/dist/commands/captcha-solve.d.ts.map +1 -1
- package/dist/commands/captcha-solve.js +13 -3
- package/dist/commands/click-action-executor.d.ts +10 -0
- package/dist/commands/click-action-executor.d.ts.map +1 -0
- package/dist/commands/click-action-executor.js +68 -0
- package/dist/commands/create-intent.d.ts +6 -0
- package/dist/commands/create-intent.d.ts.map +1 -0
- package/dist/commands/create-intent.js +75 -0
- package/dist/commands/datepicker-action-executor.d.ts +12 -0
- package/dist/commands/datepicker-action-executor.d.ts.map +1 -0
- package/dist/commands/datepicker-action-executor.js +218 -0
- package/dist/commands/descriptor-validation.d.ts +27 -0
- package/dist/commands/descriptor-validation.d.ts.map +1 -0
- package/dist/commands/descriptor-validation.js +333 -0
- package/dist/commands/extract-scope-resolution.d.ts +20 -0
- package/dist/commands/extract-scope-resolution.d.ts.map +1 -0
- package/dist/commands/extract-scope-resolution.js +100 -0
- package/dist/commands/extract-stagehand-executor.d.ts +17 -0
- package/dist/commands/extract-stagehand-executor.d.ts.map +1 -0
- package/dist/commands/extract-stagehand-executor.js +18 -0
- package/dist/commands/extract.d.ts +3 -2
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +256 -39
- package/dist/commands/fill-secret.d.ts +7 -0
- package/dist/commands/fill-secret.d.ts.map +1 -0
- package/dist/commands/fill-secret.js +371 -0
- package/dist/commands/get-secrets-catalog.d.ts +6 -0
- package/dist/commands/get-secrets-catalog.d.ts.map +1 -0
- package/dist/commands/get-secrets-catalog.js +23 -0
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +41 -7
- package/dist/commands/navigate.d.ts +2 -1
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +49 -12
- package/dist/commands/observe-inventory.d.ts +109 -0
- package/dist/commands/observe-inventory.d.ts.map +1 -0
- package/dist/commands/observe-inventory.js +2837 -0
- package/dist/commands/observe-persistence.d.ts +14 -0
- package/dist/commands/observe-persistence.d.ts.map +1 -0
- package/dist/commands/observe-persistence.js +170 -0
- package/dist/commands/observe-projection.d.ts +84 -0
- package/dist/commands/observe-projection.d.ts.map +1 -0
- package/dist/commands/observe-projection.js +140 -0
- package/dist/commands/observe-protected.d.ts +5 -0
- package/dist/commands/observe-protected.d.ts.map +1 -0
- package/dist/commands/observe-protected.js +18 -0
- package/dist/commands/observe-semantics.d.ts +10 -0
- package/dist/commands/observe-semantics.d.ts.map +1 -0
- package/dist/commands/observe-semantics.js +338 -0
- package/dist/commands/observe-stagehand.d.ts +48 -0
- package/dist/commands/observe-stagehand.d.ts.map +1 -0
- package/dist/commands/observe-stagehand.js +105 -0
- package/dist/commands/observe-surfaces.d.ts +9 -0
- package/dist/commands/observe-surfaces.d.ts.map +1 -0
- package/dist/commands/observe-surfaces.js +195 -0
- package/dist/commands/observe.d.ts +47 -1
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +173 -20
- package/dist/commands/observe.test-harness.d.ts +67 -0
- package/dist/commands/observe.test-harness.d.ts.map +1 -0
- package/dist/commands/observe.test-harness.js +107 -0
- package/dist/commands/poll-intent.d.ts +6 -0
- package/dist/commands/poll-intent.d.ts.map +1 -0
- package/dist/commands/poll-intent.js +57 -0
- package/dist/commands/screenshot.d.ts +2 -1
- package/dist/commands/screenshot.d.ts.map +1 -1
- package/dist/commands/screenshot.js +44 -12
- package/dist/commands/select-action-executor.d.ts +10 -0
- package/dist/commands/select-action-executor.d.ts.map +1 -0
- package/dist/commands/select-action-executor.js +91 -0
- package/dist/commands/semantic-observe.d.ts +24 -0
- package/dist/commands/semantic-observe.d.ts.map +1 -0
- package/dist/commands/semantic-observe.js +344 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +75 -2
- package/dist/commands/structured-grid-action-executor.d.ts +3 -0
- package/dist/commands/structured-grid-action-executor.d.ts.map +1 -0
- package/dist/commands/structured-grid-action-executor.js +4 -0
- package/dist/commands/target-resolution.d.ts +4 -0
- package/dist/commands/target-resolution.d.ts.map +1 -0
- package/dist/commands/target-resolution.js +33 -0
- package/dist/commands/text-input-action-executor.d.ts +5 -0
- package/dist/commands/text-input-action-executor.d.ts.map +1 -0
- package/dist/commands/text-input-action-executor.js +116 -0
- package/dist/commands/user-actionable.d.ts +4 -0
- package/dist/commands/user-actionable.d.ts.map +1 -0
- package/dist/commands/user-actionable.js +95 -0
- package/dist/control-semantics.d.ts +29 -0
- package/dist/control-semantics.d.ts.map +1 -0
- package/dist/control-semantics.js +299 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +95 -32
- package/dist/output.d.ts +14 -2
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +17 -29
- package/dist/playwright-runtime.d.ts +35 -0
- package/dist/playwright-runtime.d.ts.map +1 -0
- package/dist/playwright-runtime.js +224 -0
- package/dist/runtime-resolution.d.ts +9 -0
- package/dist/runtime-resolution.d.ts.map +1 -0
- package/dist/runtime-resolution.js +19 -0
- package/dist/runtime-state.d.ts +217 -0
- package/dist/runtime-state.d.ts.map +1 -0
- package/dist/runtime-state.js +629 -0
- package/dist/secrets/backend.d.ts +32 -0
- package/dist/secrets/backend.d.ts.map +1 -0
- package/dist/secrets/backend.js +169 -0
- package/dist/secrets/catalog-applicability.d.ts +5 -0
- package/dist/secrets/catalog-applicability.d.ts.map +1 -0
- package/dist/secrets/catalog-applicability.js +59 -0
- package/dist/secrets/catalog-sync.d.ts +14 -0
- package/dist/secrets/catalog-sync.d.ts.map +1 -0
- package/dist/secrets/catalog-sync.js +35 -0
- package/dist/secrets/field-policy.d.ts +3 -0
- package/dist/secrets/field-policy.d.ts.map +1 -0
- package/dist/secrets/field-policy.js +3 -0
- package/dist/secrets/fill-ordering.d.ts +11 -0
- package/dist/secrets/fill-ordering.d.ts.map +1 -0
- package/dist/secrets/fill-ordering.js +44 -0
- package/dist/secrets/form-matcher.d.ts +60 -0
- package/dist/secrets/form-matcher.d.ts.map +1 -0
- package/dist/secrets/form-matcher.js +596 -0
- package/dist/secrets/intent-output.d.ts +11 -0
- package/dist/secrets/intent-output.d.ts.map +1 -0
- package/dist/secrets/intent-output.js +64 -0
- package/dist/secrets/mock-agentpay-backend.d.ts +13 -0
- package/dist/secrets/mock-agentpay-backend.d.ts.map +1 -0
- package/dist/secrets/mock-agentpay-backend.js +87 -0
- package/dist/secrets/mock-agentpay-cabinet.d.ts +43 -0
- package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -0
- package/dist/secrets/mock-agentpay-cabinet.js +195 -0
- package/dist/secrets/protected-artifact-guard.d.ts +25 -0
- package/dist/secrets/protected-artifact-guard.d.ts.map +1 -0
- package/dist/secrets/protected-artifact-guard.js +26 -0
- package/dist/secrets/protected-bindings.d.ts +10 -0
- package/dist/secrets/protected-bindings.d.ts.map +1 -0
- package/dist/secrets/protected-bindings.js +17 -0
- package/dist/secrets/protected-field-values.d.ts +13 -0
- package/dist/secrets/protected-field-values.d.ts.map +1 -0
- package/dist/secrets/protected-field-values.js +100 -0
- package/dist/secrets/protected-fill.d.ts +47 -0
- package/dist/secrets/protected-fill.d.ts.map +1 -0
- package/dist/secrets/protected-fill.js +512 -0
- package/dist/secrets/types.d.ts +84 -0
- package/dist/secrets/types.d.ts.map +1 -0
- package/dist/secrets/types.js +27 -0
- package/dist/session.d.ts +22 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +74 -2
- package/dist/solver/browser-launcher.d.ts.map +1 -1
- package/dist/solver/browser-launcher.js +6 -3
- package/dist/stagehand-runtime.d.ts +4 -0
- package/dist/stagehand-runtime.d.ts.map +1 -0
- package/dist/stagehand-runtime.js +10 -0
- package/dist/stagehand.d.ts +0 -5
- package/dist/stagehand.d.ts.map +1 -1
- package/dist/stagehand.js +0 -6
- package/package.json +5 -2
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { AgentpayStagehandLlmClient } from '../agentpay-stagehand-llm.js';
|
|
3
|
+
import { tryResolveAgentpayGatewayConfig } from '../agentpay-gateway.js';
|
|
4
|
+
import { IDENTITY_FIELD_KEYS, LOGIN_FIELD_KEYS, PAYMENT_CARD_FIELD_KEYS, } from './types.js';
|
|
5
|
+
import { recommendedTimingForProtectedForm } from './fill-ordering.js';
|
|
6
|
+
import { normalizeProtectedBindingValueHint, protectedBindingKey, protectedBindingValueHintSchema, } from './protected-bindings.js';
|
|
7
|
+
const PROMPT_VALUE_MAX_CHARS = 180;
|
|
8
|
+
const PROMPT_SIGNAL_MAX_CHARS = 220;
|
|
9
|
+
const PROMPT_SIGNAL_MAX_VALUES = 8;
|
|
10
|
+
const PAYMENT_CARD_CORE_FIELD_KEYS = new Set([
|
|
11
|
+
'pan',
|
|
12
|
+
'exp_month',
|
|
13
|
+
'exp_year',
|
|
14
|
+
'cvv',
|
|
15
|
+
]);
|
|
16
|
+
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;
|
|
17
|
+
const PAYMENT_CARD_NAME_SIGNAL_RE = /\b(cardholder|card holder|name on card|cardholder name|full name)\b/i;
|
|
18
|
+
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
|
+
const PAYMENT_CARD_CVV_SIGNAL_RE = /\b(security code|cvv|cvc)\b/i;
|
|
21
|
+
const protectedFormPlanSchema = z.object({
|
|
22
|
+
confidence: z.enum(['high', 'medium', 'low']),
|
|
23
|
+
bindings: z
|
|
24
|
+
.array(z.object({
|
|
25
|
+
targetRef: z.string(),
|
|
26
|
+
fieldKey: z.string(),
|
|
27
|
+
valueHint: protectedBindingValueHintSchema.optional(),
|
|
28
|
+
}))
|
|
29
|
+
.max(24),
|
|
30
|
+
});
|
|
31
|
+
function normalizeText(value) {
|
|
32
|
+
return value?.replace(/\s+/g, ' ').trim().toLowerCase() ?? '';
|
|
33
|
+
}
|
|
34
|
+
function compactPromptValue(value, maxChars = PROMPT_VALUE_MAX_CHARS) {
|
|
35
|
+
const normalized = value?.replace(/\s+/g, ' ').trim();
|
|
36
|
+
if (!normalized) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
return normalized.length > maxChars ? `${normalized.slice(0, maxChars - 1)}…` : normalized;
|
|
40
|
+
}
|
|
41
|
+
function isTargetEligibleForProtectedFill(target) {
|
|
42
|
+
if (target.lifecycle !== 'live') {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
if (!allowsProtectedAvailability(target.availability)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return (target.allowedActions.includes('fill') ||
|
|
49
|
+
target.allowedActions.includes('type') ||
|
|
50
|
+
target.allowedActions.includes('select'));
|
|
51
|
+
}
|
|
52
|
+
function allowsProtectedAvailability(availability) {
|
|
53
|
+
return availability?.state === undefined || availability.state === 'available';
|
|
54
|
+
}
|
|
55
|
+
function selectorSignalFragments(selector) {
|
|
56
|
+
const fragments = [];
|
|
57
|
+
for (const match of selector.matchAll(/\[name="([^"]+)"\]/g)) {
|
|
58
|
+
fragments.push(match[1] ?? '');
|
|
59
|
+
}
|
|
60
|
+
for (const match of selector.matchAll(/#([a-zA-Z0-9_-]+)/g)) {
|
|
61
|
+
fragments.push(match[1] ?? '');
|
|
62
|
+
}
|
|
63
|
+
return fragments;
|
|
64
|
+
}
|
|
65
|
+
function signalValuesOf(target) {
|
|
66
|
+
const values = new Set();
|
|
67
|
+
const push = (value) => {
|
|
68
|
+
const normalized = normalizeText(value);
|
|
69
|
+
if (normalized) {
|
|
70
|
+
values.add(normalized.length > PROMPT_SIGNAL_MAX_CHARS
|
|
71
|
+
? `${normalized.slice(0, PROMPT_SIGNAL_MAX_CHARS - 1)}…`
|
|
72
|
+
: normalized);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
push(target.label);
|
|
76
|
+
push(target.displayLabel);
|
|
77
|
+
push(target.kind);
|
|
78
|
+
push(target.semantics?.role);
|
|
79
|
+
push(target.semantics?.name);
|
|
80
|
+
push(target.context?.hintText);
|
|
81
|
+
push(target.context?.group?.label);
|
|
82
|
+
push(target.context?.group?.text);
|
|
83
|
+
push(target.context?.container?.label);
|
|
84
|
+
push(target.context?.container?.text);
|
|
85
|
+
push(target.context?.landmark?.label);
|
|
86
|
+
push(target.context?.landmark?.text);
|
|
87
|
+
for (const candidate of target.locatorCandidates) {
|
|
88
|
+
push(candidate.name);
|
|
89
|
+
push(candidate.value);
|
|
90
|
+
if (candidate.strategy === 'css' || candidate.strategy === 'xpath') {
|
|
91
|
+
for (const fragment of selectorSignalFragments(candidate.value)) {
|
|
92
|
+
push(fragment);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return [...values];
|
|
97
|
+
}
|
|
98
|
+
function localSignalValuesOf(target) {
|
|
99
|
+
const values = new Set();
|
|
100
|
+
const push = (value) => {
|
|
101
|
+
const normalized = normalizeText(value);
|
|
102
|
+
if (normalized) {
|
|
103
|
+
values.add(normalized.length > PROMPT_SIGNAL_MAX_CHARS
|
|
104
|
+
? `${normalized.slice(0, PROMPT_SIGNAL_MAX_CHARS - 1)}…`
|
|
105
|
+
: normalized);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
push(target.label);
|
|
109
|
+
push(target.displayLabel);
|
|
110
|
+
push(target.kind);
|
|
111
|
+
push(target.semantics?.role);
|
|
112
|
+
push(target.semantics?.name);
|
|
113
|
+
push(target.placeholder);
|
|
114
|
+
push(target.inputName);
|
|
115
|
+
push(target.inputType);
|
|
116
|
+
push(target.autocomplete);
|
|
117
|
+
for (const candidate of target.locatorCandidates) {
|
|
118
|
+
push(candidate.name);
|
|
119
|
+
if (candidate.strategy === 'css' || candidate.strategy === 'xpath') {
|
|
120
|
+
push(candidate.value);
|
|
121
|
+
for (const fragment of selectorSignalFragments(candidate.value)) {
|
|
122
|
+
push(fragment);
|
|
123
|
+
}
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (candidate.strategy === 'label' || candidate.strategy === 'placeholder' || candidate.strategy === 'title') {
|
|
127
|
+
push(candidate.value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return [...values];
|
|
131
|
+
}
|
|
132
|
+
function targetLooksLikePaymentCardCore(target) {
|
|
133
|
+
const autocomplete = normalizeText(target.autocomplete);
|
|
134
|
+
const inputName = normalizeText(target.inputName);
|
|
135
|
+
const signals = localSignalValuesOf(target);
|
|
136
|
+
if (autocomplete.includes('cc-number') || autocomplete.includes('cc-exp') || autocomplete.includes('cc-csc')) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
if (signals.some((signal) => PAYMENT_CARD_CORE_SIGNAL_RE.test(signal))) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
return /\b(card(number)?|expiry|exp|cvc|cvv)\b/.test(inputName);
|
|
143
|
+
}
|
|
144
|
+
function targetLooksRelevantToPaymentCard(target) {
|
|
145
|
+
if (targetLooksLikePaymentCardCore(target)) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
const autocomplete = normalizeText(target.autocomplete);
|
|
149
|
+
const inputName = normalizeText(target.inputName);
|
|
150
|
+
const signals = localSignalValuesOf(target);
|
|
151
|
+
if (autocomplete.includes('cc-name')) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
if (PAYMENT_CARD_NAME_SIGNAL_RE.test(normalizeText(target.label))) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
if (signals.some((signal) => PAYMENT_CARD_NAME_SIGNAL_RE.test(signal))) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
return /\b(cardholder|card-holder|cc-name)\b/.test(inputName);
|
|
161
|
+
}
|
|
162
|
+
function deterministicPaymentCardFieldKeysForTarget(target) {
|
|
163
|
+
const autocomplete = normalizeText(target.autocomplete);
|
|
164
|
+
const inputName = normalizeText(target.inputName);
|
|
165
|
+
const signals = localSignalValuesOf(target);
|
|
166
|
+
if (autocomplete.includes('cc-number')) {
|
|
167
|
+
return ['pan'];
|
|
168
|
+
}
|
|
169
|
+
if (autocomplete.includes('cc-exp')) {
|
|
170
|
+
return ['exp_month', 'exp_year'];
|
|
171
|
+
}
|
|
172
|
+
if (autocomplete.includes('cc-csc')) {
|
|
173
|
+
return ['cvv'];
|
|
174
|
+
}
|
|
175
|
+
if (autocomplete.includes('cc-name')) {
|
|
176
|
+
return ['cardholder'];
|
|
177
|
+
}
|
|
178
|
+
if (signals.some((signal) => PAYMENT_CARD_PAN_SIGNAL_RE.test(signal))) {
|
|
179
|
+
return ['pan'];
|
|
180
|
+
}
|
|
181
|
+
if (signals.some((signal) => PAYMENT_CARD_EXP_SIGNAL_RE.test(signal))) {
|
|
182
|
+
return ['exp_month', 'exp_year'];
|
|
183
|
+
}
|
|
184
|
+
if (signals.some((signal) => PAYMENT_CARD_CVV_SIGNAL_RE.test(signal))) {
|
|
185
|
+
return ['cvv'];
|
|
186
|
+
}
|
|
187
|
+
if (signals.some((signal) => PAYMENT_CARD_NAME_SIGNAL_RE.test(signal))) {
|
|
188
|
+
return ['cardholder'];
|
|
189
|
+
}
|
|
190
|
+
if (/\b(card(number)?|cc-?number)\b/.test(inputName)) {
|
|
191
|
+
return ['pan'];
|
|
192
|
+
}
|
|
193
|
+
if (/\b(exp|expiry|expiration)\b/.test(inputName)) {
|
|
194
|
+
return ['exp_month', 'exp_year'];
|
|
195
|
+
}
|
|
196
|
+
if (/\b(cvv|cvc|security)\b/.test(inputName)) {
|
|
197
|
+
return ['cvv'];
|
|
198
|
+
}
|
|
199
|
+
if (/\b(cardholder|card-holder|cc-name)\b/.test(inputName)) {
|
|
200
|
+
return ['cardholder'];
|
|
201
|
+
}
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
204
|
+
function deterministicPaymentCardPlan(plannerGroup, fullGroup) {
|
|
205
|
+
const fieldTargets = new Map();
|
|
206
|
+
for (const target of plannerGroup.targets) {
|
|
207
|
+
for (const fieldKey of deterministicPaymentCardFieldKeysForTarget(target)) {
|
|
208
|
+
const refs = fieldTargets.get(fieldKey) ?? new Set();
|
|
209
|
+
refs.add(target.ref);
|
|
210
|
+
fieldTargets.set(fieldKey, refs);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
for (const fieldKey of PAYMENT_CARD_CORE_FIELD_KEYS) {
|
|
214
|
+
const refs = fieldTargets.get(fieldKey);
|
|
215
|
+
if (!refs || refs.size !== 1) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const bindings = [];
|
|
220
|
+
const targetByRef = new Map(fullGroup.targets.map((target) => [target.ref, target]));
|
|
221
|
+
const seen = new Set();
|
|
222
|
+
const push = (fieldKey, targetRef) => {
|
|
223
|
+
const key = protectedBindingKey({ fieldKey, targetRef, valueHint: 'direct' });
|
|
224
|
+
if (seen.has(key)) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
seen.add(key);
|
|
228
|
+
bindings.push({
|
|
229
|
+
fieldKey,
|
|
230
|
+
targetRef,
|
|
231
|
+
label: targetByRef.get(targetRef)?.displayLabel ?? targetByRef.get(targetRef)?.label,
|
|
232
|
+
valueHint: 'direct',
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
push('pan', [...fieldTargets.get('pan')][0]);
|
|
236
|
+
const expiryTargetRef = [...fieldTargets.get('exp_month')][0];
|
|
237
|
+
push('exp_month', expiryTargetRef);
|
|
238
|
+
push('exp_year', expiryTargetRef);
|
|
239
|
+
push('cvv', [...fieldTargets.get('cvv')][0]);
|
|
240
|
+
const cardholderRefs = fieldTargets.get('cardholder');
|
|
241
|
+
if (cardholderRefs?.size === 1) {
|
|
242
|
+
push('cardholder', [...cardholderRefs][0]);
|
|
243
|
+
}
|
|
244
|
+
const sortedBindings = bindings.sort((left, right) => {
|
|
245
|
+
const leftPriority = canonicalFieldOrder('payment_card').indexOf(left.fieldKey);
|
|
246
|
+
const rightPriority = canonicalFieldOrder('payment_card').indexOf(right.fieldKey);
|
|
247
|
+
if (leftPriority !== rightPriority) {
|
|
248
|
+
return leftPriority - rightPriority;
|
|
249
|
+
}
|
|
250
|
+
return left.targetRef.localeCompare(right.targetRef);
|
|
251
|
+
});
|
|
252
|
+
return {
|
|
253
|
+
confidence: 'high',
|
|
254
|
+
fields: dropSuspiciousIframePaymentCardBindings(sortedBindings, fullGroup, targetByRef),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function plannerGroupForKind(kind, group) {
|
|
258
|
+
switch (kind) {
|
|
259
|
+
case 'payment_card': {
|
|
260
|
+
const relevantTargets = group.targets.filter((target) => targetLooksRelevantToPaymentCard(target));
|
|
261
|
+
if (relevantTargets.length === 0) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const hasCore = relevantTargets.some((target) => targetLooksLikePaymentCardCore(target));
|
|
265
|
+
if (!hasCore) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
groupKey: group.groupKey,
|
|
270
|
+
targets: relevantTargets,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
default:
|
|
274
|
+
return group;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function formGroupKeyOf(target) {
|
|
278
|
+
for (const node of [
|
|
279
|
+
target.context?.landmark,
|
|
280
|
+
target.context?.container,
|
|
281
|
+
target.context?.group,
|
|
282
|
+
target.context?.item,
|
|
283
|
+
]) {
|
|
284
|
+
if (normalizeText(node?.kind) !== 'form') {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
const label = normalizeText(node?.label ?? node?.text);
|
|
288
|
+
return label ? `form:${label}` : `form:${target.pageRef}`;
|
|
289
|
+
}
|
|
290
|
+
return `page:${target.pageRef}`;
|
|
291
|
+
}
|
|
292
|
+
function groupTargetsByForm(targets) {
|
|
293
|
+
const groups = new Map();
|
|
294
|
+
for (const target of targets) {
|
|
295
|
+
if (!isTargetEligibleForProtectedFill(target)) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const groupKey = formGroupKeyOf(target);
|
|
299
|
+
const group = groups.get(groupKey) ?? [];
|
|
300
|
+
group.push(target);
|
|
301
|
+
groups.set(groupKey, group);
|
|
302
|
+
}
|
|
303
|
+
return [...groups.entries()].map(([groupKey, groupTargets]) => ({
|
|
304
|
+
groupKey,
|
|
305
|
+
targets: groupTargets,
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
function canonicalFieldOrder(kind) {
|
|
309
|
+
switch (kind) {
|
|
310
|
+
case 'login':
|
|
311
|
+
return LOGIN_FIELD_KEYS;
|
|
312
|
+
case 'identity':
|
|
313
|
+
return IDENTITY_FIELD_KEYS;
|
|
314
|
+
case 'payment_card':
|
|
315
|
+
return PAYMENT_CARD_FIELD_KEYS;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function purposePrompt(kind) {
|
|
319
|
+
switch (kind) {
|
|
320
|
+
case 'login':
|
|
321
|
+
return [
|
|
322
|
+
'Purpose: login form.',
|
|
323
|
+
'Expected canonical fields: username, password.',
|
|
324
|
+
'Match email/login/account fields to username when clearly used for sign-in.',
|
|
325
|
+
'Do not invent additional fields.',
|
|
326
|
+
].join('\n');
|
|
327
|
+
case 'identity':
|
|
328
|
+
return [
|
|
329
|
+
'Purpose: identity or traveler details form.',
|
|
330
|
+
'Expected canonical fields: full_name, document_number, date_of_birth, nationality, issue_date, expiry_date, issuing_country.',
|
|
331
|
+
'full_name may be one direct full-name field or two split fields:',
|
|
332
|
+
'- First/Given name -> fieldKey=full_name, valueHint=full_name.given',
|
|
333
|
+
'- Last/Family/Surname -> fieldKey=full_name, valueHint=full_name.family',
|
|
334
|
+
'Do not confuse contact fields like email, phone, address, city, country/region with identity fields.',
|
|
335
|
+
'Do not treat generic contact-only forms as identity forms.',
|
|
336
|
+
].join('\n');
|
|
337
|
+
case 'payment_card':
|
|
338
|
+
return [
|
|
339
|
+
'Purpose: payment card form.',
|
|
340
|
+
'Expected canonical fields: cardholder, pan, exp_month, exp_year, cvv.',
|
|
341
|
+
'A single expiry field may map to both exp_month and exp_year.',
|
|
342
|
+
'Do not confuse promo codes or billing ZIP/postcode with card data.',
|
|
343
|
+
].join('\n');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function buildTargetSummary(target) {
|
|
347
|
+
const parts = [`targetRef=${JSON.stringify(target.ref)}`];
|
|
348
|
+
const push = (key, value) => {
|
|
349
|
+
const compact = compactPromptValue(value);
|
|
350
|
+
if (compact) {
|
|
351
|
+
parts.push(`${key}=${JSON.stringify(compact)}`);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
if (target.kind)
|
|
355
|
+
parts.push(`kind=${JSON.stringify(target.kind)}`);
|
|
356
|
+
push('label', target.label);
|
|
357
|
+
push('displayLabel', target.displayLabel);
|
|
358
|
+
push('role', target.semantics?.role);
|
|
359
|
+
push('semanticsName', target.semantics?.name);
|
|
360
|
+
push('hintText', target.context?.hintText);
|
|
361
|
+
push('groupLabel', target.context?.group?.label);
|
|
362
|
+
push('groupText', target.context?.group?.text);
|
|
363
|
+
if (target.context?.container?.label) {
|
|
364
|
+
push('containerLabel', target.context.container.label);
|
|
365
|
+
}
|
|
366
|
+
if (target.context?.container?.text) {
|
|
367
|
+
push('containerText', target.context.container.text);
|
|
368
|
+
}
|
|
369
|
+
if (target.context?.landmark?.label) {
|
|
370
|
+
push('landmarkLabel', target.context.landmark.label);
|
|
371
|
+
}
|
|
372
|
+
if (target.allowedActions.length > 0) {
|
|
373
|
+
parts.push(`allowedActions=${JSON.stringify(target.allowedActions)}`);
|
|
374
|
+
}
|
|
375
|
+
if (target.controlFamily) {
|
|
376
|
+
parts.push(`controlFamily=${JSON.stringify(target.controlFamily)}`);
|
|
377
|
+
}
|
|
378
|
+
const signals = signalValuesOf(target);
|
|
379
|
+
if (signals.length > 0) {
|
|
380
|
+
parts.push(`signals=${JSON.stringify(signals.slice(0, PROMPT_SIGNAL_MAX_VALUES))}`);
|
|
381
|
+
}
|
|
382
|
+
return parts.join(' | ');
|
|
383
|
+
}
|
|
384
|
+
function buildMatcherPrompt(kind, group) {
|
|
385
|
+
return [
|
|
386
|
+
'You are matching protected form fields from an already discovered deterministic DOM inventory.',
|
|
387
|
+
'Return only bindings that are clearly supported by the visible field labels, placeholders, context, and locator-derived signals.',
|
|
388
|
+
'Fail closed. If the form is ambiguous, return low confidence with no bindings.',
|
|
389
|
+
'Use only the provided targetRef values.',
|
|
390
|
+
'For direct matches, omit valueHint or use valueHint=direct.',
|
|
391
|
+
purposePrompt(kind),
|
|
392
|
+
'',
|
|
393
|
+
`Form group key: ${group.groupKey}`,
|
|
394
|
+
'Targets:',
|
|
395
|
+
...group.targets.map((target) => buildTargetSummary(target)),
|
|
396
|
+
].join('\n');
|
|
397
|
+
}
|
|
398
|
+
function sanitizeBindings(kind, group, bindings) {
|
|
399
|
+
const allowedFieldKeys = new Set(canonicalFieldOrder(kind));
|
|
400
|
+
const allowedTargetRefs = new Set(group.targets.map((target) => target.ref));
|
|
401
|
+
const uniqueBindings = new Map();
|
|
402
|
+
const targetByRef = new Map(group.targets.map((target) => [target.ref, target]));
|
|
403
|
+
for (const binding of bindings) {
|
|
404
|
+
if (!allowedTargetRefs.has(binding.targetRef)) {
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
if (!allowedFieldKeys.has(binding.fieldKey)) {
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
const fieldKey = binding.fieldKey;
|
|
411
|
+
const normalizedValueHint = normalizeProtectedBindingValueHint(fieldKey, binding.valueHint);
|
|
412
|
+
const key = protectedBindingKey({
|
|
413
|
+
fieldKey,
|
|
414
|
+
targetRef: binding.targetRef,
|
|
415
|
+
valueHint: normalizedValueHint,
|
|
416
|
+
});
|
|
417
|
+
if (uniqueBindings.has(key)) {
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
uniqueBindings.set(key, {
|
|
421
|
+
fieldKey,
|
|
422
|
+
targetRef: binding.targetRef,
|
|
423
|
+
label: targetByRef.get(binding.targetRef)?.displayLabel ?? targetByRef.get(binding.targetRef)?.label,
|
|
424
|
+
valueHint: normalizedValueHint,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
return [...uniqueBindings.values()].sort((left, right) => {
|
|
428
|
+
const leftPriority = canonicalFieldOrder(kind).indexOf(left.fieldKey);
|
|
429
|
+
const rightPriority = canonicalFieldOrder(kind).indexOf(right.fieldKey);
|
|
430
|
+
if (leftPriority !== rightPriority) {
|
|
431
|
+
return leftPriority - rightPriority;
|
|
432
|
+
}
|
|
433
|
+
return left.targetRef.localeCompare(right.targetRef);
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
function isCredibleKindMatch(_kind, fieldBindings) {
|
|
437
|
+
return fieldBindings.length > 0;
|
|
438
|
+
}
|
|
439
|
+
function frameKeyOf(target) {
|
|
440
|
+
if (!target.framePath || target.framePath.length === 0) {
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
return target.framePath.join('>');
|
|
444
|
+
}
|
|
445
|
+
function targetLooksLikeIframeEnrollmentField(target) {
|
|
446
|
+
const inputType = normalizeText(target.inputType);
|
|
447
|
+
const autocomplete = normalizeText(target.autocomplete);
|
|
448
|
+
const signals = signalValuesOf(target);
|
|
449
|
+
if (inputType === 'email' || autocomplete.includes('email')) {
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
452
|
+
if (inputType === 'tel' ||
|
|
453
|
+
autocomplete.includes('tel') ||
|
|
454
|
+
signals.some((signal) => /\b(phone|mobile|telephone|tel)\b/.test(signal))) {
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
function dropSuspiciousIframePaymentCardBindings(fields, group, targetByRef) {
|
|
460
|
+
const iframeEnrollmentFrames = new Set();
|
|
461
|
+
for (const target of group.targets) {
|
|
462
|
+
const frameKey = frameKeyOf(target);
|
|
463
|
+
if (!frameKey) {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
if (targetLooksLikeIframeEnrollmentField(target)) {
|
|
467
|
+
iframeEnrollmentFrames.add(frameKey);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
if (iframeEnrollmentFrames.size === 0) {
|
|
471
|
+
return [...fields];
|
|
472
|
+
}
|
|
473
|
+
return fields.filter((field) => {
|
|
474
|
+
if (PAYMENT_CARD_CORE_FIELD_KEYS.has(field.fieldKey)) {
|
|
475
|
+
return true;
|
|
476
|
+
}
|
|
477
|
+
if (field.fieldKey !== 'cardholder') {
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
const target = targetByRef.get(field.targetRef);
|
|
481
|
+
const frameKey = target ? frameKeyOf(target) : null;
|
|
482
|
+
if (!frameKey) {
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
return !iframeEnrollmentFrames.has(frameKey);
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
function formScopeRef(fields, targetByRef) {
|
|
489
|
+
const surfaceRefs = new Set();
|
|
490
|
+
for (const field of fields) {
|
|
491
|
+
const surfaceRef = targetByRef.get(field.targetRef)?.surfaceRef;
|
|
492
|
+
if (surfaceRef) {
|
|
493
|
+
surfaceRefs.add(surfaceRef);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return surfaceRefs.size === 1 ? [...surfaceRefs][0] : undefined;
|
|
497
|
+
}
|
|
498
|
+
function buildStoredSecretCandidates(catalog, kind, confidence, matchedFieldKeys) {
|
|
499
|
+
return catalog.storedSecrets
|
|
500
|
+
.filter((secret) => secret.kind === kind && secret.fieldKeys.some((fieldKey) => matchedFieldKeys.has(fieldKey)))
|
|
501
|
+
.map((secret) => ({
|
|
502
|
+
storedSecretRef: secret.storedSecretRef,
|
|
503
|
+
kind: secret.kind,
|
|
504
|
+
scope: secret.scope,
|
|
505
|
+
displayName: secret.displayName,
|
|
506
|
+
matchConfidence: confidence,
|
|
507
|
+
intentRequired: secret.intentRequired,
|
|
508
|
+
fieldKeys: [...secret.fieldKeys],
|
|
509
|
+
fieldPolicies: secret.fieldPolicies ? { ...secret.fieldPolicies } : undefined,
|
|
510
|
+
}));
|
|
511
|
+
}
|
|
512
|
+
function hasApplicableStoredSecretKind(catalog, kind) {
|
|
513
|
+
return catalog.storedSecrets.some((secret) => secret.kind === kind);
|
|
514
|
+
}
|
|
515
|
+
function purposesByPriority(catalog) {
|
|
516
|
+
const orderedKinds = ['login', 'identity', 'payment_card'];
|
|
517
|
+
return orderedKinds.filter((kind) => hasApplicableStoredSecretKind(catalog, kind));
|
|
518
|
+
}
|
|
519
|
+
async function planBindingsForGroup(client, kind, group) {
|
|
520
|
+
const plannerGroup = plannerGroupForKind(kind, group);
|
|
521
|
+
if (!plannerGroup) {
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
if (kind === 'payment_card') {
|
|
525
|
+
const deterministicPlan = deterministicPaymentCardPlan(plannerGroup, group);
|
|
526
|
+
if (deterministicPlan) {
|
|
527
|
+
return deterministicPlan;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
const result = await client.createChatCompletion({
|
|
531
|
+
logger: () => { },
|
|
532
|
+
options: {
|
|
533
|
+
messages: [{ role: 'user', content: buildMatcherPrompt(kind, plannerGroup) }],
|
|
534
|
+
response_model: {
|
|
535
|
+
name: 'ProtectedFormPlan',
|
|
536
|
+
schema: protectedFormPlanSchema,
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
});
|
|
540
|
+
return {
|
|
541
|
+
confidence: result.data.confidence,
|
|
542
|
+
fields: kind === 'payment_card'
|
|
543
|
+
? dropSuspiciousIframePaymentCardBindings(sanitizeBindings(kind, plannerGroup, result.data.bindings), group, new Map(group.targets.map((target) => [target.ref, target])))
|
|
544
|
+
: sanitizeBindings(kind, plannerGroup, result.data.bindings),
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
export async function matchStoredSecretsToObservedTargets(pageRef, targets, catalog, options = {}) {
|
|
548
|
+
if (!catalog) {
|
|
549
|
+
return [];
|
|
550
|
+
}
|
|
551
|
+
const gateway = options.gatewayConfig === undefined
|
|
552
|
+
? tryResolveAgentpayGatewayConfig()
|
|
553
|
+
: options.gatewayConfig;
|
|
554
|
+
if (!gateway) {
|
|
555
|
+
return [];
|
|
556
|
+
}
|
|
557
|
+
const client = new AgentpayStagehandLlmClient(gateway);
|
|
558
|
+
const targetByRef = new Map(targets.map((target) => [target.ref, target]));
|
|
559
|
+
const groups = groupTargetsByForm(targets);
|
|
560
|
+
const nextObservedAt = options.observedAt ?? new Date().toISOString();
|
|
561
|
+
const forms = [];
|
|
562
|
+
for (const group of groups) {
|
|
563
|
+
for (const kind of purposesByPriority(catalog)) {
|
|
564
|
+
const planned = await planBindingsForGroup(client, kind, group).catch(() => null);
|
|
565
|
+
if (!planned || planned.confidence === 'low') {
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
if (!isCredibleKindMatch(kind, planned.fields)) {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
const matchedFieldKeys = new Set(planned.fields.map((field) => field.fieldKey));
|
|
572
|
+
const storedSecretCandidates = buildStoredSecretCandidates(catalog, kind, planned.confidence, matchedFieldKeys);
|
|
573
|
+
if (storedSecretCandidates.length === 0) {
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
forms.push({
|
|
577
|
+
pageRef,
|
|
578
|
+
scopeRef: formScopeRef(planned.fields, targetByRef),
|
|
579
|
+
purpose: kind,
|
|
580
|
+
recommendedTiming: recommendedTimingForProtectedForm(kind),
|
|
581
|
+
fields: planned.fields,
|
|
582
|
+
storedSecretCandidates,
|
|
583
|
+
observedAt: nextObservedAt,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return forms;
|
|
588
|
+
}
|
|
589
|
+
export const __testFormMatcher = {
|
|
590
|
+
buildMatcherPrompt,
|
|
591
|
+
formGroupKeyOf,
|
|
592
|
+
groupTargetsByForm,
|
|
593
|
+
sanitizeBindings,
|
|
594
|
+
selectorSignalFragments,
|
|
595
|
+
signalValuesOf,
|
|
596
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
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;
|
|
11
|
+
//# sourceMappingURL=intent-output.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export function serializeSecretIntent(snapshot) {
|
|
2
|
+
return {
|
|
3
|
+
intentId: snapshot.intentId,
|
|
4
|
+
fillRef: snapshot.fillRef,
|
|
5
|
+
storedSecretRef: snapshot.storedSecretRef,
|
|
6
|
+
status: snapshot.status,
|
|
7
|
+
...(snapshot.approvalChannel ? { approvalChannel: snapshot.approvalChannel } : {}),
|
|
8
|
+
createdAt: snapshot.createdAt,
|
|
9
|
+
...(snapshot.expiresAt ? { expiresAt: snapshot.expiresAt } : {}),
|
|
10
|
+
...(snapshot.approvedAt ? { approvedAt: snapshot.approvedAt } : {}),
|
|
11
|
+
...(snapshot.completedAt ? { completedAt: snapshot.completedAt } : {}),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function serializeSecretIntentContext(snapshot) {
|
|
15
|
+
return {
|
|
16
|
+
storedSecretRef: snapshot.storedSecretRef,
|
|
17
|
+
...(snapshot.approvalChannel ? { approvalChannel: snapshot.approvalChannel } : {}),
|
|
18
|
+
createdAt: snapshot.createdAt,
|
|
19
|
+
...(snapshot.expiresAt ? { expiresAt: snapshot.expiresAt } : {}),
|
|
20
|
+
...(snapshot.approvedAt ? { approvedAt: snapshot.approvedAt } : {}),
|
|
21
|
+
...(snapshot.completedAt ? { completedAt: snapshot.completedAt } : {}),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function describeSecretIntentStatus(status) {
|
|
25
|
+
switch (status) {
|
|
26
|
+
case 'pending':
|
|
27
|
+
case 'checking':
|
|
28
|
+
case 'notify':
|
|
29
|
+
case 'confirmation':
|
|
30
|
+
return {
|
|
31
|
+
outcomeType: 'approval_pending',
|
|
32
|
+
message: 'Protected intent is waiting for user approval.',
|
|
33
|
+
reason: 'AgentPay Cabinet has not approved this intent yet.',
|
|
34
|
+
nextAction: 'wait-for-approval',
|
|
35
|
+
};
|
|
36
|
+
case 'approved':
|
|
37
|
+
return {
|
|
38
|
+
message: 'Protected intent is approved and waiting for one-time delivery polling.',
|
|
39
|
+
reason: 'AgentPay approved this protected request, but AgentBrowse must poll again to receive the one-time secret payload.',
|
|
40
|
+
nextAction: 'poll-intent',
|
|
41
|
+
};
|
|
42
|
+
case 'denied':
|
|
43
|
+
return {
|
|
44
|
+
outcomeType: 'approval_denied',
|
|
45
|
+
message: 'Protected intent was denied and cannot be used.',
|
|
46
|
+
reason: 'AgentPay Cabinet reports that the user denied this protected action.',
|
|
47
|
+
nextAction: 'ask-user',
|
|
48
|
+
};
|
|
49
|
+
case 'timed_out':
|
|
50
|
+
return {
|
|
51
|
+
outcomeType: 'intent_expired',
|
|
52
|
+
message: 'Protected intent is no longer usable.',
|
|
53
|
+
reason: 'AgentPay Cabinet reports that this intent timed out before it could be used.',
|
|
54
|
+
nextAction: 'ask-user',
|
|
55
|
+
};
|
|
56
|
+
case 'completed':
|
|
57
|
+
return {
|
|
58
|
+
outcomeType: 'intent_expired',
|
|
59
|
+
message: 'Protected intent is no longer reusable.',
|
|
60
|
+
reason: 'AgentPay reports that this intent already completed, so any further protected action requires a new intent.',
|
|
61
|
+
nextAction: 'ask-user',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type SecretCatalogSnapshot, type StoredSecretMetadata } from './types.js';
|
|
2
|
+
export declare function setMockSecretStorePathForTests(storePath?: string): void;
|
|
3
|
+
export declare function normalizeMerchantKey(value: string): string;
|
|
4
|
+
export declare function resolveHostFromInput(value: string): string;
|
|
5
|
+
export declare function listMockStoredSecretsForHost(hostOrUrl: string, options?: {
|
|
6
|
+
merchantKey?: string;
|
|
7
|
+
}): StoredSecretMetadata[];
|
|
8
|
+
export declare function syncMockSecretCatalog(hostOrUrl: string, options?: {
|
|
9
|
+
merchantKey?: string;
|
|
10
|
+
syncedAt?: string;
|
|
11
|
+
}): SecretCatalogSnapshot;
|
|
12
|
+
export declare function resolveMockStoredSecretValues(storedSecretRef: string): Record<string, string> | null;
|
|
13
|
+
//# sourceMappingURL=mock-agentpay-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-agentpay-backend.d.ts","sourceRoot":"","sources":["../../src/secrets/mock-agentpay-backend.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,YAAY,CAAC;AAapB,wBAAgB,8BAA8B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAEvE;AAYD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAe1D;AAuBD,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;CACjB,GACL,oBAAoB,EAAE,CAexB;AAED,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,GACL,qBAAqB,CAWvB;AAED,wBAAgB,6BAA6B,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CASpG"}
|