
Session 对话级洞察 — Phase2 需求设计【免费下载链接】cannbot-skillsCANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体本仓库为其提供可复用的 Skills 模块。项目地址: https://gitcode.com/cann/cannbot-skills版本v0.2最后更新2026-06-12文档类型Phase2 需求设计 关联项目CANNBot-Insight复杂度Medium-High关联需求分析phase1-requirements-analysis.md导读本文是 Phase1 需求分析的后续聚焦数据模型设计、API 契约、UI 交互、代码结构工程师可直接进入对应章节。§1 整体架构1.1 篇目标架构概览本地文件导入 (唯一数据入口暂不实现实时上报) → CLI: cannbot-insight import --source opencode-db --path file → opencode-db adapter: 打开 sessions.db → 查询所有 session 列表 → 展示 session 选择界面创建时间、第一个提示词、turn 数、模型等 → 用户选择 → 读取选中 session 的 messages → normalize → turn-split → CLI: cannbot-insight import --source claude-jsonl --path file → claude-jsonl adapter: 读取 JSONL → ClaudeParser 解析 → normalize → turn-split → API: POST /api/ingest/import-file (multipart form) → 同 CLI 逻辑opencode-db 需先返回 session 列表供前端选择 → 同一入库 pipeline (turn-split → bridge-builder → execution-split → write-all) UI reads: → /api/observe/data (Session 列表) → /api/observe/session?taskIdxxx (Session 详情 Turn 列表) → /api/observe/session/turns?taskIdxxx (Turn 明细) → /api/observe/session/turns?taskIdxxxsubagenttrue (Subagent Turn 明细) → /api/observe/session/bridges?taskIdxxx (交互链路)1.2 项目定位CANNBot-Insight 是独立项目从零开始实现无外部代码依赖以 Turn 为一等公民建表每轮交互独立可查Subagent 自动拆出独立 Execution写入路径实际创建主↔子交互显式建桥记录InteractionBridgeLLM 输入上下文和输出内容独立存储支持上下文治理§2 数据模型设计2.1 Prisma SchemaSQLitedatasource db { provider sqlite url env(DATABASE_URL) } // ─── Session ──────────────────────────────────────────────── model Session { id String id default(cuid()) taskId String unique label String? query String? framework String? model String? startTime DateTime default(now()) endTime DateTime? // 顶层聚合指标由 turn 数据派生 totalTokens Int default(0) totalInputTokens Int default(0) totalOutputTokens Int default(0) totalReasoningTokens Int default(0) totalCacheReadTokens Int default(0) totalCacheWriteTokens Int default(0) totalCost Float default(0) totalLatencyMs Int default(0) // first→last interaction totalToolCallCount Int default(0) totalLlmCallCount Int default(0) totalSkillLoadCount Int default(0) totalSubagentCount Int default(0) rootExecutionId String? // 主 agent Execution.id user String? createdAt DateTime default(now()) updatedAt DateTime updatedAt turns Turn[] executions Execution[] interactionBridges InteractionBridge[] skills SessionSkill[] } // ─── Turn每次对话轮次的独立记录────────────────── model Turn { id String id default(cuid()) sessionId String session Session relation(fields: [sessionId], references: [id], onDelete: Cascade) turnIndex Int // 0-based, 在 session 内的顺序号 role String // user | assistant | system | tool_result content String? // 文本内容摘要完整内容存 contentJson contentJson String? // 完整内容 JSONparts/structured blocksthinking/text/tool_calls contentSummary String? // 折叠态摘要前 200 字截断用于默认不展开时展示 inputMessagesJson String? // 发给 LLM 的完整 prompt 消息序列 JSON // [{role, content, tokenCount?, name?}] — system/user/assistant/tool_result // 可能很长(10KB~100KB)用于上下文治理 inputMessagesCount Int default(0) // inputMessagesJson 中消息条数折叠态摘要用 inputMessagesTokens Int default(0) // 输入消息总 token 数折叠态摘要 contextWindowPct 计算用 contextWindowPct Float? // inputMessagesTokens / model context window 百分比 agentName String? // 标识哪个 agentroot/subagent subagentName String? // subagent 显示名 subagentSessionId String? // subagent 专属 session ID // ── Token 消耗 ── totalTokens Int default(0) inputTokens Int default(0) outputTokens Int default(0) reasoningTokens Int default(0) cacheReadTokens Int default(0) cacheWriteTokens Int default(0) // ── 时间 ── createdAt DateTime? // 交互创建时间 completedAt DateTime? // 交互完成时间 latencyMs Int default(0) // created→completed 毫秒数 ttftMs Int? // time-to-first-token流式首 token 延迟 // ── 模型 ── model String? modelId String? providerId String? temperature Float? maxTokens Int? finishReason String? // ── 元数据 ── isSubagent Boolean default(false) parentExecutionId String? // 所属 agent Execution.id createdAt DateTime default(now()) toolCalls ToolCall[] skillEvents SkillEvent[] index([sessionId, turnIndex]) index([sessionId, isSubagent]) index([subagentSessionId]) index([agentName]) } // ─── ToolCall每个工具调用的独立记录────────────────── model ToolCall { id String id default(cuid()) turnId String turn Turn relation(fields: [turnId], references: [id], onDelete: Cascade) toolCallId String // LLM 给的 tool_call id toolName String // function.name argsJson String? // function.arguments JSON resultJson String? // tool output/result JSON state String default(ok) // ok | error | failed errorType String? // timeout | permission | format | server_error | null errorMessage String? // 错误信息摘要 // ── 时间 ── startedAt DateTime? completedAt DateTime? durationMs Int default(0) // started→completed 毫秒数 // ── 关联 ── dispatchBridgeId String? // 如果是 task() 调用, 关联到 InteractionBridge isSkillRelated Boolean default(false) // 是否关联 skill 加载/调用 createdAt DateTime default(now()) index([turnId]) index([toolName]) index([toolName, state]) } // ─── SkillEvent每个 skill 加载/调用事件───────────────── model SkillEvent { id String id default(cuid()) turnId String turn Turn relation(fields: [turnId], references: [id], onDelete: Cascade) skillName String // skill 名称 skillVersion Int? // 加载时定格的版本号 eventType String // load | invoke | unload success Boolean default(true) // 是否成功 errorMessage String? // 失败时的错误信息 argsJson String? // invoke 时的参数 JSON // ── 时间 ── startedAt DateTime? completedAt DateTime? durationMs Int default(0) // 加载/调用耗时毫秒 createdAt DateTime default(now()) index([turnId]) index([skillName]) index([skillName, eventType]) } // ─── Execution按 agent 维度聚合────────────────── model Execution { id String id default(cuid()) sessionId String session Session relation(fields: [sessionId], references: [id], onDelete: Cascade) // ── Agent 身份 ── agentName String? // agent 显示名 agentSessionId String? // opencode session ID isSubagent Boolean default(false) subagentType String? // kuafu | general | null subagentName String? // 完整显示名 // ── 父子关系 ── parentExecutionId String? // nullroot; 否则指父 Execution.id rootExecutionId String? // 树的根 Execution.id depth Int default(0) // 层级深度root0, sub1, sub-sub2... // ── 聚合指标 ── tokens Int default(0) inputTokens Int default(0) outputTokens Int default(0) reasoningTokens Int default(0) cacheReadInputTokens Int default(0) cacheCreationInputTokens Int default(0) maxSingleCallTokens Int default(0) cost Float default(0) // 写入时定格不再动态重算 latencyMs Int default(0) // first→last 毫秒 toolCallCount Int default(0) toolCallErrorCount Int default(0) llmCallCount Int default(0) skillLoadCount Int default(0) skillInvokeCount Int default(0) finalResult String? model String? createdAt DateTime default(now()) // ── 关联 ── executionSkills ExecutionSkill[] index([sessionId]) index([parentExecutionId]) index([rootExecutionId]) index([isSubagent]) index([agentSessionId]) } // ─── ExecutionSkillExecution↔skill 绑定────────────────── model ExecutionSkill { id String id default(cuid()) executionId String execution Execution relation(fields: [executionId], references: [id], onDelete: Cascade) skillName String skillVersion Int? isPrimary Boolean default(false) user String? createdAt DateTime default(now()) index([skillName, skillVersion]) index([executionId]) } // ─── SessionSkillSession↔skill 绑定全 session 籇度──────────── model SessionSkill { id String id default(cuid()) sessionId String session Session relation(fields: [sessionId], references: [id], onDelete: Cascade) skillName String skillVersion Int? invocationCount Int default(0) // 调用次数 user String? createdAt DateTime default(now()) unique([sessionId, skillName]) index([skillName]) } // ─── InteractionBridge主agent↔subagent 交互链路────────── model InteractionBridge { id String id default(cuid()) sessionId String session Session relation(fields: [sessionId], references: [id], onDelete: Cascade) // ── dispatch 侧父 agent ── dispatchExecutionId String // 父 Execution.id dispatchTurnId String? // 父哪个 turn 发出 task() dispatchToolCallId String? // 具体哪个 tool_calltask() 调用 dispatchContent String? // 摘要发给 subagent 的指令/参数 dispatchTimestamp DateTime? // 发出时间 // ── response 侧子 agent ── responseExecutionId String? // 子 Execution.id responseTurnId String? // 子哪个 turn 返回结果 responseContent String? // 摘要子 agent 返回的内容 responseTimestamp DateTime? // 返回时间 // ── 链路元数据 ── subagentSessionId String? // 子 agent 的 session ID subagentType String? // subagent 类型 subagentName String? // subagent 显示名 status String default(dispatched) // dispatched | running | completed | failed | timeout // ── 子 agent 转发指标 ── subagentTokens Int default(0) subagentLatencyMs Int default(0) // 从 dispatch 到 response 的总耗时 createdAt DateTime default(now()) updatedAt DateTime updatedAt index([sessionId]) index([dispatchExecutionId]) index([responseExecutionId]) index([subagentSessionId]) index([status]) }2.2 数据流详解上传拆解流程POST /api/ingest/upload {task_id, interactions[]} │ ├─ normalizeInteractions() → RawInteraction[] │ ├─ 挆 session 是否已存在 │ ├─ 新 session: 创建 Session 行 │ └─ 已存在: mergeSessionInteractionsMonotonic() 合并 │ ├─ turn-split: 按 role 拆解每个 RawInteraction → Turn[] │ ├─ 每个 Turn: 计算 token/时间/模型字段 │ ├─ 每个 Turn.tool_calls: 拆解 → ToolCall[] │ ├─ 每个 Turn 中 skill 相关: 拆解 → SkillEvent[] │ ├─ 每个 assistant Turn: 重构 inputMessages → inputMessagesJson │ │ ├─ 从 preceding interactions 重建 request messages (system history tool results) │ │ ├─ 计算 inputMessagesCount / inputMessagesTokens / contextWindowPct │ │ ├─ 生成 contentSummary (前 200 字截断) │ ├─ bridge-builder: 扫描 task() tool_calls 对应 subagent turns │ ├─ 每个 task() 调用 → InteractionBridge (dispatch 侧) │ ├─ 匹配 subagent_session_id → 填充 response 侧 │ ├─ 计算 subagent 转发指标token/耗时 │ ├─ execution-split: 按 agent 维度拆分 Execution 行 │ ├─ root agent → Execution(isSubagentfalse) │ ├─ 每个 subagent → Execution(isSubagenttrue, parentExecutionIdroot.id) │ ├─ 每层聚合: sum(turn token/时间/工具数/skill数) │ ├─ write-all: │ ├─ Upsert Session (聚合指标) │ ├─ Upsert Turn[] (per-turn) │ ├─ Upsert ToolCall[] (per-tool-call) │ ├─ Upsert SkillEvent[] (per-skill-event) │ ├─ Upsert InteractionBridge[] (交互链路) │ ├─ Upsert Execution[] (per-agent 聚合) │ ├─ Upsert ExecutionSkill[] (per-execution skill 绑定) │ ├─ Upsert SessionSkill[] (per-session skill 绑定)关键设计决策Turn 行独立存储而非 JSON blob每个 turn 有独立 DB 行可索引、可查询、可聚合、无需解析 JSON。ToolCall 行独立存储工具调用有自己的行可按 name 查询、按 error 分类统计。SkillEvent 行独立存储skill 加载/调用是独立事件区分 load/invoke/unload 三种类型。InteractionBridge 显式链路主→子交互不再是隐含推断而是显式记录 dispatch→response 全链路。Execution 行按 agent 拆分每个 subagent 有独立 Execution 行聚合指标可直接查询。cost 写入时定格不再依赖读取时动态计算避免 pricing 表变更导致历史 cost 漂移。Session 聚合指标派生Session 的总量指标由 turn 数据 SUM 派生保持一致性。LLM 输入上下文独立存储assistant turn 的 inputMessagesJson 存完整 prompt 消息序列system history tool results用于上下文治理。单独字段而非嵌入 contentJson便于独立查询和折叠展示。长内容默认折叠inputMessagesJson 和 contentJson 可能极长Turn 行同时存 inputMessagesCount/inputMessagesTokens/contentSummary 等摘要字段UI 默认展示摘要、点击展开全文。§3 API 契约设计3.1 写入端本地文件导入唯一数据入口| 路径 | 方法 | 描述 | 入站 | 出站 | |-|-|-|-|-| |/api/ingest/import-file| POST | 本地文件导入multipart form |{source: opencode-db | claude-jsonl, file: binary, sessionId?: string}|{sessionId[], importedCount, errors[]}| |/api/ingest/import-file/sessions| POST | Opencode DB session 列表查询第一步 |{source: opencode-db, file: binary}|{sessions: [{id, createdAt, firstQuery, turnCount, model}]}|导入流程:opencode-db上传文件 → 读取 DB → 返回 session 列表 → 用户选择 → 读取选中 session 数据 → adapter 解析 → turn-split → bridge-builder → execution-split → write-allclaude-jsonl上传文件 → 直接解析入库 → turn-split → bridge-builder → execution-split → write-all3.2 读取端| 路径 | 方法 | 描述 | 核心查询参数 | |-|-|-|-| |/api/observe/data| GET | Session 列表分页 |?page1pageSize20isSubagentfalseuserxxx| |/api/observe/session| GET | Session 详情含聚合指标 |?taskIdxxx| |/api/observe/session/turns| GET | Session 的 Turn 列表 |?taskIdxxxisSubagentfalseroleassistant| |/api/observe/session/turns/:turnId| GET | 单个 Turn 详情含 contentJson inputMessagesJson | — | |/api/observe/session/bridges| GET | Session 的 InteractionBridge 列表 |?taskIdxxx| |/api/observe/executions| GET | Session 的 Execution 列表含 subagent |?taskIdxxx| |/api/observe/executions/:executionId| GET | 单个 Execution 详情 | — | |/api/observe/stats| GET | 快速聚合统计 |?taskIdxxx(返回 token/耗时/cost 汇总) |核心 API 响应结构Session 列表(/api/observe/data){ items: [ { sessionId: ..., taskId: ..., query: ..., startTime: ..., endTime: ..., totalTokens: 15000, totalCost: 0.45, totalLatencyMs: 120000, totalToolCallCount: 8, totalSkillLoadCount: 2, totalSubagentCount: 1, model: ..., user: ... } ], total: 100, page: 1 }Session 详情(/api/observe/session){ sessionId: ..., taskId: ..., query: ..., startTime: ..., endTime: ..., totalTokens: 15000, totalCost: 0.45, agents: [ { executionId: ..., agentName: root, isSubagent: false, tokens: 12000, cost: 0.36, toolCallCount: 6, skillLoadCount: 2, subagentCount: 1 }, { executionId: ..., agentName: Kuafu, isSubagent: true, parentExecutionId: ..., tokens: 3000, cost: 0.09, toolCallCount: 2, skillLoadCount: 0 } ], skills: [ {skillName: agent-debug-diagnosis, version: 3, invocationCount: 1} ] }Turn 列表(/api/observe/session/turns){ items: [ { turnId: ..., turnIndex: 0, role: user, contentSummary: 用户查询..., agentName: root, isSubagent: false, totalTokens: 0, inputMessagesCount: 0, inputMessagesTokens: 0, latencyMs: 0, createdAt: ..., toolCalls: [], skillEvents: [] }, { turnId: ..., turnIndex: 1, role: assistant, contentSummary: 助手回复摘要前200字..., inputMessagesCount: 5, inputMessagesTokens: 3000, contextWindowPct: 15.0, agentName: root, agentName: root, isSubagent: false, totalTokens: 500, inputTokens: 300, outputTokens: 200, latencyMs: 3500, createdAt: ..., completedAt: ..., model: gpt-4o, toolCalls: [ {toolCallId: ..., toolName: bash, state: ok, durationMs: 1200} ], skillEvents: [] } ] }InteractionBridge 列表(/api/observe/session/bridges){ items: [ { bridgeId: ..., dispatchExecutionId: ..., dispatchContent: 分析 vmcore 文件..., dispatchTimestamp: ..., responseExecutionId: ..., responseContent: 诊断结果..., responseTimestamp: ..., subagentName: Kuafu, status: completed, subagentTokens: 3000, subagentLatencyMs: 45000 } ] }§4 UI 交互设计4.1 页面结构/observe → Session 列表页 /observe/:taskId → Session 详情页 ├── Overview Tab → 聚合指标 Agent 概览 Skill 概览 ├── Turns Tab → Turn 列表支持 filter: agent/role/tool/skill ├── Timeline Tab → 甘特图时间线turn → tool → skill → subagent dispatch ├── Subagents Tab → Subagent 详情每个 subagent 卡片 交互链路 ├── Skills Tab → Skill 调用明细 └── Interactions Tab → 交互链路图主↔子通信可视化4.2 Session 详情页 — Overview Tab顶部聚合指标卡片总 token、总耗时、总 cost、工具调用数、skill 数、subagent 数中部Agent 概览root 每个 subagent 的小卡片含各自的 token/耗时/cost底部Skill 概览每个 skill 的调用次数 版本4.3 Session 详情页 — Turns Tab左侧Turn 时间线列表每个 turn 显示角色 badge agent badge token 数 耗时 工具调用摘要过滤器agentroot/subagent name、role、有/无 tool call、有/无 skill event右侧Turn 详情面板选中 turn 后展示Content 区完整内容markdown 渲染 折叠上下文区LLM Input默认折叠折叠态显示输入 N 条消息共 X tokens占 context window Y%摘要行 展开按钮展开态逐条显示发给 LLM 的消息列表每条消息显示role badgesystem紫色 / user蓝色 / assistant灰色 / tool_result绿色token 数如有消息内容默认折叠超过 200 字的消息点击可独立展开用途上下文治理——理解 LLM 收到了什么上下文、上下文是否过长、是否包含冗余/误导信息输出区LLM Output默认折叠折叠态显示 contentSummary前 200 字 输出 X tokens 展开按钮展开态完整内容渲染thinking/reasoning blocks 独立折叠区text 部分 markdown 渲染tool_calls 以 badge 形式嵌入用途理解 LLM 产出了什么、输出质量如何Token 区input/output/reasoning/cache 条形图Tools 区工具调用列表name duration state 展开看 args/resultSkills 区skill 事件列表name type duration successTiming 区created/completed/latency/ttftModel 区model/modelId/provider/temperature/finishReason4.4 Session 详情页 — Timeline Tab甘特图时间线行按 agent 分组root / subagent列每个 turn 的时间段 内嵌 tool/skill/subagent dispatch 的子段颜色区分LLM 思考蓝、工具调用绿、skill 加载黄、subagent dispatch橙悬浮显示 token 数 耗时4.5 Session 详情页 — Subagents Tab每个 subagent 一个独立卡片聚合指标token/耗时/cost/工具数/skill数Turn 概览该 subagent 的所有 turn 摘要交互链路该 subagent 与主 agent 的 InteractionBridge点击可展开该 subagent 的 Turn 详情与 Turns Tab 共用详情面板组件4.6 Session 详情页 — Interactions Tab交互链路图左侧主 agent 的 task() dispatch 事件列表中间连接线dispatch → response右侧subagent 的 response 事件列表每条连接线标注status subagent 耗时 token 数点击连接线弹出详细 dispatch content response content4.7 Session 列表页表格列taskId、query、startTime、endTime、totalTokens、totalCost、totalLatencyMs、model、user、subagentCount快速筛选按 user、model、有无 subagent、有无 skill§5 代码结构设计5.1 目录结构cannbot-insight/ ├── bin/ │ └─ cli.js # CLI 入口cannbot-insight import --source type --path file ├── prisma/ │ └── schema.prisma # §2 定义的数据模型 ├── src/ │ ├── app/ │ │ ├── api/ │ │ │ ├── ingest/ │ │ │ │ ├── import-file/route.ts # 本地文件导入入口multipart │ │ │ │ └── import-file/sessions/route.ts # opencode DB session 列表查询选择前展示 │ │ │ └── observe/ │ │ │ ├── data/route.ts # Session 列表 │ │ │ ├── session/route.ts # Session 详情 │ │ │ ├── session/turns/route.ts # Turn 列表 │ │ │ ├── session/bridges/route.ts # Bridge 列表 │ │ │ ├── executions/route.ts # Execution 列表 │ │ │ └── stats/route.ts # 聚合统计 │ │ ├── observe/ │ │ │ ├── page.tsx # Session 列表页 │ │ │ └── [taskId]/page.tsx # Session 详情页 │ │ └── layout.tsx │ │ └─ globals.css │ ├── lib/ │ │ ├── ingest/ │ │ │ ├── normalize.ts # 交互归一化 │ │ │ ├── turn-split.ts # turn 拆解器 │ │ │ ├── bridge-builder.ts # InteractionBridge 构建器 │ │ │ ├── execution-split.ts # Execution 拆分器 │ │ │ ├── merge.ts # 增量上传合并 │ │ │ └── adapters/ # 数据源适配器本地文件解析 │ │ │ ├── opencode-db.ts # opencode sessions.db SQLite 读取器 │ │ │ ├── claude-jsonl.ts # Claude Code session JSONL 解析器 │ │ │ └── index.ts # 适配器注册表按 source type 路由 │ │ ├── storage/ │ │ │ ├── contenteditable="false">【免费下载链接】cannbot-skillsCANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体本仓库为其提供可复用的 Skills 模块。项目地址: https://gitcode.com/cann/cannbot-skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考