feat(ssa): SSA Agent mode MVP - prompt management + Phase 5A guardrails + UX enhancements

Backend:
- Agent core prompts (Planner + Coder) now loaded from PromptService with 3-tier fallback (DB -> cache -> hardcoded)
- Seed script (seed-ssa-agent-prompts.ts) for idempotent SSA_AGENT_PLANNER + SSA_AGENT_CODER setup
- SSA fallback prompts added to prompt.fallbacks.ts
- Phase 5A: XML tag extraction, defensive programming prompt, high-fidelity schema injection, AST pre-check
- Default agent mode migration + session CRUD (rename/delete) APIs
- R Docker: structured error handling (20+ patterns) + AST syntax pre-check

Frontend:
- Default agent mode (QPER toggle removed), view code fix, analysis result cards in chat
- Session history sidebar with inline rename/delete, robust plan parsing from reviewResult
- R code export wrapper for local reproducibility (package checks + data loader + polyfills)
- SSA workspace CSS updates for sidebar actions and plan display

Docs:
- SSA module doc v4.2: Prompt inventory (2 Agent active / 11 QPER archived), dev progress updated
- System overview doc v6.8: SSA Agent MVP milestone
- Deployment checklist: DB-5 (seed script) + BE-10 (prompt management)

Made-with: Cursor
This commit is contained in:
2026-03-08 15:23:09 +08:00
parent c681155de2
commit ac724266c1
24 changed files with 1598 additions and 140 deletions

View File

