({ analysis }: { analysis: Analysis })
| 151 | } |
| 152 | |
| 153 | function ToolStatsTable({ analysis }: { analysis: Analysis }) { |
| 154 | if (analysis.toolStats.length === 0) return null; |
| 155 | return ( |
| 156 | <section className="mt-6"> |
| 157 | <SectionTitle>tool usage · {analysis.toolStats.length} distinct</SectionTitle> |
| 158 | <div className="mt-2 overflow-x-auto border border-border bg-surface-0"> |
| 159 | <table className="w-full font-mono text-[11px]"> |
| 160 | <thead> |
| 161 | <tr className="border-b border-border text-fg-3"> |
| 162 | <Th align="left">tool</Th><Th>calls</Th><Th>errors</Th><Th>truncated</Th> |
| 163 | <Th>avg</Th><Th>max</Th><Th>output</Th> |
| 164 | </tr> |
| 165 | </thead> |
| 166 | <tbody> |
| 167 | {analysis.toolStats.map((t) => ( |
| 168 | <tr key={t.name} className="border-b border-border/50"> |
| 169 | <td className="px-2 py-1 text-fg-0">{t.name}</td> |
| 170 | <Td>{t.count}</Td> |
| 171 | <Td tone={t.errorCount > 0 ? 'var(--color-sev-error)' : undefined}>{t.errorCount}</Td> |
| 172 | <Td tone={t.truncatedCount > 0 ? 'var(--color-sev-warning)' : undefined}>{t.truncatedCount}</Td> |
| 173 | <Td>{formatDuration(t.avgMs)}</Td> |
| 174 | <Td>{formatDuration(t.maxMs)}</Td> |
| 175 | <Td>{formatBytes(t.totalOutputBytes)}</Td> |
| 176 | </tr> |
| 177 | ))} |
| 178 | </tbody> |
| 179 | </table> |
| 180 | </div> |
| 181 | </section> |
| 182 | ); |
| 183 | } |
| 184 | |
| 185 | function Th({ children, align = 'right' }: { children: import('react').ReactNode; align?: 'left' | 'right' }) { |
| 186 | return <th className={`px-2 py-1 font-normal ${align === 'left' ? 'text-left' : 'text-right tabular'}`}>{children}</th>; |
nothing calls this directly
no test coverage detected