@jackwener/opencli 1.3.1 → 1.3.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/CHANGELOG.md +128 -0
- package/README.md +48 -9
- package/README.zh-CN.md +48 -9
- package/SKILL.md +317 -6
- package/TESTING.md +4 -4
- package/dist/browser/cdp.js +10 -1
- package/dist/browser/daemon-client.js +2 -1
- package/dist/browser/discover.js +2 -1
- package/dist/browser/errors.d.ts +2 -1
- package/dist/browser/errors.js +10 -10
- package/dist/browser/index.d.ts +1 -0
- package/dist/browser/index.js +1 -0
- package/dist/browser/page.js +12 -0
- package/dist/browser/stealth.d.ts +18 -0
- package/dist/browser/stealth.js +140 -0
- package/dist/browser.test.js +47 -1
- package/dist/build-manifest.js +1 -3
- package/dist/cli-manifest.json +2573 -989
- package/dist/cli.js +42 -2
- package/dist/clis/bilibili/download.js +20 -65
- package/dist/clis/bilibili/utils.js +2 -1
- package/dist/clis/chaoxing/assignments.js +2 -1
- package/dist/clis/doubao/ask.d.ts +1 -0
- package/dist/clis/doubao/ask.js +35 -0
- package/dist/clis/doubao/common.d.ts +23 -0
- package/dist/clis/doubao/common.js +564 -0
- package/dist/clis/doubao/new.d.ts +1 -0
- package/dist/clis/doubao/new.js +20 -0
- package/dist/clis/doubao/read.d.ts +1 -0
- package/dist/clis/doubao/read.js +19 -0
- package/dist/clis/doubao/send.d.ts +1 -0
- package/dist/clis/doubao/send.js +22 -0
- package/dist/clis/doubao/status.d.ts +1 -0
- package/dist/clis/doubao/status.js +24 -0
- package/dist/clis/doubao-app/ask.d.ts +1 -0
- package/dist/clis/doubao-app/ask.js +53 -0
- package/dist/clis/doubao-app/common.d.ts +37 -0
- package/dist/clis/doubao-app/common.js +110 -0
- package/dist/clis/doubao-app/dump.d.ts +1 -0
- package/dist/clis/doubao-app/dump.js +24 -0
- package/dist/clis/doubao-app/new.d.ts +1 -0
- package/dist/clis/doubao-app/new.js +20 -0
- package/dist/clis/doubao-app/read.d.ts +1 -0
- package/dist/clis/doubao-app/read.js +18 -0
- package/dist/clis/doubao-app/screenshot.d.ts +1 -0
- package/dist/clis/doubao-app/screenshot.js +18 -0
- package/dist/clis/doubao-app/send.d.ts +1 -0
- package/dist/clis/doubao-app/send.js +27 -0
- package/dist/clis/doubao-app/status.d.ts +1 -0
- package/dist/clis/doubao-app/status.js +16 -0
- package/dist/clis/hackernews/ask.yaml +38 -0
- package/dist/clis/hackernews/best.yaml +38 -0
- package/dist/clis/hackernews/jobs.yaml +36 -0
- package/dist/clis/hackernews/new.yaml +38 -0
- package/dist/clis/hackernews/search.yaml +44 -0
- package/dist/clis/hackernews/show.yaml +38 -0
- package/dist/clis/hackernews/top.yaml +3 -1
- package/dist/clis/hackernews/user.yaml +25 -0
- package/dist/clis/twitter/download.js +13 -97
- package/dist/clis/twitter/thread.js +2 -1
- package/dist/clis/v2ex/member.yaml +29 -0
- package/dist/clis/v2ex/node.yaml +34 -0
- package/dist/clis/v2ex/nodes.yaml +31 -0
- package/dist/clis/v2ex/replies.yaml +32 -0
- package/dist/clis/v2ex/user.yaml +34 -0
- package/dist/clis/weibo/search.d.ts +1 -0
- package/dist/clis/weibo/search.js +73 -0
- package/dist/clis/weixin/download.d.ts +12 -0
- package/dist/clis/weixin/download.js +183 -0
- package/dist/clis/xiaohongshu/download.js +12 -60
- package/dist/clis/xiaohongshu/publish.d.ts +18 -0
- package/dist/clis/xiaohongshu/publish.js +352 -0
- package/dist/clis/xiaohongshu/search.js +47 -15
- package/dist/clis/xiaohongshu/search.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/search.test.js +114 -0
- package/dist/clis/yollomi/background.d.ts +4 -0
- package/dist/clis/yollomi/background.js +45 -0
- package/dist/clis/yollomi/edit.d.ts +5 -0
- package/dist/clis/yollomi/edit.js +56 -0
- package/dist/clis/yollomi/face-swap.d.ts +5 -0
- package/dist/clis/yollomi/face-swap.js +43 -0
- package/dist/clis/yollomi/generate.d.ts +9 -0
- package/dist/clis/yollomi/generate.js +100 -0
- package/dist/clis/yollomi/models.d.ts +1 -0
- package/dist/clis/yollomi/models.js +33 -0
- package/dist/clis/yollomi/object-remover.d.ts +4 -0
- package/dist/clis/yollomi/object-remover.js +42 -0
- package/dist/clis/yollomi/remove-bg.d.ts +4 -0
- package/dist/clis/yollomi/remove-bg.js +38 -0
- package/dist/clis/yollomi/restore.d.ts +4 -0
- package/dist/clis/yollomi/restore.js +38 -0
- package/dist/clis/yollomi/try-on.d.ts +4 -0
- package/dist/clis/yollomi/try-on.js +46 -0
- package/dist/clis/yollomi/upload.d.ts +7 -0
- package/dist/clis/yollomi/upload.js +71 -0
- package/dist/clis/yollomi/upscale.d.ts +4 -0
- package/dist/clis/yollomi/upscale.js +53 -0
- package/dist/clis/yollomi/utils.d.ts +45 -0
- package/dist/clis/yollomi/utils.js +180 -0
- package/dist/clis/yollomi/video.d.ts +5 -0
- package/dist/clis/yollomi/video.js +56 -0
- package/dist/clis/zhihu/download.d.ts +1 -5
- package/dist/clis/zhihu/download.js +20 -126
- package/dist/clis/zhihu/download.test.js +7 -5
- package/dist/clis/zhihu/question.js +2 -1
- package/dist/commanderAdapter.js +4 -6
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/daemon.js +7 -3
- package/dist/discovery.js +10 -10
- package/dist/doctor.js +2 -1
- package/dist/download/article-download.d.ts +59 -0
- package/dist/download/article-download.js +178 -0
- package/dist/download/media-download.d.ts +49 -0
- package/dist/download/media-download.js +112 -0
- package/dist/errors.d.ts +23 -2
- package/dist/errors.js +58 -2
- package/dist/errors.test.d.ts +1 -0
- package/dist/errors.test.js +59 -0
- package/dist/execution.js +9 -10
- package/dist/explore.js +4 -2
- package/dist/external.d.ts +15 -0
- package/dist/external.js +48 -2
- package/dist/external.test.d.ts +1 -0
- package/dist/external.test.js +64 -0
- package/dist/main.js +10 -0
- package/dist/plugin.d.ts +4 -0
- package/dist/plugin.js +45 -23
- package/dist/plugin.test.js +6 -1
- package/dist/record.d.ts +47 -0
- package/dist/record.js +545 -0
- package/dist/registry.d.ts +7 -2
- package/dist/registry.js +2 -6
- package/dist/runtime.d.ts +3 -1
- package/dist/runtime.js +10 -3
- package/dist/validate.js +1 -3
- package/docs/.vitepress/config.mts +1 -0
- package/docs/adapters/browser/douban.md +18 -8
- package/docs/adapters/browser/doubao.md +35 -0
- package/docs/adapters/browser/hackernews.md +20 -4
- package/docs/adapters/browser/tiktok.md +1 -1
- package/docs/adapters/browser/v2ex.md +31 -10
- package/docs/adapters/browser/weibo.md +4 -0
- package/docs/adapters/browser/weixin.md +33 -0
- package/docs/adapters/browser/wikipedia.md +0 -9
- package/docs/adapters/browser/xiaohongshu.md +8 -6
- package/docs/adapters/browser/yollomi.md +69 -0
- package/docs/adapters/desktop/antigravity.md +0 -3
- package/docs/adapters/desktop/doubao-app.md +35 -0
- package/docs/adapters/index.md +19 -8
- package/docs/advanced/download.md +4 -0
- package/package.json +3 -1
- package/src/browser/cdp.ts +9 -1
- package/src/browser/daemon-client.ts +4 -3
- package/src/browser/discover.ts +2 -1
- package/src/browser/errors.ts +18 -11
- package/src/browser/index.ts +1 -0
- package/src/browser/page.ts +11 -0
- package/src/browser/stealth.ts +142 -0
- package/src/browser.test.ts +51 -1
- package/src/build-manifest.ts +1 -3
- package/src/cli.ts +45 -2
- package/src/clis/bilibili/download.ts +25 -83
- package/src/clis/bilibili/utils.ts +2 -1
- package/src/clis/chaoxing/assignments.ts +2 -1
- package/src/clis/doubao/ask.ts +40 -0
- package/src/clis/doubao/common.ts +619 -0
- package/src/clis/doubao/new.ts +22 -0
- package/src/clis/doubao/read.ts +20 -0
- package/src/clis/doubao/send.ts +25 -0
- package/src/clis/doubao/status.ts +27 -0
- package/src/clis/doubao-app/ask.ts +60 -0
- package/src/clis/doubao-app/common.ts +116 -0
- package/src/clis/doubao-app/dump.ts +28 -0
- package/src/clis/doubao-app/new.ts +21 -0
- package/src/clis/doubao-app/read.ts +21 -0
- package/src/clis/doubao-app/screenshot.ts +19 -0
- package/src/clis/doubao-app/send.ts +30 -0
- package/src/clis/doubao-app/status.ts +17 -0
- package/src/clis/hackernews/ask.yaml +38 -0
- package/src/clis/hackernews/best.yaml +38 -0
- package/src/clis/hackernews/jobs.yaml +36 -0
- package/src/clis/hackernews/new.yaml +38 -0
- package/src/clis/hackernews/search.yaml +44 -0
- package/src/clis/hackernews/show.yaml +38 -0
- package/src/clis/hackernews/top.yaml +3 -1
- package/src/clis/hackernews/user.yaml +25 -0
- package/src/clis/twitter/download.ts +13 -111
- package/src/clis/twitter/thread.ts +2 -1
- package/src/clis/v2ex/member.yaml +29 -0
- package/src/clis/v2ex/node.yaml +34 -0
- package/src/clis/v2ex/nodes.yaml +31 -0
- package/src/clis/v2ex/replies.yaml +32 -0
- package/src/clis/v2ex/user.yaml +34 -0
- package/src/clis/weibo/search.ts +78 -0
- package/src/clis/weixin/download.ts +199 -0
- package/src/clis/xiaohongshu/download.ts +12 -71
- package/src/clis/xiaohongshu/publish.ts +392 -0
- package/src/clis/xiaohongshu/search.test.ts +134 -0
- package/src/clis/xiaohongshu/search.ts +49 -15
- package/src/clis/yollomi/background.ts +48 -0
- package/src/clis/yollomi/edit.ts +58 -0
- package/src/clis/yollomi/face-swap.ts +45 -0
- package/src/clis/yollomi/generate.ts +95 -0
- package/src/clis/yollomi/models.ts +38 -0
- package/src/clis/yollomi/object-remover.ts +44 -0
- package/src/clis/yollomi/remove-bg.ts +40 -0
- package/src/clis/yollomi/restore.ts +40 -0
- package/src/clis/yollomi/try-on.ts +48 -0
- package/src/clis/yollomi/upload.ts +78 -0
- package/src/clis/yollomi/upscale.ts +49 -0
- package/src/clis/yollomi/utils.ts +202 -0
- package/src/clis/yollomi/video.ts +61 -0
- package/src/clis/zhihu/download.test.ts +7 -5
- package/src/clis/zhihu/download.ts +23 -158
- package/src/clis/zhihu/question.ts +2 -1
- package/src/commanderAdapter.ts +4 -7
- package/src/constants.ts +3 -0
- package/src/daemon.ts +7 -3
- package/src/discovery.ts +26 -26
- package/src/doctor.ts +2 -1
- package/src/download/article-download.ts +272 -0
- package/src/download/media-download.ts +178 -0
- package/src/errors.test.ts +79 -0
- package/src/errors.ts +92 -2
- package/src/execution.ts +14 -10
- package/src/explore.ts +4 -2
- package/src/external.test.ts +88 -0
- package/src/external.ts +56 -2
- package/src/generate.ts +2 -1
- package/src/main.ts +10 -0
- package/src/plugin.test.ts +7 -1
- package/src/plugin.ts +49 -25
- package/src/record.ts +617 -0
- package/src/registry.ts +9 -5
- package/src/runtime.ts +16 -4
- package/src/validate.ts +1 -3
- package/tests/e2e/browser-auth.test.ts +10 -1
- package/tests/e2e/browser-public.test.ts +13 -8
- package/tests/e2e/public-commands.test.ts +209 -21
- package/tests/smoke/api-health.test.ts +65 -6
package/dist/cli.js
CHANGED
|
@@ -166,6 +166,28 @@ export function runCli(BUILTIN_CLIS, USER_CLIS) {
|
|
|
166
166
|
console.log(renderGenerateSummary(r));
|
|
167
167
|
process.exitCode = r.ok ? 0 : 1;
|
|
168
168
|
});
|
|
169
|
+
// ── Built-in: record ─────────────────────────────────────────────────────
|
|
170
|
+
program
|
|
171
|
+
.command('record')
|
|
172
|
+
.description('Record API calls from a live browser session → generate YAML candidates')
|
|
173
|
+
.argument('<url>', 'URL to open and record')
|
|
174
|
+
.option('--site <name>', 'Site name (inferred from URL if omitted)')
|
|
175
|
+
.option('--out <dir>', 'Output directory for candidates')
|
|
176
|
+
.option('--poll <ms>', 'Poll interval in milliseconds', '2000')
|
|
177
|
+
.option('--timeout <ms>', 'Auto-stop after N milliseconds (default: 60000)', '60000')
|
|
178
|
+
.action(async (url, opts) => {
|
|
179
|
+
const { recordSession, renderRecordSummary } = await import('./record.js');
|
|
180
|
+
const result = await recordSession({
|
|
181
|
+
BrowserFactory: getBrowserFactory(),
|
|
182
|
+
url,
|
|
183
|
+
site: opts.site,
|
|
184
|
+
outDir: opts.out,
|
|
185
|
+
pollMs: parseInt(opts.poll, 10),
|
|
186
|
+
timeoutMs: parseInt(opts.timeout, 10),
|
|
187
|
+
});
|
|
188
|
+
console.log(renderRecordSummary(result));
|
|
189
|
+
process.exitCode = result.candidateCount > 0 ? 0 : 1;
|
|
190
|
+
});
|
|
169
191
|
program
|
|
170
192
|
.command('cascade')
|
|
171
193
|
.description('Strategy cascade: find simplest working strategy')
|
|
@@ -211,10 +233,11 @@ export function runCli(BUILTIN_CLIS, USER_CLIS) {
|
|
|
211
233
|
.argument('<source>', 'Plugin source (e.g. github:user/repo)')
|
|
212
234
|
.action(async (source) => {
|
|
213
235
|
const { installPlugin } = await import('./plugin.js');
|
|
236
|
+
const { discoverPlugins } = await import('./discovery.js');
|
|
214
237
|
try {
|
|
215
238
|
const name = installPlugin(source);
|
|
216
|
-
|
|
217
|
-
console.log(chalk.
|
|
239
|
+
await discoverPlugins();
|
|
240
|
+
console.log(chalk.green(`✅ Plugin "${name}" installed successfully. Commands are ready to use.`));
|
|
218
241
|
}
|
|
219
242
|
catch (err) {
|
|
220
243
|
console.error(chalk.red(`Error: ${err.message}`));
|
|
@@ -236,6 +259,23 @@ export function runCli(BUILTIN_CLIS, USER_CLIS) {
|
|
|
236
259
|
process.exitCode = 1;
|
|
237
260
|
}
|
|
238
261
|
});
|
|
262
|
+
pluginCmd
|
|
263
|
+
.command('update')
|
|
264
|
+
.description('Update a plugin to the latest version')
|
|
265
|
+
.argument('<name>', 'Plugin name')
|
|
266
|
+
.action(async (name) => {
|
|
267
|
+
const { updatePlugin } = await import('./plugin.js');
|
|
268
|
+
const { discoverPlugins } = await import('./discovery.js');
|
|
269
|
+
try {
|
|
270
|
+
updatePlugin(name);
|
|
271
|
+
await discoverPlugins();
|
|
272
|
+
console.log(chalk.green(`✅ Plugin "${name}" updated successfully.`));
|
|
273
|
+
}
|
|
274
|
+
catch (err) {
|
|
275
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
276
|
+
process.exitCode = 1;
|
|
277
|
+
}
|
|
278
|
+
});
|
|
239
279
|
pluginCmd
|
|
240
280
|
.command('list')
|
|
241
281
|
.description('List installed plugins')
|
|
@@ -7,11 +7,9 @@
|
|
|
7
7
|
* Requirements:
|
|
8
8
|
* - yt-dlp must be installed: pip install yt-dlp
|
|
9
9
|
*/
|
|
10
|
-
import * as fs from 'node:fs';
|
|
11
|
-
import * as path from 'node:path';
|
|
12
10
|
import { cli, Strategy } from '../../registry.js';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
11
|
+
import { checkYtdlp, sanitizeFilename } from '../../download/index.js';
|
|
12
|
+
import { downloadMedia } from '../../download/media-download.js';
|
|
15
13
|
cli({
|
|
16
14
|
site: 'bilibili',
|
|
17
15
|
name: 'download',
|
|
@@ -49,19 +47,8 @@ cli({
|
|
|
49
47
|
})()
|
|
50
48
|
`);
|
|
51
49
|
const title = sanitizeFilename(data?.title || 'video');
|
|
52
|
-
// Extract cookies for
|
|
53
|
-
const
|
|
54
|
-
const cookieString = formatCookieHeader(cookies);
|
|
55
|
-
// Create output directory
|
|
56
|
-
fs.mkdirSync(output, { recursive: true });
|
|
57
|
-
// Export cookies to Netscape format for yt-dlp
|
|
58
|
-
let cookiesFile;
|
|
59
|
-
if (cookies.length > 0) {
|
|
60
|
-
const tempDir = getTempDir();
|
|
61
|
-
fs.mkdirSync(tempDir, { recursive: true });
|
|
62
|
-
cookiesFile = path.join(tempDir, `bilibili_cookies_${Date.now()}.txt`);
|
|
63
|
-
exportCookiesToNetscape(cookies, cookiesFile);
|
|
64
|
-
}
|
|
50
|
+
// Extract cookies for yt-dlp
|
|
51
|
+
const browserCookies = await page.getCookies({ domain: 'bilibili.com' });
|
|
65
52
|
// Build yt-dlp format string based on quality
|
|
66
53
|
let format = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best';
|
|
67
54
|
if (quality === '1080p') {
|
|
@@ -73,53 +60,21 @@ cli({
|
|
|
73
60
|
else if (quality === '480p') {
|
|
74
61
|
format = 'bestvideo[height<=480][ext=mp4]+bestaudio[ext=m4a]/best[height<=480]';
|
|
75
62
|
}
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
if (progressBar) {
|
|
93
|
-
progressBar.complete(result.success, result.success ? formatBytes(result.size) : undefined);
|
|
94
|
-
}
|
|
95
|
-
tracker.onFileComplete(result.success);
|
|
96
|
-
tracker.finish();
|
|
97
|
-
// Cleanup cookies file
|
|
98
|
-
if (cookiesFile && fs.existsSync(cookiesFile)) {
|
|
99
|
-
fs.unlinkSync(cookiesFile);
|
|
100
|
-
}
|
|
101
|
-
return [{
|
|
102
|
-
bvid,
|
|
103
|
-
title: data?.title || 'video',
|
|
104
|
-
status: result.success ? 'success' : 'failed',
|
|
105
|
-
size: result.success ? formatBytes(result.size) : (result.error || 'unknown error'),
|
|
106
|
-
}];
|
|
107
|
-
}
|
|
108
|
-
catch (err) {
|
|
109
|
-
if (progressBar)
|
|
110
|
-
progressBar.fail(err.message);
|
|
111
|
-
tracker.onFileComplete(false);
|
|
112
|
-
tracker.finish();
|
|
113
|
-
// Cleanup cookies file
|
|
114
|
-
if (cookiesFile && fs.existsSync(cookiesFile)) {
|
|
115
|
-
fs.unlinkSync(cookiesFile);
|
|
116
|
-
}
|
|
117
|
-
return [{
|
|
118
|
-
bvid,
|
|
119
|
-
title: data?.title || 'video',
|
|
120
|
-
status: 'failed',
|
|
121
|
-
size: err.message,
|
|
122
|
-
}];
|
|
123
|
-
}
|
|
63
|
+
const videoUrl = `https://www.bilibili.com/video/${bvid}`;
|
|
64
|
+
const filename = `${bvid}_${title}.mp4`;
|
|
65
|
+
const results = await downloadMedia([{ type: 'video-ytdlp', url: videoUrl, filename }], {
|
|
66
|
+
output,
|
|
67
|
+
browserCookies,
|
|
68
|
+
filenamePrefix: bvid,
|
|
69
|
+
ytdlpExtraArgs: ['-f', format, '--merge-output-format', 'mp4', '--embed-thumbnail'],
|
|
70
|
+
});
|
|
71
|
+
// Map results to bilibili-specific columns
|
|
72
|
+
const r = results[0] || { status: 'failed', size: '-' };
|
|
73
|
+
return [{
|
|
74
|
+
bvid,
|
|
75
|
+
title: data?.title || 'video',
|
|
76
|
+
status: r.status,
|
|
77
|
+
size: r.size,
|
|
78
|
+
}];
|
|
124
79
|
},
|
|
125
80
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bilibili shared helpers: WBI signing, authenticated fetch, nav data, UID resolution.
|
|
3
3
|
*/
|
|
4
|
+
import { AuthRequiredError } from '../../errors.js';
|
|
4
5
|
const MIXIN_KEY_ENC_TAB = [
|
|
5
6
|
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
|
|
6
7
|
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
|
|
@@ -77,7 +78,7 @@ export async function getSelfUid(page) {
|
|
|
77
78
|
const nav = await getNavData(page);
|
|
78
79
|
const mid = nav?.data?.mid;
|
|
79
80
|
if (!mid)
|
|
80
|
-
throw new
|
|
81
|
+
throw new AuthRequiredError('bilibili.com');
|
|
81
82
|
return String(mid);
|
|
82
83
|
}
|
|
83
84
|
export async function resolveUid(page, input) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { AuthRequiredError } from '../../errors.js';
|
|
2
3
|
import { getCourses, initSession, enterCourse, getTabIframeUrl, parseAssignmentsFromDom, sleep, } from './utils.js';
|
|
3
4
|
cli({
|
|
4
5
|
site: 'chaoxing',
|
|
@@ -26,7 +27,7 @@ cli({
|
|
|
26
27
|
// 2. Get courses
|
|
27
28
|
const courses = await getCourses(page);
|
|
28
29
|
if (!courses.length)
|
|
29
|
-
throw new
|
|
30
|
+
throw new AuthRequiredError('mooc2-ans.chaoxing.com', '未获取到课程列表');
|
|
30
31
|
const filtered = courseFilter
|
|
31
32
|
? courses.filter(c => c.title.includes(courseFilter))
|
|
32
33
|
: courses;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const askCommand: import("../../registry.js").CliCommand;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { DOUBAO_DOMAIN, getDoubaoTranscriptLines, getDoubaoVisibleTurns, sendDoubaoMessage, waitForDoubaoResponse } from './common.js';
|
|
3
|
+
export const askCommand = cli({
|
|
4
|
+
site: 'doubao',
|
|
5
|
+
name: 'ask',
|
|
6
|
+
description: 'Send a prompt and wait for the Doubao response',
|
|
7
|
+
domain: DOUBAO_DOMAIN,
|
|
8
|
+
strategy: Strategy.COOKIE,
|
|
9
|
+
browser: true,
|
|
10
|
+
navigateBefore: false,
|
|
11
|
+
timeoutSeconds: 180,
|
|
12
|
+
args: [
|
|
13
|
+
{ name: 'text', required: true, positional: true, help: 'Prompt to send' },
|
|
14
|
+
{ name: 'timeout', required: false, help: 'Max seconds to wait (default: 60)', default: '60' },
|
|
15
|
+
],
|
|
16
|
+
columns: ['Role', 'Text'],
|
|
17
|
+
func: async (page, kwargs) => {
|
|
18
|
+
const text = kwargs.text;
|
|
19
|
+
const timeout = parseInt(kwargs.timeout, 10) || 60;
|
|
20
|
+
const beforeTurns = await getDoubaoVisibleTurns(page);
|
|
21
|
+
const beforeLines = await getDoubaoTranscriptLines(page);
|
|
22
|
+
await sendDoubaoMessage(page, text);
|
|
23
|
+
const response = await waitForDoubaoResponse(page, beforeLines, beforeTurns, text, timeout);
|
|
24
|
+
if (!response) {
|
|
25
|
+
return [
|
|
26
|
+
{ Role: 'User', Text: text },
|
|
27
|
+
{ Role: 'System', Text: `No response within ${timeout}s. Doubao may still be generating.` },
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
return [
|
|
31
|
+
{ Role: 'User', Text: text },
|
|
32
|
+
{ Role: 'Assistant', Text: response },
|
|
33
|
+
];
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { IPage } from '../../types.js';
|
|
2
|
+
export declare const DOUBAO_DOMAIN = "www.doubao.com";
|
|
3
|
+
export declare const DOUBAO_CHAT_URL = "https://www.doubao.com/chat";
|
|
4
|
+
export declare const DOUBAO_NEW_CHAT_URL = "https://www.doubao.com/chat/new-thread/create-by-msg";
|
|
5
|
+
export interface DoubaoTurn {
|
|
6
|
+
Role: 'User' | 'Assistant' | 'System';
|
|
7
|
+
Text: string;
|
|
8
|
+
}
|
|
9
|
+
export interface DoubaoPageState {
|
|
10
|
+
url: string;
|
|
11
|
+
title: string;
|
|
12
|
+
isLogin: boolean | null;
|
|
13
|
+
accountDescription: string;
|
|
14
|
+
placeholder: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function ensureDoubaoChatPage(page: IPage): Promise<void>;
|
|
17
|
+
export declare function getDoubaoPageState(page: IPage): Promise<DoubaoPageState>;
|
|
18
|
+
export declare function getDoubaoTurns(page: IPage): Promise<DoubaoTurn[]>;
|
|
19
|
+
export declare function getDoubaoVisibleTurns(page: IPage): Promise<DoubaoTurn[]>;
|
|
20
|
+
export declare function getDoubaoTranscriptLines(page: IPage): Promise<string[]>;
|
|
21
|
+
export declare function sendDoubaoMessage(page: IPage, text: string): Promise<'button' | 'enter'>;
|
|
22
|
+
export declare function waitForDoubaoResponse(page: IPage, beforeLines: string[], beforeTurns: DoubaoTurn[], promptText: string, timeoutSeconds: number): Promise<string>;
|
|
23
|
+
export declare function startNewDoubaoChat(page: IPage): Promise<string>;
|