@cloud411716/fancy-webnovel 0.1.75 → 0.1.77
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 +26 -7
- package/package.json +1 -1
- package/plugins/fancy-bootstrap/index.js +6 -2
- package/plugins/fancy-scan/index.js +3 -24
package/infra.js
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
* notify(session, text) — 打印消息给用户(不触发 LLM)
|
|
6
6
|
* llmFollowup(invocation, prompt) — 发送消息给 LLM,让 LLM 继续处理
|
|
7
7
|
* spawnScript(cmd, args, opts) — spawn 子进程,解析 stdout JSON
|
|
8
|
+
* startActivity(session) — 开始 Activity Line 计时,返回 stop 函数
|
|
8
9
|
*
|
|
9
10
|
* 所有 fancy-* 插件均直接 import 此文件。
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
|
-
//
|
|
13
|
+
// --------------------------------------------------------------------------
|
|
13
14
|
// notify — 打印消息给用户(queueMicrotask 避免打断 LLM 输出顺序)
|
|
14
|
-
//
|
|
15
|
+
// --------------------------------------------------------------------------
|
|
15
16
|
|
|
16
17
|
export function notify(session, text) {
|
|
17
18
|
queueMicrotask(() => {
|
|
@@ -25,7 +26,7 @@ export function notify(session, text) {
|
|
|
25
26
|
|
|
26
27
|
// --------------------------------------------------------------------------
|
|
27
28
|
// llmFollowup
|
|
28
|
-
//
|
|
29
|
+
// --------------------------------------------------------------------------
|
|
29
30
|
|
|
30
31
|
export function llmFollowup(invocation, content) {
|
|
31
32
|
const prompt = typeof content === 'string' ? content : JSON.stringify(content);
|
|
@@ -35,19 +36,37 @@ export function llmFollowup(invocation, content) {
|
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
//
|
|
39
|
+
// --------------------------------------------------------------------------
|
|
40
|
+
// startActivity — Activity Line 计时器(显示 Running… + 实时计时)
|
|
41
|
+
// 调用 startActivity() 返回 stop 函数,进入新阶段时先 stop 再 start
|
|
42
|
+
// --------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {import('@deepseek-ai/dsh-session').Session} session
|
|
46
|
+
* @returns {() => void} stop — 调用后停止计时
|
|
47
|
+
*/
|
|
48
|
+
export function startActivity(session) {
|
|
49
|
+
session.append('turn/start', { source: 'fancy-plugin' });
|
|
50
|
+
return () => session.append('turn/end', { source: 'fancy-plugin' });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// --------------------------------------------------------------------------
|
|
39
54
|
// spawnScript — spawn 子进程,stdout 只收集 JSON,stderr 单独收集
|
|
40
|
-
//
|
|
55
|
+
// opts.stop() 会在进程终止时自动调用(用于清理 turn/start)
|
|
56
|
+
// --------------------------------------------------------------------------
|
|
41
57
|
|
|
42
|
-
export function spawnScript(cmd, args, { timeout = 30000, cwd } = {}) {
|
|
58
|
+
export function spawnScript(cmd, args, { timeout = 30000, cwd, stop } = {}) {
|
|
43
59
|
return new Promise(async (resolve) => {
|
|
44
60
|
const { spawn } = await import('child_process');
|
|
45
61
|
const proc = spawn(cmd, args, { timeout, cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
46
62
|
const outParts = [], errParts = [];
|
|
47
63
|
proc.stdout.on('data', (d) => { outParts.push(d.toString()); });
|
|
48
64
|
proc.stderr.on('data', (d) => { errParts.push(d.toString()); });
|
|
65
|
+
|
|
66
|
+
const cleanup = () => { try { stop?.(); } catch (_) {} };
|
|
49
67
|
proc.on('close', (code) => {
|
|
50
68
|
const stdout = outParts.join(''), stderr = errParts.join('');
|
|
69
|
+
cleanup();
|
|
51
70
|
try {
|
|
52
71
|
const parsed = JSON.parse(stdout);
|
|
53
72
|
resolve({
|
|
@@ -63,6 +82,6 @@ export function spawnScript(cmd, args, { timeout = 30000, cwd } = {}) {
|
|
|
63
82
|
resolve({ ok: false, output: stdout, error: stderr || ('exit ' + code) });
|
|
64
83
|
}
|
|
65
84
|
});
|
|
66
|
-
proc.on('error', (err) => resolve({ ok: false, output: '', error: err.message }));
|
|
85
|
+
proc.on('error', (err) => { cleanup(); resolve({ ok: false, output: '', error: err.message }); });
|
|
67
86
|
});
|
|
68
87
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { dirname, join } from 'path';
|
|
6
6
|
import { existsSync } from 'fs';
|
|
7
|
-
import { notify, spawnScript } from '../../infra.js';
|
|
7
|
+
import { notify, spawnScript, startActivity } from '../../infra.js';
|
|
8
8
|
import { bootstrap } from './templates.js';
|
|
9
9
|
|
|
10
10
|
export const inject = ['commands', 'userQuestions'];
|
|
@@ -79,7 +79,11 @@ export async function apply(ctx) {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
notify(session, bootstrap.notify({ type: 'initializing', projectRoot }));
|
|
82
|
-
const
|
|
82
|
+
const stopActivity = startActivity(session);
|
|
83
|
+
const result = await spawnScript('node', [join(SCRIPTS_DIR, 'init.js'), projectRoot], {
|
|
84
|
+
timeout: 30000,
|
|
85
|
+
stop: stopActivity,
|
|
86
|
+
});
|
|
83
87
|
|
|
84
88
|
if (result.ok) {
|
|
85
89
|
notify(session, bootstrap.notify({ type: 'success' }));
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { dirname, join } from 'path';
|
|
6
6
|
import { existsSync } from 'fs';
|
|
7
|
-
import { notify, llmFollowup, spawnScript } from '../../infra.js';
|
|
7
|
+
import { notify, llmFollowup, spawnScript, startActivity } from '../../infra.js';
|
|
8
8
|
import { scan, PLATFORM_TABLE, platformLabel } from './templates.js';
|
|
9
9
|
|
|
10
10
|
export const inject = ['commands', 'userQuestions'];
|
|
@@ -20,23 +20,6 @@ export async function apply(ctx) {
|
|
|
20
20
|
const session = invocation.agent.session;
|
|
21
21
|
const rawInput = invocation.rawInput ? invocation.rawInput.trim() : '';
|
|
22
22
|
|
|
23
|
-
// ─── TEST: 验证直接用 invocation.agent.session 追加事件 ─────────────────
|
|
24
|
-
{
|
|
25
|
-
// invocation.agent.session 就是 Session 对象,直接 append
|
|
26
|
-
const s = invocation.agent.session;
|
|
27
|
-
notify(session, `[TEST] session.id = ${s?.id ?? 'UNDEFINED'}`);
|
|
28
|
-
if (s) {
|
|
29
|
-
// 追加一个 fake tool/call,看 status bar 是否出现进度
|
|
30
|
-
s.append('tool/call', {
|
|
31
|
-
callId: 'test-call-1',
|
|
32
|
-
name: 'fancy-scan/progress',
|
|
33
|
-
arguments: JSON.stringify({ platform: 'test', length: 'test' }),
|
|
34
|
-
});
|
|
35
|
-
notify(session, '[TEST] session.append(tool/call) 成功');
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// ─── TEST 结束 ───────────────────────────────────────────────────────
|
|
39
|
-
|
|
40
23
|
// 获取项目根
|
|
41
24
|
let projectRoot = rawInput ? rawInput.split(/\s+/)[0] : '';
|
|
42
25
|
if (!projectRoot) projectRoot = process.cwd();
|
|
@@ -109,18 +92,14 @@ export async function apply(ctx) {
|
|
|
109
92
|
|
|
110
93
|
notify(session, scan.notify({ type: 'collecting', platform, length }));
|
|
111
94
|
|
|
112
|
-
|
|
113
|
-
session.append('turn/start', { source: 'fancy-scan' });
|
|
114
|
-
|
|
95
|
+
const stopActivity = startActivity(session);
|
|
115
96
|
const scriptResult = await spawnScript(
|
|
116
97
|
'node',
|
|
117
98
|
[join(SCAN_SCRIPTS_DIR, 'run-scan.js'),
|
|
118
99
|
'--project-root', projectRoot, '--platform', platform, '--length', length],
|
|
119
|
-
{ timeout: 120000 }
|
|
100
|
+
{ timeout: 120000, stop: stopActivity }
|
|
120
101
|
);
|
|
121
102
|
|
|
122
|
-
session.append('turn/end', { source: 'fancy-scan' });
|
|
123
|
-
|
|
124
103
|
if (!scriptResult.ok) {
|
|
125
104
|
const err = (typeof scriptResult.error === 'object' && scriptResult.error !== null)
|
|
126
105
|
? (scriptResult.error.message || JSON.stringify(scriptResult.error))
|