weflow-cli 1.15.1 → 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.
- package/CHANGELOG.md +59 -1
- package/OPERATIONS.md +16 -1
- package/README.en.md +21 -2
- package/README.md +34 -6
- package/bin/weflow-cli.ts +389 -6
- package/dist/bin/weflow-cli.js +422 -8
- package/dist/bin/weflow-cli.js.map +1 -1
- package/dist/src/core/ntCore.d.ts +47 -0
- package/dist/src/core/ntCore.d.ts.map +1 -1
- package/dist/src/core/ntCore.js +24 -0
- package/dist/src/core/ntCore.js.map +1 -1
- package/dist/src/services/assistantService.d.ts +8 -1
- package/dist/src/services/assistantService.d.ts.map +1 -1
- package/dist/src/services/assistantService.js +47 -8
- package/dist/src/services/assistantService.js.map +1 -1
- package/dist/src/services/assistantTools.d.ts +8 -0
- package/dist/src/services/assistantTools.d.ts.map +1 -1
- package/dist/src/services/assistantTools.js +67 -11
- package/dist/src/services/assistantTools.js.map +1 -1
- package/dist/src/services/configService.d.ts.map +1 -1
- package/dist/src/services/configService.js +3 -2
- package/dist/src/services/configService.js.map +1 -1
- package/dist/src/services/cursorProbe.d.ts +44 -0
- package/dist/src/services/cursorProbe.d.ts.map +1 -0
- package/dist/src/services/cursorProbe.js +183 -0
- package/dist/src/services/cursorProbe.js.map +1 -0
- package/dist/src/services/qchatImport.d.ts +89 -0
- package/dist/src/services/qchatImport.d.ts.map +1 -0
- package/dist/src/services/qchatImport.js +273 -0
- package/dist/src/services/qchatImport.js.map +1 -0
- package/dist/src/services/setupVenv.d.ts +43 -0
- package/dist/src/services/setupVenv.d.ts.map +1 -0
- package/dist/src/services/setupVenv.js +198 -0
- package/dist/src/services/setupVenv.js.map +1 -0
- package/dist/src/utils/python.d.ts +10 -0
- package/dist/src/utils/python.d.ts.map +1 -1
- package/dist/src/utils/python.js +27 -4
- package/dist/src/utils/python.js.map +1 -1
- package/docs/DATA_CONTRACT.md +25 -0
- package/docs/DECISIONS.md +92 -30
- package/docs/FUNCTIONAL-IMPROVEMENT-SPEC.md +365 -365
- package/docs/HEALTH-CHECK.md +104 -104
- package/docs/JEV/345/272/224/347/224/250/346/226/275/345/267/245/346/226/207/346/241/243.md +310 -310
- package/docs/NEXT_ACTIONS.md +236 -236
- package/docs/NPM-PUBLISH.md +130 -130
- package/docs/POSITIONING.md +68 -68
- package/docs/PROJECT_STATE.md +6 -3
- package/docs/REPLAY.md +169 -0
- package/docs/SYNC_CONTRACT.md +197 -180
- package/package.json +89 -88
- package/requirements-3x.txt +4 -4
- package/requirements-voice.txt +15 -15
- package/resources/js/graph3d/NOTICE.txt +35 -35
- package/resources/js/graph3d/d3-binarytree.min.js +2 -2
- package/resources/js/graph3d/d3-dispatch.min.js +2 -2
- package/resources/js/graph3d/d3-force-3d.min.js +2 -2
- package/resources/js/graph3d/d3-octree.min.js +2 -2
- package/resources/js/graph3d/d3-quadtree.min.js +2 -2
- package/resources/js/graph3d/d3-timer.min.js +2 -2
- package/resources/js/graph3d/three.min.js +6 -6
- package/resources/js/graph3d/viewer2d.js +550 -448
- package/resources/panel/quick-menu.cjs +197 -197
- package/scripts/_utils.py +1338 -1338
- package/scripts/article_notes.py +423 -423
- package/scripts/bonds.py +11 -0
- package/scripts/chat_notes.py +86 -3
- package/scripts/check_readme_commands.py +427 -426
- package/scripts/contact_schema.py +339 -339
- package/scripts/create_reading_notes.py +11 -11
- package/scripts/daily_task.ps1 +213 -177
- package/scripts/fav_notes.py +321 -321
- package/scripts/graph_2d.py +156 -151
- package/scripts/graph_3d.py +672 -646
- package/scripts/health_check.py +473 -473
- package/scripts/imported_chats.py +68 -0
- package/scripts/install_tasks.ps1 +105 -91
- package/scripts/leads.py +179 -0
- package/scripts/network.py +206 -206
- package/scripts/nt_decrypt.py +135 -1
- package/scripts/on_this_day.py +178 -178
- package/scripts/opinion_timeline.py +138 -138
- package/scripts/promises.py +185 -185
- package/scripts/replay.py +803 -0
- package/scripts/run_hidden.vbs +25 -0
- package/scripts/semantic_search.py +73 -5
- package/scripts/user_notes.py +315 -315
- package/scripts/voice_transcribe.py +139 -139
- package/scripts/watch_issues.py +212 -212
- package/scripts/watch_mail.py +131 -131
- package/src/core/ntCore.ts +59 -0
- package/src/services/assistantService.ts +48 -8
- package/src/services/assistantTools.ts +73 -10
- package/src/services/configService.ts +3 -2
- package/src/services/cursorProbe.ts +222 -0
- package/src/services/qchatImport.ts +327 -0
- package/src/services/setupVenv.ts +238 -0
- package/src/services/syncService.ts +363 -363
- package/src/services/syncState.ts +275 -275
- package/src/services/wechatMedia.ts +166 -166
- 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":"
|
|
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"}
|
package/dist/src/utils/python.js
CHANGED
|
@@ -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
|
|
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
|
|
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":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"python.js","sourceRoot":"","sources":["../../../src/utils/python.ts"],"names":[],"mappings":"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"}
|