| 493 | |
| 494 | // 顶部条:file/ghost 节点 fetch 内容前先显示节点头部信息 |
| 495 | function FileNodeHeader({ node }: { node: FlowNodeData }) { |
| 496 | const t = useT(); |
| 497 | return ( |
| 498 | <section className="mb-3"> |
| 499 | {node.kind === "ghost" && ( |
| 500 | <div className="mb-2 rounded border border-amber-700 bg-amber-900/30 p-2 text-xs text-amber-200"> |
| 501 | {t("preview.ghost_body")} |
| 502 | </div> |
| 503 | )} |
| 504 | {node.kind === "file" && node.toolName && ( |
| 505 | <details className="mb-2"> |
| 506 | <summary className="cursor-pointer text-xs text-slate-500"> |
| 507 | {t("preview.tool_call_status", { toolName: node.toolName, status: node.status ?? "" })} |
| 508 | {node.durationMs !== undefined && ( |
| 509 | <span className="ml-2">{node.durationMs}ms</span> |
| 510 | )} |
| 511 | </summary> |
| 512 | {node.toolArgs && ( |
| 513 | <pre className="mt-1 overflow-auto whitespace-pre-wrap break-words rounded bg-slate-950/70 p-2 text-[10px] text-slate-300"> |
| 514 | {JSON.stringify(node.toolArgs, null, 2)} |
| 515 | </pre> |
| 516 | )} |
| 517 | </details> |
| 518 | )} |
| 519 | </section> |
| 520 | ); |
| 521 | } |
| 522 | |
| 523 | function kindLabel(n: FlowNodeData, t: TFn): string { |
| 524 | switch (n.kind) { |