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:
@@ -23,7 +23,7 @@ import type { WorkflowPlan } from '../types';
|
||||
// Types
|
||||
// ────────────────────────────────────────────
|
||||
|
||||
export type ChatIntentType = 'chat' | 'explore' | 'consult' | 'analyze' | 'discuss' | 'feedback';
|
||||
export type ChatIntentType = 'chat' | 'explore' | 'consult' | 'analyze' | 'discuss' | 'feedback' | 'system';
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string;
|
||||
@@ -33,6 +33,10 @@ export interface ChatMessage {
|
||||
intent?: ChatIntentType;
|
||||
status?: 'complete' | 'generating' | 'error';
|
||||
createdAt: string;
|
||||
/** Agent 执行 ID(用于在对话中渲染可点击的结果卡片) */
|
||||
executionId?: string;
|
||||
/** Agent 执行的查询摘要 */
|
||||
executionQuery?: string;
|
||||
}
|
||||
|
||||
export interface IntentMeta {
|
||||
@@ -134,20 +138,45 @@ export function useSSAChat(): UseSSAChatReturn {
|
||||
if (!resp.ok) return;
|
||||
|
||||
const data = await resp.json();
|
||||
const loaded: ChatMessage[] = [];
|
||||
|
||||
if (data.messages?.length > 0) {
|
||||
const loaded: ChatMessage[] = data.messages
|
||||
.filter((m: any) => m.status !== 'generating')
|
||||
.map((m: any) => ({
|
||||
id: m.id,
|
||||
role: m.role,
|
||||
content: m.content || '',
|
||||
thinking: m.thinkingContent,
|
||||
intent: m.intent,
|
||||
status: m.status || 'complete',
|
||||
createdAt: m.createdAt,
|
||||
}));
|
||||
setChatMessages(loaded);
|
||||
loaded.push(
|
||||
...data.messages
|
||||
.filter((m: any) => m.status !== 'generating')
|
||||
.map((m: any) => ({
|
||||
id: m.id,
|
||||
role: m.role as 'user' | 'assistant',
|
||||
content: m.content || '',
|
||||
thinking: m.thinkingContent,
|
||||
intent: m.intent,
|
||||
status: (m.status || 'complete') as 'complete' | 'generating' | 'error',
|
||||
createdAt: m.createdAt,
|
||||
executionId: m.executionId,
|
||||
executionQuery: m.executionQuery,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
// 从 store 中的 agentExecutionHistory 注入结果卡片
|
||||
const { agentExecutionHistory } = useSSAStore.getState();
|
||||
for (const exec of agentExecutionHistory) {
|
||||
if (exec.status === 'completed') {
|
||||
loaded.push({
|
||||
id: `exec-card-${exec.id}`,
|
||||
role: 'assistant',
|
||||
content: `✅ 分析完成:${exec.query}`,
|
||||
status: 'complete',
|
||||
intent: 'system',
|
||||
executionId: exec.id,
|
||||
executionQuery: exec.query,
|
||||
createdAt: exec.createdAt || new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
loaded.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
||||
setChatMessages(loaded);
|
||||
} catch (err) {
|
||||
console.warn('[useSSAChat] Failed to load history:', err);
|
||||
}
|
||||
@@ -329,13 +358,27 @@ export function useSSAChat(): UseSSAChatReturn {
|
||||
}
|
||||
|
||||
if (parsed.type === 'code_result') {
|
||||
const { updateAgentExecution } = useSSAStore.getState();
|
||||
const { updateAgentExecution, agentExecution: curExec } = useSSAStore.getState();
|
||||
updateAgentExecution({
|
||||
reportBlocks: parsed.reportBlocks,
|
||||
generatedCode: parsed.code || useSSAStore.getState().agentExecution?.generatedCode,
|
||||
generatedCode: parsed.code || curExec?.generatedCode,
|
||||
status: 'completed',
|
||||
durationMs: parsed.durationMs,
|
||||
});
|
||||
|
||||
// 在对话中插入可点击的结果卡片
|
||||
const execId = curExec?.id;
|
||||
const execQuery = curExec?.query || content;
|
||||
setChatMessages(prev => [...prev, {
|
||||
id: crypto.randomUUID(),
|
||||
role: 'assistant' as const,
|
||||
content: `✅ 分析完成:${execQuery}`,
|
||||
status: 'complete' as const,
|
||||
intent: 'system',
|
||||
executionId: execId,
|
||||
executionQuery: execQuery,
|
||||
createdAt: new Date().toISOString(),
|
||||
}]);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -448,7 +491,7 @@ export function useSSAChat(): UseSSAChatReturn {
|
||||
role: 'assistant' as const,
|
||||
content: auditContent,
|
||||
status: 'complete' as const,
|
||||
intent: 'system' as any,
|
||||
intent: 'system',
|
||||
createdAt: new Date().toISOString(),
|
||||
}]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user