feat(aia): Protocol Agent streaming + editable state panel + protocol generation plan

Day 2 Development (2026-01-24):

Backend Enhancements:
- Implement SSE streaming in ProtocolAgentController using createStreamingService
- Add data condensation via LLM in ProtocolOrchestrator.handleProtocolSync
- Support stage editing without resetting progress
- Add explicit JSON output format for each stage in system prompt
- Create independent seed script for Protocol Agent (seed-protocol-agent.ts)

Frontend Improvements:
- Integrate useAIStream hook for typewriter effect in ChatArea
- Add MarkdownContent component for basic Markdown rendering
- Implement StageEditModal for editing stage data (scientific question, PICO, etc.)
- Add edit button to StageCard (visible on hover)
- Fix routing paths from /aia to /ai-qa
- Enhance CSS with full-screen layout and Markdown styles

New Documentation:
- One-click protocol generation development plan (v1.1)
- Editor selection evaluation (Novel vs BlockNote vs Tiptap)
- Novel fork strategy for AI-native editing

Technical Decisions:
- Choose Novel (Fork) as protocol editor for AI-first design
- Two-stage progressive generation: summary in chat, full protocol in editor
- 10-day development plan for protocol generation feature

Code Stats:
- Backend: 3 files modified, 1 new file
- Frontend: 9 files modified, 2 new files
- Docs: 3 new files

Status: Streaming and editable features working, protocol generation pending
This commit is contained in:
2026-01-24 23:06:33 +08:00
parent 596f2dfc02
commit 4d7d97ca19
18 changed files with 2708 additions and 192 deletions

View File

