From 0bc0a13587c473eef59b5388f6b8bee8d864c048 Mon Sep 17 00:00:00 2001 From: catlog22 Date: Sat, 14 Feb 2026 23:30:19 +0800 Subject: [PATCH] feat: Add detailed discussion content rendering for multi-cli-plan - Add RoundDetailCard component to display synthesis details per round: - CLI execution status and duration - Solutions with feasibility, effort, risk, pros/cons - Convergence analysis with score and rationale - Cross-verification showing agreements and disagreements - Clarification questions - Update ExpandedMultiCliPanel discussion tab to use new component - Add i18n translations for new discussion content labels --- ccw/frontend/src/locales/en/lite-tasks.json | 18 +- ccw/frontend/src/locales/zh/lite-tasks.json | 18 +- ccw/frontend/src/pages/LiteTasksPage.tsx | 294 +++++++++++++++++++- 3 files changed, 326 insertions(+), 4 deletions(-) diff --git a/ccw/frontend/src/locales/en/lite-tasks.json b/ccw/frontend/src/locales/en/lite-tasks.json index be5b9de6..3f12fc12 100644 --- a/ccw/frontend/src/locales/en/lite-tasks.json +++ b/ccw/frontend/src/locales/en/lite-tasks.json @@ -20,7 +20,23 @@ "implementation": "Implementation", "feasibility": "Feasibility", "risk": "Risk", - "planSummary": "Plan Summary" + "planSummary": "Plan Summary", + "round": "Round", + "converged": "Converged", + "continuing": "Continuing", + "needsInput": "Needs Input", + "userFeedback": "User Feedback Incorporated", + "cliExecutions": "CLI Executions", + "solutions": "Solutions", + "feasible": "Feasible", + "pros": "Pros", + "cons": "Cons", + "convergence": "Convergence Analysis", + "crossVerification": "Cross Verification", + "agreements": "Agreements", + "disagreements": "Disagreements", + "resolution": "Resolution", + "clarificationQuestions": "Clarification Questions" }, "createdAt": "Created", "rounds": "rounds", diff --git a/ccw/frontend/src/locales/zh/lite-tasks.json b/ccw/frontend/src/locales/zh/lite-tasks.json index c7f637f6..cdab33cd 100644 --- a/ccw/frontend/src/locales/zh/lite-tasks.json +++ b/ccw/frontend/src/locales/zh/lite-tasks.json @@ -20,7 +20,23 @@ "implementation": "实现方式", "feasibility": "可行性", "risk": "风险", - "planSummary": "规划摘要" + "planSummary": "规划摘要", + "round": "轮", + "converged": "已收敛", + "continuing": "继续中", + "needsInput": "需要输入", + "userFeedback": "已纳入用户反馈", + "cliExecutions": "CLI 执行", + "solutions": "解决方案", + "feasible": "可行", + "pros": "优点", + "cons": "缺点", + "convergence": "收敛分析", + "crossVerification": "交叉验证", + "agreements": "共识", + "disagreements": "分歧", + "resolution": "解决方式", + "clarificationQuestions": "澄清问题" }, "createdAt": "创建时间", "rounds": "轮", diff --git a/ccw/frontend/src/pages/LiteTasksPage.tsx b/ccw/frontend/src/pages/LiteTasksPage.tsx index 5c45b914..24a0c666 100644 --- a/ccw/frontend/src/pages/LiteTasksPage.tsx +++ b/ccw/frontend/src/pages/LiteTasksPage.tsx @@ -38,9 +38,7 @@ import { Cpu, Timer, Sparkles, - Layers, CheckCheck, - ArrowRight, } from 'lucide-react'; import { useLiteTasks } from '@/hooks/useLiteTasks'; import { Button } from '@/components/ui/Button'; @@ -250,6 +248,298 @@ function ExpandedSessionPanel({ * ContextContent - Extracted to @/components/lite-tasks/LiteContextContent.tsx */ +/** + * RoundDetailCard - Display detailed information for a single discussion round + */ +function RoundDetailCard({ round, isLast }: { round: RoundSynthesis; isLast: boolean }) { + const { formatMessage } = useIntl(); + const [expanded, setExpanded] = React.useState(isLast); + + const solutions = round.solutions || []; + const convergence = round.convergence; + const crossVerification = round.cross_verification; + const clarificationQuestions = round.clarification_questions || []; + const cliExecutions = round.cli_executions || {}; + + // Format duration + const formatDuration = (ms: number) => { + if (ms < 1000) return `${ms}ms`; + return `${(ms / 1000).toFixed(1)}s`; + }; + + // Get convergence badge variant + const getConvergenceVariant = (recommendation?: string) => { + switch (recommendation) { + case 'converged': return 'success'; + case 'continue': return 'warning'; + case 'user_input_needed': return 'destructive'; + default: return 'secondary'; + } + }; + + return ( + + + {/* Round Header */} +
setExpanded(!expanded)} + > +
+
+ {round.round} +
+
+

+ {formatMessage({ id: 'liteTasks.multiCli.round' })} {round.round} + {convergence && ( + + {convergence.recommendation === 'converged' && } + {convergence.recommendation === 'converged' && formatMessage({ id: 'liteTasks.multiCli.converged' })} + {convergence.recommendation === 'continue' && formatMessage({ id: 'liteTasks.multiCli.continuing' })} + {convergence.recommendation === 'user_input_needed' && formatMessage({ id: 'liteTasks.multiCli.needsInput' })} + + )} +

+

+ {round.timestamp ? new Date(round.timestamp).toLocaleString() : ''} +

+
+
+
+ {/* CLI Status Summary */} +
+ {Object.entries(cliExecutions).map(([cli, exec]) => ( + + {cli} + + ))} +
+ {expanded ? ( + + ) : ( + + )} +
+
+ + {/* Expanded Content */} + {expanded && ( +
+ {/* User Feedback Incorporated */} + {round.user_feedback_incorporated && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.userFeedback' })} +
+

{round.user_feedback_incorporated}

+
+ )} + + {/* CLI Executions */} + {Object.keys(cliExecutions).length > 0 && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.cliExecutions' })} +
+
+ {Object.entries(cliExecutions).map(([cli, exec]) => ( +
+ {cli} +
+ {exec.model} + + + {formatDuration(exec.duration_ms)} + +
+
+ ))} +
+
+ )} + + {/* Solutions */} + {solutions.length > 0 && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.solutions' })} ({solutions.length}) +
+
+ {solutions.map((solution, idx) => ( +
+
+
{solution.name}
+
+ {solution.source_cli.map((cli) => ( + + {cli} + + ))} +
+
+

{solution.summary}

+
+ + {Math.round(solution.feasibility * 100)}% {formatMessage({ id: 'liteTasks.multiCli.feasible' })} + + {solution.effort} + + {solution.risk} {formatMessage({ id: 'liteTasks.multiCli.risk' })} + +
+ {/* Pros/Cons */} +
+ {solution.pros.length > 0 && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.pros' })} +
+
    + {solution.pros.slice(0, 3).map((pro, i) => ( +
  • • {pro}
  • + ))} +
+
+ )} + {solution.cons.length > 0 && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.cons' })} +
+
    + {solution.cons.slice(0, 3).map((con, i) => ( +
  • • {con}
  • + ))} +
+
+ )} +
+
+ ))} +
+
+ )} + + {/* Convergence Analysis */} + {convergence && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.convergence' })} +
+
+
+
+
= 0.9 ? 'bg-success' : + convergence.score >= 0.7 ? 'bg-warning' : 'bg-destructive' + }`} + style={{ width: `${convergence.score * 100}%` }} + /> +
+ {Math.round(convergence.score * 100)}% +
+

{convergence.rationale}

+
+
+ )} + + {/* Cross Verification */} + {crossVerification && (crossVerification.agreements.length > 0 || crossVerification.disagreements.length > 0) && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.crossVerification' })} +
+
+ {/* Agreements */} + {crossVerification.agreements.length > 0 && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.agreements' })} ({crossVerification.agreements.length}) +
+
    + {crossVerification.agreements.slice(0, 5).map((agreement, i) => ( +
  • + + {agreement} +
  • + ))} +
+
+ )} + {/* Disagreements */} + {crossVerification.disagreements.length > 0 && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.disagreements' })} ({crossVerification.disagreements.length}) +
+
+ {crossVerification.disagreements.map((disagreement, i) => ( +
+
{disagreement.topic}
+
+
+ gemini + {disagreement.gemini} +
+
+ codex + {disagreement.codex} +
+
+
+ ))} +
+
+ )} + {/* Resolution */} + {crossVerification.resolution && ( +
+ {formatMessage({ id: 'liteTasks.multiCli.resolution' })}: {crossVerification.resolution} +
+ )} +
+
+ )} + + {/* Clarification Questions */} + {clarificationQuestions.length > 0 && ( +
+
+ + {formatMessage({ id: 'liteTasks.multiCli.clarificationQuestions' })} ({clarificationQuestions.length}) +
+
    + {clarificationQuestions.map((question, i) => ( +
  • + + {question} +
  • + ))} +
+
+ )} +
+ )} + + + ); +} + type MultiCliExpandedTab = 'tasks' | 'discussion' | 'context'; /**