@bsbofmusic/cdper-doubao 1.1.1 → 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.
Files changed (3) hide show
  1. package/package.json +4 -4
  2. package/src/cli.js +317 -131
  3. package/src/public-api.js +15 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsbofmusic/cdper-doubao",
3
- "version": "1.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",
@@ -22,7 +22,8 @@
22
22
  },
23
23
  "files": [
24
24
  "manifest.json",
25
- "src/",
25
+ "src/**/*.js",
26
+ "src/**/*.d.ts",
26
27
  "bin/cdper-doubao.cjs"
27
28
  ],
28
29
  "keywords": [
@@ -48,7 +49,6 @@
48
49
  "node": ">=18.0.0"
49
50
  },
50
51
  "dependencies": {
51
- "@bsbofmusic/cdper-core": "~1.3.2",
52
- "yargs": "^17.7.2"
52
+ "@bsbofmusic/cdper-core": "~1.3.4"
53
53
  }
54
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
- process.stdout.write(JSON.stringify(redactValue(value), null, 2) + '\n');
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
- return {
22
- mode: argv.mode || 'expert',
23
- sessionId: argv.session,
24
- conversationPolicy: argv.conversationPolicy,
25
- expectedDuration: argv.wait || argv.expectedDuration,
26
- maxWaitMs: argv.maxWaitMs ?? argv.maxWait,
27
- progressEveryMs: argv.progressEveryMs,
28
- maxExtends: argv.maxExtends,
29
- driver: argv.driver,
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
- if (!text || !String(text).trim()) throw new Error('Query text is required');
35
- if (argv.quiet) process.env.QUIET = '1';
36
- if (argv.debug) process.env.DEBUG = '1';
37
- if (argv.check !== false) {
38
- const check = await fullCheck();
39
- if (!check.allPassed) {
40
- const failure = { ok: false, error: 'environment_not_ready', check, hints: formatAgentHints(check) };
41
- if (argv.json) writeJson(failure); else console.error(failure.hints);
42
- process.exit(1);
43
- }
44
- }
45
- const result = await queryDoubao(String(text), parseQueryOptions(argv));
46
- if (argv.json) {
47
- writeJson(result);
48
- return;
49
- }
50
- if (result.content && String(result.content).trim()) {
51
- console.log(result.content);
52
- return;
53
- }
54
- throw new Error('No valid Doubao reply received');
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
- const check = await fullCheck();
59
- const readiness = await fullReadiness('doubao').catch((error) => ({ ok: false, error: error.message }));
60
- const result = { ok: check.allPassed && readiness.browser === 'ready', version: pkg.version, check, readiness };
61
- if (argv.json) writeJson(result);
62
- else {
63
- console.log(`cdper-doubao ${pkg.version}`);
64
- console.log(check.summary);
65
- if (!check.allPassed) console.log(formatAgentHints(check));
66
- console.log(`Runtime: bridge=${readiness.bridge || 'unknown'} browser=${readiness.browser || 'unknown'} ws=${readiness.ws || 'unknown'}`);
67
- }
68
- if (!result.ok) process.exit(1);
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
- const result = await getRuntimeStatus('doubao');
73
- if (argv.json) writeJson(result); else console.log(JSON.stringify(redactValue(result), null, 2));
74
- if (!result.ok) process.exit(1);
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
- const cleaned = cleanupExpired();
79
- const sessions = listSessions().filter((s) => s.platform === 'doubao');
80
- const result = { ok: true, cleaned, sessions };
81
- if (argv.json) writeJson(result);
82
- else {
83
- console.log(`Doubao sessions (cleaned ${cleaned})`);
84
- for (const s of sessions) console.log(`${s.sessionId} turns=${s.turns} ttlMs=${s.ttl}`);
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
- const ws = String(argv.ws || '').trim();
90
- if (!/^ws:\/\//i.test(ws) || !/token=/i.test(ws)) throw new Error('Expected --ws "ws://<host>:<port>/devtools/browser?token=<token>"');
91
- const authPath = path.join(os.homedir(), '.cdp-auth.json');
92
- fs.writeFileSync(authPath, JSON.stringify({ ws_url: ws }, null, 2) + '\n', { mode: 0o600 });
93
- const result = { ok: true, path: authPath, message: 'Saved CDP WS config' };
94
- if (argv.json) writeJson(result); else console.log(`Saved ${authPath}`);
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
- function addQueryOptions(cmd) {
98
- return cmd
99
- .option('json', { type: 'boolean', describe: 'Output JSON' })
100
- .option('mode', { alias: 'm', default: 'expert', choices: ['expert'], describe: 'Doubao mode' })
101
- .option('session', { alias: 's', type: 'string', describe: 'Session ID' })
102
- .option('conversation-policy', { choices: ['auto', 'fresh', 'followup'], default: 'auto', describe: 'Conversation policy' })
103
- .option('wait', { choices: ['short', 'normal', 'long', 'very_long'], default: 'normal', describe: 'Wait profile' })
104
- .option('expected-duration', { choices: ['short', 'normal', 'long', 'very_long'], describe: 'Alias for --wait' })
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 = hideBin(process.argv);
116
- const cliArgs = rawArgs[0] === 'query' && rawArgs[1] && !String(rawArgs[1]).startsWith('-')
117
- ? rawArgs.slice(1)
118
- : rawArgs;
119
-
120
- yargs(cliArgs)
121
- .scriptName('cdper-doubao')
122
- .usage('$0 <query> [options]')
123
- .command('$0 <text>', 'Query Doubao', (cmd) => addQueryOptions(cmd.positional('text', { type: 'string', describe: 'Query text' })), async (argv) => runQuery(argv.text, argv).catch(handleError(argv)))
124
- .command('doctor', 'Check environment readiness', (cmd) => cmd.option('json', { type: 'boolean' }), async (argv) => runDoctor(argv).catch(handleError(argv)))
125
- .command('check', 'Alias for doctor', (cmd) => cmd.option('json', { type: 'boolean' }), async (argv) => runDoctor(argv).catch(handleError(argv)))
126
- .command('status', 'Show runtime status', (cmd) => cmd.option('json', { type: 'boolean' }), async (argv) => runStatus(argv).catch(handleError(argv)))
127
- .command('session [action] [id]', 'List or close sessions', (cmd) => cmd.positional('action', { type: 'string' }).positional('id', { type: 'string' }).option('json', { type: 'boolean' }), (argv) => {
128
- if (argv.action === 'close') {
129
- if (!argv.id) return handleError(argv)(new Error('session id is required'));
130
- closeSession(argv.id);
131
- const r = { ok: true, sessionId: argv.id };
132
- if (argv.json) writeJson(r); else console.log(`Closed ${argv.id}`);
133
- return;
134
- }
135
- runSessions(argv);
136
- })
137
- .command('config set', 'Save CDP WS config', (cmd) => cmd.option('ws', { type: 'string', demandOption: true }).option('json', { type: 'boolean' }), (argv) => { try { runConfigSet(argv); } catch (error) { handleError(argv)(error); } })
138
- .command('version', 'Show version', (cmd) => cmd.option('json', { type: 'boolean' }), (argv) => { const r = { ok: true, name: pkg.name, version: pkg.version }; if (argv.json) writeJson(r); else console.log(`${pkg.name} ${pkg.version}`); })
139
- .showHelpOnFail(false)
140
- .fail((msg, err, yargsInstance) => {
141
- const json = rawArgs.includes('--json');
142
- const error = err || new Error(msg || 'invalid arguments');
143
- if (json) writeJson({ ok: false, error: error.message });
144
- else {
145
- console.error(error.message);
146
- yargsInstance.showHelp('error');
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));
package/src/public-api.js CHANGED
@@ -1,16 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queryDoubao = exports.manifest = void 0;
4
+ exports.getCapabilities = getCapabilities;
1
5
  const manifest = require('../manifest.json');
6
+ exports.manifest = manifest;
2
7
  const { queryDoubao } = require('./doubao.js');
3
-
8
+ exports.queryDoubao = queryDoubao;
4
9
  function getCapabilities() {
5
- return (manifest.capabilities?.provides || []).map((id) => ({
6
- id,
7
- version: '1.0',
8
- summary: id,
9
- }));
10
+ const typedManifest = manifest;
11
+ return (typedManifest.capabilities?.provides || []).map((id) => ({
12
+ id,
13
+ version: '1.0',
14
+ summary: id,
15
+ }));
10
16
  }
11
-
12
17
  module.exports = {
13
- manifest,
14
- getCapabilities,
15
- queryDoubao,
18
+ manifest,
19
+ getCapabilities,
20
+ queryDoubao,
16
21
  };