@waterwx/dsh-novel-forge 1.10.1 → 2.0.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/README.md +287 -281
- package/lib/client.js +19572 -18127
- package/lib/index.js +12171 -6932
- package/lib/types/action-guard.d.ts +61 -0
- package/lib/types/ai-scan.d.ts +30 -0
- package/lib/types/assets.d.ts +20 -9
- package/lib/types/assistant.d.ts +29 -0
- package/lib/types/author-assets.d.ts +1 -3
- package/lib/types/bookshelf.d.ts +13 -3
- package/lib/types/client/api.d.ts +137 -21
- package/lib/types/client/chip-prefs.d.ts +36 -0
- package/lib/types/client/docx.d.ts +2 -2
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/llmLive.d.ts +31 -0
- package/lib/types/client/locales.d.ts +15 -70
- package/lib/types/client/mount.d.ts +0 -2
- package/lib/types/client/panel/AiTag.d.ts +1 -0
- package/lib/types/client/panel/AssistantTab.d.ts +4 -1
- package/lib/types/client/panel/AuthorHome.d.ts +13 -9
- package/lib/types/client/panel/BookAnalysisView.d.ts +4 -0
- package/lib/types/client/panel/CmdPalette.d.ts +12 -0
- package/lib/types/client/panel/CreateBookView.d.ts +5 -1
- package/lib/types/client/panel/DirectorView.d.ts +7 -0
- package/lib/types/client/panel/IdeaInspirationView.d.ts +6 -0
- package/lib/types/client/panel/KnowledgeBaseView.d.ts +4 -0
- package/lib/types/client/panel/LiveFeedLog.d.ts +13 -0
- package/lib/types/client/panel/MarketRadarView.d.ts +5 -0
- package/lib/types/client/panel/ModelManager.d.ts +2 -2
- package/lib/types/client/panel/NovelPanel.d.ts +6 -1
- package/lib/types/client/panel/PageHeader.d.ts +18 -0
- package/lib/types/client/panel/PromptSlotsView.d.ts +11 -0
- package/lib/types/client/panel/SettingsView.d.ts +12 -7
- package/lib/types/client/panel/ShelfView.d.ts +10 -1
- package/lib/types/client/panel/SubPage.d.ts +27 -0
- package/lib/types/client/panel/TensionView.d.ts +18 -0
- package/lib/types/client/panel/TimelineView.d.ts +18 -0
- package/lib/types/client/panel/helpers.d.ts +5 -3
- package/lib/types/client/panel/market-radar-state.d.ts +56 -0
- package/lib/types/client/panel/toast.d.ts +2 -0
- package/lib/types/client/panel/views.d.ts +21 -35
- package/lib/types/client/run-status.d.ts +21 -0
- package/lib/types/client/sidebar-entry.d.ts +0 -2
- package/lib/types/docx-core.d.ts +16 -0
- package/lib/types/docx.d.ts +2 -3
- package/lib/types/engine.d.ts +83 -79
- package/lib/types/global-assets.d.ts +6 -0
- package/lib/types/home.d.ts +11 -0
- package/lib/types/index.d.ts +27 -13
- package/lib/types/llm-live.d.ts +70 -0
- package/lib/types/llm-retry.d.ts +38 -0
- package/lib/types/market-radar-scan.d.ts +18 -0
- package/lib/types/market-radar-sources.d.ts +31 -0
- package/lib/types/migrate-output.d.ts +25 -0
- package/lib/types/model-capability.d.ts +93 -0
- package/lib/types/novel-context.d.ts +80 -0
- package/lib/types/output-budget.d.ts +86 -0
- package/lib/types/prompt-slots.d.ts +57 -0
- package/lib/types/prompting.d.ts +10 -0
- package/lib/types/protocol.d.ts +829 -522
- package/lib/types/revision.d.ts +76 -0
- package/lib/types/routes.d.ts +9 -3
- package/lib/types/run.d.ts +23 -1
- package/lib/types/settings-persist.d.ts +59 -0
- package/lib/types/snapshots.d.ts +46 -0
- package/lib/types/stage-contract.d.ts +58 -0
- package/lib/types/tension.d.ts +53 -0
- package/lib/types/timeline.d.ts +37 -0
- package/package.json +50 -28
- package/src/action-guard.ts +127 -0
- package/src/ai-scan.ts +155 -0
- package/src/assets.ts +1801 -535
- package/src/assistant.ts +1098 -770
- package/src/author-assets.ts +131 -147
- package/src/bookshelf.ts +193 -167
- package/src/client/api.ts +767 -607
- package/src/client/chip-prefs.ts +121 -0
- package/src/client/docx.ts +32 -69
- package/src/client/index.ts +3 -1
- package/src/client/llmLive.ts +111 -0
- package/src/client/locales.ts +15 -274
- package/src/client/mount.tsx +4 -3
- package/src/client/panel/AdaptModeView.tsx +535 -520
- package/src/client/panel/AiTag.tsx +7 -0
- package/src/client/panel/AssetsTab.tsx +448 -458
- package/src/client/panel/AssistantTab.tsx +355 -301
- package/src/client/panel/AuthorAssetsView.tsx +205 -207
- package/src/client/panel/AuthorHome.tsx +309 -202
- package/src/client/panel/BookAnalysisView.tsx +63 -0
- package/src/client/panel/CmdPalette.tsx +102 -0
- package/src/client/panel/CreateBookView.tsx +366 -352
- package/src/client/panel/DirectorView.tsx +200 -0
- package/src/client/panel/GlobalAssetLibraryView.tsx +168 -172
- package/src/client/panel/IdeaInspirationView.tsx +76 -0
- package/src/client/panel/ImportModal.tsx +302 -302
- package/src/client/panel/KnowledgeBaseView.tsx +125 -0
- package/src/client/panel/LiveFeedLog.tsx +204 -0
- package/src/client/panel/MarketRadarView.tsx +415 -0
- package/src/client/panel/ModelManager.tsx +205 -205
- package/src/client/panel/NovelPanel.tsx +5559 -4655
- package/src/client/panel/PageHeader.tsx +37 -0
- package/src/client/panel/ProgressConsole.tsx +63 -64
- package/src/client/panel/PromptSlotsView.tsx +97 -0
- package/src/client/panel/ReaderView.tsx +306 -306
- package/src/client/panel/RunPanel.tsx +56 -24
- package/src/client/panel/SettingsView.tsx +175 -112
- package/src/client/panel/ShelfView.tsx +63 -39
- package/src/client/panel/SubPage.tsx +42 -0
- package/src/client/panel/TensionView.tsx +212 -0
- package/src/client/panel/TimelineView.tsx +208 -0
- package/src/client/panel/WorldTab.tsx +202 -202
- package/src/client/panel/helpers.ts +7 -5
- package/src/client/panel/market-radar-state.ts +79 -0
- package/src/client/panel/panel.module.css +5767 -4199
- package/src/client/panel/toast.ts +51 -0
- package/src/client/panel/views.tsx +316 -314
- package/src/client/run-status.ts +171 -0
- package/src/client/sidebar-entry.ts +3 -3
- package/src/docx-core.ts +53 -0
- package/src/docx.ts +44 -83
- package/src/engine.ts +1610 -1541
- package/src/global-assets.ts +58 -0
- package/src/home.ts +33 -0
- package/src/index.ts +184 -103
- package/src/llm-live.ts +245 -0
- package/src/llm-retry.ts +77 -0
- package/src/market-radar-scan.ts +35 -0
- package/src/market-radar-sources.ts +173 -0
- package/src/migrate-output.ts +76 -0
- package/src/model-capability.ts +215 -0
- package/src/novel-context.ts +286 -0
- package/src/output-budget.ts +147 -0
- package/src/prompt-slots.ts +125 -0
- package/src/prompting.ts +26 -0
- package/src/protocol.ts +2454 -2148
- package/src/revision.ts +283 -0
- package/src/routes.ts +3795 -3359
- package/src/run.ts +113 -17
- package/src/settings-persist.ts +114 -0
- package/src/snapshots.ts +174 -0
- package/src/stage-contract.ts +186 -0
- package/src/tension.ts +251 -0
- package/src/timeline.ts +159 -0
- package/assets/styles/arcane-thick-3d.webp +0 -0
- package/assets/styles/chinese-ink.webp +0 -0
- package/assets/styles/clay-stopmotion-3d.webp +0 -0
- package/assets/styles/dark-ghibli.webp +0 -0
- package/assets/styles/dark-gothic-3d.webp +0 -0
- package/assets/styles/film-photo.webp +0 -0
- package/assets/styles/guofeng-heavy.webp +0 -0
- package/assets/styles/horror-game-3d.webp +0 -0
- package/assets/styles/japan-cel-dark.webp +0 -0
- package/assets/styles/korean-webtoon.webp +0 -0
- package/assets/styles/low-cyberpunk-3d.webp +0 -0
- package/assets/styles/nextgen-cg.webp +0 -0
- package/assets/styles/noir-film.webp +0 -0
- package/assets/styles/openworld-survival.webp +0 -0
- package/assets/styles/paper-cut-3d.webp +0 -0
- package/assets/styles/pixar-adult-3d.webp +0 -0
- package/assets/styles/pop-marvel-2d.webp +0 -0
- package/assets/styles/shinkai-anime.webp +0 -0
- package/assets/styles/tactical-stealth.webp +0 -0
- package/assets/styles/vaporwave-3d.webp +0 -0
- package/assets/styles/vhs90.webp +0 -0
- package/lib/types/client/panel/BookshelfBar.d.ts +0 -11
- package/lib/types/client/panel/FlowGuide.d.ts +0 -21
- package/lib/types/client/panel/MangaRoleLibrary.d.ts +0 -18
- package/lib/types/client/panel/MangaWorkspace.d.ts +0 -15
- package/lib/types/client/panel/ModelPicker.d.ts +0 -11
- package/lib/types/client/panel/ProgressHomeView.d.ts +0 -5
- package/lib/types/client/panel/SceneLibrary.d.ts +0 -14
- package/lib/types/client/panel/StoryboardTab.d.ts +0 -19
- package/lib/types/client/panel/StyleCard.d.ts +0 -8
- package/lib/types/client/panel/StyleGallery.d.ts +0 -1
- package/lib/types/comic-presets.d.ts +0 -12
- package/lib/types/shot-language.d.ts +0 -46
- package/lib/types/story-beat-language.d.ts +0 -35
- package/lib/types/style-library.d.ts +0 -33
- package/skills/chapter-batch/SKILL.md +0 -81
- package/src/client/mount.tsx._new +0 -97
- package/src/client/mount.tsx._nf +0 -97
- package/src/client/mount.tsx._tmp +0 -97
- package/src/client/panel/BookshelfBar.tsx +0 -170
- package/src/client/panel/FlowGuide.tsx +0 -83
- package/src/client/panel/MangaRoleLibrary.tsx +0 -810
- package/src/client/panel/MangaWorkspace.tsx +0 -359
- package/src/client/panel/ProgressHomeView.tsx +0 -87
- package/src/client/panel/SceneLibrary.tsx +0 -396
- package/src/client/panel/StoryboardTab.tsx +0 -466
- package/src/client/panel/StyleCard.tsx +0 -90
- package/src/client/panel/StyleGallery.tsx +0 -58
- package/src/comic-presets.ts +0 -67
- package/src/shot-language.ts +0 -181
- package/src/story-beat-language.ts +0 -130
- package/src/style-library.ts +0 -78
package/src/ai-scan.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 本地 AI 味扫描器(不调 LLM,确定性检测)
|
|
3
|
+
*
|
|
4
|
+
* 用途:生成/润色后自动扫描,结果作为「事实锚点」注入审稿提示词,
|
|
5
|
+
* 让 LLM 做判断而非机械统计。也可用于 UI 展示 AI 味指标。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface AiScanResult {
|
|
9
|
+
/** 总评分 0-100,越高越像 AI 写的 */
|
|
10
|
+
aiScore: number
|
|
11
|
+
/** 命中的套话及次数 */
|
|
12
|
+
clicheHits: Array<{ word: string; count: number }>
|
|
13
|
+
/** 段落长度方差(过高=段落过于整齐) */
|
|
14
|
+
paragraphLengthVariance: number
|
|
15
|
+
/** 连续解释性叙事段数(≥3 视为问题) */
|
|
16
|
+
consecutiveExpositoryParagraphs: number
|
|
17
|
+
/** 句式重复率(相同开头句式占比) */
|
|
18
|
+
sentenceRepetitionRate: number
|
|
19
|
+
/** 过长段落数(>300字) */
|
|
20
|
+
longParagraphCount: number
|
|
21
|
+
/** 过短段落数(<20字) */
|
|
22
|
+
shortParagraphCount: number
|
|
23
|
+
/** 对话占比(0-1) */
|
|
24
|
+
dialogueRatio: number
|
|
25
|
+
/** 问题摘要,可直接注入审稿提示词 */
|
|
26
|
+
summary: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** 重灾区套话(高频出现即问题) */
|
|
30
|
+
const HEAVY_CLICHES = [
|
|
31
|
+
'不禁', '仿佛', '一时间', '不由得', '顿时', '然而',
|
|
32
|
+
'缓缓', '轻轻', '微微', '默默', '似乎', '终于',
|
|
33
|
+
'显然', '其实', '无法形容', '难以言喻', '不由自主',
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
/** 轻微套话(偶尔出现可接受,高频才问题) */
|
|
37
|
+
const LIGHT_CLICHES = [
|
|
38
|
+
'心中', '脑海', '眼神', '嘴角', '眉头', '身影',
|
|
39
|
+
'气息', '光芒', '力量', '感觉', '知道', '明白',
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
/** 解释性叙事开头模式 */
|
|
43
|
+
const EXPOSITORY_STARTS = [
|
|
44
|
+
'原来', '因为', '由于', '所以', '因此', '于是',
|
|
45
|
+
'这就是', '也就是说', '换句话说', '事实上', '实际上',
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
export function scanAiFlavor(text: string): AiScanResult {
|
|
49
|
+
const paragraphs = text.split(/\n{2,}/).map(p => p.trim()).filter(p => p.length > 0)
|
|
50
|
+
const totalChars = text.length
|
|
51
|
+
|
|
52
|
+
// 1. 套话统计
|
|
53
|
+
const clicheHits: Array<{ word: string; count: number }> = []
|
|
54
|
+
let clicheTotal = 0
|
|
55
|
+
for (const word of [...HEAVY_CLICHES, ...LIGHT_CLICHES]) {
|
|
56
|
+
const count = countOccurrences(text, word)
|
|
57
|
+
if (count > 0) {
|
|
58
|
+
clicheHits.push({ word, count })
|
|
59
|
+
clicheTotal += count
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
clicheHits.sort((a, b) => b.count - a.count)
|
|
63
|
+
|
|
64
|
+
// 2. 段落长度方差
|
|
65
|
+
const paraLengths = paragraphs.map(p => p.length)
|
|
66
|
+
const avgLen = paraLengths.length > 0 ? paraLengths.reduce((a, b) => a + b, 0) / paraLengths.length : 0
|
|
67
|
+
const variance = paraLengths.length > 0
|
|
68
|
+
? paraLengths.reduce((sum, len) => sum + Math.pow(len - avgLen, 2), 0) / paraLengths.length
|
|
69
|
+
: 0
|
|
70
|
+
|
|
71
|
+
// 3. 连续解释性叙事
|
|
72
|
+
let maxConsecutive = 0
|
|
73
|
+
let currentConsecutive = 0
|
|
74
|
+
for (const p of paragraphs) {
|
|
75
|
+
const isExpository = EXPOSITORY_STARTS.some(s => p.startsWith(s)) ||
|
|
76
|
+
(p.length > 150 && !p.includes('"') && !p.includes('「') && !p.includes('『'))
|
|
77
|
+
if (isExpository) {
|
|
78
|
+
currentConsecutive++
|
|
79
|
+
maxConsecutive = Math.max(maxConsecutive, currentConsecutive)
|
|
80
|
+
} else {
|
|
81
|
+
currentConsecutive = 0
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 4. 句式重复率(相同句首词)
|
|
86
|
+
const sentences = text.split(/[。!?!?]/).map(s => s.trim()).filter(s => s.length > 0)
|
|
87
|
+
const starterCounts = new Map<string, number>()
|
|
88
|
+
for (const s of sentences) {
|
|
89
|
+
const starter = s.slice(0, 2)
|
|
90
|
+
starterCounts.set(starter, (starterCounts.get(starter) ?? 0) + 1)
|
|
91
|
+
}
|
|
92
|
+
const repeatedStarters = Array.from(starterCounts.values()).filter(c => c >= 3).reduce((a, b) => a + b, 0)
|
|
93
|
+
const sentenceRepetitionRate = sentences.length > 0 ? repeatedStarters / sentences.length : 0
|
|
94
|
+
|
|
95
|
+
// 5. 段落长度分布
|
|
96
|
+
const longParagraphCount = paraLengths.filter(l => l > 300).length
|
|
97
|
+
const shortParagraphCount = paraLengths.filter(l => l < 20).length
|
|
98
|
+
|
|
99
|
+
// 6. 对话占比
|
|
100
|
+
const dialogueChars = (text.match(/["「『][^"」』]*["」』]/g) ?? []).join('').length
|
|
101
|
+
const dialogueRatio = totalChars > 0 ? dialogueChars / totalChars : 0
|
|
102
|
+
|
|
103
|
+
// 7. 综合 AI 味评分(0-100,越高越像 AI)
|
|
104
|
+
let aiScore = 0
|
|
105
|
+
// 套话密度(每千字套话数)
|
|
106
|
+
const clicheDensity = totalChars > 0 ? (clicheTotal / totalChars) * 1000 : 0
|
|
107
|
+
aiScore += Math.min(40, clicheDensity * 8)
|
|
108
|
+
// 段落过于整齐(方差小=AI特征)
|
|
109
|
+
if (variance < 2000 && paraLengths.length >= 5) aiScore += 15
|
|
110
|
+
// 连续解释性叙事
|
|
111
|
+
aiScore += Math.min(20, maxConsecutive * 5)
|
|
112
|
+
// 句式重复
|
|
113
|
+
aiScore += Math.min(15, sentenceRepetitionRate * 30)
|
|
114
|
+
// 对话过少
|
|
115
|
+
if (dialogueRatio < 0.05 && totalChars > 1000) aiScore += 10
|
|
116
|
+
aiScore = Math.min(100, Math.round(aiScore))
|
|
117
|
+
|
|
118
|
+
// 8. 问题摘要
|
|
119
|
+
const issues: string[] = []
|
|
120
|
+
if (clicheDensity > 3) {
|
|
121
|
+
const topCliches = clicheHits.slice(0, 5).map(h => `${h.word}×${h.count}`).join('、')
|
|
122
|
+
issues.push(`套话密度偏高(每千字 ${clicheDensity.toFixed(1)} 次):${topCliches}`)
|
|
123
|
+
}
|
|
124
|
+
if (maxConsecutive >= 3) issues.push(`连续 ${maxConsecutive} 段解释性叙事,缺少对话/动作`)
|
|
125
|
+
if (sentenceRepetitionRate > 0.15) issues.push(`句式重复率 ${(sentenceRepetitionRate * 100).toFixed(0)}%,开头句式单一`)
|
|
126
|
+
if (longParagraphCount > 3) issues.push(`${longParagraphCount} 段超过 300 字,段落过长`)
|
|
127
|
+
if (dialogueRatio < 0.05 && totalChars > 1000) issues.push('对话占比过低,整章偏叙述')
|
|
128
|
+
|
|
129
|
+
const summary = issues.length > 0
|
|
130
|
+
? `本地 AI 味扫描(AI 味指数 ${aiScore}/100):\n` + issues.map(i => `- ${i}`).join('\n')
|
|
131
|
+
: `本地 AI 味扫描(AI 味指数 ${aiScore}/100):未发现明显问题。`
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
aiScore,
|
|
135
|
+
clicheHits,
|
|
136
|
+
paragraphLengthVariance: Math.round(variance),
|
|
137
|
+
consecutiveExpositoryParagraphs: maxConsecutive,
|
|
138
|
+
sentenceRepetitionRate: Math.round(sentenceRepetitionRate * 100) / 100,
|
|
139
|
+
longParagraphCount,
|
|
140
|
+
shortParagraphCount,
|
|
141
|
+
dialogueRatio: Math.round(dialogueRatio * 100) / 100,
|
|
142
|
+
summary,
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function countOccurrences(text: string, word: string): number {
|
|
147
|
+
if (word.length === 0) return 0
|
|
148
|
+
let count = 0
|
|
149
|
+
let idx = text.indexOf(word)
|
|
150
|
+
while (idx !== -1) {
|
|
151
|
+
count++
|
|
152
|
+
idx = text.indexOf(word, idx + word.length)
|
|
153
|
+
}
|
|
154
|
+
return count
|
|
155
|
+
}
|