@nuanu-ai/agentbrowse 0.2.29 → 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/README.md +3 -0
- 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 +7 -1
- package/dist/commands/semantic-observe.d.ts.map +1 -1
- package/dist/commands/semantic-observe.js +609 -83
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- 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/dist/update-check.d.ts +14 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +182 -0
- package/package.json +1 -1
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { getSolverDir } from './solver/config.js';
|
|
4
|
+
const PACKAGE_NAME = '@nuanu-ai/agentbrowse';
|
|
5
|
+
const PACKAGE_JSON_URL = new URL('../package.json', import.meta.url);
|
|
6
|
+
const REGISTRY_METADATA_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}`;
|
|
7
|
+
const DEFAULT_UPDATE_CHECK_TIMEOUT_MS = 1500;
|
|
8
|
+
const DEFAULT_UPDATE_TTL_MS = 12 * 60 * 60 * 1000;
|
|
9
|
+
export function compareVersions(left, right) {
|
|
10
|
+
const parsedLeft = parseVersion(left);
|
|
11
|
+
const parsedRight = parseVersion(right);
|
|
12
|
+
if (!parsedLeft || !parsedRight) {
|
|
13
|
+
return left.localeCompare(right, undefined, {
|
|
14
|
+
numeric: true,
|
|
15
|
+
sensitivity: 'base',
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
for (let i = 0; i < 3; i += 1) {
|
|
19
|
+
const diff = parsedLeft.core[i] - parsedRight.core[i];
|
|
20
|
+
if (diff !== 0) {
|
|
21
|
+
return diff;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!parsedLeft.prerelease && !parsedRight.prerelease) {
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
if (!parsedLeft.prerelease) {
|
|
28
|
+
return 1;
|
|
29
|
+
}
|
|
30
|
+
if (!parsedRight.prerelease) {
|
|
31
|
+
return -1;
|
|
32
|
+
}
|
|
33
|
+
const length = Math.max(parsedLeft.prerelease.length, parsedRight.prerelease.length);
|
|
34
|
+
for (let i = 0; i < length; i += 1) {
|
|
35
|
+
const leftPart = parsedLeft.prerelease[i];
|
|
36
|
+
const rightPart = parsedRight.prerelease[i];
|
|
37
|
+
if (leftPart === undefined) {
|
|
38
|
+
return -1;
|
|
39
|
+
}
|
|
40
|
+
if (rightPart === undefined) {
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
if (typeof leftPart === 'number' && typeof rightPart === 'number') {
|
|
44
|
+
const diff = leftPart - rightPart;
|
|
45
|
+
if (diff !== 0) {
|
|
46
|
+
return diff;
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (typeof leftPart === 'number') {
|
|
51
|
+
return -1;
|
|
52
|
+
}
|
|
53
|
+
if (typeof rightPart === 'number') {
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
const diff = leftPart.localeCompare(rightPart);
|
|
57
|
+
if (diff !== 0) {
|
|
58
|
+
return diff;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
export async function checkForLaunchUpdate(options = {}) {
|
|
64
|
+
const currentVersion = readCurrentPackageVersion();
|
|
65
|
+
const now = options.now ?? new Date();
|
|
66
|
+
const ttlMs = options.ttlMs ?? DEFAULT_UPDATE_TTL_MS;
|
|
67
|
+
const cachedState = readUpdateState();
|
|
68
|
+
const cachedNotice = buildLaunchUpdateNotice(currentVersion, cachedState?.latestVersion);
|
|
69
|
+
if (cachedState && !isCacheStale(cachedState.lastCheckedAt, now, ttlMs)) {
|
|
70
|
+
return cachedNotice;
|
|
71
|
+
}
|
|
72
|
+
const latestVersion = await fetchLatestVersion({
|
|
73
|
+
fetchImpl: options.fetchImpl,
|
|
74
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_UPDATE_CHECK_TIMEOUT_MS,
|
|
75
|
+
}).catch(() => null);
|
|
76
|
+
if (!latestVersion) {
|
|
77
|
+
return cachedNotice;
|
|
78
|
+
}
|
|
79
|
+
writeUpdateState({
|
|
80
|
+
packageName: PACKAGE_NAME,
|
|
81
|
+
latestVersion,
|
|
82
|
+
lastCheckedAt: now.toISOString(),
|
|
83
|
+
});
|
|
84
|
+
return buildLaunchUpdateNotice(currentVersion, latestVersion);
|
|
85
|
+
}
|
|
86
|
+
function parseVersion(version) {
|
|
87
|
+
const match = version
|
|
88
|
+
.trim()
|
|
89
|
+
.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+.*)?$/);
|
|
90
|
+
if (!match) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const prerelease = match[4]
|
|
94
|
+
? match[4].split('.').map((part) => (/^\d+$/.test(part) ? Number(part) : part))
|
|
95
|
+
: null;
|
|
96
|
+
return {
|
|
97
|
+
core: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
98
|
+
prerelease,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function buildLaunchUpdateNotice(currentVersion, latestVersion) {
|
|
102
|
+
if (!latestVersion || compareVersions(latestVersion, currentVersion) <= 0) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
currentVersion,
|
|
107
|
+
latestVersion,
|
|
108
|
+
message: `A newer agentbrowse version is available: ${latestVersion} (current: ${currentVersion}). Update with: npm i -g ${PACKAGE_NAME}@latest`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function readCurrentPackageVersion() {
|
|
112
|
+
const raw = JSON.parse(readFileSync(PACKAGE_JSON_URL, 'utf-8'));
|
|
113
|
+
if (!raw.version || typeof raw.version !== 'string') {
|
|
114
|
+
throw new Error('Package version is missing from package.json.');
|
|
115
|
+
}
|
|
116
|
+
return raw.version;
|
|
117
|
+
}
|
|
118
|
+
function readUpdateState() {
|
|
119
|
+
const updateStatePath = getUpdateStatePath();
|
|
120
|
+
if (!existsSync(updateStatePath)) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const raw = JSON.parse(readFileSync(updateStatePath, 'utf-8'));
|
|
125
|
+
if (raw.packageName !== PACKAGE_NAME ||
|
|
126
|
+
typeof raw.latestVersion !== 'string' ||
|
|
127
|
+
typeof raw.lastCheckedAt !== 'string') {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
packageName: raw.packageName,
|
|
132
|
+
latestVersion: raw.latestVersion,
|
|
133
|
+
lastCheckedAt: raw.lastCheckedAt,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function writeUpdateState(state) {
|
|
141
|
+
const solverDir = getSolverDir();
|
|
142
|
+
mkdirSync(solverDir, { recursive: true });
|
|
143
|
+
writeFileSync(getUpdateStatePath(), JSON.stringify(state, null, 2) + '\n', 'utf-8');
|
|
144
|
+
}
|
|
145
|
+
function isCacheStale(lastCheckedAt, now, ttlMs) {
|
|
146
|
+
const lastCheckedAtMs = new Date(lastCheckedAt).getTime();
|
|
147
|
+
if (!Number.isFinite(lastCheckedAtMs)) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
return now.getTime() - lastCheckedAtMs >= ttlMs;
|
|
151
|
+
}
|
|
152
|
+
async function fetchLatestVersion(options) {
|
|
153
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
154
|
+
if (typeof fetchImpl !== 'function') {
|
|
155
|
+
throw new Error('Global fetch is not available.');
|
|
156
|
+
}
|
|
157
|
+
const controller = new AbortController();
|
|
158
|
+
const timeout = setTimeout(() => controller.abort(), options.timeoutMs);
|
|
159
|
+
try {
|
|
160
|
+
const response = await fetchImpl(REGISTRY_METADATA_URL, {
|
|
161
|
+
headers: {
|
|
162
|
+
Accept: 'application/json',
|
|
163
|
+
},
|
|
164
|
+
signal: controller.signal,
|
|
165
|
+
});
|
|
166
|
+
if (!response.ok) {
|
|
167
|
+
throw new Error(`Registry responded with ${response.status}.`);
|
|
168
|
+
}
|
|
169
|
+
const metadata = (await response.json());
|
|
170
|
+
const latestVersion = metadata['dist-tags']?.latest;
|
|
171
|
+
if (!latestVersion || typeof latestVersion !== 'string') {
|
|
172
|
+
throw new Error('Registry metadata does not include dist-tags.latest.');
|
|
173
|
+
}
|
|
174
|
+
return latestVersion;
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
clearTimeout(timeout);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function getUpdateStatePath() {
|
|
181
|
+
return join(getSolverDir(), 'update-state.json');
|
|
182
|
+
}
|
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": [
|