@bsbofmusic/cdper-doubao 1.1.2 → 1.1.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/package.json +2 -3
- package/src/cli.js +317 -131
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsbofmusic/cdper-doubao",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Standalone Doubao CLI controlled through a user's real Chrome/Edge via CDP Bridge",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "src/public-api.js",
|
|
@@ -49,7 +49,6 @@
|
|
|
49
49
|
"node": ">=18.0.0"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@bsbofmusic/cdper-core": "~1.3.
|
|
53
|
-
"yargs": "^17.7.2"
|
|
52
|
+
"@bsbofmusic/cdper-core": "~1.3.4"
|
|
54
53
|
}
|
|
55
54
|
}
|
package/src/cli.js
CHANGED
|
@@ -1,160 +1,346 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const os = require('os');
|
|
6
6
|
const path = require('path');
|
|
7
|
-
const yargs = require('yargs/yargs');
|
|
8
|
-
const { hideBin } = require('yargs/helpers');
|
|
9
7
|
const { fullCheck, formatAgentHints, fullReadiness } = require('@bsbofmusic/cdper-core/check');
|
|
10
8
|
const { getRuntimeStatus } = require('@bsbofmusic/cdper-core/runtime_status');
|
|
11
9
|
const { listSessions, cleanupExpired, closeSession } = require('@bsbofmusic/cdper-core/session');
|
|
12
10
|
const { redactValue } = require('@bsbofmusic/cdper-core/redact');
|
|
13
11
|
const { queryDoubao } = require('./doubao');
|
|
14
12
|
const pkg = require('../package.json');
|
|
15
|
-
|
|
13
|
+
const QUERY_OPTIONS = {
|
|
14
|
+
json: { type: 'boolean' },
|
|
15
|
+
mode: { alias: 'm', type: 'string', default: 'expert', choices: ['expert'] },
|
|
16
|
+
session: { alias: 's', type: 'string' },
|
|
17
|
+
'conversation-policy': { type: 'string', default: 'auto', choices: ['auto', 'fresh', 'followup'] },
|
|
18
|
+
wait: { type: 'string', default: 'normal', choices: ['short', 'normal', 'long', 'very_long'] },
|
|
19
|
+
'expected-duration': { type: 'string', choices: ['short', 'normal', 'long', 'very_long'] },
|
|
20
|
+
'max-wait-ms': { type: 'number' },
|
|
21
|
+
'max-wait': { type: 'number' },
|
|
22
|
+
'progress-every-ms': { type: 'number' },
|
|
23
|
+
'max-extends': { type: 'number' },
|
|
24
|
+
driver: { type: 'string', choices: ['puppeteer', 'playwright'] },
|
|
25
|
+
check: { type: 'boolean', default: true },
|
|
26
|
+
quiet: { alias: 'q', type: 'boolean' },
|
|
27
|
+
debug: { alias: 'd', type: 'boolean' },
|
|
28
|
+
};
|
|
29
|
+
const JSON_ONLY_OPTIONS = { json: { type: 'boolean' } };
|
|
30
|
+
const CONFIG_OPTIONS = { ws: { type: 'string', demandOption: true }, json: { type: 'boolean' } };
|
|
31
|
+
const SESSION_OPTIONS = { json: { type: 'boolean' } };
|
|
16
32
|
function writeJson(value) {
|
|
17
|
-
|
|
33
|
+
process.stdout.write(JSON.stringify(redactValue(value), null, 2) + '\n');
|
|
34
|
+
}
|
|
35
|
+
function camelCase(name) {
|
|
36
|
+
return name.replace(/-([a-z])/g, (_match, chr) => chr.toUpperCase());
|
|
37
|
+
}
|
|
38
|
+
function buildAliasMap(specs) {
|
|
39
|
+
const aliases = {};
|
|
40
|
+
for (const [name, spec] of Object.entries(specs)) {
|
|
41
|
+
if (spec.alias)
|
|
42
|
+
aliases[spec.alias] = name;
|
|
43
|
+
}
|
|
44
|
+
return aliases;
|
|
45
|
+
}
|
|
46
|
+
function coerceOption(name, value, spec) {
|
|
47
|
+
if (spec.type === 'boolean') {
|
|
48
|
+
if (typeof value === 'boolean')
|
|
49
|
+
return value;
|
|
50
|
+
if (value === undefined)
|
|
51
|
+
return true;
|
|
52
|
+
if (/^(true|1)$/i.test(value))
|
|
53
|
+
return true;
|
|
54
|
+
if (/^(false|0)$/i.test(value))
|
|
55
|
+
return false;
|
|
56
|
+
throw new Error(`Invalid value for ${name}: expected boolean`);
|
|
57
|
+
}
|
|
58
|
+
if (value === undefined || typeof value === 'boolean') {
|
|
59
|
+
throw new Error(`Missing value for ${name}`);
|
|
60
|
+
}
|
|
61
|
+
if (spec.type === 'number') {
|
|
62
|
+
const numberValue = Number(value);
|
|
63
|
+
if (!Number.isFinite(numberValue))
|
|
64
|
+
throw new Error(`Invalid value for ${name}: expected number`);
|
|
65
|
+
return numberValue;
|
|
66
|
+
}
|
|
67
|
+
return value;
|
|
18
68
|
}
|
|
69
|
+
function setOption(argv, name, value, specs) {
|
|
70
|
+
const spec = specs[name];
|
|
71
|
+
if (!spec)
|
|
72
|
+
throw new Error(`Unknown argument: ${name}`);
|
|
73
|
+
const key = camelCase(name);
|
|
74
|
+
argv[key] = coerceOption(name, value, spec);
|
|
75
|
+
}
|
|
76
|
+
function validateChoices(argv, specs) {
|
|
77
|
+
for (const [name, spec] of Object.entries(specs)) {
|
|
78
|
+
const key = camelCase(name);
|
|
79
|
+
if (!(key in argv) && spec.default !== undefined)
|
|
80
|
+
argv[key] = spec.default;
|
|
81
|
+
if (spec.demandOption && (argv[key] === undefined || argv[key] === '')) {
|
|
82
|
+
throw new Error(`Missing required argument: ${name}`);
|
|
83
|
+
}
|
|
84
|
+
if (argv[key] !== undefined && spec.choices && !spec.choices.includes(String(argv[key]))) {
|
|
85
|
+
throw new Error(`Invalid values:\n Argument: ${name}, Given: "${argv[key]}", Choices: ${spec.choices.map((choice) => `"${choice}"`).join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function parseOptions(tokens, specs, maxPositionals) {
|
|
90
|
+
const argv = { _: [] };
|
|
91
|
+
const aliases = buildAliasMap(specs);
|
|
92
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
93
|
+
const token = tokens[index];
|
|
94
|
+
if (token === '--') {
|
|
95
|
+
argv._.push(...tokens.slice(index + 1));
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (token.startsWith('--no-')) {
|
|
99
|
+
const name = token.slice(5);
|
|
100
|
+
const spec = specs[name];
|
|
101
|
+
if (!spec || spec.type !== 'boolean')
|
|
102
|
+
throw new Error(`Unknown argument: ${name}`);
|
|
103
|
+
setOption(argv, name, false, specs);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (token.startsWith('--')) {
|
|
107
|
+
const raw = token.slice(2);
|
|
108
|
+
const equalsIndex = raw.indexOf('=');
|
|
109
|
+
const name = equalsIndex >= 0 ? raw.slice(0, equalsIndex) : raw;
|
|
110
|
+
const spec = specs[name];
|
|
111
|
+
if (!spec)
|
|
112
|
+
throw new Error(`Unknown argument: ${name}`);
|
|
113
|
+
const inlineValue = equalsIndex >= 0 ? raw.slice(equalsIndex + 1) : undefined;
|
|
114
|
+
if (spec.type === 'boolean') {
|
|
115
|
+
setOption(argv, name, inlineValue ?? true, specs);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const nextValue = inlineValue ?? tokens[++index];
|
|
119
|
+
setOption(argv, name, nextValue, specs);
|
|
120
|
+
}
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (/^-[A-Za-z]$/.test(token)) {
|
|
124
|
+
const alias = token.slice(1);
|
|
125
|
+
const name = aliases[alias];
|
|
126
|
+
if (!name)
|
|
127
|
+
throw new Error(`Unknown argument: ${alias}`);
|
|
128
|
+
const spec = specs[name];
|
|
129
|
+
if (spec.type === 'boolean')
|
|
130
|
+
setOption(argv, name, true, specs);
|
|
131
|
+
else
|
|
132
|
+
setOption(argv, name, tokens[++index], specs);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (token.startsWith('-'))
|
|
136
|
+
throw new Error(`Unknown argument: ${token.replace(/^-+/, '')}`);
|
|
137
|
+
argv._.push(token);
|
|
138
|
+
}
|
|
139
|
+
if (argv._.length > maxPositionals) {
|
|
140
|
+
throw new Error(`Unknown argument: ${argv._[maxPositionals]}`);
|
|
141
|
+
}
|
|
142
|
+
validateChoices(argv, specs);
|
|
143
|
+
return argv;
|
|
144
|
+
}
|
|
145
|
+
function printHelp() {
|
|
146
|
+
console.log(`cdper-doubao <query> [options]
|
|
147
|
+
|
|
148
|
+
Commands:
|
|
149
|
+
cdper-doubao <text> Query Doubao
|
|
150
|
+
cdper-doubao doctor|check Check environment readiness
|
|
151
|
+
cdper-doubao status Show runtime status
|
|
152
|
+
cdper-doubao session [action] [id] List or close sessions
|
|
153
|
+
cdper-doubao config set Save CDP WS config
|
|
154
|
+
cdper-doubao version Show version
|
|
19
155
|
|
|
156
|
+
Options:
|
|
157
|
+
--json --mode/-m --session/-s --conversation-policy --wait
|
|
158
|
+
--max-wait-ms --progress-every-ms --max-extends --driver
|
|
159
|
+
--check/--no-check --quiet/-q --debug/-d --help`);
|
|
160
|
+
}
|
|
161
|
+
function failCli(error, rawArgs) {
|
|
162
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
163
|
+
if (rawArgs.includes('--json'))
|
|
164
|
+
writeJson({ ok: false, error: err.message });
|
|
165
|
+
else {
|
|
166
|
+
console.error(err.message);
|
|
167
|
+
printHelp();
|
|
168
|
+
}
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
function parseCli(rawArgs) {
|
|
172
|
+
if (rawArgs.includes('--help') || rawArgs.includes('-h')) {
|
|
173
|
+
printHelp();
|
|
174
|
+
process.exit(0);
|
|
175
|
+
}
|
|
176
|
+
const args = rawArgs[0] === 'query' && rawArgs[1] && !String(rawArgs[1]).startsWith('-')
|
|
177
|
+
? rawArgs.slice(1)
|
|
178
|
+
: rawArgs.slice();
|
|
179
|
+
const command = args[0];
|
|
180
|
+
if (command === 'doctor' || command === 'check' || command === 'status' || command === 'version') {
|
|
181
|
+
return { command, argv: parseOptions(args.slice(1), JSON_ONLY_OPTIONS, 0) };
|
|
182
|
+
}
|
|
183
|
+
if (command === 'session') {
|
|
184
|
+
const argv = parseOptions(args.slice(1), SESSION_OPTIONS, 2);
|
|
185
|
+
argv.action = argv._[0];
|
|
186
|
+
argv.id = argv._[1];
|
|
187
|
+
return { command, argv };
|
|
188
|
+
}
|
|
189
|
+
if (command === 'config') {
|
|
190
|
+
if (args[1] !== 'set')
|
|
191
|
+
throw new Error(`Unknown argument: ${args[1] || 'config'}`);
|
|
192
|
+
return { command: 'config set', argv: parseOptions(args.slice(2), CONFIG_OPTIONS, 0) };
|
|
193
|
+
}
|
|
194
|
+
const argv = parseOptions(args, QUERY_OPTIONS, 1);
|
|
195
|
+
return { command: 'query', argv, text: argv._[0] };
|
|
196
|
+
}
|
|
20
197
|
function parseQueryOptions(argv) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
198
|
+
return {
|
|
199
|
+
mode: argv.mode || 'expert',
|
|
200
|
+
sessionId: argv.session,
|
|
201
|
+
conversationPolicy: argv.conversationPolicy,
|
|
202
|
+
expectedDuration: argv.wait || argv.expectedDuration,
|
|
203
|
+
maxWaitMs: argv.maxWaitMs ?? argv.maxWait,
|
|
204
|
+
progressEveryMs: argv.progressEveryMs,
|
|
205
|
+
maxExtends: argv.maxExtends,
|
|
206
|
+
driver: argv.driver,
|
|
207
|
+
};
|
|
31
208
|
}
|
|
32
|
-
|
|
33
209
|
async function runQuery(text, argv) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
210
|
+
if (!text || !String(text).trim())
|
|
211
|
+
throw new Error('Query text is required');
|
|
212
|
+
if (argv.quiet)
|
|
213
|
+
process.env.QUIET = '1';
|
|
214
|
+
if (argv.debug)
|
|
215
|
+
process.env.DEBUG = '1';
|
|
216
|
+
if (argv.check !== false) {
|
|
217
|
+
const check = await fullCheck();
|
|
218
|
+
if (!check.allPassed) {
|
|
219
|
+
const failure = { ok: false, error: 'environment_not_ready', check, hints: formatAgentHints(check) };
|
|
220
|
+
if (argv.json)
|
|
221
|
+
writeJson(failure);
|
|
222
|
+
else
|
|
223
|
+
console.error(failure.hints);
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const result = await queryDoubao(String(text), parseQueryOptions(argv));
|
|
228
|
+
if (argv.json) {
|
|
229
|
+
writeJson(result);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (result.content && String(result.content).trim()) {
|
|
233
|
+
console.log(result.content);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
throw new Error('No valid Doubao reply received');
|
|
55
237
|
}
|
|
56
|
-
|
|
57
238
|
async function runDoctor(argv) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
239
|
+
const check = await fullCheck();
|
|
240
|
+
const readiness = await fullReadiness('doubao').catch((error) => ({ ok: false, error: error.message }));
|
|
241
|
+
const result = { ok: check.allPassed && readiness.browser === 'ready', version: pkg.version, check, readiness };
|
|
242
|
+
if (argv.json)
|
|
243
|
+
writeJson(result);
|
|
244
|
+
else {
|
|
245
|
+
console.log(`cdper-doubao ${pkg.version}`);
|
|
246
|
+
console.log(check.summary);
|
|
247
|
+
if (!check.allPassed)
|
|
248
|
+
console.log(formatAgentHints(check));
|
|
249
|
+
console.log(`Runtime: bridge=${readiness.bridge || 'unknown'} browser=${readiness.browser || 'unknown'} ws=${readiness.ws || 'unknown'}`);
|
|
250
|
+
}
|
|
251
|
+
if (!result.ok)
|
|
252
|
+
process.exit(1);
|
|
69
253
|
}
|
|
70
|
-
|
|
71
254
|
async function runStatus(argv) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
255
|
+
const result = await getRuntimeStatus('doubao');
|
|
256
|
+
if (argv.json)
|
|
257
|
+
writeJson(result);
|
|
258
|
+
else
|
|
259
|
+
console.log(JSON.stringify(redactValue(result), null, 2));
|
|
260
|
+
if (!result.ok)
|
|
261
|
+
process.exit(1);
|
|
75
262
|
}
|
|
76
|
-
|
|
77
263
|
function runSessions(argv) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
264
|
+
const cleaned = cleanupExpired();
|
|
265
|
+
const sessions = listSessions().filter((s) => s.platform === 'doubao');
|
|
266
|
+
const result = { ok: true, cleaned, sessions };
|
|
267
|
+
if (argv.json)
|
|
268
|
+
writeJson(result);
|
|
269
|
+
else {
|
|
270
|
+
console.log(`Doubao sessions (cleaned ${cleaned})`);
|
|
271
|
+
for (const s of sessions)
|
|
272
|
+
console.log(`${s.sessionId} turns=${s.turns} ttlMs=${s.ttl}`);
|
|
273
|
+
}
|
|
86
274
|
}
|
|
87
|
-
|
|
88
275
|
function runConfigSet(argv) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
276
|
+
const ws = String(argv.ws || '').trim();
|
|
277
|
+
if (!/^ws:\/\//i.test(ws) || !/token=/i.test(ws)) {
|
|
278
|
+
throw new Error('Expected --ws "ws://<host>:<port>/devtools/browser?token=<token>"');
|
|
279
|
+
}
|
|
280
|
+
const authPath = path.join(os.homedir(), '.cdp-auth.json');
|
|
281
|
+
fs.writeFileSync(authPath, JSON.stringify({ ws_url: ws }, null, 2) + '\n', { mode: 0o600 });
|
|
282
|
+
const result = { ok: true, path: authPath, message: 'Saved CDP WS config' };
|
|
283
|
+
if (argv.json)
|
|
284
|
+
writeJson(result);
|
|
285
|
+
else
|
|
286
|
+
console.log(`Saved ${authPath}`);
|
|
95
287
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
.option('max-wait-ms', { type: 'number', describe: 'Override max base wait' })
|
|
106
|
-
.option('max-wait', { type: 'number', describe: 'Alias for --max-wait-ms' })
|
|
107
|
-
.option('progress-every-ms', { type: 'number', describe: 'Progress snapshot interval' })
|
|
108
|
-
.option('max-extends', { type: 'number', describe: 'Max 60s wait extensions' })
|
|
109
|
-
.option('driver', { choices: ['puppeteer', 'playwright'], describe: 'Browser driver (default: CDPER_DRIVER or playwright)' })
|
|
110
|
-
.option('check', { type: 'boolean', default: true, describe: 'Run environment pre-check before query' })
|
|
111
|
-
.option('quiet', { alias: 'q', type: 'boolean', describe: 'Quiet logs' })
|
|
112
|
-
.option('debug', { alias: 'd', type: 'boolean', describe: 'Debug logs' });
|
|
288
|
+
function handleError(argv) {
|
|
289
|
+
return (error) => {
|
|
290
|
+
const result = { ok: false, error: error.message, cdp: error.cdp || null };
|
|
291
|
+
if (argv?.json)
|
|
292
|
+
writeJson(result);
|
|
293
|
+
else
|
|
294
|
+
console.error(JSON.stringify(redactValue(result), null, 2));
|
|
295
|
+
process.exit(1);
|
|
296
|
+
};
|
|
113
297
|
}
|
|
114
|
-
|
|
115
|
-
const rawArgs =
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
298
|
+
async function main() {
|
|
299
|
+
const rawArgs = process.argv.slice(2);
|
|
300
|
+
let parsed;
|
|
301
|
+
try {
|
|
302
|
+
parsed = parseCli(rawArgs);
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
failCli(error, rawArgs);
|
|
306
|
+
}
|
|
307
|
+
const { command, argv, text } = parsed;
|
|
308
|
+
if (command === 'query')
|
|
309
|
+
return runQuery(text, argv).catch(handleError(argv));
|
|
310
|
+
if (command === 'doctor' || command === 'check')
|
|
311
|
+
return runDoctor(argv).catch(handleError(argv));
|
|
312
|
+
if (command === 'status')
|
|
313
|
+
return runStatus(argv).catch(handleError(argv));
|
|
314
|
+
if (command === 'session') {
|
|
315
|
+
if (argv.action === 'close') {
|
|
316
|
+
if (!argv.id)
|
|
317
|
+
return handleError(argv)(new Error('session id is required'));
|
|
318
|
+
closeSession(argv.id);
|
|
319
|
+
const result = { ok: true, sessionId: argv.id };
|
|
320
|
+
if (argv.json)
|
|
321
|
+
writeJson(result);
|
|
322
|
+
else
|
|
323
|
+
console.log(`Closed ${argv.id}`);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
runSessions(argv);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (command === 'config set') {
|
|
330
|
+
try {
|
|
331
|
+
runConfigSet(argv);
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
handleError(argv)(error);
|
|
335
|
+
}
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (command === 'version') {
|
|
339
|
+
const result = { ok: true, name: pkg.name, version: pkg.version };
|
|
340
|
+
if (argv.json)
|
|
341
|
+
writeJson(result);
|
|
342
|
+
else
|
|
343
|
+
console.log(`${pkg.name} ${pkg.version}`);
|
|
147
344
|
}
|
|
148
|
-
process.exit(1);
|
|
149
|
-
})
|
|
150
|
-
.strict()
|
|
151
|
-
.help()
|
|
152
|
-
.parse();
|
|
153
|
-
|
|
154
|
-
function handleError(argv) {
|
|
155
|
-
return (error) => {
|
|
156
|
-
const result = { ok: false, error: error.message, cdp: error.cdp || null };
|
|
157
|
-
if (argv?.json) writeJson(result); else console.error(JSON.stringify(redactValue(result), null, 2));
|
|
158
|
-
process.exit(1);
|
|
159
|
-
};
|
|
160
345
|
}
|
|
346
|
+
main().catch((error) => handleError({})(error));
|