browser4-cli 0.1.6 → 0.1.7
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 -11
- 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 +4 -6
- package/scripts/check-npm-publish-needed.js +56 -0
- package/scripts/npm-publish-check.js +94 -0
- package/scripts/publish-if-needed.js +66 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Browser4
|
|
1
|
+
# Browser4
|
|
2
2
|
|
|
3
3
|
Make websites accessible for AI agents. Automate tasks online with ease.
|
|
4
4
|
|
|
@@ -53,16 +53,6 @@ pnpm link --global # Makes browser4-cli available globally
|
|
|
53
53
|
- **Java 17+** - Required to run the Browser4 backend (`Browser4.jar`).
|
|
54
54
|
- **Rust** - Only needed when building from source (see From Source above).
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
56
|
## Usage
|
|
67
57
|
|
|
68
58
|
```
|
|
@@ -365,6 +355,41 @@ cargo test --test e2e -- --nocapture
|
|
|
365
355
|
cargo test --test e2e -- --nocapture --scenario=test_e2e_batch_form_submission
|
|
366
356
|
```
|
|
367
357
|
|
|
358
|
+
## Publishing the CLI package
|
|
359
|
+
|
|
360
|
+
For maintainers, the CLI package now uses an npm version guard before publish.
|
|
361
|
+
|
|
362
|
+
The GitHub release workflow publishes the npm package via npm trusted publishing
|
|
363
|
+
(GitHub Actions OIDC) instead of `NODE_AUTH_TOKEN`. This avoids CI failures caused
|
|
364
|
+
by npm one-time-password challenges (`EOTP`).
|
|
365
|
+
|
|
366
|
+
- Local release entrypoint: `npm run release`
|
|
367
|
+
- Direct guarded publish entrypoint: `npm run publish:if-needed`
|
|
368
|
+
- GitHub release workflow: re-checks npm immediately before the publish step
|
|
369
|
+
|
|
370
|
+
If the local version in `cli/package.json` already matches the version currently
|
|
371
|
+
published on npm, the publish step is skipped automatically.
|
|
372
|
+
|
|
373
|
+
Examples:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Check whether npm publish is needed
|
|
377
|
+
node scripts/check-npm-publish-needed.js --json
|
|
378
|
+
|
|
379
|
+
# Publish only when the local version differs from npm
|
|
380
|
+
npm run publish:if-needed
|
|
381
|
+
|
|
382
|
+
# Standard maintainer release command (also guarded)
|
|
383
|
+
npm run release
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
For local testing, you can override the detected remote version:
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
BROWSER4_CLI_NPM_REMOTE_VERSION=0.1.7 node scripts/check-npm-publish-needed.js --json
|
|
390
|
+
BROWSER4_CLI_NPM_REMOTE_VERSION=0.1.7 node scripts/publish-if-needed.js --dry-run
|
|
391
|
+
```
|
|
392
|
+
|
|
368
393
|
## License
|
|
369
394
|
|
|
370
395
|
Apache-2.0
|
|
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.7",
|
|
4
4
|
"description": "Browser automation CLI for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"build:windows": "npm run version:sync && docker compose -f docker/docker-compose.yml run --rm build-windows",
|
|
23
23
|
"build:all-platforms": "npm run version:sync && (npm run build:linux & npm run build:windows & wait)",
|
|
24
24
|
"build:docker": "docker build -t browser4-builder -f docker/Dockerfile.build .",
|
|
25
|
-
"
|
|
25
|
+
"publish:if-needed": "node scripts/publish-if-needed.js",
|
|
26
|
+
"release": "npm run publish:if-needed",
|
|
26
27
|
"postinstall": "node scripts/postinstall.js"
|
|
27
28
|
},
|
|
28
29
|
"keywords": [
|
|
@@ -45,8 +46,5 @@
|
|
|
45
46
|
"url": "https://github.com/platonai/Browser4/issues"
|
|
46
47
|
},
|
|
47
48
|
"homepage": "https://browser4.io",
|
|
48
|
-
"packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be"
|
|
49
|
-
"dependencies": {
|
|
50
|
-
"browser4-cli": "^0.1.5"
|
|
51
|
-
}
|
|
49
|
+
"packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be"
|
|
52
50
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { appendFileSync } from 'fs';
|
|
4
|
+
import { getPublishDecision, logPublishDecision } from './npm-publish-check.js';
|
|
5
|
+
|
|
6
|
+
const args = new Set(process.argv.slice(2));
|
|
7
|
+
const shouldWriteGithubOutput = args.has('--github-output');
|
|
8
|
+
const shouldPrintJson = args.has('--json');
|
|
9
|
+
const shouldPrintJsonOnly = args.has('--json-only');
|
|
10
|
+
const shouldPrintShell = args.has('--shell');
|
|
11
|
+
const decision = getPublishDecision();
|
|
12
|
+
|
|
13
|
+
if (!shouldPrintJsonOnly && !shouldPrintShell) {
|
|
14
|
+
logPublishDecision('check', decision);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (shouldPrintJson) {
|
|
18
|
+
console.log(JSON.stringify(decision));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (shouldPrintJsonOnly) {
|
|
22
|
+
console.log(JSON.stringify(decision));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (shouldPrintShell) {
|
|
26
|
+
console.log(`PACKAGE_NAME='${decision.packageName}'`);
|
|
27
|
+
console.log(`CLI_VERSION='${decision.cliVersion}'`);
|
|
28
|
+
console.log(`REMOTE_VERSION='${decision.remoteVersion}'`);
|
|
29
|
+
console.log(`LOOKUP_STATUS='${decision.lookupStatus}'`);
|
|
30
|
+
console.log(`SHOULD_PUBLISH='${decision.shouldPublish ? 'true' : 'false'}'`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (shouldWriteGithubOutput) {
|
|
34
|
+
const githubOutputPath = process.env.GITHUB_OUTPUT;
|
|
35
|
+
if (!githubOutputPath) {
|
|
36
|
+
console.error('GITHUB_OUTPUT is required when using --github-output');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
appendFileSync(
|
|
41
|
+
githubOutputPath,
|
|
42
|
+
[
|
|
43
|
+
`package_name=${decision.packageName}`,
|
|
44
|
+
`cli_version=${decision.cliVersion}`,
|
|
45
|
+
`remote_version=${decision.remoteVersion}`,
|
|
46
|
+
`lookup_status=${decision.lookupStatus}`,
|
|
47
|
+
`should_publish=${decision.shouldPublish ? 'true' : 'false'}`,
|
|
48
|
+
'',
|
|
49
|
+
].join('\n')
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!decision.shouldPublish && !shouldPrintJsonOnly && !shouldPrintShell) {
|
|
54
|
+
console.log(`Skipping publish because ${decision.packageName}@${decision.cliVersion} already exists on npm.`);
|
|
55
|
+
}
|
|
56
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { readFileSync } from 'fs';
|
|
5
|
+
import { dirname, join } from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
export const cliRootDir = join(__dirname, '..');
|
|
10
|
+
const packageJsonPath = join(cliRootDir, 'package.json');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Reads browser4-cli package metadata.
|
|
14
|
+
*
|
|
15
|
+
* @returns {{name: string, version: string}}
|
|
16
|
+
*/
|
|
17
|
+
export function readPackageMetadata() {
|
|
18
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
19
|
+
return {
|
|
20
|
+
name: packageJson.name,
|
|
21
|
+
version: packageJson.version,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Queries npm for the published version of the package.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} packageName Package name to inspect.
|
|
29
|
+
* @returns {{status: string, version: string}}
|
|
30
|
+
*/
|
|
31
|
+
export function getRemoteVersion(packageName) {
|
|
32
|
+
const overriddenVersion = process.env.BROWSER4_CLI_NPM_REMOTE_VERSION;
|
|
33
|
+
if (overriddenVersion) {
|
|
34
|
+
console.log(`Using overridden npm version from BROWSER4_CLI_NPM_REMOTE_VERSION=${overriddenVersion}`);
|
|
35
|
+
return {
|
|
36
|
+
status: 'overridden',
|
|
37
|
+
version: overriddenVersion,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const version = execSync(`npm view "${packageName}" version`, {
|
|
43
|
+
cwd: cliRootDir,
|
|
44
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
45
|
+
encoding: 'utf-8',
|
|
46
|
+
}).trim();
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
status: 'success',
|
|
50
|
+
version,
|
|
51
|
+
};
|
|
52
|
+
} catch (error) {
|
|
53
|
+
const stderr = error.stderr?.toString().trim();
|
|
54
|
+
const stdout = error.stdout?.toString().trim();
|
|
55
|
+
const message = stderr || stdout || error.message;
|
|
56
|
+
|
|
57
|
+
console.warn(`Warning: unable to query npm version for ${packageName}: ${message}`);
|
|
58
|
+
return {
|
|
59
|
+
status: 'failed',
|
|
60
|
+
version: 'unknown',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Computes whether npm publish should proceed.
|
|
67
|
+
*
|
|
68
|
+
* @returns {{packageName: string, cliVersion: string, remoteVersion: string, lookupStatus: string, shouldPublish: boolean}}
|
|
69
|
+
*/
|
|
70
|
+
export function getPublishDecision() {
|
|
71
|
+
const metadata = readPackageMetadata();
|
|
72
|
+
const remoteInfo = getRemoteVersion(metadata.name);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
packageName: metadata.name,
|
|
76
|
+
cliVersion: metadata.version,
|
|
77
|
+
remoteVersion: remoteInfo.version,
|
|
78
|
+
lookupStatus: remoteInfo.status,
|
|
79
|
+
shouldPublish: remoteInfo.version === 'unknown' || metadata.version !== remoteInfo.version,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Logs a human-readable publish decision.
|
|
85
|
+
*
|
|
86
|
+
* @param {string} phase Current phase label.
|
|
87
|
+
* @param {{packageName: string, cliVersion: string, remoteVersion: string, lookupStatus: string, shouldPublish: boolean}} decision Publish decision.
|
|
88
|
+
*/
|
|
89
|
+
export function logPublishDecision(phase, decision) {
|
|
90
|
+
console.log(
|
|
91
|
+
`[${phase}] package=${decision.packageName} local=${decision.cliVersion} remote=${decision.remoteVersion} status=${decision.lookupStatus} shouldPublish=${decision.shouldPublish}`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Publishes browser4-cli only when the local package version differs from npm.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/publish-if-needed.js
|
|
8
|
+
* node scripts/publish-if-needed.js --dry-run
|
|
9
|
+
*
|
|
10
|
+
* Optional env for testing:
|
|
11
|
+
* BROWSER4_CLI_NPM_REMOTE_VERSION=<version>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { execSync } from 'child_process';
|
|
15
|
+
import { cliRootDir, getPublishDecision, logPublishDecision } from './npm-publish-check.js';
|
|
16
|
+
|
|
17
|
+
const args = new Set(process.argv.slice(2));
|
|
18
|
+
const isDryRun = args.has('--dry-run');
|
|
19
|
+
|
|
20
|
+
function runCommand(command) {
|
|
21
|
+
console.log(`> ${command}`);
|
|
22
|
+
execSync(command, {
|
|
23
|
+
cwd: cliRootDir,
|
|
24
|
+
stdio: 'inherit',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function main() {
|
|
29
|
+
const initialDecision = getPublishDecision();
|
|
30
|
+
logPublishDecision('pre-check', initialDecision);
|
|
31
|
+
|
|
32
|
+
if (!initialDecision.shouldPublish) {
|
|
33
|
+
console.log(`Skipping publish because ${initialDecision.packageName}@${initialDecision.cliVersion} already exists on npm.`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (isDryRun) {
|
|
38
|
+
console.log('Dry run enabled; version differs, so publish would proceed.');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
runCommand('npm run version:sync');
|
|
43
|
+
|
|
44
|
+
const postSyncDecision = getPublishDecision();
|
|
45
|
+
logPublishDecision('post-sync-check', postSyncDecision);
|
|
46
|
+
|
|
47
|
+
if (!postSyncDecision.shouldPublish) {
|
|
48
|
+
console.log(`Skipping publish after sync because ${postSyncDecision.packageName}@${postSyncDecision.cliVersion} already exists on npm.`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
runCommand('npm run build:all-platforms');
|
|
53
|
+
|
|
54
|
+
const prePublishDecision = getPublishDecision();
|
|
55
|
+
logPublishDecision('pre-publish-check', prePublishDecision);
|
|
56
|
+
|
|
57
|
+
if (!prePublishDecision.shouldPublish) {
|
|
58
|
+
console.log(`Skipping publish before npm publish because ${prePublishDecision.packageName}@${prePublishDecision.cliVersion} already exists on npm.`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
runCommand('npm publish');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
main();
|
|
66
|
+
|