# All files / modules/book-generator index.ts

0% Statements 0/55
0% Branches 0/1
0% Functions 0/1
0% Lines 0/55

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120

     /**
     * LangGraph 书籍生成器 - 主入口（策略门面）
     *
     * 使用策略模式，通过 strategies/selector.ts 配置切换不同生成方案
     *
     * 当前支持策略：
     *   1. sequential          - 串行（原始方案）
     *   2. one-step-outline     - 一步大纲 + 并行内容
     *   3. per-chapter          - 逐章内聚
     *   4. deep-plan-parallel   - DeepPlan+RichOutline+Concurrent+Edit（当前推荐，默认策略）
     *
     * 大纲层级（genLevel）：
     *   1 = 仅章（短文/小说/故事类）
     *   2 = 章→节（科普/商业/大众类）
     *   3 = 章→节→小节（教材/技术教程/专业类）
     */

    import { bookStore } from './book-generator.store';
    import { getScaleConfig } from './book-type-config';
    import { getCurrentStrategy, setCurrentStrategy, getAllStrategies, getCurrentStrategyName } from './strategies/selector';
    import type { StrategyName } from './strategies/selector';

    // ============ 书籍类型 → 大纲层级映射 ============

    const BOOK_TYPE_GEN_LEVEL: Record<string, number> = {
      '教材': 3,
      '技术教程': 3,
      '小说': 1,
      '传记': 1,
      '商业': 2,
      '科普': 2,
      '历史': 2,
      '学术': 3,
      '心理学': 2,
    };

    /**
     * 将书籍类型映射为大纲层级
     */
    export function mapBookTypeToGenLevel(bookType: string): number {
      return BOOK_TYPE_GEN_LEVEL[bookType] ?? 2;
    }

    /**
     * 根据书籍规模和话题文本自动推荐大纲层级
     * 增强版：如未指定 genLevel，会从话题文本推断书籍类型→层级
     */
    export function resolveGenLevel(bookScale: string, userGenLevel?: number | string, topic?: string): number {
      if (userGenLevel !== undefined && userGenLevel !== null) {
        const n = typeof userGenLevel === 'string' ? parseInt(userGenLevel) : userGenLevel;
        if ([1, 2, 3].includes(n)) return n;
      }
      const config = getScaleConfig(bookScale);
      if (!config) return 2;
      if (config.isShortArticle) return 1;

      // 从话题文本推断书籍类型，增强 genLevel 推荐准确度
      if (topic) {
        const text = topic.toLowerCase();
        if (/教材|教程|编程|开发|实战|教学|课程/i.test(text)) return 3;
        if (/小说|故事|传记|散文|诗歌/i.test(text)) return 1;
      }

      return 2;
    }

    // ============ 策略切换 API（外部可调用） ============

    export { setCurrentStrategy, getCurrentStrategyName, getAllStrategies } from './strategies/selector';
    export type { StrategyName } from './strategies/selector';

    // ============ 主类（策略门面） ============

    export class LangGraphBookGenerator {
      async generate(
        bookId: string,
        topic: string,
        bookScale: string = '1000',
        genLevel?: number
      ): Promise<void> {
        const userSpecified = genLevel !== undefined; // true=用户选了层级, false=自动
        const level = genLevel ?? resolveGenLevel(bookScale, undefined, topic);

        // 获取当前激活的策略并执行
        const strategy = getCurrentStrategy();
        console.log(`[LangGraph] 开始生成: bookId=${bookId}, scale=${bookScale}, genLevel=${level}, strategy=${strategy.name}`);

        await strategy.generate(bookId, topic, bookScale, level, userSpecified ? level : undefined);
      }
    }

    export const langGraphGenerator = new LangGraphBookGenerator();

    // 重新导出 book-type-config 中的函数供外部使用
    export { getScaleConfig } from './book-type-config';

    // ============ 独立大纲生成函数（供 API 预览调用，不依赖完整策略） ============

    import { callLLMWithMessages } from '../../services/llm';
    import { buildOutlineMessages } from './prompts/builder';
    import { parseOutline } from './parsers/outline.parser';

    /**
     * 独立的大纲生成函数（供 API 预览调用，不依赖策略系统）
     * 用于让用户在正式开始生成前预览大纲结构
     */
    export async function generateOutline(bookId: string, topic: string, bookScale: string = '1000'): Promise<any> {
      console.log('[generateOutline] 预览大纲, bookId:', bookId, 'scale:', bookScale);

      const messages = buildOutlineMessages(topic, bookScale);
      const response = await callLLMWithMessages(messages);
      const outline = parseOutline(response);

      if (!outline) {
        throw new Error('大纲解析失败');
      }

      return outline;
    }