browser4-cli 0.1.19 → 0.1.20
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/bin/browser4-cli-darwin-arm64 +0 -0
- package/bin/browser4-cli-darwin-x64 +0 -0
- package/bin/browser4-cli-linux-arm64 +0 -0
- package/bin/browser4-cli-linux-musl-arm64 +0 -0
- package/bin/browser4-cli-linux-musl-x64 +0 -0
- package/bin/browser4-cli-linux-x64 +0 -0
- package/bin/browser4-cli-win32-x64.exe +0 -0
- package/package.json +2 -2
- package/scripts/check-version-sync.js +0 -44
- package/scripts/sync-version.js +0 -277
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser4-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"description": "Browser automation CLI for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"browser4": "./bin/browser4-cli.js"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"version:sync": "node
|
|
17
|
+
"version:sync": "node ../bin/version.mjs cli sync",
|
|
18
18
|
"version": "npm run version:sync && git add browser4-cli/Cargo.toml browser4-cli/Cargo.lock",
|
|
19
19
|
"build:native": "npm run version:sync && cargo build --release --manifest-path browser4-cli/Cargo.toml && node scripts/copy-native.js",
|
|
20
20
|
"build:linux": "npm run version:sync && docker compose -f docker/docker-compose.yml run --rm build-linux",
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Verifies that package.json and browser4-cli/Cargo.toml have the same version.
|
|
5
|
-
* Used in CI to catch version drift.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { readFileSync } from 'fs';
|
|
9
|
-
import { dirname, join } from 'path';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
|
-
|
|
12
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const rootDir = join(__dirname, '..');
|
|
14
|
-
|
|
15
|
-
// Read package.json version
|
|
16
|
-
const packageJson = JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf-8'));
|
|
17
|
-
const packageVersion = packageJson.version;
|
|
18
|
-
|
|
19
|
-
// Read Cargo.toml version
|
|
20
|
-
const cargoToml = readFileSync(join(rootDir, 'browser4-cli/Cargo.toml'), 'utf-8');
|
|
21
|
-
const cargoVersionMatch = cargoToml.match(/^version\s*=\s*"([^"]*)"/m);
|
|
22
|
-
|
|
23
|
-
if (!cargoVersionMatch) {
|
|
24
|
-
console.error('Could not find version in browser4-cli/Cargo.toml');
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const cargoVersion = cargoVersionMatch[1];
|
|
29
|
-
|
|
30
|
-
const mismatches = [];
|
|
31
|
-
if (packageVersion !== cargoVersion) {
|
|
32
|
-
mismatches.push(` browser4-cli/Cargo.toml: ${cargoVersion}`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (mismatches.length > 0) {
|
|
36
|
-
console.error('Version mismatch detected!');
|
|
37
|
-
console.error(` package.json: ${packageVersion}`);
|
|
38
|
-
for (const m of mismatches) console.error(m);
|
|
39
|
-
console.error('');
|
|
40
|
-
console.error("Run 'pnpm run version:sync' to fix this.");
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
console.log(`Versions are in sync: ${packageVersion}`);
|
package/scripts/sync-version.js
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Syncs the CLI version from cli/VERSION-CLI to all dependent files.
|
|
5
|
-
*
|
|
6
|
-
* cli/VERSION-CLI is the single source of truth for the CLI version. This
|
|
7
|
-
* allows the backend Maven project and the CLI to be published separately with
|
|
8
|
-
* different versions. This script:
|
|
9
|
-
* - Reads the version from cli/VERSION-CLI
|
|
10
|
-
* - Strips any "-SNAPSHOT" suffix (if present)
|
|
11
|
-
* - Fetches the latest published version from npm and compares it
|
|
12
|
-
* against the local version, warning when the bump is neither a
|
|
13
|
-
* patch nor a minor increment.
|
|
14
|
-
* - Writes the version to cli/package.json
|
|
15
|
-
* - Writes the version to cli/browser4-cli/Cargo.toml
|
|
16
|
-
* - Updates Cargo.lock to match
|
|
17
|
-
*
|
|
18
|
-
* Usage:
|
|
19
|
-
* node cli/scripts/sync-version.js # sync all files
|
|
20
|
-
* node cli/scripts/sync-version.js --check # exit 1 if out of sync (CI lint)
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import {execSync} from "child_process";
|
|
24
|
-
import {readFileSync, writeFileSync} from "fs";
|
|
25
|
-
import {dirname, join, resolve} from "path";
|
|
26
|
-
import {fileURLToPath} from "url";
|
|
27
|
-
|
|
28
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
29
|
-
const scriptsDir = __dirname; // cli/scripts
|
|
30
|
-
const cliDir = resolve(scriptsDir, ".."); // cli
|
|
31
|
-
const cargoDir = join(cliDir, "browser4-cli"); // cli/browser4-cli
|
|
32
|
-
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
// Helpers
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
|
|
37
|
-
/** Strip the "-SNAPSHOT" suffix if present. */
|
|
38
|
-
function stripSnapshot(version) {
|
|
39
|
-
if (version.endsWith("-SNAPSHOT")) {
|
|
40
|
-
return version.slice(0, -"-SNAPSHOT".length);
|
|
41
|
-
}
|
|
42
|
-
return version;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Parse a semver string into { major, minor, patch } integers.
|
|
47
|
-
* Returns null for non-semver strings (e.g. snapshots, prereleases).
|
|
48
|
-
*/
|
|
49
|
-
function parseSemver(version) {
|
|
50
|
-
const m = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
51
|
-
if (!m) return null;
|
|
52
|
-
return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Fetch the latest published version of a package from the npm registry.
|
|
57
|
-
* Returns the version string, or null if the package hasn't been published
|
|
58
|
-
* yet or the registry is unreachable.
|
|
59
|
-
*/
|
|
60
|
-
function getLatestPublishedVersion(packageName) {
|
|
61
|
-
try {
|
|
62
|
-
const raw = execSync(`npm view "${packageName}" version --json`, {
|
|
63
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
64
|
-
timeout: 10_000,
|
|
65
|
-
});
|
|
66
|
-
return JSON.parse(raw.toString().trim());
|
|
67
|
-
} catch {
|
|
68
|
-
// Package may not be published yet, or network is unavailable.
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Check whether `local` is an expected bump from `published`:
|
|
75
|
-
* - same version (already published)
|
|
76
|
-
* - next patch
|
|
77
|
-
* - next minor
|
|
78
|
-
*
|
|
79
|
-
* Returns { ok: true } or { ok: false, reason: "..." }.
|
|
80
|
-
*/
|
|
81
|
-
function checkVersionBump(published, local) {
|
|
82
|
-
const pub = parseSemver(published);
|
|
83
|
-
const loc = parseSemver(local);
|
|
84
|
-
|
|
85
|
-
if (!pub || !loc) {
|
|
86
|
-
// Can't compare — pre-release / snapshot versions are fine.
|
|
87
|
-
return { ok: true };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Same version — already published.
|
|
91
|
-
if (loc.major === pub.major && loc.minor === pub.minor && loc.patch === pub.patch) {
|
|
92
|
-
return { ok: true, note: `version ${local} is already published` };
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Next patch: X.Y.Z → X.Y.(Z+1)
|
|
96
|
-
if (loc.major === pub.major && loc.minor === pub.minor && loc.patch === pub.patch + 1) {
|
|
97
|
-
return { ok: true };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Next minor: X.Y.Z → X.(Y+1).0
|
|
101
|
-
if (loc.major === pub.major && loc.minor === pub.minor + 1 && loc.patch === 0) {
|
|
102
|
-
return { ok: true };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Local is behind published.
|
|
106
|
-
if (
|
|
107
|
-
loc.major < pub.major ||
|
|
108
|
-
(loc.major === pub.major && loc.minor < pub.minor) ||
|
|
109
|
-
(loc.major === pub.major && loc.minor === pub.minor && loc.patch < pub.patch)
|
|
110
|
-
) {
|
|
111
|
-
return {
|
|
112
|
-
ok: false,
|
|
113
|
-
reason: `local version ${local} is behind the published version ${published}`,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Anything else — skipping versions, major bump, etc.
|
|
118
|
-
return {
|
|
119
|
-
ok: false,
|
|
120
|
-
reason: `version bump from ${published} to ${local} is neither a patch nor a minor increment`,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// ---------------------------------------------------------------------------
|
|
125
|
-
// Main
|
|
126
|
-
// ---------------------------------------------------------------------------
|
|
127
|
-
|
|
128
|
-
const checkOnly = process.argv.includes("--check");
|
|
129
|
-
|
|
130
|
-
// The npm package name (hard-coded — stable across versions)
|
|
131
|
-
const pkgName = "browser4-cli";
|
|
132
|
-
|
|
133
|
-
// 1. Read the CLI version from cli/VERSION-CLI (the single source of truth)
|
|
134
|
-
const versionCliPath = join(cliDir, "VERSION-CLI");
|
|
135
|
-
let versionRaw;
|
|
136
|
-
try {
|
|
137
|
-
versionRaw = readFileSync(versionCliPath, "utf-8").trim();
|
|
138
|
-
} catch {
|
|
139
|
-
console.error(`ERROR: Cannot read ${versionCliPath}`);
|
|
140
|
-
process.exit(1);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (!versionRaw) {
|
|
144
|
-
console.error("ERROR: cli/VERSION-CLI is empty.");
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const version = stripSnapshot(versionRaw);
|
|
149
|
-
if (checkOnly) console.log(`cli/VERSION-CLI: ${version}`);
|
|
150
|
-
|
|
151
|
-
// 2. Compare against the latest published version on npm
|
|
152
|
-
const publishedVersion = getLatestPublishedVersion(pkgName);
|
|
153
|
-
if (publishedVersion) {
|
|
154
|
-
console.log(`Latest published: ${pkgName}@${publishedVersion}`);
|
|
155
|
-
const bump = checkVersionBump(publishedVersion, version);
|
|
156
|
-
if (!bump.ok) {
|
|
157
|
-
console.warn(`\x1b[33mWARNING: ${bump.reason}\x1b[0m`);
|
|
158
|
-
} else if (bump.note) {
|
|
159
|
-
console.log(` (${bump.note})`);
|
|
160
|
-
}
|
|
161
|
-
} else {
|
|
162
|
-
console.log(`Latest published: (not found — package may not be published yet)`);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// ---------------------------------------------------------------------------
|
|
166
|
-
// 3. Sync cli/package.json
|
|
167
|
-
// ---------------------------------------------------------------------------
|
|
168
|
-
const packageJsonPath = join(cliDir, "package.json");
|
|
169
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
170
|
-
|
|
171
|
-
if (!packageJson.version) {
|
|
172
|
-
console.error("ERROR: cli/package.json does not contain a version field.");
|
|
173
|
-
process.exit(1);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (packageJson.version !== version) {
|
|
177
|
-
if (checkOnly) {
|
|
178
|
-
console.error(`MISMATCH: ${packageJsonPath} version is "${packageJson.version}", expected "${version}"`);
|
|
179
|
-
process.exitCode = 1;
|
|
180
|
-
} else {
|
|
181
|
-
const oldVersion = packageJson.version;
|
|
182
|
-
packageJson.version = version;
|
|
183
|
-
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n");
|
|
184
|
-
console.log(` Updated ${packageJsonPath}: ${oldVersion} -> ${version}`);
|
|
185
|
-
}
|
|
186
|
-
} else {
|
|
187
|
-
if (!checkOnly) console.log(` ${packageJsonPath} already up to date`);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// ---------------------------------------------------------------------------
|
|
191
|
-
// 4. Sync cli/browser4-cli/Cargo.toml
|
|
192
|
-
// ---------------------------------------------------------------------------
|
|
193
|
-
const cargoTomlPath = join(cargoDir, "Cargo.toml");
|
|
194
|
-
let cargoToml = readFileSync(cargoTomlPath, "utf-8");
|
|
195
|
-
const cargoVersionRegex = /^version\s*=\s*"[^"]*"/m;
|
|
196
|
-
const cargoMatch = cargoToml.match(cargoVersionRegex);
|
|
197
|
-
|
|
198
|
-
if (!cargoMatch) {
|
|
199
|
-
console.error("ERROR: Could not find version field in Cargo.toml");
|
|
200
|
-
process.exit(1);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const cargoVersion = cargoMatch[0].match(/"([^"]*)"/)[1];
|
|
204
|
-
if (cargoVersion !== version) {
|
|
205
|
-
if (checkOnly) {
|
|
206
|
-
console.error(`MISMATCH: ${cargoTomlPath} version is "${cargoVersion}", expected "${version}"`);
|
|
207
|
-
process.exitCode = 1;
|
|
208
|
-
} else {
|
|
209
|
-
cargoToml = cargoToml.replace(cargoVersionRegex, `version = "${version}"`);
|
|
210
|
-
writeFileSync(cargoTomlPath, cargoToml);
|
|
211
|
-
console.log(` Updated ${cargoTomlPath}: ${cargoVersion} -> ${version}`);
|
|
212
|
-
}
|
|
213
|
-
} else {
|
|
214
|
-
if (!checkOnly) console.log(` ${cargoTomlPath} already up to date`);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// ---------------------------------------------------------------------------
|
|
218
|
-
// 5. Update Cargo.lock (only in sync mode)
|
|
219
|
-
// ---------------------------------------------------------------------------
|
|
220
|
-
if (!checkOnly && cargoVersion !== version) {
|
|
221
|
-
let lockUpdated = false;
|
|
222
|
-
try {
|
|
223
|
-
execSync("cargo update -p browser4-cli --offline", {
|
|
224
|
-
cwd: cargoDir,
|
|
225
|
-
stdio: "pipe",
|
|
226
|
-
});
|
|
227
|
-
console.log(" Updated Cargo.lock");
|
|
228
|
-
lockUpdated = true;
|
|
229
|
-
} catch {
|
|
230
|
-
try {
|
|
231
|
-
execSync("cargo update -p browser4-cli", {
|
|
232
|
-
cwd: cargoDir,
|
|
233
|
-
stdio: "pipe",
|
|
234
|
-
});
|
|
235
|
-
console.log(" Updated Cargo.lock");
|
|
236
|
-
lockUpdated = true;
|
|
237
|
-
} catch (e) {
|
|
238
|
-
console.error(` Warning: Could not update Cargo.lock via cargo: ${e.message}`);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Fallback: edit Cargo.lock directly when cargo update fails (e.g. due to
|
|
243
|
-
// lock file version mismatch between the installed cargo and the lock file).
|
|
244
|
-
if (!lockUpdated) {
|
|
245
|
-
const cargoLockPath = join(cargoDir, "Cargo.lock");
|
|
246
|
-
try {
|
|
247
|
-
let lockContent = readFileSync(cargoLockPath, "utf-8");
|
|
248
|
-
// Match the [[package]] block for browser4-cli and replace its version.
|
|
249
|
-
// Works for both v3 and v4 lock file formats.
|
|
250
|
-
const lockPkgRegex = new RegExp(
|
|
251
|
-
`(\\[\\[package\\]\\][\\r\\n]+\\s*name\\s*=\\s*"browser4-cli"[\\r\\n]+\\s*version\\s*=\\s*)"[^"]*"`,
|
|
252
|
-
"m"
|
|
253
|
-
);
|
|
254
|
-
if (lockPkgRegex.test(lockContent)) {
|
|
255
|
-
lockContent = lockContent.replace(lockPkgRegex, `$1"${version}"`);
|
|
256
|
-
writeFileSync(cargoLockPath, lockContent);
|
|
257
|
-
console.log(` Updated Cargo.lock directly: ${cargoVersion} -> ${version}`);
|
|
258
|
-
lockUpdated = true;
|
|
259
|
-
} else {
|
|
260
|
-
console.error(" Warning: Could not find browser4-cli entry in Cargo.lock");
|
|
261
|
-
}
|
|
262
|
-
} catch (e2) {
|
|
263
|
-
console.error(` Warning: Could not update Cargo.lock directly: ${e2.message}`);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// 6. Report
|
|
269
|
-
if (checkOnly) {
|
|
270
|
-
if (process.exitCode === 1) {
|
|
271
|
-
console.error("\nVersion mismatch detected! Run 'node cli/scripts/sync-version.js' to fix.");
|
|
272
|
-
} else {
|
|
273
|
-
console.log(`\nAll versions in sync with cli/VERSION-CLI: ${version}`);
|
|
274
|
-
}
|
|
275
|
-
} else {
|
|
276
|
-
console.log(`\nVersion sync complete: ${pkgName}@${version}`);
|
|
277
|
-
}
|