@cloud411716/fancy-webnovel 0.2.0 → 0.2.2
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/infra.js
CHANGED
|
@@ -101,18 +101,28 @@ export function onUserCancel(session, onCancel) {
|
|
|
101
101
|
export function spawnScript(cmd, args, { timeout = 30000, cwd, stop } = {}) {
|
|
102
102
|
return new Promise(async (resolve) => {
|
|
103
103
|
const { spawn } = await import('child_process');
|
|
104
|
-
const proc = spawn(cmd, args, {
|
|
104
|
+
const proc = spawn(cmd, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
105
105
|
const outParts = [], errParts = [];
|
|
106
|
+
let settled = false;
|
|
107
|
+
const settle = (v) => { if (!settled) { settled = true; resolve(v); } };
|
|
108
|
+
|
|
109
|
+
const timer = timeout > 0 ? setTimeout(() => {
|
|
110
|
+
proc.kill('SIGTERM');
|
|
111
|
+
settle({ ok: false, output: outParts.join(''), error: 'timeout after ' + timeout + 'ms' });
|
|
112
|
+
}, timeout) : null;
|
|
113
|
+
|
|
106
114
|
proc.stdout.on('data', (d) => { outParts.push(d.toString()); });
|
|
107
115
|
proc.stderr.on('data', (d) => { errParts.push(d.toString()); });
|
|
108
116
|
|
|
109
117
|
const cleanup = () => { try { stop?.(); } catch (_) {} };
|
|
110
118
|
proc.on('close', (code) => {
|
|
111
|
-
|
|
119
|
+
clearTimeout(timer);
|
|
112
120
|
cleanup();
|
|
121
|
+
if (settled) return;
|
|
122
|
+
const stdout = outParts.join(''), stderr = errParts.join('');
|
|
113
123
|
try {
|
|
114
124
|
const parsed = JSON.parse(stdout);
|
|
115
|
-
|
|
125
|
+
settle({
|
|
116
126
|
ok: parsed.ok === true,
|
|
117
127
|
output: stdout,
|
|
118
128
|
error: parsed.error
|
|
@@ -122,9 +132,9 @@ export function spawnScript(cmd, args, { timeout = 30000, cwd, stop } = {}) {
|
|
|
122
132
|
: stderr || undefined,
|
|
123
133
|
});
|
|
124
134
|
} catch (_) {
|
|
125
|
-
|
|
135
|
+
settle({ ok: false, output: stdout, error: stderr || ('exit ' + code) });
|
|
126
136
|
}
|
|
127
137
|
});
|
|
128
|
-
proc.on('error', (err) => { cleanup();
|
|
138
|
+
proc.on('error', (err) => { clearTimeout(timer); cleanup(); settle({ ok: false, output: '', error: err.message }); });
|
|
129
139
|
});
|
|
130
140
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloud411716/fancy-webnovel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"plugins/"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"playwright-core": "
|
|
17
|
+
"playwright-core": "1.48.0"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* fancy-bootstrap init — 项目初始化
|
|
3
3
|
*/
|
|
4
|
-
import { writeFileSync, mkdirSync, existsSync
|
|
4
|
+
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
5
5
|
import { expandHome, resolvePath, joinPath } from './path-utils.js';
|
|
6
6
|
|
|
7
7
|
const DIRS = [
|
|
@@ -27,10 +27,7 @@ function nowIso() {
|
|
|
27
27
|
function main() {
|
|
28
28
|
const projectRootRaw = process.argv[2] ?? '';
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
try { appendFileSync('/tmp/fancy-init-debug.txt', `argv=${JSON.stringify(process.argv)}\nraw=${projectRootRaw}\n`); } catch(e) {}
|
|
32
|
-
|
|
33
|
-
if (projectRootRaw.includes('..') || /[<>:"'|?*]/.test(projectRootRaw) || /[\x00-\x1f]/.test(projectRootRaw)) {
|
|
30
|
+
if (projectRootRaw.includes('..') || /[<>:\"'|?*]/.test(projectRootRaw) || /[\x00-\x1f]/.test(projectRootRaw)) {
|
|
34
31
|
console.log(JSON.stringify({ ok: false, error: { code: 1, code_name: 'EC001', message: '路径不合法' } }));
|
|
35
32
|
process.exit(1);
|
|
36
33
|
}
|
|
@@ -99,7 +96,6 @@ function main() {
|
|
|
99
96
|
|
|
100
97
|
} catch (e) {
|
|
101
98
|
const errMsg = e instanceof Error ? e.message : String(e);
|
|
102
|
-
try { appendFileSync('/tmp/fancy-init-debug.txt', `catch: ${errMsg}\n`); } catch(_) {}
|
|
103
99
|
console.log(JSON.stringify({ ok: false, error: { code: 17, code_name: 'EC017', message: `初始化失败: ${errMsg}` } }));
|
|
104
100
|
process.exit(17);
|
|
105
101
|
}
|
|
@@ -150,7 +150,7 @@ async function runScanWithChromiumFix(ctx, session, invocation, { platform, leng
|
|
|
150
150
|
notify(session,
|
|
151
151
|
'⚠️ 未找到 Chromium 浏览器,请手动安装后再次运行 /fancy-scan。\n\n' +
|
|
152
152
|
'安装命令:\n' +
|
|
153
|
-
' npm install -g playwright@1.
|
|
153
|
+
' npm install -g playwright@1.48.0 --registry=https://registry.npmmirror.com\n' +
|
|
154
154
|
' PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright/ playwright install chromium --with-deps\n\n' +
|
|
155
155
|
'安装完成后重新运行 /fancy-scan 即可。'
|
|
156
156
|
);
|
|
@@ -43,24 +43,13 @@ export const scan = {
|
|
|
43
43
|
question: `${platformLabel(platform)} 同时支持长篇和短篇,请选择:`,
|
|
44
44
|
hideCustomInput: true,
|
|
45
45
|
options: [
|
|
46
|
-
{ label: '长篇'
|
|
47
|
-
{ label: '短篇'
|
|
46
|
+
{ label: '长篇' },
|
|
47
|
+
{ label: '短篇' },
|
|
48
48
|
],
|
|
49
49
|
};
|
|
50
50
|
},
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
question: '⚠️ 未检测到 Chromium 浏览器,请选择处理方式:',
|
|
55
|
-
hideCustomInput: true,
|
|
56
|
-
options: [
|
|
57
|
-
{ label: '自动安装', description: '下载 Chromium 到 ~/.cache/ms-playwright/(需要网络,首次约 2-3 分钟)' },
|
|
58
|
-
{ label: '我自己安装', description: '手动安装后再次运行 /fancy-scan' },
|
|
59
|
-
],
|
|
60
|
-
};
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
notify({ type, platform, length, files, receipt, topicFile, projectRoot, err }) {
|
|
52
|
+
notify({ type, platform, length, files, topicFile, projectRoot, err }) {
|
|
64
53
|
const lenStr = length === 'long' ? '长篇' : '短篇';
|
|
65
54
|
const pLabel = platformLabel(platform);
|
|
66
55
|
|
|
@@ -77,14 +66,6 @@ export const scan = {
|
|
|
77
66
|
case 'cancelled_with_hint':
|
|
78
67
|
return '⚠️ 已取消。请再次调用 /fancy-scan 继续。';
|
|
79
68
|
|
|
80
|
-
case 'collecting':
|
|
81
|
-
return `⏳ 开始采集 ${pLabel}(${lenStr})...`;
|
|
82
|
-
|
|
83
|
-
case 'scan_complete':
|
|
84
|
-
if (!files || files.length === 0) return `✅ ${pLabel}(${lenStr})采集完成`;
|
|
85
|
-
const fileList = files.map(f => ' - ' + f.replace(projectRoot + '/', '')).join('\n');
|
|
86
|
-
return `✅ ${pLabel}(${lenStr})采集完成\n\n📁 生成文件:\n${fileList}`;
|
|
87
|
-
|
|
88
69
|
case 'failed':
|
|
89
70
|
return '❌ 采集失败:' + err;
|
|
90
71
|
|