weflow-cli 1.16.0 → 1.17.0

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 (97) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +16 -4
  3. package/bin/weflow-cli.ts +348 -6
  4. package/dist/bin/weflow-cli.js +381 -8
  5. package/dist/bin/weflow-cli.js.map +1 -1
  6. package/dist/src/core/ntCore.d.ts +47 -0
  7. package/dist/src/core/ntCore.d.ts.map +1 -1
  8. package/dist/src/core/ntCore.js +24 -0
  9. package/dist/src/core/ntCore.js.map +1 -1
  10. package/dist/src/services/assistantService.d.ts +8 -1
  11. package/dist/src/services/assistantService.d.ts.map +1 -1
  12. package/dist/src/services/assistantService.js +47 -8
  13. package/dist/src/services/assistantService.js.map +1 -1
  14. package/dist/src/services/assistantTools.d.ts +8 -0
  15. package/dist/src/services/assistantTools.d.ts.map +1 -1
  16. package/dist/src/services/assistantTools.js +67 -11
  17. package/dist/src/services/assistantTools.js.map +1 -1
  18. package/dist/src/services/configService.d.ts.map +1 -1
  19. package/dist/src/services/configService.js +3 -2
  20. package/dist/src/services/configService.js.map +1 -1
  21. package/dist/src/services/cursorProbe.d.ts +44 -0
  22. package/dist/src/services/cursorProbe.d.ts.map +1 -0
  23. package/dist/src/services/cursorProbe.js +183 -0
  24. package/dist/src/services/cursorProbe.js.map +1 -0
  25. package/dist/src/services/qchatImport.d.ts +89 -0
  26. package/dist/src/services/qchatImport.d.ts.map +1 -0
  27. package/dist/src/services/qchatImport.js +273 -0
  28. package/dist/src/services/qchatImport.js.map +1 -0
  29. package/dist/src/services/setupVenv.d.ts +43 -0
  30. package/dist/src/services/setupVenv.d.ts.map +1 -0
  31. package/dist/src/services/setupVenv.js +198 -0
  32. package/dist/src/services/setupVenv.js.map +1 -0
  33. package/dist/src/utils/python.d.ts +10 -0
  34. package/dist/src/utils/python.d.ts.map +1 -1
  35. package/dist/src/utils/python.js +27 -4
  36. package/dist/src/utils/python.js.map +1 -1
  37. package/docs/DATA_CONTRACT.md +25 -0
  38. package/docs/DECISIONS.md +92 -30
  39. package/docs/FUNCTIONAL-IMPROVEMENT-SPEC.md +365 -365
  40. package/docs/HEALTH-CHECK.md +104 -104
  41. package/docs/JEV/345/272/224/347/224/250/346/226/275/345/267/245/346/226/207/346/241/243.md +310 -310
  42. package/docs/NEXT_ACTIONS.md +236 -236
  43. package/docs/NPM-PUBLISH.md +130 -130
  44. package/docs/POSITIONING.md +68 -68
  45. package/docs/PROJECT_STATE.md +6 -3
  46. package/docs/REPLAY.md +169 -0
  47. package/docs/SYNC_CONTRACT.md +197 -180
  48. package/package.json +89 -88
  49. package/requirements-3x.txt +4 -4
  50. package/requirements-voice.txt +15 -15
  51. package/resources/js/graph3d/NOTICE.txt +35 -35
  52. package/resources/js/graph3d/d3-binarytree.min.js +2 -2
  53. package/resources/js/graph3d/d3-dispatch.min.js +2 -2
  54. package/resources/js/graph3d/d3-force-3d.min.js +2 -2
  55. package/resources/js/graph3d/d3-octree.min.js +2 -2
  56. package/resources/js/graph3d/d3-quadtree.min.js +2 -2
  57. package/resources/js/graph3d/d3-timer.min.js +2 -2
  58. package/resources/js/graph3d/three.min.js +6 -6
  59. package/resources/js/graph3d/viewer2d.js +550 -448
  60. package/resources/panel/quick-menu.cjs +197 -197
  61. package/scripts/_utils.py +1338 -1338
  62. package/scripts/article_notes.py +423 -423
  63. package/scripts/chat_notes.py +86 -3
  64. package/scripts/check_readme_commands.py +427 -426
  65. package/scripts/contact_schema.py +339 -339
  66. package/scripts/create_reading_notes.py +11 -11
  67. package/scripts/daily_task.ps1 +213 -213
  68. package/scripts/fav_notes.py +321 -321
  69. package/scripts/graph_2d.py +156 -151
  70. package/scripts/graph_3d.py +672 -646
  71. package/scripts/health_check.py +473 -473
  72. package/scripts/imported_chats.py +68 -0
  73. package/scripts/install_tasks.ps1 +105 -105
  74. package/scripts/leads.py +179 -179
  75. package/scripts/network.py +206 -206
  76. package/scripts/nt_decrypt.py +135 -1
  77. package/scripts/on_this_day.py +178 -178
  78. package/scripts/opinion_timeline.py +138 -138
  79. package/scripts/promises.py +185 -185
  80. package/scripts/replay.py +803 -0
  81. package/scripts/run_hidden.vbs +25 -0
  82. package/scripts/semantic_search.py +73 -5
  83. package/scripts/user_notes.py +315 -315
  84. package/scripts/voice_transcribe.py +139 -139
  85. package/scripts/watch_issues.py +212 -212
  86. package/scripts/watch_mail.py +131 -131
  87. package/src/core/ntCore.ts +59 -0
  88. package/src/services/assistantService.ts +48 -8
  89. package/src/services/assistantTools.ts +73 -10
  90. package/src/services/configService.ts +3 -2
  91. package/src/services/cursorProbe.ts +222 -0
  92. package/src/services/qchatImport.ts +327 -0
  93. package/src/services/setupVenv.ts +238 -0
  94. package/src/services/syncService.ts +363 -363
  95. package/src/services/syncState.ts +275 -275
  96. package/src/services/wechatMedia.ts +166 -166
  97. package/src/utils/python.ts +33 -4
