@jackwener/opencli 1.5.4 → 1.5.6
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/README.md +27 -2
- package/README.zh-CN.md +36 -4
- package/dist/browser/daemon-client.d.ts +5 -1
- package/dist/browser/page.d.ts +6 -0
- package/dist/browser/page.js +15 -0
- package/dist/cli-manifest.json +1284 -67
- package/dist/cli.js +14 -14
- package/dist/clis/antigravity/serve.js +2 -2
- package/dist/clis/band/bands.d.ts +1 -0
- package/dist/clis/band/bands.js +72 -0
- package/dist/clis/band/mentions.d.ts +1 -0
- package/dist/clis/band/mentions.js +127 -0
- package/dist/clis/band/post.d.ts +1 -0
- package/dist/clis/band/post.js +175 -0
- package/dist/clis/band/posts.d.ts +1 -0
- package/dist/clis/band/posts.js +94 -0
- package/dist/clis/doubao/detail.d.ts +1 -0
- package/dist/clis/doubao/detail.js +33 -0
- package/dist/clis/doubao/detail.test.d.ts +1 -0
- package/dist/clis/doubao/detail.test.js +42 -0
- package/dist/clis/doubao/history.d.ts +1 -0
- package/dist/clis/doubao/history.js +28 -0
- package/dist/clis/doubao/history.test.d.ts +1 -0
- package/dist/clis/doubao/history.test.js +37 -0
- package/dist/clis/doubao/meeting-summary.d.ts +1 -0
- package/dist/clis/doubao/meeting-summary.js +39 -0
- package/dist/clis/doubao/meeting-transcript.d.ts +1 -0
- package/dist/clis/doubao/meeting-transcript.js +36 -0
- package/dist/clis/doubao/utils.d.ts +27 -0
- package/dist/clis/doubao/utils.js +317 -0
- package/dist/clis/doubao/utils.test.d.ts +1 -0
- package/dist/clis/doubao/utils.test.js +24 -0
- package/dist/clis/douyin/_shared/public-api.d.ts +33 -0
- package/dist/clis/douyin/_shared/public-api.js +29 -0
- package/dist/clis/douyin/user-videos.d.ts +5 -0
- package/dist/clis/douyin/user-videos.js +74 -0
- package/dist/clis/douyin/user-videos.test.d.ts +1 -0
- package/dist/clis/douyin/user-videos.test.js +108 -0
- package/dist/clis/ones/common.d.ts +32 -0
- package/dist/clis/ones/common.js +144 -0
- package/dist/clis/ones/enrich-tasks.d.ts +5 -0
- package/dist/clis/ones/enrich-tasks.js +37 -0
- package/dist/clis/ones/login.d.ts +1 -0
- package/dist/clis/ones/login.js +80 -0
- package/dist/clis/ones/logout.d.ts +1 -0
- package/dist/clis/ones/logout.js +17 -0
- package/dist/clis/ones/me.d.ts +1 -0
- package/dist/clis/ones/me.js +30 -0
- package/dist/clis/ones/my-tasks.d.ts +1 -0
- package/dist/clis/ones/my-tasks.js +120 -0
- package/dist/clis/ones/resolve-labels.d.ts +10 -0
- package/dist/clis/ones/resolve-labels.js +64 -0
- package/dist/clis/ones/task-helpers.d.ts +29 -0
- package/dist/clis/ones/task-helpers.js +212 -0
- package/dist/clis/ones/task-helpers.test.d.ts +1 -0
- package/dist/clis/ones/task-helpers.test.js +12 -0
- package/dist/clis/ones/task.d.ts +1 -0
- package/dist/clis/ones/task.js +66 -0
- package/dist/clis/ones/tasks.d.ts +1 -0
- package/dist/clis/ones/tasks.js +79 -0
- package/dist/clis/ones/token-info.d.ts +1 -0
- package/dist/clis/ones/token-info.js +42 -0
- package/dist/clis/ones/worklog.d.ts +11 -0
- package/dist/clis/ones/worklog.js +267 -0
- package/dist/clis/ones/worklog.test.d.ts +1 -0
- package/dist/clis/ones/worklog.test.js +20 -0
- package/dist/clis/sinafinance/rolling-news.d.ts +4 -0
- package/dist/clis/sinafinance/rolling-news.js +40 -0
- package/dist/clis/sinafinance/stock.d.ts +8 -0
- package/dist/clis/sinafinance/stock.js +117 -0
- package/dist/clis/spotify/spotify.d.ts +1 -0
- package/dist/clis/spotify/spotify.js +316 -0
- package/dist/clis/spotify/utils.d.ts +21 -0
- package/dist/clis/spotify/utils.js +66 -0
- package/dist/clis/spotify/utils.test.d.ts +1 -0
- package/dist/clis/spotify/utils.test.js +67 -0
- package/dist/clis/tieba/commands.test.d.ts +4 -0
- package/dist/clis/tieba/commands.test.js +79 -0
- package/dist/clis/tieba/hot.d.ts +1 -0
- package/dist/clis/tieba/hot.js +48 -0
- package/dist/clis/tieba/posts.d.ts +1 -0
- package/dist/clis/tieba/posts.js +85 -0
- package/dist/clis/tieba/read.d.ts +1 -0
- package/dist/clis/tieba/read.js +140 -0
- package/dist/clis/tieba/search.d.ts +1 -0
- package/dist/clis/tieba/search.js +108 -0
- package/dist/clis/tieba/utils.d.ts +101 -0
- package/dist/clis/tieba/utils.js +240 -0
- package/dist/clis/tieba/utils.test.d.ts +1 -0
- package/dist/clis/tieba/utils.test.js +290 -0
- package/dist/clis/weread/book.js +100 -13
- package/dist/clis/weread/commands.test.js +221 -0
- package/dist/clis/weread/private-api-regression.test.d.ts +1 -0
- package/dist/{weread-private-api-regression.test.js → clis/weread/private-api-regression.test.js} +92 -30
- package/dist/clis/weread/search-regression.test.d.ts +1 -0
- package/dist/clis/weread/search-regression.test.js +407 -0
- package/dist/clis/weread/search.js +143 -7
- package/dist/clis/weread/shelf.js +13 -95
- package/dist/clis/weread/utils.d.ts +46 -0
- package/dist/clis/weread/utils.js +214 -7
- package/dist/clis/weread/utils.test.js +71 -1
- package/dist/clis/xiaohongshu/publish.d.ts +1 -1
- package/dist/clis/xiaohongshu/publish.js +78 -31
- package/dist/clis/xiaohongshu/publish.test.js +66 -1
- package/dist/clis/xiaohongshu/user-helpers.d.ts +1 -0
- package/dist/clis/xiaohongshu/user-helpers.js +2 -0
- package/dist/clis/xiaohongshu/user-helpers.test.js +18 -0
- package/dist/clis/xueqiu/comments.d.ts +118 -0
- package/dist/clis/xueqiu/comments.js +354 -0
- package/dist/clis/xueqiu/comments.test.d.ts +1 -0
- package/dist/clis/xueqiu/comments.test.js +696 -0
- package/dist/clis/youtube/transcript.js +2 -4
- package/dist/clis/youtube/utils.d.ts +9 -0
- package/dist/clis/youtube/utils.js +67 -3
- package/dist/clis/youtube/utils.test.d.ts +1 -0
- package/dist/clis/youtube/utils.test.js +37 -0
- package/dist/clis/youtube/video.js +16 -15
- package/dist/clis/zsxq/dynamics.d.ts +1 -0
- package/dist/clis/zsxq/dynamics.js +47 -0
- package/dist/clis/zsxq/groups.d.ts +1 -0
- package/dist/clis/zsxq/groups.js +32 -0
- package/dist/clis/zsxq/search.d.ts +1 -0
- package/dist/clis/zsxq/search.js +43 -0
- package/dist/clis/zsxq/search.test.d.ts +1 -0
- package/dist/clis/zsxq/search.test.js +24 -0
- package/dist/clis/zsxq/topic.d.ts +1 -0
- package/dist/clis/zsxq/topic.js +47 -0
- package/dist/clis/zsxq/topic.test.d.ts +1 -0
- package/dist/clis/zsxq/topic.test.js +29 -0
- package/dist/clis/zsxq/topics.d.ts +1 -0
- package/dist/clis/zsxq/topics.js +25 -0
- package/dist/clis/zsxq/topics.test.d.ts +1 -0
- package/dist/clis/zsxq/topics.test.js +24 -0
- package/dist/clis/zsxq/utils.d.ts +97 -0
- package/dist/clis/zsxq/utils.js +230 -0
- package/dist/commanderAdapter.js +27 -4
- package/dist/commanderAdapter.test.js +39 -0
- package/dist/daemon.js +5 -4
- package/dist/errors.d.ts +29 -1
- package/dist/errors.js +49 -11
- package/dist/external-clis.yaml +17 -0
- package/dist/external.js +3 -3
- package/dist/main.js +2 -1
- package/dist/tui.js +2 -1
- package/dist/types.d.ts +5 -0
- package/docs/.vitepress/config.mts +3 -0
- package/docs/adapters/browser/band.md +63 -0
- package/docs/adapters/browser/ones.md +59 -0
- package/docs/adapters/browser/sinafinance.md +56 -6
- package/docs/adapters/browser/spotify.md +62 -0
- package/docs/adapters/browser/tieba.md +45 -0
- package/docs/adapters/browser/xueqiu.md +5 -0
- package/docs/adapters/browser/zsxq.md +49 -0
- package/docs/adapters/index.md +5 -2
- package/docs/adapters-doc/ones.md +32 -0
- package/extension/dist/background.js +1 -2
- package/extension/manifest.json +1 -1
- package/extension/package.json +1 -1
- package/extension/src/background.ts +17 -1
- package/extension/src/cdp.ts +42 -0
- package/extension/src/protocol.ts +5 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +16 -0
- package/src/browser/daemon-client.ts +5 -1
- package/src/browser/page.ts +16 -0
- package/src/cli.ts +14 -14
- package/src/clis/antigravity/serve.ts +2 -2
- package/src/clis/band/bands.ts +76 -0
- package/src/clis/band/mentions.ts +134 -0
- package/src/clis/band/post.ts +187 -0
- package/src/clis/band/posts.ts +106 -0
- package/src/clis/doubao/detail.test.ts +53 -0
- package/src/clis/doubao/detail.ts +41 -0
- package/src/clis/doubao/history.test.ts +45 -0
- package/src/clis/doubao/history.ts +32 -0
- package/src/clis/doubao/meeting-summary.ts +53 -0
- package/src/clis/doubao/meeting-transcript.ts +48 -0
- package/src/clis/doubao/utils.test.ts +45 -0
- package/src/clis/doubao/utils.ts +371 -0
- package/src/clis/douyin/_shared/public-api.ts +84 -0
- package/src/clis/douyin/user-videos.test.ts +122 -0
- package/src/clis/douyin/user-videos.ts +101 -0
- package/src/clis/ones/common.ts +187 -0
- package/src/clis/ones/enrich-tasks.ts +47 -0
- package/src/clis/ones/login.ts +103 -0
- package/src/clis/ones/logout.ts +19 -0
- package/src/clis/ones/me.ts +34 -0
- package/src/clis/ones/my-tasks.ts +148 -0
- package/src/clis/ones/resolve-labels.ts +80 -0
- package/src/clis/ones/task-helpers.test.ts +14 -0
- package/src/clis/ones/task-helpers.ts +214 -0
- package/src/clis/ones/task.ts +79 -0
- package/src/clis/ones/tasks.ts +92 -0
- package/src/clis/ones/token-info.ts +46 -0
- package/src/clis/ones/worklog.test.ts +24 -0
- package/src/clis/ones/worklog.ts +306 -0
- package/src/clis/sinafinance/rolling-news.ts +42 -0
- package/src/clis/sinafinance/stock.ts +127 -0
- package/src/clis/spotify/spotify.ts +328 -0
- package/src/clis/spotify/utils.test.ts +87 -0
- package/src/clis/spotify/utils.ts +92 -0
- package/src/clis/tieba/commands.test.ts +86 -0
- package/src/clis/tieba/hot.ts +52 -0
- package/src/clis/tieba/posts.ts +108 -0
- package/src/clis/tieba/read.ts +158 -0
- package/src/clis/tieba/search.ts +119 -0
- package/src/clis/tieba/utils.test.ts +322 -0
- package/src/clis/tieba/utils.ts +348 -0
- package/src/clis/weread/book.ts +116 -13
- package/src/clis/weread/commands.test.ts +249 -0
- package/src/{weread-private-api-regression.test.ts → clis/weread/private-api-regression.test.ts} +108 -30
- package/src/clis/weread/search-regression.test.ts +440 -0
- package/src/clis/weread/search.ts +189 -9
- package/src/clis/weread/shelf.ts +20 -122
- package/src/clis/weread/utils.test.ts +81 -1
- package/src/clis/weread/utils.ts +264 -7
- package/src/clis/xiaohongshu/publish.test.ts +79 -1
- package/src/clis/xiaohongshu/publish.ts +84 -30
- package/src/clis/xiaohongshu/user-helpers.test.ts +23 -0
- package/src/clis/xiaohongshu/user-helpers.ts +4 -0
- package/src/clis/xueqiu/comments.test.ts +823 -0
- package/src/clis/xueqiu/comments.ts +461 -0
- package/src/clis/youtube/transcript.ts +2 -4
- package/src/clis/youtube/utils.test.ts +43 -0
- package/src/clis/youtube/utils.ts +69 -0
- package/src/clis/youtube/video.ts +16 -15
- package/src/clis/zsxq/dynamics.ts +60 -0
- package/src/clis/zsxq/groups.ts +41 -0
- package/src/clis/zsxq/search.test.ts +29 -0
- package/src/clis/zsxq/search.ts +54 -0
- package/src/clis/zsxq/topic.test.ts +34 -0
- package/src/clis/zsxq/topic.ts +68 -0
- package/src/clis/zsxq/topics.test.ts +29 -0
- package/src/clis/zsxq/topics.ts +36 -0
- package/src/clis/zsxq/utils.ts +351 -0
- package/src/commanderAdapter.test.ts +47 -0
- package/src/commanderAdapter.ts +26 -3
- package/src/daemon.ts +5 -4
- package/src/errors.ts +71 -10
- package/src/external-clis.yaml +17 -0
- package/src/external.ts +3 -3
- package/src/main.ts +2 -1
- package/src/tui.ts +2 -1
- package/src/types.ts +5 -0
- package/tests/e2e/band-auth.test.ts +20 -0
- package/tests/e2e/browser-auth-helpers.ts +18 -0
- package/tests/e2e/browser-auth.test.ts +35 -47
- package/tests/e2e/browser-public.test.ts +288 -0
- package/tests/e2e/management.test.ts +1 -1
- package/tests/e2e/plugin-management.test.ts +1 -1
- package/vitest.config.ts +1 -0
- package/SKILL.md +0 -879
- package/dist/weread-private-api-regression.test.d.ts +0 -1
- package/dist/weread-search-regression.test.d.ts +0 -1
- package/dist/weread-search-regression.test.js +0 -39
- package/src/weread-search-regression.test.ts +0 -44
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
const { mockGetConversationDetail } = vi.hoisted(() => ({
|
|
4
|
+
mockGetConversationDetail: vi.fn(),
|
|
5
|
+
}));
|
|
6
|
+
|
|
7
|
+
vi.mock('./utils.js', async () => {
|
|
8
|
+
const actual = await vi.importActual<typeof import('./utils.js')>('./utils.js');
|
|
9
|
+
return {
|
|
10
|
+
...actual,
|
|
11
|
+
getConversationDetail: mockGetConversationDetail,
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
import { getRegistry } from '../../registry.js';
|
|
16
|
+
import './detail.js';
|
|
17
|
+
|
|
18
|
+
describe('doubao detail', () => {
|
|
19
|
+
const detail = getRegistry().get('doubao/detail');
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
mockGetConversationDetail.mockReset();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('returns meeting metadata even when the conversation has no chat messages', async () => {
|
|
26
|
+
mockGetConversationDetail.mockResolvedValue({
|
|
27
|
+
messages: [],
|
|
28
|
+
meeting: {
|
|
29
|
+
title: 'Weekly Sync',
|
|
30
|
+
time: '2026-03-28 10:00',
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const result = await detail!.func!({} as any, { id: '1234567890' });
|
|
35
|
+
|
|
36
|
+
expect(result).toEqual([
|
|
37
|
+
{ Role: 'Meeting', Text: 'Weekly Sync (2026-03-28 10:00)' },
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('still returns an error row for a truly empty conversation', async () => {
|
|
42
|
+
mockGetConversationDetail.mockResolvedValue({
|
|
43
|
+
messages: [],
|
|
44
|
+
meeting: null,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const result = await detail!.func!({} as any, { id: '1234567890' });
|
|
48
|
+
|
|
49
|
+
expect(result).toEqual([
|
|
50
|
+
{ Role: 'System', Text: 'No messages found. Verify the conversation ID.' },
|
|
51
|
+
]);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import type { IPage } from '../../types.js';
|
|
3
|
+
import { DOUBAO_DOMAIN, getConversationDetail, parseDoubaoConversationId } from './utils.js';
|
|
4
|
+
|
|
5
|
+
export const detailCommand = cli({
|
|
6
|
+
site: 'doubao',
|
|
7
|
+
name: 'detail',
|
|
8
|
+
description: 'Read a specific Doubao conversation by ID',
|
|
9
|
+
domain: DOUBAO_DOMAIN,
|
|
10
|
+
strategy: Strategy.COOKIE,
|
|
11
|
+
browser: true,
|
|
12
|
+
navigateBefore: false,
|
|
13
|
+
args: [
|
|
14
|
+
{ name: 'id', required: true, positional: true, help: 'Conversation ID (numeric or full URL)' },
|
|
15
|
+
],
|
|
16
|
+
columns: ['Role', 'Text'],
|
|
17
|
+
func: async (page: IPage, kwargs: Record<string, unknown>) => {
|
|
18
|
+
const conversationId = parseDoubaoConversationId(kwargs.id as string);
|
|
19
|
+
|
|
20
|
+
const { messages, meeting } = await getConversationDetail(page, conversationId);
|
|
21
|
+
|
|
22
|
+
if (messages.length === 0 && !meeting) {
|
|
23
|
+
return [{ Role: 'System', Text: 'No messages found. Verify the conversation ID.' }];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const result: Array<{ Role: string; Text: string }> = [];
|
|
27
|
+
|
|
28
|
+
if (meeting) {
|
|
29
|
+
result.push({
|
|
30
|
+
Role: 'Meeting',
|
|
31
|
+
Text: `${meeting.title}${meeting.time ? ` (${meeting.time})` : ''}`,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const m of messages) {
|
|
36
|
+
result.push({ Role: m.Role, Text: m.Text });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
},
|
|
41
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
const { mockGetDoubaoConversationList } = vi.hoisted(() => ({
|
|
4
|
+
mockGetDoubaoConversationList: vi.fn(),
|
|
5
|
+
}));
|
|
6
|
+
|
|
7
|
+
vi.mock('./utils.js', async () => {
|
|
8
|
+
const actual = await vi.importActual<typeof import('./utils.js')>('./utils.js');
|
|
9
|
+
return {
|
|
10
|
+
...actual,
|
|
11
|
+
getDoubaoConversationList: mockGetDoubaoConversationList,
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
import { getRegistry } from '../../registry.js';
|
|
16
|
+
import './history.js';
|
|
17
|
+
|
|
18
|
+
describe('doubao history', () => {
|
|
19
|
+
const history = getRegistry().get('doubao/history');
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
mockGetDoubaoConversationList.mockReset();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('includes the conversation id in the tabular output', async () => {
|
|
26
|
+
mockGetDoubaoConversationList.mockResolvedValue([
|
|
27
|
+
{
|
|
28
|
+
Id: '1234567890123',
|
|
29
|
+
Title: 'Weekly Sync',
|
|
30
|
+
Url: 'https://www.doubao.com/chat/1234567890123',
|
|
31
|
+
},
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
const result = await history!.func!({} as any, {});
|
|
35
|
+
|
|
36
|
+
expect(result).toEqual([
|
|
37
|
+
{
|
|
38
|
+
Index: 1,
|
|
39
|
+
Id: '1234567890123',
|
|
40
|
+
Title: 'Weekly Sync',
|
|
41
|
+
Url: 'https://www.doubao.com/chat/1234567890123',
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import type { IPage } from '../../types.js';
|
|
3
|
+
import { DOUBAO_DOMAIN, getDoubaoConversationList } from './utils.js';
|
|
4
|
+
|
|
5
|
+
export const historyCommand = cli({
|
|
6
|
+
site: 'doubao',
|
|
7
|
+
name: 'history',
|
|
8
|
+
description: 'List conversation history from Doubao sidebar',
|
|
9
|
+
domain: DOUBAO_DOMAIN,
|
|
10
|
+
strategy: Strategy.COOKIE,
|
|
11
|
+
browser: true,
|
|
12
|
+
navigateBefore: false,
|
|
13
|
+
args: [
|
|
14
|
+
{ name: 'limit', required: false, help: 'Max number of conversations to show', default: '50' },
|
|
15
|
+
],
|
|
16
|
+
columns: ['Index', 'Id', 'Title', 'Url'],
|
|
17
|
+
func: async (page: IPage, kwargs: Record<string, unknown>) => {
|
|
18
|
+
const limit = parseInt(kwargs.limit as string, 10) || 50;
|
|
19
|
+
const conversations = await getDoubaoConversationList(page);
|
|
20
|
+
|
|
21
|
+
if (conversations.length === 0) {
|
|
22
|
+
return [{ Index: 0, Id: '', Title: 'No conversation history found. Make sure you are logged in.', Url: '' }];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return conversations.slice(0, limit).map((conv, i) => ({
|
|
26
|
+
Index: i + 1,
|
|
27
|
+
Id: conv.Id,
|
|
28
|
+
Title: conv.Title,
|
|
29
|
+
Url: conv.Url,
|
|
30
|
+
}));
|
|
31
|
+
},
|
|
32
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import type { IPage } from '../../types.js';
|
|
3
|
+
import {
|
|
4
|
+
DOUBAO_DOMAIN,
|
|
5
|
+
openMeetingPanel,
|
|
6
|
+
getMeetingSummary,
|
|
7
|
+
getMeetingChapters,
|
|
8
|
+
parseDoubaoConversationId,
|
|
9
|
+
} from './utils.js';
|
|
10
|
+
|
|
11
|
+
export const meetingSummaryCommand = cli({
|
|
12
|
+
site: 'doubao',
|
|
13
|
+
name: 'meeting-summary',
|
|
14
|
+
description: 'Get meeting summary and chapters from a Doubao conversation',
|
|
15
|
+
domain: DOUBAO_DOMAIN,
|
|
16
|
+
strategy: Strategy.COOKIE,
|
|
17
|
+
browser: true,
|
|
18
|
+
navigateBefore: false,
|
|
19
|
+
args: [
|
|
20
|
+
{ name: 'id', required: true, positional: true, help: 'Conversation ID (numeric or full URL)' },
|
|
21
|
+
{ name: 'chapters', required: false, help: 'Also include AI chapters', default: 'false' },
|
|
22
|
+
],
|
|
23
|
+
columns: ['Section', 'Content'],
|
|
24
|
+
func: async (page: IPage, kwargs: Record<string, unknown>) => {
|
|
25
|
+
const conversationId = parseDoubaoConversationId(kwargs.id as string);
|
|
26
|
+
const includeChapters = kwargs.chapters === 'true' || kwargs.chapters === true;
|
|
27
|
+
|
|
28
|
+
const opened = await openMeetingPanel(page, conversationId);
|
|
29
|
+
if (!opened) {
|
|
30
|
+
return [{ Section: 'Error', Content: 'No meeting card found in this conversation.' }];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const summary = await getMeetingSummary(page);
|
|
34
|
+
const result: Array<{ Section: string; Content: string }> = [];
|
|
35
|
+
|
|
36
|
+
if (summary) {
|
|
37
|
+
result.push({ Section: 'Summary', Content: summary });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (includeChapters) {
|
|
41
|
+
const chapters = await getMeetingChapters(page);
|
|
42
|
+
if (chapters) {
|
|
43
|
+
result.push({ Section: 'Chapters', Content: chapters });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (result.length === 0) {
|
|
48
|
+
return [{ Section: 'Info', Content: 'Meeting panel opened but no content found yet. Try again.' }];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return result;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import type { IPage } from '../../types.js';
|
|
3
|
+
import {
|
|
4
|
+
DOUBAO_DOMAIN,
|
|
5
|
+
openMeetingPanel,
|
|
6
|
+
getMeetingTranscript,
|
|
7
|
+
parseDoubaoConversationId,
|
|
8
|
+
triggerTranscriptDownload,
|
|
9
|
+
} from './utils.js';
|
|
10
|
+
|
|
11
|
+
export const meetingTranscriptCommand = cli({
|
|
12
|
+
site: 'doubao',
|
|
13
|
+
name: 'meeting-transcript',
|
|
14
|
+
description: 'Get or download the meeting transcript from a Doubao conversation',
|
|
15
|
+
domain: DOUBAO_DOMAIN,
|
|
16
|
+
strategy: Strategy.COOKIE,
|
|
17
|
+
browser: true,
|
|
18
|
+
navigateBefore: false,
|
|
19
|
+
args: [
|
|
20
|
+
{ name: 'id', required: true, positional: true, help: 'Conversation ID (numeric or full URL)' },
|
|
21
|
+
{ name: 'download', required: false, help: 'Trigger browser file download instead of reading text', default: 'false' },
|
|
22
|
+
],
|
|
23
|
+
columns: ['Section', 'Content'],
|
|
24
|
+
func: async (page: IPage, kwargs: Record<string, unknown>) => {
|
|
25
|
+
const conversationId = parseDoubaoConversationId(kwargs.id as string);
|
|
26
|
+
const shouldDownload = kwargs.download === 'true' || kwargs.download === true;
|
|
27
|
+
|
|
28
|
+
const opened = await openMeetingPanel(page, conversationId);
|
|
29
|
+
if (!opened) {
|
|
30
|
+
return [{ Section: 'Error', Content: 'No meeting card found in this conversation.' }];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (shouldDownload) {
|
|
34
|
+
const ok = await triggerTranscriptDownload(page);
|
|
35
|
+
if (!ok) {
|
|
36
|
+
return [{ Section: 'Error', Content: 'Failed to trigger transcript download.' }];
|
|
37
|
+
}
|
|
38
|
+
return [{ Section: 'Download', Content: 'Transcript download triggered in browser. Check your Downloads folder.' }];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const transcript = await getMeetingTranscript(page);
|
|
42
|
+
if (!transcript) {
|
|
43
|
+
return [{ Section: 'Info', Content: 'No transcript content found. The meeting may not have a text record.' }];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return [{ Section: 'Transcript', Content: transcript }];
|
|
47
|
+
},
|
|
48
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mergeTranscriptSnapshots, parseDoubaoConversationId } from './utils.js';
|
|
3
|
+
|
|
4
|
+
describe('parseDoubaoConversationId', () => {
|
|
5
|
+
it('extracts the numeric id from a full conversation URL', () => {
|
|
6
|
+
expect(parseDoubaoConversationId('https://www.doubao.com/chat/1234567890123')).toBe('1234567890123');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('keeps a raw id unchanged', () => {
|
|
10
|
+
expect(parseDoubaoConversationId('1234567890123')).toBe('1234567890123');
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('mergeTranscriptSnapshots', () => {
|
|
15
|
+
it('extends the transcript when the next snapshot overlaps with the tail', () => {
|
|
16
|
+
const merged = mergeTranscriptSnapshots(
|
|
17
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi',
|
|
18
|
+
'Bob 00:05\nHi\nAlice 00:10\nNext topic',
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
expect(merged).toBe(
|
|
22
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi\nAlice 00:10\nNext topic',
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('does not duplicate a snapshot that is already contained in the transcript', () => {
|
|
27
|
+
const merged = mergeTranscriptSnapshots(
|
|
28
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi',
|
|
29
|
+
'Bob 00:05\nHi',
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(merged).toBe('Alice 00:00\nHello team\nBob 00:05\nHi');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('keeps both windows when a virtualized panel returns adjacent chunks without full history', () => {
|
|
36
|
+
const merged = mergeTranscriptSnapshots(
|
|
37
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi',
|
|
38
|
+
'Alice 00:10\nNext topic\nBob 00:15\nAction items',
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
expect(merged).toBe(
|
|
42
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi\nAlice 00:10\nNext topic\nBob 00:15\nAction items',
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
});
|