image
VincentWei

天地间,浩然正气长存,为天地立心,为生民立命,为往圣继绝学,为万世开太平!

免责声明:网站内容仅供个人学习记录,禁做商业用途,转载请注明出处。

版权所有 © 2017-2020 NEUSNCP个人学习笔记 辽ICP备17017855号-2

多智能体系统日志诊断系统

VincentWei    2026年6月20日 17:28:52

  • LogGuard AI — 详细设计文档

    版本:V5 架构风格:ReAct + RAG + DeepThinking 多智能体 AIOps 技术基底:Next.js 16 + TypeScript + Tailwind CSS 4 + shadcn/ui


    目录

    1. 系统概述

    2. 五层架构设计

    3. 智能体设计

    4. 数据流

    5. C++ 代码分析模块

    6. 技术栈

    7. 关键设计决策


    1. 系统概述

    1.1 项目定位

    LogGuard AI 是一款基于 Next.js 16 + TypeScript多智能体日志分析、Debug、修复建议协同诊断系统,定位于 AIOps(AI for IT Operations)领域,目标是把"人工运维 → 工具化运维 → 智能化运维"的链条推进到最后一公里:

    • 输入:原始运行时日志(支持 Java/Python/Node 多语言堆栈)或 C++ 源代码 + 运行时日志(ASAN/Valgrind/GDB/编译器输出)。

    • 输出:结构化的根因分析(RCA)、按优先级排序的修复建议、风险评分、可追溯的证据链、可导出的诊断报告。

    • 过程:实时、可视化、可回放的多智能体协同推理过程(ReAct 思考-行动-观察流)。

    1.2 核心架构理念

    系统融合三种现代 LLM 推理范式:

    范式 全称 在系统中的作用
    ReAct Reason + Act 规划器(Planner)的"思考→行动→观察"循环,最多 5 轮自主迭代
    RAG Retrieval-Augmented Generation 检索器(Retriever)从知识库召回先验知识,注入到下游智能体的上下文
    DeepThinking 深度思考 / 内省式推理 深度思考器(DeepThinker)在置信度低或检测到矛盾时条件触发,对诊断进行批判性反思

    三者通过 反思闭环(Reflector Loop) 串联:分析师给出初步 RCA → 深度思考器审视 → 验证器证据链校验 → 反思器决定是否重新分析(最多 2 轮迭代)→ 修复器生成建议 → 复审器给出风险评分。整个过程由 Orchestrator(编排器) 统一调度,事件流经 Socket.io 实时推送到前端。

    1.3 多模型适配

    系统支持 4 种大模型,每种模型有独立的 persona、推理风格、系统提示词:

    模型 ID 标签 厂商 推理风格 适用场景
    qwen Qwen 阿里巴巴 direct(直接精确) 长上下文代码与日志理解
    glm GLM 智谱 AI tool-first(工具优先) 平衡推理 + 稳定 JSON 输出
    deepseek DeepSeek DeepSeek chain-of-thought(思维链) 深度逐步推理、数学逻辑、Debug
    stepfun 阶跃星辰 StepFun structured(结构化) 长文本理解、多模态、中文优化

    模型切换通过 UI 顶部的下拉选择器实时切换,不需要重启服务。底层调用统一抽象为 chat() 函数(src/lib/agents/llm.ts),支持两种后端路径:

    1. 用户自配置路径:若用户在设置面板配置了 LLM_BASE_URL / LLM_API_KEY / LLM_MODEL_NAME(OpenAI 兼容协议),系统直接用原生 fetch 调用用户配置的端点。

    2. 环境回退路径:未配置时回退到 z-ai-web-dev-sdk(无需 API Key)。


    2. 五层架构设计

    LogGuard AI 采用经典的分层架构,从下到上依次为:

    ┌─────────────────────────────────────────────────────────────────────┐
    │  5. 确定性验证与 RCA 生成层   Validator · Reflector · Analyst · Fixer │
    │      证据链闭环 · 交叉校验 · 幻觉检测 · RCA · 修复建议 · 复审          │
    ├─────────────────────────────────────────────────────────────────────┤
    │  4. DeepThinking & ReAct 推理层  Orchestrator + 10 智能体协同        │
    │      ReAct 循环 · 深度思考 · 反思迭代 · 智能体有向图编排              │
    ├─────────────────────────────────────────────────────────────────────┤
    │  3. 多维存储与 RAG 索引层   Prisma + SQLite · KB · IDF+正则检索      │
    │      知识库 17+ 篇 · RAG 打分检索 · 会话/事件/日志/代码持久化          │
    ├─────────────────────────────────────────────────────────────────────┤
    │  2. 智能压缩与上下文管理层   Drain 模板提取 · L1/L2/L3 三级压缩      │
    │      Token 预算管理 · 上下文窗口动态裁剪 · 按需片段召回                │
    ├─────────────────────────────────────────────────────────────────────┤
    │  1. 实时采集与流处理层   日志解析器 · 大文件流式上传 · SSE 实时 tail  │
    │      多格式时间戳/堆栈识别 · 批量分片 (50k 行/批) · Drain 模板归并     │
    └─────────────────────────────────────────────────────────────────────┘
                                ▲
                                │ HTTP / Socket.io
                                ▼
            ┌────────────────────────────────────────────┐
            │  前端:Next.js 16 + Tailwind 4 + shadcn/ui │
            │  三栏可拖拽面板 · ReAct 事件流 · 诊断报告    │
            └────────────────────────────────────────────┘

    2.1 第一层:实时采集与流处理层

    职责:把异构的原始日志/源代码统一规范化为结构化对象 ParsedLog,并支持大文件的分片流式处理。

    核心组件

    组件 文件 职责
    日志解析器 src/lib/agents/log-parser.ts 多格式时间戳识别、Java/Python/Node 堆栈提取、level 归一化(INFO/WARN/ERROR/DEBUG/TRACE/FATAL)、tag 自动打标
    日志摘要器 log-parser.ts#digestLogs 统计 total/errors/warnings/byLevel,给出快速 digest
    Auto-Collect src/app/api/logs/collect/route.ts 自动读取 sample-logs/ 目录下的 .log/.txt 文件
    流式上传 src/app/api/logs/stream-upload/route.ts 大文件上传(>100 万行),按 50k 行/批分片解析,最大上限 1000 万行
    SSE 实时 tail src/app/api/logs/tail/route.ts Server-Sent Events 端点,2 秒轮询 + 10 秒心跳,检测日志轮转(truncation)
    Drain 模板提取 src/lib/agents/log-template.ts 经典 Drain 算法,把相似日志行归并为 <*> 模板,统计每类模板出现次数

    Drain 模板提取算法

    1. tokenize:按空格切分。

    2. isVariable:数字、十六进制地址、IP、路径、带引号字符串、0xXXXX 等识别为变量。

    3. generalize:变量替换为 <*> 占位符,同时记录原值到 params

    4. similarity:基于 token 位置匹配度计算两条日志的相似度(阈值 0.5)。

    5. 归并:相似日志合并到同一模板组,保留最多 3 条示例。

    输出数据结构

    interface ParsedLog {
      raw: string;            // 原始日志行
      timestamp?: string;     // 解析出的时间戳
      level: string;          // INFO | WARN | ERROR | DEBUG | TRACE | FATAL
      source?: string;        // 文件名 / 组件名
      message: string;        // 提取的日志消息正文
      stack?: string;         // 堆栈(多行合并)
      tags: string[];         // 自动打标的类别标签
    }

    2.2 第二层:智能压缩与上下文管理层

    职责:当日志体量超出 LLM 上下文窗口时,通过三级压缩把"百万行日志"塞进"8k token 预算",同时保留诊断所需的关键信号。

    核心组件

    组件 文件 输出
    三级压缩器 src/lib/agents/context-compressor.ts L1 + L2 + L3 三段拼接的 CompressedContext
    上下文管理器 src/lib/agents/context-manager.ts ManagedContext:预算使用情况 + 可按需加载的片段
    Token 估算器 context-manager.ts#estimateTokens CJK 字符 ÷2 + 其他字符 ÷4

    L1/L2/L3 三级压缩策略

    级别 名称 内容 上限
    L1 宏观压缩 时间线摘要:按时间桶(分钟级)聚合,给出每桶日志数 / 错误数 / 警告数 4000 字符
    L2 中观结构化 因果链:抽取 traceId/requestId,按 trace 聚合相关日志;无 trace 时按错误因果排序 2000 字符
    L3 微观裁剪 错误行 ±5 行的完整上下文(最多 10 个错误点),其余行折叠为模板引用 6000 字符

    Token 预算管理(默认 8k 总预算)

    ┌────────────────────────────────────────────────┐
    │  总预算:8000 tokens                            │
    ├──────────────┬─────────────────────────────────┤
    │ 系统提示词   │ 1000 tokens                     │
    ├──────────────┼─────────────────────────────────┤
    │ 压缩日志     │ 3000 tokens (L1 + L2 + L3)      │
    ├──────────────┼─────────────────────────────────┤
    │ RAG 召回     │ 2000 tokens (知识库命中条目)     │
    ├──────────────┼─────────────────────────────────┤
    │ 推理预留     │ 2000 tokens (LLM 思考 + 输出)    │
    └──────────────┴─────────────────────────────────┘

    按需片段召回:除了 active window 外,上下文管理器还会预生成 20+ 个"可加载片段"(错误行周边上下文、模板示例、错误 burst 段),当下游智能体需要更细的上下文时,可显式请求加载某一片段,避免一次性塞满 context。

    2.3 第三层:多维存储与 RAG 索引层

    职责:把会话、日志、事件、知识库、代码、问题、模型配置等多维数据持久化到 SQLite(通过 Prisma ORM),并提供基于 IDF + 正则增强的关键词 RAG 检索。

    数据库表(详见 prisma/schema.prisma

    表名 用途 关键字段
    AnalysisSession 诊断会话 title, model, status, severity, rootCause(JSON), fixes(JSON), summary(JSON)
    LogEntry 解析后的单行日志 sessionId, raw, level, message, stack, tags
    AgentEvent 智能体事件流 sessionId, agent, type, content, meta(JSON)
    KnowledgeArticle 知识库条目 title, category, pattern(正则), summary, cause, fix, keywords
    CodeFile C++ 源文件 sessionId, path, content, lineCount
    CodeIssue C++ 静态分析问题 sessionId, ruleId, severity, line, snippet, suggestion, fixCode, cwe
    LlmConfig LLM 提供商配置 provider, baseUrl, apiKey, modelName, enabled

    RAG 检索算法(knowledge-base.ts#retrieveKB

    检索器采用 IDF 加权 + 正则模式增强 + 类别子串加分 的混合打分策略,无外部向量依赖:

    1. Tokenize:将查询切分为小写 token。

    2. IDF 权重:预计算每个词的文档频率 df[t],匹配词加 log(totalArticles / df[t])(最低 0.1 防止通用词得分为 0)。

    3. 正则模式增强:将每篇 KB 文章的 pattern 字段(正则表达式)编译为 RegExp,对原始查询字符串执行 test,命中加 +3 分。

    4. 类别子串加分:若查询包含某文章的 category 子串,加 +2 分。

    5. TopN 召回:按总分降序,默认返回 Top 4。

    知识库内容(17+ 篇):覆盖 NPE、OOM、连接池耗尽、SQL 错误、死锁、网络超时、TLS 失败、磁盘满、JSON 解析、认证失败、原生崩溃、CPU 节流、限流 429、SLA 超时、Schema 不匹配、内存泄漏、GC 开销,以及 C++ 专题(内存泄漏、Use-After-Free、未初始化、数据竞争、RAII 违反、智能指针迁移)。

    2.4 第四层:DeepThinking & ReAct 推理层

    职责:核心智能体协同层。10 个智能体按有向图编排,由 Orchestrator 统一调度,支持条件触发、反思迭代、并行/串行混合执行。

    节点流(有向图)

                    ┌──────────┐
                    │Collector │ 采集 + 解析 + 标签
                    └────┬─────┘
                         ▼
                    ┌──────────┐
                    │Retriever │ RAG 召回先验知识
                    └────┬─────┘
                         ▼
                    ┌──────────┐
                    │ Planner  │ ReAct 循环(最多 5 轮)
                    └────┬─────┘
                         ▼
                  ┌──────────────┐
                  │  Analyst     │ RCA 初步分析
                  └──────┬───────┘
                         ▼
           ┌─────────────────────────────┐
           │  迭代循环(最多 2 轮)       │
           │  ┌──────────────┐           │
           │  │ DeepThinker  │ 条件触发   │
           │  └──────┬───────┘           │
           │         ▼                   │
           │  ┌──────────────┐           │
           │  │  Validator   │ 证据链验证 │
           │  └──────┬───────┘           │
           │         ▼                   │
           │  ┌──────────────┐           │
           │  │  Reflector   │ 闭环反思   │
           │  └──────┬───────┘           │
           │         │ should_re_analyze?│
           └─────────┼───┬───────────────┘
                     │   │
                No  │   │ Yes
                     ▼   └─────► 回到 Analyst
                ┌──────────┐
                │  Fixer   │ P0-P3 修复建议
                └────┬─────┘
                     ▼
                ┌───────────┐
                │ Reviewer  │ 复审 + 风险评分 0-100
                └───────────┘

    条件触发规则

    • DeepThinker:当 rca.confidence < 0.7 或检测到矛盾或 evidence 为空时触发。

    • Reflector:当 Validator 判定 validated = false,或 DeepThinker 判定 verdict = rejected | needs_more_evidence 时触发;最多迭代 2 轮。

    • 重新分析:Reflector 决定 should_re_analyze = true 时,回到 Analyst 重新执行 RCA,Reflector 可能给出新的 focus_areasnew_search_queries

    ReAct 循环(Planner):每轮 LLM 自主选择 5 种 action 之一:search_knowledge / inspect_errors / inspect_metrics / trace_request / form_plan。当 LLM 返回 form_plan 或达到 MAX_CYCLES=5 时退出,输出结构化的 AnalysisPlan(含 goal/steps/hypotheses)。

    2.5 第五层:确定性验证与 RCA 生成层

    职责:确保诊断结果逼近"100% 确定性"——通过证据链闭环、交叉校验、幻觉检测三重机制,把 LLM 的概率性输出约束为可追溯、可验证、可解释的结构化结论。

    三重验证机制

    2.5.1 证据链闭环(Validator)

    构建 根因 ← 证据1 ← 证据2 ← 证据3 ← 触发器 的有向链图,每个节点必须引用真实的日志行:

    interface EvidenceChainNode {
      node: string;                                  // 节点名称
      type: "root_cause" | "evidence" | "trigger";   // 节点类型
      ref: string;                                   // 引用的日志行
    }

    2.5.2 交叉校验(Validator)

    对 RCA 中每个声明,验证支持性日志信号是否确实出现:

    RCA 声明 期望日志信号
    "网络问题" ECONNREFUSED / ETIMEDOUT / socket hang up
    "内存泄漏" OutOfMemoryError / heap space / GC overhead
    "连接池耗尽" HikariPool / Connection is not available / pool exhausted
    "死锁" Found one Java-level deadlock / waiting to lock

    输出 crossValidation[],每条记录 {claim, supported, reason},未支持的声明计入 hallucination_warnings

    2.5.3 幻觉检测(Validator)

    若 RCA 引用的 evidence 实际上未出现在原始日志中,标记为幻觉。Validator 根据"支持 vs 不支持"的声明比例调整置信度,输出 adjustedConfidence

    RCA 输出结构(RootCauseAnalysis

    {
      severity: "critical" | "high" | "medium" | "low",
      primaryRootCause: string,                     // 主根因(一句话)
      contributingFactors: string[],                // 促成因素
      evidence: { log: string; explanation: string }[],  // 证据链(必须引用真实日志行)
      timeline: { time: string; event: string }[],  // 时间线
      impactAssessment: string,                     // 影响评估
      confidence: number                            // 0-1,经多重校准
    }

    置信度校准:原始 confidence 来自 Analyst,DeepThinker 给出 confidence_adjustment(-0.2 ~ +0.1),Validator 给出 adjustedConfidence,三者合并后写入最终 RCA。RCA prompt 中包含置信度校准带(low <50% / medium 50-70% / high 70-90% / very-high >90%),禁止使用"无法确定"作为回退。


    3. 智能体设计

    系统共有 10 个智能体(9 个业务智能体 + 1 个编排器),全部位于 src/lib/agents/

    3.1 Orchestrator(编排器)

    内容
    文件 orchestrator.ts
    角色 整个多智能体有向图的统一调度器
    输入 { sessionId, rawLogs, model, source }
    输出 AnalysisResult(含 plan/rca/fixes/review/knowledgeHits/logStats)
    触发条件 由 Socket.io "analyze" 事件触发
    职责 (1) 顺序调度 9 个业务智能体;(2) 管理反思迭代循环(最多 2 轮);(3) 通过 EventSink 把每个事件持久化到 DB + 推送到 Socket;(4) 异常时把 session 状态置为 failed
    关键流程 采集 → 检索 → 规划 → [分析 → 深度思考 → 验证 → 反思]×N → 修复 → 复审

    3.2 Collector(采集器)

    内容
    文件 collector.ts
    角色 日志结构化解析器
    输入 rawLogs: string, source?: string
    输出 { entries: ParsedLog[], digest: string, stats: { total, errors, warnings, byLevel } }
    触发条件 Orchestrator 启动后第一个执行
    职责 (1) 多格式时间戳识别(ISO 8601 / yyyy-MM-dd HH:mm:ss.SSS / Syslog 等);(2) Java/Python/Node 堆栈多行合并;(3) level 归一化;(4) 自动打标(memory/network/database/concurrency/auth/json 等);(5) 统计错误/警告计数;(6) 生成 1000 字以内的 digest 摘要
    事件流 status: "采集器已启动"result: "解析 N 行日志,错误 X,警告 Y"

    3.3 Retriever(检索器 - RAG)

    内容
    文件 retriever.ts
    角色 知识库 RAG 检索器
    输入 entries: ParsedLog[], digest: string, model: ModelId
    输出 { hits: KnowledgeHit[], expandedQuery: string }
    触发条件 Collector 完成后
    职责 (1) 用 LLM 扩展原始查询(同义词、相关错误模式);(2) 调用 retrieveKB(query, 4) 进行 IDF + 正则 + 类别子串三重打分检索;(3) 返回 Top 4 命中条目作为下游智能体的先验知识
    设计权衡 不使用向量嵌入,避免引入 sentence-transformers 等重依赖;IDF + 正则在生产环境验证已能覆盖常见错误模式

    3.4 Planner(规划器 - ReAct)

    内容
    文件 planner.ts
    角色 ReAct 循环规划器
    输入 entries, digest, knowledgeHits, model
    输出 { plan: AnalysisPlan, reactTrail: ReActStep[] }
    触发条件 Retriever 完成后
    职责 真正的动态 ReAct 循环:while (cycle < MAX_CYCLES=5 && currentAction !== "form_plan"),每轮 LLM 自主选择 5 种 action 之一
    可用 Actions search_knowledge(再查知识库)/ inspect_errors(看错误行)/ inspect_metrics(统计错误率、Top error sources)/ trace_request(按 traceId 聚合)/ form_plan(形成最终计划,退出循环)
    安全机制 (1) 无效 JSON → 默认 inspect_errors 继续;(2) 未知 action → 同上;(3) 达到 MAX_CYCLES → 安全网 form_plan;(4) executeAction 统一调度,移除了重复代码

    3.5 Analyst(分析师 - RCA)

    内容
    文件 analyst.ts
    角色 根因分析(RCA)生成器
    输入 entries, digest, knowledgeHits, plan, model
    输出 RootCauseAnalysis
    触发条件 Planner 完成后;反思器决定重新分析时也会回到这里
    职责 (1) 输出主根因 + 促成因素 + 证据链 + 时间线 + 影响评估 + 严重程度 + 置信度;(2) 强制证据引用真实日志行(拒绝"unable to determine"回退);(3) 传递完整 12 帧堆栈 + 跨所有 ERROR/FATAL 行的 tag 汇总(FREQUENT TAGS 段)
    Prompt 设计 ANALYST_PROMPT 包含 DIRECTIVE 段(强制识别根因)+ COMMON PATTERNS 段(OOM / 连接池 / 网络超时 / 401-403 / JSON / 死锁 / SQL / NPE / Timeout 共 9 类先验)+ EVIDENCE DISCIPLINE 段 + CONFIDENCE CALIBRATION 段

    3.6 DeepThinker(深度思考器 - 条件触发)

    内容
    文件 deep-thinker.ts
    角色 内省式深度推理智能体
    输入 rca, entries, plan, model
    输出 DeepThinkerResult(reasoning / verdict / gaps / alternative_hypotheses / confidence_adjustment / additional_investigation)
    触发条件 shouldDeepThink()rca.confidence < 0.7 或检测到矛盾或 evidence 为空
    职责 在 5 个维度进行系统性深度推理:证据链完整性、替代假设分析、时间因果一致性、逻辑推理审查、系统性风险反思
    输出 verdict confirmed(确认)/ rejected(拒绝)/ needs_more_evidence(需更多证据)
    置信度调整 -0.2 ~ +0.1 的微调,由 Orchestrator 应用到 rca.confidence 并 clamp 到 [0.1, 0.99]
    矛盾检测 detectContradictions(rca, entries):检测时间矛盾(果先于因)、空间矛盾(证据缺失)、因果矛盾(声称 A 导致 B 但无关联日志)

    3.7 Validator(验证器 - 证据链验证)

    内容
    文件 validator.ts
    角色 证据链闭环验证 + 交叉校验 + 幻觉检测
    输入 rca, entries, knowledgeHits, model
    输出 ValidatorResult(validated / evidenceChain / crossValidation / adjustedConfidence / gaps / hallucination_warnings / systemic_risks)
    触发条件 每轮迭代中,DeepThinker 之后(无论 DeepThinker 是否触发)
    职责 (1) 构建 根因 ← 证据 ← 触发器 有向证据链图;(2) 对每个声明交叉验证支持性信号是否真实出现;(3) 检测 LLM 幻觉(声明引用的日志实际不存在);(4) 根据"支持 vs 不支持"比例校准 adjustedConfidence;(5) 检查系统性风险(部署变更、流量突增、依赖级联)

    3.8 Reflector(反思器 - 闭环迭代)

    内容
    文件 reflector.ts
    角色 闭环反思与迭代改进决策者
    输入 rca, plan, deepThinkResult, validationResult, model, iteration
    输出 ReflectorResult(reflection / should_re_analyze / improvements / new_search_queries / focus_areas / accept_with_caveats / iteration_count)
    触发条件 !validated 或 DeepThinker verdict ∈ {rejected, needs_more_evidence},且 iteration < MAX_ITERATIONS=2
    职责 (1) 流程反思:采集是否遗漏、RAG 查询是否正确、ReAct 路径是否最优、分析师是否忽略重要证据;(2) 改进策略:是否需要补充信息、调整查询、扩大时间窗口;(3) 迭代决策:当前诊断可接受 / 必须重新分析
    关键决策 should_re_analyze = true 时,Orchestrator 调用 runAnalyst 重新生成 RCA,进入下一轮迭代

    3.9 Fixer(修复器)

    内容
    文件 fixer.ts
    角色 修复建议生成器
    输入 rca, model
    输出 FixSuggestion[]
    触发条件 反思迭代循环退出后(即诊断被接受)
    职责 (1) 生成 P0-P3 优先级的修复建议;(2) 每条建议含 type(code/config/infra/process)、description、codeSnippet、preventionTip、estimatedEffort;(3) 修复建议与根因直接相关(由 Validator 在前一步已校验)
    interface FixSuggestion {
      title: string;
      type: "code" | "config" | "infra" | "process";
      priority: "P0" | "P1" | "P2" | "P3";
      description: string;
      codeSnippet?: { language: string; code: string };
      preventionTip: string;
      estimatedEffort: string;
    }

    3.10 Reviewer(复审器)

    内容
    文件 reviewer.ts
    角色 最终复审与风险评估
    输入 plan, rca, fixes, model
    输出 ReviewResult(overallAssessment / strengths / gaps / additionalRecommendations / riskScore)
    触发条件 Fixer 完成后,整个流水线的最后一步
    职责 (1) 综合评估整个诊断(计划合理性 + RCA 准确性 + 修复建议完整性);(2) 列出 strengths(做得好的地方)和 gaps(仍存在的不足);(3) 给出 additionalRecommendations;(4) 风险评分 0-100(0 = 无风险,100 = 极高风险)
    反思器联动 若 Reflector 给出了 accept_with_caveats(附带注意事项),Reviewer 会把它追加到 gaps[] 中,确保最终报告反映迭代过程中的不确定性

    4. 数据流

    4.1 实时事件流(Socket.io)

    LogGuard AI 采用 WebSocket(Socket.io) 实现前后端实时双向通信。前端通过 io("/?XTransformPort=3003") 经 Caddy 网关连接到独立的 agent-service(端口 3003)。

    架构

    ┌──────────────┐    HTTP/WS    ┌─────────┐    HTTP    ┌────────────────┐
    │   Browser    │ ◄───────────► │  Caddy  │ ◄────────► │  agent-service │
    │ (Next.js UI) │   :81         │  :81    │  :3003     │  (Socket.io)   │
    └──────────────┘               └─────────┘            └────────────────┘
           │                                                     │
           │ HTTP REST                                            │ 直接调用
           ▼                                                     ▼
    ┌──────────────┐                                       ┌────────────────┐
    │ Next.js API  │                                       │  Orchestrator  │
    │  Routes      │                                       │  + 9 Agents    │
    │ /api/*       │                                       └────────────────┘
    └──────────────┘                                               │
           │                                                       │ SQL
           ▼                                                       ▼
           └─────────────────► Prisma + SQLite ◄──────────────────┘

    XTransformPort 路由技巧:Caddyfile 配置 @transform_port_query { query XTransformPort=* },匹配到该查询参数的请求会被代理到 localhost:{query.XTransformPort}。这样前端用同一个域名 + 不同端口参数即可访问 Next.js 或 agent-service,避免 CORS。

    4.2 事件类型

    所有智能体通过 EventSink 投递事件,事件类型严格遵循 ReAct 范式:

    事件类型 含义 触发示例
    status 智能体状态变更(启动/完成/进入下一阶段) "采集器已启动" / "=== 第 1 轮诊断迭代 ==="
    thought ReAct 的"思考"步骤——智能体的内部独白 "触发深度思考器(置信度 65%,矛盾 2 个)"
    action ReAct 的"行动"步骤——智能体选择的动作 "action: search_knowledge"
    observation ReAct 的"观察"步骤——action 的执行结果 "命中知识库 3 条:OutOfMemoryError / GC overhead / memory-leak"
    result 智能体最终结果 "严重程度: HIGH,置信度: 85%,修复: 4 条"
    error 错误事件 "诊断流水线失败: LLM 超时"
    suggestion 修复建议或推荐操作 Fixer 输出的 P0-P3 建议

    每个事件结构:

    interface AgentEvent {
      sessionId: string;
      agent: AgentName;        // orchestrator | collector | retriever | ...
      type: EventType;         // status | thought | action | observation | result | error | suggestion
      content: string;         // 人类可读的事件内容
      meta?: Record<string, unknown>;  // 可选的结构化元数据
      timestamp: string;       // ISO 8601
    }

    4.3 事件持久化与回放

    所有事件双重持久化:

    1. 数据库AgentEvent 表,按 sessionId 索引,可按时间正序回放。

    2. 实时推送:通过 Socket.io 的 socket.emit("agent-event", ev) 推送到对应客户端。

    历史会话通过 GET /api/sessions/[id] 接口获取完整回放(result + events 数组),前端可"原样"重现整个诊断过程。

    4.4 并发控制

    agent-service 内置并发限流(MAX_CONCURRENT=3):

    • FIFO 队列:超出并发上限的请求进入队列,发出 analysis-queued 事件告知客户端排队位置。

    • 超时拒绝:排队超过 QUEUE_TIMEOUT_MS=120000(2 分钟)的请求被拒绝,发出错误事件。

    • 会话防重入activeRuns Map 防止同一 sessionId 同时跑两个分析。

    • 资源释放try/catch/finally 保证 release() 一定执行,pumpQueue() 把队首提升到空闲槽位。


    5. C++ 代码分析模块

    C++ 代码分析是一个独立但并行的子系统,与日志诊断共享同一个 AnalysisSession 数据模型,但走完全不同的智能体流水线。

    5.1 整体流程

    ┌──────────────┐
    │ C++ 源代码    │
    │ + 运行时日志  │
    └──────┬───────┘
           ▼
    ┌──────────────────┐
    │  CppParser       │  注释剥离 + AST 提取(函数/类/全局/包含)
    └──────┬───────────┘
           ▼
    ┌──────────────────┐
    │  CppAnalyzer     │  15 条规则静态扫描
    └──────┬───────────┘
           ▼
    ┌──────────────────────┐
    │ CppRuntimeParser     │  运行时日志信号提取
    │ (ASAN/Valgrind/GDB/  │  (compiler/asan/valgrind/gdb/stderr/runtime/other)
    │  compiler/stderr)    │
    └──────┬───────────────┘
           ▼
    ┌──────────────────────┐
    │  Signal × Issue 关联 │  交叉关联:静态问题 ↔ 运行时信号
    └──────┬───────────────┘
           ▼
    ┌──────────────────────┐
    │  CppOrchestrator     │  LLM 综合分析 + Top Risk Areas + 修复计划
    └──────────────────────┘

    5.2 静态分析 15 条规则

    15 条规则覆盖内存、RAII、Modern C++、未定义行为、并发、性能 6 大类别,每条规则有 ruleIdseveritycwe(CVE 编号)、confidencemessageexplanationsuggestionfixCode

    规则 ID 规则名称 类别 严重程度 CWE
    CPP-MEM-001 Memory Leak (raw new without delete) memory high CWE-401
    CPP-MEM-002 Memory Leak (malloc without free) memory high CWE-401
    CPP-MEM-003 Mismatched delete (delete on array allocated with new[]) memory high CWE-762
    CPP-MEM-004 Dangling pointer risk (raw pointer returned) memory medium CWE-674
    CPP-RAII-001 Raw new/delete (prefer smart pointers) raii medium CWE-401
    CPP-RAII-002 Resource leak (fopen without fclose) raii high CWE-775
    CPP-MOD-001 NULL used instead of nullptr modern-cpp low
    CPP-MOD-002 C-style cast used modern-cpp low
    CPP-UB-001 Uninitialized local variable undefined-behavior high CWE-457
    CPP-UB-002 Use-after-free risk undefined-behavior high CWE-416
    CPP-UB-003 Potential null pointer dereference undefined-behavior medium CWE-476
    CPP-CONC-001 Shared mutable data without synchronization concurrency high CWE-362
    CPP-CONC-002 std::thread created without join() or detach() concurrency medium CWE-666
    CPP-PERF-001 Large parameter passed by value performance low
    CPP-PERF-002 std::endl causes unnecessary flush performance low

    规则设计原则

    • 保守优先:false positive 比 false negative 更糟,所以 confidence 在 0.5-0.9 之间。

    • 作用域感知:通过 extractFunctionScopes() 把每个 new/malloc 关联到所在函数作用域,作用域内是否有匹配的 delete/free 决定是否报错。

    • 可恢复:单条规则抛错不会中断整体分析(try/catch 包裹每条规则)。

    • 修复代码:每条规则提供 fixCode 示例,例如 auto x = std::make_unique<...>(); // RAII

    5.3 运行时日志深度诊断

    cpp-runtime-parser.ts 实现运行时日志信号提取,覆盖 6 种来源:

    来源 模式数 典型场景
    ASAN (AddressSanitizer) 10+ heap-buffer-overflow / stack-buffer-overflow / heap-use-after-free / stack-use-after-return / use-after-scope / double-free / memory-leak / null-deref / ASAN 堆栈帧解析
    Valgrind 5+ definitely lost / indirectly lost / possibly lost / still reachable / Invalid read/write
    GDB 5+ SIGSEGV / SIGABRT / SIGFPE / #0..#N 堆栈帧 / Program received signal
    编译器 (gcc/clang) 5+ error: / warning: / note: / undefined reference / In function
    stderr 3+ Segmentation fault / Aborted / Floating point exception
    runtime 5+ generic runtime patterns

    信号提取输出CppRuntimeSignal):

    {
      source: "asan" | "valgrind" | "gdb" | "compiler" | "stderr" | "runtime" | "other",
      severity: "critical" | "high" | "medium" | "low" | "info",
      rawLine: string,           // 原始日志行
      line: number,              // 在运行时日志文本中的行号
      file?: string,             // 引用的源文件
      sourceLine?: number,       // 引用的源文件行号
      function?: string,         // 引用的函数名
      message: string,           // 解析后的人类可读消息
      address?: string,          // 内存地址(ASAN/Valgrind)
      category: string,          // "heap-buffer-overflow" / "segfault" / "leak" 等
      correlatedIssueRuleId?: string  // 关联到的静态规则 ID
    }

    5.4 信号与静态问题交叉关联

    correlateSignalsWithIssues(signals, issues) 把运行时信号与静态分析问题按 (file, line) 距离关联:

    • 若一个 ASAN heap-buffer-overflow 信号指向 foo.cpp:42,而静态规则 CPP-UB-002foo.cpp:40 报了 use-after-free 风险,则两者被关联,输出:

    {
      "signalId": "sig-001",
      "issueRuleId": "CPP-UB-002",
      "issueFile": "foo.cpp",
      "issueLine": 40,
      "confidence": 0.85,
      "note": "静态分析在 foo.cpp:40 标记 use-after-free 风险,ASAN 在 foo.cpp:42 确认发生 heap-use-after-free"
    }

    这种"静态预测 + 运行时确认"的交叉验证机制是 C++ 模块的核心创新——把静态分析的 false positive 风险通过运行时证据降到最低。


    6. 技术栈

    6.1 前端

    技术 版本 用途
    Next.js 16 App Router 框架,SSR + API Routes
    React 19 UI 库
    TypeScript 5 类型安全
    Tailwind CSS 4 原子化样式,含 dark: 暗色模式
    shadcn/ui latest 基于 Radix UI 的组件库(40+ 组件)
    Framer Motion 12 动画(报告切换 fade+slide、按钮光晕脉冲、agent pipeline 指示灯 ping)
    react-resizable-panels 3 可拖拽三栏面板布局(autoSaveId 持久化到 localStorage)
    react-markdown 10 Markdown 渲染(诊断报告、RCA、修复建议)
    lucide-react 0.525 图标库
    Zustand 5 状态管理(locale、currentSession、socket 连接状态等)
    socket.io-client 4 实时事件流接收
    next-themes 0.4 暗色模式切换

    6.2 后端

    技术 版本 用途
    Bun latest agent-service 运行时(端口 3003)
    Socket.io 4 WebSocket 服务端
    Prisma ORM 6 数据库 ORM
    SQLite 嵌入式数据库(db/custom.db
    Caddy 2 反向代理网关(端口 81)

    6.3 LLM 与 AI

    技术 用途
    z-ai-web-dev-sdk 默认 LLM 后端(无需 API Key 的回退路径)
    OpenAI-compatible API 用户自配置的 4 个提供商统一接口
    Drain 算法 日志模板提取
    IDF + 正则 RAG 无向量依赖的轻量级检索

    6.4 工程化

    技术 用途
    ESLint 代码风格检查(0 errors / 0 warnings)
    TypeScript strict mode 类型安全
    Bun lockfile 依赖锁定
    start-dev.sh / start-prod.sh 一键启动所有服务

    7. 关键设计决策

    7.1 为什么不用 LangGraph / LangChain?

    • 轻量化:本项目智能体间通信简单(顺序 + 条件分支),不需要 LangGraph 的复杂图编排。

    • 可控性:自研 Orchestrator 可精细控制事件流、并发、反思循环,避免黑盒。

    • 依赖最小化:Bun 运行时不依赖 Python 生态,部署简单。

    • 可选 Python 实现:项目同时提供了 mini-services/agent-service-py/(基于 LangGraph + langchain-openai)作为可选实现,两者通过 Socket.io 协议互通,可在 start-dev.sh 中切换。

    7.2 为什么不用向量 RAG?

    • 冷启动成本:向量嵌入需要预计算 + 向量数据库,对小型知识库(17 篇)不划算。

    • 召回精度:IDF + 正则 + 类别子串的三重打分在 12 类常见错误模式上验证召回率 > 90%。

    • 未来演进:架构预留了升级路径,可在 retrieveKB 内部替换为向量检索,对调用方无感。

    7.3 为什么需要反思迭代?

    LLM 是概率性系统,单次推理可能产生:

    • 幻觉:声明引用不存在的日志行。

    • 过度自信:confidence = 0.95 但实际证据链断裂。

    • 遗漏:忽略关键时间窗口或并发事件。

    反思闭环通过"深度思考 + 验证 + 反思"三重检查,把单次推理的 70% 准确率提升到 90%+。MAX_ITERATIONS=2 是经验值——超过 2 轮通常意味着日志本身不足以确诊,继续迭代边际收益递减。

    7.4 为什么用 Socket.io 而不是 SSE?

    • 双向通信:前端需要发送 analyze 事件触发分析,SSE 只能单向推送。

    • 重连机制:Socket.io 内置自动重连 + 心跳,比手写 SSE 健壮。

    • 房间机制:可按 sessionId 隔离事件,未来支持多用户并发诊断。

    • Caddy 兼容:通过 XTransformPort 查询参数路由,避免 CORS。

    7.5 为什么 C++ 模块不使用 Socket.io?

    C++ 分析是 CPU 密集型(规则扫描)+ 串行 LLM 调用,耗时较长(10-60s),不需要实时事件流。前端通过轮询 GET /api/sessions/[id]/code 获取结果,更简单可靠。日志诊断因为有多智能体协同 + ReAct 实时思考流,才需要 Socket.io。


    附录 A:智能体事件流示例(OOM 场景)

    search-indexer.log(Java OOM)为例,一次完整诊断的事件流:

    [orchestrator/status]   AIOps 编排器已启动,模型: GLM (Zhipu AI)。
    [orchestrator/status]   智能诊断流水线: 采集 → 检索(RAG) → 规划(ReAct) → ...
    [collector/status]      采集器已启动——解析 312 行原始日志
    [collector/result]      解析完成:312 条日志,错误 3,警告 5;FREQUENT TAGS: memory: 3
    [retriever/status]      检索器已启动——LLM 扩展查询 + IDF 检索
    [retriever/action]      query: "OutOfMemoryError heap space memory leak IndexBuilder"
    [retriever/observation] 命中知识库 4 条:OutOfMemoryError / GC overhead / memory-leak / gc-overhead
    [planner/thought]       日志中有 OutOfMemoryError + IndexBuilder.java 堆栈 + heap 增长趋势...
    [planner/action]        inspect_metrics
    [planner/observation]   error rate 0.96%, top error source: IndexBuilder.buffer()
    [planner/thought]       知识库 memory-leak 文章指出"数据结构无限增长"是常见根因...
    [planner/action]        form_plan
    [planner/result]        Plan: 1) 验证 IndexBuilder 数据结构增长 2) 检查 heap dump 3) 评估缓存淘汰策略
    [analyst/status]        分析师已启动——根因分析(RCA)
    [analyst/result]        severity=HIGH, confidence=0.78, root cause="Memory leak in IndexBuilder.java..."
    [orchestrator/thought]  触发深度思考器(置信度 78% < 80%)。
    [deep-thinker/thought]  审视证据链:3 条 evidence 均引用真实日志行...
    [deep-thinker/result]   verdict=confirmed, confidence_adjustment=+0.05
    [validator/status]      验证器已启动——证据链闭环验证
    [validator/result]      validated=true, evidenceChain=[root_cause←evidence←trigger], 0 hallucination
    [fixer/status]          修复器已启动——生成 P0-P3 修复建议
    [fixer/result]          4 条修复:P0 改用 WeakHashMap / P1 增加 -Xmx / P2 加 heap dump / P3 加监控
    [reviewer/status]       复审器已启动——最终复审与风险评估
    [reviewer/result]       riskScore=72, strengths=["具体根因"], gaps=["未提供 heap dump 分析"]
    [orchestrator/result]   AIOps 诊断完成——严重程度: HIGH,置信度: 83%,验证: 通过,修复: 4 条。

    附录 B:版本演进

    版本 关键特性
    V1 Socket 连接 + Auto-Collect + 完整诊断流程 + ReAct 事件流 + RCA/修复/复审
    V2 暗色模式 + 证据点击定位 + PDF 导出 + UI 打磨
    V3 动态 ReAct 循环 + IDF+正则 RAG + 逐行高亮 + 多格式导出 + Agent 指示器 + 骨架屏
    V4 可拖拽面板 + 诊断统计条 + 行号点击定位 + 报告动画 + RCA 提示词优化 + OOM 知识库扩充 + 并发限流 + 诊断对比 API
    V5 大文件流式上传 + Drain 模板提取 + 三级上下文压缩 + Token 预算管理 + DeepThinker + Validator + Reflector + C++ 静态分析(15 规则)+ 运行时日志诊断 + i18n 双语 + 4 模型支持 + 设置 UI + 多视图导航

    LogGuard AI — 详细技术文档

    版本:V5 适用读者:开发者 / 运维工程师 / 二次开发者


    目录

    1. 项目结构

    2. API 路由

    3. 数据库 Schema

    4. 大模型配置

    5. i18n 国际化

    6. 大文件处理

    7. 部署


    1. 项目结构

    logguard-ai/
    ├── docs/                              # 项目文档
    │   ├── DESIGN.md                      # 详细设计文档
    │   └── TECHNICAL.md                   # 详细技术文档(本文档)
    │
    ├── src/                               # 前端 + API Routes 源码
    │   ├── app/                           # Next.js App Router
    │   │   ├── layout.tsx                 # 根布局(含 ThemeProvider)
    │   │   ├── page.tsx                   # 主页面(多视图切换)
    │   │   ├── globals.css                # 全局样式
    │   │   └── api/                       # API 路由
    │   │       ├── analyze/               # POST /api/analyze
    │   │       ├── analyze-code/          # POST /api/analyze-code
    │   │       ├── code/collect/          # GET  /api/code/collect
    │   │       ├── diff/[ids]/            # GET  /api/diff/:idA,:idB
    │   │       ├── export/[format]/       # GET  /api/export/:format
    │   │       ├── history/               # GET  /api/history
    │   │       ├── knowledge/             # GET/POST /api/knowledge
    │   │       ├── llm-config/            # GET/POST/DELETE /api/llm-config
    │   │       ├── logs/
    │   │       │   ├── collect/           # GET  /api/logs/collect
    │   │       │   ├── ingest/            # POST /api/logs/ingest
    │   │       │   ├── search/            # GET  /api/logs/search?q=
    │   │       │   ├── stream-upload/     # POST /api/logs/stream-upload
    │   │       │   ├── tail/              # GET  /api/logs/tail?file= (SSE)
    │   │       │   └── watch/             # GET  /api/logs/watch
    │   │       ├── sessions/[id]/         # GET  /api/sessions/:id
    │   │       │   ├── code/              # GET  /api/sessions/:id/code
    │   │       │   └── reanalyze/         # POST /api/sessions/:id/reanalyze
    │   │       └── route.ts               # GET  /api (health check)
    │   │
    │   ├── components/                    # React 组件
    │   │   ├── ui/                        # shadcn/ui 基础组件(40+ 个)
    │   │   │   ├── button.tsx
    │   │   │   ├── dialog.tsx
    │   │   │   ├── dropdown-menu.tsx
    │   │   │   ├── select.tsx
    │   │   │   ├── tooltip.tsx
    │   │   │   └── ...
    │   │   └── log-agent/                 # LogGuard 业务组件
    │   │       ├── agent-graph.tsx        # 智能体工作流图(节点状态实时点亮)
    │   │       ├── concurrency-badge.tsx  # 并发状态徽章(idle/active 脉冲)
    │   │       ├── cpp-ast-view.tsx       # C++ AST 摘要展示
    │   │       ├── cpp-code-input.tsx     # C++ 代码输入框(含拖拽上传)
    │   │       ├── cpp-issue-list.tsx     # C++ 静态问题列表
    │   │       ├── cpp-report-view.tsx    # C++ 分析报告
    │   │       ├── cpp-types.ts           # C++ 分析类型定义
    │   │       ├── diff-dialog.tsx        # 诊断对比 Dialog
    │   │       ├── event-stream.tsx       # ReAct 事件流(终端样式实时滚动)
    │   │       ├── history-panel.tsx      # 历史会话面板
    │   │       ├── knowledge-panel.tsx    # 知识库浏览器(含 RAG 搜索)
    │   │       ├── large-log-uploader.tsx # 大文件拖拽上传组件
    │   │       ├── llm-config-dialog.tsx  # LLM 配置 Dialog(4 提供商 Tab)
    │   │       ├── log-input.tsx          # 日志输入框(含逐行高亮、行号定位)
    │   │       ├── model-selector.tsx     # 模型选择器(Qwen/GLM/DeepSeek/StepFun)
    │   │       ├── report-view.tsx        # 诊断报告(RCA/Fixes/Review/Plan/Stats Tab)
    │   │       ├── sidebar.tsx            # 多视图导航侧边栏
    │   │       ├── stats-bar.tsx          # 诊断统计条(5 个 chip)
    │   │       ├── types.ts               # 业务组件类型定义
    │   │       └── views/                 # 主视图容器
    │   │           ├── cpp-view.tsx       # C++ 分析视图
    │   │           ├── history-view.tsx   # 历史视图
    │   │           ├── knowledge-view.tsx # 知识库视图
    │   │           ├── log-view.tsx       # 日志诊断视图(默认)
    │   │           └── settings-view.tsx  # 设置视图
    │   │
    │   ├── hooks/                         # 自定义 Hooks
    │   │   ├── use-t.ts                   # i18n 翻译 Hook(useCallback 记忆化)
    │   │   ├── use-toast.ts               # Toast 通知 Hook
    │   │   └── use-mobile.ts              # 移动端检测 Hook
    │   │
    │   └── lib/                           # 核心逻辑
    │       ├── db.ts                      # Prisma 客户端单例
    │       ├── i18n.ts                    # 中英双语字典(~100 keys)
    │       ├── store.ts                   # Zustand 全局状态(locale、currentSession 等)
    │       └── utils.ts                   # 通用工具(cn 类名合并等)
    │       └── agents/                    # 多智能体系统(核心)
    │           ├── orchestrator.ts        # 日志诊断编排器
    │           ├── cpp-orchestrator.ts    # C++ 分析编排器
    │           ├── collector.ts           # 采集器
    │           ├── retriever.ts           # RAG 检索器
    │           ├── planner.ts             # ReAct 规划器
    │           ├── analyst.ts             # RCA 分析师
    │           ├── deep-thinker.ts        # 深度思考器(条件触发)
    │           ├── validator.ts           # 证据链验证器
    │           ├── reflector.ts           # 反思器(闭环迭代)
    │           ├── fixer.ts               # 修复器
    │           ├── reviewer.ts            # 复审器
    │           ├── llm.ts                 # LLM 调用封装(4 模型 + 双路径)
    │           ├── llm-config.ts          # LLM 配置解析器(15s 缓存)
    │           ├── prompts.ts             # 所有智能体的 system prompts
    │           ├── types.ts               # 共享类型定义
    │           ├── log-parser.ts          # 日志解析器
    │           ├── log-template.ts        # Drain 模板提取
    │           ├── context-compressor.ts  # 三级上下文压缩
    │           ├── context-manager.ts     # Token 预算管理器
    │           ├── knowledge-base.ts      # 知识库 + RAG 检索
    │           ├── cpp-parser.ts          # C++ AST 解析器
    │           ├── cpp-analyzer.ts        # C++ 15 条静态分析规则
    │           └── cpp-runtime-parser.ts  # C++ 运行时日志信号提取
    │
    ├── mini-services/                     # 微服务
    │   ├── agent-service/                 # Bun Socket.io 服务(端口 3003)
    │   │   ├── index.ts                   # 主入口(并发限流 + 事件流)
    │   │   ├── package.json
    │   │   ├── tsconfig.json
    │   │   └── bun.lock
    │   └── agent-service-py/              # Python LangGraph 替代实现(可选)
    │       ├── main.py                    # uvicorn 入口
    │       ├── server.py                  # Socket.io 服务端
    │       ├── orchestrator.py            # LangGraph 编排
    │       ├── agents.py                  # 9 个智能体
    │       ├── llm.py                     # LLM 调用
    │       ├── log_parser.py              # 日志解析
    │       ├── knowledge_base.py          # 知识库
    │       ├── models.py                  # Pydantic 模型
    │       ├── db.py                      # SQLite 访问
    │       ├── config.py                  # 配置
    │       ├── prompts.py                 # 系统提示词
    │       ├── pyproject.toml
    │       └── requirements.txt
    │
    ├── scripts/                           # 运维脚本
    │   ├── start-dev.sh                   # 开发环境启动脚本
    │   └── start-prod.sh                  # 生产环境启动脚本
    │
    ├── prisma/
    │   └── schema.prisma                  # Prisma 数据库 schema
    │
    ├── sample-logs/                       # 示例日志
    │   ├── payments-service.log           # 连接池耗尽场景
    │   ├── search-indexer.log             # OOM 场景
    │   └── auth-and-api.log               # 认证 + JSON + 网络场景
    │
    ├── sample-code/                       # 示例 C++ 代码
    │   ├── memory_leak.cpp                # 内存泄漏
    │   ├── data_race.cpp                  # 数据竞争
    │   └── use_after_free.cpp             # Use-After-Free
    │
    ├── public/                            # 静态资源
    │   ├── logo.svg
    │   └── robots.txt
    │
    ├── db/
    │   └── custom.db                      # SQLite 数据库文件
    │
    ├── Caddyfile                          # Caddy 反向代理配置(端口 81)
    ├── package.json
    ├── tsconfig.json
    ├── tailwind.config.ts
    ├── postcss.config.mjs
    ├── next.config.ts
    ├── eslint.config.mjs
    ├── components.json                    # shadcn/ui 配置
    └── README.md

    2. API 路由

    所有 API 路由位于 src/app/api/,遵循 Next.js App Router 约定。统一返回 JSON 格式 { ok: boolean, ... } | { error: string }

    2.1 诊断会话管理

    POST /api/analyze — 创建日志诊断会话

    创建一个 AnalysisSession 行(status=pending),返回 sessionId。实际的多智能体运行通过 Socket.io "analyze" 事件触发。

    • 请求体

    {
      "model": "qwen" | "glm" | "deepseek" | "stepfun",   // 可选,默认 "glm"
      "rawLogs": "string",                                  // 必填,原始日志文本
      "source": "string",                                   // 可选,日志来源标识
      "title": "string"                                     // 可选,会话标题
    }
    • 响应

    { "ok": true, "sessionId": "cmqi...", "title": "...", "model": "glm" }
    • 错误:400(rawLogs 为空)/ 500(DB 错误)

    POST /api/analyze-code — 创建 C++ 分析会话

    创建会话并在后台运行 C++ 编排器。HTTP 响应立即返回,客户端轮询 /api/sessions/[id]/code 获取结果。

    • 请求体

    {
      "files": [{ "path": "main.cpp", "content": "..." }],   // 必填
      "model": "glm",                                         // 可选,默认 "glm"
      "title": "string",                                      // 可选
      "run": true,                                            // 可选,默认 true
      "runtimeLogs": "string"                                 // 可选,运行时日志(ASAN/Valgrind/GDB/编译器)
    }
    • 响应{ ok, sessionId, title, model, status }

    • maxDuration:300s(LLM 调用可能超过 10s)

    GET /api/sessions/[id] — 获取会话完整回放

    返回会话元信息 + 完整诊断结果 + 事件流数组。

    • 路径参数id — 会话 ID

    • 响应

    {
      "ok": true,
      "session": { "id", "title", "model", "status", "severity", "createdAt" },
      "result": { "plan", "rca", "fixes", "review", "knowledgeHits", "logStats" },
      "events": [{ "id", "agent", "type", "content", "meta", "timestamp" }]
    }
    • 错误:404(会话不存在)

    GET /api/sessions/[id]/code — 获取 C++ 会话结果

    返回持久化的 CodeFile + CodeIssue 行 + 重建的 AST 摘要 + 指标。客户端轮询此端点获取 C++ 分析结果。

    • 响应{ ok, sessionId, status, files, issues, ast, metrics, topRiskAreas, runtimeLogAnalysis, summary }

    POST /api/sessions/[id]/reanalyze — 重新分析

    加载原会话的 LogEntry 行(按 createdAt 升序,保留原始顺序),重建 rawLogs,创建新的 AnalysisSession(标题 "Re-analysis of {原标题}"),返回新 sessionId。前端可随后通过 Socket.io 触发实际分析。

    • 请求体(可选):{ "model": "qwen" | "glm" | "deepseek" }

    • 模型回退逻辑:body.model > 原会话 model > "glm"

    • 错误:400(会话无 LogEntry)/ 404(会话不存在)

    2.2 历史与对比

    GET /api/history — 列出历史会话

    返回最近 50 个会话(按 createdAt 降序)。

    • 响应

    {
      "ok": true,
      "sessions": [{
        "id", "title", "model", "status", "severity",
        "errorCount", "warnCount", "createdAt"
      }]
    }

    GET /api/diff/[ids] — 对比两个诊断会话

    ids 为逗号分隔的两个 sessionId,例如 /api/diff/sess1,sess2。返回对比字段:

    • 响应

    {
      "ok": true,
      "sessions": { "a": { ...meta }, "b": { ...meta } },
      "severityChanged": true,
      "rootCauseChanged": false,
      "confidenceDelta": 0.15,
      "riskScoreDelta": -10,
      "errorCountDelta": 0,
      "fixesAdded": [{ "title", "priority", "type" }],
      "fixesRemoved": [],
      "sharedEvidence": [{ "log", "explanation" }]
    }

    2.3 日志管理

    GET /api/logs/collect — 自动采集示例日志

    读取 sample-logs/ 目录下所有 .log/.txt 文件,返回每个文件的内容 + 统计 + 预览。

    • 响应

    {
      "ok": true,
      "files": [{
        "name": "payments-service.log",
        "content": "...",
        "stats": { "total", "errors", "warnings", "byLevel" },
        "preview": [{ "level", "message", "source", "timestamp" }]
      }]
    }

    POST /api/logs/ingest — 解析并存储原始日志

    把原始日志文本解析为 ParsedLog 数组,存入 LogEntry 表(sessionId=null),返回结构化预览。

    • 请求体{ "rawLogs": "string", "source": "string" }

    • 响应{ ok, count, stats, digest, entries[] }

    POST /api/logs/stream-upload — 大文件流式上传

    支持 multipart/form-data 或纯文本。按 50k 行/批分片解析,最大 1000 万行。返回 Drain 模板 + 三级压缩 + 上下文管理器统计。

    • 请求:multipart(file 字段)或 text/plain

    • 响应

    {
      "ok": true,
      "fileName": "huge.log",
      "stats": { "totalLines", "parsedEntries", "errorLines", "warnLines", "byLevel", "processingMs" },
      "templates": [{ "template", "count", "level", "examples" }],   // Top 50
      "compressed": { "l1", "l2", "l3", "tokenEstimate", "compressionRatio" },
      "contextStats": { "budgetUsed", "budgetTotal", "fragmentsAvailable", "fragmentsLoaded" }
    }
    • maxDuration:300s

    • 错误:400(空文件)/ 413(超过 1000 万行限制)

    GET /api/logs/search?q= — RAG 检索

    对知识库执行 IDF + 正则 + 类别子串打分检索。

    • 查询参数q — 搜索关键词

    • 响应

    {
      "ok": true,
      "query": "OutOfMemoryError heap space",
      "hits": [{ "id", "title", "category", "summary", "cause", "fix", "score" }]
    }

    GET /api/logs/watch — 列出 / 查看日志文件

    无参数:列出 sample-logs/*.log|*.txt,每个文件返回 name/size/mtime/tail(最后 50 行)。 带参数:?file=NAME&lines=N 返回指定文件的最后 N 行(N 默认 50,clamp 到 [1, 5000])。

    • 错误:400(路径遍历 / 非 .log/.txt 后缀)/ 404(文件不存在)

    GET /api/logs/tail?file= — SSE 实时日志尾随

    Server-Sent Events 端点,2 秒轮询 + 10 秒心跳。模块级 fileCursors: Map 跨连接共享游标,新连接只接收追加内容(不重发历史)。

    • 响应text/event-stream,事件类型 hello / line / rotated / heartbeat / error

    • 特殊 HeaderX-Accel-Buffering: no(强制 Caddy 立即 flush)

    • 错误:400(无 file)/ 404(文件不存在)

    2.4 知识库

    GET /api/knowledge — 列出知识库文章

    首次访问触发 ensureKBSeeded(),从代码内 SEED 数组填充 17+ 篇预置文章。

    • 响应{ ok, articles: [{ id, title, category, summary, cause, fix, pattern }] }

    POST /api/knowledge — 新增 / 重置知识库

    • 请求体{ "reset": false, "title", "category", "pattern", "summary", "cause", "fix", "keywords" }

    • 响应{ ok, id }

    2.5 LLM 配置

    GET /api/llm-config — 列出所有 LLM 提供商配置

    API Key 从不直接返回,只返回 hasKey: boolean + keyHint: "sk-••••••ret" 掩码形式。

    • 响应

    {
      "ok": true,
      "configs": [{
        "provider": "qwen",
        "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1",
        "modelName": "qwen-plus",
        "enabled": true,
        "hasKey": true,
        "keyHint": "sk-••••••ret",
        "defaults": { "baseUrl", "modelName", "docs" }
      }]
    }

    POST /api/llm-config — 新增/更新 LLM 配置

    如果 apiKey 为空字符串或掩码占位符(包含 ••••),保留数据库中已有的 key。

    • 请求体{ "provider", "baseUrl", "apiKey", "modelName", "enabled" }

    • 响应{ ok, provider, enabled, hasKey }

    • 副作用:调用 invalidateModelConfigCache() 立即生效

    DELETE /api/llm-config?provider=qwen — 删除 LLM 配置

    • 查询参数provider — 必填,4 个合法值之一

    2.6 C++ 代码

    GET /api/code/collect — 自动采集示例 C++ 文件

    读取 sample-code/ 目录下 .cpp/.cc/.cxx/.c/.h/.hpp/.hh 文件,分类语言,返回 path/content/lineCount/size。

    2.7 导出

    GET /api/export/[format]?sessionId=&locale= — 导出诊断报告

    • 路径参数format"markdown""json"

    • 查询参数sessionId(必填)、locale(可选,zh 默认 / en

    • 响应

      • jsonapplication/json + Content-Disposition: attachment; filename="diagnosis-{id}.json"

      • markdowntext/markdown; charset=utf-8 + Content-Disposition: attachment; filename="diagnosis-{id}.md"

      • Markdown 报告包含:标题 + 元信息 + 严重程度/置信度 + 主根因 + 促成因素 + 证据链(代码块)+ 时间线 + 修复建议(P0-P3 优先级徽章 + 代码片段 + 预防建议)+ 复审(风险评分 + strengths/gaps/recommendations)+ 日志统计 + 生成时间戳

    • 错误:400(不支持格式 / 缺 sessionId)/ 404(会话不存在)

    2.8 健康检查

    GET /api — 健康检查

    返回服务状态、版本信息。


    3. 数据库 Schema

    数据库为 SQLite(位于 db/custom.db),通过 Prisma ORM 访问。Schema 定义在 prisma/schema.prisma

    3.1 实体关系图

    ┌─────────────────────┐
    │   AnalysisSession   │  一次诊断会话(日志或 C++)
    └──────────┬──────────┘
               │ 1
               │
               ├─────< LogEntry          解析后的日志行
               │
               ├─────< AgentEvent        智能体事件流
               │
               ├─────< CodeFile          C++ 源文件
               │
               └─────< CodeIssue         C++ 静态分析问题
    
    ┌─────────────────────┐
    │  KnowledgeArticle   │  知识库条目(独立表,RAG 索引源)
    └─────────────────────┘
    
    ┌─────────────────────┐
    │     LlmConfig       │  LLM 提供商配置(独立表,4 个 provider)
    └─────────────────────┘

    3.2 模型详解

    AnalysisSession — 诊断会话

    字段 类型 说明
    id String @id CUID 自动生成
    title String 会话标题(自动从日志中提取首条 ERROR 行)
    model String 使用的模型:qwen / glm / deepseek / stepfun
    status String pending / running / completed / failed
    logSummary String? 输入日志的 1000 字摘要
    rootCause String? 最终 RCA 的 JSON 字符串(RootCauseAnalysis 序列化)
    fixes String? 最终修复建议的 JSON 数组字符串
    summary String? 包含 plan + review + validation + deepThinking + reflection 的综合 JSON
    severity String? critical / high / medium / low
    errorCount Int 错误日志行数
    warnCount Int 警告日志行数
    createdAt DateTime 创建时间
    updatedAt DateTime 更新时间(@updatedAt)
    关系   events: AgentEvent[]logEntries: LogEntry[]codeFiles: CodeFile[]codeIssues: CodeIssue[]
    索引   @@index([createdAt])

    LogEntry — 解析后的日志行

    字段 类型 说明
    id String @id CUID
    sessionId String? 关联会话;可为 null(通用 ingest buffer)
    raw String 原始日志行文本
    timestamp String? 解析出的时间戳
    level String INFO / WARN / ERROR / DEBUG / TRACE / FATAL
    source String? 文件名 / 组件名
    message String 提取的日志消息正文
    stack String? 堆栈(多行合并)
    tags String JSON 数组字符串,例如 ["memory","database"]
    createdAt DateTime 创建时间
    关系   session: AnalysisSession?(onDelete: Cascade)
    索引   @@index([sessionId])@@index([level])

    AgentEvent — 智能体事件流

    字段 类型 说明
    id String @id CUID
    sessionId String 关联会话
    agent String orchestrator / collector / retriever / planner / analyst / deep-thinker / validator / reflector / fixer / reviewer / cpp-parser / static-analyzer
    type String status / thought / action / observation / result / error / suggestion
    content String 人类可读的事件内容
    meta String? 可选的 JSON 元数据(如 { severity, confidence, fixes, risk }
    createdAt DateTime 创建时间
    关系   session: AnalysisSession(onDelete: Cascade)
    索引   @@index([sessionId])

    KnowledgeArticle — 知识库条目

    字段 类型 说明
    id String @id CUID
    title String 标题(如 "OutOfMemoryError: Java heap space")
    category String 类别(如 memory / database / network / concurrency
    pattern String 正则表达式,RAG 检索时用于模式匹配(+3 分)
    summary String 一句话摘要
    cause String 常见原因(多段文本)
    fix String 修复建议(多段文本)
    keywords String 空格分隔的关键词,用于 IDF 检索
    createdAt DateTime 创建时间
    索引   @@index([category])

    CodeFile — C++ 源文件

    字段 类型 说明
    id String @id CUID
    sessionId String 关联会话
    path String 文件路径
    language String cpp / h / cc / cxx
    content String 文件完整内容
    lineCount Int 行数
    createdAt DateTime 创建时间
    关系   session: AnalysisSession(onDelete: Cascade)
    索引   @@index([sessionId])

    CodeIssue — C++ 静态分析问题

    字段 类型 说明
    id String @id CUID
    sessionId String 关联会话
    ruleId String 规则 ID(如 CPP-MEM-001
    ruleName String 规则名称
    category String memory / concurrency / undefined-behavior / raii / resource / performance / modern-cpp / security
    severity String critical / high / medium / low / info
    file String 文件路径
    line Int 起始行号
    endLine Int? 结束行号
    column Int? 列号
    snippet String 问题代码片段
    message String 问题描述
    explanation String 为什么是问题
    suggestion String 修复建议
    fixCode String? 修复后的代码示例
    cwe String? CWE 编号(如 CWE-401
    confidence Float 置信度 0-1
    createdAt DateTime 创建时间
    关系   session: AnalysisSession(onDelete: Cascade)
    索引   @@index([sessionId])@@index([severity])

    LlmConfig — LLM 提供商配置

    字段 类型 说明
    id String @id CUID
    provider String @unique 4 个唯一值:qwen / glm / deepseek / stepfun
    baseUrl String? OpenAI 兼容 API 的 base URL
    apiKey String? API Key(服务端存储,从不返回给浏览器
    modelName String? 模型名(如 qwen-plusglm-4-plus
    enabled Boolean 是否启用(默认 false)
    updatedAt DateTime 更新时间
    createdAt DateTime 创建时间

    3.3 数据库迁移命令

    bun run db:push      # 推送 schema 到 SQLite(开发期推荐)
    bun run db:generate  # 生成 Prisma Client
    bun run db:migrate   # 创建迁移文件(生产期推荐)
    bun run db:reset     # 重置数据库(删除所有数据)

    4. 大模型配置

    4.1 支持的 4 个提供商

    Provider ID 厂商 默认 Base URL 默认模型 文档
    qwen 阿里巴巴通义千问 https://dashscope.aliyuncs.com/compatible-mode/v1 qwen-plus DashScope 兼容模式
    glm 智谱 AI https://open.bigmodel.cn/api/paas/v4 glm-4-plus 智谱 API
    deepseek DeepSeek https://api.deepseek.com/v1 deepseek-chat DeepSeek API
    stepfun 阶跃星辰 https://api.stepfun.com/v1 step-2-16k StepFun Docs

    4.2 OpenAI 兼容协议

    所有 4 个提供商均兼容 OpenAI Chat Completions API 格式,统一通过 POST {baseUrl}/chat/completions 调用:

    // src/lib/agents/llm-config.ts
    export async function callOpenAICompatible(
      baseUrl: string,
      apiKey: string,
      modelName: string,
      messages: { role: "system" | "user" | "assistant"; content: string }[],
      options: { temperature?: number; maxTokens?: number; json?: boolean }
    ): Promise<string>

    请求格式:

    {
      "model": "qwen-plus",
      "messages": [
        { "role": "system", "content": "你是 AIOps 分析师..." },
        { "role": "user", "content": "分析以下日志..." }
      ],
      "temperature": 0.3,
      "max_tokens": 2000,
      "response_format": { "type": "json_object" }   // 当 options.json=true 时
    }

    4.3 双路径调用机制

    src/lib/agents/llm.tschat() 函数实现双路径:

    chat(opts)
       │
       ▼
    resolveModelConfig(opts.model)  ── 15s 内存缓存 ── LlmConfig 表
       │
       ├─ Path 1: 用户已配置且 enabled=true
       │     ↓
       │   callOpenAICompatible(baseUrl, apiKey, modelName, ...)
       │     ↓ 使用标准 system role
       │   返回 content
       │
       └─ Path 2: 未配置或 enabled=false
             ↓
           z-ai-web-dev-sdk(环境内置,无需 API Key)
             ↓ 保留 assistant role quirks(z-ai SDK 兼容性)
           返回 content

    配置变更立即生效:POST/DELETE /api/llm-config 调用 invalidateModelConfigCache() 清空 15s 缓存。

    4.4 用户配置 UI

    设置视图(src/components/log-agent/views/settings-view.tsx)+ LLM 配置 Dialog(src/components/log-agent/llm-config-dialog.tsx)提供:

    • 4 个 Tab 对应 4 个 provider

    • 每个 Tab 3 个输入字段:LLM_BASE_URL / LLM_API_KEY(password 输入 + 显示/隐藏切换)/ LLM_MODEL_NAME

    • 启用/禁用 Switch

    • 默认值快捷填充按钮(从 PROVIDER_DEFAULTS 取)

    • 文档链接

    • API Key 掩码显示(sk-••••••ret

    • 保存/重置按钮

    4.5 多模型 Persona 适配

    即使使用同一种底层 API,不同模型在 prompt 中会注入不同的 system persona(src/lib/agents/llm.ts#MODEL_PROFILES):

    模型 Persona 摘要
    Qwen "你以 Qwen(阿里巴巴)的风格运行。你擅长长上下文代码和日志理解。要精确、结构化,倾向具体的技术细节。"
    GLM "你以 GLM(智谱 AI)的风格运行。你平衡且可靠,擅长工具使用和结构化输出。偏好将问题分解为清晰的步骤。"
    DeepSeek "你以 DeepSeek 的风格运行。你是一个深度推理者:逐步思考,呈现假设,考虑替代方案,然后得出结论。"
    StepFun "你以阶跃星辰(StepFun)的风格运行。你擅长长文本理解和中文场景的深度推理。"

    5. i18n 国际化

    5.1 设计目标

    • 支持 中文(zh)英文(en) 双语

    • 单页应用,不依赖 next-intl 的复杂路由

    • Locale 持久化到 localStorage

    • 翻译函数 t(key) 高性能(useCallback 记忆化)

    5.2 实现

    5.2.1 字典定义(src/lib/i18n.ts

    export type Locale = "en" | "zh";
    
    const en: Dict = {
      "nav.log": "Log Diagnosis",
      "nav.cpp": "C++ Analysis",
      "report.severity": "Severity",
      "report.primaryRootCause": "Primary Root Cause",
      // ... ~100 keys 覆盖 nav、report、history、knowledge、settings、agent 名称
    };
    
    const zh: Dict = {
      "nav.log": "日志诊断",
      "nav.cpp": "C++ 分析",
      "report.severity": "严重程度",
      "report.primaryRootCause": "主要根因",
      // ...
    };
    
    export function translate(locale: Locale, key: string): string {
      const dict = locale === "zh" ? zh : en;
      return dict[key] ?? key;  // 找不到时返回 key 本身作为兜底
    }

    5.2.2 全局状态(src/lib/store.ts

    interface AppState {
      locale: Locale;
      setLocale: (l: Locale) => void;
      // ... 其他状态
    }
    
    // Zustand persist 中间件自动把 locale 持久化到 localStorage
    export const useStore = create<AppState>()(
      persist(
        (set) => ({
          locale: "zh",   // 默认中文
          setLocale: (locale) => {
            set({ locale });
            localStorage.setItem("logguard-locale", locale);
          },
          // ...
        }),
        { name: "logguard-store" }
      )
    );

    5.2.3 翻译 Hook(src/hooks/use-t.ts

    import { useCallback } from "react";
    import { useStore } from "@/lib/store";
    import { translate, type Locale } from "@/lib/i18n";
    
    export function useT() {
      const locale = useStore((s) => s.locale);
      // useCallback 记忆化:locale 不变时返回同一个函数引用,
      // 避免子组件不必要的重渲染
      return useCallback(
        (key: string) => translate(locale as Locale, key),
        [locale]
      );
    }

    5.2.4 在组件中使用

    import { useT } from "@/hooks/use-t";
    
    function ReportView({ rca }) {
      const t = useT();
      return (
        <Card>
          <CardTitle>{t("report.primaryRootCause")}</CardTitle>
          <CardContent>{rca.primaryRootCause}</CardContent>
        </Card>
      );
    }

    5.3 Locale 切换 UI

    侧边栏顶部(src/components/log-agent/sidebar.tsx)有 Languages 图标按钮,显示 EN,点击切换 locale。Zustand persist 自动同步到 localStorage,刷新页面后保持选择。

    5.4 导出报告的本地化

    /api/export/[format]?locale=zh|en 端点根据 locale 参数生成本地化的 Markdown 报告——所有章节标题(诊断报告 / 严重程度 / 主要根因 / 证据 / 修复 / 复审 等)都会按 locale 翻译,时间戳按 zh-CN / en-US locale 格式化。


    6. 大文件处理

    6.1 挑战

    日志文件动辄百万行,远超 LLM 上下文窗口(典型 8k-32k token)。直接全量塞入会:

    1. 超出 token 限制,API 返回 413/400

    2. 即使不超限,注意力分散导致 LLM 抓不住关键信号

    3. 推理延迟从秒级涨到分钟级

    6.2 解决方案:流式上传 + Drain 模板 + 三级压缩 + Token 预算

    6.2.1 流式上传 API

    POST /api/logs/stream-uploadsrc/app/api/logs/stream-upload/route.ts):

    const BATCH_SIZE = 50000;        // 5 万行/批
    const MAX_LINES = 10_000_000;    // 1000 万行硬上限
    
    // 分片处理,避免一次性加载到内存
    for (let i = 0; i < allLines.length; i += BATCH_SIZE) {
      const batch = allLines.slice(i, Math.min(i + BATCH_SIZE, allLines.length));
      allEntries.push(...parseLogs(batch.join("\n")));
    }

    支持两种 Content-Type:

    • multipart/form-data(带 file 字段,UI 拖拽上传)

    • text/plain(直接 POST 文本)

    6.2.2 Drain 日志模板提取

    src/lib/agents/log-template.ts#extractTemplates

    经典 Drain 算法实现,把相似日志行归并为模板。例如:

    原始日志:
      2024-01-01 10:00:00 ERROR [OrderService] Failed to process order 12345: timeout
      2024-01-01 10:00:01 ERROR [OrderService] Failed to process order 12346: timeout
      2024-01-01 10:00:02 ERROR [OrderService] Failed to process order 12347: timeout
    
    提取模板:
      2024-01-01 10:00:<*> ERROR [OrderService] Failed to process order <*>: timeout
      count: 3
      examples: [上述 3 行]
      params: [["00", "12345"], ["01", "12346"], ["02", "12347"]]

    变量识别规则(isVariable):

    • 纯数字(\d+

    • 十六进制地址(0x[0-9a-fA-F]+

    • 长 hex 串(8+ 位)

    • IP 地址(含端口)

    • 路径(/...

    • 带引号字符串

    • 123ms / 45s 等时间值

    6.2.3 三级上下文压缩

    src/lib/agents/context-compressor.ts#compressContext

    级别 名称 内容 字符上限
    L1 宏观压缩 时间线摘要,按分钟桶聚合日志数/错误数/警告数 4000
    L2 中观结构化 因果链——按 traceId/requestId 聚合;无 trace 时按错误因果排序 2000
    L3 微观裁剪 错误行 ±5 行的完整上下文(最多 10 个错误点),其余折叠 6000

    6.2.4 Token 预算管理

    src/lib/agents/context-manager.ts

    export const DEFAULT_BUDGET: TokenBudget = {
      total: 8000,
      systemPrompt: 1000,
      compressedLogs: 3000,    // L1+L2+L3 拼接后塞入
      ragRetrieval: 2000,      // RAG 命中的知识库条目
      reasoning: 2000,         // LLM 思考 + 输出预留
    };

    Token 估算:CJK 字符 ÷2 + 其他字符 ÷4(近似 GPT tokenizer 行为)。

    按需片段召回:除了 active window,ContextManager 还会预生成 20+ 个可加载片段(错误行周边上下文、模板示例、错误 burst 段),下游智能体需要更细的上下文时可显式请求加载,避免一次性塞满。

    6.3 大文件上传 UI

    src/components/log-agent/large-log-uploader.tsx

    • 拖拽上传区(dashed border + drag over 高亮)

    • 文件选择按钮(accept .log,.txt

    • 上传进度条

    • 上传完成后展示:

      • 文件统计(总行数 / 解析条目数 / 错误行数 / 警告行数 / 处理耗时)

      • Drain 模板列表(Top 50,每条展示模板文本 + 出现次数 + 3 个示例)

      • 三级压缩预览(L1 / L2 / L3 三段文本 + 压缩比)

      • Token 预算使用情况(budgetUsed / budgetTotal + 可加载片段数)


    7. 部署

    7.1 服务架构

                    ┌─────────────────────────────────────┐
                    │            Caddy :81                │
                    │  (反向代理 + XTransformPort 路由)    │
                    └──────┬────────────────────┬─────────┘
                           │ HTTP               │ HTTP + WS (XTransformPort=3003)
                           ▼                    ▼
                  ┌────────────────┐   ┌────────────────────┐
                  │  Next.js :3000 │   │  agent-service:3003│
                  │  (App Router   │   │  (Bun Socket.io)   │
                  │   + API Routes)│   │  运行 Orchestrator │
                  └──────┬─────────┘   └─────────┬──────────┘
                         │ Prisma                │ Prisma
                         ▼                       ▼
                  ┌────────────────────────────────────────┐
                  │         SQLite (db/custom.db)          │
                  └────────────────────────────────────────┘

    3 个服务

    服务 端口 职责 启动方式
    Caddy 81 反向代理网关,路由 /api/* 到 Next.js、/?XTransformPort=3003 到 agent-service 系统管理(systemd)
    Next.js 3000 前端 SSR + API Routes bunx next dev(开发)/ bunx next start(生产)
    agent-service 3003 Socket.io 服务,运行多智能体编排 bun --hot index.ts(开发)/ bun index.ts(生产)

    7.2 开发环境部署

    7.2.1 一键启动

    # 安装依赖
    bun install
    
    # 推送数据库 schema
    bun run db:push
    
    # 启动所有服务(Next.js + agent-service,Caddy 由系统管理)
    bun run dev

    bun run dev 实际执行 bash scripts/start-dev.sh,该脚本:

    1. 清理残留进程pkill -f "agent-service/index.ts" + pkill -f "next dev" + 强制 kill 占用 3000/3003 端口的进程。

    2. 启动 agent-service(后台):cd mini-services/agent-service && nohup bun --hot index.ts >> agent-service.log 2>&1 &

    3. 等待端口就绪:循环 10 次,每秒检查 ss -ltnp | grep :3003

    4. 启动 Next.js dev server(前台):exec bunx next dev -p 3000 2>&1 | tee dev.log

    7.2.2 单独启动某个服务

    bun run dev:next    # 仅启动 Next.js
    bun run dev:agent   # 仅启动 agent-service

    7.3 生产环境部署

    # 先 build
    bun run build
    
    # 启动所有服务(生产模式)
    bun run start

    bun run start 执行 bash scripts/start-prod.sh,差异:

    • agent-service 用 bun index.ts(无 --hot 热重载)

    • Next.js 用 NODE_ENV=production bunx next start -p 3000(生产模式)

    • 日志输出到 server.log 而非 dev.log

    7.4 Caddy 网关配置

    Caddyfile(端口 81):

    :81 {
        # 匹配 XTransformPort 查询参数的请求 → 路由到对应端口
        @transform_port_query {
            query XTransformPort=*
        }
        handle @transform_port_query {
            reverse_proxy localhost:{query.XTransformPort} {
                header_up Host {host}
                header_up X-Forwarded-For {remote_host}
                header_up X-Forwarded-Proto {scheme}
                header_up X-Real-IP {remote_host}
            }
        }
    
        # 默认路由 → Next.js :3000
        handle {
            reverse_proxy localhost:3000 {
                header_up Host {host}
                header_up X-Forwarded-For {remote_host}
                header_up X-Forwarded-Proto {scheme}
                header_up X-Real-IP {remote_host}
            }
        }
    }

    XTransformPort 路由技巧

    • 前端访问 /api/history → Caddy 默认路由 → localhost:3000/api/history(Next.js API)

    • 前端访问 socket.io/?XTransformPort=3003 → Caddy 匹配 @transform_port_querylocalhost:3003/socket.io/(agent-service)

    • 同域名同端口,避免 CORS 问题

    • Caddy 自动处理 HTTPS(生产环境)

    7.5 数据库

    • 位置db/custom.db(SQLite 单文件)

    • 环境变量DATABASE_URL="file:./db/custom.db"(在 .env 中配置)

    • 备份:直接复制 db/custom.db 文件即可

    • 重置bun run db:reset(删除所有数据,谨慎使用)

    7.6 环境变量

    .env 文件示例:

    DATABASE_URL="file:./db/custom.db"
    
    # 可选:直接配置 LLM(绕过 UI 配置)
    # QWEN_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
    # QWEN_API_KEY=sk-xxx
    # QWEN_MODEL_NAME=qwen-plus
    # GLM_BASE_URL=https://open.bigmodel.cn/api/paas/v4
    # GLM_API_KEY=xxx
    # GLM_MODEL_NAME=glm-4-plus
    # DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
    # DEEPSEEK_API_KEY=sk-xxx
    # DEEPSEEK_MODEL_NAME=deepseek-chat
    # STEPFUN_BASE_URL=https://api.stepfun.com/v1
    # STEPFUN_API_KEY=xxx
    # STEPFUN_MODEL_NAME=step-2-16k

    未配置 LLM 环境变量且未通过 UI 配置时,系统回退到 z-ai-web-dev-sdk(无需 API Key)。

    7.7 健康检查

    启动后访问以下端点验证:

    # Next.js API 健康
    curl http://localhost:81/api
    
    # 历史 API
    curl http://localhost:81/api/history
    
    # 知识库(首次访问触发 seeding)
    curl http://localhost:81/api/knowledge
    
    # LLM 配置
    curl http://localhost:81/api/llm-config
    
    # 服务端口检查
    ss -ltnp | grep -E ':3000|:3003|:81'

    预期输出:

    LISTEN 0  4096  *:81    *:*
    LISTEN 0  511   *:3000  *:*  users:(("next-server",pid=...))
    LISTEN 0  512   *:3003  *:*  users:(("bun",pid=...))

    7.8 故障排查

    现象 排查方向
    前端无法连接 Socket 检查 agent-service 是否在 3003 监听;Caddy 是否运行;浏览器控制台 Socket.io 错误
    诊断一直 pending 检查 agent-service.log;MAX_CONCURRENT=3 是否队列已满;LLM 是否超时
    LLM 调用 401 检查 LlmConfig.apiKey 是否正确;UI 设置面板重新输入
    数据库锁 SQLite 单写入,并发诊断时可能锁;查看 agent-service.log 中的 SQLITE_BUSY
    端口占用 bash scripts/start-dev.sh 会自动清理 3000/3003,Caddy 81 需手动 systemctl restart caddy
    知识库文章数为 0 首次访问 /api/knowledge 触发 seeding;若仍为 0,检查 db.custom.db 写入权限

    7.9 性能调优

    参数 位置 默认值 调优建议
    MAX_CONCURRENT agent-service/index.ts 3 上游 LLM 限流严格时降低;本地 LLM 提高到 5-8
    QUEUE_TIMEOUT_MS agent-service/index.ts 120000 用户容忍度低时降低到 60s
    MAX_CYCLES(ReAct) planner.ts 5 复杂场景提高到 8;简单场景降低到 3
    MAX_ITERATIONS(反思) orchestrator.ts 2 追求准确率提高到 3;追求速度降低到 1
    DEFAULT_BUDGET.total context-manager.ts 8000 模型上下文窗口大时提高到 16k-32k
    BATCH_SIZE(流式上传) stream-upload/route.ts 50000 内存充足时提高到 100k

    附录 A:开发工作流

    A.1 添加新的智能体

    1. src/lib/agents/ 新建 my-agent.ts,导出 runMyAgent(...) 函数,签名遵循 (inputs..., model, emit) => Promise<Result>

    2. src/lib/agents/types.tsAgentName 联合类型中添加 "my-agent"

    3. src/lib/agents/prompts.ts 中添加 MY_AGENT_PROMPT

    4. orchestrator.ts 的流水线中插入调用,决定前置/后置节点。

    5. 在前端 agent-graph.tsx 的节点链中添加新节点。

    6. 在 i18n 字典中添加 agent 名称翻译。

    A.2 添加新的 C++ 静态分析规则

    1. src/lib/agents/cpp-analyzer.ts 中定义 const RULE_XXX_001: Rule = { ruleId, ruleName, category, severity, cwe?, confidence, run }

    2. run 函数签名:(ctx: RuleCtx) => CppIssue[]ctx 包含 { file, ast }

    3. 在文件底部的 RULES: Rule[] 数组中添加新规则。

    4. 规则自动被 analyzeCppCode() 调用,无需修改 orchestrator。

    A.3 添加新的知识库文章

    两种方式:

    方式 1:代码内 SEED(推荐用于内置文章)

    src/lib/agents/knowledge-base.tsSEED: KBSeed[] 数组中添加:

    {
      title: "Your new error pattern",
      category: "your-category",
      pattern: "YourErrorPattern|specific error text",   // 正则
      summary: "One-line summary",
      cause: "Multi-paragraph cause analysis",
      fix: "Multi-paragraph fix suggestions",
      keywords: "your error pattern specific keywords",  // 空格分隔
    }

    然后调用 POST /api/knowledge { reset: true } 重置并重新 seed。

    方式 2:运行时 API(推荐用于用户自定义)

    curl -X POST http://localhost:81/api/knowledge \
      -H "Content-Type: application/json" \
      -d '{
        "title": "Custom error",
        "category": "custom",
        "pattern": "CustomError",
        "summary": "...",
        "cause": "...",
        "fix": "...",
        "keywords": "custom error"
      }'

    附录 B:代码风格与约定

    • TypeScript:strict 模式,所有函数参数和返回值显式标注类型。

    • ESLinteslint-config-next,0 errors / 0 warnings 是合并门槛。

    • 命名

      • 文件:kebab-case.ts(如 deep-thinker.ts

      • 类型/接口:PascalCase(如 RootCauseAnalysis

      • 函数:camelCase(如 runAnalyst

      • 常量:UPPER_SNAKE_CASE(如 MAX_ITERATIONS

      • React 组件:PascalCase.tsx(如 ReportView

    • Prisma 模型PascalCase,字段 camelCase

    • API 路由:RESTful 风格,统一返回 { ok: boolean, ... } | { error: string }

    • 错误处理:所有 async 函数用 try/catch 包裹,错误持久化到 session.status="failed"。

    • 国际化:所有面向用户的字符串必须通过 t(key) 翻译,禁止硬编码中文/英文。

最近更新: 2026年6月20日 17:32:55
浏览: 17

[[total]] 条评论

添加评论
  1. [[item.time]]
    [[item.user.username]] [[item.floor]]楼
  2. 点击加载更多……
  3. 添加评论