@@ -0,0 +1,273 @@
1
+ /**
2
+ * `weflow-cli import qchat` —— 读 qchat-cli 的导出文件,归一化落进本地存储(D-129)。
3
+ *
4
+ * 边界是**文件契约**,不是进程耦合:qchat-cli 一行不用改,我们读它 `qce export --format json`
5
+ * 产出的那份 JSON(形状见 `parseQchatExport`)。落盘后的存储(`output/imports/qq/sessions/`)
6
+ * 是 weflow 这边的私有形状 `weflow-import/qq-v1`,字段语义与 `weflow-message/v1` 对齐
7
+ * (serverId/createTime/parsedContent/rawContent/13 个稳定 messageType)——一套词汇表两边用。
8
+ *
9
+ * QQ 的 `messageId` 是服务端全局唯一(OneBot 语义),所以去重/合并就靠它,不需要微信侧那套
10
+ * 重叠时间窗;这一点对 D-027 也成立:qq 来源天然满足 stable-identity 判据。
11
+ *
12
+ * 隐私边界:导入的是用户本人授权的 QQ 数据(qchat-cli 侧靠 NapCatQQ/OneBot 授权),落盘后
13
+ * 继承 weflow 的纪律——QQ 号与 wxid 同级敏感,不进公开输出;下游管道(搜索/知识卡)各自
14
+ * 已有的隐私门对它照常生效。
15
+ */
16
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'fs';
17
+ import { join } from 'path';
18
+ import { resolvePackageRoot } from '../utils/packageRoot.js';
19
+ /** 存储根。`WEFLOW_IMPORT_ROOT` 可整体指到别处(测试用,Python 侧读同一个变量)。 */
20
+ export function importRoot() {
21
+ if (process.env.WEFLOW_IMPORT_ROOT)
22
+ return process.env.WEFLOW_IMPORT_ROOT;
23
+ return join(resolvePackageRoot(import.meta.url), 'output', 'imports', 'qq');
24
+ }
25
+ function sessionsDir() {
26
+ return join(importRoot(), 'sessions');
27
+ }
28
+ export const IMPORT_SCHEMA = 'weflow-import/qq-v1';
29
+ /** OneBot 消息段 → weflow 的 13 个稳定类型。纯函数,映射表只有这一份。 */
30
+ export function qqSegmentMessageType(segments) {
31
+ if (!Array.isArray(segments) || !segments.length)
32
+ return 'text';
33
+ const priority = [
34
+ ['record', 'voice'],
35
+ ['video', 'video'],
36
+ ['image', 'image'],
37
+ ['reply', 'quote'],
38
+ ['location', 'location'],
39
+ ['json', 'card'],
40
+ ['xml', 'card'],
41
+ ['contact', 'card'],
42
+ ['file', 'card'],
43
+ ['face', 'emoji'],
44
+ ];
45
+ const kinds = new Set(segments.map(s => String(s?.type || '')));
46
+ for (const [seg, type] of priority) {
47
+ if (kinds.has(seg))
48
+ return type;
49
+ }
50
+ return 'text';
51
+ }
52
+ /**
53
+ * qchat 导出 JSON 的形状识别与解析。判据是结构性的:顶层 `session` 对象 + `messages`
54
+ * 数组、且消息带 `messageId` 与 `timestamp`——认不出来就报错并给出原因,绝不猜。
55
+ */
56
+ export function parseQchatExport(text, file) {
57
+ const fail = (reason) => ({
58
+ file, ok: false, reason, sessions: [],
59
+ });
60
+ let data;
61
+ try {
62
+ data = JSON.parse(text);
63
+ }
64
+ catch (e) {
65
+ return fail(`不是合法 JSON(${String(e?.message || e).slice(0, 80)})`);
66
+ }
67
+ const session = data?.session;
68
+ const messages = data?.messages;
69
+ if (!session || typeof session !== 'object' || !Array.isArray(messages)) {
70
+ return fail('不是 qchat 导出形状(缺 session/messages;应为 `qce export --format json` 的产物)');
71
+ }
72
+ const id = String(session.id ?? '');
73
+ if (!id)
74
+ return fail('session.id 为空');
75
+ let count = 0;
76
+ for (const m of messages) {
77
+ if (m && (m.messageId !== undefined) && (m.timestamp !== undefined))
78
+ count += 1;
79
+ }
80
+ if (!count && messages.length) {
81
+ return fail(`${messages.length} 条消息里没有一条带 messageId+timestamp——大概是别的格式的 JSON`);
82
+ }
83
+ return {
84
+ file, ok: true,
85
+ sessions: [{
86
+ id,
87
+ name: String(session.name || id),
88
+ type: String(session.type || 'private'),
89
+ messages: messages.length,
90
+ }],
91
+ };
92
+ }
93
+ /** 一条 qchat 消息 → 存储形状。字段映射只有这一处。 */
94
+ export function normalizeQchatMessage(raw, ownId) {
95
+ if (!raw || raw.messageId === undefined || raw.timestamp === undefined)
96
+ return null;
97
+ const senderId = String(raw?.sender?.id ?? '');
98
+ const senderName = String(raw?.sender?.card || raw?.sender?.name || senderId);
99
+ const msg = {
100
+ serverId: String(raw.messageId),
101
+ ...(raw.message_seq !== undefined ? { messageSeq: Number(raw.message_seq) } : {}),
102
+ createTime: Number(raw.timestamp),
103
+ ...(ownId ? { isSend: senderId === ownId } : {}),
104
+ senderUsername: senderId,
105
+ senderName,
106
+ messageType: qqSegmentMessageType(raw.message),
107
+ parsedContent: String(raw.content ?? ''),
108
+ rawContent: String(raw.rawMessage ?? ''),
109
+ };
110
+ return msg;
111
+ }
112
+ function safeSessionFile(id) {
113
+ const safe = id.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 80);
114
+ return `${safe || 'session'}.json`;
115
+ }
116
+ function readStoreSession(id) {
117
+ const path = join(sessionsDir(), safeSessionFile(id));
118
+ if (!existsSync(path))
119
+ return null;
120
+ try {
121
+ const data = JSON.parse(readFileSync(path, 'utf-8'));
122
+ if (data?.schema === IMPORT_SCHEMA && Array.isArray(data?.messages))
123
+ return data;
124
+ }
125
+ catch { /* 损坏的存储文件按"没有"处理,重导入会覆盖修复 */ }
126
+ return null;
127
+ }
128
+ /** 收集输入路径下的候选文件(单文件或目录里的 *.json)。 */
129
+ function candidateFiles(input) {
130
+ if (!existsSync(input))
131
+ return [];
132
+ // readdirSync 只对目录成立:文件会抛,正好当探测用
133
+ try {
134
+ const entries = readdirSync(input);
135
+ return entries.filter(f => f.toLowerCase().endsWith('.json'))
136
+ .map(f => join(input, f));
137
+ }
138
+ catch {
139
+ return [input];
140
+ }
141
+ }
142
+ export function planImportQchat(input) {
143
+ const files = candidateFiles(input);
144
+ const plans = [];
145
+ if (!files.length) {
146
+ return {
147
+ files: [{ file: input, ok: false, reason: '输入不存在,或目录里没有 .json 文件', sessions: [] }],
148
+ sessionsFound: 0, messagesTotal: 0, storeRoot: sessionsDir(),
149
+ };
150
+ }
151
+ for (const file of files) {
152
+ let plan;
153
+ try {
154
+ plan = parseQchatExport(readFileSync(file, 'utf-8'), file);
155
+ }
156
+ catch (e) {
157
+ plan = { file, ok: false, reason: `读不了(${String(e?.message || e).slice(0, 80)})`, sessions: [] };
158
+ }
159
+ plans.push(plan);
160
+ }
161
+ const sessionIds = new Set(plans.flatMap(p => p.ok ? p.sessions.map(s => s.id) : []));
162
+ const messagesTotal = plans.flatMap(p => p.sessions).reduce((n, s) => n + s.messages, 0);
163
+ return {
164
+ files: plans,
165
+ sessionsFound: sessionIds.size,
166
+ messagesTotal,
167
+ storeRoot: sessionsDir(),
168
+ };
169
+ }
170
+ export function runImportQchat(input, ownId) {
171
+ const plan = planImportQchat(input);
172
+ const okFiles = plan.files.filter(f => f.ok);
173
+ if (!okFiles.length) {
174
+ return { success: false, sessions: [], filesOk: 0, filesSkipped: plan.files.length, storeRoot: plan.storeRoot };
175
+ }
176
+ mkdirSync(sessionsDir(), { recursive: true });
177
+ const merged = new Map();
178
+ for (const f of okFiles) {
179
+ let data;
180
+ try {
181
+ data = JSON.parse(readFileSync(f.file, 'utf-8'));
182
+ }
183
+ catch {
184
+ continue; // plan 已验证过可解析;这里的失败按跳过处理(计数在 filesSkipped)
185
+ }
186
+ const id = String(data.session.id);
187
+ let entry = merged.get(id);
188
+ if (!entry) {
189
+ entry = {
190
+ existing: readStoreSession(id),
191
+ byId: new Map((readStoreSession(id)?.messages ?? []).map(m => [m.serverId, m])),
192
+ sourceFiles: new Set(readStoreSession(id)?.sourceFiles ?? []),
193
+ meta: { id, name: String(data.session.name || id), type: String(data.session.type || 'private') },
194
+ };
195
+ merged.set(id, entry);
196
+ }
197
+ entry.sourceFiles.add(f.file);
198
+ for (const raw of data.messages ?? []) {
199
+ const msg = normalizeQchatMessage(raw, ownId);
200
+ if (msg)
201
+ entry.byId.set(msg.serverId, msg);
202
+ }
203
+ }
204
+ const sessions = [];
205
+ for (const [id, entry] of merged) {
206
+ const existing = entry.existing;
207
+ const before = new Map((existing?.messages ?? []).map(m => [m.serverId, m]));
208
+ const messages = [...entry.byId.values()].sort((a, b) => a.createTime - b.createTime || a.serverId.localeCompare(b.serverId));
209
+ const file = {
210
+ schema: IMPORT_SCHEMA,
211
+ session: entry.meta,
212
+ importedAt: new Date().toISOString(),
213
+ sourceFiles: [...entry.sourceFiles],
214
+ messages,
215
+ };
216
+ writeFileSync(join(sessionsDir(), safeSessionFile(id)), JSON.stringify(file, null, 1), 'utf-8');
217
+ let added = 0, updated = 0, unchanged = 0;
218
+ for (const m of messages) {
219
+ const old = before.get(m.serverId);
220
+ if (!old)
221
+ added += 1;
222
+ else if (JSON.stringify(old) !== JSON.stringify(m))
223
+ updated += 1;
224
+ else
225
+ unchanged += 1;
226
+ }
227
+ sessions.push({ id: entry.meta.id, name: entry.meta.name, added, updated, unchanged, total: messages.length });
228
+ }
229
+ return {
230
+ success: true,
231
+ sessions,
232
+ filesOk: okFiles.length,
233
+ filesSkipped: plan.files.length - okFiles.length,
234
+ storeRoot: plan.storeRoot,
235
+ };
236
+ }
237
+ export function listImports() {
238
+ const dir = sessionsDir();
239
+ if (!existsSync(dir))
240
+ return [];
241
+ const out = [];
242
+ for (const f of readdirSync(dir)) {
243
+ if (!f.endsWith('.json'))
244
+ continue;
245
+ try {
246
+ const data = JSON.parse(readFileSync(join(dir, f), 'utf-8'));
247
+ if (data?.schema !== IMPORT_SCHEMA)
248
+ continue;
249
+ const times = (data.messages ?? []).map((m) => Number(m.createTime) || 0).filter(Boolean);
250
+ out.push({
251
+ id: String(data.session?.id ?? ''),
252
+ name: String(data.session?.name ?? ''),
253
+ type: String(data.session?.type ?? ''),
254
+ messages: (data.messages ?? []).length,
255
+ oldestCreateTime: times.length ? Math.min(...times) : null,
256
+ newestCreateTime: times.length ? Math.max(...times) : null,
257
+ importedAt: String(data.importedAt ?? ''),
258
+ });
259
+ }
260
+ catch { /* 单个损坏文件不挡住清单 */ }
261
+ }
262
+ return out.sort((a, b) => b.newestCreateTime - a.newestCreateTime);
263
+ }
264
+ /** 读回一个会话(验证导入用)。limit=0 是全部。 */
265
+ export function readImportedSession(id, limit = 0) {
266
+ const data = readStoreSession(id);
267
+ if (!data)
268
+ return null;
269
+ if (limit > 0)
270
+ return { ...data, messages: data.messages.slice(-limit) };
271
+ return data;
272
+ }
273
+ //# sourceMappingURL=qchatImport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qchatImport.js","sourceRoot":"","sources":["../../../src/services/qchatImport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ export declare const VENV_DIR: string;
2
+ export interface SetupPlan {
3
+ venvDir: string;
4
+ venvPython: string;
5
+ /** 用来建 venv 的解释器;null = 这台机器连可运行的 Python 都没有 */
6
+ creator: string | null;
7
+ recreate: boolean;
8
+ requirementFiles: string[];
9
+ /** 解析后的安装清单(注释/空行已去掉,win32 的替换已做) */
10
+ packages: string[];
11
+ /** 替换说明,如 `sqlcipher3 -> sqlcipher3-binary (Windows 预编译轮)` */
12
+ substitutions: string[];
13
+ createsUnder: '~/.weflow-cli/venv';
14
+ network: true;
15
+ }
16
+ export interface SetupStep {
17
+ name: string;
18
+ ok: boolean;
19
+ /** 一步的补充事实(版本号、跳过原因等),不放大段日志 */
20
+ detail?: string;
21
+ }
22
+ export interface SetupResult {
23
+ success: boolean;
24
+ steps: SetupStep[];
25
+ venvPython: string;
26
+ /** 安装完清缓存后 getPythonCommand() 的实际选择——应等于 venvPython */
27
+ effectivePython: string | null;
28
+ error?: string;
29
+ }
30
+ /** requirements 文件 → 去注释/空行的依赖列表。 */
31
+ export declare function parseRequirements(text: string): string[];
32
+ /** win32 下把源码包换成预编译轮;其余平台原样。 */
33
+ export declare function resolvePackages(names: string[], platform: string): {
34
+ packages: string[];
35
+ substitutions: string[];
36
+ };
37
+ export declare function planSetup(opts?: {
38
+ recreate?: boolean;
39
+ withVoice?: boolean;
40
+ with3x?: boolean;
41
+ }): Promise<SetupPlan>;
42
+ export declare function runSetup(plan: SetupPlan, onLine?: (line: string) => void): Promise<SetupResult>;
43
+ //# sourceMappingURL=setupVenv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupVenv.d.ts","sourceRoot":"","sources":["../../../src/services/setupVenv.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,QAAQ,QAAyC,CAAA;AAE9D,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,gDAAgD;IAChD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,OAAO,CAAA;IACjB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,qCAAqC;IACrC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,YAAY,EAAE,oBAAoB,CAAA;IAClC,OAAO,EAAE,IAAI,CAAA;CACd;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,OAAO,CAAA;IACX,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,uDAAuD;IACvD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,qCAAqC;AACrC,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAKxD;AAED,gCAAgC;AAChC,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CAUlH;AAsBD,wBAAsB,SAAS,CAAC,IAAI,GAAE;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;CACZ,GAAG,OAAO,CAAC,SAAS,CAAC,CA2B1B;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CA2GrG"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * `weflow-cli setup` —— 自管 Python venv。
3
+ *
4
+ * Issues 里最大的两类环境噪音:PowerShell 执行策略拦 `.ps1`(.cmd 包装绕开),
5
+ * 和 PATH 上只有微软商店的 python 占位程序(一跑 exit 9009,`getPythonCommand()`
6
+ * 兜底返回裸名 `python` 时正好交给它)。后者真正的根因是"这台机器没有一个能
7
+ * `import sqlcipher3` 的 Python"——本命令一次性解决:在 `~/.weflow-cli/venv`
8
+ * 建一个 venv、装上 requirements,之后 `getPythonCommand()` 优先用它。
9
+ *
10
+ * Windows 上 `sqlcipher3` 被替换为 `sqlcipher3-wheels`(预编译轮,import 名
11
+ * 相同):源码包要 OpenSSL 头文件 + MSVC,正是要消掉的那类支持负担。替换会
12
+ * 写进计划与输出,不藏在背后。
13
+ */
14
+ import { execFile } from 'child_process';
15
+ import { promisify } from 'util';
16
+ import { existsSync, readFileSync, rmSync } from 'fs';
17
+ import { basename, join } from 'path';
18
+ import { homedir } from 'os';
19
+ import { resolvePackageRoot } from '../utils/packageRoot.js';
20
+ import { clearPythonCommandCache, getPythonCommand } from '../utils/python.js';
21
+ const execFileAsync = promisify(execFile);
22
+ export const VENV_DIR = join(homedir(), '.weflow-cli', 'venv');
23
+ /** requirements 文件 → 去注释/空行的依赖列表。 */
24
+ export function parseRequirements(text) {
25
+ return text
26
+ .split('\n')
27
+ .map(line => line.trim())
28
+ .filter(line => line && !line.startsWith('#'));
29
+ }
30
+ /** win32 下把源码包换成预编译轮;其余平台原样。 */
31
+ export function resolvePackages(names, platform) {
32
+ if (platform !== 'win32')
33
+ return { packages: [...names], substitutions: [] };
34
+ // Windows 上的预编译轮是 `sqlcipher3-wheels`(cp310+ 的 win32/amd64/arm64 都有)。
35
+ // `sqlcipher3-binary` 只有 Linux/macOS 轮——CI 的 ubuntu 能装它,Windows 上
36
+ // pip 直接报 "No matching distribution"(2026-10-23 实测)。
37
+ const packages = names.map(n => (n === 'sqlcipher3' ? 'sqlcipher3-wheels' : n));
38
+ const substitutions = packages.some(p => p === 'sqlcipher3-wheels') && names.some(n => n === 'sqlcipher3')
39
+ ? ['sqlcipher3 -> sqlcipher3-wheels (Windows 预编译轮,import 名相同;源码包要 OpenSSL 头文件 + MSVC)']
40
+ : [];
41
+ return { packages, substitutions };
42
+ }
43
+ /**
44
+ * 建一个"能用来创建 venv"的解释器探测:PATH 上的 python/py 逐个 `--version`。
45
+ * 商店占位程序在这一步就会被排掉(`--version` 以 9009 退出)。
46
+ */
47
+ async function findCreator() {
48
+ const names = process.platform === 'win32'
49
+ ? ['python', 'python3', 'py']
50
+ : ['python3', 'python'];
51
+ for (const name of names) {
52
+ try {
53
+ const { stdout } = await execFileAsync(name, ['--version'], { windowsHide: true, timeout: 10_000 });
54
+ const version = stdout.trim().split('\n')[0] || null;
55
+ return { creator: name, version };
56
+ }
57
+ catch {
58
+ // 这个名字跑不起来(商店占位程序 9009 也会落到这里),试下一个
59
+ }
60
+ }
61
+ return { creator: null, version: null };
62
+ }
63
+ export async function planSetup(opts = {}) {
64
+ const pkgRoot = resolvePackageRoot(import.meta.url);
65
+ const files = ['requirements.txt'];
66
+ if (opts.with3x)
67
+ files.push('requirements-3x.txt');
68
+ if (opts.withVoice)
69
+ files.push('requirements-voice.txt');
70
+ const names = [];
71
+ for (const f of files) {
72
+ names.push(...parseRequirements(readFileSync(join(pkgRoot, f), 'utf-8')));
73
+ }
74
+ const { packages, substitutions } = resolvePackages([...new Set(names)], process.platform);
75
+ const { creator } = await findCreator();
76
+ const venvPython = process.platform === 'win32'
77
+ ? join(VENV_DIR, 'Scripts', 'python.exe')
78
+ : join(VENV_DIR, 'bin', 'python');
79
+ return {
80
+ venvDir: VENV_DIR,
81
+ venvPython,
82
+ creator,
83
+ recreate: !!opts.recreate,
84
+ requirementFiles: files,
85
+ packages,
86
+ substitutions,
87
+ createsUnder: '~/.weflow-cli/venv',
88
+ network: true,
89
+ };
90
+ }
91
+ export async function runSetup(plan, onLine) {
92
+ const steps = [];
93
+ const say = (line) => onLine?.(line);
94
+ if (!plan.creator) {
95
+ return {
96
+ success: false,
97
+ steps: [{ name: 'find-python', ok: false, detail: 'PATH 上没有可运行的 Python(商店占位程序不算)——先装一个真正的 Python 3.10+ 再运行 setup' }],
98
+ venvPython: plan.venvPython,
99
+ effectivePython: null,
100
+ error: 'NO_USABLE_PYTHON',
101
+ };
102
+ }
103
+ // 1. 重建或创建 venv
104
+ if (plan.recreate && existsSync(plan.venvDir)) {
105
+ rmSync(plan.venvDir, { recursive: true, force: true });
106
+ steps.push({ name: 'remove-existing-venv', ok: true, detail: basename(plan.venvDir) });
107
+ say(`已删除旧 venv: ${plan.venvDir}`);
108
+ }
109
+ if (!existsSync(plan.venvDir)) {
110
+ try {
111
+ await execFileAsync(plan.creator, ['-m', 'venv', plan.venvDir], { windowsHide: true, timeout: 180_000 });
112
+ steps.push({ name: 'create-venv', ok: true, detail: `由 ${plan.creator} 创建` });
113
+ say(`已创建 venv: ${plan.venvDir}`);
114
+ }
115
+ catch (e) {
116
+ return {
117
+ success: false,
118
+ steps: [...steps, { name: 'create-venv', ok: false, detail: String(e?.message || e).slice(0, 200) }],
119
+ venvPython: plan.venvPython,
120
+ effectivePython: null,
121
+ error: 'VENV_CREATE_FAILED',
122
+ };
123
+ }
124
+ }
125
+ else {
126
+ steps.push({ name: 'create-venv', ok: true, detail: '已存在,跳过(--recreate 可重建)' });
127
+ }
128
+ // 2. 装依赖(走 venv 自己的 pip;PyPI 网络请求就是这一步)。
129
+ // 失败重试一次:PyPI 的瞬时网络错误(本机 2026-10-23 实测过一次整批失败、
130
+ // 逐包重装全过)不值得让用户从头再来——重试前说一声。
131
+ const pipArgs = ['-m', 'pip', 'install', '--disable-pip-version-check', ...plan.packages];
132
+ const pipDetail = (e) => {
133
+ const err = e;
134
+ const tail = (err?.stderr || '').split('\n').map(l => l.trim()).filter(Boolean).slice(-3).join(' | ');
135
+ return (tail || String(err?.message || e)).slice(0, 300);
136
+ };
137
+ let installed = false;
138
+ let pipError = null;
139
+ for (let attempt = 1; attempt <= 2 && !installed; attempt++) {
140
+ try {
141
+ say(attempt === 1
142
+ ? `安装 ${plan.packages.length} 个包(来自 ${plan.requirementFiles.join('、')})...`
143
+ : `重试安装(第 1 次失败:${pipDetail(pipError)})...`);
144
+ await execFileAsync(plan.venvPython, pipArgs, {
145
+ windowsHide: true,
146
+ timeout: 600_000,
147
+ maxBuffer: 10 * 1024 * 1024,
148
+ });
149
+ installed = true;
150
+ }
151
+ catch (e) {
152
+ pipError = e;
153
+ }
154
+ }
155
+ if (!installed) {
156
+ return {
157
+ success: false,
158
+ steps: [...steps, { name: 'pip-install', ok: false, detail: pipDetail(pipError) }],
159
+ venvPython: plan.venvPython,
160
+ effectivePython: null,
161
+ error: 'PIP_INSTALL_FAILED',
162
+ };
163
+ }
164
+ steps.push({ name: 'pip-install', ok: true, detail: `${plan.packages.length} 个包(${plan.requirementFiles.join('、')})` });
165
+ for (const s of plan.substitutions)
166
+ say(` 替换: ${s}`);
167
+ // 3. 验收:venv 里真能 import sqlcipher3(NT 解密的核心依赖)
168
+ let verified = false;
169
+ try {
170
+ await execFileAsync(plan.venvPython, ['-c', 'import sqlcipher3'], { windowsHide: true, timeout: 30_000 });
171
+ verified = true;
172
+ }
173
+ catch {
174
+ verified = false;
175
+ }
176
+ steps.push({
177
+ name: 'verify-sqlcipher3',
178
+ ok: verified,
179
+ detail: verified ? 'import sqlcipher3 通过' : 'import sqlcipher3 失败——pip 报成功但模块不可用,把上面 pip 的完整输出贴到 issue',
180
+ });
181
+ // 4. 确认运行时真的会选它(清掉模块级缓存再看选择)
182
+ clearPythonCommandCache();
183
+ const effective = getPythonCommand();
184
+ const wiringOk = existsSync(plan.venvPython) && effective === plan.venvPython;
185
+ steps.push({
186
+ name: 'runtime-prefers-venv',
187
+ ok: wiringOk,
188
+ detail: wiringOk ? 'getPythonCommand() 已指向自管 venv' : `getPythonCommand() 选了 ${effective}——venv 未通过探测(sqlcipher3 不可用时按原顺序回退 PATH)`,
189
+ });
190
+ return {
191
+ success: steps.every(s => s.ok),
192
+ steps,
193
+ venvPython: plan.venvPython,
194
+ effectivePython: effective,
195
+ ...(verified && !wiringOk ? { error: 'VENV_NOT_PREFERRED' } : {}),
196
+ };
197
+ }
198
+ //# sourceMappingURL=setupVenv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupVenv.js","sourceRoot":"","sources":["../../../src/services/setupVenv.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,12 @@
1
+ /** `weflow-cli setup` 建的自管 venv 的解释器路径;没建过就是 null。 */
2
+ export declare function managedVenvPython(): string | null;
3
+ /**
4
+ * 候选序:自管 venv 永远排最前,其余按调用方给的序。纯函数,供测试钉住
5
+ * "建了 venv 就该优先用它"这件事——它坏了的表现是 setup 装好了包、
6
+ * 运行时却仍在用 PATH 上的解释器,两边各自"正常"。
7
+ */
8
+ export declare function orderCandidates(managed: string | null, rest: string[]): string[];
1
9
  export declare function getPythonCommand(): string;
