agent-browser-stealth 0.14.0
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/LICENSE +201 -0
- package/README.md +1219 -0
- package/bin/agent-browser-darwin-arm64 +0 -0
- package/bin/agent-browser-local +0 -0
- package/bin/agent-browser.js +109 -0
- package/dist/actions.d.ts +17 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +1917 -0
- package/dist/actions.js.map +1 -0
- package/dist/browser.d.ts +598 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +2287 -0
- package/dist/browser.js.map +1 -0
- package/dist/daemon.d.ts +66 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +603 -0
- package/dist/daemon.js.map +1 -0
- package/dist/diff.d.ts +18 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +271 -0
- package/dist/diff.js.map +1 -0
- package/dist/encryption.d.ts +50 -0
- package/dist/encryption.d.ts.map +1 -0
- package/dist/encryption.js +85 -0
- package/dist/encryption.js.map +1 -0
- package/dist/ios-actions.d.ts +11 -0
- package/dist/ios-actions.d.ts.map +1 -0
- package/dist/ios-actions.js +228 -0
- package/dist/ios-actions.js.map +1 -0
- package/dist/ios-manager.d.ts +266 -0
- package/dist/ios-manager.d.ts.map +1 -0
- package/dist/ios-manager.js +1073 -0
- package/dist/ios-manager.js.map +1 -0
- package/dist/protocol.d.ts +26 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +935 -0
- package/dist/protocol.js.map +1 -0
- package/dist/snapshot.d.ts +67 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +514 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/state-utils.d.ts +77 -0
- package/dist/state-utils.d.ts.map +1 -0
- package/dist/state-utils.js +178 -0
- package/dist/state-utils.js.map +1 -0
- package/dist/stealth.d.ts +22 -0
- package/dist/stealth.d.ts.map +1 -0
- package/dist/stealth.js +614 -0
- package/dist/stealth.js.map +1 -0
- package/dist/stream-server.d.ts +117 -0
- package/dist/stream-server.d.ts.map +1 -0
- package/dist/stream-server.js +309 -0
- package/dist/stream-server.js.map +1 -0
- package/dist/types.d.ts +855 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +85 -0
- package/scripts/build-all-platforms.sh +68 -0
- package/scripts/check-creepjs-headless.js +137 -0
- package/scripts/check-sannysoft-webdriver.js +112 -0
- package/scripts/check-version-sync.js +39 -0
- package/scripts/copy-native.js +36 -0
- package/scripts/postinstall.js +275 -0
- package/scripts/sync-upstream.sh +142 -0
- package/scripts/sync-version.js +69 -0
- package/skills/agent-browser/SKILL.md +464 -0
- package/skills/agent-browser/references/authentication.md +202 -0
- package/skills/agent-browser/references/commands.md +263 -0
- package/skills/agent-browser/references/profiling.md +120 -0
- package/skills/agent-browser/references/proxy-support.md +194 -0
- package/skills/agent-browser/references/session-management.md +193 -0
- package/skills/agent-browser/references/snapshot-refs.md +194 -0
- package/skills/agent-browser/references/video-recording.md +173 -0
- package/skills/agent-browser/templates/authenticated-session.sh +100 -0
- package/skills/agent-browser/templates/capture-workflow.sh +69 -0
- package/skills/agent-browser/templates/form-automation.sh +62 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Postinstall script for agent-browser
|
|
5
|
+
*
|
|
6
|
+
* Downloads the platform-specific native binary if not present.
|
|
7
|
+
* On global installs, patches npm's bin entry to use the native binary directly:
|
|
8
|
+
* - Windows: Overwrites .cmd/.ps1 shims
|
|
9
|
+
* - Mac/Linux: Replaces symlink to point to native binary
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync, mkdirSync, chmodSync, createWriteStream, unlinkSync, writeFileSync, symlinkSync, lstatSync, readFileSync } from 'fs';
|
|
13
|
+
import { dirname, join } from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { platform, arch } from 'os';
|
|
16
|
+
import { get } from 'https';
|
|
17
|
+
import { execSync } from 'child_process';
|
|
18
|
+
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const projectRoot = join(__dirname, '..');
|
|
21
|
+
const binDir = join(projectRoot, 'bin');
|
|
22
|
+
|
|
23
|
+
// Platform detection
|
|
24
|
+
const platformKey = `${platform()}-${arch()}`;
|
|
25
|
+
const ext = platform() === 'win32' ? '.exe' : '';
|
|
26
|
+
const binaryName = `agent-browser-${platformKey}${ext}`;
|
|
27
|
+
const binaryPath = join(binDir, binaryName);
|
|
28
|
+
|
|
29
|
+
// Package info
|
|
30
|
+
const packageJson = JSON.parse(readFileSync(join(projectRoot, 'package.json'), 'utf8'));
|
|
31
|
+
const version = packageJson.version;
|
|
32
|
+
const packageName = packageJson.name;
|
|
33
|
+
const binCommands = getBinCommands(packageJson);
|
|
34
|
+
|
|
35
|
+
// GitHub release URL
|
|
36
|
+
const GITHUB_REPO = getGitHubRepoFromPackage(packageJson);
|
|
37
|
+
const DOWNLOAD_URL = `https://github.com/${GITHUB_REPO}/releases/download/v${version}/${binaryName}`;
|
|
38
|
+
|
|
39
|
+
function getGitHubRepoFromPackage(pkg) {
|
|
40
|
+
const repo = pkg?.repository;
|
|
41
|
+
const repoUrl = typeof repo === 'string' ? repo : repo?.url;
|
|
42
|
+
|
|
43
|
+
if (typeof repoUrl === 'string') {
|
|
44
|
+
const match = repoUrl.match(/github\.com[:/]([^/]+\/[^/.]+)(?:\.git)?$/i);
|
|
45
|
+
if (match?.[1]) {
|
|
46
|
+
return match[1];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Fallback for legacy package metadata
|
|
51
|
+
return 'vercel-labs/agent-browser';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getBinCommands(pkg) {
|
|
55
|
+
const bin = pkg?.bin;
|
|
56
|
+
if (typeof bin === 'string') {
|
|
57
|
+
return [pkg.name.replace(/^@[^/]+\//, '')];
|
|
58
|
+
}
|
|
59
|
+
if (bin && typeof bin === 'object') {
|
|
60
|
+
return Object.keys(bin);
|
|
61
|
+
}
|
|
62
|
+
return ['agent-browser'];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function downloadFile(url, dest) {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const file = createWriteStream(dest);
|
|
68
|
+
|
|
69
|
+
const request = (url) => {
|
|
70
|
+
get(url, (response) => {
|
|
71
|
+
// Handle redirects
|
|
72
|
+
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
73
|
+
request(response.headers.location);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (response.statusCode !== 200) {
|
|
78
|
+
reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
response.pipe(file);
|
|
83
|
+
file.on('finish', () => {
|
|
84
|
+
file.close();
|
|
85
|
+
resolve();
|
|
86
|
+
});
|
|
87
|
+
}).on('error', (err) => {
|
|
88
|
+
unlinkSync(dest);
|
|
89
|
+
reject(err);
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
request(url);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function main() {
|
|
98
|
+
// Check if binary already exists
|
|
99
|
+
if (existsSync(binaryPath)) {
|
|
100
|
+
// Ensure binary is executable (npm doesn't preserve execute bit)
|
|
101
|
+
if (platform() !== 'win32') {
|
|
102
|
+
chmodSync(binaryPath, 0o755);
|
|
103
|
+
}
|
|
104
|
+
console.log(`✓ Native binary ready: ${binaryName}`);
|
|
105
|
+
|
|
106
|
+
// On global installs, fix npm's bin entry to use native binary directly
|
|
107
|
+
await fixGlobalInstallBin();
|
|
108
|
+
|
|
109
|
+
showPlaywrightReminder();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Ensure bin directory exists
|
|
114
|
+
if (!existsSync(binDir)) {
|
|
115
|
+
mkdirSync(binDir, { recursive: true });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(`Downloading native binary for ${platformKey}...`);
|
|
119
|
+
console.log(`URL: ${DOWNLOAD_URL}`);
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
await downloadFile(DOWNLOAD_URL, binaryPath);
|
|
123
|
+
|
|
124
|
+
// Make executable on Unix
|
|
125
|
+
if (platform() !== 'win32') {
|
|
126
|
+
chmodSync(binaryPath, 0o755);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log(`✓ Downloaded native binary: ${binaryName}`);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.log(`⚠ Could not download native binary: ${err.message}`);
|
|
132
|
+
console.log(` The CLI will use Node.js fallback (slightly slower startup)`);
|
|
133
|
+
console.log('');
|
|
134
|
+
console.log('To build the native binary locally:');
|
|
135
|
+
console.log(' 1. Install Rust: https://rustup.rs');
|
|
136
|
+
console.log(' 2. Run: pnpm run build:native');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// On global installs, fix npm's bin entry to use native binary directly
|
|
140
|
+
// This avoids the /bin/sh error on Windows and provides zero-overhead execution
|
|
141
|
+
await fixGlobalInstallBin();
|
|
142
|
+
|
|
143
|
+
showPlaywrightReminder();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function showPlaywrightReminder() {
|
|
147
|
+
console.log('');
|
|
148
|
+
console.log('╔═══════════════════════════════════════════════════════════════════════════╗');
|
|
149
|
+
console.log('║ To download browser binaries, run: ║');
|
|
150
|
+
console.log('║ ║');
|
|
151
|
+
console.log('║ npx playwright install chromium ║');
|
|
152
|
+
console.log('║ ║');
|
|
153
|
+
console.log('║ On Linux, include system dependencies with: ║');
|
|
154
|
+
console.log('║ ║');
|
|
155
|
+
console.log('║ npx playwright install --with-deps chromium ║');
|
|
156
|
+
console.log('║ ║');
|
|
157
|
+
console.log('╚═══════════════════════════════════════════════════════════════════════════╝');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Fix npm's bin entry on global installs to use the native binary directly.
|
|
162
|
+
* This provides zero-overhead CLI execution for global installs.
|
|
163
|
+
*/
|
|
164
|
+
async function fixGlobalInstallBin() {
|
|
165
|
+
if (platform() === 'win32') {
|
|
166
|
+
await fixWindowsShims();
|
|
167
|
+
} else {
|
|
168
|
+
await fixUnixSymlink();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Fix npm symlink on Mac/Linux global installs.
|
|
174
|
+
* Replace the symlink to the JS wrapper with a symlink to the native binary.
|
|
175
|
+
*/
|
|
176
|
+
async function fixUnixSymlink() {
|
|
177
|
+
// Get npm's global bin directory (npm prefix -g + /bin)
|
|
178
|
+
let npmBinDir;
|
|
179
|
+
try {
|
|
180
|
+
const prefix = execSync('npm prefix -g', { encoding: 'utf8' }).trim();
|
|
181
|
+
npmBinDir = join(prefix, 'bin');
|
|
182
|
+
} catch {
|
|
183
|
+
return; // npm not available
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let optimized = false;
|
|
187
|
+
for (const commandName of binCommands) {
|
|
188
|
+
const symlinkPath = join(npmBinDir, commandName);
|
|
189
|
+
|
|
190
|
+
// Check if symlink exists (indicates global install)
|
|
191
|
+
try {
|
|
192
|
+
const stat = lstatSync(symlinkPath);
|
|
193
|
+
if (!stat.isSymbolicLink()) {
|
|
194
|
+
continue; // Not a symlink, don't touch it
|
|
195
|
+
}
|
|
196
|
+
} catch {
|
|
197
|
+
continue; // Symlink doesn't exist, not a global install
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Replace symlink to point directly to native binary
|
|
201
|
+
try {
|
|
202
|
+
unlinkSync(symlinkPath);
|
|
203
|
+
symlinkSync(binaryPath, symlinkPath);
|
|
204
|
+
optimized = true;
|
|
205
|
+
} catch (err) {
|
|
206
|
+
// Permission error or other issue - not critical, JS wrapper still works
|
|
207
|
+
console.log(`⚠ Could not optimize symlink (${commandName}): ${err.message}`);
|
|
208
|
+
console.log(' CLI will work via Node.js wrapper (slightly slower startup)');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (optimized) {
|
|
213
|
+
console.log('✓ Optimized: symlink points to native binary (zero overhead)');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Fix npm-generated shims on Windows global installs.
|
|
219
|
+
* npm generates shims that try to run /bin/sh, which doesn't exist on Windows.
|
|
220
|
+
* We overwrite them to invoke the native .exe directly.
|
|
221
|
+
*/
|
|
222
|
+
async function fixWindowsShims() {
|
|
223
|
+
// Check if this is a global install by looking for npm's global prefix
|
|
224
|
+
let npmBinDir;
|
|
225
|
+
try {
|
|
226
|
+
npmBinDir = execSync('npm prefix -g', { encoding: 'utf8' }).trim();
|
|
227
|
+
} catch {
|
|
228
|
+
return; // Not a global install or npm not available
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Path to native binary relative to npm prefix
|
|
232
|
+
const packagePath = packageName.replace(/\//g, '\\');
|
|
233
|
+
const relativeBinaryPath = `node_modules\\${packagePath}\\bin\\${binaryName}`;
|
|
234
|
+
let optimized = false;
|
|
235
|
+
|
|
236
|
+
for (const commandName of binCommands) {
|
|
237
|
+
// The shims are in the npm prefix directory (not prefix/bin on Windows)
|
|
238
|
+
const cmdShim = join(npmBinDir, `${commandName}.cmd`);
|
|
239
|
+
const ps1Shim = join(npmBinDir, `${commandName}.ps1`);
|
|
240
|
+
|
|
241
|
+
// Only fix if shims exist (indicates global install)
|
|
242
|
+
if (!existsSync(cmdShim)) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
// Overwrite .cmd shim
|
|
248
|
+
const cmdContent = `@ECHO off\r\n"%~dp0${relativeBinaryPath}" %*\r\n`;
|
|
249
|
+
writeFileSync(cmdShim, cmdContent);
|
|
250
|
+
|
|
251
|
+
// Overwrite .ps1 shim
|
|
252
|
+
const ps1Content = `#!/usr/bin/env pwsh
|
|
253
|
+
$basedir = Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
254
|
+
$exe = ""
|
|
255
|
+
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
256
|
+
$exe = ".exe"
|
|
257
|
+
}
|
|
258
|
+
& "$basedir/${relativeBinaryPath.replace(/\\/g, '/')}" $args
|
|
259
|
+
exit $LASTEXITCODE
|
|
260
|
+
`;
|
|
261
|
+
writeFileSync(ps1Shim, ps1Content);
|
|
262
|
+
optimized = true;
|
|
263
|
+
} catch (err) {
|
|
264
|
+
// Permission error or other issue - not critical, JS wrapper still works
|
|
265
|
+
console.log(`⚠ Could not optimize shims (${commandName}): ${err.message}`);
|
|
266
|
+
console.log(' CLI will work via Node.js wrapper (slightly slower startup)');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (optimized) {
|
|
271
|
+
console.log('✓ Optimized: shims point to native binary (zero overhead)');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
UPSTREAM_REMOTE="upstream"
|
|
5
|
+
UPSTREAM_BRANCH="main"
|
|
6
|
+
BASE_BRANCH="main"
|
|
7
|
+
TRACK_BRANCH="upstream-main"
|
|
8
|
+
SYNC_BRANCH=""
|
|
9
|
+
PUSH_BRANCH=false
|
|
10
|
+
|
|
11
|
+
usage() {
|
|
12
|
+
cat <<'EOF'
|
|
13
|
+
Synchronize upstream changes into a dedicated sync branch.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
./scripts/sync-upstream.sh [options]
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--push Push the created sync branch to origin
|
|
20
|
+
--upstream-remote <name> Upstream remote name (default: upstream)
|
|
21
|
+
--upstream-branch <name> Upstream branch to sync from (default: main)
|
|
22
|
+
--base-branch <name> Local base branch for sync branch (default: main)
|
|
23
|
+
--track-branch <name> Local branch tracking upstream (default: upstream-main)
|
|
24
|
+
--sync-branch <name> Explicit sync branch name (default: sync/YYYY-MM-DD)
|
|
25
|
+
-h, --help Show this help message
|
|
26
|
+
EOF
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
while [[ $# -gt 0 ]]; do
|
|
30
|
+
case "$1" in
|
|
31
|
+
--push)
|
|
32
|
+
PUSH_BRANCH=true
|
|
33
|
+
shift
|
|
34
|
+
;;
|
|
35
|
+
--upstream-remote)
|
|
36
|
+
UPSTREAM_REMOTE="${2:-}"
|
|
37
|
+
shift 2
|
|
38
|
+
;;
|
|
39
|
+
--upstream-branch)
|
|
40
|
+
UPSTREAM_BRANCH="${2:-}"
|
|
41
|
+
shift 2
|
|
42
|
+
;;
|
|
43
|
+
--base-branch)
|
|
44
|
+
BASE_BRANCH="${2:-}"
|
|
45
|
+
shift 2
|
|
46
|
+
;;
|
|
47
|
+
--track-branch)
|
|
48
|
+
TRACK_BRANCH="${2:-}"
|
|
49
|
+
shift 2
|
|
50
|
+
;;
|
|
51
|
+
--sync-branch)
|
|
52
|
+
SYNC_BRANCH="${2:-}"
|
|
53
|
+
shift 2
|
|
54
|
+
;;
|
|
55
|
+
-h|--help)
|
|
56
|
+
usage
|
|
57
|
+
exit 0
|
|
58
|
+
;;
|
|
59
|
+
*)
|
|
60
|
+
echo "Unknown option: $1" >&2
|
|
61
|
+
usage
|
|
62
|
+
exit 1
|
|
63
|
+
;;
|
|
64
|
+
esac
|
|
65
|
+
done
|
|
66
|
+
|
|
67
|
+
for var_name in UPSTREAM_REMOTE UPSTREAM_BRANCH BASE_BRANCH TRACK_BRANCH; do
|
|
68
|
+
if [[ -z "${!var_name}" ]]; then
|
|
69
|
+
echo "Error: ${var_name} cannot be empty." >&2
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|
|
72
|
+
done
|
|
73
|
+
|
|
74
|
+
if [[ -n "$(git status --porcelain)" ]]; then
|
|
75
|
+
echo "Error: working tree is not clean. Commit or stash changes first." >&2
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
if ! git remote get-url "$UPSTREAM_REMOTE" >/dev/null 2>&1; then
|
|
80
|
+
echo "Error: remote '$UPSTREAM_REMOTE' does not exist." >&2
|
|
81
|
+
exit 1
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
echo "Fetching upstream branch: ${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}"
|
|
85
|
+
git fetch "$UPSTREAM_REMOTE" "$UPSTREAM_BRANCH"
|
|
86
|
+
|
|
87
|
+
if git show-ref --verify --quiet "refs/heads/$TRACK_BRANCH"; then
|
|
88
|
+
echo "Updating local track branch: $TRACK_BRANCH"
|
|
89
|
+
git switch "$TRACK_BRANCH" >/dev/null
|
|
90
|
+
git merge --ff-only "${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}"
|
|
91
|
+
else
|
|
92
|
+
echo "Creating local track branch: $TRACK_BRANCH"
|
|
93
|
+
git branch "$TRACK_BRANCH" "${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}"
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
echo "Switching to base branch: $BASE_BRANCH"
|
|
97
|
+
git switch "$BASE_BRANCH" >/dev/null
|
|
98
|
+
|
|
99
|
+
if git show-ref --verify --quiet "refs/remotes/origin/$BASE_BRANCH"; then
|
|
100
|
+
echo "Fast-forwarding ${BASE_BRANCH} from origin/${BASE_BRANCH}"
|
|
101
|
+
git fetch origin "$BASE_BRANCH"
|
|
102
|
+
git merge --ff-only "origin/${BASE_BRANCH}"
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
if [[ -z "$SYNC_BRANCH" ]]; then
|
|
106
|
+
SYNC_BRANCH="sync/$(date +%F)"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
if git show-ref --verify --quiet "refs/heads/$SYNC_BRANCH"; then
|
|
110
|
+
suffix=1
|
|
111
|
+
while git show-ref --verify --quiet "refs/heads/${SYNC_BRANCH}-${suffix}"; do
|
|
112
|
+
suffix=$((suffix + 1))
|
|
113
|
+
done
|
|
114
|
+
SYNC_BRANCH="${SYNC_BRANCH}-${suffix}"
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
echo "Creating sync branch: $SYNC_BRANCH"
|
|
118
|
+
git switch -c "$SYNC_BRANCH" "$BASE_BRANCH" >/dev/null
|
|
119
|
+
|
|
120
|
+
merge_message="chore(sync): merge ${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH} into ${BASE_BRANCH}"
|
|
121
|
+
echo "Merging $TRACK_BRANCH into $SYNC_BRANCH"
|
|
122
|
+
if ! git merge --no-ff "$TRACK_BRANCH" -m "$merge_message"; then
|
|
123
|
+
echo ""
|
|
124
|
+
echo "Merge conflict detected. Resolve conflicts, then run:"
|
|
125
|
+
echo " git add <resolved-files>"
|
|
126
|
+
echo " git commit"
|
|
127
|
+
if [[ "$PUSH_BRANCH" == true ]]; then
|
|
128
|
+
echo " git push -u origin $SYNC_BRANCH"
|
|
129
|
+
fi
|
|
130
|
+
exit 1
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
echo "Upstream merge completed on branch: $SYNC_BRANCH"
|
|
134
|
+
|
|
135
|
+
if [[ "$PUSH_BRANCH" == true ]]; then
|
|
136
|
+
echo "Pushing branch to origin: $SYNC_BRANCH"
|
|
137
|
+
git push -u origin "$SYNC_BRANCH"
|
|
138
|
+
echo "Done. Open a PR: ${SYNC_BRANCH} -> ${BASE_BRANCH}"
|
|
139
|
+
else
|
|
140
|
+
echo "Branch is local only. Push when ready:"
|
|
141
|
+
echo " git push -u origin $SYNC_BRANCH"
|
|
142
|
+
fi
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Syncs the version from package.json to all other config files.
|
|
5
|
+
* Run this script before building or releasing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execSync } from "child_process";
|
|
9
|
+
import { readFileSync, writeFileSync } 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
|
+
const cliDir = join(rootDir, "cli");
|
|
16
|
+
|
|
17
|
+
// Read version from package.json (single source of truth)
|
|
18
|
+
const packageJson = JSON.parse(
|
|
19
|
+
readFileSync(join(rootDir, "package.json"), "utf-8")
|
|
20
|
+
);
|
|
21
|
+
const version = packageJson.version;
|
|
22
|
+
|
|
23
|
+
console.log(`Syncing version ${version} to all config files...`);
|
|
24
|
+
|
|
25
|
+
// Update Cargo.toml
|
|
26
|
+
const cargoTomlPath = join(cliDir, "Cargo.toml");
|
|
27
|
+
let cargoToml = readFileSync(cargoTomlPath, "utf-8");
|
|
28
|
+
const cargoVersionRegex = /^version\s*=\s*"[^"]*"/m;
|
|
29
|
+
const newCargoVersion = `version = "${version}"`;
|
|
30
|
+
|
|
31
|
+
let cargoTomlUpdated = false;
|
|
32
|
+
if (cargoVersionRegex.test(cargoToml)) {
|
|
33
|
+
const oldMatch = cargoToml.match(cargoVersionRegex)?.[0];
|
|
34
|
+
if (oldMatch !== newCargoVersion) {
|
|
35
|
+
cargoToml = cargoToml.replace(cargoVersionRegex, newCargoVersion);
|
|
36
|
+
writeFileSync(cargoTomlPath, cargoToml);
|
|
37
|
+
console.log(` Updated cli/Cargo.toml: ${oldMatch} -> ${newCargoVersion}`);
|
|
38
|
+
cargoTomlUpdated = true;
|
|
39
|
+
} else {
|
|
40
|
+
console.log(` cli/Cargo.toml already up to date`);
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
console.error(" Could not find version field in cli/Cargo.toml");
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Update Cargo.lock to match Cargo.toml
|
|
48
|
+
if (cargoTomlUpdated) {
|
|
49
|
+
try {
|
|
50
|
+
execSync("cargo update -p agent-browser --offline", {
|
|
51
|
+
cwd: cliDir,
|
|
52
|
+
stdio: "pipe",
|
|
53
|
+
});
|
|
54
|
+
console.log(` Updated cli/Cargo.lock`);
|
|
55
|
+
} catch {
|
|
56
|
+
// --offline may fail if package not in cache, try without it
|
|
57
|
+
try {
|
|
58
|
+
execSync("cargo update -p agent-browser", {
|
|
59
|
+
cwd: cliDir,
|
|
60
|
+
stdio: "pipe",
|
|
61
|
+
});
|
|
62
|
+
console.log(` Updated cli/Cargo.lock`);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.error(` Warning: Could not update Cargo.lock: ${e.message}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log("Version sync complete.");
|