@nuanu-ai/agentbrowse 0.2.30 → 0.2.31
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/dist/commands/extract-snapshot-sanitizer.d.ts +3 -0
- package/dist/commands/extract-snapshot-sanitizer.d.ts.map +1 -1
- package/dist/commands/extract-snapshot-sanitizer.js +33 -0
- package/dist/commands/extract-stagehand-executor.d.ts.map +1 -1
- package/dist/commands/extract-stagehand-executor.js +84 -20
- package/dist/commands/observe-inventory.d.ts +10 -0
- package/dist/commands/observe-inventory.d.ts.map +1 -1
- package/dist/commands/observe-inventory.js +388 -1
- package/dist/commands/observe.d.ts +1 -0
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +1 -1
- package/dist/commands/observe.test-harness.d.ts +1 -0
- package/dist/commands/observe.test-harness.d.ts.map +1 -1
- package/dist/commands/semantic-observe.d.ts +4 -1
- package/dist/commands/semantic-observe.d.ts.map +1 -1
- package/dist/commands/semantic-observe.js +187 -88
- package/dist/runtime-state.d.ts +47 -1
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +88 -2
- package/dist/secrets/protected-field-values.d.ts +2 -0
- package/dist/secrets/protected-field-values.d.ts.map +1 -1
- package/dist/secrets/protected-field-values.js +50 -17
- package/dist/secrets/protected-fill.d.ts.map +1 -1
- package/dist/secrets/protected-fill.js +6 -0
- package/dist/secrets/protected-value-adapters.d.ts +3 -0
- package/dist/secrets/protected-value-adapters.d.ts.map +1 -0
- package/dist/secrets/protected-value-adapters.js +39 -0
- package/package.json +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { AgentpayStagehandLlmClient } from '../agentpay-stagehand-llm.js';
|
|
3
3
|
import { tryResolveAgentpayGatewayConfig } from '../agentpay-gateway.js';
|
|
4
|
+
import { recordLlmUsage, recordPayloadBudget } from '../runtime-state.js';
|
|
4
5
|
import { resolveProtectedFieldPolicy } from './field-policy.js';
|
|
6
|
+
import { resolveDeterministicProtectedBindingValue } from './protected-value-adapters.js';
|
|
5
7
|
import { protectedBindingKey, protectedBindingValueHintSchema } from './protected-bindings.js';
|
|
6
8
|
const protectedFieldValuesSchema = z.object({
|
|
7
9
|
values: z
|
|
@@ -22,31 +24,56 @@ function buildBindingSummary(binding, target) {
|
|
|
22
24
|
];
|
|
23
25
|
if (target?.label)
|
|
24
26
|
parts.push(`label=${JSON.stringify(target.label)}`);
|
|
25
|
-
if (target?.
|
|
26
|
-
parts.push(`
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
parts.push(`role=${JSON.stringify(target.semantics.role)}`);
|
|
31
|
-
if (target?.controlFamily)
|
|
32
|
-
parts.push(`controlFamily=${JSON.stringify(target.controlFamily)}`);
|
|
33
|
-
if (target?.context?.hintText)
|
|
34
|
-
parts.push(`hintText=${JSON.stringify(target.context.hintText)}`);
|
|
35
|
-
if (target?.context?.group?.label) {
|
|
36
|
-
parts.push(`groupLabel=${JSON.stringify(target.context.group.label)}`);
|
|
27
|
+
if (target?.kind || target?.semantics?.role) {
|
|
28
|
+
parts.push(`control=${JSON.stringify({
|
|
29
|
+
kind: target?.kind,
|
|
30
|
+
role: target?.semantics?.role,
|
|
31
|
+
})}`);
|
|
37
32
|
}
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
const ownerLabel = target?.context?.container?.label ?? target?.context?.group?.label ?? target?.displayLabel;
|
|
34
|
+
if (ownerLabel) {
|
|
35
|
+
parts.push(`owner=${JSON.stringify(ownerLabel)}`);
|
|
40
36
|
}
|
|
41
37
|
return parts.join(' | ');
|
|
42
38
|
}
|
|
39
|
+
function canUseDeterministicValueForPolicy(binding, fieldPolicies) {
|
|
40
|
+
const policy = resolveProtectedFieldPolicy(fieldPolicies, binding.fieldKey);
|
|
41
|
+
if (policy !== 'llm_assisted') {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return (binding.valueHint ?? 'direct') !== 'direct';
|
|
45
|
+
}
|
|
43
46
|
export async function resolveAssistedProtectedFieldValues(params) {
|
|
44
47
|
const assistedBindings = params.bindings.filter(({ binding }) => {
|
|
45
48
|
return resolveProtectedFieldPolicy(params.fieldPolicies, binding.fieldKey) === 'llm_assisted';
|
|
46
49
|
});
|
|
50
|
+
if (params.session) {
|
|
51
|
+
recordPayloadBudget(params.session, {
|
|
52
|
+
protectedBindingsSeen: params.bindings.length,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
47
55
|
if (assistedBindings.length === 0) {
|
|
48
56
|
return new Map();
|
|
49
57
|
}
|
|
58
|
+
const resolvedValues = new Map();
|
|
59
|
+
const unresolvedBindings = assistedBindings.filter(({ binding }) => {
|
|
60
|
+
const deterministicValue = resolveDeterministicProtectedBindingValue(binding, params.protectedValues);
|
|
61
|
+
if (typeof deterministicValue !== 'string' ||
|
|
62
|
+
deterministicValue.trim().length === 0 ||
|
|
63
|
+
!canUseDeterministicValueForPolicy(binding, params.fieldPolicies)) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
resolvedValues.set(protectedBindingKey(binding), deterministicValue.trim());
|
|
67
|
+
return false;
|
|
68
|
+
});
|
|
69
|
+
if (params.session) {
|
|
70
|
+
recordPayloadBudget(params.session, {
|
|
71
|
+
protectedBindingsSent: unresolvedBindings.length,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (unresolvedBindings.length === 0) {
|
|
75
|
+
return resolvedValues;
|
|
76
|
+
}
|
|
50
77
|
const gateway = tryResolveAgentpayGatewayConfig();
|
|
51
78
|
if (!gateway) {
|
|
52
79
|
throw new Error('protected_field_value_resolver_gateway_missing');
|
|
@@ -68,7 +95,7 @@ export async function resolveAssistedProtectedFieldValues(params) {
|
|
|
68
95
|
'',
|
|
69
96
|
`pageLocale=${JSON.stringify(pageLocale)}`,
|
|
70
97
|
'Bindings:',
|
|
71
|
-
...
|
|
98
|
+
...unresolvedBindings.map(({ binding, target }) => {
|
|
72
99
|
const storedValue = params.protectedValues[binding.fieldKey] ?? '';
|
|
73
100
|
return `${buildBindingSummary(binding, target)} | storedValue=${JSON.stringify(storedValue)}`;
|
|
74
101
|
}),
|
|
@@ -83,8 +110,14 @@ export async function resolveAssistedProtectedFieldValues(params) {
|
|
|
83
110
|
},
|
|
84
111
|
},
|
|
85
112
|
});
|
|
86
|
-
|
|
87
|
-
|
|
113
|
+
if (params.session) {
|
|
114
|
+
recordLlmUsage(params.session, {
|
|
115
|
+
purpose: 'browse.protected_fill.resolve',
|
|
116
|
+
usage: result.usage,
|
|
117
|
+
inputChars: prompt.length,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
const allowedKeys = new Set(unresolvedBindings.map(({ binding }) => protectedBindingKey(binding)));
|
|
88
121
|
for (const entry of result.data.values) {
|
|
89
122
|
const key = protectedBindingKey(entry);
|
|
90
123
|
if (!allowedKeys.has(key) || entry.confidence === 'low') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protected-fill.d.ts","sourceRoot":"","sources":["../../src/secrets/protected-fill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAyB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"protected-fill.d.ts","sourceRoot":"","sources":["../../src/secrets/protected-fill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAyB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAqBnF,OAAO,KAAK,EAEV,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAGpB,KAAK,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAoB,SAAQ,oBAAoB;IAC/D,MAAM,EAAE,4BAA4B,GAAG,mBAAmB,CAAC;IAC3D,sBAAsB,CAAC,EAAE,IAAI,CAAC;CAC/B;AAED,KAAK,2BAA2B,GAC5B,gBAAgB,GAChB,iBAAiB,GACjB,yBAAyB,GACzB,wBAAwB,GACxB,2BAA2B,GAC3B,gBAAgB,CAAC;AAarB,MAAM,MAAM,4BAA4B,GACpC;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,YAAY,EAAE,oBAAoB,EAAE,CAAC;CACtC,GACD;IACE,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,MAAM,EAAE,2BAA2B,CAAC;IACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,GACD;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,YAAY,EAAE,oBAAoB,EAAE,CAAC;IACrC,WAAW,EAAE,mBAAmB,EAAE,CAAC;CACpC,GACD;IACE,IAAI,EAAE,kBAAkB,CAAC;IACzB,MAAM,EACF,yBAAyB,GACzB,mCAAmC,GACnC,sCAAsC,GACtC,kCAAkC,GAClC,eAAe,CAAC;CACrB,CAAC;AAoIN,iBAAS,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,mBAAmB,CActE;AAED,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAK7D;AA2VD,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,aAAa,CAAC;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,YAAY,EAAE,qBAAqB,CAAC;IACpC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,aAAa,CAAC,EAAE,yBAAyB,CAAC;CAC3C,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA6KxC;AAED,eAAO,MAAM,mBAAmB;;;qCAIjB,aAAa,CAAC,oBAAoB,CAAC,mBAC7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAY1C,CAAC"}
|
|
@@ -7,6 +7,7 @@ import { resolveSurfaceScopeRoot } from '../commands/target-resolution.js';
|
|
|
7
7
|
import { resolveProtectedFieldPolicy } from './field-policy.js';
|
|
8
8
|
import { protectedBindingKey } from './protected-bindings.js';
|
|
9
9
|
import { resolveAssistedProtectedFieldValues } from './protected-field-values.js';
|
|
10
|
+
import { resolveDeterministicProtectedBindingValue } from './protected-value-adapters.js';
|
|
10
11
|
import { sortProtectedBindingsForExecution } from './fill-ordering.js';
|
|
11
12
|
function targetUsesSurfaceAsPrimaryLocator(target, surface) {
|
|
12
13
|
const surfaceCandidateKeys = new Set(surface.locatorCandidates.map((candidate) => [
|
|
@@ -116,6 +117,7 @@ function resolveBindingValue(fields, protectedValues, fieldPolicies, assistedVal
|
|
|
116
117
|
if (fields.length === 1) {
|
|
117
118
|
const field = fields[0];
|
|
118
119
|
const policy = resolveProtectedFieldPolicy(fieldPolicies, field.fieldKey);
|
|
120
|
+
const deterministicValue = resolveDeterministicProtectedBindingValue(field, protectedValues);
|
|
119
121
|
if (policy === 'llm_assisted') {
|
|
120
122
|
const assistedValue = assistedValues.get(protectedBindingKey(field));
|
|
121
123
|
if (typeof assistedValue === 'string' && assistedValue.length > 0) {
|
|
@@ -123,6 +125,9 @@ function resolveBindingValue(fields, protectedValues, fieldPolicies, assistedVal
|
|
|
123
125
|
}
|
|
124
126
|
throw new Error('assisted_value_resolution_failed');
|
|
125
127
|
}
|
|
128
|
+
if (typeof deterministicValue === 'string' && deterministicValue.length > 0) {
|
|
129
|
+
return deterministicValue;
|
|
130
|
+
}
|
|
126
131
|
if ((field.valueHint ?? 'direct') !== 'direct') {
|
|
127
132
|
throw new Error('deterministic_only_resolution_failed');
|
|
128
133
|
}
|
|
@@ -371,6 +376,7 @@ export async function executeProtectedFill(params) {
|
|
|
371
376
|
let assistedValues;
|
|
372
377
|
try {
|
|
373
378
|
assistedValues = await resolveAssistedProtectedFieldValues({
|
|
379
|
+
session: params.session,
|
|
374
380
|
page: params.page,
|
|
375
381
|
bindings: preparedBindings.map((binding) => ({
|
|
376
382
|
binding: binding.fields[0],
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { FillableFormFieldBinding } from './types.js';
|
|
2
|
+
export declare function resolveDeterministicProtectedBindingValue(binding: Pick<FillableFormFieldBinding, 'fieldKey' | 'valueHint'>, protectedValues: Record<string, string>): string | null;
|
|
3
|
+
//# sourceMappingURL=protected-value-adapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protected-value-adapters.d.ts","sourceRoot":"","sources":["../../src/secrets/protected-value-adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAwB,MAAM,YAAY,CAAC;AAqBjF,wBAAgB,yCAAyC,CACvD,OAAO,EAAE,IAAI,CAAC,wBAAwB,EAAE,UAAU,GAAG,WAAW,CAAC,EACjE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,MAAM,GAAG,IAAI,CA+Bf"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function normalizeWhitespace(value) {
|
|
2
|
+
return value.replace(/\s+/g, ' ').trim();
|
|
3
|
+
}
|
|
4
|
+
function splitFullName(value) {
|
|
5
|
+
return normalizeWhitespace(value)
|
|
6
|
+
.split(' ')
|
|
7
|
+
.map((part) => part.trim())
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
}
|
|
10
|
+
function directStoredValue(protectedValues, fieldKey) {
|
|
11
|
+
const value = protectedValues[fieldKey];
|
|
12
|
+
return typeof value === 'string' && value.trim().length > 0 ? value : null;
|
|
13
|
+
}
|
|
14
|
+
export function resolveDeterministicProtectedBindingValue(binding, protectedValues) {
|
|
15
|
+
if (binding.fieldKey !== 'full_name') {
|
|
16
|
+
return binding.valueHint === 'direct'
|
|
17
|
+
? directStoredValue(protectedValues, binding.fieldKey)
|
|
18
|
+
: null;
|
|
19
|
+
}
|
|
20
|
+
const fullName = directStoredValue(protectedValues, 'full_name');
|
|
21
|
+
if (!fullName) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const valueHint = binding.valueHint ?? 'direct';
|
|
25
|
+
if (valueHint === 'direct') {
|
|
26
|
+
return fullName;
|
|
27
|
+
}
|
|
28
|
+
const parts = splitFullName(fullName);
|
|
29
|
+
if (parts.length === 0) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
if (valueHint === 'full_name.given') {
|
|
33
|
+
return parts[0] ?? fullName;
|
|
34
|
+
}
|
|
35
|
+
if (valueHint === 'full_name.family') {
|
|
36
|
+
return parts.length > 1 ? (parts.at(-1) ?? fullName) : fullName;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuanu-ai/agentbrowse",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Browser automation CLI for AI agents: control a CDP browser, observe UI surfaces, act on refs, extract data, capture screenshots, complete protected fills, and solve captchas",
|
|
6
6
|
"keywords": [
|