compact long subagent durations

This commit is contained in:
kingwl
2026-08-03 13:23:40 +08:00
parent c183fae6f9
commit 255cd90c6e
12 files changed
+136 -31

No files matched your search

@@ -76,16 +76,54 @@ function activityDuration(
return timing.settledMs + Math.max(0, end - timing.active.since)
}
/** Format a non-negative duration to seconds without dropping larger units. */
function formatDuration(ms: number, t: TranslateNS<typeof NS>): string {
interface DurationParts {
seconds: number
minutes: number
hours: number
days: number
totalMinutes: number
totalHours: number
}
function splitDuration(ms: number): DurationParts {
const totalSeconds = Math.floor(Math.max(0, ms) / 1_000)
const seconds = totalSeconds % 60
const totalMinutes = Math.floor(totalSeconds / 60)
const minutes = totalMinutes % 60
const hours = Math.floor(totalMinutes / 60)
if (hours > 0) {
const totalHours = Math.floor(totalMinutes / 60)
return {
seconds: totalSeconds % 60,
minutes: totalMinutes % 60,
hours: totalHours % 24,
days: Math.floor(totalHours / 24),
totalMinutes,
totalHours,
}
}
/** Format a duration with decreasing visual precision at larger scales. */
function formatDuration(ms: number, t: TranslateNS<typeof NS>): string {
const { seconds, minutes, hours, days, totalMinutes, totalHours } = splitDuration(ms)
if (days >= 365) {
const years = Math.floor(days / 365)
const months = Math.floor((days % 365) / 30)
return months === 0
? t('duration.years', { years })
: t('duration.yearsMonths', { years, months })
}
if (days >= 30) {
const months = Math.floor(days / 30)
const remainingDays = days % 30
return remainingDays === 0
? t('duration.months', { months })
: t('duration.monthsDays', { months, days: remainingDays })
}
if (days > 0) {
return hours === 0
? t('duration.days', { days })
: t('duration.daysHours', { days, hours })
}
if (totalHours > 0) {
return t('duration.hours', {
hours,
hours: totalHours,
minutes: String(minutes).padStart(2, '0'),
seconds: String(seconds).padStart(2, '0'),
})
@@ -99,6 +137,19 @@ function formatDuration(ms: number, t: TranslateNS<typeof NS>): string {
return t('duration.seconds', { seconds })
}
/** Preserve exact whole seconds for hover and accessible naming. */
function formatExactDuration(ms: number, t: TranslateNS<typeof NS>): string {
const { seconds, minutes, hours, days } = splitDuration(ms)
return days === 0
? formatDuration(ms, t)
: t('duration.exactDays', {
days,
hours: String(hours).padStart(2, '0'),
minutes: String(minutes).padStart(2, '0'),
seconds: String(seconds).padStart(2, '0'),
})
}
/** Aggregate the complete subagent-only descendant subtree from flat summaries. */
function summarizeDescendants(
sessionId: SessionId,
@@ -231,7 +282,10 @@ function CatalogRows({
)
const duration = durationMs === undefined
? undefined
: formatDuration(durationMs, t)
: {
compact: formatDuration(durationMs, t),
exact: formatExactDuration(durationMs, t),
}
const open = (): void => {
openChild({ parentSessionId, childSessionId: entry.id, mode: entry.mode })
@@ -263,7 +317,7 @@ function CatalogRows({
role="treeitem"
tabIndex={0}
aria-level={level}
aria-label={[label, secondary, duration]
aria-label={[label, secondary, duration?.exact]
.filter(value => value !== undefined)
.join(' ')}
{...knownLeaf ? {} : { 'aria-expanded': isExpanded }}
@@ -290,7 +344,14 @@ function CatalogRows({
<span className={css.label}>{label}</span>
<span className={css.summary}>{secondary}</span>
</span>
{duration !== undefined && <span className={css.time}>{duration}</span>}
{duration !== undefined && (
<span
className={css.time}
title={t('duration.exactTitle', { duration: duration.exact })}
>
{duration.compact}
</span>
)}
</div>
</div>
{isExpanded && !knownLeaf && (
@@ -11,6 +11,14 @@ export const zh = {
'duration.seconds': '{seconds}秒',
'duration.minutes': '{minutes}分{seconds}秒',
'duration.hours': '{hours}小时{minutes}分{seconds}秒',
'duration.days': '{days}天',
'duration.daysHours': '{days}天{hours}小时',
'duration.months': '约{months}个月',
'duration.monthsDays': '约{months}个月{days}天',
'duration.years': '约{years}年',
'duration.yearsMonths': '约{years}年{months}个月',
'duration.exactDays': '{days}天{hours}小时{minutes}分{seconds}秒',
'duration.exactTitle': '总活跃耗时:{duration}',
'loading.label': '正在加载子代理…',
'loading.aria': '正在加载子代理',
'load.error': '无法加载子代理',
@@ -40,6 +48,14 @@ export const en: Record<SubagentKey, string> = {
'duration.seconds': '{seconds}s',
'duration.minutes': '{minutes}m {seconds}s',
'duration.hours': '{hours}h {minutes}m {seconds}s',
'duration.days': '{days}d',
'duration.daysHours': '{days}d {hours}h',
'duration.months': '~{months}mo',
'duration.monthsDays': '~{months}mo {days}d',
'duration.years': '~{years}y',
'duration.yearsMonths': '~{years}y {months}mo',
'duration.exactDays': '{days}d {hours}h {minutes}m {seconds}s',
'duration.exactTitle': 'Total active duration: {duration}',
'loading.label': 'Loading subagents…',
'loading.aria': 'Loading subagents',
'load.error': 'Unable to load subagents',