@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.
Files changed (241) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/README.md +48 -9
  3. package/README.zh-CN.md +48 -9
  4. package/SKILL.md +317 -6
  5. package/TESTING.md +4 -4
  6. package/dist/browser/cdp.js +10 -1
  7. package/dist/browser/daemon-client.js +2 -1
  8. package/dist/browser/discover.js +2 -1
  9. package/dist/browser/errors.d.ts +2 -1
  10. package/dist/browser/errors.js +10 -10
  11. package/dist/browser/index.d.ts +1 -0
  12. package/dist/browser/index.js +1 -0
  13. package/dist/browser/page.js +12 -0
  14. package/dist/browser/stealth.d.ts +18 -0
  15. package/dist/browser/stealth.js +140 -0
  16. package/dist/browser.test.js +47 -1
  17. package/dist/build-manifest.js +1 -3
  18. package/dist/cli-manifest.json +2573 -989
  19. package/dist/cli.js +42 -2
  20. package/dist/clis/bilibili/download.js +20 -65
  21. package/dist/clis/bilibili/utils.js +2 -1
  22. package/dist/clis/chaoxing/assignments.js +2 -1
  23. package/dist/clis/doubao/ask.d.ts +1 -0
  24. package/dist/clis/doubao/ask.js +35 -0
  25. package/dist/clis/doubao/common.d.ts +23 -0
  26. package/dist/clis/doubao/common.js +564 -0
  27. package/dist/clis/doubao/new.d.ts +1 -0
  28. package/dist/clis/doubao/new.js +20 -0
  29. package/dist/clis/doubao/read.d.ts +1 -0
  30. package/dist/clis/doubao/read.js +19 -0
  31. package/dist/clis/doubao/send.d.ts +1 -0
  32. package/dist/clis/doubao/send.js +22 -0
  33. package/dist/clis/doubao/status.d.ts +1 -0
  34. package/dist/clis/doubao/status.js +24 -0
  35. package/dist/clis/doubao-app/ask.d.ts +1 -0
  36. package/dist/clis/doubao-app/ask.js +53 -0
  37. package/dist/clis/doubao-app/common.d.ts +37 -0
  38. package/dist/clis/doubao-app/common.js +110 -0
  39. package/dist/clis/doubao-app/dump.d.ts +1 -0
  40. package/dist/clis/doubao-app/dump.js +24 -0
  41. package/dist/clis/doubao-app/new.d.ts +1 -0
  42. package/dist/clis/doubao-app/new.js +20 -0
  43. package/dist/clis/doubao-app/read.d.ts +1 -0
  44. package/dist/clis/doubao-app/read.js +18 -0
  45. package/dist/clis/doubao-app/screenshot.d.ts +1 -0
  46. package/dist/clis/doubao-app/screenshot.js +18 -0
  47. package/dist/clis/doubao-app/send.d.ts +1 -0
  48. package/dist/clis/doubao-app/send.js +27 -0
  49. package/dist/clis/doubao-app/status.d.ts +1 -0
  50. package/dist/clis/doubao-app/status.js +16 -0
  51. package/dist/clis/hackernews/ask.yaml +38 -0
  52. package/dist/clis/hackernews/best.yaml +38 -0
  53. package/dist/clis/hackernews/jobs.yaml +36 -0
  54. package/dist/clis/hackernews/new.yaml +38 -0
  55. package/dist/clis/hackernews/search.yaml +44 -0
  56. package/dist/clis/hackernews/show.yaml +38 -0
  57. package/dist/clis/hackernews/top.yaml +3 -1
  58. package/dist/clis/hackernews/user.yaml +25 -0
  59. package/dist/clis/twitter/download.js +13 -97
  60. package/dist/clis/twitter/thread.js +2 -1
  61. package/dist/clis/v2ex/member.yaml +29 -0
  62. package/dist/clis/v2ex/node.yaml +34 -0
  63. package/dist/clis/v2ex/nodes.yaml +31 -0
  64. package/dist/clis/v2ex/replies.yaml +32 -0
  65. package/dist/clis/v2ex/user.yaml +34 -0
  66. package/dist/clis/weibo/search.d.ts +1 -0
  67. package/dist/clis/weibo/search.js +73 -0
  68. package/dist/clis/weixin/download.d.ts +12 -0
  69. package/dist/clis/weixin/download.js +183 -0
  70. package/dist/clis/xiaohongshu/download.js +12 -60
  71. package/dist/clis/xiaohongshu/publish.d.ts +18 -0
  72. package/dist/clis/xiaohongshu/publish.js +352 -0
  73. package/dist/clis/xiaohongshu/search.js +47 -15
  74. package/dist/clis/xiaohongshu/search.test.d.ts +1 -0
  75. package/dist/clis/xiaohongshu/search.test.js +114 -0
  76. package/dist/clis/yollomi/background.d.ts +4 -0
  77. package/dist/clis/yollomi/background.js +45 -0
  78. package/dist/clis/yollomi/edit.d.ts +5 -0
  79. package/dist/clis/yollomi/edit.js +56 -0
  80. package/dist/clis/yollomi/face-swap.d.ts +5 -0
  81. package/dist/clis/yollomi/face-swap.js +43 -0
  82. package/dist/clis/yollomi/generate.d.ts +9 -0
  83. package/dist/clis/yollomi/generate.js +100 -0
  84. package/dist/clis/yollomi/models.d.ts +1 -0
  85. package/dist/clis/yollomi/models.js +33 -0
  86. package/dist/clis/yollomi/object-remover.d.ts +4 -0
  87. package/dist/clis/yollomi/object-remover.js +42 -0
  88. package/dist/clis/yollomi/remove-bg.d.ts +4 -0
  89. package/dist/clis/yollomi/remove-bg.js +38 -0
  90. package/dist/clis/yollomi/restore.d.ts +4 -0
  91. package/dist/clis/yollomi/restore.js +38 -0
  92. package/dist/clis/yollomi/try-on.d.ts +4 -0
  93. package/dist/clis/yollomi/try-on.js +46 -0
  94. package/dist/clis/yollomi/upload.d.ts +7 -0
  95. package/dist/clis/yollomi/upload.js +71 -0
  96. package/dist/clis/yollomi/upscale.d.ts +4 -0
  97. package/dist/clis/yollomi/upscale.js +53 -0
  98. package/dist/clis/yollomi/utils.d.ts +45 -0
  99. package/dist/clis/yollomi/utils.js +180 -0
  100. package/dist/clis/yollomi/video.d.ts +5 -0
  101. package/dist/clis/yollomi/video.js +56 -0
  102. package/dist/clis/zhihu/download.d.ts +1 -5
  103. package/dist/clis/zhihu/download.js +20 -126
  104. package/dist/clis/zhihu/download.test.js +7 -5
  105. package/dist/clis/zhihu/question.js +2 -1
  106. package/dist/commanderAdapter.js +4 -6
  107. package/dist/constants.d.ts +2 -0
  108. package/dist/constants.js +2 -0
  109. package/dist/daemon.js +7 -3
  110. package/dist/discovery.js +10 -10
  111. package/dist/doctor.js +2 -1
  112. package/dist/download/article-download.d.ts +59 -0
  113. package/dist/download/article-download.js +178 -0
  114. package/dist/download/media-download.d.ts +49 -0
  115. package/dist/download/media-download.js +112 -0
  116. package/dist/errors.d.ts +23 -2
  117. package/dist/errors.js +58 -2
  118. package/dist/errors.test.d.ts +1 -0
  119. package/dist/errors.test.js +59 -0
  120. package/dist/execution.js +9 -10
  121. package/dist/explore.js +4 -2
  122. package/dist/external.d.ts +15 -0
  123. package/dist/external.js +48 -2
  124. package/dist/external.test.d.ts +1 -0
  125. package/dist/external.test.js +64 -0
  126. package/dist/main.js +10 -0
  127. package/dist/plugin.d.ts +4 -0
  128. package/dist/plugin.js +45 -23
  129. package/dist/plugin.test.js +6 -1
  130. package/dist/record.d.ts +47 -0
  131. package/dist/record.js +545 -0
  132. package/dist/registry.d.ts +7 -2
  133. package/dist/registry.js +2 -6
  134. package/dist/runtime.d.ts +3 -1
  135. package/dist/runtime.js +10 -3
  136. package/dist/validate.js +1 -3
  137. package/docs/.vitepress/config.mts +1 -0
  138. package/docs/adapters/browser/douban.md +18 -8
  139. package/docs/adapters/browser/doubao.md +35 -0
  140. package/docs/adapters/browser/hackernews.md +20 -4
  141. package/docs/adapters/browser/tiktok.md +1 -1
  142. package/docs/adapters/browser/v2ex.md +31 -10
  143. package/docs/adapters/browser/weibo.md +4 -0
  144. package/docs/adapters/browser/weixin.md +33 -0
  145. package/docs/adapters/browser/wikipedia.md +0 -9
  146. package/docs/adapters/browser/xiaohongshu.md +8 -6
  147. package/docs/adapters/browser/yollomi.md +69 -0
  148. package/docs/adapters/desktop/antigravity.md +0 -3
  149. package/docs/adapters/desktop/doubao-app.md +35 -0
  150. package/docs/adapters/index.md +19 -8
  151. package/docs/advanced/download.md +4 -0
  152. package/package.json +3 -1
  153. package/src/browser/cdp.ts +9 -1
  154. package/src/browser/daemon-client.ts +4 -3
  155. package/src/browser/discover.ts +2 -1
  156. package/src/browser/errors.ts +18 -11
  157. package/src/browser/index.ts +1 -0
  158. package/src/browser/page.ts +11 -0
  159. package/src/browser/stealth.ts +142 -0
  160. package/src/browser.test.ts +51 -1
  161. package/src/build-manifest.ts +1 -3
  162. package/src/cli.ts +45 -2
  163. package/src/clis/bilibili/download.ts +25 -83
  164. package/src/clis/bilibili/utils.ts +2 -1
  165. package/src/clis/chaoxing/assignments.ts +2 -1
  166. package/src/clis/doubao/ask.ts +40 -0
  167. package/src/clis/doubao/common.ts +619 -0
  168. package/src/clis/doubao/new.ts +22 -0
  169. package/src/clis/doubao/read.ts +20 -0
  170. package/src/clis/doubao/send.ts +25 -0
  171. package/src/clis/doubao/status.ts +27 -0
  172. package/src/clis/doubao-app/ask.ts +60 -0
  173. package/src/clis/doubao-app/common.ts +116 -0
  174. package/src/clis/doubao-app/dump.ts +28 -0
  175. package/src/clis/doubao-app/new.ts +21 -0
  176. package/src/clis/doubao-app/read.ts +21 -0
  177. package/src/clis/doubao-app/screenshot.ts +19 -0
  178. package/src/clis/doubao-app/send.ts +30 -0
  179. package/src/clis/doubao-app/status.ts +17 -0
  180. package/src/clis/hackernews/ask.yaml +38 -0
  181. package/src/clis/hackernews/best.yaml +38 -0
  182. package/src/clis/hackernews/jobs.yaml +36 -0
  183. package/src/clis/hackernews/new.yaml +38 -0
  184. package/src/clis/hackernews/search.yaml +44 -0
  185. package/src/clis/hackernews/show.yaml +38 -0
  186. package/src/clis/hackernews/top.yaml +3 -1
  187. package/src/clis/hackernews/user.yaml +25 -0
  188. package/src/clis/twitter/download.ts +13 -111
  189. package/src/clis/twitter/thread.ts +2 -1
  190. package/src/clis/v2ex/member.yaml +29 -0
  191. package/src/clis/v2ex/node.yaml +34 -0
  192. package/src/clis/v2ex/nodes.yaml +31 -0
  193. package/src/clis/v2ex/replies.yaml +32 -0
  194. package/src/clis/v2ex/user.yaml +34 -0
  195. package/src/clis/weibo/search.ts +78 -0
  196. package/src/clis/weixin/download.ts +199 -0
  197. package/src/clis/xiaohongshu/download.ts +12 -71
  198. package/src/clis/xiaohongshu/publish.ts +392 -0
  199. package/src/clis/xiaohongshu/search.test.ts +134 -0
  200. package/src/clis/xiaohongshu/search.ts +49 -15
  201. package/src/clis/yollomi/background.ts +48 -0
  202. package/src/clis/yollomi/edit.ts +58 -0
  203. package/src/clis/yollomi/face-swap.ts +45 -0
  204. package/src/clis/yollomi/generate.ts +95 -0
  205. package/src/clis/yollomi/models.ts +38 -0
  206. package/src/clis/yollomi/object-remover.ts +44 -0
  207. package/src/clis/yollomi/remove-bg.ts +40 -0
  208. package/src/clis/yollomi/restore.ts +40 -0
  209. package/src/clis/yollomi/try-on.ts +48 -0
  210. package/src/clis/yollomi/upload.ts +78 -0
  211. package/src/clis/yollomi/upscale.ts +49 -0
  212. package/src/clis/yollomi/utils.ts +202 -0
  213. package/src/clis/yollomi/video.ts +61 -0
  214. package/src/clis/zhihu/download.test.ts +7 -5
  215. package/src/clis/zhihu/download.ts +23 -158
  216. package/src/clis/zhihu/question.ts +2 -1
  217. package/src/commanderAdapter.ts +4 -7
  218. package/src/constants.ts +3 -0
  219. package/src/daemon.ts +7 -3
  220. package/src/discovery.ts +26 -26
  221. package/src/doctor.ts +2 -1
  222. package/src/download/article-download.ts +272 -0
  223. package/src/download/media-download.ts +178 -0
  224. package/src/errors.test.ts +79 -0
  225. package/src/errors.ts +92 -2
  226. package/src/execution.ts +14 -10
  227. package/src/explore.ts +4 -2
  228. package/src/external.test.ts +88 -0
  229. package/src/external.ts +56 -2
  230. package/src/generate.ts +2 -1
  231. package/src/main.ts +10 -0
  232. package/src/plugin.test.ts +7 -1
  233. package/src/plugin.ts +49 -25
  234. package/src/record.ts +617 -0
  235. package/src/registry.ts +9 -5
  236. package/src/runtime.ts +16 -4
  237. package/src/validate.ts +1 -3
  238. package/tests/e2e/browser-auth.test.ts +10 -1
  239. package/tests/e2e/browser-public.test.ts +13 -8
  240. package/tests/e2e/public-commands.test.ts +209 -21
  241. 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
- console.log(chalk.green(`✅ Plugin "${name}" installed successfully.`));
217
- console.log(chalk.dim(` Restart opencli to use the new commands.`));
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 { ytdlpDownload, checkYtdlp, sanitizeFilename, getTempDir, exportCookiesToNetscape, formatCookieHeader, } from '../../download/index.js';
14
- import { DownloadProgressTracker, formatBytes } from '../../download/progress.js';
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 authenticated downloads
53
- const cookies = await page.getCookies({ domain: 'bilibili.com' });
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 destPath = path.join(output, `${bvid}_${title}.mp4`);
77
- const tracker = new DownloadProgressTracker(1, true);
78
- const progressBar = tracker.onFileStart(`${bvid}.mp4`, 0);
79
- try {
80
- const result = await ytdlpDownload(`https://www.bilibili.com/video/${bvid}`, destPath, {
81
- cookiesFile,
82
- format,
83
- extraArgs: [
84
- '--merge-output-format', 'mp4',
85
- '--embed-thumbnail',
86
- ],
87
- onProgress: (percent) => {
88
- if (progressBar)
89
- progressBar.update(percent, 100);
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 Error('Not logged in to Bilibili');
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 Error('未获取到课程列表,请确认已登录学习通');
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>;