@cloud411716/fancy-webnovel 1.0.16 → 1.0.18
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/commands/bootstrap/index.js +3 -3
- package/commands/scan/index.js +3 -3
- package/index.js +5 -66
- package/infra.js +49 -5
- package/package.json +1 -1
- package/events.js +0 -19
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { existsSync } from 'fs';
|
|
9
9
|
import { join } from 'path';
|
|
10
|
-
import { notify } from '../../infra.js';
|
|
10
|
+
import { notify, askWithoutAcknowledgement } from '../../infra.js';
|
|
11
11
|
import { initProject } from './init-project.js';
|
|
12
12
|
|
|
13
13
|
// inject is declared in the root index.js; only apply() is imported by index.js
|
|
@@ -76,7 +76,7 @@ export function apply(ctx) {
|
|
|
76
76
|
let projectRoot = rawInput;
|
|
77
77
|
|
|
78
78
|
if (!projectRoot) {
|
|
79
|
-
const result = await ctx
|
|
79
|
+
const result = await askWithoutAcknowledgement(ctx, session, {
|
|
80
80
|
questions: [bootstrap.askPath()],
|
|
81
81
|
signal,
|
|
82
82
|
});
|
|
@@ -104,7 +104,7 @@ export function apply(ctx) {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
// ---------- confirm ----------
|
|
107
|
-
const confirm = await ctx
|
|
107
|
+
const confirm = await askWithoutAcknowledgement(ctx, session, {
|
|
108
108
|
questions: [{
|
|
109
109
|
id: 'confirm',
|
|
110
110
|
question: bootstrap.notify({ type: 'confirm', projectRoot }),
|
package/commands/scan/index.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { existsSync } from 'fs';
|
|
9
9
|
import { join } from 'path';
|
|
10
|
-
import { notify, llmFollowup, StatusLine } from '../../infra.js';
|
|
10
|
+
import { notify, llmFollowup, StatusLine, askWithoutAcknowledgement } from '../../infra.js';
|
|
11
11
|
import { runScans } from './scraper.js';
|
|
12
12
|
import * as qidian from './platforms/qidian.js';
|
|
13
13
|
import * as fanqie from './platforms/fanqie.js';
|
|
@@ -135,7 +135,7 @@ export function apply(ctx) {
|
|
|
135
135
|
// ---------- platform selection ----------
|
|
136
136
|
notify(session, scan.platformList());
|
|
137
137
|
|
|
138
|
-
const platformResult = await ctx
|
|
138
|
+
const platformResult = await askWithoutAcknowledgement(ctx, session, {
|
|
139
139
|
questions: [scan.askPlatform()],
|
|
140
140
|
signal,
|
|
141
141
|
});
|
|
@@ -153,7 +153,7 @@ export function apply(ctx) {
|
|
|
153
153
|
const platform = row[1];
|
|
154
154
|
|
|
155
155
|
// ---------- rank selection (multi-select) ----------
|
|
156
|
-
const rankResult = await ctx
|
|
156
|
+
const rankResult = await askWithoutAcknowledgement(ctx, session, {
|
|
157
157
|
questions: [scan.askRankList(platform)],
|
|
158
158
|
signal,
|
|
159
159
|
});
|
package/index.js
CHANGED
|
@@ -12,8 +12,10 @@
|
|
|
12
12
|
* - HTTP fetching uses Node.js native fetch (portable across all DSH UIs).
|
|
13
13
|
* - File operations use Node.js fs (project roots may be outside workspace).
|
|
14
14
|
* - ctx.timer (via ctx.timeout()) handles all delays/timeouts.
|
|
15
|
+
* - askWithoutAcknowledgement() wraps ctx.userQuestions.ask() to suppress
|
|
16
|
+
* the DSH "问卷已答" tool-result acknowledgement.
|
|
15
17
|
*
|
|
16
|
-
* Required Cordis services: commands, userQuestions, timer
|
|
18
|
+
* Required Cordis services: commands, userQuestions, timer
|
|
17
19
|
* (all are part of dsh-base, so this plugin works on dsh-tui, dsh-web, dsh-desktop).
|
|
18
20
|
*
|
|
19
21
|
* IMPORTANT: This plugin needs `danger-full-access` sandbox mode because it
|
|
@@ -21,9 +23,6 @@
|
|
|
21
23
|
* specifies). Declare this in the profile's cordis.patch.yml.
|
|
22
24
|
*/
|
|
23
25
|
|
|
24
|
-
import './events.js'; // documents fancy/scan:* event types (JSDoc, no runtime effect)
|
|
25
|
-
|
|
26
|
-
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
27
26
|
import { apply as applyBootstrap } from './commands/bootstrap/index.js';
|
|
28
27
|
import { apply as applyScan } from './commands/scan/index.js';
|
|
29
28
|
|
|
@@ -31,75 +30,15 @@ import { apply as applyScan } from './commands/scan/index.js';
|
|
|
31
30
|
* Services this plugin requires from the Cordis context.
|
|
32
31
|
* All are provided by dsh-base, so this works on every DSH UI.
|
|
33
32
|
*/
|
|
34
|
-
export const inject = ['commands', 'userQuestions', 'timer'
|
|
33
|
+
export const inject = ['commands', 'userQuestions', 'timer'];
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
36
|
* Called once when the plugin is loaded into a Cordis context (fiber).
|
|
38
|
-
* Registers slash commands
|
|
39
|
-
* to suppress the "问卷已答" tool-result message.
|
|
37
|
+
* Registers slash commands; actual logic lives in per-command modules.
|
|
40
38
|
*
|
|
41
39
|
* @param {object} ctx - Cordis plugin context
|
|
42
40
|
*/
|
|
43
41
|
export function apply(ctx) {
|
|
44
|
-
// Override the builtin ask_user_question tool so it returns null instead
|
|
45
|
-
// of { answers: [...] }, preventing DSH from appending a tool/result event
|
|
46
|
-
// (which renders as "问卷已答" in the web UI). ctx.userQuestions.ask()
|
|
47
|
-
// still works normally — only the tool result acknowledgement is suppressed.
|
|
48
|
-
ctx.tools.register(defineTool({
|
|
49
|
-
name: 'ask_user_question',
|
|
50
|
-
description: 'Ask the user a concise question when you need confirmation, a choice, or missing information before proceeding. Send one or more questions, each with a stable id that will be echoed in the answer.',
|
|
51
|
-
parameters: {
|
|
52
|
-
questions: {
|
|
53
|
-
type: 'array',
|
|
54
|
-
required: true,
|
|
55
|
-
description: 'Questions to ask the user before continuing.',
|
|
56
|
-
items: {
|
|
57
|
-
type: 'object',
|
|
58
|
-
additionalProperties: true,
|
|
59
|
-
properties: {
|
|
60
|
-
id: { type: 'string', required: true, description: 'Stable id for this question; echoed in the answer.' },
|
|
61
|
-
question: { type: 'string', required: true, description: 'The specific question to ask the user.' },
|
|
62
|
-
header: { type: 'string', description: 'Optional short heading for the question.' },
|
|
63
|
-
options: {
|
|
64
|
-
type: 'array',
|
|
65
|
-
description: 'Optional choices to show the user.',
|
|
66
|
-
items: {
|
|
67
|
-
type: 'object',
|
|
68
|
-
additionalProperties: true,
|
|
69
|
-
properties: {
|
|
70
|
-
label: { type: 'string', required: true, description: 'Short user-facing option label.' },
|
|
71
|
-
description: { type: 'string', description: 'One sentence explaining the option.' },
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
multi_select: { type: 'boolean' },
|
|
76
|
-
hideCustomInput: { type: 'boolean' },
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
output: {
|
|
82
|
-
schema: { type: 'null' },
|
|
83
|
-
render() { return []; },
|
|
84
|
-
},
|
|
85
|
-
async execute(args, exec) {
|
|
86
|
-
await ctx.userQuestions.ask({
|
|
87
|
-
questions: args.questions.map((q) => ({
|
|
88
|
-
id: q.id,
|
|
89
|
-
question: q.question,
|
|
90
|
-
...q.header !== undefined ? { header: q.header } : {},
|
|
91
|
-
...q.options !== undefined ? { options: q.options } : {},
|
|
92
|
-
...q.multi_select !== undefined ? { multiSelect: q.multi_select } : {},
|
|
93
|
-
...q.hideCustomInput !== undefined ? { hideCustomInput: q.hideCustomInput } : {},
|
|
94
|
-
})),
|
|
95
|
-
...exec.agent !== undefined ? { agent: exec.agent } : {},
|
|
96
|
-
signal: exec.signal,
|
|
97
|
-
});
|
|
98
|
-
// Return null to suppress the tool-result acknowledgement ("问卷已答").
|
|
99
|
-
return null;
|
|
100
|
-
},
|
|
101
|
-
}));
|
|
102
|
-
|
|
103
42
|
applyBootstrap(ctx);
|
|
104
43
|
applyScan(ctx);
|
|
105
44
|
}
|
package/infra.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
* infra.js — DSH Plugin Core Infrastructure
|
|
3
3
|
*
|
|
4
4
|
* Provides:
|
|
5
|
-
* notify(session, text)
|
|
6
|
-
* llmFollowup(invocation,prompt)— hand a prompt to the LLM as a user message
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* notify(session, text) — append a user-facing message to the session log
|
|
6
|
+
* llmFollowup(invocation,prompt) — hand a prompt to the LLM as a user message
|
|
7
|
+
* askWithoutAcknowledgement(ctx, session, options) — ctx.userQuestions.ask() wrapper
|
|
8
|
+
* that suppresses the DSH "问卷已答" tool-result acknowledgement
|
|
9
|
+
* StatusLine(session) — in-place updatable status bar via surfaceOp replace
|
|
10
|
+
* scanProgress(ctx, phase, data) — emit structured scan progress events
|
|
11
|
+
* sleep(ctx, ms) — DSH-native promise delay via ctx.timeout()
|
|
10
12
|
*
|
|
11
13
|
* All fancy-* plugins import from this file.
|
|
12
14
|
*/
|
|
@@ -32,6 +34,48 @@ export function notify(session, text) {
|
|
|
32
34
|
);
|
|
33
35
|
}
|
|
34
36
|
|
|
37
|
+
// --------------------------------------------------------------------------
|
|
38
|
+
// askWithoutAcknowledgement — ctx.userQuestions.ask() wrapper that suppresses
|
|
39
|
+
// the DSH "问卷已答" tool-result acknowledgement by replacing the tool result
|
|
40
|
+
// event in the session log with an empty one.
|
|
41
|
+
// --------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Wrapper around ctx.userQuestions.ask() that suppresses the DSH "问卷已答"
|
|
45
|
+
* tool-result acknowledgement.
|
|
46
|
+
*
|
|
47
|
+
* After ctx.userQuestions.ask() resolves, DSH appends a tool/result event to the
|
|
48
|
+
* session log. This function locates that event and replaces its content with
|
|
49
|
+
* an empty array using session's surfaceOp replace — the event stays in the log
|
|
50
|
+
* (so sequence is stable) but renders nothing.
|
|
51
|
+
*
|
|
52
|
+
* @param {object} ctx - Cordis plugin context (has userQuestions service)
|
|
53
|
+
* @param {object} session - DSH Session object
|
|
54
|
+
* @param {object} options - same shape as ctx.userQuestions.ask() options
|
|
55
|
+
* @param {AbortSignal} [options.signal]
|
|
56
|
+
* @param {object[]} options.questions
|
|
57
|
+
* @returns {Promise<{ answers: object[] }>} the raw result from userQuestions
|
|
58
|
+
*/
|
|
59
|
+
export async function askWithoutAcknowledgement(ctx, session, options) {
|
|
60
|
+
const logLenBefore = session.log.length;
|
|
61
|
+
const result = await ctx.userQuestions.ask(options);
|
|
62
|
+
|
|
63
|
+
// DSH appended a tool/result event after userQuestions resolved.
|
|
64
|
+
// Find it and replace its content with empty so nothing renders.
|
|
65
|
+
if (session.log.length > logLenBefore) {
|
|
66
|
+
const lastEvent = session.log[session.log.length - 1];
|
|
67
|
+
if (lastEvent.type === 'tool/result') {
|
|
68
|
+
session.append(
|
|
69
|
+
'tool/result',
|
|
70
|
+
{ message: { content: [] }, source: { kind: 'user' } },
|
|
71
|
+
{ surfaceOp: { op: 'replace', start: lastEvent.seq, end: lastEvent.seq } }
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
35
79
|
// --------------------------------------------------------------------------
|
|
36
80
|
// StatusLine — in-place updatable status bar using session surfaceOp replace
|
|
37
81
|
// --------------------------------------------------------------------------
|
package/package.json
CHANGED
package/events.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* events.js — Scan progress event vocabulary
|
|
3
|
-
*
|
|
4
|
-
* These are pure in-memory plugin events emitted via ctx.events.emit().
|
|
5
|
-
* They flow through the DSH session log and are observable by the agent.
|
|
6
|
-
*
|
|
7
|
-
* Type declarations (for TypeScript users):
|
|
8
|
-
* ```ts
|
|
9
|
-
* // @ts-check
|
|
10
|
-
* declare module '@deepseek-ai/cordis' {
|
|
11
|
-
* interface Events {
|
|
12
|
-
* 'fancy/scan:start'(platform: string, channel: string, type: string, label: string): void
|
|
13
|
-
* 'fancy/scan:book'(platform: string, channel: string, type: string, index: number, total: number, title: string, rank: number): void
|
|
14
|
-
* 'fancy/scan:rank-done'(platform: string, channel: string, type: string, ok: boolean, written: number, failed: number, errorMsg?: string): void
|
|
15
|
-
* 'fancy/scan:done'(platform: string, totalBooks: number, totalFiles: number, ok: boolean): void
|
|
16
|
-
* }
|
|
17
|
-
* }
|
|
18
|
-
* ```
|
|
19
|
-
*/
|