agent-browser-stealth 0.16.1-fork.1 → 0.16.1-fork.3
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 +4 -1
- package/bin/agent-browser +0 -0
- package/bin/agent-browser-darwin-arm64 +0 -0
- package/bin/agent-browser-darwin-x64 +0 -0
- package/bin/agent-browser-linux-arm64 +0 -0
- package/bin/agent-browser-linux-x64 +0 -0
- package/bin/agent-browser-stealth +0 -0
- package/bin/agent-browser-stealth.d +1 -0
- package/bin/agent-browser-win32-x64.exe +0 -0
- package/bin/agent-browser.d +1 -0
- package/package.json +7 -3
- package/scripts/postinstall.js +52 -16
- package/scripts/verify-bundled-binaries.js +71 -0
- package/scripts/verify-packed-host-binary.js +88 -0
- package/scripts/verify-registry-host-binary.js +120 -0
- package/skills/agent-browser/SKILL.md +4 -1
package/README.md
CHANGED
|
@@ -81,7 +81,10 @@ Install once in Chrome: load unpacked extension from `extensions/tab-group-cdp/`
|
|
|
81
81
|
- Download archive routing: downloads from managed tabs are routed to `agent-browser-stealth/<session>/...`.
|
|
82
82
|
- Domain allowlist fallback: when allowlist is configured for a session, extension can force-block out-of-policy tabs to `about:blank`.
|
|
83
83
|
- Risk hints (debug only): suspicious host/TLD hints are returned via handshake and printed only when `AGENT_BROWSER_DEBUG=1`.
|
|
84
|
-
- Side panel
|
|
84
|
+
- Side panel browser controls: open/back/forward/reload, click/fill/press by CSS selector, run shortcut commands, and switch/close tabs.
|
|
85
|
+
- Side panel developer signals: capture page console errors/warnings, fetch/xhr network events, command history, and live DOM snapshots.
|
|
86
|
+
- Workflow automation: record actions into workflows, run workflows, map workflows to slash shortcuts, and schedule runs (daily/weekly/monthly/yearly).
|
|
87
|
+
- Side panel operations console: view session/tab/group mapping, focus a session, keep only one session, clean empty groups, edit session allowlist, and toggle auto-clean.
|
|
85
88
|
|
|
86
89
|
## Stealth Architecture
|
|
87
90
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/Users/leo/github.com/agent-browser/cli/target/release/agent-browser-stealth: /Users/leo/github.com/agent-browser/cli/build.rs /Users/leo/github.com/agent-browser/cli/cdp-protocol/browser_protocol.json /Users/leo/github.com/agent-browser/cli/cdp-protocol/js_protocol.json /Users/leo/github.com/agent-browser/cli/src/color.rs /Users/leo/github.com/agent-browser/cli/src/commands.rs /Users/leo/github.com/agent-browser/cli/src/connection.rs /Users/leo/github.com/agent-browser/cli/src/flags.rs /Users/leo/github.com/agent-browser/cli/src/install.rs /Users/leo/github.com/agent-browser/cli/src/main.rs /Users/leo/github.com/agent-browser/cli/src/main_stealth.rs /Users/leo/github.com/agent-browser/cli/src/output.rs /Users/leo/github.com/agent-browser/cli/src/validation.rs
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/Users/leo/github.com/agent-browser/cli/target/release/agent-browser: /Users/leo/github.com/agent-browser/cli/build.rs /Users/leo/github.com/agent-browser/cli/cdp-protocol/browser_protocol.json /Users/leo/github.com/agent-browser/cli/cdp-protocol/js_protocol.json /Users/leo/github.com/agent-browser/cli/src/color.rs /Users/leo/github.com/agent-browser/cli/src/commands.rs /Users/leo/github.com/agent-browser/cli/src/connection.rs /Users/leo/github.com/agent-browser/cli/src/flags.rs /Users/leo/github.com/agent-browser/cli/src/install.rs /Users/leo/github.com/agent-browser/cli/src/main.rs /Users/leo/github.com/agent-browser/cli/src/output.rs /Users/leo/github.com/agent-browser/cli/src/validation.rs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-browser-stealth",
|
|
3
|
-
"version": "0.16.1-fork.
|
|
3
|
+
"version": "0.16.1-fork.3",
|
|
4
4
|
"description": "Stealth browser automation CLI for AI agents with anti-bot evasions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/daemon.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"build:windows": "npm run version:sync && docker compose -f docker/docker-compose.yml run --rm build-windows",
|
|
28
28
|
"build:all-platforms": "npm run version:sync && (npm run build:linux & npm run build:windows & wait) && npm run build:macos",
|
|
29
29
|
"build:docker": "docker build -t agent-browser-builder -f docker/Dockerfile.build .",
|
|
30
|
-
"release": "npm run version:sync && npm run build && npm run build:all-platforms && npm publish",
|
|
30
|
+
"release": "npm run version:sync && npm run build && npm run build:all-platforms && npm run verify:bundled-binaries && npm run verify:native-version && npm publish",
|
|
31
31
|
"start": "node dist/daemon.js",
|
|
32
32
|
"dev": "tsx src/daemon.ts",
|
|
33
33
|
"typecheck": "tsc --noEmit",
|
|
@@ -41,12 +41,16 @@
|
|
|
41
41
|
"check:turnstile-testkey": "pnpm exec tsx scripts/check-turnstile-testkey.ts",
|
|
42
42
|
"postinstall": "node scripts/postinstall.js",
|
|
43
43
|
"verify:native-version": "node scripts/verify-native-version.js",
|
|
44
|
+
"verify:bundled-binaries": "node scripts/verify-bundled-binaries.js",
|
|
45
|
+
"verify:packed-host-binary": "node scripts/verify-packed-host-binary.js",
|
|
46
|
+
"verify:registry-host-binary": "node scripts/verify-registry-host-binary.js",
|
|
47
|
+
"prepublishOnly": "pnpm run verify:bundled-binaries && pnpm run verify:native-version && pnpm run verify:packed-host-binary",
|
|
44
48
|
"clawhub:sync": "bash scripts/clawhub-sync.sh",
|
|
45
49
|
"sync:upstream": "bash scripts/sync-upstream.sh",
|
|
46
50
|
"sync:upstream:push": "bash scripts/sync-upstream.sh --push",
|
|
47
51
|
"changeset": "changeset",
|
|
48
52
|
"ci:version": "changeset version && pnpm run version:sync && pnpm install --no-frozen-lockfile",
|
|
49
|
-
"ci:publish": "pnpm run version:sync && pnpm run build && pnpm run build:native && pnpm run verify:native-version && changeset publish"
|
|
53
|
+
"ci:publish": "pnpm run version:sync && pnpm run build && pnpm run build:native && pnpm run verify:bundled-binaries && pnpm run verify:native-version && pnpm run verify:packed-host-binary && changeset publish"
|
|
50
54
|
},
|
|
51
55
|
"keywords": [
|
|
52
56
|
"browser",
|
package/scripts/postinstall.js
CHANGED
|
@@ -2,19 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Postinstall script for agent-browser
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* Downloads the platform-specific native binary if not present.
|
|
7
7
|
* On global installs, patches npm's bin entry to use the native binary directly:
|
|
8
8
|
* - Windows: Overwrites .cmd/.ps1 shims
|
|
9
9
|
* - Mac/Linux: Replaces symlink to point to native binary
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
existsSync,
|
|
14
|
+
mkdirSync,
|
|
15
|
+
chmodSync,
|
|
16
|
+
createWriteStream,
|
|
17
|
+
unlinkSync,
|
|
18
|
+
writeFileSync,
|
|
19
|
+
symlinkSync,
|
|
20
|
+
lstatSync,
|
|
21
|
+
readFileSync,
|
|
22
|
+
} from 'fs';
|
|
13
23
|
import { dirname, join } from 'path';
|
|
14
24
|
import { fileURLToPath } from 'url';
|
|
15
25
|
import { platform, arch } from 'os';
|
|
16
26
|
import { get } from 'https';
|
|
17
|
-
import { execSync } from 'child_process';
|
|
27
|
+
import { execFileSync, execSync } from 'child_process';
|
|
18
28
|
|
|
19
29
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
30
|
const projectRoot = join(__dirname, '..');
|
|
@@ -65,7 +75,7 @@ function getBinCommands(pkg) {
|
|
|
65
75
|
async function downloadFile(url, dest) {
|
|
66
76
|
return new Promise((resolve, reject) => {
|
|
67
77
|
const file = createWriteStream(dest);
|
|
68
|
-
|
|
78
|
+
|
|
69
79
|
const request = (url) => {
|
|
70
80
|
get(url, (response) => {
|
|
71
81
|
// Handle redirects
|
|
@@ -73,12 +83,12 @@ async function downloadFile(url, dest) {
|
|
|
73
83
|
request(response.headers.location);
|
|
74
84
|
return;
|
|
75
85
|
}
|
|
76
|
-
|
|
86
|
+
|
|
77
87
|
if (response.statusCode !== 200) {
|
|
78
88
|
reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
|
|
79
89
|
return;
|
|
80
90
|
}
|
|
81
|
-
|
|
91
|
+
|
|
82
92
|
response.pipe(file);
|
|
83
93
|
file.on('finish', () => {
|
|
84
94
|
file.close();
|
|
@@ -89,7 +99,7 @@ async function downloadFile(url, dest) {
|
|
|
89
99
|
reject(err);
|
|
90
100
|
});
|
|
91
101
|
};
|
|
92
|
-
|
|
102
|
+
|
|
93
103
|
request(url);
|
|
94
104
|
});
|
|
95
105
|
}
|
|
@@ -101,13 +111,21 @@ async function main() {
|
|
|
101
111
|
if (platform() !== 'win32') {
|
|
102
112
|
chmodSync(binaryPath, 0o755);
|
|
103
113
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
const installedVersion = readBinaryVersion(binaryPath);
|
|
115
|
+
if (installedVersion.includes(version)) {
|
|
116
|
+
console.log(`✓ Native binary ready: ${binaryName}`);
|
|
117
|
+
|
|
118
|
+
// On global installs, fix npm's bin entry to use native binary directly
|
|
119
|
+
await fixGlobalInstallBin();
|
|
120
|
+
|
|
121
|
+
showPlaywrightReminder();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
console.log(
|
|
126
|
+
`⚠ Binary version mismatch detected: expected ${version}, got "${installedVersion || 'unknown'}"`
|
|
127
|
+
);
|
|
128
|
+
console.log(` Re-downloading ${binaryName} from release assets...`);
|
|
111
129
|
}
|
|
112
130
|
|
|
113
131
|
// Ensure bin directory exists
|
|
@@ -120,12 +138,19 @@ async function main() {
|
|
|
120
138
|
|
|
121
139
|
try {
|
|
122
140
|
await downloadFile(DOWNLOAD_URL, binaryPath);
|
|
123
|
-
|
|
141
|
+
|
|
124
142
|
// Make executable on Unix
|
|
125
143
|
if (platform() !== 'win32') {
|
|
126
144
|
chmodSync(binaryPath, 0o755);
|
|
127
145
|
}
|
|
128
|
-
|
|
146
|
+
|
|
147
|
+
const downloadedVersion = readBinaryVersion(binaryPath);
|
|
148
|
+
if (!downloadedVersion.includes(version)) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
`downloaded binary version mismatch: expected ${version}, got "${downloadedVersion || 'unknown'}"`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
129
154
|
console.log(`✓ Downloaded native binary: ${binaryName}`);
|
|
130
155
|
} catch (err) {
|
|
131
156
|
console.log(`⚠ Could not download native binary: ${err.message}`);
|
|
@@ -143,6 +168,17 @@ async function main() {
|
|
|
143
168
|
showPlaywrightReminder();
|
|
144
169
|
}
|
|
145
170
|
|
|
171
|
+
function readBinaryVersion(path) {
|
|
172
|
+
try {
|
|
173
|
+
return execFileSync(path, ['--version'], {
|
|
174
|
+
encoding: 'utf8',
|
|
175
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
176
|
+
}).trim();
|
|
177
|
+
} catch {
|
|
178
|
+
return '';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
146
182
|
function showPlaywrightReminder() {
|
|
147
183
|
console.log('');
|
|
148
184
|
console.log('╔═══════════════════════════════════════════════════════════════════════════╗');
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Verifies that all bundled platform binaries are present and embed the
|
|
5
|
+
* package.json version string. This catches stale binary bundles where the
|
|
6
|
+
* package version is bumped but one or more binaries were not rebuilt.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
10
|
+
import { dirname, join } from "path";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const rootDir = join(__dirname, "..");
|
|
15
|
+
|
|
16
|
+
const pkg = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf8"));
|
|
17
|
+
const expectedVersion = String(pkg.version || "").trim();
|
|
18
|
+
|
|
19
|
+
if (!expectedVersion) {
|
|
20
|
+
console.error("Error: package.json version is empty");
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const expectedBinaries = [
|
|
25
|
+
"agent-browser-linux-x64",
|
|
26
|
+
"agent-browser-linux-arm64",
|
|
27
|
+
"agent-browser-win32-x64.exe",
|
|
28
|
+
"agent-browser-darwin-x64",
|
|
29
|
+
"agent-browser-darwin-arm64",
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const minSizeBytes = 100_000;
|
|
33
|
+
const versionBytes = Buffer.from(expectedVersion, "utf8");
|
|
34
|
+
|
|
35
|
+
let errors = 0;
|
|
36
|
+
|
|
37
|
+
for (const name of expectedBinaries) {
|
|
38
|
+
const binaryPath = join(rootDir, "bin", name);
|
|
39
|
+
if (!existsSync(binaryPath)) {
|
|
40
|
+
console.error(`ERROR: missing binary: bin/${name}`);
|
|
41
|
+
errors += 1;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const size = statSync(binaryPath).size;
|
|
46
|
+
if (size < minSizeBytes) {
|
|
47
|
+
console.error(
|
|
48
|
+
`ERROR: binary too small: bin/${name} (${size} bytes, expected >= ${minSizeBytes})`
|
|
49
|
+
);
|
|
50
|
+
errors += 1;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const bytes = readFileSync(binaryPath);
|
|
55
|
+
if (!bytes.includes(versionBytes)) {
|
|
56
|
+
console.error(
|
|
57
|
+
`ERROR: stale binary version: bin/${name} does not contain "${expectedVersion}"`
|
|
58
|
+
);
|
|
59
|
+
errors += 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log(`OK: bin/${name} matches version ${expectedVersion}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (errors > 0) {
|
|
67
|
+
console.error(`\nFound ${errors} binary validation issue(s).`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log(`\nAll bundled binaries match package.json version ${expectedVersion}.`);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build an npm tarball locally and verify that the bundled host-platform native
|
|
5
|
+
* binary reports the same version as package.json.
|
|
6
|
+
*
|
|
7
|
+
* This catches publish drifts where package.json is bumped but the embedded
|
|
8
|
+
* binary still points to an older fork version.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, unlinkSync } from 'fs';
|
|
12
|
+
import { tmpdir } from 'os';
|
|
13
|
+
import { dirname, join } from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { execFileSync } from 'child_process';
|
|
16
|
+
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const rootDir = join(__dirname, '..');
|
|
19
|
+
|
|
20
|
+
const pkg = JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf8'));
|
|
21
|
+
const expectedVersion = String(pkg.version || '').trim();
|
|
22
|
+
|
|
23
|
+
if (!expectedVersion) {
|
|
24
|
+
console.error('Error: package.json version is empty');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const ext = process.platform === 'win32' ? '.exe' : '';
|
|
29
|
+
const hostBinaryName = `agent-browser-${process.platform}-${process.arch}${ext}`;
|
|
30
|
+
|
|
31
|
+
let tempDir = '';
|
|
32
|
+
let packedTarball = '';
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const packRaw = execFileSync('npm', ['pack', '--json'], {
|
|
36
|
+
cwd: rootDir,
|
|
37
|
+
encoding: 'utf8',
|
|
38
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
39
|
+
});
|
|
40
|
+
const parsed = JSON.parse(packRaw);
|
|
41
|
+
const filename = parsed?.[0]?.filename;
|
|
42
|
+
if (!filename || typeof filename !== 'string') {
|
|
43
|
+
throw new Error(`unexpected npm pack output: ${packRaw}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
packedTarball = join(rootDir, filename);
|
|
47
|
+
if (!existsSync(packedTarball)) {
|
|
48
|
+
throw new Error(`tarball not found: ${packedTarball}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
tempDir = mkdtempSync(join(tmpdir(), 'ab-pack-verify-'));
|
|
52
|
+
execFileSync('tar', ['-xzf', packedTarball, '-C', tempDir], {
|
|
53
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const packedRoot = join(tempDir, 'package');
|
|
57
|
+
const packedPkg = JSON.parse(readFileSync(join(packedRoot, 'package.json'), 'utf8'));
|
|
58
|
+
if (String(packedPkg.version || '').trim() !== expectedVersion) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`packed package.json version mismatch: expected ${expectedVersion}, got ${packedPkg.version}`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const packedBinary = join(packedRoot, 'bin', hostBinaryName);
|
|
65
|
+
if (!existsSync(packedBinary)) {
|
|
66
|
+
throw new Error(`host binary missing in tarball: bin/${hostBinaryName}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const binaryVersion = execFileSync(packedBinary, ['--version'], {
|
|
70
|
+
encoding: 'utf8',
|
|
71
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
72
|
+
}).trim();
|
|
73
|
+
|
|
74
|
+
if (!binaryVersion.includes(expectedVersion)) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`tarball host binary version mismatch: expected ${expectedVersion}, got "${binaryVersion}"`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(`✓ Packed tarball host binary matches package.json (${expectedVersion})`);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
83
|
+
console.error(`Error: ${message}`);
|
|
84
|
+
process.exitCode = 1;
|
|
85
|
+
} finally {
|
|
86
|
+
if (tempDir) rmSync(tempDir, { recursive: true, force: true });
|
|
87
|
+
if (packedTarball && existsSync(packedTarball)) unlinkSync(packedTarball);
|
|
88
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Download the published npm tarball and verify that the bundled host-platform
|
|
5
|
+
* native binary reports the expected package version.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createWriteStream, existsSync, mkdtempSync, readFileSync, rmSync, unlinkSync } from 'fs';
|
|
9
|
+
import { tmpdir } from 'os';
|
|
10
|
+
import { dirname, join } from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import { execFileSync } from 'child_process';
|
|
13
|
+
import { get } from 'https';
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const rootDir = join(__dirname, '..');
|
|
17
|
+
|
|
18
|
+
const pkg = JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf8'));
|
|
19
|
+
const packageName = process.env.PACKAGE_NAME || pkg.name || 'agent-browser-stealth';
|
|
20
|
+
const expectedVersion = process.env.EXPECTED_VERSION || pkg.version;
|
|
21
|
+
|
|
22
|
+
if (!expectedVersion) {
|
|
23
|
+
console.error('Error: expected version is empty');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const ext = process.platform === 'win32' ? '.exe' : '';
|
|
28
|
+
const hostBinaryName = `agent-browser-${process.platform}-${process.arch}${ext}`;
|
|
29
|
+
|
|
30
|
+
function downloadFile(url, dest) {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const file = createWriteStream(dest);
|
|
33
|
+
|
|
34
|
+
const request = (currentUrl) => {
|
|
35
|
+
get(currentUrl, (response) => {
|
|
36
|
+
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
37
|
+
request(response.headers.location);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (response.statusCode !== 200) {
|
|
42
|
+
reject(new Error(`Failed to download tarball: HTTP ${response.statusCode}`));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
response.pipe(file);
|
|
47
|
+
file.on('finish', () => {
|
|
48
|
+
file.close();
|
|
49
|
+
resolve();
|
|
50
|
+
});
|
|
51
|
+
}).on('error', (err) => {
|
|
52
|
+
reject(err);
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
request(url);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let tempDir = '';
|
|
61
|
+
let tarballPath = '';
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const tarballUrl = execFileSync(
|
|
65
|
+
'npm',
|
|
66
|
+
['view', `${packageName}@${expectedVersion}`, 'dist.tarball'],
|
|
67
|
+
{
|
|
68
|
+
cwd: rootDir,
|
|
69
|
+
encoding: 'utf8',
|
|
70
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
71
|
+
}
|
|
72
|
+
).trim();
|
|
73
|
+
|
|
74
|
+
if (!tarballUrl) {
|
|
75
|
+
throw new Error(`could not resolve dist.tarball for ${packageName}@${expectedVersion}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
tempDir = mkdtempSync(join(tmpdir(), 'ab-registry-verify-'));
|
|
79
|
+
tarballPath = join(tempDir, 'package.tgz');
|
|
80
|
+
await downloadFile(tarballUrl, tarballPath);
|
|
81
|
+
|
|
82
|
+
execFileSync('tar', ['-xzf', tarballPath, '-C', tempDir], {
|
|
83
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const packedRoot = join(tempDir, 'package');
|
|
87
|
+
const packedPkg = JSON.parse(readFileSync(join(packedRoot, 'package.json'), 'utf8'));
|
|
88
|
+
if (String(packedPkg.version || '').trim() !== expectedVersion) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`registry package.json version mismatch: expected ${expectedVersion}, got ${packedPkg.version}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const packedBinary = join(packedRoot, 'bin', hostBinaryName);
|
|
95
|
+
if (!existsSync(packedBinary)) {
|
|
96
|
+
throw new Error(`host binary missing in registry tarball: bin/${hostBinaryName}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const binaryVersion = execFileSync(packedBinary, ['--version'], {
|
|
100
|
+
encoding: 'utf8',
|
|
101
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
102
|
+
}).trim();
|
|
103
|
+
|
|
104
|
+
if (!binaryVersion.includes(expectedVersion)) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`registry host binary version mismatch: expected ${expectedVersion}, got "${binaryVersion}"`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log(
|
|
111
|
+
`✓ Registry tarball host binary matches package.json (${packageName}@${expectedVersion})`
|
|
112
|
+
);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
115
|
+
console.error(`Error: ${message}`);
|
|
116
|
+
process.exitCode = 1;
|
|
117
|
+
} finally {
|
|
118
|
+
if (tarballPath && existsSync(tarballPath)) unlinkSync(tarballPath);
|
|
119
|
+
if (tempDir) rmSync(tempDir, { recursive: true, force: true });
|
|
120
|
+
}
|
|
@@ -286,7 +286,10 @@ Notes:
|
|
|
286
286
|
- non-default session: `Agent Browser Stealth • <session>`
|
|
287
287
|
- Additional extension-side capabilities:
|
|
288
288
|
- Session window isolation + deterministic group colors.
|
|
289
|
-
- Side panel controls:
|
|
289
|
+
- Side panel browser controls: `open` / `back` / `forward` / `reload` + selector-based `click` / `fill` / `press`.
|
|
290
|
+
- Side panel developer signals: page console events, fetch/xhr network events, command history, and on-demand DOM snapshots.
|
|
291
|
+
- Side panel automation: action recording, workflow run, slash shortcut binding, and scheduled execution (daily/weekly/monthly/yearly).
|
|
292
|
+
- Side panel operations: Focus / Keep Only This / Clean Empty Groups + isolation/auto-clean toggles.
|
|
290
293
|
- Session allowlist policy editing and fallback blocking (`about:blank`).
|
|
291
294
|
- Download auto-routing to `agent-browser-stealth/<session>/...`.
|
|
292
295
|
|