10
+ /** setup 装完后清缓存,让同一进程里后续的 getPythonCommand 看见新 venv。 */
11
+ export declare function clearPythonCommandCache(): void;
2
12
  //# sourceMappingURL=python.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/utils/python.ts"],"names":[],"mappings":"AAqEA,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC"}
1
+ {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/utils/python.ts"],"names":[],"mappings":"AAoBA,sDAAsD;AACtD,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAKjD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,IAAI,EAAE,MAAM,EAAE,GACb,MAAM,EAAE,CAEV;AAuDD,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC;AAED,wDAAwD;AACxD,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
@@ -1,6 +1,7 @@
1
1
  import { execFileSync } from 'child_process';
2
2
  import { delimiter, join } from 'path';
3
- import { accessSync, constants } from 'fs';
3
+ import { accessSync, constants, existsSync } from 'fs';
4
+ import { homedir } from 'os';
4
5
  let cached = null;
5
6
  const EXE_NAMES = process.platform === 'win32'
6
7
  ? ['python.exe', 'python3.exe', 'py.exe']
@@ -14,6 +15,21 @@ function isExecutable(path) {
14
15
  return false;
15
16
  }
16
17
  }
18
+ /** `weflow-cli setup` 建的自管 venv 的解释器路径;没建过就是 null。 */
19
+ export function managedVenvPython() {
20
+ const exe = process.platform === 'win32'
21
+ ? join(homedir(), '.weflow-cli', 'venv', 'Scripts', 'python.exe')
22
+ : join(homedir(), '.weflow-cli', 'venv', 'bin', 'python');
23
+ return existsSync(exe) ? exe : null;
24
+ }
25
+ /**
26
+ * 候选序:自管 venv 永远排最前,其余按调用方给的序。纯函数,供测试钉住
27
+ * "建了 venv 就该优先用它"这件事——它坏了的表现是 setup 装好了包、
28
+ * 运行时却仍在用 PATH 上的解释器,两边各自"正常"。
29
+ */
30
+ export function orderCandidates(managed, rest) {
31
+ return managed ? [managed, ...rest.filter(c => c !== managed)] : [...rest];
32
+ }
17
33
  /** 按顺序返回 PATH 中所有可用的 Python 解释器(含命令名候选) */