@@ -0,0 +1,150 @@
# **深度选型报告Novel vs. BlockNote**
**评估对象**: Novel (Fork源码方案) vs. BlockNote (npm包方案)
**业务场景**: AI 驱动的临床研究方案生成编辑器
**核心结论**: **推荐 Novel (Fork)**。虽然初期成本略高,但在 AI 集成和 UI 定制上拥有绝对的主动权。
## **1\. 核心架构对比 (The Architecture)**
两者底层都是 **Tiptap (ProseMirror)**,但封装哲学完全不同。
| 维度 | BlockNote | Novel |
| :---- | :---- | :---- |
| **封装程度** | **极高**。它试图隐藏 Tiptap 的复杂性,创造了一套自己的 Schema (BlockNote Schema)。 | **中等**。它本质上只是 Tiptap 的一个 React Wrapper直接暴露 Tiptap 的配置。 |
| **数据结构** | **自定义 JSON Blocks**。它把 Tiptap 的 Document 转换成了自己的 Block 数组。 | **标准 Tiptap JSON**。完全遵循 ProseMirror 标准结构。 |
| **UI 耦合度** | **高**。Slash Menu 和 Side Menu 是硬编码在库里的,很难改样式。 | **低 (Fork后)**。所有 UI 组件Menu, Bubble都是 React 代码,你可以随意魔改。 |
| **React 亲和度** | ⭐⭐⭐⭐⭐ (专为 React 设计) | ⭐⭐⭐⭐⭐ (专为 React/Next.js 设计) |
**🧐 分析**
* 如果您只是想做一个简单的笔记应用BlockNote 完胜。
* 但您要做的是 **"AI Protocol Editor"**,需要插入复杂的 **"样本量计算器按钮"**、**"引用卡片"**。BlockNote 的自定义 Schema 可能会成为绊脚石,而 Novel 直接操作 Tiptap灵活性无限。
## **2\. AI 集成维度 (The AI Factor)**
这是您最关心的部分:如何与你们自研的 StreamingService 对接。
### **BlockNote 的表现**
* **现状**: 它没有内置 AI 自动补全逻辑。
* **实现路径**: 您需要自己监听后端流式数据,然后手动调用 editor.insertBlocks()。
* **痛点**: 处理“流式打字机效果”时BlockNote 的 Block 更新机制可能会导致光标跳动或性能问题。
### **Novel 的表现**
* **现状**: 它是**为 AI 而生**的。它内置了 useCompletion (Vercel SDK) 的完整逻辑。
* **优势**: 它已经处理好了 "AI 生成时的 Ghost Text (幽灵文字)"、"生成后的 Markdown 解析"、"生成中的光标锁定" 等细节。
* **实现路径 (Fork)**: 您只需要把 useCompletion 替换为你们的 useAIStream剩下的 UI 交互(如 /ai 唤起生成框)都是现成的。
**🏆 胜出者**: **Novel**。它在 AI 交互体验上已经帮您踩平了坑。
## **3\. 医疗特性扩展性 (Medical Features)**
### **场景 A访视排期表 (复杂表格)**
* **BlockNote**: 对表格支持较弱,很难实现合并单元格。
* **Novel**: 可以直接引入 @tiptap/extension-table。虽然 Novel 默认表格也不强,但您可以直接修改源码,引入更强的表格插件。
### **场景 B文献引用 (Citation)**
* **BlockNote**: 需要学习它的 Custom Schema API 来定义一个 Inline Content。文档相对较少。
* **Novel**: 直接写一个标准的 Tiptap NodeView (React 组件)。网上的 Tiptap 教程都能用。
### **场景 C导出 Word**
* **BlockNote**: 它的 JSON 结构是非标准的,您需要先转成 Markdown/HTML再转 Word。
* **Novel**: 它的 JSON 是 Tiptap 标准的。社区里有现成的 tiptap-to-docx 转换库,或者直接用 pandoc。
**🏆 胜出者**: **Novel**。标准的 Tiptap 生态远比 BlockNote 的私有生态强大。
## **4\. 潜在风险与成本 (The "Gotchas")**
### **🔴 Novel (Fork) 的风险**
1. **代码维护成本**: 您 Copy 了几千行代码进项目,以后 Novel 官方更新了,您得手动同步(或者不仅同步,直接断开维护)。
2. **样式污染**: Novel 使用 Tailwind CSS类名可能会与您的 Ant Design 冲突。需要小心处理 CSS 作用域。
3. **学习曲线**: 您的团队需要懂一点 Tiptap 的底层原理Node, Mark, Extension
### **🔴 BlockNote 的风险**
1. **天花板效应**: 开发到第 2 个月产品经理说“我要在编辑器里画一个甘特图”BlockNote 可能直接做不到。
2. **黑盒**: 作为一个 npm 包,如果它有 Bug您只能等官方修或者发 Patch。
## **5\. 最终决策建议**
**如果您满足以下条件,请坚决选择 Novel (Fork)**
1. 您的团队有能力读懂并修改 React 源码。
2. 您不仅需要“写文字”,还需要在文档里插入“交互式组件”(如计算器、图表)。
3. 您对 UI 的精细度要求很高(必须符合 Ant Design X 风格)。
**如果您满足以下条件,才退而求其次选择 BlockNote**
1. 您的团队只有 1 个前端,且不熟悉富文本原理。
2. 您只需要一个“能打字的 Notion”不需要太复杂的 AI 交互。
### **🚀 您的选择确认**
您之前的 **Phase 1 (Fork Novel)** 计划是非常明智的。
**不要纠结了Fork Novel 是正确的路。** BlockNote 看起来简单,但在深度 AI 集成场景下,它是\*\*“先甜后苦”**;而 Novel 是**“先苦后甜”\*\*,一旦您掌握了源码,天空才是极限。
鉴于 Novel 的代码质量很高(基于 Tiptap + React完全放弃它太可惜。
我的最终建议是:不要作为 npm 包引入 Novel而是将其源码 Copy 到项目中作为起点 (Fork & Own)。
这样既利用了它现成的 UI (Slash Menu, Drag Handle),又拥有了 100% 的控制权,可以随意修改 AI 逻辑和组件。
🗺️ 推荐落地路线图 (Phase 1-3)
这个路线图将确保你们在 Phase 1 快速上线,同时为 Phase 2 的医疗特性预留空间。
Phase 1: Fork Novel + 对接你们的 StreamingService (快速上线)
目标3天内 跑通“编辑器 + AI 流式生成”。
Action 1: 源码引入
不要 npm install novel。
去 GitHub 把 novel/packages/core/src 下的核心代码复制到 frontend-v2/src/shared/components/Editor。
Action 2: 剥离 Vercel SDK对接自研后端
找到 useCompletion 或 AI 调用的 hook。
替换为 你们现有的 useAIStream Hook (来自 shared/components/Chat/hooks/useAIStream.ts)。
修改 API 路径:指向 /api/v1/aia/protocol-agent/generate。
Action 3: 保留核心交互
保留 Slash 命令 (/) 和 拖拽手柄 (DragHandle)。这些是 Notion 体验的灵魂,自己写很费劲。
交付物:一个长得像 Notion、实际上调用的你们 Fastify 后端的编辑器。支持 Markdown 导出。
Phase 2: 医疗特性增强 (差异化竞争)
目标:解决“表格”和“引用”这两个痛点。
Action 1: 集成 Tiptap Table 扩展
Novel 默认可能对表格支持较弱。
引入 @tiptap/extension-table并定制渲染组件支持合并单元格访视排期表刚需
Action 2: 开发 CitationBlock (对接 PKB)
这是 Novel 没有的功能。
基于 Tiptap 的 NodeView开发一个 React 组件:<Citation id="123" title="阿司匹林..." />。
点击时,右侧弹窗显示 PKB 中的文献详情。
Action 3: 导出 Word
使用 docx.js 或 pandoc (后端服务),将 Tiptap JSON 转换为 .docx。注意表格的转换是难点需预留时间调试。
Phase 3: 如需更深定制 (兜底方案)
如果发现 Fork 来的代码太乱,难以维护。
回退策略:此时你们已经熟悉了 Tiptap 的 API。可以丢弃 Novel 的 UI 代码,仅保留 Tiptap 核心,用 Ant Design X 重写工具栏。数据模型 (JSON) 是完全兼容的,用户数据不会丢。