AI 小说工坊:主编 + 作家多模型协作写作应用
- Nuxt 4 + Nuxt UI 4 + AI SDK 7 + Drizzle/SQLite - 主编规划大纲与章节简报、选派作家;作家流式写入章节文件并实时推送前端 - 逐章确认模式(默认)与自动模式;摘要与故事记忆 - 酒馆角色卡(PNG/JSON,V1-V3)与世界书导入 - 自定义最高优先级系统提示词、审稿/修改/多版本、任务日志与提示词检视 - 模拟 LLM 服务与端到端测试脚本 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
export type ProviderType = 'openai-compatible' | 'anthropic' | 'google'
|
||||
|
||||
export type AgentRole = 'editor' | 'writer' | 'summarizer'
|
||||
|
||||
/**
|
||||
* 章节状态流转:
|
||||
* planned(大纲已规划)→ briefed(主编已写简报)→ writing(作家写作中)
|
||||
* → written(等待用户确认)→ approved(已确认,摘要已入库)
|
||||
*/
|
||||
export type ChapterStatus = 'planned' | 'briefed' | 'writing' | 'written' | 'approved'
|
||||
|
||||
export type VersionStatus = 'writing' | 'done' | 'error' | 'cancelled'
|
||||
|
||||
export type JobType = 'outline' | 'brief' | 'write' | 'summarize' | 'review' | 'pipeline'
|
||||
|
||||
export type JobStatus = 'running' | 'done' | 'error' | 'cancelled'
|
||||
|
||||
export type LoreEntrySource = 'user' | 'card'
|
||||
|
||||
export interface ProjectRequirements {
|
||||
/** 文风,如:细腻、冷峻、轻松幽默 */
|
||||
style: string
|
||||
/** 输出语言 */
|
||||
language: string
|
||||
/** 叙事视角:第一人称 / 第三人称有限 / 全知 */
|
||||
pov: string
|
||||
/** 叙述方式补充:时态、节奏、对白比例等 */
|
||||
narration: string
|
||||
/** 每章目标字数 */
|
||||
wordsPerChapter: number
|
||||
/** 其他要求(禁用词、尺度等) */
|
||||
extra: string
|
||||
}
|
||||
|
||||
export interface ProjectSettings {
|
||||
/** 自动模式:章节写完后自动确认并继续下一章 */
|
||||
autoMode: boolean
|
||||
/** 主编写完简报后暂停,等用户确认简报 */
|
||||
pauseAfterBrief: boolean
|
||||
/** 允许主编自行创建作家 */
|
||||
allowEditorCreateWriters: boolean
|
||||
/** 注入给作家的上一章结尾字数 */
|
||||
prevTailChars: number
|
||||
/** 注入的最近章节摘要数量 */
|
||||
recentSummaryCount: number
|
||||
/** 输出被截断时自动续写的最大次数 */
|
||||
maxContinuations: number
|
||||
/** 自动模式下最多连续写作的章节数(防止失控) */
|
||||
autoChapterLimit: number
|
||||
}
|
||||
|
||||
export interface CharacterState {
|
||||
name: string
|
||||
state: string
|
||||
}
|
||||
|
||||
export interface Foreshadowing {
|
||||
text: string
|
||||
status: 'open' | 'resolved'
|
||||
chapter: number
|
||||
resolvedChapter?: number
|
||||
}
|
||||
|
||||
export interface ProjectMemory {
|
||||
characterStates: CharacterState[]
|
||||
foreshadowing: Foreshadowing[]
|
||||
timeline: { chapter: number, event: string }[]
|
||||
}
|
||||
|
||||
export const DEFAULT_REQUIREMENTS: ProjectRequirements = {
|
||||
style: '',
|
||||
language: '简体中文',
|
||||
pov: '第三人称有限视角',
|
||||
narration: '',
|
||||
wordsPerChapter: 3000,
|
||||
extra: ''
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: ProjectSettings = {
|
||||
autoMode: false,
|
||||
pauseAfterBrief: false,
|
||||
allowEditorCreateWriters: true,
|
||||
prevTailChars: 1500,
|
||||
recentSummaryCount: 5,
|
||||
maxContinuations: 2,
|
||||
autoChapterLimit: 10
|
||||
}
|
||||
|
||||
export const EMPTY_MEMORY: ProjectMemory = {
|
||||
characterStates: [],
|
||||
foreshadowing: [],
|
||||
timeline: []
|
||||
}
|
||||
|
||||
export const CHAPTER_STATUS_LABEL: Record<ChapterStatus, string> = {
|
||||
planned: '已规划',
|
||||
briefed: '已出简报',
|
||||
writing: '写作中',
|
||||
written: '待确认',
|
||||
approved: '已确认'
|
||||
}
|
||||
|
||||
export const CHAPTER_STATUS_COLOR: Record<ChapterStatus, 'neutral' | 'info' | 'warning' | 'primary' | 'success'> = {
|
||||
planned: 'neutral',
|
||||
briefed: 'info',
|
||||
writing: 'warning',
|
||||
written: 'primary',
|
||||
approved: 'success'
|
||||
}
|
||||
|
||||
export const ROLE_LABEL: Record<AgentRole, string> = {
|
||||
editor: '主编',
|
||||
writer: '作家',
|
||||
summarizer: '摘要员'
|
||||
}
|
||||
|
||||
export const JOB_TYPE_LABEL: Record<JobType, string> = {
|
||||
outline: '规划大纲',
|
||||
brief: '章节简报',
|
||||
write: '写作',
|
||||
summarize: '摘要',
|
||||
review: '审稿',
|
||||
pipeline: '流水线'
|
||||
}
|
||||
|
||||
/** 解析后的酒馆角色卡(统一为内部结构) */
|
||||
export interface ParsedCard {
|
||||
spec: 'v1' | 'v2' | 'v3'
|
||||
name: string
|
||||
description: string
|
||||
personality: string
|
||||
scenario: string
|
||||
firstMes: string
|
||||
mesExample: string
|
||||
systemPrompt: string
|
||||
postHistoryInstructions: string
|
||||
creatorNotes: string
|
||||
alternateGreetings: string[]
|
||||
tags: string[]
|
||||
world: string
|
||||
lore: { title: string, keys: string[], content: string, constant: boolean, enabled: boolean, order: number }[]
|
||||
raw: Record<string, unknown>
|
||||
}
|
||||
|
||||
/** 服务端推送给前端的事件 */
|
||||
export type ProjectEvent =
|
||||
| { type: 'job', job: JobInfo }
|
||||
| { type: 'delta', chapterId: string, versionId: string, text: string }
|
||||
| { type: 'chapter', chapterId: string }
|
||||
| { type: 'chapters' }
|
||||
| { type: 'agents' }
|
||||
| { type: 'pipeline', running: boolean, message?: string }
|
||||
| { type: 'log', level: 'info' | 'warn' | 'error', message: string }
|
||||
|
||||
export interface JobInfo {
|
||||
id: string
|
||||
type: JobType
|
||||
status: JobStatus
|
||||
chapterId: string | null
|
||||
agentName: string
|
||||
modelLabel: string
|
||||
inputTokens: number
|
||||
outputTokens: number
|
||||
error: string
|
||||
log: string
|
||||
createdAt: string | number | Date
|
||||
finishedAt: string | number | Date | null
|
||||
}
|
||||
Reference in New Issue
Block a user