@jackwener/opencli 1.5.6 → 1.5.7
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 +26 -0
- package/README.md +4 -2
- package/README.zh-CN.md +4 -1
- package/SKILL.md +879 -0
- package/dist/browser/cdp.d.ts +1 -0
- package/dist/browser/cdp.js +30 -27
- package/dist/browser/daemon-client.d.ts +7 -1
- package/dist/browser/daemon-client.js +3 -0
- package/dist/browser/dom-helpers.js +1 -0
- package/dist/browser/dom-helpers.test.js +14 -1
- package/dist/browser/mcp.js +18 -13
- package/dist/browser/page.js +22 -2
- package/dist/browser/page.test.d.ts +1 -0
- package/dist/browser/page.test.js +44 -0
- package/dist/browser/stealth.js +198 -0
- package/dist/browser/stealth.test.d.ts +1 -0
- package/dist/browser/stealth.test.js +134 -0
- package/dist/browser.test.js +1 -1
- package/dist/build-manifest.d.ts +1 -0
- package/dist/build-manifest.js +5 -1
- package/dist/build-manifest.test.js +2 -0
- package/dist/cli-manifest.json +544 -137
- package/dist/cli.js +20 -3
- package/dist/clis/antigravity/serve.d.ts +1 -1
- package/dist/clis/antigravity/serve.js +5 -8
- package/dist/clis/bilibili/subtitle.js +4 -0
- package/dist/clis/bilibili/subtitle.test.d.ts +1 -0
- package/dist/clis/bilibili/subtitle.test.js +48 -0
- package/dist/clis/chatwise/ask.js +0 -2
- package/dist/clis/chatwise/export.js +0 -2
- package/dist/clis/chatwise/history.js +0 -2
- package/dist/clis/chatwise/model.js +0 -2
- package/dist/clis/chatwise/new.js +1 -2
- package/dist/clis/chatwise/read.js +0 -2
- package/dist/clis/chatwise/screenshot.js +1 -2
- package/dist/clis/chatwise/send.js +0 -2
- package/dist/clis/chatwise/status.js +1 -2
- package/dist/clis/ctrip/search.d.ts +13 -0
- package/dist/clis/ctrip/search.js +73 -48
- package/dist/clis/ctrip/search.test.d.ts +1 -0
- package/dist/clis/ctrip/search.test.js +64 -0
- package/dist/clis/douyin/_shared/sts2.js +8 -2
- package/dist/clis/douyin/_shared/sts2.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/sts2.test.js +27 -0
- package/dist/clis/douyin/activities.js +4 -2
- package/dist/clis/douyin/activities.test.js +34 -1
- package/dist/clis/douyin/collections.js +1 -1
- package/dist/clis/douyin/collections.test.js +24 -2
- package/dist/clis/douyin/draft.d.ts +8 -11
- package/dist/clis/douyin/draft.js +302 -185
- package/dist/clis/douyin/draft.test.d.ts +1 -1
- package/dist/clis/douyin/draft.test.js +357 -2
- package/dist/clis/douyin/hashtag.js +9 -2
- package/dist/clis/douyin/hashtag.test.js +35 -2
- package/dist/clis/douyin/profile.js +1 -1
- package/dist/clis/douyin/profile.test.js +36 -1
- package/dist/clis/douyin/videos.js +22 -5
- package/dist/clis/douyin/videos.test.js +45 -2
- package/dist/clis/facebook/search.test.d.ts +5 -0
- package/dist/clis/facebook/search.test.js +60 -0
- package/dist/clis/facebook/search.yaml +4 -3
- package/dist/clis/instagram/download.d.ts +16 -0
- package/dist/clis/instagram/download.js +225 -0
- package/dist/clis/instagram/download.test.d.ts +1 -0
- package/dist/clis/instagram/download.test.js +118 -0
- package/dist/clis/notebooklm/bind-current.d.ts +1 -0
- package/dist/clis/notebooklm/bind-current.js +29 -0
- package/dist/clis/notebooklm/bind-current.test.d.ts +1 -0
- package/dist/clis/notebooklm/bind-current.test.js +35 -0
- package/dist/clis/notebooklm/binding.test.d.ts +1 -0
- package/dist/clis/notebooklm/binding.test.js +44 -0
- package/dist/clis/notebooklm/compat.test.d.ts +3 -0
- package/dist/clis/notebooklm/compat.test.js +16 -0
- package/dist/clis/notebooklm/current.d.ts +1 -0
- package/dist/clis/notebooklm/current.js +28 -0
- package/dist/clis/notebooklm/get.d.ts +1 -0
- package/dist/clis/notebooklm/get.js +37 -0
- package/dist/clis/notebooklm/history.d.ts +1 -0
- package/dist/clis/notebooklm/history.js +25 -0
- package/dist/clis/notebooklm/history.test.d.ts +1 -0
- package/dist/clis/notebooklm/history.test.js +58 -0
- package/dist/clis/notebooklm/list.d.ts +1 -0
- package/dist/clis/notebooklm/list.js +35 -0
- package/dist/clis/notebooklm/note-list.d.ts +1 -0
- package/dist/clis/notebooklm/note-list.js +28 -0
- package/dist/clis/notebooklm/note-list.test.d.ts +1 -0
- package/dist/clis/notebooklm/note-list.test.js +56 -0
- package/dist/clis/notebooklm/notes-get.d.ts +1 -0
- package/dist/clis/notebooklm/notes-get.js +47 -0
- package/dist/clis/notebooklm/notes-get.test.d.ts +1 -0
- package/dist/clis/notebooklm/notes-get.test.js +72 -0
- package/dist/clis/notebooklm/rpc.d.ts +36 -0
- package/dist/clis/notebooklm/rpc.js +189 -0
- package/dist/clis/notebooklm/rpc.test.d.ts +1 -0
- package/dist/clis/notebooklm/rpc.test.js +105 -0
- package/dist/clis/notebooklm/shared.d.ts +87 -0
- package/dist/clis/notebooklm/shared.js +3 -0
- package/dist/clis/notebooklm/source-fulltext.d.ts +1 -0
- package/dist/clis/notebooklm/source-fulltext.js +44 -0
- package/dist/clis/notebooklm/source-fulltext.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-fulltext.test.js +106 -0
- package/dist/clis/notebooklm/source-get.d.ts +1 -0
- package/dist/clis/notebooklm/source-get.js +40 -0
- package/dist/clis/notebooklm/source-get.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-get.test.js +84 -0
- package/dist/clis/notebooklm/source-guide.d.ts +1 -0
- package/dist/clis/notebooklm/source-guide.js +44 -0
- package/dist/clis/notebooklm/source-guide.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-guide.test.js +104 -0
- package/dist/clis/notebooklm/source-list.d.ts +1 -0
- package/dist/clis/notebooklm/source-list.js +30 -0
- package/dist/clis/notebooklm/status.d.ts +1 -0
- package/dist/clis/notebooklm/status.js +31 -0
- package/dist/clis/notebooklm/summary.d.ts +1 -0
- package/dist/clis/notebooklm/summary.js +30 -0
- package/dist/clis/notebooklm/summary.test.d.ts +1 -0
- package/dist/clis/notebooklm/summary.test.js +78 -0
- package/dist/clis/notebooklm/utils.d.ts +37 -0
- package/dist/clis/notebooklm/utils.js +739 -0
- package/dist/clis/notebooklm/utils.test.d.ts +1 -0
- package/dist/clis/notebooklm/utils.test.js +390 -0
- package/dist/clis/substack/utils.d.ts +4 -0
- package/dist/clis/substack/utils.js +8 -2
- package/dist/clis/substack/utils.test.d.ts +1 -0
- package/dist/clis/substack/utils.test.js +46 -0
- package/dist/clis/v2ex/hot.yaml +4 -1
- package/dist/clis/v2ex/latest.yaml +4 -1
- package/dist/clis/v2ex/topic.yaml +6 -1
- package/dist/clis/weixin/download.d.ts +9 -0
- package/dist/clis/weixin/download.js +76 -6
- package/dist/clis/weread/book.js +108 -2
- package/dist/clis/weread/commands.test.js +262 -152
- package/dist/clis/weread/utils.d.ts +10 -0
- package/dist/clis/weread/utils.js +27 -7
- package/dist/clis/xiaohongshu/comments.d.ts +3 -0
- package/dist/clis/xiaohongshu/comments.js +76 -17
- package/dist/clis/xiaohongshu/comments.test.js +70 -9
- package/dist/clis/xiaohongshu/download.d.ts +4 -1
- package/dist/clis/xiaohongshu/download.js +83 -22
- package/dist/clis/xiaohongshu/download.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/download.test.js +75 -0
- package/dist/clis/xiaohongshu/note-helpers.d.ts +12 -0
- package/dist/clis/xiaohongshu/note-helpers.js +23 -0
- package/dist/clis/xiaohongshu/note.d.ts +7 -0
- package/dist/clis/xiaohongshu/note.js +76 -0
- package/dist/clis/xiaohongshu/note.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/note.test.js +136 -0
- package/dist/clis/xiaohongshu/search.js +9 -0
- package/dist/clis/xiaohongshu/search.test.js +10 -4
- package/dist/clis/youtube/search.js +57 -17
- package/dist/clis/zhihu/question.js +19 -17
- package/dist/clis/zhihu/question.test.d.ts +1 -0
- package/dist/clis/zhihu/question.test.js +54 -0
- package/dist/commanderAdapter.js +9 -0
- package/dist/commanderAdapter.test.js +25 -0
- package/dist/commands/daemon.d.ts +9 -0
- package/dist/commands/daemon.js +124 -0
- package/dist/commands/daemon.test.d.ts +1 -0
- package/dist/commands/daemon.test.js +185 -0
- package/dist/completion.js +3 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/daemon.d.ts +1 -1
- package/dist/daemon.js +25 -14
- package/dist/daemon.test.d.ts +1 -0
- package/dist/daemon.test.js +65 -0
- package/dist/discovery.d.ts +9 -0
- package/dist/discovery.js +47 -2
- package/dist/electron-apps.d.ts +29 -0
- package/dist/electron-apps.js +65 -0
- package/dist/electron-apps.test.d.ts +1 -0
- package/dist/electron-apps.test.js +43 -0
- package/dist/engine.test.js +41 -9
- package/dist/execution.js +20 -16
- package/dist/idle-manager.d.ts +19 -0
- package/dist/idle-manager.js +54 -0
- package/dist/launcher.d.ts +36 -0
- package/dist/launcher.js +152 -0
- package/dist/launcher.test.d.ts +1 -0
- package/dist/launcher.test.js +57 -0
- package/dist/main.js +3 -3
- package/dist/registry.d.ts +1 -0
- package/dist/registry.js +31 -3
- package/dist/registry.test.js +13 -0
- package/dist/runtime.d.ts +5 -3
- package/dist/runtime.js +12 -5
- package/dist/serialization.d.ts +1 -0
- package/dist/serialization.js +3 -0
- package/dist/serialization.test.js +17 -1
- package/dist/tui.d.ts +7 -0
- package/dist/tui.js +52 -0
- package/dist/tui.test.d.ts +1 -0
- package/dist/tui.test.js +19 -0
- package/dist/weixin-download.test.js +14 -0
- package/docs/.vitepress/config.mts +1 -0
- package/docs/adapters/browser/notebooklm.md +69 -0
- package/docs/adapters/browser/xiaohongshu.md +19 -10
- package/docs/adapters/index.md +67 -66
- package/docs/guide/browser-bridge.md +12 -0
- package/docs/guide/troubleshooting.md +9 -4
- package/docs/superpowers/plans/2026-03-31-daemon-lifecycle-redesign.md +857 -0
- package/docs/superpowers/specs/2026-03-31-daemon-lifecycle-redesign.md +208 -0
- package/docs/zh/guide/browser-bridge.md +12 -0
- package/extension/dist/background.js +794 -513
- package/extension/src/background.test.ts +202 -2
- package/extension/src/background.ts +174 -10
- package/extension/src/cdp.ts +12 -0
- package/extension/src/protocol.ts +7 -5
- package/package.json +1 -1
- package/src/browser/cdp.ts +24 -17
- package/src/browser/daemon-client.ts +7 -1
- package/src/browser/dom-helpers.test.ts +15 -1
- package/src/browser/dom-helpers.ts +1 -0
- package/src/browser/mcp.ts +18 -13
- package/src/browser/page.test.ts +58 -0
- package/src/browser/page.ts +18 -2
- package/src/browser/stealth.test.ts +153 -0
- package/src/browser/stealth.ts +198 -0
- package/src/browser.test.ts +1 -1
- package/src/build-manifest.test.ts +2 -0
- package/src/build-manifest.ts +6 -1
- package/src/cli.ts +21 -3
- package/src/clis/antigravity/SKILL.md +3 -12
- package/src/clis/antigravity/serve.ts +5 -10
- package/src/clis/bilibili/subtitle.test.ts +60 -0
- package/src/clis/bilibili/subtitle.ts +4 -0
- package/src/clis/chatwise/ask.ts +0 -2
- package/src/clis/chatwise/export.ts +0 -2
- package/src/clis/chatwise/history.ts +0 -2
- package/src/clis/chatwise/model.ts +0 -2
- package/src/clis/chatwise/new.ts +1 -2
- package/src/clis/chatwise/read.ts +0 -2
- package/src/clis/chatwise/screenshot.ts +1 -2
- package/src/clis/chatwise/send.ts +0 -2
- package/src/clis/chatwise/status.ts +1 -2
- package/src/clis/ctrip/search.test.ts +73 -0
- package/src/clis/ctrip/search.ts +97 -47
- package/src/clis/douyin/_shared/sts2.test.ts +31 -0
- package/src/clis/douyin/_shared/sts2.ts +11 -3
- package/src/clis/douyin/activities.test.ts +41 -1
- package/src/clis/douyin/activities.ts +12 -3
- package/src/clis/douyin/collections.test.ts +35 -2
- package/src/clis/douyin/collections.ts +1 -1
- package/src/clis/douyin/draft.test.ts +444 -2
- package/src/clis/douyin/draft.ts +382 -218
- package/src/clis/douyin/hashtag.test.ts +42 -2
- package/src/clis/douyin/hashtag.ts +11 -3
- package/src/clis/douyin/profile.test.ts +43 -1
- package/src/clis/douyin/profile.ts +9 -2
- package/src/clis/douyin/videos.test.ts +52 -2
- package/src/clis/douyin/videos.ts +49 -15
- package/src/clis/facebook/search.test.ts +70 -0
- package/src/clis/facebook/search.yaml +4 -3
- package/src/clis/instagram/download.test.ts +159 -0
- package/src/clis/instagram/download.ts +286 -0
- package/src/clis/notebooklm/bind-current.test.ts +43 -0
- package/src/clis/notebooklm/bind-current.ts +36 -0
- package/src/clis/notebooklm/binding.test.ts +53 -0
- package/src/clis/notebooklm/compat.test.ts +19 -0
- package/src/clis/notebooklm/current.ts +38 -0
- package/src/clis/notebooklm/get.ts +53 -0
- package/src/clis/notebooklm/history.test.ts +70 -0
- package/src/clis/notebooklm/history.ts +36 -0
- package/src/clis/notebooklm/list.ts +40 -0
- package/src/clis/notebooklm/note-list.test.ts +64 -0
- package/src/clis/notebooklm/note-list.ts +42 -0
- package/src/clis/notebooklm/notes-get.test.ts +88 -0
- package/src/clis/notebooklm/notes-get.ts +67 -0
- package/src/clis/notebooklm/rpc.test.ts +126 -0
- package/src/clis/notebooklm/rpc.ts +286 -0
- package/src/clis/notebooklm/shared.ts +98 -0
- package/src/clis/notebooklm/source-fulltext.test.ts +123 -0
- package/src/clis/notebooklm/source-fulltext.ts +69 -0
- package/src/clis/notebooklm/source-get.test.ts +100 -0
- package/src/clis/notebooklm/source-get.ts +60 -0
- package/src/clis/notebooklm/source-guide.test.ts +121 -0
- package/src/clis/notebooklm/source-guide.ts +69 -0
- package/src/clis/notebooklm/source-list.ts +45 -0
- package/src/clis/notebooklm/status.ts +34 -0
- package/src/clis/notebooklm/summary.test.ts +94 -0
- package/src/clis/notebooklm/summary.ts +45 -0
- package/src/clis/notebooklm/utils.test.ts +446 -0
- package/src/clis/notebooklm/utils.ts +893 -0
- package/src/clis/substack/utils.test.ts +54 -0
- package/src/clis/substack/utils.ts +10 -2
- package/src/clis/v2ex/hot.yaml +4 -1
- package/src/clis/v2ex/latest.yaml +4 -1
- package/src/clis/v2ex/topic.yaml +6 -1
- package/src/clis/weixin/download.ts +95 -6
- package/src/clis/weread/book.ts +142 -2
- package/src/clis/weread/commands.test.ts +314 -154
- package/src/clis/weread/utils.ts +33 -4
- package/src/clis/xiaohongshu/comments.test.ts +85 -9
- package/src/clis/xiaohongshu/comments.ts +76 -17
- package/src/clis/xiaohongshu/download.test.ts +96 -0
- package/src/clis/xiaohongshu/download.ts +83 -22
- package/src/clis/xiaohongshu/note-helpers.ts +25 -0
- package/src/clis/xiaohongshu/note.test.ts +164 -0
- package/src/clis/xiaohongshu/note.ts +86 -0
- package/src/clis/xiaohongshu/search.test.ts +11 -4
- package/src/clis/xiaohongshu/search.ts +13 -0
- package/src/clis/youtube/search.ts +57 -17
- package/src/clis/zhihu/question.test.ts +71 -0
- package/src/clis/zhihu/question.ts +27 -15
- package/src/commanderAdapter.test.ts +30 -0
- package/src/commanderAdapter.ts +7 -0
- package/src/commands/daemon.test.ts +238 -0
- package/src/commands/daemon.ts +135 -0
- package/src/completion.ts +2 -1
- package/src/constants.ts +3 -0
- package/src/daemon.test.ts +88 -0
- package/src/daemon.ts +26 -14
- package/src/discovery.ts +52 -2
- package/src/electron-apps.test.ts +50 -0
- package/src/electron-apps.ts +89 -0
- package/src/engine.test.ts +45 -9
- package/src/execution.ts +24 -19
- package/src/idle-manager.ts +60 -0
- package/src/launcher.test.ts +67 -0
- package/src/launcher.ts +185 -0
- package/src/main.ts +3 -2
- package/src/registry.test.ts +15 -0
- package/src/registry.ts +32 -3
- package/src/runtime.ts +13 -7
- package/src/serialization.test.ts +19 -1
- package/src/serialization.ts +2 -0
- package/src/tui.test.ts +23 -0
- package/src/tui.ts +65 -0
- package/src/weixin-download.test.ts +27 -0
- package/tests/e2e/browser-public-extended.test.ts +6 -2
- package/chatwise-opencli.ps1 +0 -82
- package/dist/clis/chatwise/shared.d.ts +0 -2
- package/dist/clis/chatwise/shared.js +0 -6
- package/src/clis/chatwise/shared.ts +0 -8
package/src/registry.ts
CHANGED
|
@@ -33,6 +33,7 @@ export type CommandArgs = Record<string, any>;
|
|
|
33
33
|
export interface CliCommand {
|
|
34
34
|
site: string;
|
|
35
35
|
name: string;
|
|
36
|
+
aliases?: string[];
|
|
36
37
|
description: string;
|
|
37
38
|
domain?: string;
|
|
38
39
|
strategy?: Strategy;
|
|
@@ -85,9 +86,11 @@ const _registry: Map<string, CliCommand> =
|
|
|
85
86
|
export function cli(opts: CliOptions): CliCommand {
|
|
86
87
|
const strategy = opts.strategy ?? (opts.browser === false ? Strategy.PUBLIC : Strategy.COOKIE);
|
|
87
88
|
const browser = opts.browser ?? (strategy !== Strategy.PUBLIC);
|
|
89
|
+
const aliases = normalizeAliases(opts.aliases, opts.name);
|
|
88
90
|
const cmd: CliCommand = {
|
|
89
91
|
site: opts.site,
|
|
90
92
|
name: opts.name,
|
|
93
|
+
aliases,
|
|
91
94
|
description: opts.description ?? '',
|
|
92
95
|
domain: opts.domain,
|
|
93
96
|
strategy,
|
|
@@ -104,8 +107,7 @@ export function cli(opts: CliOptions): CliCommand {
|
|
|
104
107
|
navigateBefore: opts.navigateBefore,
|
|
105
108
|
};
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
_registry.set(key, cmd);
|
|
110
|
+
registerCommand(cmd);
|
|
109
111
|
return cmd;
|
|
110
112
|
}
|
|
111
113
|
|
|
@@ -122,5 +124,32 @@ export function strategyLabel(cmd: CliCommand): string {
|
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
export function registerCommand(cmd: CliCommand): void {
|
|
125
|
-
|
|
127
|
+
const canonicalKey = fullName(cmd);
|
|
128
|
+
const existing = _registry.get(canonicalKey);
|
|
129
|
+
if (existing) {
|
|
130
|
+
for (const [key, value] of _registry.entries()) {
|
|
131
|
+
if (value === existing && key !== canonicalKey) _registry.delete(key);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const aliases = normalizeAliases(cmd.aliases, cmd.name);
|
|
136
|
+
cmd.aliases = aliases.length > 0 ? aliases : undefined;
|
|
137
|
+
_registry.set(canonicalKey, cmd);
|
|
138
|
+
for (const alias of aliases) {
|
|
139
|
+
_registry.set(`${cmd.site}/${alias}`, cmd);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function normalizeAliases(aliases: string[] | undefined, commandName: string): string[] {
|
|
144
|
+
if (!Array.isArray(aliases) || aliases.length === 0) return [];
|
|
145
|
+
|
|
146
|
+
const seen = new Set<string>();
|
|
147
|
+
const normalized: string[] = [];
|
|
148
|
+
for (const alias of aliases) {
|
|
149
|
+
const value = typeof alias === 'string' ? alias.trim() : '';
|
|
150
|
+
if (!value || value === commandName || seen.has(value)) continue;
|
|
151
|
+
seen.add(value);
|
|
152
|
+
normalized.push(value);
|
|
153
|
+
}
|
|
154
|
+
return normalized;
|
|
126
155
|
}
|
package/src/runtime.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { BrowserBridge, CDPBridge } from './browser/index.js';
|
|
2
2
|
import type { IPage } from './types.js';
|
|
3
3
|
import { TimeoutError } from './errors.js';
|
|
4
|
+
import { isElectronApp } from './electron-apps.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Returns the appropriate browser factory based on
|
|
7
|
-
* Uses CDPBridge
|
|
7
|
+
* Returns the appropriate browser factory based on site type.
|
|
8
|
+
* Uses CDPBridge for registered Electron apps, otherwise BrowserBridge.
|
|
8
9
|
*/
|
|
9
|
-
export function getBrowserFactory(): new () => IBrowserFactory {
|
|
10
|
-
|
|
10
|
+
export function getBrowserFactory(site?: string): new () => IBrowserFactory {
|
|
11
|
+
if (site && isElectronApp(site)) return CDPBridge;
|
|
12
|
+
return BrowserBridge;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
function parseEnvTimeout(envVar: string, fallback: number): number {
|
|
@@ -61,18 +63,22 @@ export function withTimeoutMs<T>(
|
|
|
61
63
|
|
|
62
64
|
/** Interface for browser factory (BrowserBridge or test mocks) */
|
|
63
65
|
export interface IBrowserFactory {
|
|
64
|
-
connect(opts?: { timeout?: number; workspace?: string }): Promise<IPage>;
|
|
66
|
+
connect(opts?: { timeout?: number; workspace?: string; cdpEndpoint?: string }): Promise<IPage>;
|
|
65
67
|
close(): Promise<void>;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
export async function browserSession<T>(
|
|
69
71
|
BrowserFactory: new () => IBrowserFactory,
|
|
70
72
|
fn: (page: IPage) => Promise<T>,
|
|
71
|
-
opts: { workspace?: string } = {},
|
|
73
|
+
opts: { workspace?: string; cdpEndpoint?: string } = {},
|
|
72
74
|
): Promise<T> {
|
|
73
75
|
const mcp = new BrowserFactory();
|
|
74
76
|
try {
|
|
75
|
-
const page = await mcp.connect({
|
|
77
|
+
const page = await mcp.connect({
|
|
78
|
+
timeout: DEFAULT_BROWSER_CONNECT_TIMEOUT,
|
|
79
|
+
workspace: opts.workspace,
|
|
80
|
+
cdpEndpoint: opts.cdpEndpoint,
|
|
81
|
+
});
|
|
76
82
|
return await fn(page);
|
|
77
83
|
} finally {
|
|
78
84
|
await mcp.close().catch(() => {});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import type { CliCommand } from './registry.js';
|
|
3
3
|
import { Strategy } from './registry.js';
|
|
4
|
-
import { formatRegistryHelpText } from './serialization.js';
|
|
4
|
+
import { formatRegistryHelpText, serializeCommand } from './serialization.js';
|
|
5
5
|
|
|
6
6
|
describe('formatRegistryHelpText', () => {
|
|
7
7
|
it('summarizes long choices lists so help text stays readable', () => {
|
|
@@ -23,4 +23,22 @@ describe('formatRegistryHelpText', () => {
|
|
|
23
23
|
|
|
24
24
|
expect(formatRegistryHelpText(cmd)).toContain('--field: all-fields, topic, title, author, ... (+3 more)');
|
|
25
25
|
});
|
|
26
|
+
|
|
27
|
+
it('includes aliases in structured serialization and help text', () => {
|
|
28
|
+
const cmd: CliCommand = {
|
|
29
|
+
site: 'demo',
|
|
30
|
+
name: 'get',
|
|
31
|
+
aliases: ['metadata'],
|
|
32
|
+
description: 'Demo command',
|
|
33
|
+
strategy: Strategy.COOKIE,
|
|
34
|
+
browser: true,
|
|
35
|
+
args: [],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
expect(serializeCommand(cmd)).toMatchObject({
|
|
39
|
+
command: 'demo/get',
|
|
40
|
+
aliases: ['metadata'],
|
|
41
|
+
});
|
|
42
|
+
expect(formatRegistryHelpText(cmd)).toContain('Aliases: metadata');
|
|
43
|
+
});
|
|
26
44
|
});
|
package/src/serialization.ts
CHANGED
|
@@ -39,6 +39,7 @@ export function serializeCommand(cmd: CliCommand) {
|
|
|
39
39
|
command: fullName(cmd),
|
|
40
40
|
site: cmd.site,
|
|
41
41
|
name: cmd.name,
|
|
42
|
+
aliases: cmd.aliases ?? [],
|
|
42
43
|
description: cmd.description,
|
|
43
44
|
strategy: strategyLabel(cmd),
|
|
44
45
|
browser: !!cmd.browser,
|
|
@@ -82,6 +83,7 @@ export function formatRegistryHelpText(cmd: CliCommand): string {
|
|
|
82
83
|
if (cmd.domain) meta.push(`Domain: ${cmd.domain}`);
|
|
83
84
|
if (cmd.deprecated) meta.push(`Deprecated: ${typeof cmd.deprecated === 'string' ? cmd.deprecated : 'yes'}`);
|
|
84
85
|
if (cmd.replacedBy) meta.push(`Use instead: ${cmd.replacedBy}`);
|
|
86
|
+
if (cmd.aliases?.length) meta.push(`Aliases: ${cmd.aliases.join(', ')}`);
|
|
85
87
|
lines.push(meta.join(' | '));
|
|
86
88
|
if (cmd.columns?.length) lines.push(`Output columns: ${cmd.columns.join(', ')}`);
|
|
87
89
|
return '\n' + lines.join('\n') + '\n';
|
package/src/tui.test.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { confirmPrompt } from './tui.js';
|
|
3
|
+
|
|
4
|
+
describe('confirmPrompt', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
vi.restoreAllMocks();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('returns defaultYes when stdin is not TTY', async () => {
|
|
10
|
+
const result = await confirmPrompt('Restart?', true);
|
|
11
|
+
expect(result).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('returns false when defaultYes is false and non-TTY', async () => {
|
|
15
|
+
const result = await confirmPrompt('Restart?', false);
|
|
16
|
+
expect(result).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('defaults to true when defaultYes is omitted and non-TTY', async () => {
|
|
20
|
+
const result = await confirmPrompt('Restart?');
|
|
21
|
+
expect(result).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
});
|
package/src/tui.ts
CHANGED
|
@@ -170,3 +170,68 @@ export async function checkboxPrompt(
|
|
|
170
170
|
draw();
|
|
171
171
|
});
|
|
172
172
|
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Simple yes/no confirmation prompt.
|
|
176
|
+
*
|
|
177
|
+
* In non-TTY environments, returns `defaultYes` (defaults to true) without blocking.
|
|
178
|
+
* In TTY, waits for a single keypress: y/Enter → true, n/Esc/q → false.
|
|
179
|
+
*/
|
|
180
|
+
export async function confirmPrompt(
|
|
181
|
+
message: string,
|
|
182
|
+
defaultYes: boolean = true,
|
|
183
|
+
): Promise<boolean> {
|
|
184
|
+
const { stdin, stdout } = process;
|
|
185
|
+
if (!stdin.isTTY) return defaultYes;
|
|
186
|
+
|
|
187
|
+
const hint = defaultYes ? '[Y/n]' : '[y/N]';
|
|
188
|
+
stdout.write(` ${message} ${chalk.dim(hint)} `);
|
|
189
|
+
|
|
190
|
+
return new Promise<boolean>((resolve) => {
|
|
191
|
+
const wasRaw = stdin.isRaw;
|
|
192
|
+
stdin.setRawMode(true);
|
|
193
|
+
stdin.resume();
|
|
194
|
+
|
|
195
|
+
function cleanup() {
|
|
196
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
197
|
+
stdin.pause();
|
|
198
|
+
stdin.removeListener('data', onData);
|
|
199
|
+
stdout.write('\n');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function onData(data: Buffer) {
|
|
203
|
+
const key = data.toString();
|
|
204
|
+
|
|
205
|
+
// Ctrl+C
|
|
206
|
+
if (key === '\x03') {
|
|
207
|
+
cleanup();
|
|
208
|
+
process.exit(EXIT_CODES.INTERRUPTED);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Enter — use default
|
|
212
|
+
if (key === '\r' || key === '\n') {
|
|
213
|
+
cleanup();
|
|
214
|
+
resolve(defaultYes);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// y/Y — yes
|
|
219
|
+
if (key === 'y' || key === 'Y') {
|
|
220
|
+
cleanup();
|
|
221
|
+
resolve(true);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// n/N/q/Esc — no
|
|
226
|
+
if (key === 'n' || key === 'N' || key === 'q' || key === '\x1b') {
|
|
227
|
+
cleanup();
|
|
228
|
+
resolve(false);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Ignore other keys
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
stdin.on('data', onData);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
@@ -61,4 +61,31 @@ describe('weixin publish time extraction', () => {
|
|
|
61
61
|
'var create_time = "1711291080";',
|
|
62
62
|
)).toBe('2026年3月24日 22:38');
|
|
63
63
|
});
|
|
64
|
+
|
|
65
|
+
it('detects WeChat verification gate pages', async () => {
|
|
66
|
+
const mod = await loadModule();
|
|
67
|
+
|
|
68
|
+
expect(mod.detectWechatAccessIssue(
|
|
69
|
+
'环境异常 当前环境异常,完成验证后即可继续访问。 去验证',
|
|
70
|
+
'<html><body><a id="js_verify">去验证</a></body></html>',
|
|
71
|
+
)).toBe('environment verification required');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('browser access detector matches the server-side verifier', async () => {
|
|
75
|
+
const mod = await loadModule();
|
|
76
|
+
|
|
77
|
+
const detectInPage = eval(mod.buildDetectWechatAccessIssueJs()) as (pageText: string, htmlStr: string) => string;
|
|
78
|
+
|
|
79
|
+
expect(detectInPage(
|
|
80
|
+
'环境异常 当前环境异常,完成验证后即可继续访问。 去验证',
|
|
81
|
+
'<html>secitptpage/verify.html<a id="js_verify">去验证</a></html>',
|
|
82
|
+
)).toBe('environment verification required');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('picks the first non-empty WeChat metadata field', async () => {
|
|
86
|
+
const mod = await loadModule();
|
|
87
|
+
|
|
88
|
+
expect(mod.pickFirstWechatMetaText('', 'Name cleared', '数字生命卡兹克')).toBe('数字生命卡兹克');
|
|
89
|
+
expect(mod.pickFirstWechatMetaText('', ' 聊聊刚刚上线的PixVerse V6视频模型。 ')).toBe('聊聊刚刚上线的PixVerse V6视频模型。');
|
|
90
|
+
});
|
|
64
91
|
});
|
|
@@ -126,9 +126,13 @@ describe('browser extended public-data commands E2E', () => {
|
|
|
126
126
|
}, 60_000);
|
|
127
127
|
|
|
128
128
|
// ── ctrip ──
|
|
129
|
-
it('ctrip search returns
|
|
130
|
-
const data = await tryBrowserCommand(['ctrip', 'search', '-f', 'json']);
|
|
129
|
+
it('ctrip search returns destination suggestions', async () => {
|
|
130
|
+
const data = await tryBrowserCommand(['ctrip', 'search', '苏州', '--limit', '3', '-f', 'json']);
|
|
131
131
|
expectDataOrSkip(data, 'ctrip search');
|
|
132
|
+
if (data) {
|
|
133
|
+
expect(data[0]).toHaveProperty('name');
|
|
134
|
+
expect(data[0]).toHaveProperty('type');
|
|
135
|
+
}
|
|
132
136
|
}, 60_000);
|
|
133
137
|
|
|
134
138
|
// ── coupang ──
|
package/chatwise-opencli.ps1
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
[CmdletBinding()]
|
|
2
|
-
param(
|
|
3
|
-
[Parameter(ValueFromRemainingArguments = $true)]
|
|
4
|
-
[string[]]$OpenCliArgs
|
|
5
|
-
)
|
|
6
|
-
|
|
7
|
-
$ErrorActionPreference = 'Stop'
|
|
8
|
-
|
|
9
|
-
$chatwiseExe = 'C:\Program Files\ChatWise\ChatWise.exe'
|
|
10
|
-
if (-not (Test-Path $chatwiseExe)) {
|
|
11
|
-
throw "ChatWise executable not found at $chatwiseExe"
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
$opencli = Get-Command opencli -ErrorAction SilentlyContinue
|
|
15
|
-
if (-not $opencli) {
|
|
16
|
-
throw 'opencli was not found in PATH'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function Clear-LocalProxyEnv {
|
|
20
|
-
$vars = 'http_proxy','https_proxy','HTTP_PROXY','HTTPS_PROXY'
|
|
21
|
-
foreach ($name in $vars) {
|
|
22
|
-
Set-Item -Path "Env:$name" -Value ''
|
|
23
|
-
}
|
|
24
|
-
$noProxy = '127.0.0.1,localhost'
|
|
25
|
-
Set-Item -Path 'Env:NO_PROXY' -Value $noProxy
|
|
26
|
-
Set-Item -Path 'Env:no_proxy' -Value $noProxy
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function Stop-ChatWiseTree {
|
|
30
|
-
$candidates = Get-CimInstance Win32_Process |
|
|
31
|
-
Where-Object { $_.Name -match '^ChatWise\.exe$|^chatwise\.exe$' }
|
|
32
|
-
|
|
33
|
-
foreach ($proc in $candidates) {
|
|
34
|
-
try {
|
|
35
|
-
Stop-Process -Id $proc.ProcessId -Force -ErrorAction Stop
|
|
36
|
-
} catch {}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
Start-Sleep -Seconds 2
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function Wait-ChatWiseDebugPort {
|
|
43
|
-
param(
|
|
44
|
-
[int]$Port = 9228,
|
|
45
|
-
[int]$TimeoutSeconds = 20
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
|
49
|
-
while ((Get-Date) -lt $deadline) {
|
|
50
|
-
try {
|
|
51
|
-
$resp = Invoke-WebRequest -UseBasicParsing -TimeoutSec 2 -Uri "http://127.0.0.1:$Port/json/version"
|
|
52
|
-
if ($resp.StatusCode -ge 200 -and $resp.StatusCode -lt 300) {
|
|
53
|
-
return
|
|
54
|
-
}
|
|
55
|
-
} catch {}
|
|
56
|
-
Start-Sleep -Milliseconds 500
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
throw "ChatWise debugging endpoint did not come up on 127.0.0.1:$Port"
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
Clear-LocalProxyEnv
|
|
63
|
-
Stop-ChatWiseTree
|
|
64
|
-
|
|
65
|
-
$proc = Start-Process -FilePath $chatwiseExe -ArgumentList '--remote-debugging-port=9228' -PassThru
|
|
66
|
-
Start-Sleep -Seconds 4
|
|
67
|
-
|
|
68
|
-
if ($proc.HasExited) {
|
|
69
|
-
throw "ChatWise exited early with code $($proc.ExitCode)"
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
Wait-ChatWiseDebugPort
|
|
73
|
-
|
|
74
|
-
$env:OPENCLI_CDP_ENDPOINT = 'http://127.0.0.1:9228'
|
|
75
|
-
|
|
76
|
-
if (-not $OpenCliArgs -or $OpenCliArgs.Count -eq 0) {
|
|
77
|
-
& $opencli.Source 'chatwise' 'status'
|
|
78
|
-
exit $LASTEXITCODE
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
& $opencli.Source @OpenCliArgs
|
|
82
|
-
exit $LASTEXITCODE
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export const chatwiseRequiredEnv = [
|
|
2
|
-
{
|
|
3
|
-
name: 'OPENCLI_CDP_ENDPOINT',
|
|
4
|
-
help: 'Launch ChatWise with --remote-debugging-port=9228, then run OPENCLI_CDP_ENDPOINT=http://127.0.0.1:9228 opencli chatwise status. If you use a local proxy, also set NO_PROXY=127.0.0.1,localhost.',
|
|
5
|
-
},
|
|
6
|
-
];
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { RequiredEnv } from '../../registry.js';
|
|
2
|
-
|
|
3
|
-
export const chatwiseRequiredEnv: RequiredEnv[] = [
|
|
4
|
-
{
|
|
5
|
-
name: 'OPENCLI_CDP_ENDPOINT',
|
|
6
|
-
help: 'Launch ChatWise with --remote-debugging-port=9228, then run OPENCLI_CDP_ENDPOINT=http://127.0.0.1:9228 opencli chatwise status. If you use a local proxy, also set NO_PROXY=127.0.0.1,localhost.',
|
|
7
|
-
},
|
|
8
|
-
];
|