@zb2947244682/supernovel 1.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/LICENSE +21 -0
- package/README.md +122 -0
- package/dist/adapters/aiAdapter.d.ts +21 -0
- package/dist/adapters/aiAdapter.d.ts.map +1 -0
- package/dist/adapters/aiAdapter.js +196 -0
- package/dist/adapters/aiAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +20 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/logger.d.ts +9 -0
- package/dist/adapters/logger.d.ts.map +1 -0
- package/dist/adapters/logger.js +22 -0
- package/dist/adapters/logger.js.map +1 -0
- package/dist/adapters/storageAdapter.d.ts +20 -0
- package/dist/adapters/storageAdapter.d.ts.map +1 -0
- package/dist/adapters/storageAdapter.js +190 -0
- package/dist/adapters/storageAdapter.js.map +1 -0
- package/dist/adapters/validationAdapter.d.ts +16 -0
- package/dist/adapters/validationAdapter.d.ts.map +1 -0
- package/dist/adapters/validationAdapter.js +33 -0
- package/dist/adapters/validationAdapter.js.map +1 -0
- package/dist/bus/commands.d.ts +70 -0
- package/dist/bus/commands.d.ts.map +1 -0
- package/dist/bus/commands.js +34 -0
- package/dist/bus/commands.js.map +1 -0
- package/dist/bus/dispatcher.d.ts +4 -0
- package/dist/bus/dispatcher.d.ts.map +1 -0
- package/dist/bus/dispatcher.js +313 -0
- package/dist/bus/dispatcher.js.map +1 -0
- package/dist/bus/effectRunner.d.ts +11 -0
- package/dist/bus/effectRunner.d.ts.map +1 -0
- package/dist/bus/effectRunner.js +117 -0
- package/dist/bus/effectRunner.js.map +1 -0
- package/dist/bus/index.d.ts +4 -0
- package/dist/bus/index.d.ts.map +1 -0
- package/dist/bus/index.js +6 -0
- package/dist/bus/index.js.map +1 -0
- package/dist/config/paths.d.ts +13 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +53 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/core/effects.d.ts +109 -0
- package/dist/core/effects.d.ts.map +1 -0
- package/dist/core/effects.js +42 -0
- package/dist/core/effects.js.map +1 -0
- package/dist/core/errors.d.ts +28 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +56 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +12 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +18 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/jsonUtils.d.ts +13 -0
- package/dist/core/jsonUtils.d.ts.map +1 -0
- package/dist/core/jsonUtils.js +130 -0
- package/dist/core/jsonUtils.js.map +1 -0
- package/dist/core/logger.d.ts +16 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +59 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/ports.d.ts +57 -0
- package/dist/core/ports.d.ts.map +1 -0
- package/dist/core/ports.js +3 -0
- package/dist/core/ports.js.map +1 -0
- package/dist/core/rag/consistency.d.ts +51 -0
- package/dist/core/rag/consistency.d.ts.map +1 -0
- package/dist/core/rag/consistency.js +239 -0
- package/dist/core/rag/consistency.js.map +1 -0
- package/dist/core/rag/contextAssembler.d.ts +44 -0
- package/dist/core/rag/contextAssembler.d.ts.map +1 -0
- package/dist/core/rag/contextAssembler.js +278 -0
- package/dist/core/rag/contextAssembler.js.map +1 -0
- package/dist/core/rag/index.d.ts +12 -0
- package/dist/core/rag/index.d.ts.map +1 -0
- package/dist/core/rag/index.js +15 -0
- package/dist/core/rag/index.js.map +1 -0
- package/dist/core/rag/knowledgeGraph.d.ts +72 -0
- package/dist/core/rag/knowledgeGraph.d.ts.map +1 -0
- package/dist/core/rag/knowledgeGraph.js +227 -0
- package/dist/core/rag/knowledgeGraph.js.map +1 -0
- package/dist/core/rag/summaries.d.ts +57 -0
- package/dist/core/rag/summaries.d.ts.map +1 -0
- package/dist/core/rag/summaries.js +251 -0
- package/dist/core/rag/summaries.js.map +1 -0
- package/dist/core/rag/types.d.ts +201 -0
- package/dist/core/rag/types.d.ts.map +1 -0
- package/dist/core/rag/types.js +4 -0
- package/dist/core/rag/types.js.map +1 -0
- package/dist/core/rag/vectorStore.d.ts +68 -0
- package/dist/core/rag/vectorStore.d.ts.map +1 -0
- package/dist/core/rag/vectorStore.js +211 -0
- package/dist/core/rag/vectorStore.js.map +1 -0
- package/dist/core/types.d.ts +246 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usecases/generateChapter.d.ts +26 -0
- package/dist/core/usecases/generateChapter.d.ts.map +1 -0
- package/dist/core/usecases/generateChapter.js +132 -0
- package/dist/core/usecases/generateChapter.js.map +1 -0
- package/dist/core/usecases/generateChapterRAG.d.ts +40 -0
- package/dist/core/usecases/generateChapterRAG.d.ts.map +1 -0
- package/dist/core/usecases/generateChapterRAG.js +221 -0
- package/dist/core/usecases/generateChapterRAG.js.map +1 -0
- package/dist/core/usecases/generateOutline.d.ts +19 -0
- package/dist/core/usecases/generateOutline.d.ts.map +1 -0
- package/dist/core/usecases/generateOutline.js +129 -0
- package/dist/core/usecases/generateOutline.js.map +1 -0
- package/dist/core/usecases/generateWorld.d.ts +18 -0
- package/dist/core/usecases/generateWorld.d.ts.map +1 -0
- package/dist/core/usecases/generateWorld.js +189 -0
- package/dist/core/usecases/generateWorld.js.map +1 -0
- package/dist/core/usecases/parseRequirements.d.ts +20 -0
- package/dist/core/usecases/parseRequirements.d.ts.map +1 -0
- package/dist/core/usecases/parseRequirements.js +95 -0
- package/dist/core/usecases/parseRequirements.js.map +1 -0
- package/dist/core/usecases/validateNovel.d.ts +29 -0
- package/dist/core/usecases/validateNovel.d.ts.map +1 -0
- package/dist/core/usecases/validateNovel.js +156 -0
- package/dist/core/usecases/validateNovel.js.map +1 -0
- package/dist/shell/cli.d.ts +3 -0
- package/dist/shell/cli.d.ts.map +1 -0
- package/dist/shell/cli.js +158 -0
- package/dist/shell/cli.js.map +1 -0
- package/dist/shell/index.d.ts +3 -0
- package/dist/shell/index.d.ts.map +1 -0
- package/dist/shell/index.js +279 -0
- package/dist/shell/index.js.map +1 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SuperNovel Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# SuperNovel - AI小说生成器
|
|
2
|
+
|
|
3
|
+
基于 Core-Shell 架构的 AI 长篇小说生成系统。
|
|
4
|
+
|
|
5
|
+
## 架构设计
|
|
6
|
+
|
|
7
|
+
项目采用 **Core-Shell 架构**,分为三层:
|
|
8
|
+
|
|
9
|
+
### 1. Core 层(核心层)
|
|
10
|
+
- **纯函数**:所有业务逻辑都是纯函数,无副作用
|
|
11
|
+
- **Effects 模式**:UseCase 返回 Effect 声明而非直接执行 I/O
|
|
12
|
+
- **类型安全**:完整的 TypeScript 类型定义
|
|
13
|
+
|
|
14
|
+
### 2. Bus 层(总线层)
|
|
15
|
+
- **命令分发**:Command 到 UseCase 的路由
|
|
16
|
+
- **Effect 执行**:执行 Core 层声明的 Effects
|
|
17
|
+
- **工作流协调**:管理生成流程的状态流转
|
|
18
|
+
|
|
19
|
+
### 3. Shell 层(外壳层)
|
|
20
|
+
- **TUI 界面**:基于 @inquirer/prompts 的交互式界面
|
|
21
|
+
- **CLI 支持**:命令行接口
|
|
22
|
+
- **配置管理**:用户配置和项目存储
|
|
23
|
+
|
|
24
|
+
### 4. Adapters 层(适配器层)
|
|
25
|
+
- **AI 适配器**:支持 OpenAI、Anthropic、OpenRouter 等
|
|
26
|
+
- **存储适配器**:文件系统操作
|
|
27
|
+
- **校验适配器**:AI 辅助的内容校验
|
|
28
|
+
|
|
29
|
+
## 安装
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install
|
|
33
|
+
npm run build
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 使用
|
|
37
|
+
|
|
38
|
+
### 方式一:TUI 界面(推荐)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm start
|
|
42
|
+
# 或
|
|
43
|
+
npx supernovel
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 方式二:CLI 命令
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# 生成小说框架
|
|
50
|
+
npx supernovel framework "你的小说创意描述" --name my-novel
|
|
51
|
+
|
|
52
|
+
# 生成章节
|
|
53
|
+
npx supernovel chapters ./my-novel
|
|
54
|
+
|
|
55
|
+
# 测试 AI 模型
|
|
56
|
+
npx supernovel test
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 工作流程
|
|
60
|
+
|
|
61
|
+
1. **生成框架**
|
|
62
|
+
- 输入自然语言需求描述
|
|
63
|
+
- AI 生成需求文档、世界观、大纲
|
|
64
|
+
- 保存为项目文件
|
|
65
|
+
|
|
66
|
+
2. **生成章节**
|
|
67
|
+
- 选择已创建的项目
|
|
68
|
+
- AI 自动按大纲生成章节
|
|
69
|
+
- 自动校验并保存
|
|
70
|
+
|
|
71
|
+
3. **导出小说**
|
|
72
|
+
- 导出为 Markdown 格式
|
|
73
|
+
- 后续支持 EPUB 格式
|
|
74
|
+
|
|
75
|
+
## 项目结构
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
~/novel/ # 默认小说存储目录
|
|
79
|
+
└── my-novel/ # 项目目录
|
|
80
|
+
├── project.json # 项目主文件
|
|
81
|
+
├── requirements.md # 需求文档
|
|
82
|
+
├── world.md # 世界观设定
|
|
83
|
+
├── outline.md # 小说大纲
|
|
84
|
+
└── chapters/ # 章节文件
|
|
85
|
+
├── chapter-1.md
|
|
86
|
+
├── chapter-2.md
|
|
87
|
+
└── ...
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 配置
|
|
91
|
+
|
|
92
|
+
首次运行会自动创建配置文件:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
~/.supernovel/config.json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
支持的 AI 提供商:
|
|
99
|
+
- OpenAI (GPT-4, GPT-3.5)
|
|
100
|
+
- Anthropic (Claude)
|
|
101
|
+
- OpenRouter (多种模型)
|
|
102
|
+
- 自定义 API
|
|
103
|
+
|
|
104
|
+
## 特性
|
|
105
|
+
|
|
106
|
+
- 全自动小说生成,无需人工干预
|
|
107
|
+
- 智能校验:字数、角色一致性、禁用元素等
|
|
108
|
+
- 两阶段生成:先框架后章节,确保质量
|
|
109
|
+
- 纯函数架构,易于测试和维护
|
|
110
|
+
- 模块化设计,易于扩展
|
|
111
|
+
|
|
112
|
+
## 技术栈
|
|
113
|
+
|
|
114
|
+
- TypeScript 5.x
|
|
115
|
+
- Node.js 20+
|
|
116
|
+
- @inquirer/prompts (TUI)
|
|
117
|
+
- Commander.js (CLI)
|
|
118
|
+
- Vitest (测试)
|
|
119
|
+
|
|
120
|
+
## 许可证
|
|
121
|
+
|
|
122
|
+
MIT
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AIPort } from '../core/ports.js';
|
|
2
|
+
import type { AIConfig, AIResponse } from '../core/types.js';
|
|
3
|
+
interface AIMessage {
|
|
4
|
+
role: 'system' | 'user' | 'assistant';
|
|
5
|
+
content: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class AIAdapter implements AIPort {
|
|
8
|
+
chat(messages: AIMessage[], config: AIConfig): Promise<AIResponse>;
|
|
9
|
+
chatStream(messages: AIMessage[], config: AIConfig, onChunk: (chunk: string) => void): Promise<AIResponse>;
|
|
10
|
+
testConnection(config: AIConfig): Promise<{
|
|
11
|
+
success: boolean;
|
|
12
|
+
latency: number;
|
|
13
|
+
error?: string;
|
|
14
|
+
}>;
|
|
15
|
+
private callOpenAI;
|
|
16
|
+
private callAnthropic;
|
|
17
|
+
private callOpenRouter;
|
|
18
|
+
private callCustom;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=aiAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aiAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/aiAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG7D,UAAU,SAAS;IACjB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,SAAU,YAAW,MAAM;IAChC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAelE,UAAU,CACd,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAC/B,OAAO,CAAC,UAAU,CAAC;IAOhB,cAAc,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;YAiBxF,UAAU;YA8CV,aAAa;YAuDb,cAAc;YA4Cd,UAAU;CAyCzB"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// Adapter - AI服务适配器
|
|
2
|
+
// 封装AI API调用
|
|
3
|
+
import { AppError } from '../core/errors.js';
|
|
4
|
+
export class AIAdapter {
|
|
5
|
+
async chat(messages, config) {
|
|
6
|
+
switch (config.provider) {
|
|
7
|
+
case 'openai':
|
|
8
|
+
return this.callOpenAI(messages, config);
|
|
9
|
+
case 'anthropic':
|
|
10
|
+
return this.callAnthropic(messages, config);
|
|
11
|
+
case 'openrouter':
|
|
12
|
+
return this.callOpenRouter(messages, config);
|
|
13
|
+
case 'custom':
|
|
14
|
+
return this.callCustom(messages, config);
|
|
15
|
+
default:
|
|
16
|
+
throw new AppError('CONFIG_ERROR', `未知的AI提供商: ${config.provider}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async chatStream(messages, config, onChunk) {
|
|
20
|
+
// 流式输出 - 简化实现,直接调用非流式版本
|
|
21
|
+
const response = await this.chat(messages, config);
|
|
22
|
+
onChunk(response.content);
|
|
23
|
+
return response;
|
|
24
|
+
}
|
|
25
|
+
async testConnection(config) {
|
|
26
|
+
const start = Date.now();
|
|
27
|
+
try {
|
|
28
|
+
await this.chat([{ role: 'user', content: 'Hello' }], { ...config, maxTokens: 10 });
|
|
29
|
+
return { success: true, latency: Date.now() - start };
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return {
|
|
33
|
+
success: false,
|
|
34
|
+
latency: Date.now() - start,
|
|
35
|
+
error: error instanceof Error ? error.message : String(error)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async callOpenAI(messages, config) {
|
|
40
|
+
console.log(`[AI] 调用 OpenAI 兼容 API: ${config.baseURL}/chat/completions`);
|
|
41
|
+
console.log(`[AI] 模型: ${config.model}, 消息数: ${messages.length}`);
|
|
42
|
+
const requestBody = {
|
|
43
|
+
model: config.model,
|
|
44
|
+
messages,
|
|
45
|
+
temperature: config.temperature ?? 0.7,
|
|
46
|
+
max_tokens: config.maxTokens ?? 4000
|
|
47
|
+
};
|
|
48
|
+
console.log(`[AI] 请求体:`, JSON.stringify(requestBody, null, 2).slice(0, 500) + '...');
|
|
49
|
+
const response = await fetch(`${config.baseURL}/chat/completions`, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
headers: {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
'Authorization': `Bearer ${config.apiKey}`
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify(requestBody)
|
|
56
|
+
});
|
|
57
|
+
console.log(`[AI] 响应状态: ${response.status} ${response.statusText}`);
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
const errorText = await response.text();
|
|
60
|
+
console.error(`[AI] API错误: ${errorText}`);
|
|
61
|
+
throw new AppError('AI_ERROR', `OpenAI API错误 (${response.status}): ${errorText}`);
|
|
62
|
+
}
|
|
63
|
+
const data = await response.json();
|
|
64
|
+
console.log(`[AI] 响应成功,使用 tokens:`, data.usage);
|
|
65
|
+
const content = data.choices?.[0]?.message?.content;
|
|
66
|
+
if (!content) {
|
|
67
|
+
console.error(`[AI] 响应缺少内容:`, JSON.stringify(data, null, 2));
|
|
68
|
+
throw new AppError('AI_ERROR', 'API响应缺少内容字段');
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
content,
|
|
72
|
+
usage: data.usage,
|
|
73
|
+
model: data.model
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async callAnthropic(messages, config) {
|
|
77
|
+
console.log(`[AI] 调用 Anthropic API: ${config.baseURL}/messages`);
|
|
78
|
+
console.log(`[AI] 模型: ${config.model}, 消息数: ${messages.length}`);
|
|
79
|
+
// 分离system消息
|
|
80
|
+
const systemMessage = messages.find(m => m.role === 'system');
|
|
81
|
+
const userMessages = messages.filter(m => m.role !== 'system');
|
|
82
|
+
const response = await fetch(`${config.baseURL}/messages`, {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
headers: {
|
|
85
|
+
'Content-Type': 'application/json',
|
|
86
|
+
'x-api-key': config.apiKey,
|
|
87
|
+
'anthropic-version': '2023-06-01'
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify({
|
|
90
|
+
model: config.model,
|
|
91
|
+
system: systemMessage?.content,
|
|
92
|
+
messages: userMessages.map(m => ({
|
|
93
|
+
role: m.role,
|
|
94
|
+
content: m.content
|
|
95
|
+
})),
|
|
96
|
+
temperature: config.temperature ?? 0.7,
|
|
97
|
+
max_tokens: config.maxTokens ?? 4000
|
|
98
|
+
})
|
|
99
|
+
});
|
|
100
|
+
console.log(`[AI] 响应状态: ${response.status} ${response.statusText}`);
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
const errorText = await response.text();
|
|
103
|
+
console.error(`[AI] API错误: ${errorText}`);
|
|
104
|
+
throw new AppError('AI_ERROR', `Anthropic API错误 (${response.status}): ${errorText}`);
|
|
105
|
+
}
|
|
106
|
+
const data = await response.json();
|
|
107
|
+
console.log(`[AI] 响应成功,使用 tokens:`, data.usage);
|
|
108
|
+
const content = data.content?.[0]?.text;
|
|
109
|
+
if (!content) {
|
|
110
|
+
console.error(`[AI] 响应缺少内容:`, JSON.stringify(data, null, 2));
|
|
111
|
+
throw new AppError('AI_ERROR', 'API响应缺少内容字段');
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
content,
|
|
115
|
+
usage: {
|
|
116
|
+
prompt_tokens: data.usage.input_tokens,
|
|
117
|
+
completion_tokens: data.usage.output_tokens,
|
|
118
|
+
total_tokens: data.usage.input_tokens + data.usage.output_tokens
|
|
119
|
+
},
|
|
120
|
+
model: data.model
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
async callOpenRouter(messages, config) {
|
|
124
|
+
console.log(`[AI] 调用 OpenRouter API: ${config.baseURL}/chat/completions`);
|
|
125
|
+
console.log(`[AI] 模型: ${config.model}, 消息数: ${messages.length}`);
|
|
126
|
+
const response = await fetch(`${config.baseURL}/chat/completions`, {
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
131
|
+
'HTTP-Referer': 'https://supernovel.app',
|
|
132
|
+
'X-Title': 'SuperNovel'
|
|
133
|
+
},
|
|
134
|
+
body: JSON.stringify({
|
|
135
|
+
model: config.model,
|
|
136
|
+
messages,
|
|
137
|
+
temperature: config.temperature ?? 0.7,
|
|
138
|
+
max_tokens: config.maxTokens ?? 4000
|
|
139
|
+
})
|
|
140
|
+
});
|
|
141
|
+
console.log(`[AI] 响应状态: ${response.status} ${response.statusText}`);
|
|
142
|
+
if (!response.ok) {
|
|
143
|
+
const errorText = await response.text();
|
|
144
|
+
console.error(`[AI] API错误: ${errorText}`);
|
|
145
|
+
throw new AppError('AI_ERROR', `OpenRouter API错误 (${response.status}): ${errorText}`);
|
|
146
|
+
}
|
|
147
|
+
const data = await response.json();
|
|
148
|
+
console.log(`[AI] 响应成功,使用 tokens:`, data.usage);
|
|
149
|
+
const content = data.choices?.[0]?.message?.content;
|
|
150
|
+
if (!content) {
|
|
151
|
+
console.error(`[AI] 响应缺少内容:`, JSON.stringify(data, null, 2));
|
|
152
|
+
throw new AppError('AI_ERROR', 'API响应缺少内容字段');
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
content,
|
|
156
|
+
usage: data.usage,
|
|
157
|
+
model: data.model
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
async callCustom(messages, config) {
|
|
161
|
+
console.log(`[AI] 调用自定义 API: ${config.baseURL}/chat/completions`);
|
|
162
|
+
console.log(`[AI] 模型: ${config.model}, 消息数: ${messages.length}`);
|
|
163
|
+
const response = await fetch(`${config.baseURL}/chat/completions`, {
|
|
164
|
+
method: 'POST',
|
|
165
|
+
headers: {
|
|
166
|
+
'Content-Type': 'application/json',
|
|
167
|
+
'Authorization': `Bearer ${config.apiKey}`
|
|
168
|
+
},
|
|
169
|
+
body: JSON.stringify({
|
|
170
|
+
model: config.model,
|
|
171
|
+
messages,
|
|
172
|
+
temperature: config.temperature ?? 0.7,
|
|
173
|
+
max_tokens: config.maxTokens ?? 4000
|
|
174
|
+
})
|
|
175
|
+
});
|
|
176
|
+
console.log(`[AI] 响应状态: ${response.status} ${response.statusText}`);
|
|
177
|
+
if (!response.ok) {
|
|
178
|
+
const errorText = await response.text();
|
|
179
|
+
console.error(`[AI] API错误: ${errorText}`);
|
|
180
|
+
throw new AppError('AI_ERROR', `自定义API错误 (${response.status}): ${errorText}`);
|
|
181
|
+
}
|
|
182
|
+
const data = await response.json();
|
|
183
|
+
console.log(`[AI] 响应成功,使用 tokens:`, data.usage);
|
|
184
|
+
const content = data.choices?.[0]?.message?.content;
|
|
185
|
+
if (!content) {
|
|
186
|
+
console.error(`[AI] 响应缺少内容:`, JSON.stringify(data, null, 2));
|
|
187
|
+
throw new AppError('AI_ERROR', 'API响应缺少内容字段');
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
content,
|
|
191
|
+
usage: data.usage,
|
|
192
|
+
model: data.model
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=aiAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aiAdapter.js","sourceRoot":"","sources":["../../src/adapters/aiAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AppContext } from '../core/ports.js';
|
|
2
|
+
import type { AIConfig } from '../core/types.js';
|
|
3
|
+
export interface AdapterConfig {
|
|
4
|
+
ai: AIConfig;
|
|
5
|
+
}
|
|
6
|
+
export declare function createAppContext(config: AdapterConfig): AppContext;
|
|
7
|
+
export * from './aiAdapter.js';
|
|
8
|
+
export * from './storageAdapter.js';
|
|
9
|
+
export * from './validationAdapter.js';
|
|
10
|
+
export * from './logger.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAMjD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,QAAQ,CAAC;CACd;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAQlE;AAED,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Adapters层导出
|
|
2
|
+
// 组装所有适配器
|
|
3
|
+
import { AIAdapter } from './aiAdapter.js';
|
|
4
|
+
import { StorageAdapter, ProjectStorageAdapter } from './storageAdapter.js';
|
|
5
|
+
import { ValidationAdapter } from './validationAdapter.js';
|
|
6
|
+
import { ConsoleLogger } from './logger.js';
|
|
7
|
+
export function createAppContext(config) {
|
|
8
|
+
return {
|
|
9
|
+
ai: new AIAdapter(),
|
|
10
|
+
storage: new StorageAdapter(),
|
|
11
|
+
projectStorage: new ProjectStorageAdapter(),
|
|
12
|
+
validation: new ValidationAdapter(),
|
|
13
|
+
logger: new ConsoleLogger()
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export * from './aiAdapter.js';
|
|
17
|
+
export * from './storageAdapter.js';
|
|
18
|
+
export * from './validationAdapter.js';
|
|
19
|
+
export * from './logger.js';
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,UAAU;AAIV,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAM5C,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IACpD,OAAO;QACL,EAAE,EAAE,IAAI,SAAS,EAAE;QACnB,OAAO,EAAE,IAAI,cAAc,EAAE;QAC7B,cAAc,EAAE,IAAI,qBAAqB,EAAE;QAC3C,UAAU,EAAE,IAAI,iBAAiB,EAAE;QACnC,MAAM,EAAE,IAAI,aAAa,EAAE;KAC5B,CAAC;AACJ,CAAC;AAED,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LoggerPort } from '../core/ports.js';
|
|
2
|
+
export declare class ConsoleLogger implements LoggerPort {
|
|
3
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
4
|
+
error(message: string, error?: Error | unknown): void;
|
|
5
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
6
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
7
|
+
progress(stage: string, current: number, total: number, message: string): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/adapters/logger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,qBAAa,aAAc,YAAW,UAAU;IAC9C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI;IAIrD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI5D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAK/E"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Adapter - 日志记录器
|
|
2
|
+
// 简单的控制台日志实现
|
|
3
|
+
export class ConsoleLogger {
|
|
4
|
+
info(message, data) {
|
|
5
|
+
console.log(`[INFO] ${message}`, data ? JSON.stringify(data, null, 0) : '');
|
|
6
|
+
}
|
|
7
|
+
error(message, error) {
|
|
8
|
+
console.error(`[ERROR] ${message}`, error instanceof Error ? error.message : error);
|
|
9
|
+
}
|
|
10
|
+
warn(message, data) {
|
|
11
|
+
console.warn(`[WARN] ${message}`, data ? JSON.stringify(data, null, 0) : '');
|
|
12
|
+
}
|
|
13
|
+
debug(message, data) {
|
|
14
|
+
console.debug(`[DEBUG] ${message}`, data ? JSON.stringify(data, null, 0) : '');
|
|
15
|
+
}
|
|
16
|
+
progress(stage, current, total, message) {
|
|
17
|
+
const percent = Math.round((current / total) * 100);
|
|
18
|
+
const bar = '█'.repeat(Math.round(percent / 5)) + '░'.repeat(20 - Math.round(percent / 5));
|
|
19
|
+
console.log(`[${bar}] ${percent}% | ${stage}: ${message}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/adapters/logger.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAClB,aAAa;AAIb,MAAM,OAAO,aAAa;IACxB,IAAI,CAAC,OAAe,EAAE,IAA8B;QAClD,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,KAAuB;QAC5C,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,EAAE,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACtF,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA8B;QAClD,OAAO,CAAC,IAAI,CAAC,UAAU,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA8B;QACnD,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,OAAe,EAAE,KAAa,EAAE,OAAe;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;QACpD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3F,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,OAAO,OAAO,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC;IAC7D,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { StoragePort, ProjectStoragePort } from '../core/ports.js';
|
|
2
|
+
import type { NovelProject } from '../core/types.js';
|
|
3
|
+
export declare class StorageAdapter implements StoragePort {
|
|
4
|
+
writeFile(filePath: string, content: string): Promise<void>;
|
|
5
|
+
readFile(filePath: string): Promise<string>;
|
|
6
|
+
fileExists(filePath: string): Promise<boolean>;
|
|
7
|
+
ensureDir(dirPath: string): Promise<void>;
|
|
8
|
+
listFiles(dir: string, pattern?: string): Promise<string[]>;
|
|
9
|
+
}
|
|
10
|
+
export declare class ProjectStorageAdapter implements ProjectStoragePort {
|
|
11
|
+
private storage;
|
|
12
|
+
saveProject(project: NovelProject, basePath: string): Promise<void>;
|
|
13
|
+
loadProject(projectId: string, basePath: string): Promise<NovelProject | null>;
|
|
14
|
+
projectExists(projectId: string, basePath: string): Promise<boolean>;
|
|
15
|
+
listProjects(basePath: string): Promise<string[]>;
|
|
16
|
+
private generateRequirementsMarkdown;
|
|
17
|
+
private generateWorldMarkdown;
|
|
18
|
+
private generateOutlineMarkdown;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=storageAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storageAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/storageAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAIrD,qBAAa,cAAe,YAAW,WAAW;IAC1C,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3C,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS9C,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CASlE;AAED,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,OAAO,CAAC,OAAO,CAAwB;IAEjC,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BnE,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAU9E,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpE,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAsBvD,OAAO,CAAC,4BAA4B;IAkCpC,OAAO,CAAC,qBAAqB;IAwC7B,OAAO,CAAC,uBAAuB;CA8BhC"}
|