@@ -1,13 +1,20 @@
# SSA智能统计分析模块 - 当前状态与开发指南
> **文档版本:** v4.1
> **文档版本:** v4.2
> **创建日期:** 2026-02-18
> **最后更新:** 2026-03-07
> **最后更新:** 2026-03-08
> **维护者:** 开发团队
> **当前状态:** 🎉 **QPER 主线闭环 + Phase I-IV + Phase V-A + 双通道架构 Phase 1-3 + Agent 通道体验优化完成**
> **当前状态:** 🎉 **QPER 主线闭环 + Phase I-IV + Phase V-A + 双通道架构 Phase 1-3 + Agent 通道体验优化 + Agent Prompt 运营管理化完成**
> **文档目的:** 快速了解SSA模块状态为新AI助手提供上下文
>
> **最新进展2026-03-07 Agent 通道体验优化 — 方案 B 左右职责分离 + 10 项 Bug 修复**
> **最新进展2026-03-08 Agent 核心 Prompt 接入运营管理端**
> - ✅ **PlannerAgent Prompt 动态化** — `AgentPlannerService.buildSystemPrompt()` 改为 `PromptService.get('SSA_AGENT_PLANNER', { dataContext })`,支持运营管理端在线编辑、灰度预览、版本管理
> - ✅ **CoderAgent Prompt 动态化** — `AgentCoderService.buildSystemPrompt()` 改为 `PromptService.get('SSA_AGENT_CODER', { dataContext })`,同上
> - ✅ **三级容灾** — 数据库 ACTIVE 版本 → 内存缓存5 分钟) → 代码 fallback`prompt.fallbacks.ts`),任何一层失败自动降级
> - ✅ **种子数据脚本** — `prisma/seed-ssa-agent-prompts.ts` 幂等写入初始 Promptupsert template + ACTIVE v1
> - ✅ **Handlebars 模板变量** — 两个 Prompt 均使用 `{{{dataContext}}}` 三括号无转义渲染,运营可编辑模板内容但保留变量占位符
>
> **此前进展2026-03-07 Agent 通道体验优化 — 方案 B 左右职责分离 + 10 项 Bug 修复):**
> - ✅ **方案 B — 左右职责分离** — 左侧对话区仅输出简洁视线牵引提示,右侧工作区承载计划/代码/结果全部交互;双屏状态互斥同步(右侧操作→左侧追加审计消息);历史穿梭(点击左侧卡片→右侧切换对应任务)
> - ✅ **JWT Token 刷新机制** — 前端 `ensureFreshToken()` 在 API 调用前检查并刷新过期 Token解决 HTTP 401 问题
> - ✅ **代码截断修复** — LLM maxTokens 4000→8000 + CSS max-height 60vh + word-break 优化
@@ -194,7 +201,8 @@ AnalysisRecord {
| **双通道 Phase 3** | **前端集成SSE + AgentCodePanel + 确认流程)** | **~6h** | ✅ **已完成(三步确认 + 流式代码 + 7 种 SSE 事件)** | 2026-03-02 |
| **Agent 体验优化** | **方案 B 左右职责分离 + 10 项 Bug 修复** | **~8h** | ✅ **已完成12 文件, +931/-203 行)** | 2026-03-07 |
| **Plan-and-Execute 设计** | **分步执行架构设计(代码累加 + 工程护栏)** | **~4h** | ✅ **已完成(架构评审 + 三份评估报告)** | 2026-03-07 |
| **Phase 5A** | **CoderAgent 防错护栏XML 标签 + AST 预检 + 防御性 Prompt + 高保真 Schema** | **~6h** | 📋 待开始 | - |
| **Phase 5A** | **CoderAgent 防错护栏XML 标签 + AST 预检 + 防御性 Prompt + 高保真 Schema** | **~6h** | **已完成** | 2026-03-08 |
| **Agent Prompt 管理化** | **PlannerAgent + CoderAgent Prompt 接入运营管理端PromptService 三级容灾)** | **~2h** | ✅ **已完成(种子脚本 + fallback + 文档)** | 2026-03-08 |
| **Phase 5B** | **后端分步执行引擎DB schema + 代码累加循环 + 错误分类短路 + 新 SSE 事件)** | **~10h** | 📋 待开始 | - |
| **Phase 5C** | **前端分步展示(类型扩展 + AgentCodePanel 多步骤 UI + SSE 处理器)** | **~6h** | 📋 待开始 | - |
| **Phase V-B** | **反思编排 + 高级特性** | **18h** | 📋 待开始 | - |
@@ -223,6 +231,7 @@ AnalysisRecord {
| **Phase V-A 前端** | WorkflowTimeline 可编辑化SingleVarSelect + MultiVarTags + 三层柔性拦截)+ ssaStore updateStepParams + SSAWorkspacePane 同步阻塞执行 + DynamicReport 对象 rows 兼容 + Word 导出修复 | ✅ |
| **双通道 Agent 通道** | PlannerAgent意图→分析计划+ CoderAgent计划→R 代码,含流式生成)+ CodeRunnerService沙箱执行+ AgentCodePanel三步确认 UI+ ModeToggle通道切换+ R Docker /execute-code 端点 | ✅ |
| **Agent 体验优化** | 方案 B 左右职责分离(视线牵引+状态互斥+历史穿梭)+ JWT 刷新 + 代码截断修复 + 重试流式生成 + R Docker 结构化错误20+ 模式)+ Prompt 铁律 + parseCode 健壮化 + consoleOutput 类型防御 + 进度条同步 + 导出/查看代码恢复 + ExecutingProgress 动态 UI | ✅ |
| **Agent Prompt 管理化** | PlannerAgent + CoderAgent System Prompt 从硬编码迁移至 PromptService 动态加载;运营管理端在线编辑/灰度预览/版本回滚三级容灾DB→缓存→fallback种子脚本 `seed-ssa-agent-prompts.ts` 幂等 | ✅ |
| **测试** | QPER 端到端 40/40 + 集成测试 7 Bug 修复 + Phase I E2E 31/31 + Phase II E2E 38/38 + Phase III E2E 13/13+4skip + Phase IV E2E 25/25 + Phase V-A 前后端集成测试通过 + 双通道 E2E 8/8 通过 + Agent 体验测试通过(统计分析结果+图表正常) | ✅ |
---
@@ -350,6 +359,51 @@ npx tsx scripts/seed-ssa-pico-prompt.ts # Phase I: PICO 推断
npx tsx scripts/seed-ssa-phase2-prompts.ts # Phase II: 8 Prompt
npx tsx scripts/seed-ssa-phase3-prompts.ts # Phase III: SSA_METHOD_CONSULT
npx tsx scripts/seed-ssa-phase4-prompts.ts # Phase IV: SSA_ANALYZE_PLAN
npx tsx prisma/seed-ssa-agent-prompts.ts # Agent: SSA_AGENT_PLANNER + SSA_AGENT_CODER
```
---
## 🧠 Prompt 全景盘点QPER vs Agent
> **结论:当前 Agent 模式仅使用 2 个 Prompt其余 11 个为 QPER 遗产。**
>
> 自 `chat.routes.ts` 硬编码 `executionMode = 'agent'` 后QPER 通道代码不再执行。
### Agent 通道 Prompt当前生效 ✅)
| # | Prompt Code | 服务 | 模板变量 | 用途 |
|---|------------|------|---------|------|
| 1 | `SSA_AGENT_PLANNER` | `AgentPlannerService` | `{{{dataContext}}}` | 规划师 System Prompt制定统计分析计划JSON 格式) |
| 2 | `SSA_AGENT_CODER` | `AgentCoderService` | `{{{dataContext}}}` | 编码器 System Prompt生成可执行 R 代码XML 标签输出) |
**管理方式:** 运营管理端 → Prompt 管理 → SSA 模块 → 在线编辑/灰度预览/版本管理
**容灾链路:** 数据库 ACTIVE 版本 → 内存缓存5min TTL→ 代码 fallback`prompt.fallbacks.ts`
### QPER 通道 Prompt当前不执行保留备用
| # | Prompt Code | 服务 | 用途 |
|---|------------|------|------|
| 3 | `SSA_BASE_SYSTEM` | `SystemPromptService` | QPER 对话基础角色定义 |
| 4 | `SSA_INTENT_ROUTER` | `IntentRouterService` | LLM 意图分类器6 种意图) |
| 5 | `SSA_INTENT_CHAT` | `SystemPromptService` | 普通聊天意图指令 |
| 6 | `SSA_INTENT_EXPLORE` | `SystemPromptService` | 数据探索意图指令 |
| 7 | `SSA_INTENT_CONSULT` | `SystemPromptService` | 方法咨询意图指令 |
| 8 | `SSA_INTENT_ANALYZE` | `SystemPromptService` | 执行分析意图指令 |
| 9 | `SSA_INTENT_DISCUSS` | `SystemPromptService` | 结果讨论意图指令 |
| 10 | `SSA_INTENT_FEEDBACK` | `SystemPromptService` | 改进反馈意图指令 |
| 11 | `SSA_QUERY_INTENT` | `QueryService` | Q 层 LLM 意图解析 |
| 12 | `SSA_PICO_INFERENCE` | `PicoInferenceService` | PICO 结构推断 |
| 13 | `SSA_REFLECTION` | `ReflectionService` | R 层论文级结论生成 |
### Agent 调用链(仅 2 个 Prompt
```
用户消息
→ ChatHandlerService.handleAgentMode()
→ AgentPlannerService.generatePlan() ← SSA_AGENT_PLANNER
→ AgentCoderService.generateCodeStream() ← SSA_AGENT_CODER
→ CodeRunnerService.executeCode() ← 纯 R 执行,无 Prompt
```
---
@@ -443,7 +497,7 @@ npx tsx scripts/seed-ssa-phase4-prompts.ts # Phase IV: SSA_ANALYZE_PLAN
---
**文档版本:** v4.1
**最后更新:** 2026-03-07
**当前状态:** 🎉 QPER 主线闭环 + Phase I-IV + Phase V-A + 双通道架构 Phase 1-3 + Agent 体验优化已完成
**下一步:** Phase 5ACoderAgent 防错护栏)→ Phase 5B分步执行引擎→ Phase 5C前端分步展示
**文档版本:** v4.2
**最后更新:** 2026-03-08
**当前状态:** 🎉 SSA Agent 模式 MVP 完成(QPER 闭环 + Phase I-IV + Phase V-A + 双通道架构 + Agent 体验优化 + Prompt 运营管理化 + Phase 5A 护栏)
**下一步:** Phase 5B分步执行引擎→ Phase 5C前端分步展示→ Phase V-B反思编排

View File

@@ -0,0 +1,110 @@
# **架构优化方案R 代码的本地复现与导出包装 (Export Wrapper)**
**问题诊断:** 大模型在 Agent 管线中生成的 R 代码是高度依赖“平台沙箱环境”的。它缺失了数据读取操作 (df),且引用了平台专属的 UI 辅助函数 (make\_table\_block\_from\_df 等)。
**解决目标:** 用户点击“下载 R 代码”时,系统必须动态注入“本地兼容层”,使得代码可以在任何一台普通的 RStudio 中一键运行。
## **一、 根本解决方案:导出包装器 (Export Wrapper)**
当用户点击“下载 R 代码”时,前端不能仅仅把 Agent 生成的代码原样保存为 .R 文件。我们需要像编译器一样,将代码包裹在一个**标准的本地复现模板**中。
完整的导出文件应该由 3 个部分拼接而成:
1. **数据加载层 (Data Loading)**
2. **函数兼容层 (Polyfills / Mock Helpers)**
3. **Agent 生成的核心代码 (Core Logic)**
## **二、 包装器代码实现范例**
前端或后端在生成下载文件时,请使用以下字符串拼接逻辑:
// 伪代码:在前端 SSACodeModal 或后端导出 API 中实现
function generateDownloadableRCode(agentCode: string, fileName: string): string {
const headerAndPolyfills \= \`
\# \=====================================================================
\# SSA-Pro 智能统计分析 \- 本地复现脚本
\# \=====================================================================
\# 1\. 自动安装缺失的包 (本地复现安全保障)
required\_packages \<- c("dplyr", "gtsummary", "base64enc", "ggplot2")
new\_packages \<- required\_packages\[\!(required\_packages %in% installed.packages()\[,"Package"\])\]
if(length(new\_packages)) install.packages(new\_packages)
suppressPackageStartupMessages({
library(dplyr)
library(gtsummary)
library(base64enc)
library(ggplot2)
})
\# \=====================================================================
\# 2\. 数据读取 (请确保数据文件与本脚本在同一目录下)
\# \=====================================================================
\# 系统已将您的原始数据名填入,如果路径不同请手动修改:
file\_name \<- "${fileName}"
if (file.exists(file\_name)) {
if (grepl("\\\\\\\\.csv$", file\_name, ignore.case \= TRUE)) {
df \<- read.csv(file\_name, stringsAsFactors \= FALSE)
} else if (grepl("\\\\\\\\.xlsx?$", file\_name, ignore.case \= TRUE)) {
library(readxl)
df \<- read\_excel(file\_name)
}
} else {
\# 如果找不到文件,生成测试数据以防代码直接崩溃
warning(paste("找不到数据文件:", file\_name, "。将使用模拟数据进行演示。"))
df \<- data.frame(
root\_curve \= sample(c(1, 2), 100, replace \= TRUE),
Yqol \= sample(c(0, 1), 100, replace \= TRUE)
)
}
\# \=====================================================================
\# 3\. 平台 UI 辅助函数本地兼容层 (Polyfills)
\# 这使得平台专用的 make\_\*\_block 函数在本地控制台优雅地输出,而不报错
\# \=====================================================================
make\_markdown\_block \<- function(text) {
cat("\\\\n========================================\\\\n")
cat(text, "\\\\n")
}
make\_table\_block\_from\_df \<- function(data, title="", footnote="") {
cat("\\\\n---", title, "---\\\\n")
print(data)
if(footnote \!= "") cat("注:", footnote, "\\\\n")
return(list(type="table"))
}
make\_image\_block \<- function(base64\_data, title="", alt="") {
cat("\\\\n\[图形已生成:", title, "- 请查看 RStudio 的 Plots 面板\]\\\\n")
return(list(type="image"))
}
make\_kv\_block \<- function(items, title="") {
cat("\\\\n---", title, "---\\\\n")
print(unlist(items))
return(list(type="key\_value"))
}
\# \=====================================================================
\# 4\. 核心分析代码 (由 AI Agent 生成)
\# \=====================================================================
\`;
return headerAndPolyfills \+ "\\n" \+ agentCode;
}
## **三、 为什么必须这么做?(架构收益)**
1. **防患于未然的数据读取:** 我们不仅注入了 read.csv还加入了 file.exists 检查。如果医生把 R 脚本发给另一个没有原始数据的统计师,代码会自动生成一组 Mock模拟数据。这样 R 脚本无论如何都能跑通,极大提升了产品的专业感。
2. **优雅的 Polyfills (兼容层) 技术:**
这是前端工程(如适配老版本浏览器)最常用的技术。我们在脚本头部用普通的 print() 和 cat() 重写了 make\_table\_block\_from\_df 等函数。这样,大模型生成的复杂 UI 代码在本地 RStudio 中执行时,不仅**不会报错**,还会把结果**整齐地打印在本地控制台上**。
3. **保持 Agent Prompt 的纯净:**
我们**不需要**去修改 CoderAgent 的 System Prompt 让它“记得写读取文件的代码”。因为每次让 LLM 动态写数据读取逻辑它很容易因为编码UTF-8 vs GBK或文件路径错误而翻车。把这种死板的工作交给前端的字符串拼接Wrapper是最稳定、最省 Token 的做法。
## **四、 实施建议**
请前端团队接手此任务:
在 AgentCodePanel.tsx 或 SSACodeModal.tsx 中,找到处理\*\*“导出 R 脚本 (Export/Download .R)”\*\*的 onClick 函数。在生成 Blob 对象并触发浏览器下载之前,将原有的代码字符串通过上述包装器函数处理一遍即可。这只需半小时即可实现。