18
34
  function candidates() {
19
35
  const found = [];
@@ -52,14 +68,17 @@ function hasSqlcipher(cmd) {
52
68
  }
53
69
  }
54
70
  function detect() {
71
+ // 自管 venv(`weflow-cli setup`)优先:它就是为了"这台机器有一个能
72
+ // import sqlcipher3 的 Python"而存在的。venv 坏了(装完又被卸了包)会
73
+ // 自然落到下面的 PATH 候选——行为退回 setup 之前,而不是更糟。
74
+ const ordered = orderCandidates(managedVenvPython(), candidates());
55
75
  // 优先选择能 import sqlcipher3 的解释器(NT 解密核心依赖),
56
76
  // 避免命中 PATH 中仅有基础库的裸 Python 环境(如被 IDE 注入的 VM Python 抢占)。
57
- const list = candidates();
58
- for (const cmd of list) {
77
+ for (const cmd of ordered) {
59
78
  if (canRun(cmd) && hasSqlcipher(cmd))
60
79
  return cmd;
61
80
  }
62
- for (const cmd of list) {
81
+ for (const cmd of ordered) {
63
82
  if (canRun(cmd))
64
83
  return cmd;
65
84
  }
@@ -69,4 +88,8 @@ export function getPythonCommand() {
69
88
  cached ??= detect();
70
89
  return cached;
71
90
  }
91
+ /** setup 装完后清缓存,让同一进程里后续的 getPythonCommand 看见新 venv。 */
92
+ export function clearPythonCommandCache() {
93
+ cached = null;
94
+ }
72
95
  //# sourceMappingURL=python.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"python.js","sourceRoot":"","sources":["../../../src/utils/python.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"python.js","sourceRoot":"","sources":["../../../src/utils/python.ts"],"names":[],"mappings":"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"}