@optima-chat/browser-cli 0.6.1 → 0.7.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/dist/index.js +198 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -98,6 +98,16 @@ var BrowserAPIError = class extends Error {
|
|
|
98
98
|
this.name = "BrowserAPIError";
|
|
99
99
|
}
|
|
100
100
|
};
|
|
101
|
+
function toAPIError(status, statusText, body) {
|
|
102
|
+
const detail = body.detail ?? body;
|
|
103
|
+
if (typeof detail === "string") {
|
|
104
|
+
return new BrowserAPIError(status, "http_error", `HTTP ${status}: ${detail}`);
|
|
105
|
+
}
|
|
106
|
+
if (detail?.message) {
|
|
107
|
+
return new BrowserAPIError(status, detail.error ?? "unknown", detail.message);
|
|
108
|
+
}
|
|
109
|
+
return new BrowserAPIError(status, "unknown", `HTTP ${status}: ${statusText}`);
|
|
110
|
+
}
|
|
101
111
|
async function request(path, options = {}) {
|
|
102
112
|
const url = `${BROWSER_API_URL}${path}`;
|
|
103
113
|
let response;
|
|
@@ -126,8 +136,7 @@ async function request(path, options = {}) {
|
|
|
126
136
|
`HTTP ${response.status}: ${response.statusText}`
|
|
127
137
|
);
|
|
128
138
|
}
|
|
129
|
-
|
|
130
|
-
throw new BrowserAPIError(response.status, detail.error, detail.message);
|
|
139
|
+
throw toAPIError(response.status, response.statusText, body);
|
|
131
140
|
}
|
|
132
141
|
if (response.status === 204) {
|
|
133
142
|
return void 0;
|
|
@@ -159,20 +168,20 @@ async function requestBinary(path) {
|
|
|
159
168
|
`HTTP ${response.status}: ${response.statusText}`
|
|
160
169
|
);
|
|
161
170
|
}
|
|
162
|
-
|
|
163
|
-
throw new BrowserAPIError(response.status, detail.error, detail.message);
|
|
171
|
+
throw toAPIError(response.status, response.statusText, body);
|
|
164
172
|
}
|
|
165
173
|
const arrayBuffer = await response.arrayBuffer();
|
|
166
174
|
return Buffer.from(arrayBuffer);
|
|
167
175
|
}
|
|
168
176
|
var BrowserAPI = class {
|
|
169
|
-
async createSession(url, profileId, force, connector, ziniaoProfileId) {
|
|
177
|
+
async createSession(url, profileId, force, connector, ziniaoProfileId, bitbrowserProfileId) {
|
|
170
178
|
const body = {};
|
|
171
179
|
if (url) body.url = url;
|
|
172
180
|
if (profileId) body.profile_id = profileId;
|
|
173
181
|
if (force) body.force = true;
|
|
174
182
|
if (connector) body.connector = connector;
|
|
175
183
|
if (ziniaoProfileId) body.ziniao_profile_id = ziniaoProfileId;
|
|
184
|
+
if (bitbrowserProfileId) body.bitbrowser_profile_id = bitbrowserProfileId;
|
|
176
185
|
return request("/api/sessions", {
|
|
177
186
|
method: "POST",
|
|
178
187
|
body: JSON.stringify(body)
|
|
@@ -201,6 +210,9 @@ var BrowserAPI = class {
|
|
|
201
210
|
async getZiNiaoProfiles() {
|
|
202
211
|
return request("/api/user/ziniao-profiles");
|
|
203
212
|
}
|
|
213
|
+
async getBitBrowserProfiles() {
|
|
214
|
+
return request("/api/user/bitbrowser-profiles");
|
|
215
|
+
}
|
|
204
216
|
async closeSession(sessionId) {
|
|
205
217
|
await request(`/api/sessions/${sessionId}`, { method: "DELETE" });
|
|
206
218
|
}
|
|
@@ -246,6 +258,22 @@ var BrowserAPI = class {
|
|
|
246
258
|
async getScreenshot(sessionId) {
|
|
247
259
|
return requestBinary(`/api/sessions/${sessionId}/screenshot`);
|
|
248
260
|
}
|
|
261
|
+
async runRecipeScript(name, params, pollMs = 2e3) {
|
|
262
|
+
const started = await request(`/api/scripts/${name}/run`, {
|
|
263
|
+
method: "POST",
|
|
264
|
+
body: JSON.stringify({ params })
|
|
265
|
+
});
|
|
266
|
+
for (; ; ) {
|
|
267
|
+
const task = await request(
|
|
268
|
+
`/api/script-tasks/${started.id}`
|
|
269
|
+
);
|
|
270
|
+
if (task.status === "completed") return task.output;
|
|
271
|
+
if (task.status === "failed" || task.status === "needs_fallback") {
|
|
272
|
+
throw new Error(task.error || `recipe ${task.status}`);
|
|
273
|
+
}
|
|
274
|
+
await new Promise((r) => setTimeout(r, pollMs));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
249
277
|
async search(sessionId, pattern) {
|
|
250
278
|
return request(`/api/sessions/${sessionId}/search`, {
|
|
251
279
|
method: "POST",
|
|
@@ -300,9 +328,11 @@ var BrowserAPI = class {
|
|
|
300
328
|
async deleteScript(name) {
|
|
301
329
|
await request(`/api/scripts/${encodeURIComponent(name)}`, { method: "DELETE" });
|
|
302
330
|
}
|
|
303
|
-
async runScript(scriptName, params = {}, profileId) {
|
|
331
|
+
async runScript(scriptName, params = {}, profileId, connector, bitbrowserProfileId) {
|
|
304
332
|
const payload = { params };
|
|
305
333
|
if (profileId) payload.profile_id = profileId;
|
|
334
|
+
if (connector) payload.connector = connector;
|
|
335
|
+
if (bitbrowserProfileId) payload.bitbrowser_profile_id = bitbrowserProfileId;
|
|
306
336
|
return request(`/api/scripts/${encodeURIComponent(scriptName)}/run`, {
|
|
307
337
|
method: "POST",
|
|
308
338
|
body: JSON.stringify(payload)
|
|
@@ -404,6 +434,9 @@ function formatFind(result) {
|
|
|
404
434
|
}
|
|
405
435
|
return lines.join("\n");
|
|
406
436
|
}
|
|
437
|
+
function formatDesktopNotConnected(result) {
|
|
438
|
+
return result.message ?? "\u684C\u9762\u5E94\u7528\u672A\u8FDE\u63A5\uFF0C\u8BF7\u5148\u5B89\u88C5\u5E76\u542F\u52A8\u684C\u9762\u5E94\u7528\u540E\u91CD\u8BD5\u3002";
|
|
439
|
+
}
|
|
407
440
|
function formatError(err) {
|
|
408
441
|
if (err instanceof Error) {
|
|
409
442
|
return `\u2717 Error: ${err.message}`;
|
|
@@ -430,9 +463,9 @@ function formatProfileDelete(profileId) {
|
|
|
430
463
|
|
|
431
464
|
// src/commands/lifecycle.ts
|
|
432
465
|
function registerLifecycleCommands(program2) {
|
|
433
|
-
program2.command("launch").description("Launch a browser session").option("--url <url>", "Navigate to URL after launch").option("--profile <id>", "Use a named browser profile").option("--force", "Close existing session before launching").option("--connector <type>", "Browser connector: chrome or
|
|
466
|
+
program2.command("launch").description("Launch a browser session").option("--url <url>", "Navigate to URL after launch").option("--profile <id>", "Use a named browser profile").option("--force", "Close existing session before launching").option("--connector <type>", "Browser connector: chrome, ziniao, or bitbrowser").option("--ziniao-profile <id>", "ZiNiao browser profile ID").option("--bitbrowser-profile <id>", "BitBrowser profile ID").action(async (opts) => {
|
|
434
467
|
try {
|
|
435
|
-
const state = await api.createSession(opts.url, opts.profile, opts.force, opts.connector, opts.ziniaoProfile);
|
|
468
|
+
const state = await api.createSession(opts.url, opts.profile, opts.force, opts.connector, opts.ziniaoProfile, opts.bitbrowserProfile);
|
|
436
469
|
saveSessionId(state.session_id);
|
|
437
470
|
console.log(formatLaunch(state));
|
|
438
471
|
} catch (err) {
|
|
@@ -748,7 +781,7 @@ function registerScriptCommands(program2) {
|
|
|
748
781
|
process.exit(1);
|
|
749
782
|
}
|
|
750
783
|
});
|
|
751
|
-
program2.command("runscript").argument("<name>", "Script name").description("Run a script (polls until complete)").option("--param <params...>", "Parameters as key=value").option("--profile <id>", "Use a named browser profile").option("--no-poll", "Return immediately without polling").action(async (name, opts) => {
|
|
784
|
+
program2.command("runscript").argument("<name>", "Script name").description("Run a script (polls until complete)").option("--param <params...>", "Parameters as key=value").option("--profile <id>", "Use a named browser profile").option("--connector <type>", "Browser connector: chrome, ziniao, or bitbrowser").option("--bitbrowser-profile <id>", "BitBrowser profile ID (with --connector bitbrowser)").option("--no-poll", "Return immediately without polling").action(async (name, opts) => {
|
|
752
785
|
try {
|
|
753
786
|
const params = {};
|
|
754
787
|
if (opts.param) {
|
|
@@ -758,7 +791,7 @@ function registerScriptCommands(program2) {
|
|
|
758
791
|
}
|
|
759
792
|
}
|
|
760
793
|
clearSessionId();
|
|
761
|
-
const task = await api.runScript(name, params, opts.profile);
|
|
794
|
+
const task = await api.runScript(name, params, opts.profile, opts.connector, opts.bitbrowserProfile);
|
|
762
795
|
console.log(`Script started (task: ${task.id})`);
|
|
763
796
|
if (!opts.poll) {
|
|
764
797
|
console.log(`Poll with: browser-cli script-task ${task.id}`);
|
|
@@ -820,6 +853,105 @@ function registerProfileCommands(program2) {
|
|
|
820
853
|
});
|
|
821
854
|
}
|
|
822
855
|
|
|
856
|
+
// src/ziniao-doctor.ts
|
|
857
|
+
var ZINIAO_WEBDRIVER_DOC_URL = "https://open.ziniao.com/docSupport?docId=99#%E7%AC%AC%E4%B8%80%E6%AD%A5%EF%BC%9A%E7%99%BB%E5%BD%95%E5%BC%80%E6%94%BE%E5%B9%B3%E5%8F%B0%E6%8E%A7%E5%88%B6%E5%8F%B00";
|
|
858
|
+
var BOSS_GUIDANCE = [
|
|
859
|
+
"\u9700\u8981\u7D2B\u9E1F BOSS \u8D26\u53F7\u5B8C\u6210\u5F00\u901A\uFF08\u4E00\u6B21\u6027\u914D\u7F6E\uFF09\uFF1A",
|
|
860
|
+
" 1. \u767B\u5F55\u7D2B\u9E1F\u5F00\u653E\u5E73\u53F0\u63A7\u5236\u53F0\uFF0C\u5F00\u901A Webdriver \u6743\u9650\uFF1B",
|
|
861
|
+
" 2. \u521B\u5EFA\u4E13\u7528\u81EA\u52A8\u5316\u6210\u5458\u8D26\u53F7\uFF08robot\uFF09\uFF0C\u89D2\u8272\u9700\u542B\u300C\u67E5\u770B\u8D26\u53F7\u300D\u6743\u9650\uFF1B",
|
|
862
|
+
" 3. \u4E3A\u8BE5\u8D26\u53F7\u6388\u6743\u9700\u8981\u64CD\u4F5C\u7684\u5E97\u94FA\u3002",
|
|
863
|
+
`\u53C2\u8003\u6587\u6863: ${ZINIAO_WEBDRIVER_DOC_URL}`
|
|
864
|
+
].join("\n");
|
|
865
|
+
function ziniaoErrorHint(message) {
|
|
866
|
+
if (/webdriver|开通|权限|permission/i.test(message)) {
|
|
867
|
+
return `\u7591\u4F3C\u672A\u5F00\u901A Webdriver \u6743\u9650\u6216\u8D26\u53F7\u6743\u9650\u4E0D\u8DB3\u3002${BOSS_GUIDANCE}`;
|
|
868
|
+
}
|
|
869
|
+
if (/错误次数太多/.test(message)) {
|
|
870
|
+
return "\u7D2B\u9E1F\u98CE\u63A7\u5DF2\u4E34\u65F6\u9501\u5B9A\uFF0C\u8BF7\u7B49\u5F85\u7EA6 10 \u5206\u949F\u540E\u91CD\u8BD5\uFF08\u7EE7\u7EED\u5931\u8D25\u4F1A\u5EF6\u957F\u9501\u5B9A\uFF09\u3002";
|
|
871
|
+
}
|
|
872
|
+
if (/用户名或密码错误|密码错误/.test(message)) {
|
|
873
|
+
return "\u8BF7\u6838\u5BF9\u51ED\u636E\uFF08company=\u4F01\u4E1A\u540D\u79F0\uFF0Cusername/password=\u6210\u5458\u8D26\u53F7\uFF0C\u63A8\u8350 robot \u8D26\u53F7\uFF09\uFF0C\u7136\u540E\u7528 browser-cli ziniao set \u91CD\u65B0\u914D\u7F6E\u3002";
|
|
874
|
+
}
|
|
875
|
+
return null;
|
|
876
|
+
}
|
|
877
|
+
async function runZiNiaoDoctor(client) {
|
|
878
|
+
const checks = [];
|
|
879
|
+
const done = () => ({ checks, ok: checks.every((c) => c.ok === true) });
|
|
880
|
+
let cfg;
|
|
881
|
+
try {
|
|
882
|
+
cfg = await client.getZiNiaoConfig();
|
|
883
|
+
} catch (err) {
|
|
884
|
+
checks.push({
|
|
885
|
+
name: "\u540E\u7AEF\u8FDE\u63A5",
|
|
886
|
+
ok: false,
|
|
887
|
+
detail: err.message,
|
|
888
|
+
hint: "\u786E\u8BA4 browser-backend \u6B63\u5728\u8FD0\u884C\uFF0C\u4E14 BROWSER_API_URL \u6307\u5411\u6B63\u786E\u5730\u5740\u3002"
|
|
889
|
+
});
|
|
890
|
+
return done();
|
|
891
|
+
}
|
|
892
|
+
checks.push({ name: "\u540E\u7AEF\u8FDE\u63A5", ok: true });
|
|
893
|
+
if (!cfg.configured) {
|
|
894
|
+
checks.push({
|
|
895
|
+
name: "\u7D2B\u9E1F\u51ED\u636E",
|
|
896
|
+
ok: false,
|
|
897
|
+
hint: "browser-cli ziniao set --company <\u4F01\u4E1A\u540D\u79F0> --username <\u6210\u5458\u8D26\u53F7> --password <\u5BC6\u7801>\uFF08\u63A8\u8350\u4F7F\u7528\u4E13\u7528 robot \u6210\u5458\u8D26\u53F7\uFF09"
|
|
898
|
+
});
|
|
899
|
+
return done();
|
|
900
|
+
}
|
|
901
|
+
checks.push({ name: "\u7D2B\u9E1F\u51ED\u636E", ok: true, detail: `${cfg.company} / ${cfg.username}` });
|
|
902
|
+
try {
|
|
903
|
+
const r = await client.getZiNiaoProfiles();
|
|
904
|
+
if (!r.connected) {
|
|
905
|
+
checks.push({
|
|
906
|
+
name: "\u684C\u9762\u5E94\u7528",
|
|
907
|
+
ok: false,
|
|
908
|
+
detail: r.message,
|
|
909
|
+
hint: `\u8BF7\u542F\u52A8 Optima \u684C\u9762\u5E94\u7528\u5E76\u5B8C\u6210\u8FDE\u63A5\u3002${r.download_url ? `\u4E0B\u8F7D: ${r.download_url}` : ""}`.trim()
|
|
910
|
+
});
|
|
911
|
+
return done();
|
|
912
|
+
}
|
|
913
|
+
checks.push({ name: "\u684C\u9762\u5E94\u7528", ok: true });
|
|
914
|
+
if (!r.ziniao_available) {
|
|
915
|
+
checks.push({
|
|
916
|
+
name: "\u7D2B\u9E1F\u5BA2\u6237\u7AEF",
|
|
917
|
+
ok: false,
|
|
918
|
+
hint: "\u684C\u9762\u7AEF\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684\u7D2B\u9E1F\uFF1A\u786E\u8BA4\u672C\u673A\u5DF2\u5B89\u88C5\u7D2B\u9E1F\u5BA2\u6237\u7AEF\uFF0C\u4E14\u51ED\u636E\u5DF2\u540C\u6B65\u5230\u684C\u9762\uFF08\u91CD\u542F\u684C\u9762\u5E94\u7528\u53EF\u89E6\u53D1\u540C\u6B65\uFF09\u3002"
|
|
919
|
+
});
|
|
920
|
+
return done();
|
|
921
|
+
}
|
|
922
|
+
checks.push({ name: "\u7D2B\u9E1F\u5BA2\u6237\u7AEF", ok: true });
|
|
923
|
+
if (r.profiles.length === 0) {
|
|
924
|
+
checks.push({
|
|
925
|
+
name: "\u5E97\u94FA\u5217\u8868",
|
|
926
|
+
ok: "warn",
|
|
927
|
+
detail: "\u767B\u5F55\u6210\u529F\uFF0C\u4F46\u5E97\u94FA\u5217\u8868\u4E3A\u7A7A",
|
|
928
|
+
hint: `robot \u8D26\u53F7\u7684\u89D2\u8272\u53EF\u80FD\u7F3A\u300C\u67E5\u770B\u8D26\u53F7\u300D\u6743\u9650\uFF0C\u6216\u5C1A\u672A\u6388\u6743\u4EFB\u4F55\u5E97\u94FA\u3002${BOSS_GUIDANCE}`
|
|
929
|
+
});
|
|
930
|
+
return done();
|
|
931
|
+
}
|
|
932
|
+
checks.push({ name: "\u5E97\u94FA\u5217\u8868", ok: true, detail: `${r.profiles.length} \u4E2A\u5E97\u94FA\u53EF\u7528` });
|
|
933
|
+
} catch (err) {
|
|
934
|
+
checks.push({
|
|
935
|
+
name: "\u7D2B\u9E1F Webdriver \u901A\u9053",
|
|
936
|
+
ok: false,
|
|
937
|
+
detail: err.message,
|
|
938
|
+
hint: ziniaoErrorHint(err.message ?? "") ?? void 0
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
return done();
|
|
942
|
+
}
|
|
943
|
+
function formatDoctorReport(checks) {
|
|
944
|
+
const lines = [];
|
|
945
|
+
for (const c of checks) {
|
|
946
|
+
const mark = c.ok === true ? "\u2713" : c.ok === "warn" ? "\u26A0" : "\u2717";
|
|
947
|
+
lines.push(`${mark} ${c.name}${c.detail ? `: ${c.detail}` : ""}`);
|
|
948
|
+
if (c.hint) {
|
|
949
|
+
lines.push(...c.hint.split("\n").map((l) => ` ${l}`));
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
return lines.join("\n");
|
|
953
|
+
}
|
|
954
|
+
|
|
823
955
|
// src/commands/ziniao.ts
|
|
824
956
|
function registerZiNiaoCommands(program2) {
|
|
825
957
|
const ziniao = program2.command("ziniao").description("Manage ZiNiao browser credentials");
|
|
@@ -851,15 +983,17 @@ function registerZiNiaoCommands(program2) {
|
|
|
851
983
|
try {
|
|
852
984
|
const result = await api.getZiNiaoProfiles();
|
|
853
985
|
if (!result.connected) {
|
|
854
|
-
console.log(
|
|
986
|
+
console.log(formatDesktopNotConnected(result));
|
|
855
987
|
process.exit(1);
|
|
856
988
|
}
|
|
857
989
|
if (!result.ziniao_available) {
|
|
858
990
|
console.log("ZiNiao not available on Desktop app. Start ZiNiao WebDriver mode first.");
|
|
991
|
+
console.log("Run: browser-cli ziniao doctor \uFF08\u9010\u9879\u6392\u67E5\u7D2B\u9E1F\u901A\u9053\uFF09");
|
|
859
992
|
process.exit(1);
|
|
860
993
|
}
|
|
861
994
|
if (result.profiles.length === 0) {
|
|
862
995
|
console.log("No ZiNiao profiles found.");
|
|
996
|
+
console.log("Run: browser-cli ziniao doctor \uFF08\u9010\u9879\u6392\u67E5\u7D2B\u9E1F\u901A\u9053\uFF0C\u5E38\u89C1\u539F\u56E0\uFF1Arobot \u8D26\u53F7\u7F3A\u300C\u67E5\u770B\u8D26\u53F7\u300D\u6743\u9650\u6216\u672A\u6388\u6743\u5E97\u94FA\uFF09");
|
|
863
997
|
return;
|
|
864
998
|
}
|
|
865
999
|
console.log(`ZiNiao profiles (${result.profiles.length}):
|
|
@@ -870,9 +1004,16 @@ function registerZiNiaoCommands(program2) {
|
|
|
870
1004
|
console.log("\nUse: browser-cli launch --connector ziniao --ziniao-profile <id> --url <url>");
|
|
871
1005
|
} catch (err) {
|
|
872
1006
|
console.error(formatError(err));
|
|
1007
|
+
const hint = ziniaoErrorHint(err?.message ?? "");
|
|
1008
|
+
if (hint) console.error(hint);
|
|
873
1009
|
process.exit(1);
|
|
874
1010
|
}
|
|
875
1011
|
});
|
|
1012
|
+
ziniao.command("doctor").description("Diagnose the ZiNiao Webdriver chain (credentials / desktop / permission / stores)").action(async () => {
|
|
1013
|
+
const { checks, ok } = await runZiNiaoDoctor(api);
|
|
1014
|
+
console.log(formatDoctorReport(checks));
|
|
1015
|
+
if (!ok) process.exit(1);
|
|
1016
|
+
});
|
|
876
1017
|
ziniao.command("clear").description("Remove ZiNiao credentials").action(async () => {
|
|
877
1018
|
try {
|
|
878
1019
|
await api.deleteZiNiaoConfig();
|
|
@@ -884,6 +1025,50 @@ function registerZiNiaoCommands(program2) {
|
|
|
884
1025
|
});
|
|
885
1026
|
}
|
|
886
1027
|
|
|
1028
|
+
// src/commands/recipes.ts
|
|
1029
|
+
import { writeFileSync as writeFileSync3 } from "fs";
|
|
1030
|
+
function registerRecipeCommands(program2) {
|
|
1031
|
+
program2.command("export-ad-report").description("Export TikTok Shop last-7-days video ad data into the session workspace").requiredOption("--ziniao-profile <id>", "ZiNiao browser profile ID").option("--out <path>", "Output CSV path", "./tt_video_ad_7d.csv").action(async (opts) => {
|
|
1032
|
+
try {
|
|
1033
|
+
const out = await api.runRecipeScript("tiktok_video_ad_export", {
|
|
1034
|
+
ziniao_profile_id: opts.ziniaoProfile
|
|
1035
|
+
});
|
|
1036
|
+
writeFileSync3(opts.out, Buffer.from(out.content_b64, "base64"));
|
|
1037
|
+
console.log(`Saved ${out.filename} -> ${opts.out} (${out.size} bytes)`);
|
|
1038
|
+
} catch (err) {
|
|
1039
|
+
console.error(formatError(err));
|
|
1040
|
+
process.exit(1);
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// src/commands/bitbrowser.ts
|
|
1046
|
+
function registerBitBrowserCommands(program2) {
|
|
1047
|
+
const bitbrowser = program2.command("bitbrowser").description("Manage BitBrowser (\u6BD4\u7279\u6D4F\u89C8\u5668) anti-detect browser");
|
|
1048
|
+
bitbrowser.command("profiles").description("List BitBrowser profiles (requires Desktop app online + BitBrowser running)").action(async () => {
|
|
1049
|
+
try {
|
|
1050
|
+
const result = await api.getBitBrowserProfiles();
|
|
1051
|
+
if (!result.connected) {
|
|
1052
|
+
console.log(formatDesktopNotConnected(result));
|
|
1053
|
+
process.exit(1);
|
|
1054
|
+
}
|
|
1055
|
+
if (result.profiles.length === 0) {
|
|
1056
|
+
console.log("No BitBrowser profiles found. Is BitBrowser running with its local API enabled?");
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
console.log(`BitBrowser profiles (${result.profiles.length}):
|
|
1060
|
+
`);
|
|
1061
|
+
for (const p of result.profiles) {
|
|
1062
|
+
console.log(` ${p.id} ${p.name}`);
|
|
1063
|
+
}
|
|
1064
|
+
console.log("\nUse: browser-cli launch --connector bitbrowser --bitbrowser-profile <id> --url <url>");
|
|
1065
|
+
} catch (err) {
|
|
1066
|
+
console.error(formatError(err));
|
|
1067
|
+
process.exit(1);
|
|
1068
|
+
}
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
|
|
887
1072
|
// src/index.ts
|
|
888
1073
|
var require2 = createRequire(import.meta.url);
|
|
889
1074
|
var { version } = require2("../package.json");
|
|
@@ -903,4 +1088,6 @@ registerTabCommands(program);
|
|
|
903
1088
|
registerScriptCommands(program);
|
|
904
1089
|
registerProfileCommands(program);
|
|
905
1090
|
registerZiNiaoCommands(program);
|
|
1091
|
+
registerRecipeCommands(program);
|
|
1092
|
+
registerBitBrowserCommands(program);
|
|
906
1093
|
program.parse();
|