| |
| |
| |
| |
| |
| export default function MessageItem({ message }) { |
| if (message.role === "user") { |
| return ( |
| <div className="message user-message"> |
| <div className="message-content">{message.content}</div> |
| </div> |
| ); |
| } |
|
|
| |
| return ( |
| <div className="message assistant-message"> |
| {message.steps.map((step, i) => ( |
| <StepBlock key={i} step={step} /> |
| ))} |
| {!message.done && message.steps.length === 0 && ( |
| <span className="placeholder">Agent is thinking…</span> |
| )} |
| </div> |
| ); |
| } |
|
|
| function StepBlock({ step }) { |
| switch (step.type) { |
| case "thinking": |
| return ( |
| <div className="step thinking-step"> |
| <div className="result-label">💭 Reasoning</div> |
| <pre>{step.content}</pre> |
| </div> |
| ); |
|
|
| case "code": |
| return ( |
| <div className="step code-step"> |
| <div className="code-header"> |
| <span className="code-lang">{step.lang}</span> |
| <button onClick={() => navigator.clipboard.writeText(step.content)}> |
| Copy |
| </button> |
| </div> |
| <pre className="code-block">{step.content}</pre> |
| </div> |
| ); |
|
|
| case "tool_use": |
| return ( |
| <div className="step tool-step"> |
| 🔧 <strong>{step.tool}</strong> |
| <span className="tool-detail">{step.content?.slice(0, 80)}…</span> |
| </div> |
| ); |
|
|
| case "observation": |
| return ( |
| <details className="step observation-step"> |
| <summary>📊 Observation</summary> |
| <pre>{step.content}</pre> |
| </details> |
| ); |
|
|
| case "result": |
| return ( |
| <div className="step result-step"> |
| <div className="result-label">✅ Result</div> |
| <div className="result-content">{step.content}</div> |
| </div> |
| ); |
|
|
| case "error": |
| return ( |
| <details className="step error-step" open> |
| <summary>❌ Error</summary> |
| <pre>{step.content}</pre> |
| </details> |
| ); |
|
|
| default: |
| return null; |
| } |
| } |
|
|