@web-auto/webauto 0.1.14 → 0.1.15

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 ADDED
@@ -0,0 +1,137 @@
1
+ # @web-auto/webauto
2
+
3
+ Windows 优先的 WebAuto CLI + Desktop UI 使用说明。
4
+
5
+ ## 1. 安装(Windows)
6
+
7
+ 要求:
8
+ - Node.js 18+(建议 20+)
9
+ - npm 可用
10
+
11
+ 全局安装:
12
+
13
+ ```bat
14
+ npm install -g @web-auto/webauto
15
+ ```
16
+
17
+ 验证:
18
+
19
+ ```bat
20
+ webauto --help
21
+ ```
22
+
23
+ ## 2. 直接启动 UI
24
+
25
+ 最直接方式:
26
+
27
+ ```bat
28
+ webauto ui console
29
+ ```
30
+
31
+ 或用 UI CLI 自动拉起(适合脚本化):
32
+
33
+ ```bat
34
+ webauto ui cli start --json
35
+ webauto ui cli status --json
36
+ ```
37
+
38
+ 说明:
39
+ - 首次启动会自动准备 Desktop runtime 依赖(Electron),不需要手工安装。
40
+ - 启动成功后,UI CLI bridge 默认端口是 `7716`。
41
+
42
+ ## 3. UI CLI 常用命令(模拟真实 UI 操作)
43
+
44
+ ```bat
45
+ webauto ui cli --help
46
+
47
+ :: 切换到任务页
48
+ webauto ui cli tab --tab tasks --json
49
+
50
+ :: 输入任务参数
51
+ webauto ui cli input --selector "#task-keyword" --value "deepseek" --json
52
+ webauto ui cli input --selector "#task-target" --value "20" --json
53
+
54
+ :: 点击执行
55
+ webauto ui cli click --selector "#task-run-ephemeral-btn" --json
56
+
57
+ :: 读取当前 UI 快照
58
+ webauto ui cli status --json
59
+ webauto ui cli snapshot --json
60
+
61
+ :: 元素探测
62
+ webauto ui cli probe --selector "#task-likes" --json
63
+ ```
64
+
65
+ 任务状态查看(后端状态):
66
+
67
+ ```bat
68
+ webauto xhs status --json
69
+ webauto xhs status --run-id <runId> --json
70
+ ```
71
+
72
+ ## 4. Windows 路径与设置
73
+
74
+ 默认数据目录(未设置环境变量时):
75
+ - 有 `D:` 盘:`D:\webauto`
76
+ - 无 `D:` 盘:`%USERPROFILE%\.webauto`
77
+
78
+ 可选环境变量:
79
+ - `WEBAUTO_HOME`:显式指定数据根目录(推荐)
80
+ - `WEBAUTO_ROOT` / `WEBAUTO_PORTABLE_ROOT`:兼容旧变量(会归一化到 `.webauto`)
81
+
82
+ PowerShell 设置示例:
83
+
84
+ ```powershell
85
+ $env:WEBAUTO_HOME = "D:\webauto"
86
+ webauto ui console
87
+ ```
88
+
89
+ CMD 设置示例:
90
+
91
+ ```bat
92
+ set WEBAUTO_HOME=D:\webauto
93
+ webauto ui console
94
+ ```
95
+
96
+ 不设置也可以直接用,系统会按默认规则落盘。
97
+
98
+ ## 5. 首次安装常见问题
99
+
100
+ ### 5.1 `Lock file can not be created` / 启动失败
101
+
102
+ 说明:通常是残留的 Electron/Node 进程占用。
103
+
104
+ ```bat
105
+ taskkill /F /IM electron.exe /T
106
+ taskkill /F /IM node.exe /T
107
+ webauto ui console
108
+ ```
109
+
110
+ ### 5.2 `ui cli fetch failed`
111
+
112
+ 先确认 UI 已启动并就绪:
113
+
114
+ ```bat
115
+ webauto ui cli start --json
116
+ webauto ui cli status --json
117
+ ```
118
+
119
+ 若仍失败,前台启动看日志:
120
+
121
+ ```bat
122
+ webauto ui console --no-daemon
123
+ ```
124
+
125
+ ## 6. 资源检查/安装
126
+
127
+ ```bat
128
+ webauto xhs install --check --json
129
+ webauto xhs install --download-browser --json
130
+ webauto xhs install --download-geoip --json
131
+ ```
132
+
133
+ ## 7. 开发者(仓库模式)
134
+
135
+ 在仓库中开发请看:
136
+ - `apps/desktop-console/README.md`
137
+
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ import minimist from 'minimist';
3
+ import {
4
+ listPlatformFlowGates,
5
+ loadFlowGateDoc,
6
+ patchPlatformFlowGate,
7
+ resetPlatformFlowGate,
8
+ resolveFlowGatePath,
9
+ resolvePlatformFlowGate,
10
+ } from './lib/flow-gate.mjs';
11
+
12
+ function normalizePlatform(value) {
13
+ const text = String(value || '').trim().toLowerCase();
14
+ if (!text) return 'xiaohongshu';
15
+ if (text === 'xhs') return 'xiaohongshu';
16
+ return text;
17
+ }
18
+
19
+ function toJsonMode(argv) {
20
+ return argv.json === true || argv.j === true;
21
+ }
22
+
23
+ function printHelp() {
24
+ console.log([
25
+ 'Usage: node apps/webauto/entry/flow-gate.mjs <get|list|set|reset|path> [options]',
26
+ 'Options:',
27
+ ' --platform <name> 平台名(默认 xiaohongshu)',
28
+ ' --patch-json <json> set 动作补丁 JSON(对象)',
29
+ ' --json 输出 JSON',
30
+ '',
31
+ 'Examples:',
32
+ ' node apps/webauto/entry/flow-gate.mjs get --platform xiaohongshu --json',
33
+ ' node apps/webauto/entry/flow-gate.mjs list --json',
34
+ ' node apps/webauto/entry/flow-gate.mjs set --platform xiaohongshu --patch-json \'{"noteInterval":{"minMs":2600,"maxMs":5200}}\' --json',
35
+ ' node apps/webauto/entry/flow-gate.mjs reset --platform xiaohongshu --json',
36
+ ].join('\n'));
37
+ }
38
+
39
+ function parsePatchJson(raw) {
40
+ const text = String(raw || '').trim();
41
+ if (!text) throw new Error('missing --patch-json');
42
+ let parsed = null;
43
+ try {
44
+ parsed = JSON.parse(text);
45
+ } catch (error) {
46
+ throw new Error(`invalid --patch-json: ${error?.message || String(error)}`);
47
+ }
48
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
49
+ throw new Error('--patch-json must be object JSON');
50
+ }
51
+ return parsed;
52
+ }
53
+
54
+ async function main() {
55
+ const argv = minimist(process.argv.slice(2), {
56
+ boolean: ['help', 'h', 'json', 'j'],
57
+ string: ['platform', 'patch-json'],
58
+ });
59
+ if (argv.help || argv.h) {
60
+ printHelp();
61
+ return;
62
+ }
63
+
64
+ const action = String(argv._[0] || 'get').trim().toLowerCase();
65
+ const platform = normalizePlatform(argv.platform);
66
+ const jsonMode = toJsonMode(argv);
67
+ const path = resolveFlowGatePath();
68
+
69
+ if (action === 'path') {
70
+ if (jsonMode) {
71
+ console.log(JSON.stringify({ ok: true, path }, null, 2));
72
+ } else {
73
+ console.log(path);
74
+ }
75
+ return;
76
+ }
77
+
78
+ if (action === 'get') {
79
+ const gate = await resolvePlatformFlowGate(platform);
80
+ if (jsonMode) {
81
+ console.log(JSON.stringify({ ok: true, platform, path, gate }, null, 2));
82
+ } else {
83
+ console.log(`[flow-gate] platform=${platform}`);
84
+ console.log(JSON.stringify(gate, null, 2));
85
+ console.log(`[flow-gate] file=${path}`);
86
+ }
87
+ return;
88
+ }
89
+
90
+ if (action === 'list') {
91
+ const gates = await listPlatformFlowGates();
92
+ if (jsonMode) {
93
+ console.log(JSON.stringify({ ok: true, path, platforms: gates }, null, 2));
94
+ } else {
95
+ console.log(JSON.stringify(gates, null, 2));
96
+ console.log(`[flow-gate] file=${path}`);
97
+ }
98
+ return;
99
+ }
100
+
101
+ if (action === 'set') {
102
+ const patch = parsePatchJson(argv['patch-json']);
103
+ const gate = await patchPlatformFlowGate(platform, patch);
104
+ if (jsonMode) {
105
+ console.log(JSON.stringify({ ok: true, action, platform, path, gate }, null, 2));
106
+ } else {
107
+ console.log(`[flow-gate] updated platform=${platform}`);
108
+ console.log(JSON.stringify(gate, null, 2));
109
+ console.log(`[flow-gate] file=${path}`);
110
+ }
111
+ return;
112
+ }
113
+
114
+ if (action === 'reset') {
115
+ const gate = await resetPlatformFlowGate(platform);
116
+ if (jsonMode) {
117
+ console.log(JSON.stringify({ ok: true, action, platform, path, gate }, null, 2));
118
+ } else {
119
+ console.log(`[flow-gate] reset platform=${platform}`);
120
+ console.log(JSON.stringify(gate, null, 2));
121
+ console.log(`[flow-gate] file=${path}`);
122
+ }
123
+ return;
124
+ }
125
+
126
+ if (action === 'show-doc') {
127
+ const doc = await loadFlowGateDoc();
128
+ if (jsonMode) console.log(JSON.stringify({ ok: true, path, doc }, null, 2));
129
+ else console.log(JSON.stringify(doc, null, 2));
130
+ return;
131
+ }
132
+
133
+ throw new Error(`unknown action: ${action}`);
134
+ }
135
+
136
+ main().catch((err) => {
137
+ console.error(err?.message || String(err));
138
+ process.exit(1);
139
+ });