@browserbasehq/browse-cli 0.4.2 → 0.5.0-alpha-34598b9
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 +12 -11
- package/dist/index.js +229 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -173,22 +173,23 @@ browse env
|
|
|
173
173
|
# Switch current session to Browserbase (restarts daemon if needed)
|
|
174
174
|
browse env remote
|
|
175
175
|
|
|
176
|
-
# Switch back to local Chrome (
|
|
176
|
+
# Switch back to local Chrome (clean isolated browser by default)
|
|
177
177
|
browse env local
|
|
178
178
|
```
|
|
179
179
|
|
|
180
180
|
#### Local Browser Strategies
|
|
181
181
|
|
|
182
|
-
By default, `browse env local`
|
|
183
|
-
|
|
184
|
-
If no debuggable Chrome is found, it
|
|
182
|
+
By default, `browse env local` launches a clean isolated local browser.
|
|
183
|
+
Use `browse env local --auto-connect` to opt into reusing an already-running
|
|
184
|
+
Chrome with remote debugging enabled. If no debuggable Chrome is found, it
|
|
185
|
+
falls back to launching an isolated browser.
|
|
185
186
|
|
|
186
187
|
```bash
|
|
187
|
-
#
|
|
188
|
+
# Use a clean isolated browser (default)
|
|
188
189
|
browse env local
|
|
189
190
|
|
|
190
|
-
#
|
|
191
|
-
browse env local --
|
|
191
|
+
# Auto-discover local Chrome, fallback to isolated
|
|
192
|
+
browse env local --auto-connect
|
|
192
193
|
|
|
193
194
|
# Attach to a specific CDP target (port or URL)
|
|
194
195
|
browse env local 9222
|
|
@@ -210,7 +211,7 @@ Use `browse status` to see which strategy was resolved:
|
|
|
210
211
|
|
|
211
212
|
```bash
|
|
212
213
|
browse status
|
|
213
|
-
# {"running":true,"session":"default","mode":"local","localStrategy":"
|
|
214
|
+
# {"running":true,"session":"default","mode":"local","localStrategy":"isolated","localSource":"isolated"}
|
|
214
215
|
```
|
|
215
216
|
|
|
216
217
|
#### General Behavior
|
|
@@ -283,19 +284,19 @@ browse --session personal open https://twitter.com
|
|
|
283
284
|
|
|
284
285
|
## Direct CDP Connection
|
|
285
286
|
|
|
286
|
-
|
|
287
|
+
Opt into using an existing Chrome instance:
|
|
287
288
|
|
|
288
289
|
To make your Chrome discoverable:
|
|
289
290
|
|
|
290
291
|
1. Open `chrome://inspect/#remote-debugging`
|
|
291
292
|
2. Check the box **"Allow remote debugging for this browser instance"**
|
|
292
|
-
3. Re-run the CLI
|
|
293
|
+
3. Re-run the CLI with auto-connect enabled.
|
|
293
294
|
|
|
294
295
|
For more information, see the [Chrome DevTools docs](https://developer.chrome.com/blog/chrome-devtools-mcp-debug-your-browser-session).
|
|
295
296
|
|
|
296
297
|
```bash
|
|
297
298
|
# Auto-discover Chrome with remote debugging enabled
|
|
298
|
-
browse env local
|
|
299
|
+
browse env local --auto-connect
|
|
299
300
|
browse open https://example.com
|
|
300
301
|
|
|
301
302
|
# Or target a specific port / WebSocket URL
|
package/dist/index.js
CHANGED
|
@@ -164652,7 +164652,72 @@ var import_child_process4 = require("child_process");
|
|
|
164652
164652
|
var readline = __toESM(require("readline"));
|
|
164653
164653
|
|
|
164654
164654
|
// package.json
|
|
164655
|
-
var version3 = "0.
|
|
164655
|
+
var version3 = "0.5.0";
|
|
164656
|
+
|
|
164657
|
+
// src/local-strategy.ts
|
|
164658
|
+
init_cjs_shims();
|
|
164659
|
+
var DEFAULT_LOCAL_CONFIG = { strategy: "isolated" };
|
|
164660
|
+
var ISOLATED_MODE_HINT = "Hint: Run `browse env local --auto-connect` to reuse your local browsing credentials and cookies.";
|
|
164661
|
+
var ATTACHED_EXISTING_HINT = "Hint: Run `browse env local` without `--auto-connect` to switch back to an isolated Chromium browser.";
|
|
164662
|
+
function getLocalModeHint(localConfig, localInfo) {
|
|
164663
|
+
if (localInfo?.localSource === "attached-existing") {
|
|
164664
|
+
return ATTACHED_EXISTING_HINT;
|
|
164665
|
+
}
|
|
164666
|
+
if (localInfo?.localSource === "isolated-fallback") {
|
|
164667
|
+
return null;
|
|
164668
|
+
}
|
|
164669
|
+
if (localConfig.strategy === "auto" && !localInfo) {
|
|
164670
|
+
return ATTACHED_EXISTING_HINT;
|
|
164671
|
+
}
|
|
164672
|
+
if (localInfo?.localSource === "isolated" || localConfig.strategy === "isolated" && !localInfo) {
|
|
164673
|
+
return ISOLATED_MODE_HINT;
|
|
164674
|
+
}
|
|
164675
|
+
return null;
|
|
164676
|
+
}
|
|
164677
|
+
async function resolveLocalStrategy({
|
|
164678
|
+
localConfig,
|
|
164679
|
+
headless,
|
|
164680
|
+
defaultViewport,
|
|
164681
|
+
discoverLocalCdp: discoverLocalCdp2,
|
|
164682
|
+
resolveWsTarget: resolveWsTarget2
|
|
164683
|
+
}) {
|
|
164684
|
+
if (localConfig.strategy === "isolated") {
|
|
164685
|
+
return {
|
|
164686
|
+
localLaunchOptions: { headless, viewport: defaultViewport },
|
|
164687
|
+
localInfo: { localSource: "isolated" }
|
|
164688
|
+
};
|
|
164689
|
+
}
|
|
164690
|
+
if (localConfig.strategy === "cdp") {
|
|
164691
|
+
if (!localConfig.cdpTarget) {
|
|
164692
|
+
throw new Error("Local CDP strategy requires a cdpTarget");
|
|
164693
|
+
}
|
|
164694
|
+
const cdpUrl = await resolveWsTarget2(localConfig.cdpTarget);
|
|
164695
|
+
return {
|
|
164696
|
+
localLaunchOptions: { cdpUrl },
|
|
164697
|
+
localInfo: {
|
|
164698
|
+
localSource: "attached-explicit",
|
|
164699
|
+
resolvedCdpUrl: cdpUrl
|
|
164700
|
+
}
|
|
164701
|
+
};
|
|
164702
|
+
}
|
|
164703
|
+
const discovered = await discoverLocalCdp2();
|
|
164704
|
+
if (discovered) {
|
|
164705
|
+
return {
|
|
164706
|
+
localLaunchOptions: { cdpUrl: discovered.wsUrl },
|
|
164707
|
+
localInfo: {
|
|
164708
|
+
localSource: "attached-existing",
|
|
164709
|
+
resolvedCdpUrl: discovered.wsUrl
|
|
164710
|
+
}
|
|
164711
|
+
};
|
|
164712
|
+
}
|
|
164713
|
+
return {
|
|
164714
|
+
localLaunchOptions: { headless, viewport: defaultViewport },
|
|
164715
|
+
localInfo: {
|
|
164716
|
+
localSource: "isolated-fallback",
|
|
164717
|
+
fallbackReason: "no debuggable local browser found"
|
|
164718
|
+
}
|
|
164719
|
+
};
|
|
164720
|
+
}
|
|
164656
164721
|
|
|
164657
164722
|
// src/resolve-ws.ts
|
|
164658
164723
|
init_cjs_shims();
|
|
@@ -164778,12 +164843,15 @@ function getLocalConfigPath(session) {
|
|
|
164778
164843
|
function getLocalInfoPath(session) {
|
|
164779
164844
|
return path11.join(SOCKET_DIR, `browse-${session}.local-info`);
|
|
164780
164845
|
}
|
|
164846
|
+
function getSessionParamsPath(session) {
|
|
164847
|
+
return path11.join(SOCKET_DIR, `browse-${session}.session-params`);
|
|
164848
|
+
}
|
|
164781
164849
|
async function readLocalConfig(session) {
|
|
164782
164850
|
try {
|
|
164783
164851
|
const raw = await import_fs11.promises.readFile(getLocalConfigPath(session), "utf-8");
|
|
164784
164852
|
return JSON.parse(raw);
|
|
164785
164853
|
} catch {
|
|
164786
|
-
return {
|
|
164854
|
+
return { ...DEFAULT_LOCAL_CONFIG };
|
|
164787
164855
|
}
|
|
164788
164856
|
}
|
|
164789
164857
|
async function writeLocalConfig(session, config3) {
|
|
@@ -164800,6 +164868,23 @@ async function readLocalInfo(session) {
|
|
|
164800
164868
|
return null;
|
|
164801
164869
|
}
|
|
164802
164870
|
}
|
|
164871
|
+
async function waitForLocalInfo(session, timeoutMs = 1500) {
|
|
164872
|
+
const startTime = Date.now();
|
|
164873
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
164874
|
+
const localInfo = await readLocalInfo(session);
|
|
164875
|
+
if (localInfo) {
|
|
164876
|
+
return localInfo;
|
|
164877
|
+
}
|
|
164878
|
+
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
164879
|
+
}
|
|
164880
|
+
return readLocalInfo(session);
|
|
164881
|
+
}
|
|
164882
|
+
function logLocalModeHint(localConfig, localInfo) {
|
|
164883
|
+
const hint = getLocalModeHint(localConfig, localInfo);
|
|
164884
|
+
if (hint) {
|
|
164885
|
+
console.error(hint);
|
|
164886
|
+
}
|
|
164887
|
+
}
|
|
164803
164888
|
function hasBrowserbaseCredentials() {
|
|
164804
164889
|
return Boolean(process.env.BROWSERBASE_API_KEY);
|
|
164805
164890
|
}
|
|
@@ -165017,7 +165102,8 @@ async function cleanupStaleFiles(session) {
|
|
|
165017
165102
|
// Client-written config, only cleaned on full shutdown
|
|
165018
165103
|
getContextPath(session),
|
|
165019
165104
|
getConnectPath(session),
|
|
165020
|
-
getLocalConfigPath(session)
|
|
165105
|
+
getLocalConfigPath(session),
|
|
165106
|
+
getSessionParamsPath(session)
|
|
165021
165107
|
];
|
|
165022
165108
|
for (const file2 of files) {
|
|
165023
165109
|
try {
|
|
@@ -165094,36 +165180,24 @@ async function runDaemon(session, headless) {
|
|
|
165094
165180
|
connectSessionId = (await import_fs11.promises.readFile(getConnectPath(session), "utf-8")).trim();
|
|
165095
165181
|
} catch {
|
|
165096
165182
|
}
|
|
165183
|
+
let sessionParams = {};
|
|
165184
|
+
try {
|
|
165185
|
+
const raw = await import_fs11.promises.readFile(getSessionParamsPath(session), "utf-8");
|
|
165186
|
+
sessionParams = JSON.parse(raw);
|
|
165187
|
+
} catch {
|
|
165188
|
+
}
|
|
165097
165189
|
let localLaunchOptions;
|
|
165098
165190
|
let localInfo;
|
|
165099
165191
|
if (!useBrowserbase) {
|
|
165100
|
-
const
|
|
165101
|
-
|
|
165102
|
-
|
|
165103
|
-
|
|
165104
|
-
|
|
165105
|
-
|
|
165106
|
-
|
|
165107
|
-
|
|
165108
|
-
|
|
165109
|
-
resolvedCdpUrl: cdpUrl
|
|
165110
|
-
};
|
|
165111
|
-
} else {
|
|
165112
|
-
const discovered = await discoverLocalCdp();
|
|
165113
|
-
if (discovered) {
|
|
165114
|
-
localLaunchOptions = { cdpUrl: discovered.wsUrl };
|
|
165115
|
-
localInfo = {
|
|
165116
|
-
localSource: "attached-existing",
|
|
165117
|
-
resolvedCdpUrl: discovered.wsUrl
|
|
165118
|
-
};
|
|
165119
|
-
} else {
|
|
165120
|
-
localLaunchOptions = { headless, viewport: DEFAULT_VIEWPORT2 };
|
|
165121
|
-
localInfo = {
|
|
165122
|
-
localSource: "isolated-fallback",
|
|
165123
|
-
fallbackReason: "no debuggable local browser found"
|
|
165124
|
-
};
|
|
165125
|
-
}
|
|
165126
|
-
}
|
|
165192
|
+
const resolvedLocalStrategy = await resolveLocalStrategy({
|
|
165193
|
+
localConfig: await readLocalConfig(session),
|
|
165194
|
+
headless,
|
|
165195
|
+
defaultViewport: DEFAULT_VIEWPORT2,
|
|
165196
|
+
discoverLocalCdp,
|
|
165197
|
+
resolveWsTarget
|
|
165198
|
+
});
|
|
165199
|
+
localLaunchOptions = resolvedLocalStrategy.localLaunchOptions;
|
|
165200
|
+
localInfo = resolvedLocalStrategy.localInfo;
|
|
165127
165201
|
}
|
|
165128
165202
|
stagehand = new V3({
|
|
165129
165203
|
env: useBrowserbase ? "BROWSERBASE" : "LOCAL",
|
|
@@ -165136,14 +165210,19 @@ async function runDaemon(session, headless) {
|
|
|
165136
165210
|
keepAlive: true
|
|
165137
165211
|
} : {},
|
|
165138
165212
|
...!connectSessionId ? {
|
|
165139
|
-
browserbaseSessionCreateParams: {
|
|
165140
|
-
|
|
165141
|
-
...
|
|
165213
|
+
browserbaseSessionCreateParams: (() => {
|
|
165214
|
+
const sessionBrowserSettings = sessionParams.browserSettings || {};
|
|
165215
|
+
const { browserSettings: _2, ...sessionParamsWithoutBS } = sessionParams;
|
|
165216
|
+
void _2;
|
|
165217
|
+
return {
|
|
165218
|
+
userMetadata: { browse_cli: "true" },
|
|
165219
|
+
...sessionParamsWithoutBS,
|
|
165142
165220
|
browserSettings: {
|
|
165143
|
-
|
|
165221
|
+
...sessionBrowserSettings,
|
|
165222
|
+
...contextConfig ? { context: contextConfig } : {}
|
|
165144
165223
|
}
|
|
165145
|
-
}
|
|
165146
|
-
}
|
|
165224
|
+
};
|
|
165225
|
+
})()
|
|
165147
165226
|
} : {}
|
|
165148
165227
|
} : {
|
|
165149
165228
|
localBrowserLaunchOptions: localLaunchOptions
|
|
@@ -165462,6 +165541,13 @@ async function executeCommand(context, command, args, stagehand) {
|
|
|
165462
165541
|
await stagehand.act(action);
|
|
165463
165542
|
return { selected: values };
|
|
165464
165543
|
}
|
|
165544
|
+
case "upload": {
|
|
165545
|
+
const [selector, filePaths] = args;
|
|
165546
|
+
const resolved = resolveSelector(selector);
|
|
165547
|
+
const files = filePaths.length === 1 ? filePaths[0] : filePaths;
|
|
165548
|
+
await page.deepLocator(resolved).setInputFiles(files);
|
|
165549
|
+
return { uploaded: true, files: filePaths };
|
|
165550
|
+
}
|
|
165465
165551
|
case "highlight": {
|
|
165466
165552
|
const [selector, duration3] = args;
|
|
165467
165553
|
await page.deepLocator(resolveSelector(selector)).highlight({ durationMs: duration3 ?? 2e3 });
|
|
@@ -165955,6 +166041,24 @@ function getSession(opts) {
|
|
|
165955
166041
|
function isHeadless(opts) {
|
|
165956
166042
|
return opts.headless === true && opts.headed !== true;
|
|
165957
166043
|
}
|
|
166044
|
+
function buildSessionParamsFromOpts(opts) {
|
|
166045
|
+
const params = {};
|
|
166046
|
+
const browserSettings = {};
|
|
166047
|
+
if (opts.proxies) params.proxies = true;
|
|
166048
|
+
if (opts.region) params.region = opts.region;
|
|
166049
|
+
if (opts.keepAlive) params.keepAlive = true;
|
|
166050
|
+
if (opts.sessionTimeout !== void 0) params.timeout = opts.sessionTimeout;
|
|
166051
|
+
if (opts.advancedStealth) browserSettings.advancedStealth = true;
|
|
166052
|
+
if (opts.blockAds) browserSettings.blockAds = true;
|
|
166053
|
+
if (opts.solveCaptchas !== void 0) {
|
|
166054
|
+
browserSettings.solveCaptchas = opts.solveCaptchas;
|
|
166055
|
+
}
|
|
166056
|
+
if (Object.keys(browserSettings).length > 0) {
|
|
166057
|
+
params.browserSettings = browserSettings;
|
|
166058
|
+
}
|
|
166059
|
+
if (Object.keys(params).length === 0) return null;
|
|
166060
|
+
return params;
|
|
166061
|
+
}
|
|
165958
166062
|
function output(data, json2) {
|
|
165959
166063
|
if (json2) {
|
|
165960
166064
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -166009,6 +166113,29 @@ async function runCommand(command, args) {
|
|
|
166009
166113
|
} catch {
|
|
166010
166114
|
}
|
|
166011
166115
|
}
|
|
166116
|
+
const sessionParams = buildSessionParamsFromOpts(opts);
|
|
166117
|
+
if (sessionParams) {
|
|
166118
|
+
const desiredMode = await getDesiredMode(session);
|
|
166119
|
+
if (desiredMode !== "browserbase") {
|
|
166120
|
+
console.error(
|
|
166121
|
+
JSON.stringify({
|
|
166122
|
+
error: "Session flags (--proxies, --advanced-stealth, etc.) are only supported in remote mode. Run 'browse env remote' first."
|
|
166123
|
+
})
|
|
166124
|
+
);
|
|
166125
|
+
process.exit(1);
|
|
166126
|
+
}
|
|
166127
|
+
const paramsPath = getSessionParamsPath(session);
|
|
166128
|
+
const newParamsJson = JSON.stringify(sessionParams);
|
|
166129
|
+
let currentParamsJson = "";
|
|
166130
|
+
try {
|
|
166131
|
+
currentParamsJson = await import_fs11.promises.readFile(paramsPath, "utf-8");
|
|
166132
|
+
} catch {
|
|
166133
|
+
}
|
|
166134
|
+
await import_fs11.promises.writeFile(paramsPath, newParamsJson);
|
|
166135
|
+
if (currentParamsJson !== newParamsJson && await isDaemonRunning(session)) {
|
|
166136
|
+
await stopDaemonAndCleanup(session);
|
|
166137
|
+
}
|
|
166138
|
+
}
|
|
166012
166139
|
await ensureDaemon(session, headless);
|
|
166013
166140
|
return sendCommand(session, command, args, headless);
|
|
166014
166141
|
}
|
|
@@ -166021,6 +166148,19 @@ program.name("browse").description("Browser automation CLI for AI agents").versi
|
|
|
166021
166148
|
).option(
|
|
166022
166149
|
"--connect <session-id>",
|
|
166023
166150
|
"Connect to an existing Browserbase session by ID"
|
|
166151
|
+
).option("--proxies", "Enable Browserbase proxy (remote only)").option("--advanced-stealth", "Enable advanced stealth mode (remote only)").option("--solve-captchas", "Enable automatic CAPTCHA solving (remote only)").option(
|
|
166152
|
+
"--no-solve-captchas",
|
|
166153
|
+
"Disable automatic CAPTCHA solving (remote only)"
|
|
166154
|
+
).option("--block-ads", "Enable ad blocking (remote only)").option(
|
|
166155
|
+
"--region <region>",
|
|
166156
|
+
"Session region: us-west-2, us-east-1, eu-central-1, ap-southeast-1 (remote only)"
|
|
166157
|
+
).option(
|
|
166158
|
+
"--keep-alive",
|
|
166159
|
+
"Keep session alive after disconnection (remote only)"
|
|
166160
|
+
).option(
|
|
166161
|
+
"--session-timeout <seconds>",
|
|
166162
|
+
"Session timeout in seconds (remote only)",
|
|
166163
|
+
parseInt
|
|
166024
166164
|
);
|
|
166025
166165
|
program.command("start").description("Start browser daemon (auto-started by other commands)").action(async () => {
|
|
166026
166166
|
const opts = program.opts();
|
|
@@ -166072,13 +166212,20 @@ program.command("status").description("Check daemon status").action(async () =>
|
|
|
166072
166212
|
}
|
|
166073
166213
|
if (mode === "local") {
|
|
166074
166214
|
const localConfig = await readLocalConfig(session);
|
|
166075
|
-
const localInfo = await readLocalInfo(session);
|
|
166215
|
+
const localInfo = await readLocalInfo(session) ?? await waitForLocalInfo(session);
|
|
166216
|
+
logLocalModeHint(localConfig, localInfo);
|
|
166076
166217
|
localDetails = {
|
|
166077
166218
|
localStrategy: localConfig.strategy,
|
|
166078
166219
|
...localInfo ?? {}
|
|
166079
166220
|
};
|
|
166080
166221
|
}
|
|
166081
166222
|
}
|
|
166223
|
+
let sessionParams = null;
|
|
166224
|
+
try {
|
|
166225
|
+
const raw = await import_fs11.promises.readFile(getSessionParamsPath(session), "utf-8");
|
|
166226
|
+
sessionParams = JSON.parse(raw);
|
|
166227
|
+
} catch {
|
|
166228
|
+
}
|
|
166082
166229
|
console.log(
|
|
166083
166230
|
JSON.stringify({
|
|
166084
166231
|
running,
|
|
@@ -166086,13 +166233,25 @@ program.command("status").description("Check daemon status").action(async () =>
|
|
|
166086
166233
|
wsUrl,
|
|
166087
166234
|
mode,
|
|
166088
166235
|
browserbaseSessionId,
|
|
166089
|
-
...localDetails
|
|
166236
|
+
...localDetails,
|
|
166237
|
+
...sessionParams ? { sessionParams } : {}
|
|
166090
166238
|
})
|
|
166091
166239
|
);
|
|
166092
166240
|
});
|
|
166093
|
-
|
|
166094
|
-
|
|
166095
|
-
)
|
|
166241
|
+
var envUsage = "Usage: browse env [local|remote]\n browse env local [--auto-connect|<port|url>]";
|
|
166242
|
+
var envCommand = program.command("env [target] [cdpTarget]").description(
|
|
166243
|
+
"Show or switch browser environment (local | remote)\n\n browse env Show current environment\n browse env local Use clean isolated local browser (default)\n browse env local --auto-connect Auto-discover local Chrome, fallback to isolated\n browse env local <port|url> Attach to specific CDP target\n browse env remote Use Browserbase (requires API key)"
|
|
166244
|
+
).option(
|
|
166245
|
+
"--auto-connect",
|
|
166246
|
+
"Auto-discover an existing local Chrome instance via CDP"
|
|
166247
|
+
);
|
|
166248
|
+
envCommand.addOption(
|
|
166249
|
+
new import_commander.Option(
|
|
166250
|
+
"--isolated",
|
|
166251
|
+
"Deprecated alias for the default isolated local browser"
|
|
166252
|
+
).hideHelp()
|
|
166253
|
+
);
|
|
166254
|
+
envCommand.action(
|
|
166096
166255
|
async (target, cdpTarget, cmdOpts) => {
|
|
166097
166256
|
const opts = program.opts();
|
|
166098
166257
|
const session = getSession(opts);
|
|
@@ -166123,9 +166282,7 @@ program.command("env [target] [cdpTarget]").description(
|
|
|
166123
166282
|
};
|
|
166124
166283
|
const mapped = modeMap[target];
|
|
166125
166284
|
if (!mapped) {
|
|
166126
|
-
console.error(
|
|
166127
|
-
"Usage: browse env [local|remote]\n browse env local [--isolated] [<port|url>]"
|
|
166128
|
-
);
|
|
166285
|
+
console.error(envUsage);
|
|
166129
166286
|
process.exit(1);
|
|
166130
166287
|
}
|
|
166131
166288
|
try {
|
|
@@ -166134,10 +166291,22 @@ program.command("env [target] [cdpTarget]").description(
|
|
|
166134
166291
|
console.error(err instanceof Error ? err.message : String(err));
|
|
166135
166292
|
process.exit(1);
|
|
166136
166293
|
}
|
|
166137
|
-
let localConfig = {
|
|
166294
|
+
let localConfig = { ...DEFAULT_LOCAL_CONFIG };
|
|
166138
166295
|
if (mapped === "local") {
|
|
166139
|
-
|
|
166140
|
-
|
|
166296
|
+
const selectedLocalStrategies = [
|
|
166297
|
+
Boolean(cmdOpts.autoConnect),
|
|
166298
|
+
Boolean(cmdOpts.isolated),
|
|
166299
|
+
Boolean(cdpTarget)
|
|
166300
|
+
].filter(Boolean);
|
|
166301
|
+
if (selectedLocalStrategies.length > 1) {
|
|
166302
|
+
console.error(envUsage);
|
|
166303
|
+
console.error(
|
|
166304
|
+
"Use only one of --auto-connect, --isolated, or <port|url>."
|
|
166305
|
+
);
|
|
166306
|
+
process.exit(1);
|
|
166307
|
+
}
|
|
166308
|
+
if (cmdOpts.autoConnect) {
|
|
166309
|
+
localConfig = { strategy: "auto" };
|
|
166141
166310
|
} else if (cdpTarget) {
|
|
166142
166311
|
localConfig = { strategy: "cdp", cdpTarget };
|
|
166143
166312
|
}
|
|
@@ -166160,6 +166329,9 @@ program.command("env [target] [cdpTarget]").description(
|
|
|
166160
166329
|
await stopDaemonAndCleanup(session);
|
|
166161
166330
|
}
|
|
166162
166331
|
await ensureDaemon(session, isHeadless(opts));
|
|
166332
|
+
if (mapped === "local") {
|
|
166333
|
+
logLocalModeHint(localConfig, await waitForLocalInfo(session));
|
|
166334
|
+
}
|
|
166163
166335
|
console.log(
|
|
166164
166336
|
JSON.stringify({
|
|
166165
166337
|
mode: toModeTarget(mapped),
|
|
@@ -166419,6 +166591,16 @@ program.command("select <selector> <values...>").description("Select option(s)")
|
|
|
166419
166591
|
process.exit(1);
|
|
166420
166592
|
}
|
|
166421
166593
|
});
|
|
166594
|
+
program.command("upload <selector> <files...>").description('Upload file(s) to an <input type="file"> element').action(async (selector, files) => {
|
|
166595
|
+
const opts = program.opts();
|
|
166596
|
+
try {
|
|
166597
|
+
const result = await runCommand("upload", [selector, files]);
|
|
166598
|
+
output(result, opts.json ?? false);
|
|
166599
|
+
} catch (e3) {
|
|
166600
|
+
console.error("Error:", e3 instanceof Error ? e3.message : e3);
|
|
166601
|
+
process.exit(1);
|
|
166602
|
+
}
|
|
166603
|
+
});
|
|
166422
166604
|
program.command("highlight <selector>").description("Highlight element").option("-d, --duration <ms>", "Duration", "2000").action(async (selector, cmdOpts) => {
|
|
166423
166605
|
const opts = program.opts();
|
|
166424
166606
|
try {
|