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

@@ -192,6 +192,38 @@ function(req) {
message(glue::glue("[ExecuteCode] session={session_id}, code_length={nchar(code)}, timeout={timeout_sec}s"))
# ── AST 语法预检parse() 先于 eval(),快速捕获语法错误 ──
ast_check <- tryCatch({
parse(text = code)
NULL
}, error = function(e) {
e$message
})
if (!is.null(ast_check)) {
line_match <- regmatches(ast_check, regexpr("\\d+:\\d+", ast_check))
error_line <- if (length(line_match) > 0) as.integer(sub(":.*", "", line_match)) else NULL
code_lines <- strsplit(code, "\n")[[1]]
context_lines <- if (!is.null(error_line) && error_line > 0 && error_line <= length(code_lines)) {
start_l <- max(1, error_line - 2)
end_l <- min(length(code_lines), error_line + 2)
paste(sprintf("%3d| %s", start_l:end_l, code_lines[start_l:end_l]), collapse = "\n")
} else NULL
return(list(
status = "error",
error_code = "E_SYNTAX",
error_type = "syntax",
message = paste0("R 语法错误(代码无法解析): ", ast_check),
user_hint = "代码存在语法错误,请检查括号/引号是否匹配、运算符是否正确",
error_line = error_line,
error_context = context_lines,
console_output = list(),
duration_ms = 0
))
}
sandbox_env <- new.env(parent = globalenv())
if (!is.null(session_id) && nchar(session_id) > 0) {